From 24ecf0226aebba6ef9710502c4c3b5fe2388a674 Mon Sep 17 00:00:00 2001 From: Roy Chou Date: Fri, 3 Feb 2023 13:48:53 +0000 Subject: [PATCH] feat(#AlwaysOnMagnifier)!: Support always on feature in A11y controllers Support always on feature in MagnificationController/AccessibilityController/AccessibilityUserState. It would check AlwaysOnMagnificationFeatureFlag and Settings to decide whether to enable always on feature. If both feature flag and settings preference are true, we would enable the always on feature in FullScreenMagnificationController. Otherwise the feature is disabled. Bug: 146504200 Test: manual atest MagnificationControllerTest atest AccessibilityManagerServiceTest atest AccessibilityUserStateTest Change-Id: Ie0ecf6276ac2323d05ddf6b185ba34d33bc8dd7d --- .../AccessibilityManagerService.java | 26 +++++++++++++ .../accessibility/AccessibilityUserState.java | 13 +++++++ .../MagnificationController.java | 13 +++++++ .../AccessibilityManagerServiceTest.java | 37 +++++++++++++++++++ .../AccessibilityUserStateTest.java | 10 +++++ .../MagnificationControllerTest.java | 7 ++++ 6 files changed, 106 insertions(+) diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 776405d23035e..7e4567b91d2e0 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -2725,6 +2725,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub somethingChanged |= readMagnificationModeForDefaultDisplayLocked(userState); somethingChanged |= readMagnificationCapabilitiesLocked(userState); somethingChanged |= readMagnificationFollowTypingLocked(userState); + somethingChanged |= readAlwaysOnMagnificationLocked(userState); somethingChanged |= readUiContrastLocked(userState); return somethingChanged; } @@ -4378,6 +4379,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private final Uri mMagnificationFollowTypingUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED); + // TODO: replace name with Settings Secure Key + private final Uri mAlwaysOnMagnificationUri = Settings.Secure.getUriFor( + "accessibility_magnification_always_on_enabled"); + private final Uri mUiContrastUri = Settings.Secure.getUriFor( CONTRAST_LEVEL); @@ -4421,6 +4426,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mMagnificationCapabilityUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( mMagnificationFollowTypingUri, false, this, UserHandle.USER_ALL); + contentResolver.registerContentObserver( + mAlwaysOnMagnificationUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( mUiContrastUri, false, this, UserHandle.USER_ALL); } @@ -4492,6 +4499,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } else if (mMagnificationFollowTypingUri.equals(uri)) { readMagnificationFollowTypingLocked(userState); + } else if (mAlwaysOnMagnificationUri.equals(uri)) { + readAlwaysOnMagnificationLocked(userState); } else if (mUiContrastUri.equals(uri)) { if (readUiContrastLocked(userState)) { updateUiContrastLocked(userState); @@ -4605,6 +4614,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return false; } + boolean readAlwaysOnMagnificationLocked(AccessibilityUserState userState) { + // TODO: replace name const with Settings Secure Key + final boolean isSettingsAlwaysOnEnabled = Settings.Secure.getIntForUser( + mContext.getContentResolver(), + "accessibility_magnification_always_on_enabled", + 0, userState.mUserId) == 1; + final boolean isAlwaysOnFeatureFlagEnabled = mMagnificationController + .isAlwaysOnMagnificationFeatureFlagEnabled(); + final boolean isAlwaysOnEnabled = isAlwaysOnFeatureFlagEnabled && isSettingsAlwaysOnEnabled; + if (isAlwaysOnEnabled != userState.isAlwaysOnMagnificationEnabled()) { + userState.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled); + mMagnificationController.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled); + return true; + } + return false; + } + @Override public void setGestureDetectionPassthroughRegion(int displayId, Region region) { mMainHandler.sendMessage( diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java index 43730fce0cb7a..1c9ce3c827356 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java @@ -136,6 +136,8 @@ class AccessibilityUserState { private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; // Whether the following typing focus feature for magnification is enabled. private boolean mMagnificationFollowTypingEnabled = true; + // Whether the always on magnification feature is enabled. + private boolean mAlwaysOnMagnificationEnabled = false; /** The stroke width of the focus rectangle in pixels */ private int mFocusStrokeWidth; @@ -221,6 +223,7 @@ class AccessibilityUserState { mFocusStrokeWidth = mFocusStrokeWidthDefaultValue; mFocusColor = mFocusColorDefaultValue; mMagnificationFollowTypingEnabled = true; + mAlwaysOnMagnificationEnabled = false; mUiContrast = CONTRAST_NOT_SET; } @@ -531,6 +534,8 @@ class AccessibilityUserState { .append(String.valueOf(mIsAudioDescriptionByDefaultRequested)); pw.append(", magnificationFollowTypingEnabled=") .append(String.valueOf(mMagnificationFollowTypingEnabled)); + pw.append(", alwaysOnMagnificationEnabled=") + .append(String.valueOf(mAlwaysOnMagnificationEnabled)); pw.append("}"); pw.println(); pw.append(" shortcut key:{"); @@ -711,6 +716,14 @@ class AccessibilityUserState { return mMagnificationFollowTypingEnabled; } + public void setAlwaysOnMagnificationEnabled(boolean enabled) { + mAlwaysOnMagnificationEnabled = enabled; + } + + public boolean isAlwaysOnMagnificationEnabled() { + return mAlwaysOnMagnificationEnabled; + } + /** * Sets the magnification mode to the given display. * 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 558c71b11c864..a6e6bd7d7b664 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -677,6 +677,19 @@ public class MagnificationController implements WindowMagnificationManager.Callb getFullScreenMagnificationController().setMagnificationFollowTypingEnabled(enabled); } + /** + * Called when the always on magnification feature is switched. + * + * @param enabled Enable the always on magnification feature + */ + public void setAlwaysOnMagnificationEnabled(boolean enabled) { + getFullScreenMagnificationController().setAlwaysOnMagnificationEnabled(enabled); + } + + public boolean isAlwaysOnMagnificationFeatureFlagEnabled() { + return AlwaysOnMagnificationFeatureFlag.isAlwaysOnMagnificationEnabled(); + } + private DisableMagnificationCallback getDisableMagnificationEndRunnableLocked( int displayId) { return mMagnificationEndRunnableSparseArray.get(displayId); 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 4d1d2b22ed345..32b98647e78b4 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java @@ -34,6 +34,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; @@ -438,6 +439,42 @@ public class AccessibilityManagerServiceTest { verify(mMockMagnificationController).setMagnificationFollowTypingEnabled(false); } + @Test + public void testSettingsAlwaysOn_setEnabled_featureFlagDisabled_doNothing() { + when(mMockMagnificationController.isAlwaysOnMagnificationFeatureFlagEnabled()) + .thenReturn(false); + + final AccessibilityUserState userState = mA11yms.mUserStates.get( + mA11yms.getCurrentUserIdLocked()); + Settings.Secure.putIntForUser( + mTestableContext.getContentResolver(), + // TODO: replace name with Settings Secure Key + "accessibility_magnification_always_on_enabled", + 1, mA11yms.getCurrentUserIdLocked()); + + mA11yms.readAlwaysOnMagnificationLocked(userState); + + verify(mMockMagnificationController, never()).setAlwaysOnMagnificationEnabled(anyBoolean()); + } + + @Test + public void testSettingsAlwaysOn_setEnabled_featureFlagEnabled_propagateToController() { + when(mMockMagnificationController.isAlwaysOnMagnificationFeatureFlagEnabled()) + .thenReturn(true); + + final AccessibilityUserState userState = mA11yms.mUserStates.get( + mA11yms.getCurrentUserIdLocked()); + Settings.Secure.putIntForUser( + mTestableContext.getContentResolver(), + // TODO: replace name with Settings Secure Key + "accessibility_magnification_always_on_enabled", + 1, mA11yms.getCurrentUserIdLocked()); + + mA11yms.readAlwaysOnMagnificationLocked(userState); + + verify(mMockMagnificationController).setAlwaysOnMagnificationEnabled(eq(true)); + } + @SmallTest @Test public void testOnClientChange_magnificationEnabledAndCapabilityAll_requestConnection() { 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 ed0336a5a4ea7..b4558b211fc68 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java @@ -179,6 +179,7 @@ public class AccessibilityUserStateTest { assertEquals(mFocusStrokeWidthDefaultValue, mUserState.getFocusStrokeWidthLocked()); assertEquals(mFocusColorDefaultValue, mUserState.getFocusColorLocked()); assertTrue(mUserState.isMagnificationFollowTypingEnabled()); + assertFalse(mUserState.isAlwaysOnMagnificationEnabled()); } @Test @@ -389,6 +390,15 @@ public class AccessibilityUserStateTest { assertFalse(mUserState.isMagnificationFollowTypingEnabled()); } + @Test + public void setAlwaysOnMagnificationEnabled_defaultFalseAndSetTrue_returnTrue() { + assertFalse(mUserState.isAlwaysOnMagnificationEnabled()); + + mUserState.setAlwaysOnMagnificationEnabled(true); + + assertTrue(mUserState.isAlwaysOnMagnificationEnabled()); + } + @Test public void setFocusAppearanceData_returnExpectedFocusAppearanceData() { final int focusStrokeWidthValue = 100; 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 407c575fd6d03..b4a16c2da517f 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 @@ -738,6 +738,13 @@ public class MagnificationControllerTest { verify(mScreenMagnificationController).setMagnificationFollowTypingEnabled(eq(false)); } + @Test + public void setPreferenceAlwaysOnMagnificationEnabled_setPrefEnabled_enableOnFullScreen() { + mMagnificationController.setAlwaysOnMagnificationEnabled(true); + + verify(mScreenMagnificationController).setAlwaysOnMagnificationEnabled(eq(true)); + } + @Test public void onRectangleOnScreenRequested_fullScreenIsActivated_fullScreenDispatchEvent() { mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY,