Loading services/core/java/com/android/server/input/InputManagerService.java +7 −57 Original line number Diff line number Diff line Loading @@ -16,9 +16,6 @@ package com.android.server.input; import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW; import static android.content.PermissionChecker.PERMISSION_GRANTED; import static android.content.PermissionChecker.PID_UNKNOWN; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.provider.DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT; import static android.view.KeyEvent.KEYCODE_UNKNOWN; Loading @@ -26,13 +23,13 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M import static com.android.hardware.input.Flags.enableCustomizableInputGestures; import static com.android.hardware.input.Flags.fixKeyboardInterceptorPolicyCall; import static com.android.hardware.input.Flags.fixSearchModifierFallbacks; import static com.android.hardware.input.Flags.keyEventActivityDetection; import static com.android.hardware.input.Flags.touchpadVisualizer; import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER; import android.Manifest; import android.annotation.EnforcePermission; import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; Loading @@ -44,7 +41,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.PermissionChecker; import android.content.pm.PackageManager; import android.graphics.PixelFormat; import android.graphics.PointF; Loading @@ -55,7 +51,6 @@ import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayTopologyGraph; import android.hardware.display.DisplayViewport; import android.hardware.input.AidlInputGestureData; import android.hardware.input.AppLaunchData; import android.hardware.input.HostUsiVersion; import android.hardware.input.IInputDeviceBatteryListener; import android.hardware.input.IInputDeviceBatteryState; Loading Loading @@ -138,7 +133,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.os.SomeArgs; import com.android.internal.policy.IShortcutService; import com.android.internal.policy.KeyInterceptionInfo; import com.android.internal.protolog.ProtoLog; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.IProtoLogGroup; Loading @@ -153,7 +147,6 @@ import com.android.server.input.InputManagerInternal.LidSwitchCallback; import com.android.server.input.debug.FocusEventDebugView; import com.android.server.input.debug.TouchpadDebugViewController; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.WindowManagerInternal; import libcore.io.IoUtils; Loading Loading @@ -206,8 +199,6 @@ public class InputManagerService extends IInputManager.Stub private final InputManagerHandler mHandler; private DisplayManagerInternal mDisplayManagerInternal; private WindowManagerInternal mWindowManagerInternal; private final File mDoubleTouchGestureEnableFile; private WindowManagerCallbacks mWindowManagerCallbacks; Loading Loading @@ -628,7 +619,6 @@ public class InputManagerService extends IInputManager.Stub } mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mSettingsObserver.registerAndUpdate(); Loading Loading @@ -2674,46 +2664,8 @@ public class InputManagerService extends IInputManager.Stub // Native callback. @SuppressWarnings("unused") @VisibleForTesting long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { final long keyNotConsumedGoFallback = -2; final long keyConsumed = -1; final long keyNotConsumed = 0; long value = keyNotConsumed; // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts if ((event.isMetaPressed() || KeyEvent.isMetaKey(event.getKeyCode())) && shouldInterceptShortcuts(focus)) { return keyNotConsumed; } value = mKeyGestureController.interceptKeyBeforeDispatching(focus, event, policyFlags); if (value == keyNotConsumed) { value = mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags); } if (value == keyNotConsumed && event.isMetaPressed()) { if (fixSearchModifierFallbacks() ) { // If the key has not been consumed and includes the meta key, do not send the event // to the app and attempt to generate a fallback. final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap.FallbackAction fallbackAction = kcm.getFallbackAction(event.getKeyCode(), event.getMetaState()); if (fallbackAction != null) { return keyNotConsumedGoFallback; } } return keyConsumed; } return value; } private boolean shouldInterceptShortcuts(IBinder focusedToken) { KeyInterceptionInfo info = mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken); boolean hasInterceptWindowFlag = info != null && (info.layoutParamsPrivateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0; return hasInterceptWindowFlag && PermissionChecker.checkPermissionForDataDelivery(mContext, OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW, PID_UNKNOWN, info.windowOwnerUid, null, null, null) == PERMISSION_GRANTED; return mKeyGestureController.interceptKeyBeforeDispatching(focus, event, policyFlags); } // Native callback. Loading Loading @@ -3347,13 +3299,9 @@ public class InputManagerService extends IInputManager.Stub * key. * @param token the window token that's about to receive this event * @param event the key event that's being dispatched * @param policyFlags the policy flags * @return -1 if the key should be skipped (not sent to the app). -2 if the key should not * be sent to the app, but it should still generate a fallback. * 0 if the key should proceed getting dispatched to the app. positive value to indicate the * additional time delay, in nanoseconds, to wait before sending this key to the app. * @return {@code true} if consumed, and {@code false} otherwise. */ long interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags); boolean interceptKeyBeforeDispatching(IBinder token, KeyEvent event); /** * Intercept unhandled key Loading Loading @@ -3879,7 +3827,9 @@ public class InputManagerService extends IInputManager.Stub event, /* policyFlags= */0); } else { return mWindowManagerCallbacks.interceptKeyBeforeDispatching( /* focusedToken= */null, event, /* policyFlags= */0); /* focusedToken= */null, event) ? KeyGestureController.KEY_INTERCEPT_RESULT_CONSUMED : KeyGestureController.KEY_INTERCEPT_RESULT_NOT_CONSUMED; } } } Loading services/core/java/com/android/server/input/KeyGestureController.java +66 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.server.input; import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW; import static android.content.PermissionChecker.PERMISSION_GRANTED; import static android.content.PermissionChecker.PID_UNKNOWN; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.os.UserManager.isVisibleBackgroundUsersEnabled; Loading @@ -25,9 +28,11 @@ import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER; import static android.view.WindowManagerPolicyConstants.FLAG_INTERACTIVE; import static com.android.hardware.input.Flags.enableNew25q2Keycodes; import static com.android.hardware.input.Flags.fixSearchModifierFallbacks; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import android.annotation.BinderThread; import android.annotation.LongDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -35,6 +40,7 @@ import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.content.ContentResolver; import android.content.Context; import android.content.PermissionChecker; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; Loading Loading @@ -74,16 +80,20 @@ import com.android.internal.accessibility.AccessibilityShortcutController; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.IShortcutService; 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.pm.UserManagerInternal; import com.android.server.wm.WindowManagerInternal; import org.xmlpull.v1.XmlPullParserException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; import java.util.Arrays; import java.util.HashSet; Loading Loading @@ -135,6 +145,19 @@ 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; @LongDef(prefix = {"KEY_INTERCEPT_RESULT_"}, value = { KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK, KEY_INTERCEPT_RESULT_CONSUMED, KEY_INTERCEPT_RESULT_NOT_CONSUMED }) @Retention(RetentionPolicy.SOURCE) private @interface KeyInterceptResult { } private static final long KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK = -2; static final long KEY_INTERCEPT_RESULT_CONSUMED = -1; static final long KEY_INTERCEPT_RESULT_NOT_CONSUMED = 0; private final Context mContext; private InputManagerService.WindowManagerCallbacks mWindowManagerCallbacks; private final Handler mHandler; Loading Loading @@ -193,6 +216,7 @@ final class KeyGestureController { private final SparseArray<Set<Integer>> mConsumedKeysForDevice = new SparseArray<>(); private final UserManagerInternal mUserManagerInternal; private WindowManagerInternal mWindowManagerInternal; private final boolean mVisibleBackgroundUsersEnabled = isVisibleBackgroundUsersEnabled(); Loading Loading @@ -450,6 +474,7 @@ final class KeyGestureController { } public void systemRunning() { mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mSettingsObserver.observe(); mAppLaunchShortcutManager.init(); mInputGestureManager.init(mAppLaunchShortcutManager.getBookmarks()); Loading Loading @@ -504,8 +529,47 @@ final class KeyGestureController { return false; } public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, int policyFlags) { public long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts if ((event.isMetaPressed() || KeyEvent.isMetaKey(event.getKeyCode())) && shouldInterceptShortcuts(focus)) { return KEY_INTERCEPT_RESULT_NOT_CONSUMED; } final long interceptResult = interceptKeyBeforeDispatchingInternal(focus, event); if (interceptResult != KEY_INTERCEPT_RESULT_NOT_CONSUMED) { // Result is either delay or consumed return interceptResult; } if (mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event)) { return KEY_INTERCEPT_RESULT_CONSUMED; } if (event.isMetaPressed()) { if (fixSearchModifierFallbacks() ) { // If the key has not been consumed and includes the meta key, do not send the event // to the app and attempt to generate a fallback. final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap.FallbackAction fallbackAction = kcm.getFallbackAction(event.getKeyCode(), event.getMetaState()); if (fallbackAction != null) { return KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK; } } return KEY_INTERCEPT_RESULT_CONSUMED; } return KEY_INTERCEPT_RESULT_NOT_CONSUMED; } private boolean shouldInterceptShortcuts(IBinder focusedToken) { KeyInterceptionInfo info = mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken); boolean hasInterceptWindowFlag = info != null && (info.layoutParamsPrivateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0; return hasInterceptWindowFlag && PermissionChecker.checkPermissionForDataDelivery(mContext, OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW, PID_UNKNOWN, info.windowOwnerUid, null, null, null) == PERMISSION_GRANTED; } private long interceptKeyBeforeDispatchingInternal(IBinder focusedToken, KeyEvent event) { // TODO(b/358569822): Handle shortcuts trigger logic here and pass it to appropriate // KeyGestureHandler (PWM is one of the handlers) final int keyCode = event.getKeyCode(); Loading services/core/java/com/android/server/policy/PhoneWindowManager.java +3 −7 Original line number Diff line number Diff line Loading @@ -3334,12 +3334,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // TODO (b/283241997): Add the remaining keyboard shortcut logging after refactoring /** {@inheritDoc} */ @Override public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, int policyFlags) { public boolean interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event) { final int keyCode = event.getKeyCode(); final int flags = event.getFlags(); final long keyConsumed = -1; final long keyNotConsumed = 0; final int deviceId = event.getDeviceId(); if (DEBUG_INPUT) { Loading @@ -3358,7 +3354,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (interceptSystemKeysAndShortcuts(focusedToken, event) && event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { consumedKeys.add(keyCode); return keyConsumed; return true; } boolean needToConsumeKey = consumedKeys.contains(keyCode); Loading @@ -3369,7 +3365,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } return needToConsumeKey ? keyConsumed : keyNotConsumed; return needToConsumeKey; } // You can only start consuming the key gesture if ACTION_DOWN and repeat count Loading services/core/java/com/android/server/policy/WindowManagerPolicy.java +2 −6 Original line number Diff line number Diff line Loading @@ -735,13 +735,9 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * @param focusedToken Client window token that currently has focus. This is where the key * event will normally go. * @param event The key event. * @param policyFlags The policy flags associated with the key. * @return 0 if the key should be dispatched immediately, -1 if the key should * not be dispatched ever, or a positive value indicating the number of * milliseconds by which the key dispatch should be delayed before trying * again. * @return {@code true} if consumed, and {@code false} otherwise. */ long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, int policyFlags); boolean interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event); /** * Called from the input dispatcher thread when an application did not handle Loading services/core/java/com/android/server/wm/InputManagerCallback.java +2 −3 Original line number Diff line number Diff line Loading @@ -234,9 +234,8 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal * ordinary dispatch. */ @Override public long interceptKeyBeforeDispatching( IBinder focusedToken, KeyEvent event, int policyFlags) { return mService.mPolicy.interceptKeyBeforeDispatching(focusedToken, event, policyFlags); public boolean interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event) { return mService.mPolicy.interceptKeyBeforeDispatching(focusedToken, event); } /** Loading Loading
services/core/java/com/android/server/input/InputManagerService.java +7 −57 Original line number Diff line number Diff line Loading @@ -16,9 +16,6 @@ package com.android.server.input; import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW; import static android.content.PermissionChecker.PERMISSION_GRANTED; import static android.content.PermissionChecker.PID_UNKNOWN; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.provider.DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT; import static android.view.KeyEvent.KEYCODE_UNKNOWN; Loading @@ -26,13 +23,13 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M import static com.android.hardware.input.Flags.enableCustomizableInputGestures; import static com.android.hardware.input.Flags.fixKeyboardInterceptorPolicyCall; import static com.android.hardware.input.Flags.fixSearchModifierFallbacks; import static com.android.hardware.input.Flags.keyEventActivityDetection; import static com.android.hardware.input.Flags.touchpadVisualizer; import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER; import android.Manifest; import android.annotation.EnforcePermission; import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; Loading @@ -44,7 +41,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.PermissionChecker; import android.content.pm.PackageManager; import android.graphics.PixelFormat; import android.graphics.PointF; Loading @@ -55,7 +51,6 @@ import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayTopologyGraph; import android.hardware.display.DisplayViewport; import android.hardware.input.AidlInputGestureData; import android.hardware.input.AppLaunchData; import android.hardware.input.HostUsiVersion; import android.hardware.input.IInputDeviceBatteryListener; import android.hardware.input.IInputDeviceBatteryState; Loading Loading @@ -138,7 +133,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.os.SomeArgs; import com.android.internal.policy.IShortcutService; import com.android.internal.policy.KeyInterceptionInfo; import com.android.internal.protolog.ProtoLog; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.IProtoLogGroup; Loading @@ -153,7 +147,6 @@ import com.android.server.input.InputManagerInternal.LidSwitchCallback; import com.android.server.input.debug.FocusEventDebugView; import com.android.server.input.debug.TouchpadDebugViewController; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.WindowManagerInternal; import libcore.io.IoUtils; Loading Loading @@ -206,8 +199,6 @@ public class InputManagerService extends IInputManager.Stub private final InputManagerHandler mHandler; private DisplayManagerInternal mDisplayManagerInternal; private WindowManagerInternal mWindowManagerInternal; private final File mDoubleTouchGestureEnableFile; private WindowManagerCallbacks mWindowManagerCallbacks; Loading Loading @@ -628,7 +619,6 @@ public class InputManagerService extends IInputManager.Stub } mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mSettingsObserver.registerAndUpdate(); Loading Loading @@ -2674,46 +2664,8 @@ public class InputManagerService extends IInputManager.Stub // Native callback. @SuppressWarnings("unused") @VisibleForTesting long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { final long keyNotConsumedGoFallback = -2; final long keyConsumed = -1; final long keyNotConsumed = 0; long value = keyNotConsumed; // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts if ((event.isMetaPressed() || KeyEvent.isMetaKey(event.getKeyCode())) && shouldInterceptShortcuts(focus)) { return keyNotConsumed; } value = mKeyGestureController.interceptKeyBeforeDispatching(focus, event, policyFlags); if (value == keyNotConsumed) { value = mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags); } if (value == keyNotConsumed && event.isMetaPressed()) { if (fixSearchModifierFallbacks() ) { // If the key has not been consumed and includes the meta key, do not send the event // to the app and attempt to generate a fallback. final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap.FallbackAction fallbackAction = kcm.getFallbackAction(event.getKeyCode(), event.getMetaState()); if (fallbackAction != null) { return keyNotConsumedGoFallback; } } return keyConsumed; } return value; } private boolean shouldInterceptShortcuts(IBinder focusedToken) { KeyInterceptionInfo info = mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken); boolean hasInterceptWindowFlag = info != null && (info.layoutParamsPrivateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0; return hasInterceptWindowFlag && PermissionChecker.checkPermissionForDataDelivery(mContext, OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW, PID_UNKNOWN, info.windowOwnerUid, null, null, null) == PERMISSION_GRANTED; return mKeyGestureController.interceptKeyBeforeDispatching(focus, event, policyFlags); } // Native callback. Loading Loading @@ -3347,13 +3299,9 @@ public class InputManagerService extends IInputManager.Stub * key. * @param token the window token that's about to receive this event * @param event the key event that's being dispatched * @param policyFlags the policy flags * @return -1 if the key should be skipped (not sent to the app). -2 if the key should not * be sent to the app, but it should still generate a fallback. * 0 if the key should proceed getting dispatched to the app. positive value to indicate the * additional time delay, in nanoseconds, to wait before sending this key to the app. * @return {@code true} if consumed, and {@code false} otherwise. */ long interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags); boolean interceptKeyBeforeDispatching(IBinder token, KeyEvent event); /** * Intercept unhandled key Loading Loading @@ -3879,7 +3827,9 @@ public class InputManagerService extends IInputManager.Stub event, /* policyFlags= */0); } else { return mWindowManagerCallbacks.interceptKeyBeforeDispatching( /* focusedToken= */null, event, /* policyFlags= */0); /* focusedToken= */null, event) ? KeyGestureController.KEY_INTERCEPT_RESULT_CONSUMED : KeyGestureController.KEY_INTERCEPT_RESULT_NOT_CONSUMED; } } } Loading
services/core/java/com/android/server/input/KeyGestureController.java +66 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.server.input; import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW; import static android.content.PermissionChecker.PERMISSION_GRANTED; import static android.content.PermissionChecker.PID_UNKNOWN; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.os.UserManager.isVisibleBackgroundUsersEnabled; Loading @@ -25,9 +28,11 @@ import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER; import static android.view.WindowManagerPolicyConstants.FLAG_INTERACTIVE; import static com.android.hardware.input.Flags.enableNew25q2Keycodes; import static com.android.hardware.input.Flags.fixSearchModifierFallbacks; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import android.annotation.BinderThread; import android.annotation.LongDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -35,6 +40,7 @@ import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.content.ContentResolver; import android.content.Context; import android.content.PermissionChecker; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; Loading Loading @@ -74,16 +80,20 @@ import com.android.internal.accessibility.AccessibilityShortcutController; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.IShortcutService; 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.pm.UserManagerInternal; import com.android.server.wm.WindowManagerInternal; import org.xmlpull.v1.XmlPullParserException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; import java.util.Arrays; import java.util.HashSet; Loading Loading @@ -135,6 +145,19 @@ 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; @LongDef(prefix = {"KEY_INTERCEPT_RESULT_"}, value = { KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK, KEY_INTERCEPT_RESULT_CONSUMED, KEY_INTERCEPT_RESULT_NOT_CONSUMED }) @Retention(RetentionPolicy.SOURCE) private @interface KeyInterceptResult { } private static final long KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK = -2; static final long KEY_INTERCEPT_RESULT_CONSUMED = -1; static final long KEY_INTERCEPT_RESULT_NOT_CONSUMED = 0; private final Context mContext; private InputManagerService.WindowManagerCallbacks mWindowManagerCallbacks; private final Handler mHandler; Loading Loading @@ -193,6 +216,7 @@ final class KeyGestureController { private final SparseArray<Set<Integer>> mConsumedKeysForDevice = new SparseArray<>(); private final UserManagerInternal mUserManagerInternal; private WindowManagerInternal mWindowManagerInternal; private final boolean mVisibleBackgroundUsersEnabled = isVisibleBackgroundUsersEnabled(); Loading Loading @@ -450,6 +474,7 @@ final class KeyGestureController { } public void systemRunning() { mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mSettingsObserver.observe(); mAppLaunchShortcutManager.init(); mInputGestureManager.init(mAppLaunchShortcutManager.getBookmarks()); Loading Loading @@ -504,8 +529,47 @@ final class KeyGestureController { return false; } public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, int policyFlags) { public long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts if ((event.isMetaPressed() || KeyEvent.isMetaKey(event.getKeyCode())) && shouldInterceptShortcuts(focus)) { return KEY_INTERCEPT_RESULT_NOT_CONSUMED; } final long interceptResult = interceptKeyBeforeDispatchingInternal(focus, event); if (interceptResult != KEY_INTERCEPT_RESULT_NOT_CONSUMED) { // Result is either delay or consumed return interceptResult; } if (mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event)) { return KEY_INTERCEPT_RESULT_CONSUMED; } if (event.isMetaPressed()) { if (fixSearchModifierFallbacks() ) { // If the key has not been consumed and includes the meta key, do not send the event // to the app and attempt to generate a fallback. final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap.FallbackAction fallbackAction = kcm.getFallbackAction(event.getKeyCode(), event.getMetaState()); if (fallbackAction != null) { return KEY_INTERCEPT_RESULT_NOT_CONSUMED_GO_FALLBACK; } } return KEY_INTERCEPT_RESULT_CONSUMED; } return KEY_INTERCEPT_RESULT_NOT_CONSUMED; } private boolean shouldInterceptShortcuts(IBinder focusedToken) { KeyInterceptionInfo info = mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken); boolean hasInterceptWindowFlag = info != null && (info.layoutParamsPrivateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0; return hasInterceptWindowFlag && PermissionChecker.checkPermissionForDataDelivery(mContext, OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW, PID_UNKNOWN, info.windowOwnerUid, null, null, null) == PERMISSION_GRANTED; } private long interceptKeyBeforeDispatchingInternal(IBinder focusedToken, KeyEvent event) { // TODO(b/358569822): Handle shortcuts trigger logic here and pass it to appropriate // KeyGestureHandler (PWM is one of the handlers) final int keyCode = event.getKeyCode(); Loading
services/core/java/com/android/server/policy/PhoneWindowManager.java +3 −7 Original line number Diff line number Diff line Loading @@ -3334,12 +3334,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // TODO (b/283241997): Add the remaining keyboard shortcut logging after refactoring /** {@inheritDoc} */ @Override public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, int policyFlags) { public boolean interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event) { final int keyCode = event.getKeyCode(); final int flags = event.getFlags(); final long keyConsumed = -1; final long keyNotConsumed = 0; final int deviceId = event.getDeviceId(); if (DEBUG_INPUT) { Loading @@ -3358,7 +3354,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (interceptSystemKeysAndShortcuts(focusedToken, event) && event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { consumedKeys.add(keyCode); return keyConsumed; return true; } boolean needToConsumeKey = consumedKeys.contains(keyCode); Loading @@ -3369,7 +3365,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } return needToConsumeKey ? keyConsumed : keyNotConsumed; return needToConsumeKey; } // You can only start consuming the key gesture if ACTION_DOWN and repeat count Loading
services/core/java/com/android/server/policy/WindowManagerPolicy.java +2 −6 Original line number Diff line number Diff line Loading @@ -735,13 +735,9 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * @param focusedToken Client window token that currently has focus. This is where the key * event will normally go. * @param event The key event. * @param policyFlags The policy flags associated with the key. * @return 0 if the key should be dispatched immediately, -1 if the key should * not be dispatched ever, or a positive value indicating the number of * milliseconds by which the key dispatch should be delayed before trying * again. * @return {@code true} if consumed, and {@code false} otherwise. */ long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, int policyFlags); boolean interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event); /** * Called from the input dispatcher thread when an application did not handle Loading
services/core/java/com/android/server/wm/InputManagerCallback.java +2 −3 Original line number Diff line number Diff line Loading @@ -234,9 +234,8 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal * ordinary dispatch. */ @Override public long interceptKeyBeforeDispatching( IBinder focusedToken, KeyEvent event, int policyFlags) { return mService.mPolicy.interceptKeyBeforeDispatching(focusedToken, event, policyFlags); public boolean interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event) { return mService.mPolicy.interceptKeyBeforeDispatching(focusedToken, event); } /** Loading