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

Commit f20dd40f authored by Roy Chou's avatar Roy Chou Committed by Android (Google) Code Review
Browse files

Merge "feat(#AlwaysOnMagnifier)!: Supports magnification zooming to 100% [2/2]"

parents ff1d6b01 9a7f0771
Loading
Loading
Loading
Loading
+21 −9
Original line number Diff line number Diff line
@@ -50,9 +50,9 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
    @interface MagnificationState {}

    // The window magnification is disabled.
    private static final int STATE_DISABLED = 0;
    @VisibleForTesting static final int STATE_DISABLED = 0;
    // The window magnification is enabled.
    private static final int STATE_ENABLED = 1;
    @VisibleForTesting static final int STATE_ENABLED = 1;
    // The window magnification is going to be disabled when the animation is end.
    private static final int STATE_DISABLING = 2;
    // The animation is running for enabling the window magnification.
@@ -151,7 +151,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
            }
            mController.enableWindowMagnificationInternal(scale, centerX, centerY,
                    mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
            setState(STATE_ENABLED);
            updateState();
            return;
        }
        mAnimationCallback = animationCallback;
@@ -165,7 +165,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
                mValueAnimator.cancel();
            }
            sendAnimationCallback(true);
            setState(STATE_ENABLED);
            updateState();
        } else {
            if (mState == STATE_DISABLING) {
                mValueAnimator.reverse();
@@ -254,7 +254,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
                mValueAnimator.cancel();
            }
            mController.deleteWindowMagnification();
            setState(STATE_DISABLED);
            updateState();
            return;
        }

