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

Commit b26c4316 authored by Daniel Hsieh's avatar Daniel Hsieh
Browse files

Supports multiple-display on activated mode recording.

In previous, we only use a variable to record the state of magnification
mode. Therefore, it would be confused when there are multiple displays.

Now, we use sparse array to keep the state of current magnification mode
and last magnification activated modes with corresponding displayId,
making us have ability to distinguish different modes in different
displayId.

Bug: 182227245
Test: atest MagnificationControllerTest
      atest MagnificationProcessorTest
      atest FullScreenMagnificationGestureHandlerTest
      atest MagnificationConfigTest
Change-Id: I239faab22bb6abe3e6cadde9b09eba496c4688c0
parent 23b8a6d6
Loading
Loading
Loading
Loading
+61 −44
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.view.accessibility.MagnificationAnimationCallback;

import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
@@ -97,20 +99,22 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    private final boolean mSupportWindowMagnification;

    @GuardedBy("mLock")
    private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
    private final SparseIntArray mCurrentMagnificationModeArray = new SparseIntArray();
    @GuardedBy("mLock")
    private int mLastActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
    private final SparseIntArray mLastMagnificationActivatedModeArray = new SparseIntArray();
    // Track the active user to reset the magnification and get the associated user settings.
    private @UserIdInt int mUserId = UserHandle.USER_SYSTEM;
    @GuardedBy("mLock")
    private final SparseBooleanArray mIsImeVisibleArray = new SparseBooleanArray();
    private long mWindowModeEnabledTime = 0;
    private long mFullScreenModeEnabledTime = 0;
    @GuardedBy("mLock")
    private final SparseLongArray mWindowModeEnabledTimeArray = new SparseLongArray();
    @GuardedBy("mLock")
    private final SparseLongArray mFullScreenModeEnabledTimeArray = new SparseLongArray();

    @GuardedBy("mLock")
    @Nullable
    private WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks
            mAccessibilityCallbacksDelegate;
    private final SparseArray<WindowManagerInternal.AccessibilityControllerInternal
            .UiChangesForAccessibilityCallbacks> mAccessibilityCallbacksDelegateArray =
            new SparseArray<>();

    /**
     * A callback to inform the magnification transition result on the given display.
@@ -333,20 +337,20 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    }

    @GuardedBy("mLock")
    private void setActivatedModeAndSwitchDelegate(int mode) {
        mActivatedMode = mode;
        assignMagnificationWindowManagerDelegateByMode(mode);
    private void setCurrentMagnificationModeAndSwitchDelegate(int displayId, int mode) {
        mCurrentMagnificationModeArray.put(displayId, mode);
        assignMagnificationWindowManagerDelegateByMode(displayId, mode);
    }

    private void assignMagnificationWindowManagerDelegateByMode(int mode) {
        synchronized (mLock) {
    @GuardedBy("mLock")
    private void assignMagnificationWindowManagerDelegateByMode(int displayId, int mode) {
        if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
                mAccessibilityCallbacksDelegate = getFullScreenMagnificationController();
            mAccessibilityCallbacksDelegateArray.put(displayId,
                    getFullScreenMagnificationController());
        } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
                mAccessibilityCallbacksDelegate = getWindowMagnificationMgr();
            mAccessibilityCallbacksDelegateArray.put(displayId, getWindowMagnificationMgr());
        } else {
                mAccessibilityCallbacksDelegate = null;
            }
            mAccessibilityCallbacksDelegateArray.delete(displayId);
        }
    }

@@ -356,7 +360,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks
                delegate;
        synchronized (mLock) {
            delegate = mAccessibilityCallbacksDelegate;
            delegate = mAccessibilityCallbacksDelegateArray.get(displayId);
        }
        if (delegate != null) {
            delegate.onRectangleOnScreenRequested(displayId, left, top, right, bottom);
@@ -378,25 +382,26 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        }
    }

    // TODO : supporting multi-display (b/182227245).
    @Override
    public void onWindowMagnificationActivationState(int displayId, boolean activated) {
        if (activated) {
            mWindowModeEnabledTime = SystemClock.uptimeMillis();

            synchronized (mLock) {
                setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
                mLastActivatedMode = mActivatedMode;
                mWindowModeEnabledTimeArray.put(displayId, SystemClock.uptimeMillis());
                setCurrentMagnificationModeAndSwitchDelegate(displayId,
                        ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
                mLastMagnificationActivatedModeArray.put(displayId,
                        ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
            }
            logMagnificationModeWithImeOnIfNeeded(displayId);
            disableFullScreenMagnificationIfNeeded(displayId);
        } else {
            logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
                    SystemClock.uptimeMillis() - mWindowModeEnabledTime);

            long duration;
            synchronized (mLock) {
                setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_NONE);
                setCurrentMagnificationModeAndSwitchDelegate(displayId,
                        ACCESSIBILITY_MAGNIFICATION_MODE_NONE);
                duration = SystemClock.uptimeMillis() - mWindowModeEnabledTimeArray.get(displayId);
            }
            logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, duration);
        }
        updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
    }
@@ -437,21 +442,24 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    @Override
    public void onFullScreenMagnificationActivationState(int displayId, boolean activated) {
        if (activated) {
            mFullScreenModeEnabledTime = SystemClock.uptimeMillis();

            synchronized (mLock) {
                setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
                mLastActivatedMode = mActivatedMode;
                mFullScreenModeEnabledTimeArray.put(displayId, SystemClock.uptimeMillis());
                setCurrentMagnificationModeAndSwitchDelegate(displayId,
                        ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
                mLastMagnificationActivatedModeArray.put(displayId,
                        ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
            }
            logMagnificationModeWithImeOnIfNeeded(displayId);
            disableWindowMagnificationIfNeeded(displayId);
        } else {
            logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
                    SystemClock.uptimeMillis() - mFullScreenModeEnabledTime);

            long duration;
            synchronized (mLock) {
                setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_NONE);
                setCurrentMagnificationModeAndSwitchDelegate(displayId,
                        ACCESSIBILITY_MAGNIFICATION_MODE_NONE);
                duration = SystemClock.uptimeMillis()
                        - mFullScreenModeEnabledTimeArray.get(displayId);
            }
            logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, duration);
        }
        updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
    }
@@ -477,9 +485,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb
     * Returns the last activated magnification mode. If there is no activated magnifier before, it
     * returns fullscreen mode by default.
     */
    public int getLastActivatedMode() {
    public int getLastMagnificationActivatedMode(int displayId) {
        synchronized (mLock) {
            return mLastActivatedMode;
            return mLastMagnificationActivatedModeArray.get(displayId,
                    ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
        }
    }

@@ -522,7 +531,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        synchronized (mLock) {
            fullMagnificationController = mFullScreenMagnificationController;
            windowMagnificationManager = mWindowMagnificationMgr;
            mLastActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
            mAccessibilityCallbacksDelegateArray.clear();
            mCurrentMagnificationModeArray.clear();
            mLastMagnificationActivatedModeArray.clear();
            mIsImeVisibleArray.clear();
        }

        mScaleProvider.onUserChanged(userId);
@@ -547,6 +559,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb
            if (mWindowMagnificationMgr != null) {
                mWindowMagnificationMgr.onDisplayRemoved(displayId);
            }
            mAccessibilityCallbacksDelegateArray.delete(displayId);
            mCurrentMagnificationModeArray.delete(displayId);
            mLastMagnificationActivatedModeArray.delete(displayId);
            mIsImeVisibleArray.delete(displayId);
        }
        mScaleProvider.onDisplayRemoved(displayId);
    }
