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

Commit 237c3701 authored by Zach Lee's avatar Zach Lee Committed by Zachary Lee
Browse files

Read default stem press behavior from xml

Test: manual
Test: atest WmTests:StemKeyGestureTests
Bug: b/309859099
Change-Id: Ib7dbf5430d5bb5d1369d9a2f33570945ae86bf70
parent 459ed769
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -1696,10 +1696,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return mLongPressOnStemPrimaryBehavior != LONG_PRESS_PRIMARY_NOTHING;
    }

    /** Determine whether the device has any stem primary behaviors. */
    private boolean hasStemPrimaryBehavior() {
        // Read the default stem behaviors from the XML config to determine whether stem primary
        // behaviors are supported in this build. If they are supported, then the behaviors may be
        // overridden at runtime through their respective Settings overrides. If they are not
        // supported, the Settings overrides will not apply.
        final int defaultShortPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior);
        final int defaultLongPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_longPressOnStemPrimaryBehavior);
        return getMaxMultiPressStemPrimaryCount() > 1
                || hasLongPressOnStemPrimaryBehavior()
                || mShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING;
                || defaultLongPressOnStemPrimaryBehavior != LONG_PRESS_PRIMARY_NOTHING
                || defaultShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING;
    }

    private void interceptScreenshotChord(int source, long pressDelay) {
+39 −5
Original line number Diff line number Diff line
@@ -43,9 +43,12 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER;

import static org.mockito.ArgumentMatchers.eq;

import static java.util.Collections.unmodifiableMap;

import android.content.Context;
import android.content.res.Resources;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArrayMap;
import android.view.InputDevice;
@@ -57,6 +60,7 @@ import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.RuleChain;

@@ -70,9 +74,10 @@ class ShortcutKeyTestBase {
    @Rule
    public RuleChain rules = RuleChain.outerRule(mSettingsProviderRule).around(mSetFlagsRule);

    private Resources mResources;
    TestPhoneWindowManager mPhoneWindowManager;
    DispatchedKeyHandler mDispatchedKeyHandler = event -> false;
    final Context mContext = spy(getInstrumentation().getTargetContext());
    Context mContext;

    /** Modifier key to meta state */
    protected static final Map<Integer, Integer> MODIFIER;
@@ -90,6 +95,16 @@ class ShortcutKeyTestBase {
        MODIFIER = unmodifiableMap(map);
    }

    @Before
    public void setup() {
        mContext = spy(getInstrumentation().getTargetContext());
        mResources = spy(mContext.getResources());
        doReturn(mResources).when(mContext).getResources();
        doReturn(mSettingsProviderRule.mockContentResolver(mContext))
                .when(mContext).getContentResolver();
    }


    /** Same as {@link setUpPhoneWindowManager(boolean)}, without supporting settings update. */
    protected final void setUpPhoneWindowManager() {
        setUpPhoneWindowManager(/* supportSettingsUpdate= */ false);
@@ -101,12 +116,14 @@ class ShortcutKeyTestBase {
     * <p>Subclasses must call this at the start of the test if they intend to interact with phone
     * window manager.
     *
     * @param supportSettingsUpdate {@code true} if this test should read and listen to provider
     *      settings values.
     * @param supportSettingsUpdate {@code true} to have PWM respond to any Settings changes upon
     *    instantiation. Although this is supposed to also allow a test to listen to any Settings
     *    changes after instantiation, MockContentResolver in this class's setup stubs out
     *    notifyChange(), which prevents SettingsObserver from getting notified of events. So
     *    we're effectively always instantiating TestPhoneWindowManager with
     *    supportSettingsUpdate=false.
     */
    protected final void setUpPhoneWindowManager(boolean supportSettingsUpdate) {
        doReturn(mSettingsProviderRule.mockContentResolver(mContext))
                .when(mContext).getContentResolver();
        mPhoneWindowManager = new TestPhoneWindowManager(mContext, supportSettingsUpdate);
    }

@@ -187,6 +204,23 @@ class ShortcutKeyTestBase {
        sendKeyCombination(new int[]{keyCode}, 0 /*durationMillis*/, longPress, DEFAULT_DISPLAY);
    }

    /**
     * Since we use SettingsProviderRule to mock the ContentResolver in these
     * tests, the settings observer registered by PhoneWindowManager will not
     * be triggered automatically by the mock. Use this method to force the
     * settings observer change after modifying any settings.
     */
    void triggerSettingsObserverChange() {
        mPhoneWindowManager.getSettingsObserver().onChange(
                // This boolean doesn't matter. This observer does the same thing regardless.
                /*selfChange=*/true);
    }

    /** Override a resource's return value. */
    void overrideResource(int resId, int expectedBehavior) {
        doReturn(expectedBehavior).when(mResources).getInteger(eq(resId));
    }

    private void interceptKey(KeyEvent keyEvent) {
        int actions = mPhoneWindowManager.interceptKeyBeforeQueueing(keyEvent);
        if ((actions & ACTION_PASS_TO_USER) != 0) {
+95 −0
Original line number Diff line number Diff line
@@ -291,6 +291,101 @@ public class StemKeyGestureTests extends ShortcutKeyTestBase {
        mPhoneWindowManager.assertSwitchToTask(referenceId);
    }

    /**
     * Ensure the stem rule is added even when button behaviors are set to nothing.
     *
     * This makes sure that if stem key behaviors are overridden to NOTHING, then we check the
     * XML config as the source of truth upon reboot to see whether a device should have a stem
     * key rule. This test walks us through a scenario where a device powers off during Wear's
     * Touch Lock mode.
     */
    @Test
    public void stemKeyRuleIsAddedEvenWhenBehaviorsRemoved() {
        // deactivate stem button presses
        overrideBehavior(STEM_PRIMARY_BUTTON_SHORT_PRESS,
                PhoneWindowManager.SHORT_PRESS_PRIMARY_NOTHING);
        overrideBehavior(STEM_PRIMARY_BUTTON_DOUBLE_PRESS,
                PhoneWindowManager.DOUBLE_PRESS_PRIMARY_NOTHING);
        overrideBehavior(STEM_PRIMARY_BUTTON_TRIPLE_PRESS,
                PhoneWindowManager.TRIPLE_PRESS_PRIMARY_NOTHING);
        overrideBehavior(STEM_PRIMARY_BUTTON_LONG_PRESS,
                PhoneWindowManager.LONG_PRESS_PRIMARY_NOTHING);

        // pretend like we have stem keys enabled in the xmls
        overrideResource(
                com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior,
                SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS);

        // start the PhoneWindowManager, just like would happen with a reboot
        setUpPhoneWindowManager(/* supportSettingsUpdate= */ true);
        // Set the stem behavior back to something normal after boot
        overrideBehavior(STEM_PRIMARY_BUTTON_SHORT_PRESS,
                SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS);
        // manually trigger the SettingsObserver's onChange() method because subclasses of
        // ShortcutKeyTestBase cannot automatically pick up Settings changes.
        triggerSettingsObserverChange();

        // These calls are required to make the All Apps view show up
        mPhoneWindowManager.overrideShouldEarlyShortPressOnStemPrimary(false);
        mPhoneWindowManager.overrideStartActivity();
        mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false);
        mPhoneWindowManager.overrideIsUserSetupComplete(true);

        sendKey(KEYCODE_STEM_PRIMARY);

        // Because the rule was loaded and we changed the behavior back to non-zero, PWM should
        // actually perform this action. It would not perform the action if the rule was missing.
        mPhoneWindowManager.assertOpenAllAppView();
    }

    /**
     * Ensure the stem rule is not added when stem behavior is not defined in the xml.
     *
     * This is the opposite of the test above.
     */
    @Test
    public void stemKeyRuleIsNotAddedWhenXmlDoesntDefineIt() {
        // deactivate stem button presses
        overrideBehavior(STEM_PRIMARY_BUTTON_SHORT_PRESS,
                PhoneWindowManager.SHORT_PRESS_PRIMARY_NOTHING);
        overrideBehavior(STEM_PRIMARY_BUTTON_DOUBLE_PRESS,
                PhoneWindowManager.DOUBLE_PRESS_PRIMARY_NOTHING);
        overrideBehavior(STEM_PRIMARY_BUTTON_TRIPLE_PRESS,
                PhoneWindowManager.TRIPLE_PRESS_PRIMARY_NOTHING);
        overrideBehavior(STEM_PRIMARY_BUTTON_LONG_PRESS,
                PhoneWindowManager.LONG_PRESS_PRIMARY_NOTHING);

        // pretend like we do not have stem keys enabled in the xmls
        overrideResource(
                com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior,
                PhoneWindowManager.SHORT_PRESS_PRIMARY_NOTHING);
        overrideResource(
                com.android.internal.R.integer.config_longPressOnStemPrimaryBehavior,
                PhoneWindowManager.LONG_PRESS_PRIMARY_NOTHING);

        // start the PhoneWindowManager, just like would happen with a reboot
        setUpPhoneWindowManager(/* supportSettingsUpdate= */ true);
        // Set the stem behavior back to something normal after boot
        // (Despite this fact, a stem press shouldn't have any behavior because there's no rule.)
        overrideBehavior(STEM_PRIMARY_BUTTON_SHORT_PRESS,
                SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS);
        // manually trigger the SettingsObserver's onChange() method because subclasses of
        // ShortcutKeyTestBase cannot automatically pick up Settings changes.
        triggerSettingsObserverChange();

        // These calls are required to make the All Apps view show up
        mPhoneWindowManager.overrideShouldEarlyShortPressOnStemPrimary(false);
        mPhoneWindowManager.overrideStartActivity();
        mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false);
        mPhoneWindowManager.overrideIsUserSetupComplete(true);

        sendKey(KEYCODE_STEM_PRIMARY);

        // Because the rule was not loaded, PWM should not actually perform this action, even
        // though the Settings override is set to non-null.
        mPhoneWindowManager.assertNotOpenAllAppView();
    }

    private void overrideBehavior(String key, int expectedBehavior) {
        Settings.Global.putLong(mContext.getContentResolver(), key, expectedBehavior);
    }
+15 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
@@ -246,6 +247,13 @@ class TestPhoneWindowManager {
        }
    }

    /**
     * {@link TestPhoneWindowManager}'s constructor.
     *
     * @param context The {@Context} to be used in any Context-related actions.
     * @param supportSettingsUpdate {@code true} if this object should read and listen to provider
     *      settings values.
     */
    TestPhoneWindowManager(Context context, boolean supportSettingsUpdate) {
        MockitoAnnotations.initMocks(this);
        mHandler = new Handler(mTestLooper.getLooper());
@@ -416,6 +424,13 @@ class TestPhoneWindowManager {
        mPhoneWindowManager.dispatchUnhandledKey(mInputToken, event, FLAG_INTERACTIVE);
    }

    /**
     * Provide access to the SettingsObserver so that tests can manually trigger Settings changes.
     */
    ContentObserver getSettingsObserver() {
        return mPhoneWindowManager.mSettingsObserver;
    }

    long getCurrentTime() {
        return mClock.now();
    }