@@ -272,6 +272,14 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
        setState(STATE_DISABLING);
    }

    private void updateState() {
        if (Float.isNaN(mController.getScale())) {
            setState(STATE_DISABLED);
        } else {
            setState(STATE_ENABLED);
        }
    }

    private void setState(@MagnificationState int state) {
        if (DEBUG) {
            Log.d(TAG, "setState from " + mState + " to " + state);
@@ -279,6 +287,11 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
        mState = state;
    }

    @VisibleForTesting
    @MagnificationState int getState() {
        return mState;
    }

    @Override
    public void onAnimationStart(Animator animation) {
        mEndAnimationCanceled = false;
@@ -289,11 +302,10 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
        if (mEndAnimationCanceled || mController == null) {
            return;
        }
        if (Float.isNaN(mController.getScale())) {
            setState(STATE_DISABLED);
        } else {
            setState(STATE_ENABLED);
        if (mState == STATE_DISABLING) {
            mController.deleteWindowMagnification();
        }
        updateState();
        sendAnimationCallback(true);
        // We reset the duration to config_longAnimTime
        mValueAnimator.setDuration(mContext.getResources()
+11 −4
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
    // Delay to avoid updating state description too frequently.
    private static final int UPDATE_STATE_DESCRIPTION_DELAY_MS = 100;
    // It should be consistent with the value defined in WindowMagnificationGestureHandler.
    private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(2.0f, 8.0f);
    private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(1.0f, 8.0f);
    private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f;
    private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f;
    private static final float[] MAGNIFICATION_SCALE_OPTIONS = {1.0f, 1.4f, 1.8f, 2.5f};
@@ -213,7 +213,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
    private static final int MAX_HORIZONTAL_MOVE_ANGLE = 50;
    private static final int HORIZONTAL = 1;
    private static final int VERTICAL = 0;
    private static final double HORIZONTAL_LOCK_BASE =

    @VisibleForTesting
    static final double HORIZONTAL_LOCK_BASE =
            Math.tan(Math.toRadians(MAX_HORIZONTAL_MOVE_ANGLE));

    private boolean mAllowDiagonalScrolling = false;
@@ -704,6 +706,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
        }
    }

    @VisibleForTesting
    WindowMagnificationSettings getMagnificationSettings() {
        return mWindowMagnificationSettings;
    }

    /**
     * Sets the window size with given width and height in pixels without changing the
     * window center. The width or the height will be clamped in the range
@@ -1075,7 +1082,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold

    /**
     * Enables window magnification with specified parameters. If the given scale is <strong>less
     * than or equal to 1.0f<strong>, then
     * than 1.0f<strong>, then
     * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to
     * be consistent with the behavior of display magnification.
     *
@@ -1093,7 +1100,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
     */
    void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
                float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) {
        if (Float.compare(scale, 1.0f)  <= 0) {
        if (Float.compare(scale, 1.0f) < 0) {
            deleteWindowMagnification();
            return;
        }
+14 −7
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
    private ImageButton mChangeModeButton;
    private boolean mAllowDiagonalScrolling = false;
    private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f;
    private static final float A11Y_SCALE_MIN_VALUE = 2.0f;
    private static final float A11Y_SCALE_MIN_VALUE = 1.0f;
    private WindowMagnificationSettingsCallback mCallback;

    @Retention(RetentionPolicy.SOURCE)
@@ -136,9 +136,12 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            float scale = progress * A11Y_CHANGE_SCALE_DIFFERENCE + A11Y_SCALE_MIN_VALUE;
            mSecureSettings.putFloatForUser(
            // update persisted scale only when scale >= 2.0
            if (scale >= 2.0f) {
                Settings.Secure.putFloatForUser(mContext.getContentResolver(),
                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale,
                        UserHandle.USER_CURRENT);
            }
            mCallback.onMagnifierScale(scale);
        }

@@ -516,12 +519,16 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
        boolean enabled = mSecureSettings.getIntForUser(
                Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, 0,
                UserHandle.USER_CURRENT) == 1;
        setDiagonalScrolling(!enabled);
    }

        mSecureSettings.putIntForUser(
                Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, enabled ? 0 : 1,
    @VisibleForTesting
    void setDiagonalScrolling(boolean enabled) {
        Settings.Secure.putIntForUser(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, enabled ? 1 : 0,
                UserHandle.USER_CURRENT);

        mCallback.onSetDiagonalScrolling(!enabled);
        mCallback.onSetDiagonalScrolling(enabled);
    }

    private void setEditMagnifierSizeMode(boolean enable) {
+111 −7
Original line number Diff line number Diff line
@@ -251,10 +251,51 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            throws RemoteException {
        enableWindowMagnificationWithoutAnimation();

        final float targetScale = 1.0f;
        final float targetCenterX = DEFAULT_CENTER_X + 100;
        final float targetCenterY = DEFAULT_CENTER_Y + 100;

        mInstrumentation.runOnMainSync(() -> {
            Mockito.reset(mSpyController);
            mWindowMagnificationAnimationController.enableWindowMagnification(1.0f,
                    DEFAULT_CENTER_X + 100, DEFAULT_CENTER_Y + 100, mAnimationCallback);
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
        });

        SystemClock.sleep(mWaitingAnimationPeriod);

        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                mScaleCaptor.capture(),
                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
        verifyStartValue(mScaleCaptor, mCurrentScale.get());
        verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
        verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
        verifyStartValue(mOffsetXCaptor, 0f);
        verifyStartValue(mOffsetYCaptor, 0f);

        verifyFinalSpec(targetScale, targetCenterX, targetCenterY);

        verify(mAnimationCallback).onResult(true);
        assertEquals(WindowMagnificationAnimationController.STATE_ENABLED,
                mWindowMagnificationAnimationController.getState());
    }

    @Test
    public void enableWindowMagnificationWithScaleLessThanOne_enabled_AnimationAndInvokeCallback()
            throws RemoteException {
        enableWindowMagnificationWithoutAnimation();

        final float targetScale = 0.99f;
        final float targetCenterX = DEFAULT_CENTER_X + 100;
        final float targetCenterY = DEFAULT_CENTER_Y + 100;

        mInstrumentation.runOnMainSync(() -> {
            Mockito.reset(mSpyController);
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
@@ -275,6 +316,29 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
        verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);

        verify(mAnimationCallback).onResult(true);
        assertEquals(WindowMagnificationAnimationController.STATE_DISABLED,
                mWindowMagnificationAnimationController.getState());
    }

    @Test
    public void
            enableWindowMagnificationWithScaleLessThanOneAndWithoutCallBack_enabled_expectedValues()
            throws RemoteException {
        enableWindowMagnificationWithoutAnimation();

        final float targetScale = 0.99f;
        final float targetCenterX = DEFAULT_CENTER_X + 100;
        final float targetCenterY = DEFAULT_CENTER_Y + 100;

        mInstrumentation.runOnMainSync(() -> {
            Mockito.reset(mSpyController);
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, null);
        });

        verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
        assertEquals(WindowMagnificationAnimationController.STATE_DISABLED,
                mWindowMagnificationAnimationController.getState());
    }

    @Test
@@ -684,14 +748,54 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
    }

    @Test
    public void moveWindowMagnifier_enabled() {
    public void moveWindowMagnifier_enabled_vertical_only_expectedValue() {
        enableWindowMagnificationWithoutAnimation();

        // should move vertically since offsetY/offsetX > HORIZONTAL_LOCK_BASE
        final float offsetX = 50.0f;
        final float offsetY =
                (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
                + 1.0f;
        mInstrumentation.runOnMainSync(
                () -> mController.moveWindowMagnifier(100f, 200f));
                () -> mController.moveWindowMagnifier(offsetX, offsetY));

        verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y + offsetY);
    }

    @Test
    public void moveWindowMagnifier_enabled_horinzontal_only_expectedValue() {
        enableWindowMagnificationWithoutAnimation();

        // should move vertically since offsetY/offsetX <= HORIZONTAL_LOCK_BASE
        final float offsetX = 50.0f;
        final float offsetY =
                (float) Math.floor(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
                        - 1.0f;
        mInstrumentation.runOnMainSync(
                () -> mController.moveWindowMagnifier(offsetX, offsetY));

        verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + offsetX, DEFAULT_CENTER_Y);
    }

    @Test
    public void moveWindowMagnifier_enabled_setDiagonalEnabled_expectedValues() {
        enableWindowMagnificationWithoutAnimation();

        final float offsetX = 50.0f;
        final float offsetY =
                (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE);
        // while diagonal scrolling enabled,
        //  should move with both offsetX and offsetY without regrading offsetY/offsetX
        mInstrumentation.runOnMainSync(
                () -> {
                    mController.getMagnificationSettings().setDiagonalScrolling(true);
                    mController.moveWindowMagnifier(offsetX, offsetY);
                });

        verify(mSpyController).moveWindowMagnifier(100f, 200f);
        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 100f, DEFAULT_CENTER_Y + 100f);
        verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + offsetX, DEFAULT_CENTER_Y + offsetY);
    }

    @Test
@@ -807,7 +911,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {

        @Override
        void moveWindowMagnifier(float offsetX, float offsetY) {
            super.moveWindowMagnifier(offsetX, offsetX);
            super.moveWindowMagnifier(offsetX, offsetY);
            mSpyController.moveWindowMagnifier(offsetX, offsetY);
        }

+4 −4
Original line number Diff line number Diff line
@@ -618,18 +618,18 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
    public void performA11yActions_visible_expectedResults() {
        final int displayId = mContext.getDisplayId();
        mInstrumentation.runOnMainSync(() -> {
            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
            mWindowMagnificationController.enableWindowMagnificationInternal(1.5f, Float.NaN,
                    Float.NaN);
        });

        final View mirrorView = mWindowManager.getAttachedView();
        assertTrue(
                mirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_out, null));
        // Minimum scale is 2.0.
        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(2.0f));
        // Minimum scale is 1.0.
        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(1.0f));

        assertTrue(mirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_in, null));
        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(3.5f));
        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(2.5f));

        // TODO: Verify the final state when the mirror surface is visible.
        assertTrue(mirrorView.performAccessibilityAction(R.id.accessibility_action_move_up, null));
Loading