@@ -587,16 +603,17 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    }

    private void logMagnificationModeWithImeOnIfNeeded(int displayId) {
        final int mode;
        final int currentActivateMode;

        synchronized (mLock) {
            currentActivateMode = mCurrentMagnificationModeArray.get(displayId,
                    ACCESSIBILITY_MAGNIFICATION_MODE_NONE);
            if (!mIsImeVisibleArray.get(displayId, false)
                    || mActivatedMode == ACCESSIBILITY_MAGNIFICATION_MODE_NONE) {
                    || currentActivateMode == ACCESSIBILITY_MAGNIFICATION_MODE_NONE) {
                return;
            }
            mode = mActivatedMode;
        }
        logMagnificationModeWithIme(mode);
        logMagnificationModeWithIme(currentActivateMode);
    }

    /**
+2 −1
Original line number Diff line number Diff line
@@ -341,7 +341,8 @@ public class MagnificationProcessor {
                ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)) {
            return MAGNIFICATION_MODE_FULLSCREEN;
        } else {
            return (mController.getLastActivatedMode() == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)
            return (mController.getLastMagnificationActivatedMode(displayId)
                    == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)
                    ? MAGNIFICATION_MODE_WINDOW
                    : MAGNIFICATION_MODE_FULLSCREEN;
        }
+17 −0
Original line number Diff line number Diff line
@@ -18,8 +18,11 @@ package com.android.server.accessibility;

import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_WINDOW;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -254,6 +257,20 @@ public class MagnificationProcessorTest {
        assertEquals(MAGNIFICATION_MODE_WINDOW, currentMode);
    }

    @Test
    public void getCurrentMode_changeOtherDisplayMode_returnDefaultModeOnDefaultDisplay() {
        final int otherDisplayId = TEST_DISPLAY + 1;
        setMagnificationActivated(otherDisplayId, MAGNIFICATION_MODE_WINDOW);

        int currentMode = mMagnificationProcessor.getControllingMode(TEST_DISPLAY);

        assertFalse(mMockMagnificationController.isActivated(TEST_DISPLAY,
                ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
        assertFalse(mMockMagnificationController.isActivated(TEST_DISPLAY,
                ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
        assertEquals(MAGNIFICATION_MODE_FULLSCREEN, currentMode);
    }

    @Test
    public void resetFullscreenMagnification_fullscreenMagnificationActivated() {
        setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_FULLSCREEN);
+60 −5
Original line number Diff line number Diff line
@@ -555,7 +555,22 @@ public class MagnificationControllerTest {
    }

    @Test
    public void onRectangleOnScreenRequested_NoneIsActivated_noneDispatchEvent() {
    public void onRectangleOnScreenRequested_noneIsActivated_noneDispatchEvent() {
        UiChangesForAccessibilityCallbacks callbacks = getUiChangesForAccessibilityCallbacks();

        callbacks.onRectangleOnScreenRequested(TEST_DISPLAY,
                TEST_RECT.left, TEST_RECT.top, TEST_RECT.right, TEST_RECT.bottom);

        verify(mScreenMagnificationController, never()).onRectangleOnScreenRequested(
                eq(TEST_DISPLAY), anyInt(), anyInt(), anyInt(), anyInt());
        verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(),
                anyInt(), anyInt(), anyInt(), anyInt());
    }

    @Test
    public void onRectangleOnScreenRequested_otherDisplayIsActivated_noneEventOnDefaultDisplay() {
        mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY + 1,
                true);
        UiChangesForAccessibilityCallbacks callbacks = getUiChangesForAccessibilityCallbacks();

        callbacks.onRectangleOnScreenRequested(TEST_DISPLAY,
@@ -578,6 +593,41 @@ public class MagnificationControllerTest {
        assertFalse(mScreenMagnificationController.isMagnifying(TEST_DISPLAY));
    }

    @Test
    public void getLastActivatedMode_switchMode_returnExpectedLastActivatedMode()
            throws RemoteException {
        activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);

        final int lastActivatedMode = mMagnificationController
                .getLastMagnificationActivatedMode(TEST_DISPLAY);

        assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, lastActivatedMode);
    }

    @Test
    public void getLastActivatedMode_switchModeAtOtherDisplay_returnExpectedLastActivatedMode()
            throws RemoteException {
        activateMagnifier(TEST_DISPLAY, MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
        activateMagnifier(TEST_DISPLAY + 1, MODE_FULLSCREEN, MAGNIFIED_CENTER_X,
                MAGNIFIED_CENTER_Y);

        final int lastActivatedMode = mMagnificationController
                .getLastMagnificationActivatedMode(TEST_DISPLAY);

        assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, lastActivatedMode);
    }

    @Test
    public void getLastActivatedMode_otherDisplayIsActivated_defaultModeOnDefaultDisplay()
            throws RemoteException {
        activateMagnifier(TEST_DISPLAY + 1, MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);

        int lastActivatedMode = mMagnificationController
                .getLastMagnificationActivatedMode(TEST_DISPLAY);

        assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, lastActivatedMode);
    }

    @Test
    public void onFullScreenMagnificationActivationState_fullScreenEnabled_logFullScreenDuration() {
        MagnificationController spyController = spy(mMagnificationController);
@@ -818,17 +868,22 @@ public class MagnificationControllerTest {
    }

    private void activateMagnifier(int mode, float centerX, float centerY) throws RemoteException {
        activateMagnifier(TEST_DISPLAY, mode, centerX, centerY);
    }

    private void activateMagnifier(int displayId, int mode, float centerX, float centerY)
            throws RemoteException {
        final boolean windowMagnifying = mWindowMagnificationManager.isWindowMagnifierEnabled(
                TEST_DISPLAY);
                displayId);
        if (windowMagnifying) {
            mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false);
            mWindowMagnificationManager.disableWindowMagnification(displayId, false);
            mMockConnection.invokeCallbacks();
        }
        if (mode == MODE_FULLSCREEN) {
            mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE, centerX,
            mScreenMagnificationController.setScaleAndCenter(displayId, DEFAULT_SCALE, centerX,
                    centerY, true, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
        } else {
            mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, DEFAULT_SCALE,
            mWindowMagnificationManager.enableWindowMagnification(displayId, DEFAULT_SCALE,
                    centerX, centerY, null, TEST_SERVICE_ID);
            mMockConnection.invokeCallbacks();
        }