diff options
3 files changed, 88 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index cf1036c03c83..72c10cc9a5e8 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -32,7 +32,6 @@ import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.O; import static android.os.IInputConstants.INVALID_INPUT_DEVICE_ID; import static android.provider.Settings.Secure.VOLUME_HUSH_OFF; -import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.STATE_OFF; @@ -69,6 +68,7 @@ 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.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE; @@ -101,6 +101,7 @@ import android.app.ActivityManager.RecentTaskInfo; import android.app.ActivityManagerInternal; import android.app.ActivityTaskManager; import android.app.AppOpsManager; +import android.app.IActivityManager; import android.app.IUiModeManager; import android.app.NotificationManager; import android.app.ProgressDialog; @@ -427,6 +428,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManagerInternal mWindowManagerInternal; PowerManager mPowerManager; ActivityManagerInternal mActivityManagerInternal; + IActivityManager mActivityManagerService; ActivityTaskManagerInternal mActivityTaskManagerInternal; AutofillManagerInternal mAutofillManagerInternal; InputManager mInputManager; @@ -549,7 +551,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLidNavigationAccessibility; int mShortPressOnPowerBehavior; private boolean mShouldEarlyShortPressOnPower; - private boolean mShouldEarlyShortPressOnStemPrimary; + boolean mShouldEarlyShortPressOnStemPrimary; int mLongPressOnPowerBehavior; long mLongPressOnPowerAssistantTimeoutMs; int mVeryLongPressOnPowerBehavior; @@ -578,6 +580,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private int mDoublePressOnStemPrimaryBehavior; private int mTriplePressOnStemPrimaryBehavior; private int mLongPressOnStemPrimaryBehavior; + private RecentTaskInfo mBackgroundRecentTaskInfoOnStemPrimarySingleKeyUp; private boolean mHandleVolumeKeysInWM; @@ -1563,7 +1566,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { ? false : mKeyguardDelegate.isShowing(); if (!keyguardActive) { - switchRecentTask(); + performStemPrimaryDoublePressSwitchToRecentTask(); } break; } @@ -1672,11 +1675,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** * Load most recent task (expect current task) and bring it to the front. */ - private void switchRecentTask() { - RecentTaskInfo targetTask = mActivityTaskManagerInternal.getMostRecentTaskFromBackground(); + void performStemPrimaryDoublePressSwitchToRecentTask() { + RecentTaskInfo targetTask = mBackgroundRecentTaskInfoOnStemPrimarySingleKeyUp; if (targetTask == null) { if (DEBUG_INPUT) { - Slog.w(TAG, "No recent task available! Show watch face."); + Slog.w(TAG, "No recent task available! Show wallpaper."); } goHome(); return; @@ -1695,7 +1698,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { + targetTask.baseIntent); } try { - ActivityManager.getService().startActivityFromRecents(targetTask.persistentId, null); + mActivityManagerService.startActivityFromRecents(targetTask.persistentId, null); } catch (RemoteException | IllegalArgumentException e) { Slog.e(TAG, "Failed to start task " + targetTask.persistentId + " from recents", e); } @@ -2219,6 +2222,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }); } + + IActivityManager getActivityManagerService() { + return ActivityManager.getService(); + } } /** {@inheritDoc} */ @@ -2233,6 +2240,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManagerFuncs = injector.getWindowManagerFuncs(); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); + mActivityManagerService = injector.getActivityManagerService(); mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mInputManager = mContext.getSystemService(InputManager.class); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); @@ -2767,8 +2775,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override void onKeyUp(long eventTime, int count) { - if (mShouldEarlyShortPressOnStemPrimary && count == 1) { - stemPrimaryPress(1 /*pressCount*/); + if (count == 1) { + // Save info about the most recent task on the first press of the stem key. This + // may be used later to switch to the most recent app using double press gesture. + // It is possible that we may navigate away from this task before the double + // press is detected, as a result of the first press, so we save the current + // most recent task before that happens. + mBackgroundRecentTaskInfoOnStemPrimarySingleKeyUp = + mActivityTaskManagerInternal.getMostRecentTaskFromBackground(); + if (mShouldEarlyShortPressOnStemPrimary) { + stemPrimaryPress(1 /*pressCount*/); + } } } } diff --git a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java index eab8757b7331..912e1d3df945 100644 --- a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java @@ -16,15 +16,19 @@ package com.android.server.policy; +import static android.provider.Settings.Global.STEM_PRIMARY_BUTTON_DOUBLE_PRESS; import static android.provider.Settings.Global.STEM_PRIMARY_BUTTON_LONG_PRESS; import static android.provider.Settings.Global.STEM_PRIMARY_BUTTON_SHORT_PRESS; import static android.view.KeyEvent.KEYCODE_STEM_PRIMARY; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT; import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS; import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_PRIMARY_LAUNCH_TARGET_ACTIVITY; +import android.app.ActivityManager.RecentTaskInfo; import android.content.ComponentName; +import android.os.RemoteException; import android.provider.Settings; import org.junit.Test; @@ -120,6 +124,46 @@ public class StemKeyGestureTests extends ShortcutKeyTestBase { mPhoneWindowManager.assertStatusBarStartAssist(); } + @Test + public void stemDoubleKey_EarlyShortPress_AllAppsThenSwitchToMostRecent() + throws RemoteException { + overrideBehavior(STEM_PRIMARY_BUTTON_DOUBLE_PRESS, SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS); + setUpPhoneWindowManager(/* supportSettingsUpdate= */ true); + mPhoneWindowManager.overrideShouldEarlyShortPressOnStemPrimary(true); + mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false); + mPhoneWindowManager.overrideIsUserSetupComplete(true); + RecentTaskInfo recentTaskInfo = new RecentTaskInfo(); + int referenceId = 666; + recentTaskInfo.persistentId = referenceId; + doReturn(recentTaskInfo).when( + mPhoneWindowManager.mActivityTaskManagerInternal).getMostRecentTaskFromBackground(); + + sendKey(KEYCODE_STEM_PRIMARY); + sendKey(KEYCODE_STEM_PRIMARY); + + mPhoneWindowManager.assertOpenAllAppView(); + mPhoneWindowManager.assertSwitchToRecent(referenceId); + } + + @Test + public void stemDoubleKey_NoEarlyShortPress_SwitchToMostRecent() throws RemoteException { + overrideBehavior(STEM_PRIMARY_BUTTON_DOUBLE_PRESS, SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS); + setUpPhoneWindowManager(/* supportSettingsUpdate= */ true); + mPhoneWindowManager.overrideShouldEarlyShortPressOnStemPrimary(false); + mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false); + mPhoneWindowManager.overrideIsUserSetupComplete(true); + RecentTaskInfo recentTaskInfo = new RecentTaskInfo(); + int referenceId = 666; + recentTaskInfo.persistentId = referenceId; + doReturn(recentTaskInfo).when( + mPhoneWindowManager.mActivityTaskManagerInternal).getMostRecentTaskFromBackground(); + + sendKey(KEYCODE_STEM_PRIMARY); + sendKey(KEYCODE_STEM_PRIMARY); + + mPhoneWindowManager.assertNotOpenAllAppView(); + mPhoneWindowManager.assertSwitchToRecent(referenceId); + } private void overrideBehavior(String key, int expectedBehavior) { Settings.Global.putLong(mContext.getContentResolver(), key, expectedBehavior); diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java index e26260a6836c..314cd04695ba 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -57,6 +57,7 @@ import static org.mockito.Mockito.withSettings; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; +import android.app.IActivityManager; import android.app.NotificationManager; import android.app.SearchManager; import android.content.ComponentName; @@ -126,7 +127,8 @@ class TestPhoneWindowManager { @Mock private WindowManagerInternal mWindowManagerInternal; @Mock private ActivityManagerInternal mActivityManagerInternal; - @Mock private ActivityTaskManagerInternal mActivityTaskManagerInternal; + @Mock ActivityTaskManagerInternal mActivityTaskManagerInternal; + @Mock IActivityManager mActivityManagerService; @Mock private InputManagerInternal mInputManagerInternal; @Mock private InputManager mInputManager; @Mock private SensorPrivacyManager mSensorPrivacyManager; @@ -181,6 +183,10 @@ class TestPhoneWindowManager { KeyguardServiceDelegate getKeyguardServiceDelegate() { return mKeyguardServiceDelegate; } + + IActivityManager getActivityManagerService() { + return mActivityManagerService; + } } TestPhoneWindowManager(Context context, boolean supportSettingsUpdate) { @@ -347,6 +353,10 @@ class TestPhoneWindowManager { mPhoneWindowManager.mShortPressOnPowerBehavior = behavior; } + void overrideShouldEarlyShortPressOnStemPrimary(boolean shouldEarlyShortPress) { + mPhoneWindowManager.mShouldEarlyShortPressOnStemPrimary = shouldEarlyShortPress; + } + // Override assist perform function. void overrideLongPressOnPower(int behavior) { mPhoneWindowManager.mLongPressOnPowerBehavior = behavior; @@ -667,4 +677,11 @@ class TestPhoneWindowManager { vendorId, productId, logEvent.getIntValue(), new int[]{expectedKey}, expectedModifierState), description(errorMsg)); } + + void assertSwitchToRecent(int persistentId) throws RemoteException { + mTestLooper.dispatchAll(); + verify(mActivityManagerService, + timeout(TEST_SINGLE_KEY_DELAY_MILLIS)).startActivityFromRecents(eq(persistentId), + isNull()); + } } |