From 58ec92d10b7083448410033a7da26609fc8e2d6b Mon Sep 17 00:00:00 2001 From: mincheli Date: Wed, 8 Dec 2021 21:22:42 +0800 Subject: [PATCH] Resets the window magnifier after the a11y service is unbinded After the service connection is ubineded or the binder died, a11y framework should reset all the magnifiers that had been controlled by the service connection. Now the framework should also support reseting the window magnfiers that had been controlled by the service. Bug: 203532041 Test: atest AccessibilityMagnificationTest, atest AccessibilityServiceConnectionTest, atest MagnificationProcessorTest, atest MagnificationControllerTest, atest WindowMagnificationManagerTest, Change-Id: I605a2cb17e3fb6677b9da0715ca7d7a84af70295 --- .../AccessibilityManagerService.java | 2 + .../FullScreenMagnificationController.java | 13 +-- .../MagnificationController.java | 16 ++-- .../magnification/MagnificationProcessor.java | 20 ++-- .../WindowMagnificationManager.java | 96 ++++++++++++------- .../AccessibilityServiceConnectionTest.java | 17 ++++ .../MagnificationProcessorTest.java | 17 +++- .../MagnificationControllerTest.java | 14 +-- .../MockWindowMagnificationConnection.java | 17 +++- .../WindowMagnificationManagerTest.java | 70 ++++++++++++-- 10 files changed, 205 insertions(+), 77 deletions(-) diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 52a6dc143df74..e59a3d633cfd0 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -193,6 +193,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private static final int OWN_PROCESS_ID = android.os.Process.myPid(); + public static final int INVALID_SERVICE_ID = -1; + // Each service has an ID. Also provide one for magnification gesture handling public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0; diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java index 38615feeba48b..72bc8503b7a53 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -19,6 +19,8 @@ package com.android.server.accessibility.magnification; import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL; import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK; +import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID; + import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.NonNull; @@ -117,8 +119,7 @@ public class FullScreenMagnificationController implements private final int mDisplayId; - private static final int INVALID_ID = -1; - private int mIdOfLastServiceToMagnify = INVALID_ID; + private int mIdOfLastServiceToMagnify = INVALID_SERVICE_ID; private boolean mMagnificationActivated = false; DisplayMagnification(int displayId) { @@ -425,7 +426,7 @@ public class FullScreenMagnificationController implements } final float scale = getScale(); - offsetMagnifiedRegion(scrollX * scale, scrollY * scale, INVALID_ID); + offsetMagnifiedRegion(scrollX * scale, scrollY * scale, INVALID_SERVICE_ID); } } @@ -472,7 +473,7 @@ public class FullScreenMagnificationController implements spec.clear(); onMagnificationChangedLocked(); } - mIdOfLastServiceToMagnify = INVALID_ID; + mIdOfLastServiceToMagnify = INVALID_SERVICE_ID; mForceShowMagnifiableBounds = false; sendSpecToAnimation(spec, animationCallback); return changed; @@ -519,7 +520,7 @@ public class FullScreenMagnificationController implements } final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY); sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback); - if (isMagnifying() && (id != INVALID_ID)) { + if (isMagnifying() && (id != INVALID_SERVICE_ID)) { mIdOfLastServiceToMagnify = id; mMagnificationInfoChangedCallback.onRequestMagnificationSpec(mDisplayId, mIdOfLastServiceToMagnify); @@ -583,7 +584,7 @@ public class FullScreenMagnificationController implements if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) { onMagnificationChangedLocked(); } - if (id != INVALID_ID) { + if (id != INVALID_SERVICE_ID) { mIdOfLastServiceToMagnify = id; } sendSpecToAnimation(mCurrentMagnificationSpec, null); 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 791da694c8117..a63dd005f988e 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -22,6 +22,8 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK; +import static com.android.server.accessibility.AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID; + import android.accessibilityservice.MagnificationConfig; import android.annotation.NonNull; import android.annotation.Nullable; @@ -240,9 +242,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb * @param config The targeting magnification config * @param animate {@code true} to animate the transition, {@code false} * to transition immediately + * @param id The ID of the service requesting the change */ public void transitionMagnificationConfigMode(int displayId, MagnificationConfig config, - boolean animate) { + boolean animate, int id) { synchronized (mLock) { final int targetMode = config.getMode(); final PointF currentBoundsCenter = getCurrentMagnificationBoundsCenterLocked(displayId, @@ -273,7 +276,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb screenMagnificationController.reset(displayId, false); windowMagnificationMgr.enableWindowMagnification(displayId, scale, magnificationCenter.x, magnificationCenter.y, - animate ? STUB_ANIMATION_CALLBACK : null); + animate ? STUB_ANIMATION_CALLBACK : null, id); } else if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { windowMagnificationMgr.disableWindowMagnification(displayId, false, null); if (!screenMagnificationController.isRegistered(displayId)) { @@ -281,7 +284,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb } screenMagnificationController.setScaleAndCenter(displayId, scale, magnificationCenter.x, magnificationCenter.y, animate, - AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); + id); } } } @@ -337,7 +340,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb public void onRequestMagnificationSpec(int displayId, int serviceId) { final WindowMagnificationManager windowMagnificationManager; synchronized (mLock) { - if (serviceId == AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID) { + if (serviceId == MAGNIFICATION_GESTURE_HANDLER_ID) { return; } updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); @@ -718,11 +721,12 @@ public class MagnificationController implements WindowMagnificationManager.Callb } fullScreenMagnificationController.setScaleAndCenter(mDisplayId, mCurrentScale, mCurrentCenter.x, mCurrentCenter.y, mAnimate, - AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); + MAGNIFICATION_GESTURE_HANDLER_ID); } else { getWindowMagnificationMgr().enableWindowMagnification(mDisplayId, mCurrentScale, mCurrentCenter.x, - mCurrentCenter.y, mAnimate ? STUB_ANIMATION_CALLBACK : null); + mCurrentCenter.y, mAnimate ? STUB_ANIMATION_CALLBACK : null, + MAGNIFICATION_GESTURE_HANDLER_ID); } } } 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 7a525ee23d276..40f77b04d5de4 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java @@ -99,7 +99,7 @@ public class MagnificationProcessor { */ public boolean setMagnificationConfig(int displayId, @NonNull MagnificationConfig config, boolean animate, int id) { - if (transitionModeIfNeeded(displayId, config, animate)) { + if (transitionModeIfNeeded(displayId, config, animate, id)) { return true; } @@ -114,7 +114,8 @@ public class MagnificationProcessor { } else if (configMode == MAGNIFICATION_MODE_WINDOW) { return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId, config.getScale(), config.getCenterX(), config.getCenterY(), - animate ? STUB_ANIMATION_CALLBACK : null); + animate ? STUB_ANIMATION_CALLBACK : null, + id); } return false; } @@ -136,13 +137,13 @@ public class MagnificationProcessor { * mode when the controlling mode is unchanged or the controlling magnifier is not activated. */ private boolean transitionModeIfNeeded(int displayId, MagnificationConfig config, - boolean animate) { + boolean animate, int id) { int currentMode = getControllingMode(displayId); if (currentMode == config.getMode() || !mController.hasDisableMagnificationCallback(displayId)) { return false; } - mController.transitionMagnificationConfigMode(displayId, config, animate); + mController.transitionMagnificationConfigMode(displayId, config, animate, id); return true; } @@ -237,7 +238,8 @@ public class MagnificationProcessor { if (mode == MAGNIFICATION_MODE_FULLSCREEN) { return mController.getFullScreenMagnificationController().reset(displayId, animate); } else if (mode == MAGNIFICATION_MODE_WINDOW) { - return mController.getWindowMagnificationMgr().reset(displayId); + return mController.getWindowMagnificationMgr().disableWindowMagnification(displayId, + false, animate ? STUB_ANIMATION_CALLBACK : null); } return false; } @@ -256,11 +258,15 @@ public class MagnificationProcessor { } /** - * {@link FullScreenMagnificationController#resetIfNeeded(int, boolean)} + * Resets all the magnifiers on all the displays. + * Called when the a11y service connection that has changed the current magnification spec is + * unbound or the binder died. + * + * @param connectionId The connection id */ - // TODO: support window magnification public void resetAllIfNeeded(int connectionId) { mController.getFullScreenMagnificationController().resetAllIfNeeded(connectionId); + mController.getWindowMagnificationMgr().resetAllIfNeeded(connectionId); } /** diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java index 3f6ff25dafe56..336f0bbbe5185 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -20,6 +20,9 @@ import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNI import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK; import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK; +import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID; +import static com.android.server.accessibility.AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -253,7 +256,26 @@ public class WindowMagnificationManager implements } mWindowMagnifiers.clear(); } + } + /** + * Resets the window magnifier on all displays that had been controlled by the + * specified service connection. Called when the service connection is unbound + * or binder died. + * + * @param connectionId The connection id + */ + public void resetAllIfNeeded(int connectionId) { + synchronized (mLock) { + for (int i = 0; i < mWindowMagnifiers.size(); i++) { + final WindowMagnifier magnifier = mWindowMagnifiers.valueAt(i); + if (magnifier != null + && magnifier.mEnabled + && connectionId == magnifier.getIdOfLastServiceToControl()) { + magnifier.disableWindowMagnificationInternal(null); + } + } + } } private void resetWindowMagnifiers() { @@ -310,7 +332,7 @@ public class WindowMagnificationManager implements public boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY) { return enableWindowMagnification(displayId, scale, centerX, centerY, - STUB_ANIMATION_CALLBACK); + STUB_ANIMATION_CALLBACK, MAGNIFICATION_GESTURE_HANDLER_ID); } /** @@ -324,12 +346,13 @@ public class WindowMagnificationManager implements * @param centerY The screen-relative Y coordinate around which to center for magnification, * or {@link Float#NaN} to leave unchanged. * @param animationCallback Called when the animation result is valid. + * @param id The connection ID * @return {@code true} if the magnification is enabled successfully. */ public boolean enableWindowMagnification(int displayId, float scale, float centerX, - float centerY, @Nullable MagnificationAnimationCallback animationCallback) { + float centerY, @Nullable MagnificationAnimationCallback animationCallback, int id) { return enableWindowMagnification(displayId, scale, centerX, centerY, animationCallback, - WINDOW_POSITION_AT_CENTER); + WINDOW_POSITION_AT_CENTER, id); } /** @@ -348,7 +371,7 @@ public class WindowMagnificationManager implements public boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY, @WindowPosition int windowPosition) { return enableWindowMagnification(displayId, scale, centerX, centerY, - STUB_ANIMATION_CALLBACK, windowPosition); + STUB_ANIMATION_CALLBACK, windowPosition, MAGNIFICATION_GESTURE_HANDLER_ID); } /** @@ -367,7 +390,7 @@ public class WindowMagnificationManager implements */ public boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY, @Nullable MagnificationAnimationCallback animationCallback, - @WindowPosition int windowPosition) { + @WindowPosition int windowPosition, int id) { final boolean enabled; boolean previousEnabled; synchronized (mLock) { @@ -380,7 +403,7 @@ public class WindowMagnificationManager implements } previousEnabled = magnifier.mEnabled; enabled = magnifier.enableWindowMagnificationInternal(scale, centerX, centerY, - animationCallback, windowPosition); + animationCallback, windowPosition, id); } if (enabled && !previousEnabled) { @@ -394,9 +417,10 @@ public class WindowMagnificationManager implements * * @param displayId The logical display id. * @param clear {@true} Clears the state of window magnification. + * @return {@code true} if the magnification is turned to be disabled successfully */ - void disableWindowMagnification(int displayId, boolean clear) { - disableWindowMagnification(displayId, clear, STUB_ANIMATION_CALLBACK); + boolean disableWindowMagnification(int displayId, boolean clear) { + return disableWindowMagnification(displayId, clear, STUB_ANIMATION_CALLBACK); } /** @@ -405,14 +429,15 @@ public class WindowMagnificationManager implements * @param displayId The logical display id. * @param clear {@true} Clears the state of window magnification. * @param animationCallback Called when the animation result is valid. + * @return {@code true} if the magnification is turned to be disabled successfully */ - void disableWindowMagnification(int displayId, boolean clear, + public boolean disableWindowMagnification(int displayId, boolean clear, MagnificationAnimationCallback animationCallback) { final boolean disabled; synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); if (magnifier == null || mConnectionWrapper == null) { - return; + return false; } disabled = magnifier.disableWindowMagnificationInternal(animationCallback); if (clear) { @@ -423,6 +448,7 @@ public class WindowMagnificationManager implements if (disabled) { mCallback.onWindowMagnificationActivationState(displayId, false); } + return disabled; } /** @@ -490,7 +516,7 @@ public class WindowMagnificationManager implements public float getScale(int displayId) { synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); - if (magnifier == null) { + if (magnifier == null || !magnifier.mEnabled) { return 1.0f; } return magnifier.getScale(); @@ -548,7 +574,7 @@ public class WindowMagnificationManager implements public float getCenterX(int displayId) { synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); - if (magnifier == null) { + if (magnifier == null || !magnifier.mEnabled) { return Float.NaN; } return magnifier.getCenterX(); @@ -564,7 +590,7 @@ public class WindowMagnificationManager implements public float getCenterY(int displayId) { synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); - if (magnifier == null) { + if (magnifier == null || !magnifier.mEnabled) { return Float.NaN; } return magnifier.getCenterY(); @@ -581,7 +607,7 @@ public class WindowMagnificationManager implements public void getMagnificationSourceBounds(int displayId, @NonNull Region outRegion) { synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); - if (magnifier == null) { + if (magnifier == null || !magnifier.mEnabled) { outRegion.setEmpty(); } else { outRegion.set(magnifier.mSourceBounds); @@ -589,24 +615,6 @@ public class WindowMagnificationManager implements } } - /** - * Resets the magnification scale and center. - * - * @param displayId The logical display id. - * @return {@code true} if the magnification spec changed, {@code false} if - * the spec did not change - */ - public boolean reset(int displayId) { - synchronized (mLock) { - WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); - if (magnifier == null) { - return false; - } - magnifier.reset(); - return true; - } - } - /** * Creates the windowMagnifier based on the specified display and stores it. * @@ -722,6 +730,9 @@ public class WindowMagnificationManager implements /** * A class manipulates window magnification per display and contains the magnification * information. + *

