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

Commit 6061ddc2 authored by Bill Lin's avatar Bill Lin
Browse files

Check shortcut enabled before auto trun on OHM

When device (factory)boot, controller regsiter settings
'one_handed_mode_activated' will receive callback, and
the shortcut do not enabled by default, the flow will
go to auto enable one-handed mode feature and leading
unexpedted UX(disabled by default) and testing issue.

Solution:
- Add additional check for shortcut enabled when
  onActivatedActionChanged() callback.
- When setting is pull screen, notify shortcut
  one_handed_mode_activated to reset and align current
  mState when function enabled.

Note:
The setting provider one_handed_mode_activated could set
2 different values when shortcut button pressed
 - "0" mapping to pull screen STATE_NONE
 - "1" mapping to pull screen STATE_ACTIVE
Since show notification do not have state, whenever
onChange callback, we trigger expand notification.

Test: atest WMShellUnitTests
Test: manual factory reset | reboot check Log should show \
      "Shortcut not enabled, skip onActivatedActionChanged()".
Test: manual disable both OHM & shortcut toggle in settings \
      '# adb shell settings --user 0 put secure \
      one_handed_mode_activated 1'
      should not auto enable OHM main toggle.
Bug: 191736174
Bug: 191831415
Bug: 191950195
Fixes: 191812697
Change-Id: Ib9d66fbbcc7e6a52a37bb47efebf90c9d2644508
parent 3245ab13
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -498,6 +498,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController>

    @VisibleForTesting
    void onActivatedActionChanged() {
        if (!isShortcutEnabled()) {
            Slog.w(TAG, "Shortcut not enabled, skip onActivatedActionChanged()");
            return;
        }

        if (!isOneHandedEnabled()) {
            final boolean success = mOneHandedSettingsUtil.setOneHandedModeEnabled(
                    mContext.getContentResolver(), 1 /* Enabled for shortcut */, mUserId);
@@ -607,6 +612,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
        return mIsOneHandedEnabled;
    }

    @VisibleForTesting
    boolean isShortcutEnabled() {
        return mOneHandedSettingsUtil.getShortcutEnabled(mContext.getContentResolver(), mUserId);
    }

    @VisibleForTesting
    boolean isSwipeToNotificationEnabled() {
        return mIsSwipeToNotificationEnabled;
@@ -617,8 +627,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
            mMainExecutor.execute(() -> stopOneHanded());
        }

        // Reset and align shortcut one_handed_mode_activated status with current mState
        // If setting is pull screen, notify shortcut one_handed_mode_activated to reset
        // and align status with current mState when function enabled.
        if (isOneHandedEnabled() && !isSwipeToNotificationEnabled()) {
            notifyShortcutState(mState.getState());
        }

        mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);

