diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java index 62ba0c821f4e9..b263fb377e825 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -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 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) { - if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { - mAccessibilityCallbacksDelegate = getFullScreenMagnificationController(); - } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { - mAccessibilityCallbacksDelegate = getWindowMagnificationMgr(); - } else { - mAccessibilityCallbacksDelegate = null; - } + @GuardedBy("mLock") + private void assignMagnificationWindowManagerDelegateByMode(int displayId, int mode) { + if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { + mAccessibilityCallbacksDelegateArray.put(displayId, + getFullScreenMagnificationController()); + } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { + mAccessibilityCallbacksDelegateArray.put(displayId, getWindowMagnificationMgr()); + } else { + 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); } /** diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java index 3e07b095fd29c..a356ae6799d7d 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java @@ -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; } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java index 3c2fbd9ccf7de..863dcb64b885c 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java @@ -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); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java index cc6d7611b4a13..ca22f80a7189d 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java @@ -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(); }