+ * This class requires to hold the lock when controlling the magnifier. + *

*/ private static class WindowMagnifier { @@ -735,6 +746,8 @@ public class WindowMagnificationManager implements // The magnified bounds on the screen. private final Rect mSourceBounds = new Rect(); + private int mIdOfLastServiceToControl = INVALID_SERVICE_ID; + private PointF mMagnificationFrameOffsetRatio = new PointF(0f, 0f); WindowMagnifier(int displayId, WindowMagnificationManager windowMagnificationManager) { @@ -745,7 +758,7 @@ public class WindowMagnificationManager implements @GuardedBy("mLock") boolean enableWindowMagnificationInternal(float scale, float centerX, float centerY, @Nullable MagnificationAnimationCallback animationCallback, - @WindowPosition int windowPosition) { + @WindowPosition int windowPosition, int id) { // Handle defaults. The scale may be NAN when just updating magnification center. if (Float.isNaN(scale)) { scale = getScale(); @@ -757,7 +770,7 @@ public class WindowMagnificationManager implements mMagnificationFrameOffsetRatio.y, animationCallback)) { mScale = normScale; mEnabled = true; - + mIdOfLastServiceToControl = id; return true; } return false; @@ -785,7 +798,7 @@ public class WindowMagnificationManager implements if (mWindowMagnificationManager.disableWindowMagnificationInternal( mDisplayId, animationResultCallback)) { mEnabled = false; - + mIdOfLastServiceToControl = INVALID_SERVICE_ID; return true; } return false; @@ -813,6 +826,13 @@ public class WindowMagnificationManager implements mBounds.set(rect); } + /** + * Returns the ID of the last service that changed the magnification config. + */ + int getIdOfLastServiceToControl() { + return mIdOfLastServiceToControl; + } + @GuardedBy("mLock") int pointersInWindow(MotionEvent motionEvent) { int count = 0; @@ -840,6 +860,8 @@ public class WindowMagnificationManager implements @GuardedBy("mLock") void reset() { mEnabled = false; + mIdOfLastServiceToControl = INVALID_SERVICE_ID; + mSourceBounds.setEmpty(); } @GuardedBy("mLock") @@ -849,12 +871,12 @@ public class WindowMagnificationManager implements @GuardedBy("mLock") float getCenterX() { - return mEnabled ? mSourceBounds.exactCenterX() : Float.NaN; + return mSourceBounds.exactCenterX(); } @GuardedBy("mLock") float getCenterY() { - return mEnabled ? mSourceBounds.exactCenterY() : Float.NaN; + return mSourceBounds.exactCenterY(); } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java index e93e5444870e9..82b75408ad188 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java @@ -247,4 +247,21 @@ public class AccessibilityServiceConnectionTest { verify(mMockServiceClient).onPerformGestureResult(0, false); } + @Test + public void unbind_resetAllMagnification() { + mConnection.unbindLocked(); + verify(mMockMagnificationProcessor).resetAllIfNeeded(anyInt()); + } + + @Test + public void binderDied_resetAllMagnification() { + setServiceBinding(COMPONENT_NAME); + mConnection.bindLocked(); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); + + mConnection.binderDied(); + + verify(mMockMagnificationProcessor).resetAllIfNeeded(anyInt()); + } + } 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 621507e2bfc8d..99d6c2af6f75c 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java @@ -24,6 +24,7 @@ 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.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; @@ -235,7 +236,17 @@ public class MagnificationProcessorTest { mMagnificationProcessor.resetCurrentMagnification(TEST_DISPLAY, /* animate= */false); - verify(mMockWindowMagnificationManager).reset(TEST_DISPLAY); + verify(mMockWindowMagnificationManager).disableWindowMagnification(TEST_DISPLAY, false, + null); + } + + @Test + public void resetAllIfNeeded_resetFullscreenAndWindowMagnificationByConnectionId() { + final int connectionId = 1; + mMagnificationProcessor.resetAllIfNeeded(connectionId); + + verify(mMockFullScreenMagnificationController).resetAllIfNeeded(eq(connectionId)); + verify(mMockWindowMagnificationManager).resetAllIfNeeded(eq(connectionId)); } @Test @@ -322,7 +333,7 @@ public class MagnificationProcessorTest { final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig( TEST_DISPLAY); verify(mMockMagnificationController).transitionMagnificationConfigMode(eq(TEST_DISPLAY), - eq(newConfig), anyBoolean()); + eq(newConfig), anyBoolean(), anyInt()); assertConfigEquals(newConfig, result); } @@ -438,7 +449,7 @@ public class MagnificationProcessorTest { anyFloat(), anyFloat(), anyFloat()); doAnswer(enableWindowMagnificationStubAnswer).when( mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY), - anyFloat(), anyFloat(), anyFloat(), any()); + anyFloat(), anyFloat(), anyFloat(), any(), anyInt()); } public void resetAndStubMethods() { 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 08421de3183a2..c9ae11a14ed30 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 @@ -293,7 +293,7 @@ public class MagnificationControllerTest { // Enable window magnification while animating. mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, DEFAULT_SCALE, - Float.NaN, Float.NaN, null); + Float.NaN, Float.NaN, null, TEST_SERVICE_ID); mMockConnection.invokeCallbacks(); assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); @@ -310,7 +310,7 @@ public class MagnificationControllerTest { mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, obtainMagnificationConfig(MODE_WINDOW), - false); + false, TEST_SERVICE_ID); verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), eq(false)); mMockConnection.invokeCallbacks(); @@ -325,13 +325,13 @@ public class MagnificationControllerTest { activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y); mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, obtainMagnificationConfig(MODE_FULLSCREEN), - animate); + animate, TEST_SERVICE_ID); 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); + animate, TEST_SERVICE_ID); } @Test @@ -345,7 +345,7 @@ public class MagnificationControllerTest { // Config-setting mode mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, obtainMagnificationConfig(MODE_FULLSCREEN), - true); + true, TEST_SERVICE_ID); assertEquals(DEFAULT_SCALE, mScreenMagnificationController.getScale(TEST_DISPLAY), 0); assertEquals(MAGNIFIED_CENTER_X, mScreenMagnificationController.getCenterX(TEST_DISPLAY), @@ -365,7 +365,7 @@ public class MagnificationControllerTest { // Config-setting mode mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, obtainMagnificationConfig(MODE_FULLSCREEN), - true); + true, TEST_SERVICE_ID); verify(mTransitionCallBack, never()).onResult(TEST_DISPLAY, true); } @@ -772,7 +772,7 @@ public class MagnificationControllerTest { centerY, true, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); } else { mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, DEFAULT_SCALE, - centerX, centerY, null); + centerX, centerY, null, TEST_SERVICE_ID); mMockConnection.invokeCallbacks(); } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java index 0659a60193365..4c03ec34f0742 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java @@ -35,6 +35,9 @@ import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; +import java.util.ArrayList; +import java.util.List; + /** * Mocks the basic logic of window magnification in System UI. We assume the screen size is * unlimited, so source bounds is always on the center of the mirror window bounds. @@ -42,6 +45,8 @@ import android.view.accessibility.IWindowMagnificationConnectionCallback; class MockWindowMagnificationConnection { public static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; + public static final int TEST_DISPLAY_2 = Display.DEFAULT_DISPLAY + 1; + private final List mValidDisplayIds; private final IWindowMagnificationConnection mConnection; private final Binder mBinder; private final boolean mSuspendCallback; @@ -60,6 +65,10 @@ class MockWindowMagnificationConnection { } MockWindowMagnificationConnection(boolean suspendCallback) throws RemoteException { + mValidDisplayIds = new ArrayList(); + mValidDisplayIds.add(TEST_DISPLAY); + mValidDisplayIds.add(TEST_DISPLAY_2); + mSuspendCallback = suspendCallback; mConnection = mock(IWindowMagnificationConnection.class); mBinder = mock(Binder.class); @@ -86,8 +95,8 @@ class MockWindowMagnificationConnection { private void stubEnableWindowMagnification() throws RemoteException { doAnswer((invocation) -> { final int displayId = invocation.getArgument(0); - if (displayId != TEST_DISPLAY) { - throw new IllegalArgumentException("only support default display :" + displayId); + if (!mValidDisplayIds.contains(displayId)) { + throw new IllegalArgumentException("Not support display :" + displayId); } mWindowMagnificationEnabled = true; final float scale = invocation.getArgument(1); @@ -107,8 +116,8 @@ class MockWindowMagnificationConnection { private void stubDisableWindowMagnification() throws RemoteException { doAnswer((invocation) -> { final int displayId = invocation.getArgument(0); - if (displayId != TEST_DISPLAY) { - throw new IllegalArgumentException("only support default display :" + displayId); + if (!mValidDisplayIds.contains(displayId)) { + throw new IllegalArgumentException("Not support display :" + displayId); } setAnimationCallback(invocation.getArgument(1)); mHasPendingCallback = true; diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java index 85512f36da41d..8b7a19136f50f 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java @@ -16,6 +16,9 @@ package com.android.server.accessibility.magnification; +import static com.android.server.accessibility.magnification.MockWindowMagnificationConnection.TEST_DISPLAY; +import static com.android.server.accessibility.magnification.MockWindowMagnificationConnection.TEST_DISPLAY_2; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; @@ -38,13 +41,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.Region; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.test.mock.MockContentResolver; -import android.view.Display; import android.view.InputDevice; import android.view.MotionEvent; import android.view.accessibility.IRemoteMagnificationAnimationCallback; @@ -67,8 +70,8 @@ import org.mockito.invocation.InvocationOnMock; */ public class WindowMagnificationManagerTest { - private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM; + private static final int SERVICE_ID = 1; private MockWindowMagnificationConnection mMockConnection; @Mock @@ -185,7 +188,7 @@ public class WindowMagnificationManagerTest { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f, - mAnimationCallback); + mAnimationCallback, SERVICE_ID); verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(2f), eq(200f), eq(300f), eq(0f), eq(0f), @@ -377,14 +380,51 @@ public class WindowMagnificationManagerTest { } @Test - public void resetMagnification_enabled_windowMagnifierDisabled() { + public void requestConnectionToNull_expectedGetterResults() { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 1, 1); - mWindowMagnificationManager.reset(TEST_DISPLAY); + mWindowMagnificationManager.requestConnection(false); + + assertEquals(1f, mWindowMagnificationManager.getScale(TEST_DISPLAY), 0); + assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterX(TEST_DISPLAY))); + assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterY(TEST_DISPLAY))); + final Region bounds = new Region(); + mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, bounds); + assertTrue(bounds.isEmpty()); + } + + @Test + public void resetAllMagnification_enabledBySameId_windowMagnifiersDisabled() { + mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY_2, 3f, + 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); + assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); + + mWindowMagnificationManager.resetAllIfNeeded(SERVICE_ID); assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); + } + + @Test + public void resetAllMagnification_enabledByDifferentId_windowMagnifierDisabled() { + final int serviceId2 = SERVICE_ID + 1; + mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY_2, 3f, + 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, serviceId2); + assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); + + mWindowMagnificationManager.resetAllIfNeeded(SERVICE_ID); + + assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); } @Test @@ -438,6 +478,22 @@ public class WindowMagnificationManagerTest { eq(100f), eq(200f), eq(-1f), eq(-1f), notNull()); } + @Test + public void magnifierGetters_disabled_expectedValues() { + mWindowMagnificationManager.requestConnection(true); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER); + + mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + + assertEquals(1f, mWindowMagnificationManager.getScale(TEST_DISPLAY), 0); + assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterX(TEST_DISPLAY))); + assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterY(TEST_DISPLAY))); + final Region bounds = new Region(); + mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, bounds); + assertTrue(bounds.isEmpty()); + } + @Test public void onDisplayRemoved_enabledOnTestDisplay_disabled() { mWindowMagnificationManager.requestConnection(true);