Loading core/java/android/hardware/input/KeyGestureEvent.java +4 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ public final class KeyGestureEvent { public static final int KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK = 77; public static final int KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK = 78; public static final int KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL = 79; public static final int KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK = 80; public static final int FLAG_CANCELLED = 1 << 0; public static final int FLAG_LONG_PRESS = 1 << 1; Loading Loading @@ -226,6 +227,7 @@ public final class KeyGestureEvent { KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK, KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK, KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL, KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK, }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -824,6 +826,8 @@ public final class KeyGestureEvent { return "KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK"; case KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL: return "KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL"; case KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK: return "KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK"; default: return Integer.toHexString(value); } Loading core/res/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2507,6 +2507,9 @@ <!-- Description of policy access to disable keyguard features. [CHAR LIMIT=110]--> <string name="policydesc_disableKeyguardFeatures">Prevent use of some screen lock features.</string> <!-- Text for toast instructing user to long press escape to exit the current application. [CHAR LIMIT=TOAST]--> <string name="exit_toast_on_long_press_escape">Long press escape key to quit the application.</string> <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip /> <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. --> <string-array name="phoneTypes"> Loading core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -6289,6 +6289,8 @@ <java-symbol type="string" name="proximity_provider_service_package_name" /> <java-symbol type="string" name="proximity_provider_service_class_name" /> <java-symbol type="string" name="exit_toast_on_long_press_escape" /> <!-- For App Functions --> <java-symbol type="array" name="config_appFunctionDeviceSettingsPackages" /> </resources> services/core/java/com/android/server/input/KeyGestureController.java +31 −1 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.ViewConfiguration; import android.view.WindowManager; import android.widget.Toast; import com.android.internal.R; import com.android.internal.accessibility.AccessibilityShortcutController; Loading @@ -86,6 +87,7 @@ import com.android.internal.policy.KeyInterceptionInfo; import com.android.internal.util.ScreenshotHelper; import com.android.internal.util.ScreenshotRequest; import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.pm.UserManagerInternal; import com.android.server.wm.WindowManagerInternal; Loading Loading @@ -127,6 +129,7 @@ final class KeyGestureController { private static final int MSG_LOAD_CUSTOM_GESTURES = 3; private static final int MSG_ACCESSIBILITY_SHORTCUT = 4; private static final int MSG_SCREENSHOT_SHORTCUT = 5; private static final int MSG_EXIT_FOCUSED_APP = 6; // must match: config_settingsKeyBehavior in config.xml private static final int SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY = 0; Loading @@ -148,6 +151,9 @@ final class KeyGestureController { // Increase the chord delay when taking a screenshot from the keyguard private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; // Duration to long press escape to exit application when app is capturing keyboard keys private static final long LONG_PRESS_DURATION_FOR_EXIT_APP_MS = 1000; @LongDef(prefix = {"KEY_INTERCEPT_RESULT_"}, value = { KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK, KEY_INTERCEPT_RESULT_CONSUMED, Loading Loading @@ -804,6 +810,28 @@ final class KeyGestureController { } } return true; case KeyEvent.KEYCODE_ESCAPE: // TODO(b/358569822): Currently implemented long press using handler and delayed // message here, instead of using SingleKeyGestureDetector because that detection // logic doesn't have access to focused token. Refactor this so that we don't // have this custom logic to detect long press. if (firstDown && canFocusedWindowCaptureKeys(focusedToken)) { // Toast to quit application is shown on key down for ESCAPE key, when the // focused window is capturing keys. Toast.makeText(mContext, UiThread.get().getLooper(), mContext.getString(R.string.exit_toast_on_long_press_escape), Toast.LENGTH_SHORT).show(); AidlKeyGestureEvent eventToSend = createKeyGestureEvent(event.getDeviceId(), new int[]{KeyEvent.KEYCODE_ESCAPE}, metaState, KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, /* flags= */0, /* appLaunchData= */ null); Message msg = Message.obtain(mHandler, MSG_EXIT_FOCUSED_APP, eventToSend); mHandler.sendMessageDelayed(msg, LONG_PRESS_DURATION_FOR_EXIT_APP_MS); } else if (!down) { mHandler.removeMessages(MSG_EXIT_FOCUSED_APP); } break; case KeyEvent.KEYCODE_ASSIST: Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing"); return true; Loading Loading @@ -1272,7 +1300,9 @@ final class KeyGestureController { case MSG_SCREENSHOT_SHORTCUT: takeScreenshot(msg.arg1, msg.arg2); break; case MSG_EXIT_FOCUSED_APP: handleKeyGesture((AidlKeyGestureEvent) msg.obj, /* focusedToken= */null); break; } return true; } Loading services/core/java/com/android/server/policy/PhoneWindowManager.java +21 −1 Original line number Diff line number Diff line Loading @@ -3467,7 +3467,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB, KeyGestureEvent.KEY_GESTURE_TYPE_RINGER_TOGGLE_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_GLOBAL_ACTIONS, KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT, KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK )); if (!com.android.window.flags.Flags.grantManageKeyGesturesToRecents()) { // When grantManageKeyGesturesToRecents is enabled, the event is handled in the Loading Loading @@ -3671,6 +3672,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { "Key gesture DND", true); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK: if (complete) { try { RootTaskInfo currentRootTask = mActivityManagerService.getFocusedRootTaskInfo(); if (currentRootTask == null) { Slog.e(TAG, "onKeyGesture: KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK the current" + " root task is null" ); return; } mActivityManagerService.removeTask(currentRootTask.taskId); } catch (RemoteException e) { Slog.e(TAG, "onKeyGesture: KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK failed to close" + " the current root task", e); } } default: Log.w(TAG, "Received a key gesture " + event + " that was not registered by this handler"); Loading Loading
core/java/android/hardware/input/KeyGestureEvent.java +4 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ public final class KeyGestureEvent { public static final int KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK = 77; public static final int KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK = 78; public static final int KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL = 79; public static final int KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK = 80; public static final int FLAG_CANCELLED = 1 << 0; public static final int FLAG_LONG_PRESS = 1 << 1; Loading Loading @@ -226,6 +227,7 @@ public final class KeyGestureEvent { KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK, KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK, KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL, KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK, }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -824,6 +826,8 @@ public final class KeyGestureEvent { return "KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK"; case KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL: return "KEY_GESTURE_TYPE_TOGGLE_QUICK_SETTINGS_PANEL"; case KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK: return "KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK"; default: return Integer.toHexString(value); } Loading
core/res/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2507,6 +2507,9 @@ <!-- Description of policy access to disable keyguard features. [CHAR LIMIT=110]--> <string name="policydesc_disableKeyguardFeatures">Prevent use of some screen lock features.</string> <!-- Text for toast instructing user to long press escape to exit the current application. [CHAR LIMIT=TOAST]--> <string name="exit_toast_on_long_press_escape">Long press escape key to quit the application.</string> <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip /> <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. --> <string-array name="phoneTypes"> Loading
core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -6289,6 +6289,8 @@ <java-symbol type="string" name="proximity_provider_service_package_name" /> <java-symbol type="string" name="proximity_provider_service_class_name" /> <java-symbol type="string" name="exit_toast_on_long_press_escape" /> <!-- For App Functions --> <java-symbol type="array" name="config_appFunctionDeviceSettingsPackages" /> </resources>
services/core/java/com/android/server/input/KeyGestureController.java +31 −1 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.ViewConfiguration; import android.view.WindowManager; import android.widget.Toast; import com.android.internal.R; import com.android.internal.accessibility.AccessibilityShortcutController; Loading @@ -86,6 +87,7 @@ import com.android.internal.policy.KeyInterceptionInfo; import com.android.internal.util.ScreenshotHelper; import com.android.internal.util.ScreenshotRequest; import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.pm.UserManagerInternal; import com.android.server.wm.WindowManagerInternal; Loading Loading @@ -127,6 +129,7 @@ final class KeyGestureController { private static final int MSG_LOAD_CUSTOM_GESTURES = 3; private static final int MSG_ACCESSIBILITY_SHORTCUT = 4; private static final int MSG_SCREENSHOT_SHORTCUT = 5; private static final int MSG_EXIT_FOCUSED_APP = 6; // must match: config_settingsKeyBehavior in config.xml private static final int SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY = 0; Loading @@ -148,6 +151,9 @@ final class KeyGestureController { // Increase the chord delay when taking a screenshot from the keyguard private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; // Duration to long press escape to exit application when app is capturing keyboard keys private static final long LONG_PRESS_DURATION_FOR_EXIT_APP_MS = 1000; @LongDef(prefix = {"KEY_INTERCEPT_RESULT_"}, value = { KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK, KEY_INTERCEPT_RESULT_CONSUMED, Loading Loading @@ -804,6 +810,28 @@ final class KeyGestureController { } } return true; case KeyEvent.KEYCODE_ESCAPE: // TODO(b/358569822): Currently implemented long press using handler and delayed // message here, instead of using SingleKeyGestureDetector because that detection // logic doesn't have access to focused token. Refactor this so that we don't // have this custom logic to detect long press. if (firstDown && canFocusedWindowCaptureKeys(focusedToken)) { // Toast to quit application is shown on key down for ESCAPE key, when the // focused window is capturing keys. Toast.makeText(mContext, UiThread.get().getLooper(), mContext.getString(R.string.exit_toast_on_long_press_escape), Toast.LENGTH_SHORT).show(); AidlKeyGestureEvent eventToSend = createKeyGestureEvent(event.getDeviceId(), new int[]{KeyEvent.KEYCODE_ESCAPE}, metaState, KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, /* flags= */0, /* appLaunchData= */ null); Message msg = Message.obtain(mHandler, MSG_EXIT_FOCUSED_APP, eventToSend); mHandler.sendMessageDelayed(msg, LONG_PRESS_DURATION_FOR_EXIT_APP_MS); } else if (!down) { mHandler.removeMessages(MSG_EXIT_FOCUSED_APP); } break; case KeyEvent.KEYCODE_ASSIST: Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing"); return true; Loading Loading @@ -1272,7 +1300,9 @@ final class KeyGestureController { case MSG_SCREENSHOT_SHORTCUT: takeScreenshot(msg.arg1, msg.arg2); break; case MSG_EXIT_FOCUSED_APP: handleKeyGesture((AidlKeyGestureEvent) msg.obj, /* focusedToken= */null); break; } return true; } Loading
services/core/java/com/android/server/policy/PhoneWindowManager.java +21 −1 Original line number Diff line number Diff line Loading @@ -3467,7 +3467,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB, KeyGestureEvent.KEY_GESTURE_TYPE_RINGER_TOGGLE_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_GLOBAL_ACTIONS, KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT, KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK )); if (!com.android.window.flags.Flags.grantManageKeyGesturesToRecents()) { // When grantManageKeyGesturesToRecents is enabled, the event is handled in the Loading Loading @@ -3671,6 +3672,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { "Key gesture DND", true); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK: if (complete) { try { RootTaskInfo currentRootTask = mActivityManagerService.getFocusedRootTaskInfo(); if (currentRootTask == null) { Slog.e(TAG, "onKeyGesture: KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK the current" + " root task is null" ); return; } mActivityManagerService.removeTask(currentRootTask.taskId); } catch (RemoteException e) { Slog.e(TAG, "onKeyGesture: KEY_GESTURE_TYPE_QUIT_FOCUSED_TASK failed to close" + " the current root task", e); } } default: Log.w(TAG, "Received a key gesture " + event + " that was not registered by this handler"); Loading