@@ -717,6 +730,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
        pw.println(mLockedDisabled);
        pw.print(innerPrefix + "mUserId=");
        pw.println(mUserId);
        pw.print(innerPrefix + "isShortcutEnabled=");
        pw.println(isShortcutEnabled());

        if (mBackgroundPanelOrganizer != null) {
            mBackgroundPanelOrganizer.dump(pw);
+16 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.wm.shell.onehanded;

import static com.android.internal.accessibility.AccessibilityShortcutController.ONE_HANDED_COMPONENT_NAME;

import android.annotation.IntDef;
import android.content.ContentResolver;
import android.database.ContentObserver;
@@ -34,6 +36,9 @@ import java.lang.annotation.RetentionPolicy;
public final class OneHandedSettingsUtil {
    private static final String TAG = "OneHandedSettingsUtil";

    private static final String ONE_HANDED_MODE_TARGET_NAME =
            ONE_HANDED_COMPONENT_NAME.getShortClassName();

    @IntDef(prefix = {"ONE_HANDED_TIMEOUT_"}, value = {
            ONE_HANDED_TIMEOUT_NEVER,
            ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS,
@@ -157,6 +162,17 @@ public final class OneHandedSettingsUtil {
                Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0, userId);
    }

    /**
     * Queries one-handed mode shortcut enabled in settings or not.
     *
     * @return true if user enabled one-handed shortcut in settings, false otherwise.
     */
    public boolean getShortcutEnabled(ContentResolver resolver, int userId) {
        final String targets = Settings.Secure.getStringForUser(resolver,
                Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId);
        return targets != null ? targets.contains(ONE_HANDED_MODE_TARGET_NAME) : false;
    }

    /**
     * Sets tutorial shown counts.
     *
+38 −3
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
                mDefaultTapAppToExitEnabled);
        when(mMockSettingsUitl.getSettingsSwipeToNotificationEnabled(any(), anyInt())).thenReturn(
                mDefaultSwipeToNotificationEnabled);
        when(mMockSettingsUitl.getShortcutEnabled(any(), anyInt())).thenReturn(false);

        when(mMockDisplayAreaOrganizer.getLastDisplayBounds()).thenReturn(
                new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height()));
@@ -341,6 +342,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        when(mSpiedTransitionState.getState()).thenReturn(STATE_ACTIVE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        mSpiedOneHandedController.onActivatedActionChanged();

        verify(mSpiedOneHandedController, never()).startOneHanded();
@@ -352,6 +354,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(false);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        mSpiedOneHandedController.onActivatedActionChanged();

        verify(mSpiedOneHandedController, never()).startOneHanded();
@@ -363,6 +366,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        mSpiedOneHandedController.onActivatedActionChanged();

        verify(mSpiedOneHandedController).startOneHanded();
@@ -374,6 +378,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        when(mSpiedTransitionState.getState()).thenReturn(STATE_ENTERING);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(true);
        when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        mSpiedOneHandedController.onActivatedActionChanged();

        verify(mSpiedTransitionState, never()).setState(STATE_EXITING);
@@ -384,6 +389,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        when(mSpiedTransitionState.getState()).thenReturn(STATE_EXITING);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(true);
        when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        mSpiedOneHandedController.onActivatedActionChanged();

        verify(mSpiedTransitionState, never()).setState(STATE_ENTERING);
@@ -392,6 +398,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
    @Test
    public void testOneHandedDisabled_shortcutTrigger_thenAutoEnabled() {
        when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(false);
@@ -417,6 +424,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(true);
        when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(true);
        mSpiedOneHandedController.registerEventCallback(mMockEventCallback);
        mSpiedOneHandedController.onActivatedActionChanged();
@@ -425,11 +433,11 @@ public class OneHandedControllerTest extends OneHandedTestCase {
    }

    @Test
    public void testNotifyShortcutState_whenUpdateOneHandedEnabled() {
        when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false);
    public void testNotifyShortcutState_whenSetOneHandedEnabled() {
        when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(true);
        when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(true);
        when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(false);
        mSpiedOneHandedController.registerEventCallback(mMockEventCallback);
        mSpiedOneHandedController.setOneHandedEnabled(true);

@@ -448,4 +456,31 @@ public class OneHandedControllerTest extends OneHandedTestCase {
        // Verify no NPE crash and mMockShellMainExecutor never be execute.
        verify(mMockShellMainExecutor, never()).execute(any());
    }

    @Test
    public void testShortcutEnable_ableToAutoEnableOneHandedMode() {
        when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false);
        when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mSpiedOneHandedController.isShortcutEnabled()).thenReturn(true);
        when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(false);
        when(mMockSettingsUitl.setOneHandedModeEnabled(any(), anyInt(), anyInt())).thenReturn(
                false /* To avoid test runner create Toast */);
        mSpiedOneHandedController.onActivatedActionChanged();

        verify(mSpiedOneHandedController).notifyUserConfigChanged(anyBoolean());
    }

    @Test
    public void testShortcutDisable_shouldNotAutoEnableOneHandedMode() {
        when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false);
        when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
        when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
        when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(false);
        when(mMockSettingsUitl.setOneHandedModeEnabled(any(), anyInt(), anyInt())).thenReturn(true);
        mSpiedOneHandedController.onActivatedActionChanged();

        verify(mMockSettingsUitl, never()).setOneHandedModeEnabled(any(), anyInt(), anyInt());
        verify(mSpiedOneHandedController, never()).notifyUserConfigChanged(anyBoolean());
    }
}