From 80a35549c84d053efa9df0d74958db0f79bda7b9 Mon Sep 17 00:00:00 2001 From: mincheli Date: Wed, 24 Mar 2021 17:49:26 +0800 Subject: [PATCH] Updates magnification button after an accessibility action is performed To switch magnification mode, a user has to click the magnifcation button UI. However magnification button UI is visible only when there is an user touch interaction or the magnification shortcut triggered event. However some a11y services like switch-access or voice-access can only interact with magnification UI by performing accessibility actions. To make magnification button showing and able to interact with a user, we also trigger updating magnification button UI when an accessibility action is performed. Bug: 179442890 Test: atest WindowMagnificationControllerTest; atest WindowMagnificationTest;atest MagnificationControllerTest;atest WindowMagnificationManagerTest Change-Id: I8d762096c9cb6a4421d024a7a1af99b3a48a3462 --- ...WindowMagnificationConnectionCallback.aidl | 7 ++++ .../accessibility/WindowMagnification.java | 7 ++++ .../WindowMagnificationConnectionImpl.java | 10 +++++ .../WindowMagnificationController.java | 26 +++++-------- .../WindowMagnifierCallback.java | 7 ++++ .../WindowMagnificationControllerTest.java | 13 +++++++ .../WindowMagnificationTest.java | 10 +++++ .../MagnificationController.java | 37 ++++++++++++++----- .../WindowMagnificationManager.java | 16 ++++++-- .../MagnificationControllerTest.java | 23 ++++++++++++ .../WindowMagnificationManagerTest.java | 11 ++++++ 11 files changed, 138 insertions(+), 29 deletions(-) diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl index d0ab004d6cf34..1cb6825e426e0 100644 --- a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl +++ b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl @@ -60,4 +60,11 @@ import android.graphics.Rect; */ void onPerformScaleAction(int displayId, float scale); + /** + * Called when the accessibility action is performed. + * + * @param displayId The logical display id. + */ + void onAccessibilityActionPerformed(int displayId); + } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index cdd69429132ac..4f5fdc90e9298 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -194,6 +194,13 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall } } + @Override + public void onAccessibilityActionPerformed(int displayId) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onAccessibilityActionPerformed(displayId); + } + } + @Override public void requestWindowMagnificationConnection(boolean connect) { if (connect) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java index be7d757244425..2d620ab9e3c92 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java @@ -120,4 +120,14 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S } } } + + void onAccessibilityActionPerformed(int displayId) { + if (mConnectionCallback != null) { + try { + mConnectionCallback.onAccessibilityActionPerformed(displayId); + } catch (RemoteException e) { + Log.e(TAG, "Failed to inform an accessibility action is already performed", e); + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 2b666f13efcca..48beea3804a41 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -756,31 +756,23 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold final float scale = mScale + A11Y_CHANGE_SCALE_DIFFERENCE; mWindowMagnifierCallback.onPerformScaleAction(mDisplayId, A11Y_ACTION_SCALE_RANGE.clamp(scale)); - return true; - } - if (action == R.id.accessibility_action_zoom_out) { + } else if (action == R.id.accessibility_action_zoom_out) { final float scale = mScale - A11Y_CHANGE_SCALE_DIFFERENCE; mWindowMagnifierCallback.onPerformScaleAction(mDisplayId, A11Y_ACTION_SCALE_RANGE.clamp(scale)); - return true; - } - if (action == R.id.accessibility_action_move_up) { + } else if (action == R.id.accessibility_action_move_up) { move(0, -mSourceBounds.height()); - return true; - } - if (action == R.id.accessibility_action_move_down) { + } else if (action == R.id.accessibility_action_move_down) { move(0, mSourceBounds.height()); - return true; - } - if (action == R.id.accessibility_action_move_left) { + } else if (action == R.id.accessibility_action_move_left) { move(-mSourceBounds.width(), 0); - return true; - } - if (action == R.id.accessibility_action_move_right) { + } else if (action == R.id.accessibility_action_move_right) { move(mSourceBounds.width(), 0); - return true; + } else { + return false; } - return false; + mWindowMagnifierCallback.onAccessibilityActionPerformed(mDisplayId); + return true; } } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java index fb1d1b6d7816d..628a5e88b89e2 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java @@ -46,4 +46,11 @@ interface WindowMagnifierCallback { * @param scale the target scale, or {@link Float#NaN} to leave unchanged */ void onPerformScaleAction(int displayId, float scale); + + /** + * Called when the accessibility action is performed. + * + * @param displayId The logical display id. + */ + void onAccessibilityActionPerformed(int displayId); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 9659610e71150..d3a2d2e3b5cc6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -302,6 +302,19 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_left, null)); } + @Test + public void performA11yActions_visible_notifyAccessibilityActionPerformed() { + final int displayId = mContext.getDisplayId(); + mInstrumentation.runOnMainSync(() -> { + mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN, + Float.NaN); + }); + + mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_up, null); + + verify(mWindowMagnifierCallback).onAccessibilityActionPerformed(eq(displayId)); + } + @Test public void onNavigationModeChanged_updateMirrorViewLayout() { mInstrumentation.runOnMainSync(() -> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java index ad1ce76cc36c0..78331143af94d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java @@ -117,6 +117,16 @@ public class WindowMagnificationTest extends SysuiTestCase { eq(newScale)); } + @Test + public void onAccessibilityActionPerformed_enabled_notifyCallback() throws RemoteException { + mCommandQueue.requestWindowMagnificationConnection(true); + waitForIdleSync(); + + mWindowMagnification.onAccessibilityActionPerformed(Display.DEFAULT_DISPLAY); + + verify(mConnectionCallback).onAccessibilityActionPerformed(eq(Display.DEFAULT_DISPLAY)); + } + @Test public void onConfigurationChanged_updateModeSwitches() { final Configuration config = new Configuration(); 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 878ebc5bbfbde..41f75a7da36f0 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -115,6 +115,11 @@ public class MagnificationController implements WindowMagnificationManager.Callb getWindowMagnificationMgr().persistScale(displayId); } + @Override + public void onAccessibilityActionPerformed(int displayId) { + updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + } + @Override public void onTouchInteractionStart(int displayId, int mode) { handleUserInteractionChanged(displayId, mode); @@ -145,8 +150,13 @@ public class MagnificationController implements WindowMagnificationManager.Callb } private void updateMagnificationButton(int displayId, int mode) { - if (isActivated(displayId, mode) && mMagnificationCapabilities - == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL) { + final boolean isActivated = isActivated(displayId, mode); + final boolean showButton; + synchronized (mLock) { + showButton = isActivated && mMagnificationCapabilities + == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL; + } + if (showButton) { getWindowMagnificationMgr().showMagnificationButton(displayId, mode); } else { getWindowMagnificationMgr().removeMagnificationButton(displayId); @@ -414,13 +424,22 @@ public class MagnificationController implements WindowMagnificationManager.Callb private boolean isActivated(int displayId, int mode) { boolean isActivated = false; - if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN - && mFullScreenMagnificationController != null) { - isActivated = mFullScreenMagnificationController.isMagnifying(displayId) - || mFullScreenMagnificationController.isForceShowMagnifiableBounds(displayId); - } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW - && mWindowMagnificationMgr != null) { - isActivated = mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId); + if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { + synchronized (mLock) { + if (mFullScreenMagnificationController == null) { + return false; + } + isActivated = mFullScreenMagnificationController.isMagnifying(displayId) + || mFullScreenMagnificationController.isForceShowMagnifiableBounds( + displayId); + } + } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { + synchronized (mLock) { + if (mWindowMagnificationMgr == null) { + return false; + } + isActivated = mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId); + } } return isActivated; } 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 ded601e70ff12..7af4d48d887ab 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -94,6 +94,13 @@ public class WindowMagnificationManager implements */ void onPerformScaleAction(int displayId, float scale); + /** + * Called when the accessibility action is performed. + * + * @param displayId The logical display id. + */ + void onAccessibilityActionPerformed(int displayId); + /** * Called when the state of the magnification activation is changed. * @@ -535,9 +542,12 @@ public class WindowMagnificationManager implements @Override public void onPerformScaleAction(int displayId, float scale) { - synchronized (mLock) { - mCallback.onPerformScaleAction(displayId, scale); - } + mCallback.onPerformScaleAction(displayId, scale); + } + + @Override + public void onAccessibilityActionPerformed(int displayId) { + mCallback.onAccessibilityActionPerformed(displayId); } @Override 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 3dff36e8f379d..697a2e4987051 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 @@ -303,6 +303,29 @@ public class MagnificationControllerTest { verify(mWindowMagnificationManager).persistScale(eq(TEST_DISPLAY)); } + @Test + public void onAccessibilityActionPerformed_magnifierEnabled_showMagnificationButton() + throws RemoteException { + setMagnificationEnabled(MODE_WINDOW); + + mMagnificationController.onAccessibilityActionPerformed(TEST_DISPLAY); + + verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), + eq(MODE_WINDOW)); + } + + @Test + public void onAccessibilityActionPerformed_capabilityNotAll_removeMagnificationButton() + throws RemoteException { + mMagnificationController.setMagnificationCapabilities( + ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + setMagnificationEnabled(MODE_WINDOW); + + mMagnificationController.onAccessibilityActionPerformed(TEST_DISPLAY); + + verify(mWindowMagnificationManager).removeMagnificationButton(eq(TEST_DISPLAY)); + } + @Test public void onWindowMagnificationActivationState_windowActivated_logWindowDuration() { mMagnificationController.onWindowMagnificationActivationState(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 955217c7d93f8..898ff9527512c 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 @@ -312,6 +312,17 @@ public class WindowMagnificationManagerTest { verify(mMockCallback).onPerformScaleAction(eq(TEST_DISPLAY), eq(newScale)); } + @Test + public void onAccessibilityActionPerformed_magnifierEnabled_notifyAction() + throws RemoteException { + mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); + + mMockConnection.getConnectionCallback().onAccessibilityActionPerformed(TEST_DISPLAY); + + verify(mMockCallback).onAccessibilityActionPerformed(eq(TEST_DISPLAY)); + } + @Test public void binderDied_windowMagnifierIsEnabled_resetState() throws RemoteException { mWindowMagnificationManager.setConnection(mMockConnection.getConnection());