diff options
| author | 2023-10-27 19:14:00 -0700 | |
|---|---|---|
| committer | 2023-11-13 17:05:07 -0800 | |
| commit | 358af23218e3fbacfb4a17d1e94f3d5431513183 (patch) | |
| tree | 325a9053268bae1db664a1309adcb23c8099e4c9 | |
| parent | eac0de972b98bcdc03d6a0def82c457ccfcffe7b (diff) | |
clobber wom: get correct most recent task when stem early short press
The expected double press behavior is to switch to the most recent app.
When "early short press" enabled for stem primary key, an ALL_APPS
launcher is launched upon first key-up envet. That means if we
query the most recent backgroud task at detected double press event,
we'll always get the ALL_APPS launcher, instead of the correct
"most recent app". So, we need to collect the "most recent app" info
earlier, before the ALL_APPS launcher of key-up and use that collected
info as the target task to swtich to at double press event.
Test: atest WmTests:StemKeyGestureTests
BUG: 297122524
Change-Id: I23f6e144b7265643980ba1d6619776c7058d9841
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()); + } } |