Loading core/java/android/view/accessibility/flags/accessibility_flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,16 @@ flag { } } flag { name: "restore_a11y_secure_settings_on_hsum_device" namespace: "accessibility" description: "Grab the a11y settings and send the settings restored broadcast for current visible foreground user" bug: "381294327" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "supplemental_description" namespace: "accessibility" Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +41 −13 Original line number Diff line number Diff line Loading @@ -101,21 +101,26 @@ public class SettingsHelper { */ private static final ArraySet<String> sBroadcastOnRestore; private static final ArraySet<String> sBroadcastOnRestoreSystemUI; private static final ArraySet<String> sBroadcastOnRestoreAccessibility; static { sBroadcastOnRestore = new ArraySet<String>(12); sBroadcastOnRestore = new ArraySet<>(7); sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS); sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); sBroadcastOnRestore.add(Settings.Global.BLUETOOTH_ON); sBroadcastOnRestore.add(Settings.Secure.UI_NIGHT_MODE); sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_START_TIME); sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_END_TIME); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); sBroadcastOnRestore.add(Settings.Secure.SCREEN_RESOLUTION_MODE); sBroadcastOnRestoreSystemUI = new ArraySet<String>(2); sBroadcastOnRestoreAccessibility = new ArraySet<>(5); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); sBroadcastOnRestoreAccessibility.add( Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); sBroadcastOnRestoreSystemUI = new ArraySet<>(2); sBroadcastOnRestoreSystemUI.add(Settings.Secure.QS_TILES); sBroadcastOnRestoreSystemUI.add(Settings.Secure.QS_AUTO_ADDED_TILES); } Loading Loading @@ -188,6 +193,7 @@ public class SettingsHelper { String oldValue = null; boolean sendBroadcast = false; boolean sendBroadcastSystemUI = false; boolean sendBroadcastAccessibility = false; final SettingsLookup table; if (destination.equals(Settings.Secure.CONTENT_URI)) { Loading @@ -200,6 +206,7 @@ public class SettingsHelper { sendBroadcast = sBroadcastOnRestore.contains(name); sendBroadcastSystemUI = sBroadcastOnRestoreSystemUI.contains(name); sendBroadcastAccessibility = sBroadcastOnRestoreAccessibility.contains(name); if (sendBroadcast) { // TODO: http://b/22388012 Loading @@ -209,6 +216,10 @@ public class SettingsHelper { // It would probably be correct to do it for the ones sent to the system, but consumers // may be depending on the current behavior. oldValue = table.lookup(cr, name, context.getUserId()); } else if (sendBroadcastAccessibility) { int userId = android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice() ? context.getUserId() : UserHandle.USER_SYSTEM; oldValue = table.lookup(cr, name, userId); } try { Loading Loading @@ -251,11 +262,7 @@ public class SettingsHelper { } else if (Settings.System.ACCELEROMETER_ROTATION.equals(name) && shouldSkipAutoRotateRestore()) { return; } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(name)) { // Don't write it to setting. Let the broadcast receiver in // AccessibilityManagerService handle restore/merging logic. return; } else if (Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE.equals(name)) { } else if (shouldSkipAndLetBroadcastHandlesRestoreLogic(name)) { // Don't write it to setting. Let the broadcast receiver in // AccessibilityManagerService handle restore/merging logic. return; Loading Loading @@ -287,12 +294,13 @@ public class SettingsHelper { // If we fail to apply the setting, by definition nothing happened sendBroadcast = false; sendBroadcastSystemUI = false; sendBroadcastAccessibility = false; Log.e(TAG, "Failed to restore setting name: " + name + " + value: " + value, e); } finally { // If this was an element of interest, send the "we just restored it" // broadcast with the historical value now that the new value has // been committed and observers kicked off. if (sendBroadcast || sendBroadcastSystemUI) { if (sendBroadcast || sendBroadcastSystemUI || sendBroadcastAccessibility) { Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) .putExtra(Intent.EXTRA_SETTING_NAME, name) Loading @@ -309,6 +317,13 @@ public class SettingsHelper { context.getString(com.android.internal.R.string.config_systemUi)); context.sendBroadcastAsUser(intent, context.getUser(), null); } if (sendBroadcastAccessibility) { UserHandle userHandle = android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice() ? context.getUser() : UserHandle.SYSTEM; intent.setPackage("android"); context.sendBroadcastAsUser(intent, userHandle, null); } } } } Loading Loading @@ -474,6 +489,19 @@ public class SettingsHelper { } } private boolean shouldSkipAndLetBroadcastHandlesRestoreLogic(String settingName) { boolean restoreHandledByBroadcast = Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals( settingName) || Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE.equals(settingName); if (android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice()) { restoreHandledByBroadcast |= Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(settingName) || Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(settingName); } return restoreHandledByBroadcast; } private void setAutoRestore(boolean enabled) { try { IBackupManager bm = IBackupManager.Stub.asInterface( Loading packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java +51 −34 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.provider.SettingsStringUtil; import android.view.accessibility.Flags; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; Loading @@ -41,7 +42,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import java.util.concurrent.ExecutionException; Loading @@ -54,17 +54,17 @@ import java.util.concurrent.ExecutionException; public class SettingsHelperRestoreTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); public final BroadcastInterceptingContext mInterceptingContext = new BroadcastInterceptingContext( InstrumentationRegistry.getInstrumentation().getContext()); private static final float FLOAT_TOLERANCE = 0.01f; private Context mContext; private ContentResolver mContentResolver; private SettingsHelper mSettingsHelper; @Before public void setUp() { mContext = InstrumentationRegistry.getInstrumentation().getContext(); mContentResolver = mContext.getContentResolver(); mSettingsHelper = new SettingsHelper(mContext); mContentResolver = mInterceptingContext.getContentResolver(); mSettingsHelper = new SettingsHelper(mInterceptingContext); } @After Loading @@ -73,6 +73,8 @@ public class SettingsHelperRestoreTest { Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0); Settings.Secure.putString(mContentResolver, Settings.Secure.ACCESSIBILITY_QS_TARGETS, null); Settings.Secure.putString(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, null); Settings.Secure.putString(mContentResolver, Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null); } Loading @@ -80,17 +82,14 @@ public class SettingsHelperRestoreTest { @Test public void restoreHighTextContrastEnabled_currentlyEnabled_enableInRestoredFromVanilla_dontSendNotification_hctKeepsEnabled() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent( mInterceptingContext.nextBroadcastIntent( SettingsHelper.HIGH_CONTRAST_TEXT_RESTORED_BROADCAST_ACTION); mContentResolver = interceptingContext.getContentResolver(); String settingName = Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED; Settings.Secure.putInt(mContentResolver, settingName, 1); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -106,17 +105,14 @@ public class SettingsHelperRestoreTest { @Test public void restoreHighTextContrastEnabled_currentlyDisabled_enableInRestoredFromVanilla_sendNotification_hctKeepsDisabled() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent( mInterceptingContext.nextBroadcastIntent( SettingsHelper.HIGH_CONTRAST_TEXT_RESTORED_BROADCAST_ACTION); mContentResolver = interceptingContext.getContentResolver(); String settingName = Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED; Settings.Secure.putInt(mContentResolver, settingName, 0); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -133,17 +129,14 @@ public class SettingsHelperRestoreTest { @Test public void restoreHighTextContrastEnabled_currentlyDisabled_enableInRestoredFromAfterVanilla_dontSendNotification_hctShouldEnabled() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent( mInterceptingContext.nextBroadcastIntent( SettingsHelper.HIGH_CONTRAST_TEXT_RESTORED_BROADCAST_ACTION); mContentResolver = interceptingContext.getContentResolver(); String settingName = Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED; Settings.Secure.putInt(mContentResolver, settingName, 0); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -169,7 +162,7 @@ public class SettingsHelperRestoreTest { Settings.Secure.putFloat(mContentResolver, settingName, configuredSettingValue); mSettingsHelper.restoreValue( mContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -192,7 +185,7 @@ public class SettingsHelperRestoreTest { float restoreSettingValue = defaultSettingValue + 0.5f; mSettingsHelper.restoreValue( Mockito.mock(Context.class), mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -214,7 +207,7 @@ public class SettingsHelperRestoreTest { */ private float setDefaultAccessibilityDisplayMagnificationScale() { float defaultSettingValue = mContext.getResources() mInterceptingContext.getResources() .getFraction( R.fraction.def_accessibility_display_magnification_scale, 1, 1); Settings.Secure.putFloat( Loading @@ -235,7 +228,7 @@ public class SettingsHelperRestoreTest { Settings.Secure.putInt(mContentResolver, settingName, configuredSettingValue); mSettingsHelper.restoreValue( Mockito.mock(Context.class), mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -257,7 +250,7 @@ public class SettingsHelperRestoreTest { int restoreSettingValue = 1; mSettingsHelper.restoreValue( Mockito.mock(Context.class), mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -271,17 +264,15 @@ public class SettingsHelperRestoreTest { @Test public void restoreAccessibilityQsTargets_broadcastSent() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); final String settingName = Settings.Secure.ACCESSIBILITY_QS_TARGETS; final String restoreSettingValue = "com.android.server.accessibility/ColorInversion" + SettingsStringUtil.DELIMITER + "com.android.server.accessibility/ColorCorrectionTile"; BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mInterceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -300,15 +291,13 @@ public class SettingsHelperRestoreTest { @Test public void restoreAccessibilityShortcutTargetService_broadcastSent() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); final String settingName = Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE; final String restoredValue = "com.android.a11y/Service"; BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mInterceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -323,4 +312,32 @@ public class SettingsHelperRestoreTest { Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, /* defaultValue= */ 0)) .isEqualTo(Build.VERSION.SDK_INT); } @EnableFlags(Flags.FLAG_RESTORE_A11Y_SECURE_SETTINGS_ON_HSUM_DEVICE) @Test public void restoreAccessibilityShortcutTargets_broadcastSent() throws ExecutionException, InterruptedException { final String settingName = Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS; final String restoreSettingValue = "com.android.server.accessibility/ColorInversion" + SettingsStringUtil.DELIMITER + "com.android.server.accessibility/ColorCorrectionTile"; BroadcastInterceptingContext.FutureIntent futureIntent = mInterceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mSettingsHelper.restoreValue( mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), settingName, restoreSettingValue, Build.VERSION.SDK_INT); Intent intentReceived = futureIntent.get(); assertThat(intentReceived.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)) .isEqualTo(restoreSettingValue); assertThat(intentReceived.getIntExtra( Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, /* defaultValue= */ 0)) .isEqualTo(Build.VERSION.SDK_INT); } } services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +24 −20 Original line number Diff line number Diff line Loading @@ -1057,17 +1057,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE); final int restoredFromSdk = intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, 0); final int userId = android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice() ? getSendingUserId() : UserHandle.USER_SYSTEM; switch (which) { case Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES -> { synchronized (mLock) { restoreEnabledAccessibilityServicesLocked( previousValue, newValue, restoredFromSdk); previousValue, newValue, restoredFromSdk, userId); } } case ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED -> { synchronized (mLock) { restoreLegacyDisplayMagnificationNavBarIfNeededLocked( newValue, restoredFromSdk); newValue, restoredFromSdk, userId); } } // Currently in SUW, the user can't see gesture shortcut option as the Loading @@ -1078,7 +1081,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub Settings.Secure.ACCESSIBILITY_QS_TARGETS, Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE -> restoreShortcutTargets(newValue, ShortcutUtils.convertToType(which)); ShortcutUtils.convertToType(which), userId); } } } Loading Loading @@ -1144,10 +1147,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } // Called only during settings restore; currently supports only the owner user // TODO: b/22388012 private void restoreLegacyDisplayMagnificationNavBarIfNeededLocked(String newSetting, int restoreFromSdkInt) { // Called only during settings restore; currently supports only the main user // TODO: http://b/374830726 private void restoreLegacyDisplayMagnificationNavBarIfNeededLocked( String newSetting, int restoreFromSdkInt, int userId) { if (restoreFromSdkInt >= Build.VERSION_CODES.R) { return; } Loading @@ -1160,7 +1163,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return; } final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); final AccessibilityUserState userState = getUserStateLocked(userId); final Set<String> targetsFromSetting = new ArraySet<>(); readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userState.mUserId, str -> str, targetsFromSetting); Loading Loading @@ -2225,20 +2228,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub getMagnificationController().onUserRemoved(userId); } // Called only during settings restore; currently supports only the owner user // TODO: http://b/22388012 void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting, int restoreFromSdkInt) { // Called only during settings restore; currently supports only the main user // TODO: http://b/374830726 void restoreEnabledAccessibilityServicesLocked( String oldSetting, String newSetting, int restoreFromSdkInt, int userId) { readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false); readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true); AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); AccessibilityUserState userState = getUserStateLocked(userId); userState.mEnabledServices.clear(); userState.mEnabledServices.addAll(mTempComponentNameSet); persistComponentNamesToSettingLocked( Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, userState.mEnabledServices, UserHandle.USER_SYSTEM); userState.mUserId); onUserStateChangedLocked(userState); migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null, restoreFromSdkInt); } Loading @@ -2247,21 +2250,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * User could configure accessibility shortcut during the SUW before restoring user data. * Merges the current value and the new value to make sure we don't lost the setting the user's * preferences of accessibility shortcut updated in SUW are not lost. * Called only during settings restore; currently supports only the owner user. * * <P> * Throws an exception if used with {@code TRIPLETAP} or {@code TWOFINGER_DOUBLETAP}. * </P> * TODO: http://b/22388012 */ private void restoreShortcutTargets(String newValue, @UserShortcutType int shortcutType) { // Called only during settings restore; currently supports only the main user. // TODO: http://b/374830726 private void restoreShortcutTargets( String newValue, @UserShortcutType int shortcutType, int userId) { assertNoTapShortcut(shortcutType); if (shortcutType == QUICK_SETTINGS && !android.view.accessibility.Flags.a11yQsShortcut()) { return; } synchronized (mLock) { final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); final AccessibilityUserState userState = getUserStateLocked(userId); final Set<String> mergedTargets = (shortcutType == HARDWARE) ? new ArraySet<>(ShortcutUtils.getShortcutTargetsFromSettings( mContext, shortcutType, userState.mUserId)) Loading Loading @@ -2295,7 +2299,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub userState.updateShortcutTargetsLocked(mergedTargets, shortcutType); persistColonDelimitedSetToSettingLocked(ShortcutUtils.convertToKey(shortcutType), UserHandle.USER_SYSTEM, mergedTargets, str -> str); userState.mUserId, mergedTargets, str -> str); scheduleNotifyClientsOfServicesStateChangeLocked(userState); onUserStateChangedLocked(userState); } Loading services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +75 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/view/accessibility/flags/accessibility_flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,16 @@ flag { } } flag { name: "restore_a11y_secure_settings_on_hsum_device" namespace: "accessibility" description: "Grab the a11y settings and send the settings restored broadcast for current visible foreground user" bug: "381294327" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "supplemental_description" namespace: "accessibility" Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +41 −13 Original line number Diff line number Diff line Loading @@ -101,21 +101,26 @@ public class SettingsHelper { */ private static final ArraySet<String> sBroadcastOnRestore; private static final ArraySet<String> sBroadcastOnRestoreSystemUI; private static final ArraySet<String> sBroadcastOnRestoreAccessibility; static { sBroadcastOnRestore = new ArraySet<String>(12); sBroadcastOnRestore = new ArraySet<>(7); sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS); sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); sBroadcastOnRestore.add(Settings.Global.BLUETOOTH_ON); sBroadcastOnRestore.add(Settings.Secure.UI_NIGHT_MODE); sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_START_TIME); sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_END_TIME); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS); sBroadcastOnRestore.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); sBroadcastOnRestore.add(Settings.Secure.SCREEN_RESOLUTION_MODE); sBroadcastOnRestoreSystemUI = new ArraySet<String>(2); sBroadcastOnRestoreAccessibility = new ArraySet<>(5); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); sBroadcastOnRestoreAccessibility.add( Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS); sBroadcastOnRestoreAccessibility.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); sBroadcastOnRestoreSystemUI = new ArraySet<>(2); sBroadcastOnRestoreSystemUI.add(Settings.Secure.QS_TILES); sBroadcastOnRestoreSystemUI.add(Settings.Secure.QS_AUTO_ADDED_TILES); } Loading Loading @@ -188,6 +193,7 @@ public class SettingsHelper { String oldValue = null; boolean sendBroadcast = false; boolean sendBroadcastSystemUI = false; boolean sendBroadcastAccessibility = false; final SettingsLookup table; if (destination.equals(Settings.Secure.CONTENT_URI)) { Loading @@ -200,6 +206,7 @@ public class SettingsHelper { sendBroadcast = sBroadcastOnRestore.contains(name); sendBroadcastSystemUI = sBroadcastOnRestoreSystemUI.contains(name); sendBroadcastAccessibility = sBroadcastOnRestoreAccessibility.contains(name); if (sendBroadcast) { // TODO: http://b/22388012 Loading @@ -209,6 +216,10 @@ public class SettingsHelper { // It would probably be correct to do it for the ones sent to the system, but consumers // may be depending on the current behavior. oldValue = table.lookup(cr, name, context.getUserId()); } else if (sendBroadcastAccessibility) { int userId = android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice() ? context.getUserId() : UserHandle.USER_SYSTEM; oldValue = table.lookup(cr, name, userId); } try { Loading Loading @@ -251,11 +262,7 @@ public class SettingsHelper { } else if (Settings.System.ACCELEROMETER_ROTATION.equals(name) && shouldSkipAutoRotateRestore()) { return; } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(name)) { // Don't write it to setting. Let the broadcast receiver in // AccessibilityManagerService handle restore/merging logic. return; } else if (Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE.equals(name)) { } else if (shouldSkipAndLetBroadcastHandlesRestoreLogic(name)) { // Don't write it to setting. Let the broadcast receiver in // AccessibilityManagerService handle restore/merging logic. return; Loading Loading @@ -287,12 +294,13 @@ public class SettingsHelper { // If we fail to apply the setting, by definition nothing happened sendBroadcast = false; sendBroadcastSystemUI = false; sendBroadcastAccessibility = false; Log.e(TAG, "Failed to restore setting name: " + name + " + value: " + value, e); } finally { // If this was an element of interest, send the "we just restored it" // broadcast with the historical value now that the new value has // been committed and observers kicked off. if (sendBroadcast || sendBroadcastSystemUI) { if (sendBroadcast || sendBroadcastSystemUI || sendBroadcastAccessibility) { Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) .putExtra(Intent.EXTRA_SETTING_NAME, name) Loading @@ -309,6 +317,13 @@ public class SettingsHelper { context.getString(com.android.internal.R.string.config_systemUi)); context.sendBroadcastAsUser(intent, context.getUser(), null); } if (sendBroadcastAccessibility) { UserHandle userHandle = android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice() ? context.getUser() : UserHandle.SYSTEM; intent.setPackage("android"); context.sendBroadcastAsUser(intent, userHandle, null); } } } } Loading Loading @@ -474,6 +489,19 @@ public class SettingsHelper { } } private boolean shouldSkipAndLetBroadcastHandlesRestoreLogic(String settingName) { boolean restoreHandledByBroadcast = Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals( settingName) || Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE.equals(settingName); if (android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice()) { restoreHandledByBroadcast |= Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(settingName) || Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(settingName); } return restoreHandledByBroadcast; } private void setAutoRestore(boolean enabled) { try { IBackupManager bm = IBackupManager.Stub.asInterface( Loading
packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java +51 −34 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.provider.SettingsStringUtil; import android.view.accessibility.Flags; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; Loading @@ -41,7 +42,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import java.util.concurrent.ExecutionException; Loading @@ -54,17 +54,17 @@ import java.util.concurrent.ExecutionException; public class SettingsHelperRestoreTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); public final BroadcastInterceptingContext mInterceptingContext = new BroadcastInterceptingContext( InstrumentationRegistry.getInstrumentation().getContext()); private static final float FLOAT_TOLERANCE = 0.01f; private Context mContext; private ContentResolver mContentResolver; private SettingsHelper mSettingsHelper; @Before public void setUp() { mContext = InstrumentationRegistry.getInstrumentation().getContext(); mContentResolver = mContext.getContentResolver(); mSettingsHelper = new SettingsHelper(mContext); mContentResolver = mInterceptingContext.getContentResolver(); mSettingsHelper = new SettingsHelper(mInterceptingContext); } @After Loading @@ -73,6 +73,8 @@ public class SettingsHelperRestoreTest { Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0); Settings.Secure.putString(mContentResolver, Settings.Secure.ACCESSIBILITY_QS_TARGETS, null); Settings.Secure.putString(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, null); Settings.Secure.putString(mContentResolver, Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null); } Loading @@ -80,17 +82,14 @@ public class SettingsHelperRestoreTest { @Test public void restoreHighTextContrastEnabled_currentlyEnabled_enableInRestoredFromVanilla_dontSendNotification_hctKeepsEnabled() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent( mInterceptingContext.nextBroadcastIntent( SettingsHelper.HIGH_CONTRAST_TEXT_RESTORED_BROADCAST_ACTION); mContentResolver = interceptingContext.getContentResolver(); String settingName = Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED; Settings.Secure.putInt(mContentResolver, settingName, 1); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -106,17 +105,14 @@ public class SettingsHelperRestoreTest { @Test public void restoreHighTextContrastEnabled_currentlyDisabled_enableInRestoredFromVanilla_sendNotification_hctKeepsDisabled() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent( mInterceptingContext.nextBroadcastIntent( SettingsHelper.HIGH_CONTRAST_TEXT_RESTORED_BROADCAST_ACTION); mContentResolver = interceptingContext.getContentResolver(); String settingName = Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED; Settings.Secure.putInt(mContentResolver, settingName, 0); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -133,17 +129,14 @@ public class SettingsHelperRestoreTest { @Test public void restoreHighTextContrastEnabled_currentlyDisabled_enableInRestoredFromAfterVanilla_dontSendNotification_hctShouldEnabled() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent( mInterceptingContext.nextBroadcastIntent( SettingsHelper.HIGH_CONTRAST_TEXT_RESTORED_BROADCAST_ACTION); mContentResolver = interceptingContext.getContentResolver(); String settingName = Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED; Settings.Secure.putInt(mContentResolver, settingName, 0); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -169,7 +162,7 @@ public class SettingsHelperRestoreTest { Settings.Secure.putFloat(mContentResolver, settingName, configuredSettingValue); mSettingsHelper.restoreValue( mContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -192,7 +185,7 @@ public class SettingsHelperRestoreTest { float restoreSettingValue = defaultSettingValue + 0.5f; mSettingsHelper.restoreValue( Mockito.mock(Context.class), mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -214,7 +207,7 @@ public class SettingsHelperRestoreTest { */ private float setDefaultAccessibilityDisplayMagnificationScale() { float defaultSettingValue = mContext.getResources() mInterceptingContext.getResources() .getFraction( R.fraction.def_accessibility_display_magnification_scale, 1, 1); Settings.Secure.putFloat( Loading @@ -235,7 +228,7 @@ public class SettingsHelperRestoreTest { Settings.Secure.putInt(mContentResolver, settingName, configuredSettingValue); mSettingsHelper.restoreValue( Mockito.mock(Context.class), mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -257,7 +250,7 @@ public class SettingsHelperRestoreTest { int restoreSettingValue = 1; mSettingsHelper.restoreValue( Mockito.mock(Context.class), mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -271,17 +264,15 @@ public class SettingsHelperRestoreTest { @Test public void restoreAccessibilityQsTargets_broadcastSent() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); final String settingName = Settings.Secure.ACCESSIBILITY_QS_TARGETS; final String restoreSettingValue = "com.android.server.accessibility/ColorInversion" + SettingsStringUtil.DELIMITER + "com.android.server.accessibility/ColorCorrectionTile"; BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mInterceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -300,15 +291,13 @@ public class SettingsHelperRestoreTest { @Test public void restoreAccessibilityShortcutTargetService_broadcastSent() throws ExecutionException, InterruptedException { BroadcastInterceptingContext interceptingContext = new BroadcastInterceptingContext( mContext); final String settingName = Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE; final String restoredValue = "com.android.a11y/Service"; BroadcastInterceptingContext.FutureIntent futureIntent = interceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mInterceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mSettingsHelper.restoreValue( interceptingContext, mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), Loading @@ -323,4 +312,32 @@ public class SettingsHelperRestoreTest { Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, /* defaultValue= */ 0)) .isEqualTo(Build.VERSION.SDK_INT); } @EnableFlags(Flags.FLAG_RESTORE_A11Y_SECURE_SETTINGS_ON_HSUM_DEVICE) @Test public void restoreAccessibilityShortcutTargets_broadcastSent() throws ExecutionException, InterruptedException { final String settingName = Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS; final String restoreSettingValue = "com.android.server.accessibility/ColorInversion" + SettingsStringUtil.DELIMITER + "com.android.server.accessibility/ColorCorrectionTile"; BroadcastInterceptingContext.FutureIntent futureIntent = mInterceptingContext.nextBroadcastIntent(Intent.ACTION_SETTING_RESTORED); mSettingsHelper.restoreValue( mInterceptingContext, mContentResolver, new ContentValues(2), Settings.Secure.getUriFor(settingName), settingName, restoreSettingValue, Build.VERSION.SDK_INT); Intent intentReceived = futureIntent.get(); assertThat(intentReceived.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)) .isEqualTo(restoreSettingValue); assertThat(intentReceived.getIntExtra( Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, /* defaultValue= */ 0)) .isEqualTo(Build.VERSION.SDK_INT); } }
services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +24 −20 Original line number Diff line number Diff line Loading @@ -1057,17 +1057,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE); final int restoredFromSdk = intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, 0); final int userId = android.view.accessibility.Flags.restoreA11ySecureSettingsOnHsumDevice() ? getSendingUserId() : UserHandle.USER_SYSTEM; switch (which) { case Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES -> { synchronized (mLock) { restoreEnabledAccessibilityServicesLocked( previousValue, newValue, restoredFromSdk); previousValue, newValue, restoredFromSdk, userId); } } case ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED -> { synchronized (mLock) { restoreLegacyDisplayMagnificationNavBarIfNeededLocked( newValue, restoredFromSdk); newValue, restoredFromSdk, userId); } } // Currently in SUW, the user can't see gesture shortcut option as the Loading @@ -1078,7 +1081,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub Settings.Secure.ACCESSIBILITY_QS_TARGETS, Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE -> restoreShortcutTargets(newValue, ShortcutUtils.convertToType(which)); ShortcutUtils.convertToType(which), userId); } } } Loading Loading @@ -1144,10 +1147,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } // Called only during settings restore; currently supports only the owner user // TODO: b/22388012 private void restoreLegacyDisplayMagnificationNavBarIfNeededLocked(String newSetting, int restoreFromSdkInt) { // Called only during settings restore; currently supports only the main user // TODO: http://b/374830726 private void restoreLegacyDisplayMagnificationNavBarIfNeededLocked( String newSetting, int restoreFromSdkInt, int userId) { if (restoreFromSdkInt >= Build.VERSION_CODES.R) { return; } Loading @@ -1160,7 +1163,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return; } final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); final AccessibilityUserState userState = getUserStateLocked(userId); final Set<String> targetsFromSetting = new ArraySet<>(); readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userState.mUserId, str -> str, targetsFromSetting); Loading Loading @@ -2225,20 +2228,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub getMagnificationController().onUserRemoved(userId); } // Called only during settings restore; currently supports only the owner user // TODO: http://b/22388012 void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting, int restoreFromSdkInt) { // Called only during settings restore; currently supports only the main user // TODO: http://b/374830726 void restoreEnabledAccessibilityServicesLocked( String oldSetting, String newSetting, int restoreFromSdkInt, int userId) { readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false); readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true); AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); AccessibilityUserState userState = getUserStateLocked(userId); userState.mEnabledServices.clear(); userState.mEnabledServices.addAll(mTempComponentNameSet); persistComponentNamesToSettingLocked( Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, userState.mEnabledServices, UserHandle.USER_SYSTEM); userState.mUserId); onUserStateChangedLocked(userState); migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null, restoreFromSdkInt); } Loading @@ -2247,21 +2250,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * User could configure accessibility shortcut during the SUW before restoring user data. * Merges the current value and the new value to make sure we don't lost the setting the user's * preferences of accessibility shortcut updated in SUW are not lost. * Called only during settings restore; currently supports only the owner user. * * <P> * Throws an exception if used with {@code TRIPLETAP} or {@code TWOFINGER_DOUBLETAP}. * </P> * TODO: http://b/22388012 */ private void restoreShortcutTargets(String newValue, @UserShortcutType int shortcutType) { // Called only during settings restore; currently supports only the main user. // TODO: http://b/374830726 private void restoreShortcutTargets( String newValue, @UserShortcutType int shortcutType, int userId) { assertNoTapShortcut(shortcutType); if (shortcutType == QUICK_SETTINGS && !android.view.accessibility.Flags.a11yQsShortcut()) { return; } synchronized (mLock) { final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); final AccessibilityUserState userState = getUserStateLocked(userId); final Set<String> mergedTargets = (shortcutType == HARDWARE) ? new ArraySet<>(ShortcutUtils.getShortcutTargetsFromSettings( mContext, shortcutType, userState.mUserId)) Loading Loading @@ -2295,7 +2299,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub userState.updateShortcutTargetsLocked(mergedTargets, shortcutType); persistColonDelimitedSetToSettingLocked(ShortcutUtils.convertToKey(shortcutType), UserHandle.USER_SYSTEM, mergedTargets, str -> str); userState.mUserId, mergedTargets, str -> str); scheduleNotifyClientsOfServicesStateChangeLocked(userState); onUserStateChangedLocked(userState); } Loading
services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +75 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes