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

Commit b48bfed4 authored by Minche Li's avatar Minche Li Committed by Automerger Merge Worker
Browse files

Merge "Notifies magnification change for the transitioning target mode" into...

Merge "Notifies magnification change for the transitioning target mode" into tm-dev am: b26d2ae8 am: 6724a507

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17040106



Change-Id: Id97468d1a9aea9baf970ff4dc8db34926f056120
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 16f7b4a0 6724a507
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -353,6 +353,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
        mSourceBounds.setEmpty();
        updateSystemUIStateIfNeeded();
        mContext.unregisterComponentCallbacks(this);
        // Notify source bounds empty when magnification is deleted.
        mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, new Rect());
    }

    @Override
+16 −0
Original line number Diff line number Diff line
@@ -292,6 +292,22 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        assertFalse(hasMagnificationOverlapFlag());
    }

    @Test
    public void deleteWindowMagnification_notifySourceBoundsChanged() {
        mInstrumentation.runOnMainSync(
                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
                        Float.NaN,
                        Float.NaN));

        mInstrumentation.runOnMainSync(
                () -> mWindowMagnificationController.deleteWindowMagnification());

        // The first time is for notifying magnification enabled and the second time is for
        // notifying magnification disabled.
        verify(mWindowMagnifierCallback, times(2)).onSourceBoundsChanged(
                (eq(mContext.getDisplayId())), any());
    }

    @Test
    public void moveMagnifier_schedulesFrame() {
        mInstrumentation.runOnMainSync(() -> {
+9 −8
Original line number Diff line number Diff line
@@ -356,13 +356,6 @@ public class FullScreenMagnificationController implements
                        mSpecAnimationBridge, spec, animationCallback);
                mControllerCtx.getHandler().sendMessage(m);
            }

            final boolean lastMagnificationActivated = mMagnificationActivated;
            mMagnificationActivated = spec.scale > 1.0f;
            if (mMagnificationActivated != lastMagnificationActivated) {
                mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState(
                        mDisplayId, mMagnificationActivated);
            }
        }

        /**
@@ -376,9 +369,17 @@ public class FullScreenMagnificationController implements

        @GuardedBy("mLock")
        void onMagnificationChangedLocked() {
            final float scale = getScale();
            final boolean lastMagnificationActivated = mMagnificationActivated;
            mMagnificationActivated = scale > 1.0f;
            if (mMagnificationActivated != lastMagnificationActivated) {
                mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState(
                        mDisplayId, mMagnificationActivated);
            }

            final MagnificationConfig config = new MagnificationConfig.Builder()
                    .setMode(MAGNIFICATION_MODE_FULLSCREEN)
                    .setScale(getScale())
                    .setScale(scale)
                    .setCenterX(getCenterX())
                    .setCenterY(getCenterY()).build();
            mMagnificationInfoChangedCallback.onFullScreenMagnificationChanged(mDisplayId,
+122 −20
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.accessibility.magnification;

import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_WINDOW;
import static android.content.pm.PackageManager.FEATURE_WINDOW_MAGNIFICATION;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
@@ -111,6 +112,15 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    @GuardedBy("mLock")
    private final SparseLongArray mFullScreenModeEnabledTimeArray = new SparseLongArray();

    /**
     * The transitioning magnification modes on the displays. The controller notifies
     * magnification change depending on the target config mode.
     * If the target mode is null, it means the config mode of the display is not
     * transitioning.
     */
    @GuardedBy("mLock")
    private final SparseArray<Integer> mTransitionModes = new SparseArray();

    @GuardedBy("mLock")
    private final SparseArray<WindowManagerInternal.AccessibilityControllerInternal
            .UiChangesForAccessibilityCallbacks> mAccessibilityCallbacksDelegateArray =
@@ -213,6 +223,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        final PointF currentCenter = getCurrentMagnificationCenterLocked(displayId, targetMode);
        final DisableMagnificationCallback animationCallback =
                getDisableMagnificationEndRunnableLocked(displayId);

        if (currentCenter == null && animationCallback == null) {
            transitionCallBack.onResult(displayId, true);
            return;
@@ -233,6 +244,9 @@ public class MagnificationController implements WindowMagnificationManager.Callb
            transitionCallBack.onResult(displayId, true);
            return;
        }

        setTransitionState(displayId, targetMode);

        final FullScreenMagnificationController screenMagnificationController =
                getFullScreenMagnificationController();
        final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr();
