diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index e521c90961fba..052ec86d83985 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -28,7 +28,6 @@ import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Bundle;
-import android.os.UserHandle;
import android.provider.Settings;
import android.util.MathUtils;
import android.view.Gravity;
@@ -75,6 +74,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
private final LayoutParams mParams;
+ private final SwitchListener mSwitchListener;
@VisibleForTesting
final Rect mDraggableWindowBounds = new Rect();
private boolean mIsVisible = false;
@@ -82,17 +82,29 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
private boolean mSingleTapDetected = false;
private boolean mToLeftScreenEdge = false;
- MagnificationModeSwitch(@UiContext Context context) {
- this(context, createView(context), new SfVsyncFrameCallbackProvider());
+ public interface SwitchListener {
+ /**
+ * Called when the switch is clicked to change the magnification mode.
+ * @param displayId the display id of the display to which the view's window has been
+ * attached
+ * @param magnificationMode the magnification mode
+ */
+ void onSwitch(int displayId, int magnificationMode);
+ }
+
+ MagnificationModeSwitch(@UiContext Context context,
+ SwitchListener switchListener) {
+ this(context, createView(context), new SfVsyncFrameCallbackProvider(), switchListener);
}
@VisibleForTesting
MagnificationModeSwitch(Context context, @NonNull ImageView imageView,
- SfVsyncFrameCallbackProvider sfVsyncFrameProvider) {
+ SfVsyncFrameCallbackProvider sfVsyncFrameProvider, SwitchListener switchListener) {
mContext = context;
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
mWindowManager = mContext.getSystemService(WindowManager.class);
mSfVsyncFrameProvider = sfVsyncFrameProvider;
+ mSwitchListener = switchListener;
mParams = createLayoutParams(context);
mImageView = imageView;
mImageView.setOnTouchListener(this::onTouch);
@@ -364,11 +376,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
mMagnificationMode ^ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
mMagnificationMode = newMode;
mImageView.setImageResource(getIconResId(newMode));
- Settings.Secure.putIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
- newMode,
- UserHandle.USER_CURRENT);
+ mSwitchListener.onSwitch(mContext.getDisplayId(), newMode);
}
private void handleSingleTap() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java
index 1a01ad85fccc2..5e48ee3d23664 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java
@@ -18,6 +18,8 @@ package com.android.systemui.accessibility;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
+import static com.android.systemui.accessibility.MagnificationModeSwitch.SwitchListener;
+
import android.annotation.MainThread;
import android.content.Context;
import android.hardware.display.DisplayManager;
@@ -27,21 +29,24 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.SysUISingleton;
/**
- * A class to control {@link MagnificationModeSwitch}. It should show the button UI with following
+ * A class to control {@link MagnificationModeSwitch}. It shows the button UI with following
* conditions:
*
* - Both full-screen and window magnification mode are capable.
* - The magnification scale is changed by a user.
*
+ * The switch action will be handled by {@link #mSwitchListenerDelegate} which informs the system
+ * server about the changed mode.
*/
@SysUISingleton
-public class ModeSwitchesController {
+public class ModeSwitchesController implements SwitchListener {
private final DisplayIdIndexSupplier mSwitchSupplier;
+ private SwitchListener mSwitchListenerDelegate;
public ModeSwitchesController(Context context) {
mSwitchSupplier = new SwitchSupplier(context,
- context.getSystemService(DisplayManager.class));
+ context.getSystemService(DisplayManager.class), this::onSwitch);
}
@VisibleForTesting
@@ -50,8 +55,8 @@ public class ModeSwitchesController {
}
/**
- * Shows a button that a user can click the button to switch magnification mode. And the
- * button would be dismissed automatically after the button is displayed for a period of time.
+ * Shows a button that a user can click to switch magnification mode. And the button
+ * would be dismissed automatically after the button is displayed for a period of time.
*
* @param displayId The logical display id
* @param mode The magnification mode
@@ -93,24 +98,41 @@ public class ModeSwitchesController {
switchController -> switchController.onConfigurationChanged(configDiff));
}
+ @Override
+ public void onSwitch(int displayId, int magnificationMode) {
+ if (mSwitchListenerDelegate != null) {
+ mSwitchListenerDelegate.onSwitch(displayId, magnificationMode);
+ }
+ }
+
+ public void setSwitchListenerDelegate(SwitchListener switchListenerDelegate) {
+ mSwitchListenerDelegate = switchListenerDelegate;
+ }
+
private static class SwitchSupplier extends DisplayIdIndexSupplier {
private final Context mContext;
+ private final SwitchListener mSwitchListener;
/**
+ * Supplies the switch for the given display.
+ *
* @param context Context
* @param displayManager DisplayManager
+ * @param switchListener The callback that will run when the switch is clicked
*/
- SwitchSupplier(Context context, DisplayManager displayManager) {
+ SwitchSupplier(Context context, DisplayManager displayManager,
+ SwitchListener switchListener) {
super(displayManager);
mContext = context;
+ mSwitchListener = switchListener;
}
@Override
protected MagnificationModeSwitch createInstance(Display display) {
final Context uiContext = mContext.createWindowContext(display,
TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null);
- return new MagnificationModeSwitch(uiContext);
+ return new MagnificationModeSwitch(uiContext, mSwitchListener);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 32813479dc0a2..d34ac71735efd 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -243,12 +243,15 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
mWindowMagnificationConnectionImpl = new WindowMagnificationConnectionImpl(this,
mHandler, mModeSwitchesController);
}
+ mModeSwitchesController.setSwitchListenerDelegate(
+ mWindowMagnificationConnectionImpl::onChangeMagnificationMode);
mAccessibilityManager.setWindowMagnificationConnection(
mWindowMagnificationConnectionImpl);
}
private void clearWindowMagnificationConnection() {
mAccessibilityManager.setWindowMagnificationConnection(null);
+ mModeSwitchesController.setSwitchListenerDelegate(null);
//TODO: destroy controllers.
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
index 2d620ab9e3c92..92cd8b183b62b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
@@ -130,4 +130,14 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S
}
}
}
+
+ void onChangeMagnificationMode(int displayId, int mode) {
+ if (mConnectionCallback != null) {
+ try {
+ mConnectionCallback.onChangeMagnificationMode(displayId, mode);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to inform changing magnification mode", e);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index fe5633eb9df8d..6ddfbb2f430f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -55,10 +55,9 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Handler;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.SparseIntArray;
import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.View;
@@ -101,6 +100,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
private AccessibilityManager mAccessibilityManager;
@Mock
private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
+ private SwitchListenerStub mSwitchListener;
private TestableWindowManager mWindowManager;
private ViewPropertyAnimator mViewPropertyAnimator;
private MagnificationModeSwitch mMagnificationModeSwitch;
@@ -112,6 +112,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
final WindowManager wm = mContext.getSystemService(WindowManager.class);
+ mSwitchListener = new SwitchListenerStub();
mWindowManager = spy(new TestableWindowManager(wm));
mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
@@ -130,7 +131,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
}).when(mSfVsyncFrameProvider).postFrameCallback(
any(Choreographer.FrameCallback.class));
mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView,
- mSfVsyncFrameProvider);
+ mSfVsyncFrameProvider, mSwitchListener);
assertNotNull(mTouchListener);
}
@@ -326,8 +327,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
public void performDragging_showMagnificationButton_updateViewLayout() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
- final int previousMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0, UserHandle.USER_CURRENT);
// Perform dragging
final int offset = ViewConfiguration.get(mContext).getScaledTouchSlop() + 10;
@@ -345,7 +344,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_UP, 100 + offset, 100));
- assertModeUnchanged(previousMode);
+ assertModeUnchanged();
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@@ -353,8 +352,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
public void performSingleTapActionCanceled_showButtonAnimation() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
- final int previousMode = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
final long downTime = SystemClock.uptimeMillis();
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
@@ -363,7 +360,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_CANCEL, 100, 100));
- assertModeUnchanged(previousMode);
+ assertModeUnchanged();
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@@ -371,8 +368,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
public void performDraggingActionCanceled_showButtonAnimation() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
- final int previousMode = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
// Perform dragging
final long downTime = SystemClock.uptimeMillis();
@@ -385,7 +380,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_CANCEL, 100 + offset, 100));
- assertModeUnchanged(previousMode);
+ assertModeUnchanged();
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@@ -529,10 +524,9 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
assertEquals(expectedY, mWindowManager.getLayoutParamsFromAttachedView().y);
}
- private void assertModeUnchanged(int expectedMode) {
- final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
- assertEquals(expectedMode, actualMode);
+ private void assertModeUnchanged() {
+ assertEquals(SwitchListenerStub.MODE_INVALID,
+ mSwitchListener.getChangedMode(mContext.getDisplayId()));
}
private void assertShowFadingAnimation(float alpha) {
@@ -594,9 +588,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
verify(mSpyImageView).setImageResource(
getIconResId(expectedMode));
verify(mWindowManager).removeView(mSpyImageView);
- final int actualMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0, UserHandle.USER_CURRENT);
- assertEquals(expectedMode, actualMode);
+ final int changedMode = mSwitchListener.getChangedMode(mContext.getDisplayId());
+ assertEquals(expectedMode, changedMode);
}
private MotionEvent obtainMotionEvent(long downTime, long eventTime, int action, float x,
@@ -621,4 +614,20 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
assertEquals(expectedX, layoutParams.x);
assertEquals(expectedY, layoutParams.y);
}
+
+ private static class SwitchListenerStub implements MagnificationModeSwitch.SwitchListener {
+
+ private static final int MODE_INVALID = -1;
+
+ private final SparseIntArray mModes = new SparseIntArray();
+
+ @Override
+ public void onSwitch(int displayId, int magnificationMode) {
+ mModes.put(displayId, magnificationMode);
+ }
+
+ int getChangedMode(int displayId) {
+ return mModes.get(displayId, MODE_INVALID);
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java
index 9fa5b87af3b45..216f63fce8858 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java
@@ -22,27 +22,32 @@ import android.content.pm.ActivityInfo;
import android.hardware.display.DisplayManager;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
import android.view.Display;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
/** Tests the ModeSwitchesController. */
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class ModeSwitchesControllerTest extends SysuiTestCase {
private FakeSwitchSupplier mSupplier;
- @Mock
private MagnificationModeSwitch mModeSwitch;
private ModeSwitchesController mModeSwitchesController;
+ @Mock
+ private MagnificationModeSwitch.SwitchListener mListener;
@Before
@@ -50,6 +55,13 @@ public class ModeSwitchesControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mSupplier = new FakeSwitchSupplier(mContext.getSystemService(DisplayManager.class));
mModeSwitchesController = new ModeSwitchesController(mSupplier);
+ mModeSwitchesController.setSwitchListenerDelegate(mListener);
+ mModeSwitch = Mockito.spy(new MagnificationModeSwitch(mContext, mModeSwitchesController));
+ }
+
+ @After
+ public void tearDown() {
+ mModeSwitchesController.removeButton(Display.DEFAULT_DISPLAY);
}
@Test
@@ -79,6 +91,18 @@ public class ModeSwitchesControllerTest extends SysuiTestCase {
verify(mModeSwitch).onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
}
+
+ @Test
+ public void testOnSwitchClick_showWindowModeButton_invokeListener() {
+ mModeSwitchesController.showButton(Display.DEFAULT_DISPLAY,
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+ mModeSwitch.onSingleTap();
+
+ verify(mListener).onSwitch(mContext.getDisplayId(),
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+ }
+
private class FakeSwitchSupplier extends DisplayIdIndexSupplier {
FakeSwitchSupplier(DisplayManager displayManager) {
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 6ef7cc3f0af8d..fb1716aed4748 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
@@ -22,6 +22,8 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_M
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -99,17 +101,19 @@ public class WindowMagnificationTest extends SysuiTestCase {
}
@Test
- public void requestWindowMagnificationConnection_setWindowMagnificationConnection() {
+ public void requestWindowMagnificationConnection_setConnectionAndListener() {
mCommandQueue.requestWindowMagnificationConnection(true);
waitForIdleSync();
verify(mAccessibilityManager).setWindowMagnificationConnection(any(
IWindowMagnificationConnection.class));
+ verify(mModeSwitchesController).setSwitchListenerDelegate(notNull());
mCommandQueue.requestWindowMagnificationConnection(false);
waitForIdleSync();
- verify(mAccessibilityManager).setWindowMagnificationConnection(null);
+ verify(mAccessibilityManager).setWindowMagnificationConnection(isNull());
+ verify(mModeSwitchesController).setSwitchListenerDelegate(isNull());
}
@Test
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 214769bbd9c98..0e39327991237 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -272,6 +272,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return getUserStateLocked(mCurrentUserId);
}
+ /**
+ * Changes the magnification mode on the given display.
+ *
+ * @param displayId the logical display
+ * @param magnificationMode the target magnification mode
+ */
+ public void changeMagnificationMode(int displayId, int magnificationMode) {
+ synchronized (mLock) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ persistMagnificationModeSettingsLocked(magnificationMode);
+ } else {
+ final AccessibilityUserState userState = getCurrentUserStateLocked();
+ final int currentMode = userState.getMagnificationModeLocked(displayId);
+ if (magnificationMode != currentMode) {
+ userState.setMagnificationModeLocked(displayId, magnificationMode);
+ updateMagnificationModeChangeSettingsLocked(userState, displayId);
+ }
+ }
+ }
+ }
+
public static final class Lifecycle extends SystemService {
private final AccessibilityManagerService mService;
@@ -299,7 +320,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
SystemActionPerformer systemActionPerformer,
AccessibilityWindowManager a11yWindowManager,
AccessibilityDisplayListener a11yDisplayListener,
- MagnificationController magnificationController) {
+ MagnificationController magnificationController,
+ @Nullable AccessibilityInputFilter inputFilter) {
mContext = context;
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
@@ -314,6 +336,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mA11yDisplayListener = a11yDisplayListener;
mMagnificationController = magnificationController;
mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
+ if (inputFilter != null) {
+ mInputFilter = inputFilter;
+ mHasInputFilter = true;
+ }
init();
}
@@ -1794,47 +1820,51 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return relevantEventTypes;
}
- private void updateMagnificationModeChangeSettingsLocked(AccessibilityUserState userState) {
+ private void updateMagnificationModeChangeSettingsLocked(AccessibilityUserState userState,
+ int displayId) {
if (userState.mUserId != mCurrentUserId) {
return;
}
// New mode is invalid, so ignore and restore it.
- if (fallBackMagnificationModeSettingsLocked(userState)) {
+ if (fallBackMagnificationModeSettingsLocked(userState, displayId)) {
return;
}
mMagnificationController.transitionMagnificationModeLocked(
- Display.DEFAULT_DISPLAY, userState.getMagnificationModeLocked(),
+ displayId, userState.getMagnificationModeLocked(displayId),
this::onMagnificationTransitionEndedLocked);
}
/**
- * Called when the magnification mode transition is completed.
+ * Called when the magnification mode transition is completed. If the given display is default
+ * display, we also need to fall back the mode in user settings.
*/
- void onMagnificationTransitionEndedLocked(boolean success) {
+ void onMagnificationTransitionEndedLocked(int displayId, boolean success) {
final AccessibilityUserState userState = getCurrentUserStateLocked();
- final int previousMode = userState.getMagnificationModeLocked()
+ final int previousMode = userState.getMagnificationModeLocked(displayId)
^ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
if (!success && previousMode != 0) {
- userState.setMagnificationModeLocked(previousMode);
- persistMagnificationModeSettingLocked(previousMode);
+ userState.setMagnificationModeLocked(displayId, previousMode);
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ persistMagnificationModeSettingsLocked(previousMode);
+ }
} else {
mMainHandler.sendMessage(obtainMessage(
AccessibilityManagerService::notifyRefreshMagnificationModeToInputFilter,
- this));
+ this, displayId));
}
}
- private void notifyRefreshMagnificationModeToInputFilter() {
+ private void notifyRefreshMagnificationModeToInputFilter(int displayId) {
synchronized (mLock) {
if (!mHasInputFilter) {
return;
}
- // TODO: notify the mode change on specified display.
final ArrayList displays = getValidDisplayList();
for (int i = 0; i < displays.size(); i++) {
final Display display = displays.get(i);
- if (display != null) {
+ if (display != null && display.getDisplayId() == displayId) {
mInputFilter.refreshMagnificationMode(display);
+ return;
}
}
}
@@ -2245,12 +2275,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
scheduleUpdateClientsIfNeededLocked(userState);
updateAccessibilityShortcutKeyTargetsLocked(userState);
updateAccessibilityButtonTargetsLocked(userState);
- // Update the capabilities before the mode.
+ // Update the capabilities before the mode because we will check the current mode is
+ // invalid or not..
updateMagnificationCapabilitiesSettingsChangeLocked(userState);
- updateMagnificationModeChangeSettingsLocked(userState);
+ updateMagnificationModeChangeSettingsForAllDisplaysLocked(userState);
updateFocusAppearanceDataLocked(userState);
}
+ private void updateMagnificationModeChangeSettingsForAllDisplaysLocked(
+ AccessibilityUserState userState) {
+ final ArrayList displays = getValidDisplayList();
+ for (int i = 0; i < displays.size(); i++) {
+ final int displayId = displays.get(i).getDisplayId();
+ updateMagnificationModeChangeSettingsLocked(userState, displayId);
+ }
+ }
+
private void updateWindowsForAccessibilityCallbackLocked(AccessibilityUserState userState) {
// We observe windows for accessibility only if there is at least
// one bound service that can retrieve window content that specified
@@ -2348,7 +2388,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
somethingChanged |= readAccessibilityButtonTargetsLocked(userState);
somethingChanged |= readAccessibilityButtonTargetComponentLocked(userState);
somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
- somethingChanged |= readMagnificationModeLocked(userState);
+ somethingChanged |= readMagnificationModeForDefaultDisplayLocked(userState);
somethingChanged |= readMagnificationCapabilitiesLocked(userState);
return somethingChanged;
}
@@ -3878,8 +3918,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|| mUserInteractiveUiTimeoutUri.equals(uri)) {
readUserRecommendedUiTimeoutSettingsLocked(userState);
} else if (mMagnificationModeUri.equals(uri)) {
- if (readMagnificationModeLocked(userState)) {
- updateMagnificationModeChangeSettingsLocked(userState);
+ if (readMagnificationModeForDefaultDisplayLocked(userState)) {
+ updateMagnificationModeChangeSettingsLocked(userState,
+ Display.DEFAULT_DISPLAY);
}
} else if (mMagnificationCapabilityUri.equals(uri)) {
if (readMagnificationCapabilitiesLocked(userState)) {
@@ -3892,8 +3933,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private void updateMagnificationCapabilitiesSettingsChangeLocked(
AccessibilityUserState userState) {
- if (fallBackMagnificationModeSettingsLocked(userState)) {
- updateMagnificationModeChangeSettingsLocked(userState);
+ final ArrayList displays = getValidDisplayList();
+ for (int i = 0; i < displays.size(); i++) {
+ final int displayId = displays.get(i).getDisplayId();
+ if (fallBackMagnificationModeSettingsLocked(userState, displayId)) {
+ updateMagnificationModeChangeSettingsLocked(userState, displayId);
+ }
}
updateWindowMagnificationConnectionIfNeeded(userState);
// Remove magnification button UI when the magnification capability is not all mode or
@@ -3902,7 +3947,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|| userState.isShortcutMagnificationEnabledLocked())
|| userState.getMagnificationCapabilitiesLocked()
!= Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL) {
- final ArrayList displays = getValidDisplayList();
+
for (int i = 0; i < displays.size(); i++) {
final int displayId = displays.get(i).getDisplayId();
getWindowMagnificationMgr().removeMagnificationButton(displayId);
@@ -3910,18 +3955,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
- private boolean fallBackMagnificationModeSettingsLocked(AccessibilityUserState userState) {
- if (userState.isValidMagnificationModeLocked()) {
+ private boolean fallBackMagnificationModeSettingsLocked(AccessibilityUserState userState,
+ int displayId) {
+ if (userState.isValidMagnificationModeLocked(displayId)) {
return false;
}
- Slog.w(LOG_TAG, "invalid magnification mode:" + userState.getMagnificationModeLocked());
+ Slog.w(LOG_TAG, "displayId " + displayId + ", invalid magnification mode:"
+ + userState.getMagnificationModeLocked(displayId));
final int capabilities = userState.getMagnificationCapabilitiesLocked();
- userState.setMagnificationModeLocked(capabilities);
- persistMagnificationModeSettingLocked(capabilities);
+ userState.setMagnificationModeLocked(displayId, capabilities);
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ persistMagnificationModeSettingsLocked(capabilities);
+ }
return true;
}
- private void persistMagnificationModeSettingLocked(int mode) {
+ private void persistMagnificationModeSettingsLocked(int mode) {
BackgroundThread.getHandler().post(() -> {
final long identity = Binder.clearCallingIdentity();
try {
@@ -3933,7 +3982,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
});
}
- //TODO: support multi-display.
/**
* Gets the magnification mode of the specified display.
*
@@ -3943,17 +3991,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
*/
public int getMagnificationMode(int displayId) {
synchronized (mLock) {
- return getCurrentUserStateLocked().getMagnificationModeLocked();
+ return getCurrentUserStateLocked().getMagnificationModeLocked(displayId);
}
}
- private boolean readMagnificationModeLocked(AccessibilityUserState userState) {
+ // Only the value of the default display is from user settings because not each of displays has
+ // a unique id.
+ private boolean readMagnificationModeForDefaultDisplayLocked(AccessibilityUserState userState) {
final int magnificationMode = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, userState.mUserId);
- if (magnificationMode != userState.getMagnificationModeLocked()) {
- userState.setMagnificationModeLocked(magnificationMode);
+ if (magnificationMode != userState.getMagnificationModeLocked(Display.DEFAULT_DISPLAY)) {
+ userState.setMagnificationModeLocked(Display.DEFAULT_DISPLAY, magnificationMode);
return true;
}
return false;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index c70bf73fc7f5d..8c3ca3430a3aa 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -23,6 +23,7 @@ import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
import static android.view.accessibility.AccessibilityManager.ShortcutType;
@@ -42,6 +43,7 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.SparseIntArray;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;
@@ -122,8 +124,8 @@ class AccessibilityUserState {
/** {@code true} if the device config supports magnification area. */
private final boolean mSupportMagnificationArea;
- // The magnification mode of default display.
- private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+ // The magnification modes on displays.
+ private final SparseIntArray mMagnificationModes = new SparseIntArray();
// The magnification capabilities used to know magnification mode could be switched.
private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
@@ -141,12 +143,13 @@ class AccessibilityUserState {
@SoftKeyboardShowMode
private int mSoftKeyboardShowMode = SHOW_MODE_AUTO;
- boolean isValidMagnificationModeLocked() {
+ boolean isValidMagnificationModeLocked(int displayId) {
+ final int mode = getMagnificationModeLocked(displayId);
if (!mSupportMagnificationArea
- && mMagnificationMode == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
+ && mode == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
return false;
}
- return (mMagnificationCapabilities & mMagnificationMode) != 0;
+ return (mMagnificationCapabilities & mode) != 0;
}
interface ServiceInfoChangeListener {
@@ -203,7 +206,7 @@ class AccessibilityUserState {
mIsAutoclickEnabled = false;
mUserNonInteractiveUiTimeout = 0;
mUserInteractiveUiTimeout = 0;
- mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+ mMagnificationModes.clear();
mFocusStrokeWidth = mFocusStrokeWidthDefaultValue;
mFocusColor = mFocusColorDefaultValue;
}
@@ -500,7 +503,7 @@ class AccessibilityUserState {
pw.append(", nonInteractiveUiTimeout=").append(String.valueOf(mNonInteractiveUiTimeout));
pw.append(", interactiveUiTimeout=").append(String.valueOf(mInteractiveUiTimeout));
pw.append(", installedServiceCount=").append(String.valueOf(mInstalledServices.size()));
- pw.append(", magnificationMode=").append(String.valueOf(mMagnificationMode));
+ pw.append(", magnificationModes=").append(String.valueOf(mMagnificationModes));
pw.append(", magnificationCapabilities=")
.append(String.valueOf(mMagnificationCapabilities));
pw.append("}");
@@ -635,14 +638,19 @@ class AccessibilityUserState {
}
/**
- * Gets the magnification mode of default display.
+ * Gets the magnification mode for the given display.
* @return magnification mode
*
* @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
* @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW
*/
- public int getMagnificationModeLocked() {
- return mMagnificationMode;
+ public int getMagnificationModeLocked(int displayId) {
+ int mode = mMagnificationModes.get(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_NONE);
+ if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_NONE) {
+ mode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+ setMagnificationModeLocked(displayId, mode);
+ }
+ return mode;
}
@@ -671,11 +679,13 @@ class AccessibilityUserState {
}
/**
- * Sets the magnification mode of default display.
+ * Sets the magnification mode to the given display.
+ *
+ * @param displayId The display id.
* @param mode The magnification mode.
*/
- public void setMagnificationModeLocked(int mode) {
- mMagnificationMode = mode;
+ public void setMagnificationModeLocked(int displayId, int mode) {
+ mMagnificationModes.put(displayId, mode);
}
/**
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 935df9934dcbb..966d887d11f7a 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -208,8 +208,8 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
}
mPromptController.onDestroy();
// Check if need to reset when MagnificationGestureHandler is the last magnifying service.
- mFullScreenMagnificationController.resetAllIfNeeded(
- AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ mFullScreenMagnificationController.resetIfNeeded(
+ mDisplayId, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
clearAndTransitionToStateDetecting();
}
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 3708c7a422a0d..6473bf5ffc3ef 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -92,14 +92,16 @@ public class MagnificationController implements WindowMagnificationManager.Callb
private long mFullScreenModeEnabledTime = 0;
/**
- * A callback to inform the magnification transition result.
+ * A callback to inform the magnification transition result on the given display.
*/
public interface TransitionCallBack {
/**
* Invoked when the transition ends.
+ *
+ * @param displayId The display id.
* @param success {@code true} if the transition success.
*/
- void onResult(boolean success);
+ void onResult(int displayId, boolean success);
}
public MagnificationController(AccessibilityManagerService ams, Object lock,
@@ -179,7 +181,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
final DisableMagnificationCallback animationCallback =
getDisableMagnificationEndRunnableLocked(displayId);
if (magnificationCenter == null && animationCallback == null) {
- transitionCallBack.onResult(true);
+ transitionCallBack.onResult(displayId, true);
return;
}
@@ -195,7 +197,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
if (magnificationCenter == null) {
Slog.w(TAG, "Invalid center, ignore it");
- transitionCallBack.onResult(true);
+ transitionCallBack.onResult(displayId, true);
return;
}
final FullScreenMagnificationController screenMagnificationController =
@@ -251,6 +253,11 @@ public class MagnificationController implements WindowMagnificationManager.Callb
updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
}
+ @Override
+ public void onChangeMagnificationMode(int displayId, int magnificationMode) {
+ mAms.changeMagnificationMode(displayId, magnificationMode);
+ }
+
private void disableFullScreenMagnificationIfNeeded(int displayId) {
final FullScreenMagnificationController fullScreenMagnificationController =
getFullScreenMagnificationController();
@@ -514,7 +521,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
applyMagnificationModeLocked(mTargetMode);
}
updateMagnificationButton(mDisplayId, mTargetMode);
- mTransitionCallBack.onResult(success);
+ mTransitionCallBack.onResult(mDisplayId, success);
}
}
@@ -539,7 +546,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
setExpiredAndRemoveFromListLocked();
applyMagnificationModeLocked(mCurrentMode);
updateMagnificationButton(mDisplayId, mCurrentMode);
- mTransitionCallBack.onResult(true);
+ mTransitionCallBack.onResult(mDisplayId, true);
}
}
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 ce7ba7568b6e4..bfaab9a0aa709 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -106,6 +106,15 @@ public class WindowMagnificationManager implements
* @param activated {@code true} if the magnification is activated, otherwise {@code false}.
*/
void onWindowMagnificationActivationState(int displayId, boolean activated);
+
+ /**
+ * Called from {@link IWindowMagnificationConnection} to request changing the magnification
+ * mode on the given display.
+ *
+ * @param displayId the logical display id
+ * @param magnificationMode the target magnification mode
+ */
+ void onChangeMagnificationMode(int displayId, int magnificationMode);
}
private final Callback mCallback;
@@ -535,7 +544,7 @@ public class WindowMagnificationManager implements
FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
"displayId=" + displayId + ";mode=" + magnificationMode);
}
- //TODO: Uses this method to change the magnification mode on non-default display.
+ mCallback.onChangeMagnificationMode(displayId, magnificationMode);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index ae2b8dc2add7a..3ade9ff617356 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -16,13 +16,22 @@
package com.android.server.accessibility;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -38,17 +47,23 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
import android.graphics.drawable.Icon;
+import android.hardware.display.DisplayManagerGlobal;
import android.os.IBinder;
import android.provider.Settings;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableContext;
+import android.view.Display;
+import android.view.DisplayAdjustments;
+import android.view.DisplayInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.TestUtils;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener;
+import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.MagnificationController;
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.accessibility.test.MessageCapturingHandler;
@@ -58,10 +73,16 @@ import com.android.server.wm.WindowManagerInternal;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+
/**
* APCT tests for {@link AccessibilityManagerService}.
*/
@@ -72,7 +93,8 @@ public class AccessibilityManagerServiceTest {
private static final String INTENT_ACTION = "TESTACTION";
private static final String DESCRIPTION = "description";
private static final PendingIntent TEST_PENDING_INTENT = PendingIntent.getBroadcast(
- InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION),
+ PendingIntent.FLAG_MUTABLE_UNAUDITED);
private static final RemoteAction TEST_ACTION = new RemoteAction(
Icon.createWithContentUri("content://test"),
LABEL,
@@ -81,11 +103,12 @@ public class AccessibilityManagerServiceTest {
private static final AccessibilityAction NEW_ACCESSIBILITY_ACTION =
new AccessibilityAction(ACTION_ID, LABEL);
+ private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY + 1;
+
static final ComponentName COMPONENT_NAME = new ComponentName(
"com.android.server.accessibility", "AccessibilityManagerServiceTest");
static final int SERVICE_ID = 42;
- @Mock private Context mMockContext;
@Mock private AccessibilityServiceInfo mMockServiceInfo;
@Mock private ResolveInfo mMockResolveInfo;
@Mock private AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport;
@@ -102,12 +125,15 @@ public class AccessibilityManagerServiceTest {
@Mock private IAccessibilityServiceClient mMockServiceClient;
@Mock private WindowMagnificationManager mMockWindowMagnificationMgr;
@Mock private MagnificationController mMockMagnificationController;
- @Mock private Resources mMockResources;
+ @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController;
- private AccessibilityUserState mUserState;
+ @Rule
+ public final TestableContext mTestableContext = new TestableContext(
+ getInstrumentation().getTargetContext(), null);
private MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
private AccessibilityServiceConnection mAccessibilityServiceConnection;
+ private AccessibilityInputFilter mInputFilter;
private AccessibilityManagerService mA11yms;
@Before
@@ -122,43 +148,54 @@ public class AccessibilityManagerServiceTest {
ActivityTaskManagerInternal.class, mMockActivityTaskManagerInternal);
LocalServices.addService(
UserManagerInternal.class, mMockUserManagerInternal);
+ mInputFilter = Mockito.mock(FakeInputFilter.class);
when(mMockMagnificationController.getWindowMagnificationMgr()).thenReturn(
mMockWindowMagnificationMgr);
+ when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn(
+ mMockFullScreenMagnificationController);
when(mMockWindowManagerService.getAccessibilityController()).thenReturn(
mMockA11yController);
when(mMockA11yController.isAccessibilityTracingEnabled()).thenReturn(false);
when(mMockUserManagerInternal.isUserUnlockingOrUnlocked(anyInt())).thenReturn(true);
+
+ final ArrayList displays = new ArrayList<>();
+ final Display defaultDisplay = new Display(DisplayManagerGlobal.getInstance(),
+ Display.DEFAULT_DISPLAY, new DisplayInfo(),
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ final Display testDisplay = new Display(DisplayManagerGlobal.getInstance(), TEST_DISPLAY,
+ new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ displays.add(defaultDisplay);
+ displays.add(testDisplay);
+ when(mMockA11yDisplayListener.getValidDisplayList()).thenReturn(displays);
+
mA11yms = new AccessibilityManagerService(
- InstrumentationRegistry.getContext(),
- mMockPackageManager,
- mMockSecurityPolicy,
- mMockSystemActionPerformer,
- mMockA11yWindowManager,
- mMockA11yDisplayListener,
- mMockMagnificationController);
+ mTestableContext,
+ mMockPackageManager,
+ mMockSecurityPolicy,
+ mMockSystemActionPerformer,
+ mMockA11yWindowManager,
+ mMockA11yDisplayListener,
+ mMockMagnificationController,
+ mInputFilter);
- mMockResources = mock(Resources.class);
- when(mMockContext.getResources()).thenReturn(mMockResources);
-
- mUserState = new AccessibilityUserState(
- mA11yms.getCurrentUserIdLocked(), mMockContext, mA11yms);
- mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), mUserState);
+ final AccessibilityUserState userState = new AccessibilityUserState(
+ mA11yms.getCurrentUserIdLocked(), mTestableContext, mA11yms);
+ mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), userState);
}
private void setupAccessibilityServiceConnection() {
- when(mMockContext.getSystemService(Context.DISPLAY_SERVICE)).thenReturn(
- InstrumentationRegistry.getContext().getSystemService(
- Context.DISPLAY_SERVICE));
-
+ final AccessibilityUserState userState = mA11yms.mUserStates.get(
+ mA11yms.getCurrentUserIdLocked());
when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
mMockResolveInfo.serviceInfo = mock(ServiceInfo.class);
mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
when(mMockBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient);
+ mTestableContext.addMockService(COMPONENT_NAME, mMockBinder);
mAccessibilityServiceConnection = new AccessibilityServiceConnection(
- mUserState,
- mMockContext,
+ userState,
+ mTestableContext,
COMPONENT_NAME,
mMockServiceInfo,
SERVICE_ID,
@@ -172,7 +209,6 @@ public class AccessibilityManagerServiceTest {
mMockA11yWindowManager,
mMockActivityTaskManagerInternal);
mAccessibilityServiceConnection.bindLocked();
- mAccessibilityServiceConnection.onServiceConnected(COMPONENT_NAME, mMockBinder);
}
@SmallTest
@@ -220,7 +256,10 @@ public class AccessibilityManagerServiceTest {
@Test
public void testOnSystemActionsChanged() throws Exception {
setupAccessibilityServiceConnection();
- mA11yms.notifySystemActionsChangedLocked(mUserState);
+ final AccessibilityUserState userState = mA11yms.mUserStates.get(
+ mA11yms.getCurrentUserIdLocked());
+
+ mA11yms.notifySystemActionsChangedLocked(userState);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
verify(mMockServiceClient).onSystemActionsChanged();
}
@@ -228,24 +267,89 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
public void testOnMagnificationTransitionFailed_capabilitiesIsAll_fallBackToPreviousMode() {
+ final AccessibilityUserState userState = mA11yms.mUserStates.get(
+ mA11yms.getCurrentUserIdLocked());
+ userState.setMagnificationCapabilitiesLocked(ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
+ userState.setMagnificationModeLocked(Display.DEFAULT_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
+ );
+
+ mA11yms.onMagnificationTransitionEndedLocked(Display.DEFAULT_DISPLAY, false);
+
+ Assert.assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+ userState.getMagnificationModeLocked(Display.DEFAULT_DISPLAY));
+ }
+
+ @SmallTest
+ @Test
+ public void testOnMagnificationTransitionSuccess_capabilitiesIsAll_inputFilterRefreshMode() {
final AccessibilityUserState userState = mA11yms.mUserStates.get(
mA11yms.getCurrentUserIdLocked());
userState.setMagnificationCapabilitiesLocked(
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
- userState.setMagnificationModeLocked(
- Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+ ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
+ userState.setMagnificationModeLocked(Display.DEFAULT_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
+ );
- mA11yms.onMagnificationTransitionEndedLocked(false);
+ mA11yms.onMagnificationTransitionEndedLocked(Display.DEFAULT_DISPLAY, true);
- Assert.assertEquals(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
- userState.getMagnificationModeLocked());
+ ArgumentCaptor displayCaptor = ArgumentCaptor.forClass(Display.class);
+ verify(mInputFilter, timeout(100)).refreshMagnificationMode(displayCaptor.capture());
+ Assert.assertEquals(Display.DEFAULT_DISPLAY, displayCaptor.getValue().getDisplayId());
+ }
+
+ @SmallTest
+ @Test
+ public void testChangeMagnificationModeOnDefaultDisplay_capabilitiesIsAll_persistChangedMode()
+ throws Exception {
+ final AccessibilityUserState userState = mA11yms.mUserStates.get(
+ mA11yms.getCurrentUserIdLocked());
+ userState.setMagnificationCapabilitiesLocked(
+ ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
+ userState.setMagnificationModeLocked(Display.DEFAULT_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
+ );
+
+ mA11yms.changeMagnificationMode(Display.DEFAULT_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+ TestUtils.waitUntil("magnification mode " + ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW
+ + " is not persisted in setting", 1,
+ () -> {
+ final int userMode = Settings.Secure.getIntForUser(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
+ ACCESSIBILITY_MAGNIFICATION_MODE_NONE,
+ mA11yms.getCurrentUserIdLocked());
+ return userMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+ });
+ }
+
+ @SmallTest
+ @Test
+ public void testChangeMagnificationModeOnTestDisplay_capabilitiesIsAll_transitMode() {
+ final AccessibilityUserState userState = mA11yms.mUserStates.get(
+ mA11yms.getCurrentUserIdLocked());
+ userState.setMagnificationCapabilitiesLocked(
+ ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
+ userState.setMagnificationModeLocked(TEST_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
+ );
+
+ mA11yms.changeMagnificationMode(TEST_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+ verify(mMockMagnificationController).transitionMagnificationModeLocked(eq(TEST_DISPLAY),
+ eq(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW), ArgumentMatchers.isNotNull());
}
@SmallTest
@Test
public void testOnClientChange_magnificationEnabledAndCapabilityAll_requestConnection() {
- mUserState.mAccessibilityShortcutKeyTargets.add(MAGNIFICATION_CONTROLLER_NAME);
- mUserState.setMagnificationCapabilitiesLocked(
+ final AccessibilityUserState userState = mA11yms.mUserStates.get(
+ mA11yms.getCurrentUserIdLocked());
+ userState.mAccessibilityShortcutKeyTargets.add(MAGNIFICATION_CONTROLLER_NAME);
+ userState.setMagnificationCapabilitiesLocked(
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
// Invokes client change to trigger onUserStateChanged.
@@ -265,4 +369,11 @@ public class AccessibilityManagerServiceTest {
verify(mMockWindowMagnificationMgr).requestConnection(true);
}
+
+ public static class FakeInputFilter extends AccessibilityInputFilter {
+ FakeInputFilter(Context context,
+ AccessibilityManagerService service) {
+ super(context, service);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index 81ca92cc3c8cf..b9d94edc5981f 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -48,6 +48,7 @@ import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.testing.DexmakerShareClassLoaderRule;
import android.util.ArraySet;
+import android.view.Display;
import androidx.test.InstrumentationRegistry;
@@ -79,6 +80,8 @@ public class AccessibilityUserStateTest {
private static final int USER_ID = 42;
+ private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY;
+
// Mock package-private class AccessibilityServiceConnection
@Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
@@ -143,7 +146,8 @@ public class AccessibilityUserStateTest {
mUserState.setAutoclickEnabledLocked(true);
mUserState.setUserNonInteractiveUiTimeoutLocked(30);
mUserState.setUserInteractiveUiTimeoutLocked(30);
- mUserState.setMagnificationModeLocked(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+ mUserState.setMagnificationModeLocked(TEST_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mUserState.setFocusAppearanceLocked(20, Color.BLUE);
mUserState.onSwitchToAnotherUserLocked();
@@ -165,7 +169,7 @@ public class AccessibilityUserStateTest {
assertEquals(0, mUserState.getUserNonInteractiveUiTimeoutLocked());
assertEquals(0, mUserState.getUserInteractiveUiTimeoutLocked());
assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
- mUserState.getMagnificationModeLocked());
+ mUserState.getMagnificationModeLocked(TEST_DISPLAY));
assertEquals(mFocusStrokeWidthDefaultValue, mUserState.getFocusStrokeWidthLocked());
assertEquals(mFocusColorDefaultValue, mUserState.getFocusColorLocked());
}
@@ -360,12 +364,13 @@ public class AccessibilityUserStateTest {
@Test
public void setWindowMagnificationMode_returnExpectedMagnificationMode() {
assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
- mUserState.getMagnificationModeLocked());
+ mUserState.getMagnificationModeLocked(TEST_DISPLAY));
- mUserState.setMagnificationModeLocked(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+ mUserState.setMagnificationModeLocked(TEST_DISPLAY,
+ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
- mUserState.getMagnificationModeLocked());
+ mUserState.getMagnificationModeLocked(TEST_DISPLAY));
}
@Test
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 69061c14c70e0..8a521d8a74900 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
@@ -150,7 +150,7 @@ public class MagnificationControllerTest {
MODE_WINDOW,
mTransitionCallBack);
- verify(mTransitionCallBack).onResult(true);
+ verify(mTransitionCallBack).onResult(TEST_DISPLAY, true);
verify(mScreenMagnificationController, never()).reset(anyInt(),
any(MagnificationAnimationCallback.class));
verify(mMockConnection.getConnection(), never()).enableWindowMagnification(anyInt(),
@@ -171,7 +171,7 @@ public class MagnificationControllerTest {
mCallbackArgumentCaptor.capture());
mCallbackArgumentCaptor.getValue().onResult(true);
mMockConnection.invokeCallbacks();
- verify(mTransitionCallBack).onResult(true);
+ verify(mTransitionCallBack).onResult(TEST_DISPLAY, true);
assertEquals(MAGNIFIED_CENTER_X, mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 0);
assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0);
}
@@ -189,7 +189,7 @@ public class MagnificationControllerTest {
mTransitionCallBack);
mMockConnection.invokeCallbacks();
- verify(mTransitionCallBack).onResult(true);
+ verify(mTransitionCallBack).onResult(TEST_DISPLAY, true);
assertEquals(MAGNIFIED_CENTER_X, mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 0);
assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0);
}
@@ -225,7 +225,7 @@ public class MagnificationControllerTest {
verify(mScreenMagnificationController).setScaleAndCenter(TEST_DISPLAY,
DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
true, MAGNIFICATION_GESTURE_HANDLER_ID);
- verify(mTransitionCallBack).onResult(true);
+ verify(mTransitionCallBack).onResult(TEST_DISPLAY, true);
}
@Test
@@ -245,7 +245,7 @@ public class MagnificationControllerTest {
verify(mScreenMagnificationController).setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE,
magnificationBounds.exactCenterX(), magnificationBounds.exactCenterY(), true,
MAGNIFICATION_GESTURE_HANDLER_ID);
- verify(mTransitionCallBack).onResult(true);
+ verify(mTransitionCallBack).onResult(TEST_DISPLAY, true);
}
@Test
@@ -265,7 +265,7 @@ public class MagnificationControllerTest {
0);
assertEquals(MAGNIFIED_CENTER_Y, mScreenMagnificationController.getCenterY(TEST_DISPLAY),
0);
- verify(mTransitionCallBack).onResult(true);
+ verify(mTransitionCallBack).onResult(TEST_DISPLAY, true);
}
@Test
@@ -285,7 +285,7 @@ public class MagnificationControllerTest {
verify(mScreenMagnificationController, never()).setScaleAndCenter(TEST_DISPLAY,
DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
true, MAGNIFICATION_GESTURE_HANDLER_ID);
- verify(mTransitionCallBack).onResult(false);
+ verify(mTransitionCallBack).onResult(TEST_DISPLAY, false);
}
@Test
@@ -595,6 +595,13 @@ public class MagnificationControllerTest {
verify(mScaleProvider).onUserRemoved(SECOND_USER_ID);
}
+ @Test
+ public void onChangeMagnificationMode_delegateToService() {
+ mMagnificationController.onChangeMagnificationMode(TEST_DISPLAY, MODE_WINDOW);
+
+ verify(mService).changeMagnificationMode(TEST_DISPLAY, MODE_WINDOW);
+ }
+
private void setMagnificationEnabled(int mode) throws RemoteException {
setMagnificationEnabled(mode, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
}