Fixes magnification settings did not restore

- A redundant a11y button migration was called during the period
  of enabled accessibility services restoring. It rewrited the
  settings of a11y button targets which is restored.
- User could enable a11y services in the SUW. Merges previous vales
  for a11y button targets after it's restored to avoid settings are
  lost.

Bug: 160752945
Test: atest AccessibilityShortcutTest
Test: Manual restore from SUW
Change-Id: If55f4839c6ab0c648a35d47c9032e4b9954c0d5c
This commit is contained in:
Rhed Jao
2020-07-24 15:43:14 +08:00
parent 82658d6c48
commit e03de99a88
2 changed files with 70 additions and 18 deletions

View File

@@ -81,6 +81,7 @@ public class SettingsHelper {
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);
}
private interface SettingsLookup {

View File

@@ -437,7 +437,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (reboundAService || configurationChanged) {
onUserStateChangedLocked(userState);
}
migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, packageName);
// Passing 0 for restoreFromSdkInt to have this migration check execute each
// time. It can make sure a11y button settings are correctly if there's an a11y
// service updated and modifies the a11y button configuration.
migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, packageName,
/* restoreFromSdkInt = */0);
}
}
@@ -548,7 +552,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
synchronized (mLock) {
restoreEnabledAccessibilityServicesLocked(
intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
0));
}
} else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
synchronized (mLock) {
@@ -557,6 +563,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
0));
}
} else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
synchronized (mLock) {
restoreAccessibilityButtonTargetsLocked(
intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
}
}
}
}
@@ -582,7 +594,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
final Set<String> targetsFromSetting = new ArraySet<>();
readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
userState.mUserId, targetsFromSetting, str -> str);
userState.mUserId, str -> str, targetsFromSetting);
final boolean targetsContainMagnification = targetsFromSetting.contains(
MAGNIFICATION_CONTROLLER_NAME);
if (targetsContainMagnification == displayMagnificationNavBarEnabled) {
@@ -1145,7 +1157,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
// the state since the context in which the current user
// state was used has changed since it was inactive.
onUserStateChangedLocked(userState);
migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null);
// It's better to have this migration in SettingsProvider. Unfortunately,
// SettingsProvider migrated database in a very early stage which A11yManagerService
// haven't finished or started the initialization. We cannot get enough information from
// A11yManagerService to execute these migrations in SettingsProvider. Passing 0 for
// restoreFromSdkInt to have this migration check execute every time, because we did not
// find out a way to detect the device finished the OTA and switch the user.
migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null,
/* restoreFromSdkInt = */0);
if (announceNewUser) {
// Schedule announcement of the current user if needed.
@@ -1190,7 +1209,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
// Called only during settings restore; currently supports only the owner user
// TODO: http://b/22388012
void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) {
void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting,
int restoreFromSdkInt) {
readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false);
readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true);
@@ -1202,7 +1222,32 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState.mEnabledServices,
UserHandle.USER_SYSTEM);
onUserStateChangedLocked(userState);
migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null);
migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null, restoreFromSdkInt);
}
/**
* User could enable accessibility services and configure accessibility button during the SUW.
* Merges current value of accessibility button settings into the restored one to make sure
* user's preferences of accessibility button updated in SUW are not lost.
*
* Called only during settings restore; currently supports only the owner user
* TODO: http://b/22388012
*/
void restoreAccessibilityButtonTargetsLocked(String oldSetting, String newSetting) {
final Set<String> targetsFromSetting = new ArraySet<>();
readColonDelimitedStringToSet(oldSetting, str -> str, targetsFromSetting,
/* doMerge = */false);
readColonDelimitedStringToSet(newSetting, str -> str, targetsFromSetting,
/* doMerge = */true);
final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
userState.mAccessibilityButtonTargets.clear();
userState.mAccessibilityButtonTargets.addAll(targetsFromSetting);
persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
UserHandle.USER_SYSTEM, userState.mAccessibilityButtonTargets, str -> str);
scheduleNotifyClientsOfServicesStateChangeLocked(userState);
onUserStateChangedLocked(userState);
}
private int getClientStateLocked(AccessibilityUserState userState) {
@@ -1525,8 +1570,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
*/
private void readComponentNamesFromSettingLocked(String settingName, int userId,
Set<ComponentName> outComponentNames) {
readColonDelimitedSettingToSet(settingName, userId, outComponentNames,
str -> ComponentName.unflattenFromString(str));
readColonDelimitedSettingToSet(settingName, userId,
str -> ComponentName.unflattenFromString(str), outComponentNames);
}
/**
@@ -1541,8 +1586,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private void readComponentNamesFromStringLocked(String names,
Set<ComponentName> outComponentNames,
boolean doMerge) {
readColonDelimitedStringToSet(names, outComponentNames, doMerge,
str -> ComponentName.unflattenFromString(str));
readColonDelimitedStringToSet(names, str -> ComponentName.unflattenFromString(str),
outComponentNames, doMerge);
}
@Override
@@ -1552,15 +1597,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
componentName -> componentName.flattenToShortString());
}
private <T> void readColonDelimitedSettingToSet(String settingName, int userId, Set<T> outSet,
Function<String, T> toItem) {
private <T> void readColonDelimitedSettingToSet(String settingName, int userId,
Function<String, T> toItem, Set<T> outSet) {
final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
settingName, userId);
readColonDelimitedStringToSet(settingValue, outSet, false, toItem);
readColonDelimitedStringToSet(settingValue, toItem, outSet, false);
}
private <T> void readColonDelimitedStringToSet(String names, Set<T> outSet, boolean doMerge,
Function<String, T> toItem) {
private <T> void readColonDelimitedStringToSet(String names, Function<String, T> toItem,
Set<T> outSet, boolean doMerge) {
if (!doMerge) {
outSet.clear();
}
@@ -2058,7 +2103,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userState.mUserId);
final Set<String> targetsFromSetting = new ArraySet<>();
readColonDelimitedStringToSet(settingValue, targetsFromSetting, false, str -> str);
readColonDelimitedStringToSet(settingValue, str -> str, targetsFromSetting, false);
// Fall back to device's default a11y service, only when setting is never updated.
if (settingValue == null) {
final String defaultService = mContext.getString(
@@ -2082,7 +2127,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private boolean readAccessibilityButtonTargetsLocked(AccessibilityUserState userState) {
final Set<String> targetsFromSetting = new ArraySet<>();
readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
userState.mUserId, targetsFromSetting, str -> str);
userState.mUserId, str -> str, targetsFromSetting);
final Set<String> currentTargets =
userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON);
@@ -2346,9 +2391,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
* (It happens when an enabled accessibility service package is upgraded.)
*
* @param packageName The package name to check, or {@code null} to check all services.
* @param restoreFromSdkInt The target sdk version of the restored source device, or {@code 0}
* if the caller is not related to the restore.
*/
private void migrateAccessibilityButtonSettingsIfNecessaryLocked(
AccessibilityUserState userState, @Nullable String packageName) {
AccessibilityUserState userState, @Nullable String packageName, int restoreFromSdkInt) {
// No need to migrate settings if they are restored from a version after Q.
if (restoreFromSdkInt > Build.VERSION_CODES.Q) {
return;
}
final Set<String> buttonTargets =
userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON);
int lastSize = buttonTargets.size();