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

Commit 1736e28e authored by Roy Chou's avatar Roy Chou
Browse files

chore(#Magnification): use persisted scale if zoom-in-temporary when magnifier...

chore(#Magnification): use persisted scale if zoom-in-temporary when magnifier is zoomed out by service

Originally when the fullscreen magnifier is activated, using triple-tap-and-hold to temporarily zoom in would use (current scale + 1) as the furthur zoom in scale.

We add two cases that would zoom in with persisted scale.
1. User just tap the shortcut to activate the magnifier.
2. The magnifier just zooms out due to user context changed such as transitions or rotations.

For these two cases we conclude the expected bahaviour should be zooming in with persisted scale.

Bug: 289131167
Test: manually
      atest FullScreenMagnificationControllerTest
      atest FullScreenMagnificationGestureHandlerTest
Change-Id: I0a48e1465763c5387bbac537471de82efff7caf5
parent 84c898de
Loading
Loading
Loading
Loading
+54 −3
Original line number Diff line number Diff line
@@ -142,6 +142,8 @@ public class FullScreenMagnificationController implements
        private int mIdOfLastServiceToMagnify = INVALID_SERVICE_ID;
        private boolean mMagnificationActivated = false;

        private boolean mZoomedOutFromService = false;

        @GuardedBy("mLock") @Nullable private MagnificationThumbnail mMagnificationThumbnail;

        DisplayMagnification(int displayId) {
@@ -545,6 +547,24 @@ public class FullScreenMagnificationController implements
            return changed;
        }

        /**
         * Directly Zooms out the scale to 1f with animating the transition. This method is
         * triggered only by service automatically, such as when user context changed.
         */
        void zoomOutFromService() {
            setScaleAndCenter(1.0f, Float.NaN, Float.NaN,
                    transformToStubCallback(true),
                    AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
            mZoomedOutFromService = true;
        }

        /**
         * Whether the zooming out is triggered by {@link #zoomOutFromService}.
         */
        boolean isZoomedOutFromService() {
            return mZoomedOutFromService;
        }

        @GuardedBy("mLock")
        boolean reset(boolean animate) {
            return reset(transformToStubCallback(animate));
@@ -619,6 +639,8 @@ public class FullScreenMagnificationController implements
                            mIdOfLastServiceToMagnify);
                });
            }
            // the zoom scale would be changed so we reset the flag
            mZoomedOutFromService = false;
            return changed;
        }