@@ -286,19 +300,21 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                Slog.w(TAG, "Discard previous animation request");
                animationCallback.setExpiredAndRemoveFromListLocked();
            }

            final FullScreenMagnificationController screenMagnificationController =
                    getFullScreenMagnificationController();
            final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr();
            final float targetScale = Float.isNaN(config.getScale())
                    ? getTargetModeScaleFromCurrentMagnification(displayId, targetMode)
                    : config.getScale();
            if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
            try {
                setTransitionState(displayId, targetMode);

                if (targetMode == MAGNIFICATION_MODE_WINDOW) {
                    screenMagnificationController.reset(displayId, false);
                    windowMagnificationMgr.enableWindowMagnification(displayId,
                            targetScale, magnificationCenter.x, magnificationCenter.y,
                            animate ? STUB_ANIMATION_CALLBACK : null, id);
            } else if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
                } else if (targetMode == MAGNIFICATION_MODE_FULLSCREEN) {
                    windowMagnificationMgr.disableWindowMagnification(displayId, false, null);
                    if (!screenMagnificationController.isRegistered(displayId)) {
                        screenMagnificationController.register(displayId);
@@ -307,6 +323,29 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                            magnificationCenter.x, magnificationCenter.y, animate,
                            id);
                }
            } finally {
                // Reset transition state after enabling target mode.
                setTransitionState(displayId, null);
            }
        }
    }

    /**
     * Sets magnification config mode transition state. Called when the mode transition starts and
     * ends. If the targetMode and the display id are null, it resets all
     * the transition state.
     *
     * @param displayId  The logical display id
     * @param targetMode The transition target mode. It is not transitioning, if the target mode
     *                   is set null
     */
    private void setTransitionState(Integer displayId, Integer targetMode) {
        synchronized (mLock) {
            if (targetMode == null && displayId == null) {
                mTransitionModes.clear();
            } else {
                mTransitionModes.put(displayId, targetMode);
            }
        }
    }

