Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 358af232 authored by Chen Bai's avatar Chen Bai
Browse files

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
parent eac0de97
Loading
Loading
Loading
Loading
+26 −9
Original line number Diff line number Diff line
@@ -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,11 +2775,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {

        @Override
        void onKeyUp(long eventTime, int count) {
            if (mShouldEarlyShortPressOnStemPrimary && count == 1) {
            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*/);
                }
            }
        }
    }

    private void initSingleKeyGestureRules(Looper looper) {
        mSingleKeyGestureDetector = SingleKeyGestureDetector.get(mContext, looper);
+44 −0
Original line number Diff line number Diff line
@@ -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);
+18 −1
Original line number Diff line number Diff line
@@ -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());
    }
}