@@ -944,9 +966,7 @@ public class FullScreenMagnificationController implements
            }

            if (isAlwaysOnMagnificationEnabled()) {
                setScaleAndCenter(displayId, 1.0f, Float.NaN, Float.NaN,
                        true,
                        AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
                zoomOutFromService(displayId);
            } else {
                reset(displayId, true);
            }
@@ -1427,6 +1447,37 @@ public class FullScreenMagnificationController implements
                MagnificationScaleProvider.MAX_SCALE);
    }

    /**
     * Directly Zooms out the scale to 1f with animating the transition. This method is
     * triggered only by service automatically, such as when user context changed.
     *
     * @param displayId The logical display id.
     */
    private void zoomOutFromService(int displayId) {
        synchronized (mLock) {
            final DisplayMagnification display = mDisplays.get(displayId);
            if (display == null || !display.isActivated()) {
                return;
            }
            display.zoomOutFromService();
        }
    }

    /**
     * Whether the magnification is zoomed out by {@link #zoomOutFromService(int)}.
     *
     * @param displayId The logical display id.
     */
    public boolean isZoomedOutFromService(int displayId) {
        synchronized (mLock) {
            final DisplayMagnification display = mDisplays.get(displayId);
            if (display == null || !display.isActivated()) {
                return false;
            }
            return display.isZoomedOutFromService();
        }
    }

    /**
     * Resets all displays' magnification if last magnifying service is disabled.
     *
+9 −3
Original line number Diff line number Diff line
@@ -1093,7 +1093,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH

            mViewportDraggingState.prepareForZoomInTemporary(shortcutTriggered);

            zoomInTemporary(down.getX(), down.getY());
            zoomInTemporary(down.getX(), down.getY(), shortcutTriggered);

            transitionTo(mViewportDraggingState);
        }
@@ -1150,14 +1150,20 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
        }
    }

    private void zoomInTemporary(float centerX, float centerY) {
    private void zoomInTemporary(float centerX, float centerY, boolean shortcutTriggered) {
        final float currentScale = mFullScreenMagnificationController.getScale(mDisplayId);
        final float persistedScale = MathUtils.constrain(
                mFullScreenMagnificationController.getPersistedScale(mDisplayId),
                MIN_SCALE, MAX_SCALE);

        final boolean isActivated = mFullScreenMagnificationController.isActivated(mDisplayId);
        final float scale = isActivated ? (currentScale + 1.0f) : persistedScale;
        final boolean isShortcutTriggered = shortcutTriggered;
        final boolean isZoomedOutFromService =
                mFullScreenMagnificationController.isZoomedOutFromService(mDisplayId);

        boolean zoomInWithPersistedScale =
                !isActivated || isShortcutTriggered || isZoomedOutFromService;
        final float scale = zoomInWithPersistedScale ?  persistedScale : (currentScale + 1.0f);
        zoomToScale(scale, centerX, centerY);
    }

+15 −0
Original line number Diff line number Diff line
@@ -130,6 +130,8 @@ public class FullScreenMagnificationControllerTest {

    public DisplayManagerInternal mDisplayManagerInternalMock = mock(DisplayManagerInternal.class);

    private float mOriginalMagnificationPersistedScale;

    @Before
    public void setUp() {
        Looper looper = InstrumentationRegistry.getContext().getMainLooper();
@@ -143,6 +145,9 @@ public class FullScreenMagnificationControllerTest {
        mResolver = new MockContentResolver();
        mResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
        when(mMockContext.getContentResolver()).thenReturn(mResolver);
        mOriginalMagnificationPersistedScale = Settings.Secure.getFloatForUser(mResolver,
                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.0f,
                CURRENT_USER_ID);
        Settings.Secure.putFloatForUser(mResolver,
                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.0f,
                CURRENT_USER_ID);
@@ -169,6 +174,10 @@ public class FullScreenMagnificationControllerTest {
    @After
    public void tearDown() {
        mMessageCapturingHandler.removeAllMessages();
        Settings.Secure.putFloatForUser(mResolver,
                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
                mOriginalMagnificationPersistedScale,
                CURRENT_USER_ID);
    }


@@ -1311,7 +1320,10 @@ public class FullScreenMagnificationControllerTest {
        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(false);
        mFullScreenMagnificationController.onUserContextChanged(DISPLAY_0);

        // the magnifier should be deactivated.
        verify(mRequestObserver).onFullScreenMagnificationActivationState(eq(DISPLAY_0), eq(false));
        assertFalse(mFullScreenMagnificationController.isZoomedOutFromService(DISPLAY_0));

        verify(mMockThumbnail).setThumbnailBounds(
                /* currentBounds= */ any(),
                /* scale= */ anyFloat(),
