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

Commit 606b2a16 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Read default stem press behavior from xml" into main

parents b0215934 237c3701
Loading
Loading
Loading
Loading
+11 −2
Original line number Original line Diff line number Diff line
@@ -1696,10 +1696,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return mLongPressOnStemPrimaryBehavior != LONG_PRESS_PRIMARY_NOTHING;
        return mLongPressOnStemPrimaryBehavior != LONG_PRESS_PRIMARY_NOTHING;
    }
    }


    /** Determine whether the device has any stem primary behaviors. */
    private boolean hasStemPrimaryBehavior() {
    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
        return getMaxMultiPressStemPrimaryCount() > 1
                || hasLongPressOnStemPrimaryBehavior()
                || defaultLongPressOnStemPrimaryBehavior != LONG_PRESS_PRIMARY_NOTHING
                || mShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING;
                || defaultShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING;
    }
    }


    private void interceptScreenshotChord(int source, long pressDelay) {
    private void interceptScreenshotChord(int source, long pressDelay) {
+39 −5
Original line number Original line 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.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER;
import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER;


import static org.mockito.ArgumentMatchers.eq;

import static java.util.Collections.unmodifiableMap;
import static java.util.Collections.unmodifiableMap;


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


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


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


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


    /** Modifier key to meta state */
    /** Modifier key to meta state */
    protected static final Map<Integer, Integer> MODIFIER;
    protected static final Map<Integer, Integer> MODIFIER;
@@ -90,6 +95,16 @@ class ShortcutKeyTestBase {
        MODIFIER = unmodifiableMap(map);
        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. */
    /** Same as {@link setUpPhoneWindowManager(boolean)}, without supporting settings update. */
    protected final void setUpPhoneWindowManager() {
    protected final void setUpPhoneWindowManager() {
        setUpPhoneWindowManager(/* supportSettingsUpdate= */ false);
        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
     * <p>Subclasses must call this at the start of the test if they intend to interact with phone
     * window manager.
     * window manager.
     *
     *
     * @param supportSettingsUpdate {@code true} if this test should read and listen to provider
     * @param supportSettingsUpdate {@code true} to have PWM respond to any Settings changes upon
     *      settings values.
     *    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) {
    protected final void setUpPhoneWindowManager(boolean supportSettingsUpdate) {
        doReturn(mSettingsProviderRule.mockContentResolver(mContext))
                .when(mContext).getContentResolver();
        mPhoneWindowManager = new TestPhoneWindowManager(mContext, supportSettingsUpdate);
        mPhoneWindowManager = new TestPhoneWindowManager(mContext, supportSettingsUpdate);
    }
    }


@@ -187,6 +204,23 @@ class ShortcutKeyTestBase {
        sendKeyCombination(new int[]{keyCode}, 0 /*durationMillis*/, longPress, DEFAULT_DISPLAY);
        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) {
    private void interceptKey(KeyEvent keyEvent) {
        int actions = mPhoneWindowManager.interceptKeyBeforeQueueing(keyEvent);
        int actions = mPhoneWindowManager.interceptKeyBeforeQueueing(keyEvent);
        if ((actions & ACTION_PASS_TO_USER) != 0) {
        if ((actions & ACTION_PASS_TO_USER) != 0) {
+95 −0
Original line number Original line Diff line number Diff line
@@ -291,6 +291,101 @@ public class StemKeyGestureTests extends ShortcutKeyTestBase {
        mPhoneWindowManager.assertSwitchToTask(referenceId);
        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) {
    private void overrideBehavior(String key, int expectedBehavior) {
        Settings.Global.putLong(mContext.getContentResolver(), key, expectedBehavior);
        Settings.Global.putLong(mContext.getContentResolver(), key, expectedBehavior);
    }
    }
+15 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
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) {
    TestPhoneWindowManager(Context context, boolean supportSettingsUpdate) {
        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
        mHandler = new Handler(mTestLooper.getLooper());
        mHandler = new Handler(mTestLooper.getLooper());
@@ -416,6 +424,13 @@ class TestPhoneWindowManager {
        mPhoneWindowManager.dispatchUnhandledKey(mInputToken, event, FLAG_INTERACTIVE);
        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() {
    long getCurrentTime() {
        return mClock.now();
        return mClock.now();
    }
    }