From db026034a907d602eb66a4276ddc45912a0fab3d Mon Sep 17 00:00:00 2001 From: ryanlwlin Date: Thu, 10 Feb 2022 14:37:05 +0800 Subject: [PATCH] Fix inconsistent scale when setting magnificaotion config We used to use MagnificationScaleProvider to retrive the scale when transitioning the mode, which is incorrect because the provider only persists the scale changed by users. If the scale is changed by public api, then the scale will become inconsistent. To fix it we choose the scale based on the target mode. We also fix that mode transition without animation should be considered as a transition case. We also add more log for flaky CTS debugging. Bug: 218792845 Test: atest MagnificationProcessorTest atest com.android.server.accessibility.magnification Change-Id: I47f49345ce46f726d6e06e203110ef793f35c76e --- .../MagnificationController.java | 48 +++-- .../magnification/MagnificationProcessor.java | 23 ++- .../WindowMagnificationManager.java | 34 ++-- .../MagnificationProcessorTest.java | 67 ++++++- .../MagnificationControllerTest.java | 176 +++++++++++------- .../WindowMagnificationManagerTest.java | 9 +- 6 files changed, 248 insertions(+), 109 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 b70ffb2243e16..c376bf873dc86 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -78,6 +78,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb private static final boolean DEBUG = false; private static final String TAG = "MagnificationController"; + private final AccessibilityManagerService mAms; private final PointF mTempPoint = new PointF(); private final Object mLock; @@ -194,11 +195,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb */ public void transitionMagnificationModeLocked(int displayId, int targetMode, @NonNull TransitionCallBack transitionCallBack) { - final PointF magnificationCenter = getCurrentMagnificationBoundsCenterLocked(displayId, - targetMode); + final PointF currentCenter = getCurrentMagnificationCenterLocked(displayId, targetMode); final DisableMagnificationCallback animationCallback = getDisableMagnificationEndRunnableLocked(displayId); - if (magnificationCenter == null && animationCallback == null) { + if (currentCenter == null && animationCallback == null) { transitionCallBack.onResult(displayId, true); return; } @@ -213,7 +213,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb } } - if (magnificationCenter == null) { + if (currentCenter == null) { Slog.w(TAG, "Invalid center, ignore it"); transitionCallBack.onResult(displayId, true); return; @@ -221,10 +221,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb final FullScreenMagnificationController screenMagnificationController = getFullScreenMagnificationController(); final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr(); - final float scale = mScaleProvider.getScale(displayId); + final float scale = getTargetModeScaleFromCurrentMagnification(displayId, targetMode); final DisableMagnificationCallback animationEndCallback = new DisableMagnificationCallback(transitionCallBack, displayId, targetMode, - scale, magnificationCenter, true); + scale, currentCenter, true); if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { screenMagnificationController.reset(displayId, animationEndCallback); } else { @@ -247,17 +247,20 @@ public class MagnificationController implements WindowMagnificationManager.Callb */ public void transitionMagnificationConfigMode(int displayId, MagnificationConfig config, boolean animate, int id) { + if (DEBUG) { + Slog.d(TAG, "transitionMagnificationConfigMode displayId = " + displayId + + ", config = " + config); + } synchronized (mLock) { final int targetMode = config.getMode(); - final PointF currentBoundsCenter = getCurrentMagnificationBoundsCenterLocked(displayId, - targetMode); + final PointF currentCenter = getCurrentMagnificationCenterLocked(displayId, targetMode); final PointF magnificationCenter = new PointF(config.getCenterX(), config.getCenterY()); - if (currentBoundsCenter != null) { + if (currentCenter != null) { final float centerX = Float.isNaN(config.getCenterX()) - ? currentBoundsCenter.x + ? currentCenter.x : config.getCenterX(); final float centerY = Float.isNaN(config.getCenterY()) - ? currentBoundsCenter.y + ? currentCenter.y : config.getCenterY(); magnificationCenter.set(centerX, centerY); } @@ -272,24 +275,36 @@ public class MagnificationController implements WindowMagnificationManager.Callb final FullScreenMagnificationController screenMagnificationController = getFullScreenMagnificationController(); final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr(); - final float scale = mScaleProvider.getScale(displayId); + final float targetScale = Float.isNaN(config.getScale()) + ? getTargetModeScaleFromCurrentMagnification(displayId, targetMode) + : config.getScale(); if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { screenMagnificationController.reset(displayId, false); windowMagnificationMgr.enableWindowMagnification(displayId, - scale, magnificationCenter.x, magnificationCenter.y, + targetScale, magnificationCenter.x, magnificationCenter.y, animate ? STUB_ANIMATION_CALLBACK : null, id); } else if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { windowMagnificationMgr.disableWindowMagnification(displayId, false, null); if (!screenMagnificationController.isRegistered(displayId)) { screenMagnificationController.register(displayId); } - screenMagnificationController.setScaleAndCenter(displayId, scale, + screenMagnificationController.setScaleAndCenter(displayId, targetScale, magnificationCenter.x, magnificationCenter.y, animate, id); } } } + // We assume the target mode is different from the current mode, and there is only + // two modes, so we get the target scale from another mode. + private float getTargetModeScaleFromCurrentMagnification(int displayId, int targetMode) { + if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { + return getFullScreenMagnificationController().getScale(displayId); + } else { + return getWindowMagnificationMgr().getScale(displayId); + } + } + /** * Return {@code true} if disable magnification animation callback of the display is running. * @@ -384,7 +399,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb public void onSourceBoundsChanged(int displayId, Rect bounds) { final MagnificationConfig config = new MagnificationConfig.Builder() .setMode(MAGNIFICATION_MODE_WINDOW) - .setScale(mScaleProvider.getScale(displayId)) + .setScale(getWindowMagnificationMgr().getScale(displayId)) .setCenterX(bounds.exactCenterX()) .setCenterY(bounds.exactCenterY()).build(); mAms.notifyMagnificationChanged(displayId, new Region(bounds), config); @@ -607,8 +622,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb } } - private @Nullable - PointF getCurrentMagnificationBoundsCenterLocked(int displayId, int targetMode) { + private @Nullable PointF getCurrentMagnificationCenterLocked(int displayId, int targetMode) { if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { if (mWindowMagnificationMgr == null || !mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId)) { 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 9eb77b4366b34..175182c7a3bb8 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java @@ -26,6 +26,7 @@ import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANI import android.accessibilityservice.MagnificationConfig; import android.annotation.NonNull; import android.graphics.Region; +import android.util.Slog; import android.view.Display; import java.io.PrintWriter; @@ -56,6 +57,9 @@ import java.util.ArrayList; */ public class MagnificationProcessor { + private static final String TAG = "MagnificationProcessor"; + private static final boolean DEBUG = false; + private final MagnificationController mController; public MagnificationProcessor(MagnificationController controller) { @@ -103,6 +107,9 @@ public class MagnificationProcessor { */ public boolean setMagnificationConfig(int displayId, @NonNull MagnificationConfig config, boolean animate, int id) { + if (DEBUG) { + Slog.d(TAG, "setMagnificationConfig config=" + config); + } if (transitionModeIfNeeded(displayId, config, animate, id)) { return true; } @@ -125,15 +132,13 @@ public class MagnificationProcessor { } private boolean setScaleAndCenterForFullScreenMagnification(int displayId, float scale, - float centerX, float centerY, - boolean animate, int id) { + float centerX, float centerY, boolean animate, int id) { + if (!isRegistered(displayId)) { register(displayId); } return mController.getFullScreenMagnificationController().setScaleAndCenter( - displayId, - scale, - centerX, centerY, animate, id); + displayId, scale, centerX, centerY, animate, id); } /** @@ -143,8 +148,12 @@ public class MagnificationProcessor { private boolean transitionModeIfNeeded(int displayId, MagnificationConfig config, boolean animate, int id) { int currentMode = getControllingMode(displayId); - if (currentMode == config.getMode() - || !mController.hasDisableMagnificationCallback(displayId)) { + if (config.getMode() == MagnificationConfig.MAGNIFICATION_MODE_DEFAULT) { + return false; + } + // Target mode is as same as current mode and is not transitioning. + if (currentMode == config.getMode() && !mController.hasDisableMagnificationCallback( + displayId)) { return false; } mController.transitionMagnificationConfigMode(displayId, config, animate, id); 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 278f3f9cbf777..89910eac06c50 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -177,6 +177,9 @@ public class WindowMagnificationManager implements * @param connection {@link IWindowMagnificationConnection} */ public void setConnection(@Nullable IWindowMagnificationConnection connection) { + if (DBG) { + Slog.d(TAG, "setConnection :" + connection); + } synchronized (mLock) { // Reset connectionWrapper. if (mConnectionWrapper != null) { @@ -223,6 +226,9 @@ public class WindowMagnificationManager implements * @return {@code true} if {@link IWindowMagnificationConnection} state is going to change. */ public boolean requestConnection(boolean connect) { + if (DBG) { + Slog.d(TAG, "requestConnection :" + connect); + } synchronized (mLock) { if (connect == isConnected()) { return false; @@ -485,10 +491,6 @@ public class WindowMagnificationManager implements final boolean enabled; boolean previousEnabled; synchronized (mLock) { - if (mConnectionWrapper == null) { - Slog.w(TAG, "enableWindowMagnification failed: connection null"); - return false; - } WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); if (magnifier == null) { magnifier = createWindowMagnifier(displayId); @@ -528,10 +530,10 @@ public class WindowMagnificationManager implements final boolean disabled; synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); - if (magnifier == null || mConnectionWrapper == null) { - Slog.w(TAG, "disableWindowMagnification failed: connection " + mConnectionWrapper); + if (magnifier == null) { return false; } + disabled = magnifier.disableWindowMagnificationInternal(animationCallback); if (clear) { mWindowMagnifiers.delete(displayId); @@ -1018,25 +1020,33 @@ public class WindowMagnificationManager implements } } + @GuardedBy("mLock") private boolean enableWindowMagnificationInternal(int displayId, float scale, float centerX, float centerY, float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY, MagnificationAnimationCallback animationCallback) { - synchronized (mLock) { - return mConnectionWrapper != null && mConnectionWrapper.enableWindowMagnification( - displayId, scale, centerX, centerY, - magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY, - animationCallback); + if (mConnectionWrapper == null) { + Slog.w(TAG, "enableWindowMagnificationInternal mConnectionWrapper is null"); + return false; } + return mConnectionWrapper.enableWindowMagnification( + displayId, scale, centerX, centerY, + magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY, + animationCallback); } private boolean setScaleInternal(int displayId, float scale) { return mConnectionWrapper != null && mConnectionWrapper.setScale(displayId, scale); } + @GuardedBy("mLock") private boolean disableWindowMagnificationInternal(int displayId, MagnificationAnimationCallback animationCallback) { - return mConnectionWrapper != null && mConnectionWrapper.disableWindowMagnification( + if (mConnectionWrapper == null) { + Slog.w(TAG, "mConnectionWrapper is null"); + return false; + } + return mConnectionWrapper.disableWindowMagnification( displayId, animationCallback); } 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 c4040b405d19a..3c2fbd9ccf7de 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java @@ -27,6 +27,7 @@ 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.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -342,9 +343,58 @@ public class MagnificationProcessorTest { } @Test - public void setMagnificationConfig_controllingModeChangeAndAnimating_transitionConfigMode() { + public void setWindowModeConfig_fullScreenMode_transitionConfigMode() { + final int currentActivatedMode = MAGNIFICATION_MODE_FULLSCREEN; + final MagnificationConfig oldConfig = new MagnificationConfig.Builder() + .setMode(currentActivatedMode) + .setScale(TEST_SCALE) + .setCenterX(TEST_CENTER_X) + .setCenterY(TEST_CENTER_Y).build(); + setMagnificationActivated(TEST_DISPLAY, oldConfig); + final MagnificationConfig targetConfig = new MagnificationConfig.Builder() + .setMode(MAGNIFICATION_MODE_WINDOW) + .setScale(TEST_SCALE) + .setCenterX(TEST_CENTER_X + 10) + .setCenterY(TEST_CENTER_Y + 10).build(); + + mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, targetConfig, false, + SERVICE_ID); + + verify(mMockMagnificationController).transitionMagnificationConfigMode(eq(TEST_DISPLAY), + eq(targetConfig), eq(false), eq(SERVICE_ID)); + } + + @Test + public void setConfigWithDefaultMode_fullScreenMode_expectedConfig() { + final MagnificationConfig oldConfig = new MagnificationConfig.Builder() + .setMode(MAGNIFICATION_MODE_FULLSCREEN) + .setScale(TEST_SCALE) + .setCenterX(TEST_CENTER_X) + .setCenterY(TEST_CENTER_Y).build(); + setMagnificationActivated(TEST_DISPLAY, oldConfig); + final MagnificationConfig targetConfig = new MagnificationConfig.Builder() + .setScale(TEST_SCALE + 1) + .setCenterX(TEST_CENTER_X + 10) + .setCenterY(TEST_CENTER_Y + 10).build(); + + mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, targetConfig, false, + SERVICE_ID); + + verify(mMockMagnificationController, never()).transitionMagnificationConfigMode( + eq(TEST_DISPLAY), any(MagnificationConfig.class), eq(false), eq(SERVICE_ID)); + final MagnificationConfig expectedConfig = new MagnificationConfig.Builder() + .setMode(MAGNIFICATION_MODE_FULLSCREEN) + .setScale(TEST_SCALE + 1) + .setCenterX(TEST_CENTER_X + 10) + .setCenterY(TEST_CENTER_Y + 10).build(); + assertConfigEquals(expectedConfig, + mMagnificationProcessor.getMagnificationConfig(TEST_DISPLAY)); + } + + @Test + public void setWindowModeConfig_transitionToFullScreenModeWithAnimation_transitionConfigMode() { final int currentActivatedMode = MAGNIFICATION_MODE_WINDOW; - final int targetMode = MAGNIFICATION_MODE_FULLSCREEN; + final int targetMode = MAGNIFICATION_MODE_WINDOW; final MagnificationConfig oldConfig = new MagnificationConfig.Builder() .setMode(currentActivatedMode) .setScale(TEST_SCALE) @@ -356,17 +406,14 @@ public class MagnificationProcessorTest { .setScale(TEST_SCALE) .setCenterX(TEST_CENTER_X + 10) .setCenterY(TEST_CENTER_Y + 10).build(); - // Has magnification animation running when(mMockMagnificationController.hasDisableMagnificationCallback(TEST_DISPLAY)).thenReturn( true); - setMagnificationActivated(TEST_DISPLAY, newConfig); - final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig( - TEST_DISPLAY); + mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, newConfig, false, SERVICE_ID); + verify(mMockMagnificationController).transitionMagnificationConfigMode(eq(TEST_DISPLAY), eq(newConfig), anyBoolean(), anyInt()); - assertConfigEquals(newConfig, result); } private void setMagnificationActivated(int displayId, int configMode) { @@ -383,7 +430,7 @@ public class MagnificationProcessorTest { MAGNIFICATION_MODE_WINDOW)).thenReturn(false); mFullScreenMagnificationControllerStub.resetAndStubMethods(); mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(), - config.getCenterX(), config.getCenterY(), true, SERVICE_ID); + config.getCenterX(), config.getCenterY(), false, SERVICE_ID); } else if (config.getMode() == MAGNIFICATION_MODE_WINDOW) { when(mMockMagnificationController.isActivated(displayId, MAGNIFICATION_MODE_FULLSCREEN)).thenReturn(false); @@ -429,7 +476,7 @@ public class MagnificationProcessorTest { }; doAnswer(enableMagnificationStubAnswer).when( mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(), - anyFloat(), anyFloat(), eq(true), eq(SERVICE_ID)); + anyFloat(), anyFloat(), anyBoolean(), eq(SERVICE_ID)); Answer registerStubAnswer = invocation -> { mIsRegistered = true; @@ -444,6 +491,8 @@ public class MagnificationProcessorTest { }; doAnswer(unregisterStubAnswer).when( mScreenMagnificationController).unregister(eq(TEST_DISPLAY)); + doAnswer(unregisterStubAnswer).when( + mScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean()); } 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 064b762430579..3fcce92fe1417 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 @@ -20,6 +20,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; import static com.android.server.accessibility.AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID; +import static com.android.server.wm.WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -32,9 +33,9 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -80,7 +81,6 @@ public class MagnificationControllerTest { private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; private static final int TEST_SERVICE_ID = 1; - private static final Region MAGNIFICATION_REGION = new Region(0, 0, 500, 600); private static final Rect TEST_RECT = new Rect(0, 50, 100, 51); private static final float MAGNIFIED_CENTER_X = 100; private static final float MAGNIFIED_CENTER_Y = 200; @@ -109,7 +109,8 @@ public class MagnificationControllerTest { private WindowMagnificationManager mWindowMagnificationManager; private MockContentResolver mMockResolver; private MagnificationController mMagnificationController; - private FullScreenMagnificationControllerStubber mScreenMagnificationControllerStubber; + private final WindowMagnificationMgrCallbackDelegate mCallbackDelegate = + new WindowMagnificationMgrCallbackDelegate(); @Mock private WindowManagerInternal mMockWindowManagerInternal; @@ -141,17 +142,16 @@ public class MagnificationControllerTest { mScaleProvider = spy(new MagnificationScaleProvider(mContext)); mWindowMagnificationManager = Mockito.spy( new WindowMagnificationManager(mContext, globalLock, - mock(WindowMagnificationManager.Callback.class), mTraceManager, - mScaleProvider)); + mCallbackDelegate, mTraceManager, mScaleProvider)); mMockConnection = new MockWindowMagnificationConnection(true); mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mScreenMagnificationControllerStubber = new FullScreenMagnificationControllerStubber( - mScreenMagnificationController); + new FullScreenMagnificationControllerStubber(mScreenMagnificationController); mMagnificationController = new MagnificationController(mService, globalLock, mContext, mScreenMagnificationController, mWindowMagnificationManager, mScaleProvider); mMagnificationController.setMagnificationCapabilities( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); + mCallbackDelegate.setDelegate(mMagnificationController); } @After @@ -222,8 +222,10 @@ public class MagnificationControllerTest { MODE_WINDOW, mTransitionCallBack); - mMockConnection.invokeCallbacks(); - verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), + // The first time is triggered when window mode is activated, the second time is triggered + // when activating the window mode again. The third time is triggered when the transition is + // completed. + verify(mWindowMagnificationManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); } @@ -247,7 +249,8 @@ public class MagnificationControllerTest { @Test public void transitionToFullScreen_centerNotInTheBounds_magnifyBoundsCenter() throws RemoteException { - final Rect magnificationBounds = MAGNIFICATION_REGION.getBounds(); + final Rect magnificationBounds = + FullScreenMagnificationControllerStubber.MAGNIFICATION_REGION.getBounds(); final PointF magnifiedCenter = new PointF(magnificationBounds.right + 100, magnificationBounds.bottom + 100); setMagnificationEnabled(MODE_WINDOW, magnifiedCenter.x, magnifiedCenter.y); @@ -430,18 +433,21 @@ public class MagnificationControllerTest { } @Test - public void onSourceBoundsChanged_notifyMagnificationChanged() { - Rect rect = new Rect(0, 0, 100, 120); - Region region = new Region(rect); - - mMagnificationController.onSourceBoundsChanged(TEST_DISPLAY, rect); + public void enableWindowMode_notifyMagnificationChanged() throws RemoteException { + setMagnificationEnabled(MODE_WINDOW); final ArgumentCaptor configCaptor = ArgumentCaptor.forClass( MagnificationConfig.class); - verify(mService).notifyMagnificationChanged(eq(TEST_DISPLAY), eq(region), + final ArgumentCaptor regionCaptor = ArgumentCaptor.forClass( + Region.class); + verify(mService).notifyMagnificationChanged(eq(TEST_DISPLAY), regionCaptor.capture(), configCaptor.capture()); - assertEquals(rect.exactCenterX(), configCaptor.getValue().getCenterX(), 0); - assertEquals(rect.exactCenterY(), configCaptor.getValue().getCenterY(), 0); + + final Rect actualRect = regionCaptor.getValue().getBounds(); + final MagnificationConfig actualConfig = configCaptor.getValue(); + assertEquals(actualRect.exactCenterX(), actualConfig.getCenterX(), 0); + assertEquals(actualRect.exactCenterY(), actualConfig.getCenterY(), 0); + assertEquals(DEFAULT_SCALE, actualConfig.getScale(), 0); } @Test @@ -451,7 +457,8 @@ public class MagnificationControllerTest { mMagnificationController.onAccessibilityActionPerformed(TEST_DISPLAY); - verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), + // The first time is triggered when window mode is activated. + verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); } @@ -464,7 +471,8 @@ public class MagnificationControllerTest { mMagnificationController.onAccessibilityActionPerformed(TEST_DISPLAY); - verify(mWindowMagnificationManager).removeMagnificationButton(eq(TEST_DISPLAY)); + // The first time is triggered when window mode is activated. + verify(mWindowMagnificationManager, times(2)).removeMagnificationButton(eq(TEST_DISPLAY)); } @Test @@ -490,8 +498,7 @@ public class MagnificationControllerTest { public void onRectangleOnScreenRequested_fullScreenIsActivated_fullScreenDispatchEvent() { mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); - WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks - callbacks = getUiChangesForAccessibilityCallbacks(); + UiChangesForAccessibilityCallbacks callbacks = getUiChangesForAccessibilityCallbacks(); callbacks.onRectangleOnScreenRequested(TEST_DISPLAY, TEST_RECT.left, TEST_RECT.top, TEST_RECT.right, TEST_RECT.bottom); @@ -508,8 +515,7 @@ public class MagnificationControllerTest { true); mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, false); - WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks - callbacks = getUiChangesForAccessibilityCallbacks(); + UiChangesForAccessibilityCallbacks callbacks = getUiChangesForAccessibilityCallbacks(); callbacks.onRectangleOnScreenRequested(TEST_DISPLAY, TEST_RECT.left, TEST_RECT.top, TEST_RECT.right, TEST_RECT.bottom); @@ -522,8 +528,7 @@ public class MagnificationControllerTest { @Test public void onRectangleOnScreenRequested_NoneIsActivated_noneDispatchEvent() { - WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks - callbacks = getUiChangesForAccessibilityCallbacks(); + UiChangesForAccessibilityCallbacks callbacks = getUiChangesForAccessibilityCallbacks(); callbacks.onRectangleOnScreenRequested(TEST_DISPLAY, TEST_RECT.left, TEST_RECT.top, TEST_RECT.right, TEST_RECT.bottom); @@ -546,8 +551,7 @@ public class MagnificationControllerTest { } @Test - public void - onFullScreenMagnificationActivationState_fullScreenActivated_logFullScreenDuration() { + public void onFullScreenMagnificationActivationState_fullScreenEnabled_logFullScreenDuration() { MagnificationController spyController = spy(mMagnificationController); spyController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); @@ -596,7 +600,8 @@ public class MagnificationControllerTest { mMagnificationController.onTouchInteractionStart(TEST_DISPLAY, MODE_WINDOW); - verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), + // The first time is triggered when the window mode is activated. + verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); } @@ -607,7 +612,8 @@ public class MagnificationControllerTest { mMagnificationController.onTouchInteractionEnd(TEST_DISPLAY, MODE_WINDOW); - verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), + // The first time is triggered when the window mode is activated. + verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); } @@ -639,12 +645,10 @@ public class MagnificationControllerTest { } @Test - public void onWindowActivated_windowModeEnabledAndCapabilitiesAll_showMagnificationButton() + public void enableWindowMode_showMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); - mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, true); - verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); } @@ -661,18 +665,17 @@ public class MagnificationControllerTest { } @Test - public void onWindowDeactivated_windowModeInactive_removeMagnificationButton() + public void disableWindowMode_windowModeInActive_removeMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); - mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, false); + mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); verify(mWindowMagnificationManager).removeMagnificationButton(eq(TEST_DISPLAY)); } @Test - public void onFullScreenDeactivated_fullscreenModeInactive_removeMagnificationButton() + public void onFullScreenDeactivated_fullscreenModeInActive_removeMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_FULLSCREEN); mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, @@ -685,7 +688,7 @@ public class MagnificationControllerTest { } @Test - public void transitionToFullScreenMode_fullscreenModeActivated_showMagnificationButton() + public void transitionToFullScreenMode_fullscreenModeInActive_showMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); @@ -698,7 +701,7 @@ public class MagnificationControllerTest { } @Test - public void transitionToWindow_windowModeActivated_showMagnificationButton() + public void transitionToWindow_fullscreenModeInActive_showMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_FULLSCREEN); @@ -709,7 +712,10 @@ public class MagnificationControllerTest { mCallbackArgumentCaptor.capture()); mCallbackArgumentCaptor.getValue().onResult(true); mMockConnection.invokeCallbacks(); - verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), + + // The first time is triggered when window mode is activated, the second time is triggered + // when the disable-magnification callback is triggered. + verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); } @@ -784,7 +790,6 @@ public class MagnificationControllerTest { } private void activateMagnifier(int mode, float centerX, float centerY) throws RemoteException { - mScreenMagnificationControllerStubber.resetAndStubMethods(); final boolean windowMagnifying = mWindowMagnificationManager.isWindowMagnifierEnabled( TEST_DISPLAY); if (windowMagnifying) { @@ -806,13 +811,20 @@ public class MagnificationControllerTest { Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, mode, CURRENT_USER_ID); } - private MagnificationConfig obtainMagnificationConfig(int mode) { - return new MagnificationConfig.Builder().setMode(mode).setScale(DEFAULT_SCALE).setCenterX( - MAGNIFIED_CENTER_X).setCenterY(MAGNIFIED_CENTER_Y).build(); + private static MagnificationConfig obtainMagnificationConfig(int mode) { + return obtainMagnificationConfig(mode, true); } - private WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks - getUiChangesForAccessibilityCallbacks() { + private static MagnificationConfig obtainMagnificationConfig(int mode, boolean defaultScale) { + MagnificationConfig.Builder builder = new MagnificationConfig.Builder(); + if (defaultScale) { + builder = builder.setScale(DEFAULT_SCALE); + } + return builder.setMode(mode).setCenterX(MAGNIFIED_CENTER_X) + .setCenterY(MAGNIFIED_CENTER_Y).build(); + } + + private UiChangesForAccessibilityCallbacks getUiChangesForAccessibilityCallbacks() { ArgumentCaptor captor = ArgumentCaptor.forClass( WindowManagerInternal.AccessibilityControllerInternal @@ -822,21 +834,65 @@ public class MagnificationControllerTest { return captor.getValue(); } + private static class WindowMagnificationMgrCallbackDelegate implements + WindowMagnificationManager.Callback { + private WindowMagnificationManager.Callback mCallback; + + public void setDelegate(WindowMagnificationManager.Callback callback) { + mCallback = callback; + } + + @Override + public void onPerformScaleAction(int displayId, float scale) { + if (mCallback != null) { + mCallback.onPerformScaleAction(displayId, scale); + } + } + + @Override + public void onAccessibilityActionPerformed(int displayId) { + if (mCallback != null) { + mCallback.onAccessibilityActionPerformed(displayId); + } + } + + @Override + public void onWindowMagnificationActivationState(int displayId, boolean activated) { + if (mCallback != null) { + mCallback.onWindowMagnificationActivationState(displayId, activated); + } + } + + @Override + public void onSourceBoundsChanged(int displayId, Rect bounds) { + if (mCallback != null) { + mCallback.onSourceBoundsChanged(displayId, bounds); + } + } + + @Override + public void onChangeMagnificationMode(int displayId, int magnificationMode) { + if (mCallback != null) { + mCallback.onChangeMagnificationMode(displayId, magnificationMode); + } + } + } + /** - * Stubs public methods to simulate the real beahviours. + * Stubs public methods to simulate the real behaviours. */ private static class FullScreenMagnificationControllerStubber { + private static final Region MAGNIFICATION_REGION = new Region(0, 0, 500, 600); private final FullScreenMagnificationController mScreenMagnificationController; private boolean mIsMagnifying = false; private float mScale = 1.0f; - private float mCenterX = 0; - private float mCenterY = 0; + private float mCenterX = MAGNIFICATION_REGION.getBounds().exactCenterX(); + private float mCenterY = MAGNIFICATION_REGION.getBounds().exactCenterY(); private int mServiceId = -1; FullScreenMagnificationControllerStubber( FullScreenMagnificationController screenMagnificationController) { mScreenMagnificationController = screenMagnificationController; - resetCenter(); stubMethods(); } @@ -872,8 +928,7 @@ public class MagnificationControllerTest { mCenterY = invocation.getArgument(3); mServiceId = invocation.getArgument(5); } else { - mServiceId = -1; - resetCenter(); + reset(); } return true; }; @@ -886,26 +941,21 @@ public class MagnificationControllerTest { anyFloat(), anyFloat(), anyFloat(), anyBoolean(), anyInt()); Answer resetStubAnswer = invocation -> { - mScale = 1.0f; - mIsMagnifying = false; - mServiceId = -1; - resetCenter(); + reset(); return true; }; doAnswer(resetStubAnswer).when(mScreenMagnificationController).reset(eq(TEST_DISPLAY), - any()); + any(MagnificationAnimationCallback.class)); doAnswer(resetStubAnswer).when(mScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean()); } - private void resetCenter() { + private void reset() { + mScale = 1.0f; + mIsMagnifying = false; + mServiceId = -1; mCenterX = MAGNIFICATION_REGION.getBounds().exactCenterX(); mCenterY = MAGNIFICATION_REGION.getBounds().exactCenterY(); } - - public void resetAndStubMethods() { - Mockito.reset(mScreenMagnificationController); - stubMethods(); - } } } 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 8da513b50d657..0742c09492f2a 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 @@ -62,6 +62,7 @@ import com.android.server.statusbar.StatusBarManagerInternal; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; @@ -633,9 +634,15 @@ public class WindowMagnificationManagerTest { public void onWindowMagnificationActivationState_magnifierDisabled_notifyDeactivatedState() { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, true); + mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); verify(mMockCallback).onWindowMagnificationActivationState(TEST_DISPLAY, false); + + Mockito.reset(mMockCallback); + mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + + verify(mMockCallback, never()).onWindowMagnificationActivationState(eq(TEST_DISPLAY), + anyBoolean()); } private MotionEvent generatePointersDownEvent(PointF[] pointersLocation) {