From 97550d060bdf368327fb10fcb6364e39694dcd06 Mon Sep 17 00:00:00 2001 From: Roy Chou Date: Thu, 13 Apr 2023 09:54:17 +0000 Subject: [PATCH] fix(#Magnification): magnification gesture handler might not be activated after config transition If the magnification mode transition is triggered by magnification config, the AccessibilityManagerService would not be notified. It might cause some issues. 1. The AccessibilityUserState would stay in old/wrong mode not same as current mode 2. the AccessibilityInputFilter would not be notified, and thus it would not switch to the corresponding magnification gesture handler Therefore, in MagnificationController#transitionMagnificationConfigMode, we adjust to notify the service the mode changed, and the service would notify the userState and inputFilter as its original behavior. Bug: 278031878 Test: manually atest MagnificationControllerTest Change-Id: I7d567873b35eefd7a5a515cb7692d48413a7dd9d --- .../MagnificationController.java | 18 ++++++-- .../MagnificationControllerTest.java | 43 +++++++++++++++++-- 2 files changed, 55 insertions(+), 6 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 22e742bc09731..c1c47f53ab7ec 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -231,6 +231,12 @@ public class MagnificationController implements WindowMagnificationManager.Callb */ public void transitionMagnificationModeLocked(int displayId, int targetMode, @NonNull TransitionCallBack transitionCallBack) { + // check if target mode is already activated + if (isActivated(displayId, targetMode)) { + transitionCallBack.onResult(displayId, true); + return; + } + final PointF currentCenter = getCurrentMagnificationCenterLocked(displayId, targetMode); final DisableMagnificationCallback animationCallback = getDisableMagnificationEndRunnableLocked(displayId); @@ -322,13 +328,16 @@ public class MagnificationController implements WindowMagnificationManager.Callb : config.getScale(); try { setTransitionState(displayId, targetMode); + final MagnificationAnimationCallback magnificationAnimationCallback = animate + ? success -> mAms.changeMagnificationMode(displayId, targetMode) + : null; // Activate or deactivate target mode depending on config activated value if (targetMode == MAGNIFICATION_MODE_WINDOW) { screenMagnificationController.reset(displayId, false); if (targetActivated) { windowMagnificationMgr.enableWindowMagnification(displayId, targetScale, magnificationCenter.x, magnificationCenter.y, - animate ? STUB_ANIMATION_CALLBACK : null, id); + magnificationAnimationCallback, id); } else { windowMagnificationMgr.disableWindowMagnification(displayId, false); } @@ -339,8 +348,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb screenMagnificationController.register(displayId); } screenMagnificationController.setScaleAndCenter(displayId, targetScale, - magnificationCenter.x, magnificationCenter.y, animate, - id); + magnificationCenter.x, magnificationCenter.y, + magnificationAnimationCallback, id); } else { if (screenMagnificationController.isRegistered(displayId)) { screenMagnificationController.reset(displayId, false); @@ -348,6 +357,9 @@ public class MagnificationController implements WindowMagnificationManager.Callb } } } finally { + if (!animate) { + mAms.changeMagnificationMode(displayId, targetMode); + } // Reset transition state after enabling target mode. setTransitionState(displayId, null); } 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 913d8c1dda20b..11e4120e77e68 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 @@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -435,9 +436,9 @@ public class MagnificationControllerTest { mMockConnection.invokeCallbacks(); assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); - verify(mScreenMagnificationController).setScaleAndCenter(TEST_DISPLAY, - DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, - animate, TEST_SERVICE_ID); + verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), + eq(DEFAULT_SCALE), eq(MAGNIFIED_CENTER_X), eq(MAGNIFIED_CENTER_Y), + any(MagnificationAnimationCallback.class), eq(TEST_SERVICE_ID)); } @Test @@ -503,6 +504,42 @@ public class MagnificationControllerTest { 0); } + @Test + public void configTransitionToFullScreenWithAnimation_windowMagnifying_notifyService() + throws RemoteException { + final boolean animate = true; + activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y); + + reset(mService); + MagnificationConfig config = (new MagnificationConfig.Builder()) + .setMode(MODE_FULLSCREEN).build(); + mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, + config, animate, TEST_SERVICE_ID); + verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), + /* scale= */ anyFloat(), /* centerX= */ anyFloat(), /* centerY= */ anyFloat(), + mCallbackArgumentCaptor.capture(), /* id= */ anyInt()); + mCallbackArgumentCaptor.getValue().onResult(true); + mMockConnection.invokeCallbacks(); + + verify(mService).changeMagnificationMode(TEST_DISPLAY, MODE_FULLSCREEN); + } + + @Test + public void configTransitionToFullScreenWithoutAnimation_windowMagnifying_notifyService() + throws RemoteException { + final boolean animate = false; + activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y); + + reset(mService); + MagnificationConfig config = (new MagnificationConfig.Builder()) + .setMode(MODE_FULLSCREEN).build(); + mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, + config, animate, TEST_SERVICE_ID); + mMockConnection.invokeCallbacks(); + + verify(mService).changeMagnificationMode(TEST_DISPLAY, MODE_FULLSCREEN); + } + @Test public void interruptDuringTransitionToWindow_disablingFullScreen_discardPreviousTransition() throws RemoteException {