Keyboard shortcuts: dismiss when activities start via shortcut
* introduced a new intent DISMISS_KEYBOARD_SHORTCUTS and
and new public API in Activity (which sends a broadcast
to KeyboardShortcutsReceiver) which applications can
use to dismiss the keyboard shortcuts.
* plumbing and implementation for a new call to dismiss
keyboard shortcuts from PhoneWindowManager and used it:
** when starting activities invoked via Search+key
** when starting activities invoked via META
** when starting activities via application launch keys
* removed unused variable in
Activity#onProvideKeyboardShortcuts
Note that for apps started via touch (aka non-shortcut)
like tapping the Settings gear icon from the notification
bar the menu is not automatically dismissed.
Bug: 28012198
Change-Id: I83a8d4f342bb8a08115a648648834d0d2bac19fd
diff --git a/api/current.txt b/api/current.txt
index a04ecfb..30e88e5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3424,6 +3424,7 @@
method public void closeOptionsMenu();
method public android.app.PendingIntent createPendingResult(int, android.content.Intent, int);
method public final deprecated void dismissDialog(int);
+ method public final void dismissKeyboardShortcutsHelper();
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
method public boolean dispatchKeyEvent(android.view.KeyEvent);
method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
diff --git a/api/system-current.txt b/api/system-current.txt
index 013d8f1..6692aac 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3541,6 +3541,7 @@
method public boolean convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions);
method public android.app.PendingIntent createPendingResult(int, android.content.Intent, int);
method public final deprecated void dismissDialog(int);
+ method public final void dismissKeyboardShortcutsHelper();
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
method public boolean dispatchKeyEvent(android.view.KeyEvent);
method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
diff --git a/api/test-current.txt b/api/test-current.txt
index d056f7d..1e2d493 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3424,6 +3424,7 @@
method public void closeOptionsMenu();
method public android.app.PendingIntent createPendingResult(int, android.content.Intent, int);
method public final deprecated void dismissDialog(int);
+ method public final void dismissKeyboardShortcutsHelper();
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
method public boolean dispatchKeyEvent(android.view.KeyEvent);
method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index cc76854..1af9d0a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -721,6 +721,10 @@
private static final String REQUEST_PERMISSIONS_WHO_PREFIX = "@android:requestPermissions:";
+ private static final String KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME = "com.android.systemui";
+ private static final String KEYBOARD_SHORTCUTS_RECEIVER_CLASS_NAME =
+ "com.android.systemui.statusbar.KeyboardShortcutsReceiver";
+
private static class ManagedDialog {
Dialog mDialog;
Bundle mArgs;
@@ -1682,8 +1686,18 @@
*/
public final void requestKeyboardShortcutsHelper() {
Intent intent = new Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS);
- intent.setComponent(new ComponentName("com.android.systemui",
- "com.android.systemui.statusbar.KeyboardShortcutsReceiver"));
+ intent.setComponent(new ComponentName(KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME,
+ KEYBOARD_SHORTCUTS_RECEIVER_CLASS_NAME));
+ sendBroadcast(intent);
+ }
+
+ /**
+ * Dismiss the Keyboard Shortcuts screen.
+ */
+ public final void dismissKeyboardShortcutsHelper() {
+ Intent intent = new Intent(Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS);
+ intent.setComponent(new ComponentName(KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME,
+ KEYBOARD_SHORTCUTS_RECEIVER_CLASS_NAME));
sendBroadcast(intent);
}
@@ -1693,11 +1707,6 @@
if (menu == null) {
return;
}
- final InputDevice inputDevice = InputManager.getInstance().getInputDevice(deviceId);
- if (inputDevice == null) {
- return;
- }
- final KeyCharacterMap keyCharacterMap = inputDevice.getKeyCharacterMap();
KeyboardShortcutGroup group = null;
int menuSize = menu.size();
for (int i = 0; i < menuSize; ++i) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index fb4dd84..4243246 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1427,6 +1427,16 @@
"android.intent.action.SHOW_KEYBOARD_SHORTCUTS";
/**
+ * Activity Action: Dismiss the Keyboard Shortcuts Helper screen.
+ * <p>Input: Nothing.
+ * <p>Output: Nothing.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DISMISS_KEYBOARD_SHORTCUTS =
+ "android.intent.action.DISMISS_KEYBOARD_SHORTCUTS";
+
+ /**
* Activity Action: Show settings for managing network data usage of a
* specific application. Applications should define an activity that offers
* options to control data usage.
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index fcf65f2..5cbe1ce 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -65,6 +65,7 @@
void cancelPreloadRecentApps();
void showScreenPinningRequest(int taskId);
+ void dismissKeyboardShortcutsMenu();
void toggleKeyboardShortcutsMenu(int deviceId);
/**
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index c248adf..70c8957 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -508,6 +508,7 @@
<receiver
android:name=".statusbar.KeyboardShortcutsReceiver">
<intent-filter>
+ <action android:name="android.intent.action.DISMISS_KEYBOARD_SHORTCUTS" />
<action android:name="android.intent.action.SHOW_KEYBOARD_SHORTCUTS" />
</intent-filter>
</receiver>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2d5b6d4..f2c5820 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -143,6 +143,7 @@
protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
+ protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
protected static final boolean ENABLE_HEADS_UP = true;
protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
@@ -1248,6 +1249,13 @@
}
@Override
+ public void dismissKeyboardShortcutsMenu() {
+ int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+
+ @Override
public void toggleKeyboardShortcutsMenu(int deviceId) {
int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
mHandler.removeMessages(msg);
@@ -1344,6 +1352,10 @@
KeyboardShortcuts.toggle(mContext, deviceId);
}
+ protected void dismissKeyboardShortcuts() {
+ KeyboardShortcuts.dismiss();
+ }
+
protected void cancelPreloadingRecents() {
if (mRecents != null) {
mRecents.cancelPreloadingRecents();
@@ -1518,6 +1530,9 @@
case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
toggleKeyboardShortcuts(m.arg1);
break;
+ case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU:
+ dismissKeyboardShortcuts();
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f7d13ee..1bc2ebc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -74,6 +74,7 @@
private static final int MSG_CLICK_QS_TILE = 29 << MSG_SHIFT;
private static final int MSG_TOGGLE_APP_SPLIT_SCREEN = 30 << MSG_SHIFT;
private static final int MSG_APP_TRANSITION_FINISHED = 31 << MSG_SHIFT;
+ private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS = 32 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -108,6 +109,7 @@
void toggleRecentApps();
void toggleSplitScreen();
void preloadRecentApps();
+ void dismissKeyboardShortcutsMenu();
void toggleKeyboardShortcutsMenu(int deviceId);
void cancelPreloadRecentApps();
void setWindowState(int window, int state);
@@ -256,6 +258,14 @@
}
@Override
+ public void dismissKeyboardShortcutsMenu() {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_DISMISS_KEYBOARD_SHORTCUTS);
+ mHandler.obtainMessage(MSG_DISMISS_KEYBOARD_SHORTCUTS).sendToTarget();
+ }
+ }
+
+ @Override
public void toggleKeyboardShortcutsMenu(int deviceId) {
synchronized (mLock) {
mHandler.removeMessages(MSG_TOGGLE_KEYBOARD_SHORTCUTS);
@@ -435,6 +445,9 @@
case MSG_CANCEL_PRELOAD_RECENT_APPS:
mCallbacks.cancelPreloadRecentApps();
break;
+ case MSG_DISMISS_KEYBOARD_SHORTCUTS:
+ mCallbacks.dismissKeyboardShortcutsMenu();
+ break;
case MSG_TOGGLE_KEYBOARD_SHORTCUTS:
mCallbacks.toggleKeyboardShortcutsMenu(msg.arg1);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
index 5f4ebd8..8a5bece 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
@@ -27,6 +27,8 @@
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
KeyboardShortcuts.show(context, -1 /* deviceId unknown */);
+ } else if (Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
+ KeyboardShortcuts.dismiss();
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d7afc13..b028c9d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17156,6 +17156,7 @@
if (isCallerSystem) {
if (isProtectedBroadcast
|| Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
+ || Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(action)
|| Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)
|| Intent.ACTION_GET_PERMISSIONS_COUNT.equals(action)
|| Intent.ACTION_GET_PERMISSIONS_PACKAGES.equals(action)
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 007190d..9f31f4f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3301,6 +3301,7 @@
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
+ dismissKeyboardShortcutsMenu();
} catch (ActivityNotFoundException ex) {
Slog.w(TAG, "Dropping shortcut key combination because "
+ "the activity to which it is registered was not found: "
@@ -3327,6 +3328,7 @@
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
+ dismissKeyboardShortcutsMenu();
} catch (ActivityNotFoundException ex) {
Slog.w(TAG, "Dropping shortcut key combination because "
+ "the activity to which it is registered was not found: "
@@ -3345,6 +3347,7 @@
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivityAsUser(intent, UserHandle.CURRENT);
+ dismissKeyboardShortcutsMenu();
} catch (ActivityNotFoundException ex) {
Slog.w(TAG, "Dropping application launch key because "
+ "the activity to which it is registered was not found: "
@@ -3635,6 +3638,13 @@
}
}
+ private void dismissKeyboardShortcutsMenu() {
+ StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+ if (statusbar != null) {
+ statusbar.dismissKeyboardShortcutsMenu();
+ }
+ }
+
private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
mPreloadedRecentApps = false; // preloading no longer needs to be canceled
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 38a3d01..52b2439 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -37,6 +37,7 @@
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
+ void dismissKeyboardShortcutsMenu();
void toggleKeyboardShortcutsMenu(int deviceId);
/**
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 9020677..c630d4a 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -277,6 +277,15 @@
}
@Override
+ public void dismissKeyboardShortcutsMenu() {
+ if (mBar != null) {
+ try {
+ mBar.dismissKeyboardShortcutsMenu();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
public void toggleKeyboardShortcutsMenu(int deviceId) {
if (mBar != null) {
try {