Loading services/core/java/com/android/server/input/KeyGestureController.java +60 −1 Original line number Diff line number Diff line Loading @@ -20,9 +20,12 @@ import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.os.UserManager.isVisibleBackgroundUsersEnabled; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD; 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.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import android.annotation.BinderThread; import android.annotation.MainThread; Loading Loading @@ -52,6 +55,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.Settings; import android.util.IndentingPrintWriter; import android.util.Log; Loading @@ -63,12 +67,15 @@ import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.ViewConfiguration; import android.view.WindowManager; import com.android.internal.R; 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.util.ScreenshotHelper; import com.android.internal.util.ScreenshotRequest; import com.android.server.LocalServices; import com.android.server.pm.UserManagerInternal; Loading Loading @@ -106,6 +113,7 @@ final class KeyGestureController { private static final int MSG_PERSIST_CUSTOM_GESTURES = 2; 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; // must match: config_settingsKeyBehavior in config.xml private static final int SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY = 0; Loading @@ -123,12 +131,17 @@ final class KeyGestureController { static final int POWER_VOLUME_UP_BEHAVIOR_MUTE = 1; static final int POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS = 2; // Screenshot trigger states // Increase the chord delay when taking a screenshot from the keyguard private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; private final Context mContext; private InputManagerService.WindowManagerCallbacks mWindowManagerCallbacks; private final Handler mHandler; private final Handler mIoHandler; private final int mSystemPid; private final KeyCombinationManager mKeyCombinationManager; private final ScreenshotHelper mScreenshotHelper; private final SettingsObserver mSettingsObserver; private final AppLaunchShortcutManager mAppLaunchShortcutManager; @VisibleForTesting Loading Loading @@ -196,6 +209,7 @@ final class KeyGestureController { mIoHandler = new Handler(ioLooper, this::handleIoMessage); mSystemPid = Process.myPid(); mKeyCombinationManager = new KeyCombinationManager(mHandler); mScreenshotHelper = injector.getScreenshotHelper(mContext); mSettingsObserver = new SettingsObserver(mHandler); mAppLaunchShortcutManager = new AppLaunchShortcutManager(mContext); mInputGestureManager = new InputGestureManager(mContext); Loading Loading @@ -454,7 +468,9 @@ final class KeyGestureController { InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class)); im.registerKeyGestureEventHandler( List.of(KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT), KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT, KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT, KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD), new LocalKeyGestureEventHandler()); } Loading Loading @@ -1083,6 +1099,10 @@ final class KeyGestureController { case MSG_ACCESSIBILITY_SHORTCUT: mAccessibilityShortcutController.performAccessibilityShortcut(); break; case MSG_SCREENSHOT_SHORTCUT: takeScreenshot(msg.arg1, msg.arg2); break; } return true; } Loading Loading @@ -1454,6 +1474,25 @@ final class KeyGestureController { } } private void takeScreenshot(int source, int displayId) { ScreenshotRequest request = new ScreenshotRequest.Builder(WindowManager.TAKE_SCREENSHOT_FULLSCREEN, source) .setDisplayId(displayId) .build(); mScreenshotHelper.takeScreenshot(request, mHandler, null /* completionConsumer */); } private long getScreenshotChordLongPressDelay() { long delayMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_SYSTEMUI, SCREENSHOT_KEYCHORD_DELAY, ViewConfiguration.get(mContext).getScreenshotChordKeyTimeout()); if (mWindowManagerCallbacks.isKeyguardLocked(DEFAULT_DISPLAY)) { // Double the time it takes to take a screenshot from the keyguard return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * delayMs); } return delayMs; } public void dump(IndentingPrintWriter ipw) { ipw.println("KeyGestureController:"); ipw.increaseIndent(); Loading Loading @@ -1510,6 +1549,10 @@ final class KeyGestureController { Handler handler) { return new AccessibilityShortcutController(context, handler, UserHandle.USER_SYSTEM); } ScreenshotHelper getScreenshotHelper(Context context) { return new ScreenshotHelper(context); } } private class LocalKeyGestureEventHandler implements InputManager.KeyGestureEventHandler { Loading @@ -1534,6 +1577,22 @@ final class KeyGestureController { mHandler.sendMessage(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT)); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT: if (complete) { mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREENSHOT_SHORTCUT, SCREENSHOT_KEY_OTHER, event.getDisplayId())); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD: mHandler.removeMessages(MSG_SCREENSHOT_SHORTCUT); if (start) { mHandler.sendMessageDelayed( mHandler.obtainMessage(MSG_SCREENSHOT_SHORTCUT, SCREENSHOT_KEY_CHORD, event.getDisplayId()), getScreenshotChordLongPressDelay()); } break; default: Log.w(TAG, "Received a key gesture " + event + " that was not registered by this handler"); Loading services/core/java/com/android/server/policy/PhoneWindowManager.java +0 −58 Original line number Diff line number Diff line Loading @@ -74,16 +74,12 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER; import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN; import static android.view.WindowManagerGlobal.ADD_OKAY; import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED; import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled; import static com.android.hardware.input.Flags.enableNew25q2Keycodes; import static com.android.hardware.input.Flags.enableTalkbackAndMagnifierKeyGestures; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; Loading Loading @@ -175,7 +171,6 @@ import android.os.Trace; import android.os.UEventObserver; import android.os.UserHandle; import android.os.Vibrator; import android.provider.DeviceConfig; import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.Secure; Loading Loading @@ -376,7 +371,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot"; static public final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav"; public static final String TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD = "waitForAllWindowsDrawn"; Loading Loading @@ -667,10 +661,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Whether to go to sleep entering theater mode from power button private boolean mGoToSleepOnButtonPressTheaterMode; // Screenshot trigger states // Increase the chord delay when taking a screenshot from the keyguard private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up int mRingerToggleChord = VOLUME_HUSH_OFF; Loading Loading @@ -722,7 +712,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_HIDE_BOOT_MESSAGE = 11; private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 15; private static final int MSG_SCREENSHOT_CHORD = 16; private static final int MSG_BUGREPORT_TV = 18; private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 20; private static final int MSG_SYSTEM_KEY_PRESS = 21; Loading Loading @@ -804,9 +793,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_RINGER_TOGGLE_CHORD: handleRingerChordGesture(); break; case MSG_SCREENSHOT_CHORD: handleScreenShot(msg.arg1); break; case MSG_SWITCH_KEYBOARD_LAYOUT: SwitchKeyboardLayoutMessageObject object = (SwitchKeyboardLayoutMessageObject) msg.obj; Loading Loading @@ -1774,40 +1760,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { || defaultShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING; } private void interceptScreenshotChord(int source, long pressDelay) { mHandler.removeMessages(MSG_SCREENSHOT_CHORD); // arg2 is unused, but necessary to insure we call the correct method signature // since the screenshot source is read from message.arg1 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SCREENSHOT_CHORD, source, 0), pressDelay); } private void interceptRingerToggleChord() { mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RINGER_TOGGLE_CHORD), getRingerToggleChordDelay()); } private long getScreenshotChordLongPressDelay() { long delayMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_SYSTEMUI, SCREENSHOT_KEYCHORD_DELAY, ViewConfiguration.get(mContext).getScreenshotChordKeyTimeout()); if (mKeyguardDelegate.isShowing()) { // Double the time it takes to take a screenshot from the keyguard return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * delayMs); } return delayMs; } private long getRingerToggleChordDelay() { // Always timeout like a tap return ViewConfiguration.getTapTimeout(); } private void cancelPendingScreenshotChordAction() { mHandler.removeMessages(MSG_SCREENSHOT_CHORD); } private void cancelPendingRingerToggleChordAction() { mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD); } Loading @@ -1822,10 +1785,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; private void handleScreenShot(@WindowManager.ScreenshotSource int source) { mDefaultDisplayPolicy.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN, source); } @Override public void showGlobalActions() { mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); Loading Loading @@ -3381,7 +3340,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS, KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN, KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT, KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT, KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION, KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE, Loading @@ -3395,7 +3353,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { KeyGestureEvent.KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS, KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB, KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_RINGER_TOGGLE_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_GLOBAL_ACTIONS, KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT Loading Loading @@ -3479,11 +3436,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { toggleNotificationPanel(); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT: if (complete) { interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT: if (complete && mEnableBugReportKeyboardShortcut) { try { Loading Loading @@ -3568,16 +3520,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { sendSwitchKeyboardLayout(displayId, focusedToken, direction); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD: if (start) { // Screenshot chord is pressed: Wait for long press delay before taking // screenshot interceptScreenshotChord(SCREENSHOT_KEY_CHORD, getScreenshotChordLongPressDelay()); } else { cancelPendingScreenshotChordAction(); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_RINGER_TOGGLE_CHORD: if (start) { interceptRingerToggleChord(); Loading services/core/java/com/android/server/wm/DisplayPolicy.java +0 −23 Original line number Diff line number Diff line Loading @@ -133,8 +133,6 @@ import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.protolog.ProtoLog; import com.android.internal.statusbar.LetterboxDetails; import com.android.internal.util.ScreenshotHelper; import com.android.internal.util.ScreenshotRequest; import com.android.internal.util.function.TriFunction; import com.android.internal.view.AppearanceRegion; import com.android.internal.widget.PointerLocationView; Loading Loading @@ -198,7 +196,6 @@ public class DisplayPolicy { private final boolean mCarDockEnablesAccelerometer; private final boolean mDeskDockEnablesAccelerometer; private final AccessibilityManager mAccessibilityManager; private final ScreenshotHelper mScreenshotHelper; private final Object mServiceAcquireLock = new Object(); private long mPanicTime; Loading Loading @@ -658,10 +655,6 @@ public class DisplayPolicy { }; displayContent.mTransitionController.registerLegacyListener(mAppTransitionListener); // TODO: Make it can take screenshot on external display mScreenshotHelper = displayContent.isDefaultDisplay ? new ScreenshotHelper(mContext) : null; if (mDisplayContent.isDefaultDisplay) { mHasStatusBar = true; mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar); Loading Loading @@ -3050,22 +3043,6 @@ public class DisplayPolicy { mService.mAtmService.setProcessAnimatingWhileDozing(w != null ? w.getProcess() : null); } /** * Request a screenshot be taken. * * @param screenshotType The type of screenshot, for example either * {@link WindowManager#TAKE_SCREENSHOT_FULLSCREEN} or * {@link WindowManager#TAKE_SCREENSHOT_PROVIDED_IMAGE} * @param source Where the screenshot originated from (see WindowManager.ScreenshotSource) */ public void takeScreenshot(int screenshotType, int source) { if (mScreenshotHelper != null) { ScreenshotRequest request = new ScreenshotRequest.Builder(screenshotType, source).build(); mScreenshotHelper.takeScreenshot(request, mHandler, null /* completionConsumer */); } } RefreshRatePolicy getRefreshRatePolicy() { return mRefreshRatePolicy; } Loading services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java +0 −21 Original line number Diff line number Diff line Loading @@ -259,12 +259,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { mPhoneWindowManager.assertTogglePanel(); } @Test public void testKeyGestureScreenshot() { sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT); mPhoneWindowManager.assertTakeScreenshotCalled(); } @Test public void testKeyGestureTriggerBugReport() throws RemoteException { sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT); Loading Loading @@ -348,21 +342,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { mPhoneWindowManager.assertLaunchSearch(); } @Test public void testKeyGestureScreenshotChord() { sendKeyGestureEventStart(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); mPhoneWindowManager.moveTimeForward(500); sendKeyGestureEventCancel(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); mPhoneWindowManager.assertTakeScreenshotCalled(); } @Test public void testKeyGestureScreenshotChordCancelled() { sendKeyGestureEventStart(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); sendKeyGestureEventCancel(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); mPhoneWindowManager.assertTakeScreenshotNotCalled(); } @Test public void testKeyGestureRingerToggleChord() { mPhoneWindowManager.overrideVolumeHushMode(); Loading services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +0 −14 Original line number Diff line number Diff line Loading @@ -358,7 +358,6 @@ class TestPhoneWindowManager { doReturn(mDisplay).when(mDisplayManager).getDisplay(eq(DEFAULT_DISPLAY)); doReturn(STATE_ON).when(mDisplay).getState(); doReturn(true).when(mDisplayPolicy).isAwake(); doNothing().when(mDisplayPolicy).takeScreenshot(anyInt(), anyInt()); doReturn(mDisplayPolicy).when(mDisplayRotation).getDisplayPolicy(); doReturn(mScreenOnListener).when(mDisplayPolicy).getScreenOnListener(); mPhoneWindowManager.setDefaultDisplay(new WindowManagerPolicy.DisplayContentInfo() { Loading Loading @@ -682,19 +681,6 @@ class TestPhoneWindowManager { mKeyEventPolicyFlags = flags; } /** * Below functions will check the policy behavior could be invoked. */ void assertTakeScreenshotCalled() { mTestLooper.dispatchAll(); verify(mDisplayPolicy).takeScreenshot(anyInt(), anyInt()); } void assertTakeScreenshotNotCalled() { mTestLooper.dispatchAll(); verify(mDisplayPolicy, never()).takeScreenshot(anyInt(), anyInt()); } void assertShowGlobalActionsCalled() { mTestLooper.dispatchAll(); verify(mPhoneWindowManager).showGlobalActions(); Loading Loading
services/core/java/com/android/server/input/KeyGestureController.java +60 −1 Original line number Diff line number Diff line Loading @@ -20,9 +20,12 @@ import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.os.UserManager.isVisibleBackgroundUsersEnabled; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD; 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.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import android.annotation.BinderThread; import android.annotation.MainThread; Loading Loading @@ -52,6 +55,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.Settings; import android.util.IndentingPrintWriter; import android.util.Log; Loading @@ -63,12 +67,15 @@ import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.ViewConfiguration; import android.view.WindowManager; import com.android.internal.R; 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.util.ScreenshotHelper; import com.android.internal.util.ScreenshotRequest; import com.android.server.LocalServices; import com.android.server.pm.UserManagerInternal; Loading Loading @@ -106,6 +113,7 @@ final class KeyGestureController { private static final int MSG_PERSIST_CUSTOM_GESTURES = 2; 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; // must match: config_settingsKeyBehavior in config.xml private static final int SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY = 0; Loading @@ -123,12 +131,17 @@ final class KeyGestureController { static final int POWER_VOLUME_UP_BEHAVIOR_MUTE = 1; static final int POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS = 2; // Screenshot trigger states // Increase the chord delay when taking a screenshot from the keyguard private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; private final Context mContext; private InputManagerService.WindowManagerCallbacks mWindowManagerCallbacks; private final Handler mHandler; private final Handler mIoHandler; private final int mSystemPid; private final KeyCombinationManager mKeyCombinationManager; private final ScreenshotHelper mScreenshotHelper; private final SettingsObserver mSettingsObserver; private final AppLaunchShortcutManager mAppLaunchShortcutManager; @VisibleForTesting Loading Loading @@ -196,6 +209,7 @@ final class KeyGestureController { mIoHandler = new Handler(ioLooper, this::handleIoMessage); mSystemPid = Process.myPid(); mKeyCombinationManager = new KeyCombinationManager(mHandler); mScreenshotHelper = injector.getScreenshotHelper(mContext); mSettingsObserver = new SettingsObserver(mHandler); mAppLaunchShortcutManager = new AppLaunchShortcutManager(mContext); mInputGestureManager = new InputGestureManager(mContext); Loading Loading @@ -454,7 +468,9 @@ final class KeyGestureController { InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class)); im.registerKeyGestureEventHandler( List.of(KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT), KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT, KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT, KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD), new LocalKeyGestureEventHandler()); } Loading Loading @@ -1083,6 +1099,10 @@ final class KeyGestureController { case MSG_ACCESSIBILITY_SHORTCUT: mAccessibilityShortcutController.performAccessibilityShortcut(); break; case MSG_SCREENSHOT_SHORTCUT: takeScreenshot(msg.arg1, msg.arg2); break; } return true; } Loading Loading @@ -1454,6 +1474,25 @@ final class KeyGestureController { } } private void takeScreenshot(int source, int displayId) { ScreenshotRequest request = new ScreenshotRequest.Builder(WindowManager.TAKE_SCREENSHOT_FULLSCREEN, source) .setDisplayId(displayId) .build(); mScreenshotHelper.takeScreenshot(request, mHandler, null /* completionConsumer */); } private long getScreenshotChordLongPressDelay() { long delayMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_SYSTEMUI, SCREENSHOT_KEYCHORD_DELAY, ViewConfiguration.get(mContext).getScreenshotChordKeyTimeout()); if (mWindowManagerCallbacks.isKeyguardLocked(DEFAULT_DISPLAY)) { // Double the time it takes to take a screenshot from the keyguard return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * delayMs); } return delayMs; } public void dump(IndentingPrintWriter ipw) { ipw.println("KeyGestureController:"); ipw.increaseIndent(); Loading Loading @@ -1510,6 +1549,10 @@ final class KeyGestureController { Handler handler) { return new AccessibilityShortcutController(context, handler, UserHandle.USER_SYSTEM); } ScreenshotHelper getScreenshotHelper(Context context) { return new ScreenshotHelper(context); } } private class LocalKeyGestureEventHandler implements InputManager.KeyGestureEventHandler { Loading @@ -1534,6 +1577,22 @@ final class KeyGestureController { mHandler.sendMessage(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT)); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT: if (complete) { mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREENSHOT_SHORTCUT, SCREENSHOT_KEY_OTHER, event.getDisplayId())); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD: mHandler.removeMessages(MSG_SCREENSHOT_SHORTCUT); if (start) { mHandler.sendMessageDelayed( mHandler.obtainMessage(MSG_SCREENSHOT_SHORTCUT, SCREENSHOT_KEY_CHORD, event.getDisplayId()), getScreenshotChordLongPressDelay()); } break; default: Log.w(TAG, "Received a key gesture " + event + " that was not registered by this handler"); Loading
services/core/java/com/android/server/policy/PhoneWindowManager.java +0 −58 Original line number Diff line number Diff line Loading @@ -74,16 +74,12 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER; import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN; import static android.view.WindowManagerGlobal.ADD_OKAY; import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED; import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled; import static com.android.hardware.input.Flags.enableNew25q2Keycodes; import static com.android.hardware.input.Flags.enableTalkbackAndMagnifierKeyGestures; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; Loading Loading @@ -175,7 +171,6 @@ import android.os.Trace; import android.os.UEventObserver; import android.os.UserHandle; import android.os.Vibrator; import android.provider.DeviceConfig; import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.Secure; Loading Loading @@ -376,7 +371,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot"; static public final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav"; public static final String TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD = "waitForAllWindowsDrawn"; Loading Loading @@ -667,10 +661,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Whether to go to sleep entering theater mode from power button private boolean mGoToSleepOnButtonPressTheaterMode; // Screenshot trigger states // Increase the chord delay when taking a screenshot from the keyguard private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up int mRingerToggleChord = VOLUME_HUSH_OFF; Loading Loading @@ -722,7 +712,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_HIDE_BOOT_MESSAGE = 11; private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 15; private static final int MSG_SCREENSHOT_CHORD = 16; private static final int MSG_BUGREPORT_TV = 18; private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 20; private static final int MSG_SYSTEM_KEY_PRESS = 21; Loading Loading @@ -804,9 +793,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_RINGER_TOGGLE_CHORD: handleRingerChordGesture(); break; case MSG_SCREENSHOT_CHORD: handleScreenShot(msg.arg1); break; case MSG_SWITCH_KEYBOARD_LAYOUT: SwitchKeyboardLayoutMessageObject object = (SwitchKeyboardLayoutMessageObject) msg.obj; Loading Loading @@ -1774,40 +1760,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { || defaultShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING; } private void interceptScreenshotChord(int source, long pressDelay) { mHandler.removeMessages(MSG_SCREENSHOT_CHORD); // arg2 is unused, but necessary to insure we call the correct method signature // since the screenshot source is read from message.arg1 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SCREENSHOT_CHORD, source, 0), pressDelay); } private void interceptRingerToggleChord() { mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RINGER_TOGGLE_CHORD), getRingerToggleChordDelay()); } private long getScreenshotChordLongPressDelay() { long delayMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_SYSTEMUI, SCREENSHOT_KEYCHORD_DELAY, ViewConfiguration.get(mContext).getScreenshotChordKeyTimeout()); if (mKeyguardDelegate.isShowing()) { // Double the time it takes to take a screenshot from the keyguard return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * delayMs); } return delayMs; } private long getRingerToggleChordDelay() { // Always timeout like a tap return ViewConfiguration.getTapTimeout(); } private void cancelPendingScreenshotChordAction() { mHandler.removeMessages(MSG_SCREENSHOT_CHORD); } private void cancelPendingRingerToggleChordAction() { mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD); } Loading @@ -1822,10 +1785,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; private void handleScreenShot(@WindowManager.ScreenshotSource int source) { mDefaultDisplayPolicy.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN, source); } @Override public void showGlobalActions() { mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); Loading Loading @@ -3381,7 +3340,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS, KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN, KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT, KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT, KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION, KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE, Loading @@ -3395,7 +3353,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { KeyGestureEvent.KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS, KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB, KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_RINGER_TOGGLE_CHORD, KeyGestureEvent.KEY_GESTURE_TYPE_GLOBAL_ACTIONS, KeyGestureEvent.KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT Loading Loading @@ -3479,11 +3436,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { toggleNotificationPanel(); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT: if (complete) { interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT: if (complete && mEnableBugReportKeyboardShortcut) { try { Loading Loading @@ -3568,16 +3520,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { sendSwitchKeyboardLayout(displayId, focusedToken, direction); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD: if (start) { // Screenshot chord is pressed: Wait for long press delay before taking // screenshot interceptScreenshotChord(SCREENSHOT_KEY_CHORD, getScreenshotChordLongPressDelay()); } else { cancelPendingScreenshotChordAction(); } break; case KeyGestureEvent.KEY_GESTURE_TYPE_RINGER_TOGGLE_CHORD: if (start) { interceptRingerToggleChord(); Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +0 −23 Original line number Diff line number Diff line Loading @@ -133,8 +133,6 @@ import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.protolog.ProtoLog; import com.android.internal.statusbar.LetterboxDetails; import com.android.internal.util.ScreenshotHelper; import com.android.internal.util.ScreenshotRequest; import com.android.internal.util.function.TriFunction; import com.android.internal.view.AppearanceRegion; import com.android.internal.widget.PointerLocationView; Loading Loading @@ -198,7 +196,6 @@ public class DisplayPolicy { private final boolean mCarDockEnablesAccelerometer; private final boolean mDeskDockEnablesAccelerometer; private final AccessibilityManager mAccessibilityManager; private final ScreenshotHelper mScreenshotHelper; private final Object mServiceAcquireLock = new Object(); private long mPanicTime; Loading Loading @@ -658,10 +655,6 @@ public class DisplayPolicy { }; displayContent.mTransitionController.registerLegacyListener(mAppTransitionListener); // TODO: Make it can take screenshot on external display mScreenshotHelper = displayContent.isDefaultDisplay ? new ScreenshotHelper(mContext) : null; if (mDisplayContent.isDefaultDisplay) { mHasStatusBar = true; mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar); Loading Loading @@ -3050,22 +3043,6 @@ public class DisplayPolicy { mService.mAtmService.setProcessAnimatingWhileDozing(w != null ? w.getProcess() : null); } /** * Request a screenshot be taken. * * @param screenshotType The type of screenshot, for example either * {@link WindowManager#TAKE_SCREENSHOT_FULLSCREEN} or * {@link WindowManager#TAKE_SCREENSHOT_PROVIDED_IMAGE} * @param source Where the screenshot originated from (see WindowManager.ScreenshotSource) */ public void takeScreenshot(int screenshotType, int source) { if (mScreenshotHelper != null) { ScreenshotRequest request = new ScreenshotRequest.Builder(screenshotType, source).build(); mScreenshotHelper.takeScreenshot(request, mHandler, null /* completionConsumer */); } } RefreshRatePolicy getRefreshRatePolicy() { return mRefreshRatePolicy; } Loading
services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java +0 −21 Original line number Diff line number Diff line Loading @@ -259,12 +259,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { mPhoneWindowManager.assertTogglePanel(); } @Test public void testKeyGestureScreenshot() { sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT); mPhoneWindowManager.assertTakeScreenshotCalled(); } @Test public void testKeyGestureTriggerBugReport() throws RemoteException { sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT); Loading Loading @@ -348,21 +342,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { mPhoneWindowManager.assertLaunchSearch(); } @Test public void testKeyGestureScreenshotChord() { sendKeyGestureEventStart(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); mPhoneWindowManager.moveTimeForward(500); sendKeyGestureEventCancel(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); mPhoneWindowManager.assertTakeScreenshotCalled(); } @Test public void testKeyGestureScreenshotChordCancelled() { sendKeyGestureEventStart(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); sendKeyGestureEventCancel(KeyGestureEvent.KEY_GESTURE_TYPE_SCREENSHOT_CHORD); mPhoneWindowManager.assertTakeScreenshotNotCalled(); } @Test public void testKeyGestureRingerToggleChord() { mPhoneWindowManager.overrideVolumeHushMode(); Loading
services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +0 −14 Original line number Diff line number Diff line Loading @@ -358,7 +358,6 @@ class TestPhoneWindowManager { doReturn(mDisplay).when(mDisplayManager).getDisplay(eq(DEFAULT_DISPLAY)); doReturn(STATE_ON).when(mDisplay).getState(); doReturn(true).when(mDisplayPolicy).isAwake(); doNothing().when(mDisplayPolicy).takeScreenshot(anyInt(), anyInt()); doReturn(mDisplayPolicy).when(mDisplayRotation).getDisplayPolicy(); doReturn(mScreenOnListener).when(mDisplayPolicy).getScreenOnListener(); mPhoneWindowManager.setDefaultDisplay(new WindowManagerPolicy.DisplayContentInfo() { Loading Loading @@ -682,19 +681,6 @@ class TestPhoneWindowManager { mKeyEventPolicyFlags = flags; } /** * Below functions will check the policy behavior could be invoked. */ void assertTakeScreenshotCalled() { mTestLooper.dispatchAll(); verify(mDisplayPolicy).takeScreenshot(anyInt(), anyInt()); } void assertTakeScreenshotNotCalled() { mTestLooper.dispatchAll(); verify(mDisplayPolicy, never()).takeScreenshot(anyInt(), anyInt()); } void assertShowGlobalActionsCalled() { mTestLooper.dispatchAll(); verify(mPhoneWindowManager).showGlobalActions(); Loading