@@ -1330,8 +1342,11 @@ public class FullScreenMagnificationControllerTest {
        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(true);
        mFullScreenMagnificationController.onUserContextChanged(DISPLAY_0);

        // the magnifier should be zoomed out and keep activated by service action.
        assertEquals(1.0f, mFullScreenMagnificationController.getScale(DISPLAY_0), 0);
        assertTrue(mFullScreenMagnificationController.isActivated(DISPLAY_0));
        assertTrue(mFullScreenMagnificationController.isZoomedOutFromService(DISPLAY_0));

        verify(mMockThumbnail).setThumbnailBounds(
                /* currentBounds= */ any(),
                /* scale= */ anyFloat(),
+153 −102
Original line number Diff line number Diff line
@@ -96,19 +96,29 @@ import java.util.function.IntConsumer;
 *          NON_ACTIVATED_ZOOMED_TMP -> IDLE [label="release"]
 *          SHORTCUT_TRIGGERED -> IDLE [label="a11y\nbtn"]
 *          SHORTCUT_TRIGGERED -> ACTIVATED [label="tap"]
 *          SHORTCUT_TRIGGERED -> SHORTCUT_TRIGGERED_ZOOMED_TMP [label="hold"]
 *          SHORTCUT_TRIGGERED -> PANNING [label="2hold]
 *          SHORTCUT_TRIGGERED -> ZOOMED_WITH_PERSISTED_SCALE_TMP [label="hold"]
 *          SHORTCUT_TRIGGERED -> PANNING [label="2hold"]
 *          ZOOMED_OUT_FROM_SERVICE -> IDLE [label="a11y\nbtn"]
 *          ZOOMED_OUT_FROM_SERVICE -> ZOOMED_OUT_FROM_SERVICE_DOUBLE_TAP [label="2tap"]
 *          ZOOMED_OUT_FROM_SERVICE -> PANNING [label="2hold"]
 *          ZOOMED_OUT_FROM_SERVICE_DOUBLE_TAP -> IDLE [label="tap"]
 *          ZOOMED_OUT_FROM_SERVICE_DOUBLE_TAP -> ZOOMED_OUT_FROM_SERVICE [label="timeout"]
 *          ZOOMED_OUT_FROM_SERVICE_DOUBLE_TAP -> ZOOMED_WITH_PERSISTED_SCALE_TMP [label="hold"]
 *          if always-on enabled:
 *              SHORTCUT_TRIGGERED_ZOOMED_TMP -> ACTIVATED [label="release"]
 *              ZOOMED_WITH_PERSISTED_SCALE_TMP -> ACTIVATED [label="release"]
 *          else:
 *              SHORTCUT_TRIGGERED_ZOOMED_TMP -> IDLE [label="release"]
 *              ZOOMED_WITH_PERSISTED_SCALE_TMP -> IDLE [label="release"]
 *          ACTIVATED -> ACTIVATED_DOUBLE_TAP [label="2tap"]
 *          ACTIVATED -> IDLE [label="a11y\nbtn"]
 *          ACTIVATED -> PANNING [label="2hold"]
 *          if always-on enabled:
 *              ACTIVATED -> ZOOMED_OUT_FROM_SERVICE [label="contextChanged"]
 *          else:
 *              ACTIVATED -> IDLE [label="contextChanged"]
 *          ACTIVATED_DOUBLE_TAP -> ACTIVATED [label="timeout"]
 *          ACTIVATED_DOUBLE_TAP -> ACTIVATED_ZOOMED_TMP [label="hold"]
 *          ACTIVATED_DOUBLE_TAP -> ZOOMED_FURTHER_TMP [label="hold"]
 *          ACTIVATED_DOUBLE_TAP -> IDLE [label="tap"]
 *          ACTIVATED_ZOOMED_TMP -> ACTIVATED [label="release"]
 *          ZOOMED_FURTHER_TMP -> ACTIVATED [label="release"]
 *          PANNING -> ACTIVATED [label="release"]
 *          PANNING -> PANNING_SCALING [label="pinch"]
 *          PANNING_SCALING -> ACTIVATED [label="release"]
@@ -120,15 +130,20 @@ public class FullScreenMagnificationGestureHandlerTest {

    public static final int STATE_IDLE = 1;
    public static final int STATE_ACTIVATED = 2;
    public static final int STATE_2TAPS = 3;
    public static final int STATE_ACTIVATED_2TAPS = 4;
    public static final int STATE_SHORTCUT_TRIGGERED = 5;
    public static final int STATE_NON_ACTIVATED_ZOOMED_TMP = 6;
    public static final int STATE_ACTIVATED_ZOOMED_TMP = 7;
    public static final int STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP = 8;
    public static final int STATE_PANNING = 9;
    public static final int STATE_SCALING_AND_PANNING = 10;
    public static final int STATE_SINGLE_PANNING = 11;
    public static final int STATE_SHORTCUT_TRIGGERED = 3;
    public static final int STATE_ZOOMED_OUT_FROM_SERVICE = 4;

    public static final int STATE_2TAPS = 5;
    public static final int STATE_ACTIVATED_2TAPS = 6;
    public static final int STATE_ZOOMED_OUT_FROM_SERVICE_2TAPS = 7;

    public static final int STATE_NON_ACTIVATED_ZOOMED_TMP = 8;
    public static final int STATE_ZOOMED_FURTHER_TMP = 9;
    public static final int STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP = 10;

    public static final int STATE_PANNING = 11;
    public static final int STATE_SCALING_AND_PANNING = 12;
    public static final int STATE_SINGLE_PANNING = 13;

    public static final int FIRST_STATE = STATE_IDLE;
    public static final int LAST_STATE = STATE_SINGLE_PANNING;
@@ -313,7 +328,7 @@ public class FullScreenMagnificationGestureHandlerTest {
        assertTransition(STATE_SHORTCUT_TRIGGERED, () -> {
            send(downEvent());
            fastForward1sec();
        }, STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
        }, STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP);

        // A11y button followed by a tap turns magnifier on
        assertTransition(STATE_SHORTCUT_TRIGGERED, () -> tap(), STATE_ACTIVATED);
@@ -337,22 +352,22 @@ public class FullScreenMagnificationGestureHandlerTest {
        assertTransition(STATE_2TAPS, () -> swipeAndHold(), STATE_NON_ACTIVATED_ZOOMED_TMP);

        // release when activated temporary zoom in back to activated
        assertTransition(STATE_ACTIVATED_ZOOMED_TMP, () -> send(upEvent()), STATE_ACTIVATED);
        assertTransition(STATE_ZOOMED_FURTHER_TMP, () -> send(upEvent()), STATE_ACTIVATED);
    }

    @Test
    public void testRelease_shortcutTriggeredZoomedTmp_alwaysOnNotEnabled_shouldInIdle() {
    public void testRelease_zoomedWithPersistedScaleTmpAndAlwaysOnNotEnabled_shouldInIdle() {
        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(false);
        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
        goFromStateIdleTo(STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP);
        send(upEvent());

        assertIn(STATE_IDLE);
    }

    @Test
    public void testRelease_shortcutTriggeredZoomedTmp_alwaysOnEnabled_shouldInActivated() {
    public void testRelease_zoomedWithPersistedScaleTmpAndAlwaysOnEnabled_shouldInActivated() {
        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(true);
        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
        goFromStateIdleTo(STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP);
        send(upEvent());

        assertIn(STATE_ACTIVATED);
@@ -404,9 +419,11 @@ public class FullScreenMagnificationGestureHandlerTest {
    @Test
    public void testTripleTapAndHold_zoomsImmediately() {
        assertZoomsImmediatelyOnSwipeFrom(STATE_2TAPS, STATE_NON_ACTIVATED_ZOOMED_TMP);
        assertZoomsImmediatelyOnSwipeFrom(STATE_ACTIVATED_2TAPS, STATE_ZOOMED_FURTHER_TMP);
        assertZoomsImmediatelyOnSwipeFrom(STATE_SHORTCUT_TRIGGERED,
                STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
        assertZoomsImmediatelyOnSwipeFrom(STATE_ACTIVATED_2TAPS, STATE_ACTIVATED_ZOOMED_TMP);
                STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP);
        assertZoomsImmediatelyOnSwipeFrom(STATE_ZOOMED_OUT_FROM_SERVICE_2TAPS,
                STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP);
    }

    @Test
@@ -755,6 +772,10 @@ public class FullScreenMagnificationGestureHandlerTest {
        mHandler.timeAdvance();
    }

    private void triggerContextChanged() {
        mFullScreenMagnificationController.onUserContextChanged(DISPLAY_0);
    }

    /**
     * Asserts that {@link #mMgh the handler} is in the given {@code state}
     */
@@ -763,43 +784,63 @@ public class FullScreenMagnificationGestureHandlerTest {

            // Asserts on separate lines for accurate stack traces

            case STATE_IDLE: {
            case STATE_IDLE:
                check(tapCount() < 2, state);
                check(!mMgh.mDetectingState.mShortcutTriggered, state);
                check(!isActivated(), state);
                check(!isZoomed(), state);
            } break;
            case STATE_ACTIVATED: {
                break;
            case STATE_ACTIVATED:
                check(isActivated(), state);
                check(tapCount() < 2, state);
            } break;
            case STATE_2TAPS: {
                break;
            case STATE_SHORTCUT_TRIGGERED:
                check(mMgh.mDetectingState.mShortcutTriggered, state);
                check(isActivated(), state);
                check(!isZoomed(), state);
                break;
            case STATE_ZOOMED_OUT_FROM_SERVICE:
                // the always-on feature must be enabled then this state is reachable.
                assertTrue(mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled());
                check(isActivated(), state);
                check(!isZoomed(), state);
                check(mMgh.mFullScreenMagnificationController.isZoomedOutFromService(DISPLAY_0),
                        state);
                break;
            case STATE_2TAPS:
                check(!isActivated(), state);
                check(!isZoomed(), state);
                check(tapCount() == 2, state);
            } break;
            case STATE_ACTIVATED_2TAPS: {
                break;
            case STATE_ACTIVATED_2TAPS:
                check(isActivated(), state);
                check(isZoomed(), state);
                check(tapCount() == 2, state);
            } break;
            case STATE_NON_ACTIVATED_ZOOMED_TMP: {
                break;
            case STATE_ZOOMED_OUT_FROM_SERVICE_2TAPS:
                check(isActivated(), state);
                check(!isZoomed(), state);
                check(mMgh.mFullScreenMagnificationController.isZoomedOutFromService(DISPLAY_0),
                        state);
                check(tapCount() == 2, state);
                break;
            case STATE_NON_ACTIVATED_ZOOMED_TMP:
                check(isActivated(), state);
                check(isZoomed(), state);
                check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
                        state);
                check(Float.isNaN(mMgh.mViewportDraggingState.mScaleToRecoverAfterDraggingEnd),
                        state);
            } break;
            case STATE_ACTIVATED_ZOOMED_TMP: {
                break;
            case STATE_ZOOMED_FURTHER_TMP:
                check(isActivated(), state);
                check(isZoomed(), state);
                check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
                        state);
                check(mMgh.mViewportDraggingState.mScaleToRecoverAfterDraggingEnd >= 1.0f,
                        state);
            } break;
            case STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP: {
                break;
            case STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP:
                check(isActivated(), state);
                check(isZoomed(), state);
                check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
@@ -811,29 +852,25 @@ public class FullScreenMagnificationGestureHandlerTest {
                    check(Float.isNaN(mMgh.mViewportDraggingState.mScaleToRecoverAfterDraggingEnd),
                            state);
                }
            } break;
            case STATE_SHORTCUT_TRIGGERED: {
                check(mMgh.mDetectingState.mShortcutTriggered, state);
                check(isActivated(), state);
                check(!isZoomed(), state);
            } break;
            case STATE_PANNING: {
                break;
            case STATE_PANNING:
                check(isActivated(), state);
                check(mMgh.mCurrentState == mMgh.mPanningScalingState,
                        state);
                check(!mMgh.mPanningScalingState.mScaling, state);
            } break;
            case STATE_SCALING_AND_PANNING: {
                break;
            case STATE_SCALING_AND_PANNING:
                check(isActivated(), state);
                check(mMgh.mCurrentState == mMgh.mPanningScalingState,
                        state);
                check(mMgh.mPanningScalingState.mScaling, state);
            } break;
            case STATE_SINGLE_PANNING: {
                break;
            case STATE_SINGLE_PANNING:
                check(isZoomed(), state);
                check(mMgh.mCurrentState == mMgh.mSinglePanningState, state);
            } break;
            default: throw new IllegalArgumentException("Illegal state: " + state);
                break;
            default:
                throw new IllegalArgumentException("Illegal state: " + state);
        }
    }

@@ -843,15 +880,10 @@ public class FullScreenMagnificationGestureHandlerTest {
    private void goFromStateIdleTo(int state) {
        try {
            switch (state) {
                case STATE_IDLE: {
                case STATE_IDLE:
                    mMgh.clearAndTransitionToStateDetecting();
                } break;
                case STATE_2TAPS: {
                    goFromStateIdleTo(STATE_IDLE);
                    tap();
                    tap();
                } break;
                case STATE_ACTIVATED: {
                    break;
                case STATE_ACTIVATED:
                    if (mMgh.mDetectTripleTap) {
                        goFromStateIdleTo(STATE_2TAPS);
                        tap();
@@ -859,47 +891,63 @@ public class FullScreenMagnificationGestureHandlerTest {
                        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
                        tap();
                    }
                } break;
                case STATE_ACTIVATED_2TAPS: {
                    break;
                case STATE_SHORTCUT_TRIGGERED:
                    goFromStateIdleTo(STATE_IDLE);
                    triggerShortcut();
                    break;
                case STATE_ZOOMED_OUT_FROM_SERVICE:
                    // the always-on feature must be enabled then this state is reachable.
                    assertTrue(mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled());
                    goFromStateIdleTo(STATE_ACTIVATED);
                    triggerContextChanged();
                    break;
                case STATE_2TAPS:
                    goFromStateIdleTo(STATE_IDLE);
                    tap();
                    tap();
                    break;
                case STATE_ACTIVATED_2TAPS:
                    goFromStateIdleTo(STATE_ACTIVATED);
                    tap();
                    tap();
                    break;
                case STATE_ZOOMED_OUT_FROM_SERVICE_2TAPS:
                    goFromStateIdleTo(STATE_ZOOMED_OUT_FROM_SERVICE);
                    tap();
                    tap();
                } break;
                case STATE_NON_ACTIVATED_ZOOMED_TMP: {
                    break;
                case STATE_NON_ACTIVATED_ZOOMED_TMP:
                    goFromStateIdleTo(STATE_2TAPS);
                    send(downEvent());
                    fastForward1sec();
                } break;
                case STATE_ACTIVATED_ZOOMED_TMP: {
                    break;
                case STATE_ZOOMED_FURTHER_TMP:
                    goFromStateIdleTo(STATE_ACTIVATED_2TAPS);
                    send(downEvent());
                    fastForward1sec();
                } break;
                case STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP: {
                    break;
                case STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP:
                    goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
                    send(downEvent());
                    fastForward1sec();
                } break;
                case STATE_SHORTCUT_TRIGGERED: {
                    goFromStateIdleTo(STATE_IDLE);
                    triggerShortcut();
                } break;
                case STATE_PANNING: {
                    break;
                case STATE_PANNING:
                    goFromStateIdleTo(STATE_ACTIVATED);
                    send(downEvent());
                    send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
                    fastForward(ViewConfiguration.getTapTimeout());
                } break;
                case STATE_SCALING_AND_PANNING: {
                    break;
                case STATE_SCALING_AND_PANNING:
                    goFromStateIdleTo(STATE_PANNING);
                    send(pointerEvent(ACTION_MOVE, DEFAULT_X * 2, DEFAULT_Y * 3));
                    send(pointerEvent(ACTION_MOVE, DEFAULT_X * 2, DEFAULT_Y * 4));
                    send(pointerEvent(ACTION_MOVE, DEFAULT_X * 2, DEFAULT_Y * 5));
                } break;
                case STATE_SINGLE_PANNING: {
                    break;
                case STATE_SINGLE_PANNING:
                    goFromStateIdleTo(STATE_ACTIVATED);
                    swipeAndHold();
                } break;
                    break;
                default:
                    throw new IllegalArgumentException("Illegal state: " + state);
            }
@@ -913,14 +961,11 @@ public class FullScreenMagnificationGestureHandlerTest {
     */
    private void returnToNormalFrom(int state) {
        switch (state) {
            case STATE_IDLE: {
            case STATE_IDLE:
                // no op
            } break;
            case STATE_2TAPS: {
                allowEventDelegation();
                fastForward1sec();
            } break;
            case STATE_ACTIVATED: {
                break;
            case STATE_ACTIVATED:
            case STATE_ZOOMED_OUT_FROM_SERVICE:
                if (mMgh.mDetectTripleTap) {
                    tap();
                    tap();
@@ -928,39 +973,45 @@ public class FullScreenMagnificationGestureHandlerTest {
                } else {
                    triggerShortcut();
                }
            } break;
            case STATE_ACTIVATED_2TAPS: {
                break;
            case STATE_SHORTCUT_TRIGGERED:
                triggerShortcut();
                break;
            case STATE_2TAPS:
                allowEventDelegation();
                fastForward1sec();
                break;
            case STATE_ACTIVATED_2TAPS:
            case STATE_ZOOMED_OUT_FROM_SERVICE_2TAPS:
                tap();
            } break;
            case STATE_NON_ACTIVATED_ZOOMED_TMP: {
                break;
            case STATE_NON_ACTIVATED_ZOOMED_TMP:
                send(upEvent());
            } break;
            case STATE_ACTIVATED_ZOOMED_TMP: {
                break;
            case STATE_ZOOMED_FURTHER_TMP:
                send(upEvent());
                returnToNormalFrom(STATE_ACTIVATED);
            } break;
            case STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP: {
                break;
            case STATE_ZOOMED_WITH_PERSISTED_SCALE_TMP:
                send(upEvent());
                if (mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled()) {
                    returnToNormalFrom(STATE_ACTIVATED);
                }
            } break;
            case STATE_SHORTCUT_TRIGGERED: {
                triggerShortcut();
            } break;
            case STATE_PANNING: {
                break;
            case STATE_PANNING:
                send(pointerEvent(ACTION_POINTER_UP, DEFAULT_X * 2, DEFAULT_Y));
                send(upEvent());
                returnToNormalFrom(STATE_ACTIVATED);
            } break;
            case STATE_SCALING_AND_PANNING: {
                break;
            case STATE_SCALING_AND_PANNING:
                returnToNormalFrom(STATE_PANNING);
            } break;
            case STATE_SINGLE_PANNING: {
                break;
            case STATE_SINGLE_PANNING:
                send(upEvent());
                returnToNormalFrom(STATE_ACTIVATED);
            } break;
            default: throw new IllegalArgumentException("Illegal state: " + state);
                break;
            default:
                throw new IllegalArgumentException("Illegal state: " + state);
        }
    }