From b26c4316cbf2b3cd34e4e67046760f67bdbf41d5 Mon Sep 17 00:00:00 2001 From: Daniel Hsieh Date: Fri, 1 Apr 2022 15:38:11 +0000 Subject: [PATCH] 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 --- .../MagnificationController.java | 105 ++++++++++-------- .../magnification/MagnificationProcessor.java | 3 +- .../MagnificationProcessorTest.java | 17 +++ .../MagnificationControllerTest.java | 65 ++++++++++- 4 files changed, 140 insertions(+), 50 deletions(-) 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(); }