@@ -413,6 +452,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb

    @Override
    public void onSourceBoundsChanged(int displayId, Rect bounds) {
        if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_WINDOW)) {
            final MagnificationConfig config = new MagnificationConfig.Builder()
                    .setMode(MAGNIFICATION_MODE_WINDOW)
                    .setScale(getWindowMagnificationMgr().getScale(displayId))
@@ -420,12 +460,50 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                    .setCenterY(bounds.exactCenterY()).build();
            mAms.notifyMagnificationChanged(displayId, new Region(bounds), config);
        }
    }

    @Override
    public void onFullScreenMagnificationChanged(int displayId, @NonNull Region region,
            @NonNull MagnificationConfig config) {
        if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_FULLSCREEN)) {
            mAms.notifyMagnificationChanged(displayId, region, config);
        }
    }

    /**
     * Should notify magnification change for the given display under the conditions below
     *
     * <ol>
     *   <li> 1. No mode transitioning and the change mode is active. </li>
     *   <li> 2. No mode transitioning and all the modes are inactive. </li>
     *   <li> 3. It is mode transitioning and the change mode is the transition mode. </li>
     * </ol>
     *
     * @param displayId  The logical display id
     * @param changeMode The mode that has magnification spec change
     */
    private boolean shouldNotifyMagnificationChange(int displayId, int changeMode) {
        synchronized (mLock) {
            final boolean fullScreenMagnifying = mFullScreenMagnificationController != null
                    && mFullScreenMagnificationController.isMagnifying(displayId);
            final boolean windowEnabled = mWindowMagnificationMgr != null
                    && mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId);
            final Integer transitionMode = mTransitionModes.get(displayId);
            if (((changeMode == MAGNIFICATION_MODE_FULLSCREEN && fullScreenMagnifying)
                    || (changeMode == MAGNIFICATION_MODE_WINDOW && windowEnabled))
                    && (transitionMode == null)) {
                return true;
            }
            if ((!fullScreenMagnifying && !windowEnabled)
                    && (transitionMode == null)) {
                return true;
            }
            if (transitionMode != null && changeMode == transitionMode) {
                return true;
            }
        }
        return false;
    }

    private void disableFullScreenMagnificationIfNeeded(int displayId) {
        final FullScreenMagnificationController fullScreenMagnificationController =
@@ -740,9 +818,32 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                    return;
                }
                setExpiredAndRemoveFromListLocked();
                setTransitionState(mDisplayId, null);

                if (success) {
                    adjustCurrentCenterIfNeededLocked();
                    applyMagnificationModeLocked(mTargetMode);
                } else {
                    // Notify magnification change if magnification is inactive when the
                    // transition is failed. This is for the failed transition from
                    // full-screen to window mode. Disable magnification callback helps to send
                    // magnification inactive change since FullScreenMagnificationController
                    // would not notify magnification change if the spec is not changed.
                    final FullScreenMagnificationController screenMagnificationController =
                            getFullScreenMagnificationController();
                    if (mCurrentMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
                            && !screenMagnificationController.isMagnifying(mDisplayId)) {
                        MagnificationConfig.Builder configBuilder =
                                new MagnificationConfig.Builder();
                        Region region = new Region();
                        configBuilder.setMode(MAGNIFICATION_MODE_FULLSCREEN)
                                .setScale(screenMagnificationController.getScale(mDisplayId))
                                .setCenterX(screenMagnificationController.getCenterX(mDisplayId))
                                .setCenterY(screenMagnificationController.getCenterY(mDisplayId));
                        screenMagnificationController.getMagnificationRegion(mDisplayId,
                                region);
                        mAms.notifyMagnificationChanged(mDisplayId, region, configBuilder.build());
                    }
                }
                updateMagnificationButton(mDisplayId, mTargetMode);
                if (mTransitionCallBack != null) {
@@ -770,6 +871,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                    return;
                }
                setExpiredAndRemoveFromListLocked();
                setTransitionState(mDisplayId, null);
                applyMagnificationModeLocked(mCurrentMode);
                updateMagnificationButton(mDisplayId, mCurrentMode);
                if (mTransitionCallBack != null) {
+115 −5
Original line number Diff line number Diff line
@@ -197,6 +197,31 @@ public class MagnificationControllerTest {
        assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0);
    }

    @Test
    public void transitionToWindowModeFailedByReset_fullScreenMagnifying_notifyTransitionFailed()
            throws RemoteException {
        setMagnificationEnabled(MODE_FULLSCREEN);

        mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY,
                MODE_WINDOW,
                mTransitionCallBack);

        verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY),
                mCallbackArgumentCaptor.capture());
        // The transition is interrupted and failed by calling reset.
        mCallbackArgumentCaptor.getValue().onResult(false);
        verify(mTransitionCallBack).onResult(TEST_DISPLAY, false);
        final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
                MagnificationConfig.class);
        // The first time is for notifying full-screen enabled and the second time is for notifying
        // the target mode transitions failed.
        verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class),
                configCaptor.capture());
        final MagnificationConfig actualConfig = configCaptor.getValue();
        assertEquals(MODE_FULLSCREEN, actualConfig.getMode(), 0);
        assertEquals(1.0f, actualConfig.getScale(), 0);
    }

    @Test
    public void transitionToWindowMode_disablingWindowMode_enablingWindowWithFormerCenter()
            throws RemoteException {
@@ -478,6 +503,92 @@ public class MagnificationControllerTest {
        assertEquals(config.getScale(), actualConfig.getScale(), 0);
    }

    @Test
    public void transitionMagnificationMode_windowEnabled_notifyTargetMagnificationChanged()
            throws RemoteException {
        setMagnificationEnabled(MODE_WINDOW);

        mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY,
                MODE_FULLSCREEN, mTransitionCallBack);
        mMockConnection.invokeCallbacks();

        final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
                MagnificationConfig.class);
        // The first time is for notifying window enabled and the second time is for notifying
        // the target mode transitions.
        verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class),
                configCaptor.capture());
        final MagnificationConfig actualConfig = configCaptor.getValue();
        assertEquals(MODE_FULLSCREEN, actualConfig.getMode(), 0);
    }

    @Test
    public void transitionConfigMode_windowEnabled_notifyTargetMagnificationChanged()
            throws RemoteException {
        setMagnificationEnabled(MODE_WINDOW);

        final MagnificationConfig config = obtainMagnificationConfig(MODE_FULLSCREEN);
        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
                config, true, TEST_SERVICE_ID);
        mMockConnection.invokeCallbacks();

        final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
                MagnificationConfig.class);
        // The first time is for notifying window enabled and the second time is for notifying
        // the target mode transitions.
        verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class),
                configCaptor.capture());
        final MagnificationConfig actualConfig = configCaptor.getValue();
        assertEquals(config.getCenterX(), actualConfig.getCenterX(), 0);
        assertEquals(config.getCenterY(), actualConfig.getCenterY(), 0);
        assertEquals(config.getScale(), actualConfig.getScale(), 0);
    }

    @Test
    public void transitionMagnificationMode_fullScreenEnabled_notifyTargetMagnificationChanged()
            throws RemoteException {
        setMagnificationEnabled(MODE_FULLSCREEN);

        mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY,
                MODE_WINDOW, mTransitionCallBack);
        verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY),
                mCallbackArgumentCaptor.capture());
        mCallbackArgumentCaptor.getValue().onResult(true);
        mMockConnection.invokeCallbacks();

        final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
                MagnificationConfig.class);
        // The first time is for notifying full-screen enabled and the second time is for notifying
        // the target mode transitions.
        verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class),
                configCaptor.capture());
        final MagnificationConfig actualConfig = configCaptor.getValue();
        assertEquals(MODE_WINDOW, actualConfig.getMode(), 0);
    }

    @Test
    public void transitionConfigMode_fullScreenEnabled_notifyTargetMagnificationChanged()
            throws RemoteException {
        setMagnificationEnabled(MODE_FULLSCREEN);

        final MagnificationConfig config = obtainMagnificationConfig(MODE_WINDOW);
        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
                config, true, TEST_SERVICE_ID);
        mMockConnection.invokeCallbacks();

        final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
                MagnificationConfig.class);
        // The first time is for notifying full-screen enabled and the second time is for notifying
        // the target mode transitions.
        verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class),
                configCaptor.capture());
        final MagnificationConfig actualConfig = configCaptor.getValue();
        assertEquals(config.getCenterX(), actualConfig.getCenterX(), 0);
        assertEquals(config.getCenterY(), actualConfig.getCenterY(), 0);
        assertEquals(config.getScale(), actualConfig.getScale(), 0);
    }


    @Test
    public void onAccessibilityActionPerformed_magnifierEnabled_showMagnificationButton()
            throws RemoteException {
@@ -743,7 +854,7 @@ public class MagnificationControllerTest {
    }

    @Test
    public void disableWindowMode_windowModeInActive_removeMagnificationButton()
    public void disableWindowMode_windowEnabled_removeMagnificationButton()
            throws RemoteException {
        setMagnificationEnabled(MODE_WINDOW);

@@ -753,7 +864,7 @@ public class MagnificationControllerTest {
    }

    @Test
    public void onFullScreenDeactivated_fullscreenModeInActive_removeMagnificationButton()
    public void onFullScreenDeactivated_fullScreenEnabled_removeMagnificationButton()
            throws RemoteException {
        setMagnificationEnabled(MODE_FULLSCREEN);
        mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
@@ -766,7 +877,7 @@ public class MagnificationControllerTest {
    }

    @Test
    public void transitionToFullScreenMode_fullscreenModeInActive_showMagnificationButton()
    public void transitionToFullScreenMode_windowEnabled_showMagnificationButton()
            throws RemoteException {
        setMagnificationEnabled(MODE_WINDOW);

@@ -779,7 +890,7 @@ public class MagnificationControllerTest {
    }

    @Test
    public void transitionToWindow_fullscreenModeInActive_showMagnificationButton()
    public void transitionToWindow_fullScreenEnabled_showMagnificationButton()
            throws RemoteException {
        setMagnificationEnabled(MODE_FULLSCREEN);

@@ -1018,7 +1129,6 @@ public class MagnificationControllerTest {
                    reset();
                }


                final MagnificationConfig config = new MagnificationConfig.Builder().setMode(
                        MODE_FULLSCREEN).setScale(mScale).setCenterX(mCenterX).setCenterY(
                        mCenterY).build();