From 19c468c8b796d6c65dbbbdb8469f62d7af946342 Mon Sep 17 00:00:00 2001 From: Vaibhav Devmurari Date: Wed, 19 Feb 2025 12:35:39 +0000 Subject: (1/n) Remove usage of isKeyGestureSupported() from KeyGestureController isKeyGestureSupported is synchronous API that makes system server dependent on handler and can cause ANR if handlers misbehave. It was added as a stop gap for multi-key gestures that require some SysUI info like keyguard state, display state, etc, to decide if the key needs to be consumed or not at the start of the gesture. With this refactor: - Use Display state for Default display as a replacement for mDefaultDisplayPolicy.isAwake() which was added initially to ensure the shortcut chords are only trigerred if default display is on. In subsequent CLs: - WM policy added an API to check isKeyguardLocked() and we will use that for checking keyguard status - Move A11yShortcutController to KGC to circumvent the need of the isShortcutAvailable() API Test: atest KeyGestureControllerTests Bug: 358569822 Bug: 383602794 Flag: EXEMPT refactor Change-Id: I000c6a46ae0e17495db5fa5f0f039940549bc243 --- .../android/server/input/KeyGestureController.java | 38 +++++++++------------- .../server/policy/KeyCombinationManager.java | 8 ++--- .../android/server/policy/PhoneWindowManager.java | 17 ++++------ 3 files changed, 26 insertions(+), 37 deletions(-) diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java index fba0b0453bfb..ef5babf19d83 100644 --- a/services/core/java/com/android/server/input/KeyGestureController.java +++ b/services/core/java/com/android/server/input/KeyGestureController.java @@ -35,6 +35,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; +import android.hardware.display.DisplayManager; import android.hardware.input.AidlInputGestureData; import android.hardware.input.AidlKeyGestureEvent; import android.hardware.input.AppLaunchData; @@ -57,6 +58,7 @@ import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Slog; import android.util.SparseArray; +import android.view.Display; import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -127,6 +129,7 @@ final class KeyGestureController { private final SettingsObserver mSettingsObserver; private final AppLaunchShortcutManager mAppLaunchShortcutManager; private final InputGestureManager mInputGestureManager; + private final DisplayManager mDisplayManager; @GuardedBy("mInputDataStore") private final InputDataStore mInputDataStore; private static final Object mUserLock = new Object(); @@ -194,6 +197,7 @@ final class KeyGestureController { mSettingsObserver = new SettingsObserver(mHandler); mAppLaunchShortcutManager = new AppLaunchShortcutManager(mContext); mInputGestureManager = new InputGestureManager(mContext); + mDisplayManager = Objects.requireNonNull(mContext.getSystemService(DisplayManager.class)); mInputDataStore = inputDataStore; mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); initBehaviors(); @@ -245,12 +249,6 @@ final class KeyGestureController { mKeyCombinationManager.addRule( new KeyCombinationManager.TwoKeysCombinationRule(KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_POWER) { - @Override - public boolean preCondition() { - return isKeyGestureSupported( - KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); - } - @Override public void execute() { handleMultiKeyGesture( @@ -273,12 +271,6 @@ final class KeyGestureController { mKeyCombinationManager.addRule( new KeyCombinationManager.TwoKeysCombinationRule(KeyEvent.KEYCODE_POWER, KeyEvent.KEYCODE_STEM_PRIMARY) { - @Override - public boolean preCondition() { - return isKeyGestureSupported( - KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); - } - @Override public void execute() { handleMultiKeyGesture(new int[]{KeyEvent.KEYCODE_POWER, @@ -333,9 +325,6 @@ final class KeyGestureController { KeyEvent.KEYCODE_POWER) { @Override public boolean preCondition() { - if (!isKeyGestureSupported(getGestureType())) { - return false; - } switch (mPowerVolUpBehavior) { case POWER_VOLUME_UP_BEHAVIOR_MUTE: return mRingerToggleChord != Settings.Secure.VOLUME_HUSH_OFF; @@ -422,12 +411,6 @@ final class KeyGestureController { mKeyCombinationManager.addRule( new KeyCombinationManager.TwoKeysCombinationRule(KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_DPAD_CENTER) { - @Override - public boolean preCondition() { - return isKeyGestureSupported( - KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT); - } - @Override public void execute() { handleMultiKeyGesture( @@ -468,10 +451,11 @@ final class KeyGestureController { if (mVisibleBackgroundUsersEnabled && shouldIgnoreKeyEventForVisibleBackgroundUser(event)) { return false; } - final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; if (InputSettings.doesKeyGestureEventHandlerSupportMultiKeyGestures() && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { - return mKeyCombinationManager.interceptKey(event, interactive); + final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; + final boolean isDefaultDisplayOn = isDefaultDisplayOn(); + return mKeyCombinationManager.interceptKey(event, interactive && isDefaultDisplayOn); } return false; } @@ -1038,6 +1022,14 @@ final class KeyGestureController { mIoHandler.obtainMessage(MSG_LOAD_CUSTOM_GESTURES, userId).sendToTarget(); } + private boolean isDefaultDisplayOn() { + Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); + if (defaultDisplay == null) { + return false; + } + return Display.isOnState(defaultDisplay.getState()); + } + @MainThread private void notifyKeyGestureEvent(AidlKeyGestureEvent event) { InputDevice device = getInputDevice(event.deviceId); diff --git a/services/core/java/com/android/server/policy/KeyCombinationManager.java b/services/core/java/com/android/server/policy/KeyCombinationManager.java index 1592ef306cb3..1b98dd1e249c 100644 --- a/services/core/java/com/android/server/policy/KeyCombinationManager.java +++ b/services/core/java/com/android/server/policy/KeyCombinationManager.java @@ -148,19 +148,19 @@ public class KeyCombinationManager { * to a window. * Return true if any active rule could be triggered by the key event, otherwise false. */ - public boolean interceptKey(KeyEvent event, boolean interactive) { + public boolean interceptKey(KeyEvent event, boolean isDefaultDisplayInteractive) { synchronized (mLock) { - return interceptKeyLocked(event, interactive); + return interceptKeyLocked(event, isDefaultDisplayInteractive); } } - private boolean interceptKeyLocked(KeyEvent event, boolean interactive) { + private boolean interceptKeyLocked(KeyEvent event, boolean isDefaultDisplayInteractive) { final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final int keyCode = event.getKeyCode(); final int count = mActiveRules.size(); final long eventTime = event.getEventTime(); - if (interactive && down) { + if (isDefaultDisplayInteractive && down) { if (mDownTimes.size() > 0) { if (count > 0 && eventTime > mDownTimes.valueAt(0) + COMBINE_KEY_DELAY_MILLIS) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 980fb155999e..2f3111278a66 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -4300,22 +4300,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyGestureEvent.KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS: case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION: case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB: - return true; case KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD: case KeyGestureEvent.KEY_GESTURE_TYPE_RINGER_TOGGLE_CHORD: case KeyGestureEvent.KEY_GESTURE_TYPE_GLOBAL_ACTIONS: case KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT: - return mDefaultDisplayPolicy.isAwake(); - case KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT_CHORD: - return mDefaultDisplayPolicy.isAwake() && mAccessibilityShortcutController - .isAccessibilityShortcutAvailable(isKeyguardLocked()); - case KeyGestureEvent.KEY_GESTURE_TYPE_TV_ACCESSIBILITY_SHORTCUT_CHORD: - return mDefaultDisplayPolicy.isAwake() && mAccessibilityShortcutController - .isAccessibilityShortcutAvailable(false); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK: - return enableTalkbackAndMagnifierKeyGestures(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS: - return enableVoiceAccessKeyGestures(); + return true; + case KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT_CHORD: + return mAccessibilityShortcutController.isAccessibilityShortcutAvailable( + isKeyguardLocked()); + case KeyGestureEvent.KEY_GESTURE_TYPE_TV_ACCESSIBILITY_SHORTCUT_CHORD: + return mAccessibilityShortcutController.isAccessibilityShortcutAvailable( + false); default: return false; } -- cgit v1.2.3-59-g8ed1b