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

Commit 53d887fe authored by Minche Li's avatar Minche Li Committed by Android (Google) Code Review
Browse files

Merge "Transist the controlling magnification mode if needed for AccessibilityService"

parents 5eb03883 269725c9
Loading
Loading
Loading
Loading
+94 −9
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;

import android.accessibilityservice.MagnificationConfig;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -74,6 +76,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    private final PointF mTempPoint = new PointF();
    private final Object mLock;
    private final Context mContext;
    @GuardedBy("mLock")
    private final SparseArray<DisableMagnificationCallback>
            mMagnificationEndRunnableSparseArray = new SparseArray();

@@ -208,7 +211,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        final float scale = mScaleProvider.getScale(displayId);
        final DisableMagnificationCallback animationEndCallback =
                new DisableMagnificationCallback(transitionCallBack, displayId, targetMode,
                        scale, magnificationCenter);
                        scale, magnificationCenter, true);
        if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
            screenMagnificationController.reset(displayId, animationEndCallback);
        } else {
@@ -218,6 +221,77 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        setDisableMagnificationCallbackLocked(displayId, animationEndCallback);
    }

    /**
     * Transitions to the targeting magnification config mode with current center of the
     * magnification mode if it is available. It disables the current magnifier immediately then
     * transitions to the targeting magnifier.
     *
     * @param displayId  The logical display id
     * @param config The targeting magnification config
     * @param animate    {@code true} to animate the transition, {@code false}
     *                   to transition immediately
     */
    public void transitionMagnificationConfigMode(int displayId, MagnificationConfig config,
            boolean animate) {
        synchronized (mLock) {
            final int targetMode = config.getMode();
            final PointF currentBoundsCenter = getCurrentMagnificationBoundsCenterLocked(displayId,
                    targetMode);
            final PointF magnificationCenter = new PointF(config.getCenterX(), config.getCenterY());
            if (currentBoundsCenter != null) {
                final float centerX = Float.isNaN(config.getCenterX())
                        ? currentBoundsCenter.x
                        : config.getCenterX();
                final float centerY = Float.isNaN(config.getCenterY())
                        ? currentBoundsCenter.y
                        : config.getCenterY();
                magnificationCenter.set(centerX, centerY);
            }

            final DisableMagnificationCallback animationCallback =
                    getDisableMagnificationEndRunnableLocked(displayId);
            if (animationCallback != null) {
                Slog.w(TAG, "Discard previous animation request");
                animationCallback.setExpiredAndRemoveFromListLocked();
            }

            final FullScreenMagnificationController screenMagnificationController =
                    getFullScreenMagnificationController();
            final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr();
            final float scale = mScaleProvider.getScale(displayId);
            if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
                screenMagnificationController.reset(displayId, false);
                windowMagnificationMgr.enableWindowMagnification(displayId,
                        scale, magnificationCenter.x, magnificationCenter.y,
                        animate ? STUB_ANIMATION_CALLBACK : null);
            } else if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
                windowMagnificationMgr.disableWindowMagnification(displayId, false, null);
                if (!screenMagnificationController.isRegistered(displayId)) {
                    screenMagnificationController.register(displayId);
                }
                screenMagnificationController.setScaleAndCenter(displayId, scale,
                        magnificationCenter.x, magnificationCenter.y, animate,
                        AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
            }
        }
    }

    /**
     * Return {@code true} if disable magnification animation callback of the display is running.
     *
     * @param displayId The logical display id
     */
    public boolean hasDisableMagnificationCallback(int displayId) {
        synchronized (mLock) {
            final DisableMagnificationCallback animationCallback =
                    getDisableMagnificationEndRunnableLocked(displayId);
            if (animationCallback != null) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void onRequestMagnificationSpec(int displayId, int serviceId) {
        final WindowMagnificationManager windowMagnificationManager;
@@ -267,7 +341,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        // Internal request may be for transition, so we just need to check external request.
        final boolean isMagnifyByExternalRequest =
                fullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId) > 0;
        if (isMagnifyByExternalRequest) {
        if (isMagnifyByExternalRequest || isActivated(displayId,
                ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)) {
            fullScreenMagnificationController.reset(displayId, false);
        }
    }
@@ -518,15 +593,17 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        private final int mCurrentMode;
        private final float mCurrentScale;
        private final PointF mCurrentCenter = new PointF();
        private final boolean mAnimate;

        DisableMagnificationCallback(TransitionCallBack transitionCallBack,
                int displayId, int targetMode, float scale, PointF currentCenter) {
        DisableMagnificationCallback(@Nullable TransitionCallBack transitionCallBack,
                int displayId, int targetMode, float scale, PointF currentCenter, boolean animate) {
            mTransitionCallBack = transitionCallBack;
            mDisplayId = displayId;
            mTargetMode = targetMode;
            mCurrentMode = mTargetMode ^ ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
            mCurrentScale = scale;
            mCurrentCenter.set(currentCenter);
            mAnimate = animate;
        }

        @Override
@@ -544,9 +621,11 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                    applyMagnificationModeLocked(mTargetMode);
                }
                updateMagnificationButton(mDisplayId, mTargetMode);
                if (mTransitionCallBack != null) {
                    mTransitionCallBack.onResult(mDisplayId, success);
                }
            }
        }

        private void adjustCurrentCenterIfNeededLocked() {
            if (mTargetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
@@ -569,9 +648,11 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                setExpiredAndRemoveFromListLocked();
                applyMagnificationModeLocked(mCurrentMode);
                updateMagnificationButton(mDisplayId, mCurrentMode);
                if (mTransitionCallBack != null) {
                    mTransitionCallBack.onResult(mDisplayId, true);
                }
            }
        }

        void setExpiredAndRemoveFromListLocked() {
            mExpired = true;
@@ -580,9 +661,13 @@ public class MagnificationController implements WindowMagnificationManager.Callb

        private void applyMagnificationModeLocked(int mode) {
            if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
                getFullScreenMagnificationController().setScaleAndCenter(mDisplayId,
                        mCurrentScale, mCurrentCenter.x,
                        mCurrentCenter.y, true,
                final FullScreenMagnificationController fullScreenMagnificationController =
                        getFullScreenMagnificationController();
                if (!fullScreenMagnificationController.isRegistered(mDisplayId)) {
                    fullScreenMagnificationController.register(mDisplayId);
                }
                fullScreenMagnificationController.setScaleAndCenter(mDisplayId, mCurrentScale,
                        mCurrentCenter.x, mCurrentCenter.y, mAnimate,
                        AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
            } else {
                getWindowMagnificationMgr().enableWindowMagnification(mDisplayId,
+19 −0
Original line number Diff line number Diff line
@@ -98,6 +98,10 @@ public class MagnificationProcessor {
     */
    public boolean setMagnificationConfig(int displayId, @NonNull MagnificationConfig config,
            boolean animate, int id) {
        if (transitionModeIfNeeded(displayId, config, animate)) {
            return true;
        }

        int configMode = config.getMode();
        if (configMode == DEFAULT_MODE) {
            configMode = getControllingMode(displayId);
@@ -113,6 +117,21 @@ public class MagnificationProcessor {
        return false;
    }

    /**
     * Returns {@code true} if transition magnification mode needed. And it is no need to transition
     * mode when the controlling mode is unchanged or the controlling magnifier is not activated.
     */
    private boolean transitionModeIfNeeded(int displayId, MagnificationConfig config,
            boolean animate) {
        int currentMode = getControllingMode(displayId);
        if (currentMode == config.getMode()
                || !mController.hasDisableMagnificationCallback(displayId)) {
            return false;
        }
        mController.transitionMagnificationConfigMode(displayId, config, animate);
        return true;
    }

    /**
     * Returns the magnification scale. If an animation is in progress,
     * this reflects the end state of the animation.
+29 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.accessibilityservice.MagnificationConfig.WINDOW_MODE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -316,6 +317,34 @@ public class MagnificationProcessorTest {
        assertConfigEquals(config, result);
    }

    @Test
    public void setMagnificationConfig_controllingModeChangeAndAnimating_transitionConfigMode() {
        final int currentActivatedMode = WINDOW_MODE;
        final int targetMode = FULLSCREEN_MODE;
        final MagnificationConfig oldConfig = new MagnificationConfig.Builder()
                .setMode(currentActivatedMode)
                .setScale(TEST_SCALE)
                .setCenterX(TEST_CENTER_X)
                .setCenterY(TEST_CENTER_Y).build();
        setMagnificationActivated(TEST_DISPLAY, oldConfig);
        final MagnificationConfig newConfig = new MagnificationConfig.Builder()
                .setMode(targetMode)
                .setScale(TEST_SCALE)
                .setCenterX(TEST_CENTER_X + 10)
                .setCenterY(TEST_CENTER_Y + 10).build();

        // Has magnification animation running
        when(mMockMagnificationController.hasDisableMagnificationCallback(TEST_DISPLAY)).thenReturn(
                true);
        setMagnificationActivated(TEST_DISPLAY, newConfig);

        final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig(
                TEST_DISPLAY);
        verify(mMockMagnificationController).transitionMagnificationConfigMode(eq(TEST_DISPLAY),
                eq(newConfig), anyBoolean());
        assertConfigEquals(newConfig, result);
    }

    private void setMagnificationActivated(int displayId, int configMode) {
        setMagnificationActivated(displayId,
                new MagnificationConfig.Builder().setMode(configMode).build());
+78 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.accessibilityservice.MagnificationConfig;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -229,7 +230,7 @@ public class MagnificationControllerTest {
    }

    @Test
    public void transitionToFullScreen_centerNotInTheBounds_magnifyTheCenterOfMagnificationBounds()
    public void transitionToFullScreen_centerNotInTheBounds_magnifyBoundsCenter()
            throws RemoteException {
        final Rect magnificationBounds = MAGNIFICATION_REGION.getBounds();
        final PointF magnifiedCenter = new PointF(magnificationBounds.right + 100,
@@ -288,6 +289,73 @@ public class MagnificationControllerTest {
        verify(mTransitionCallBack).onResult(TEST_DISPLAY, false);
    }

    @Test
    public void configTransitionToWindowMode_fullScreenMagnifying_disableFullScreenAndEnableWindow()
            throws RemoteException {
        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);

        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
                obtainMagnificationConfig(MODE_WINDOW),
                false);

        verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), eq(false));
        mMockConnection.invokeCallbacks();
        assertEquals(MAGNIFIED_CENTER_X, mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 0);
        assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0);
    }

    @Test
    public void configTransitionToFullScreen_windowMagnifying_disableWindowAndEnableFullScreen()
            throws RemoteException {
        final boolean animate = true;
        activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
                obtainMagnificationConfig(MODE_FULLSCREEN),
                animate);
        mMockConnection.invokeCallbacks();

        assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
        verify(mScreenMagnificationController).setScaleAndCenter(TEST_DISPLAY,
                DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
                animate, MAGNIFICATION_GESTURE_HANDLER_ID);
    }

    @Test
    public void configTransitionToFullScreen_userSettingsDisablingFullScreen_enableFullScreen()
            throws RemoteException {
        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
        // User-setting mode
        mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY,
                MODE_WINDOW, mTransitionCallBack);

        // Config-setting mode
        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
                obtainMagnificationConfig(MODE_FULLSCREEN),
                true);

        assertEquals(DEFAULT_SCALE, mScreenMagnificationController.getScale(TEST_DISPLAY), 0);
        assertEquals(MAGNIFIED_CENTER_X, mScreenMagnificationController.getCenterX(TEST_DISPLAY),
                0);
        assertEquals(MAGNIFIED_CENTER_Y, mScreenMagnificationController.getCenterY(TEST_DISPLAY),
                0);
    }

    @Test
    public void interruptDuringTransitionToWindow_disablingFullScreen_discardPreviousTransition()
            throws RemoteException {
        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
        // User-setting mode
        mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY,
                MODE_WINDOW, mTransitionCallBack);

        // Config-setting mode
        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
                obtainMagnificationConfig(MODE_FULLSCREEN),
                true);

        verify(mTransitionCallBack, never()).onResult(TEST_DISPLAY, true);
    }

    @Test
    public void onDisplayRemoved_notifyAllModules() {
        mMagnificationController.onDisplayRemoved(TEST_DISPLAY);
@@ -609,6 +677,10 @@ public class MagnificationControllerTest {
    private void setMagnificationEnabled(int mode, float centerX, float centerY)
            throws RemoteException {
        setMagnificationModeSettings(mode);
        activateMagnifier(mode, centerX, centerY);
    }

    private void activateMagnifier(int mode, float centerX, float centerY) throws RemoteException {
        mScreenMagnificationControllerStubber.resetAndStubMethods();
        final boolean windowMagnifying = mWindowMagnificationManager.isWindowMagnifierEnabled(
                TEST_DISPLAY);
@@ -631,6 +703,11 @@ public class MagnificationControllerTest {
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, mode, CURRENT_USER_ID);
    }

    private MagnificationConfig obtainMagnificationConfig(int mode) {
        return new MagnificationConfig.Builder().setMode(mode).setScale(DEFAULT_SCALE).setCenterX(
                MAGNIFIED_CENTER_X).setCenterY(MAGNIFIED_CENTER_Y).build();
    }

    /**
     * Stubs public methods to simulate the real beahviours.
     */