Ensure settings provider joins the rescue party

The settings provider has logic to incrementally reset state
in an effort to recover from pushing a bad value putting the
system in a bad state. The settings provider was not force
persisting its state after a reset so after the reboot we
lost the reset changes. Also while resetting we were also
resetting the package name leading to a promotion of the reset
value to being set by the system. Updated the tests and while at
this added logic to synchronously persist critical settings
such as device provisioned.

Test: All tests pass. Manually tested end-to-end rescue party

bug:34677175

Change-Id: Ib240072df2fa549dae39c301008adf48cdf1573a
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 25e1f16..7a9ba20 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -182,6 +182,18 @@
     private static final Bundle NULL_SETTING_BUNDLE = Bundle.forPair(
             Settings.NameValueTable.VALUE, null);
 
+    // Changes to these global settings are synchronously persisted
+    private static final Set<String> CRITICAL_GLOBAL_SETTINGS = new ArraySet<>();
+    static {
+        CRITICAL_GLOBAL_SETTINGS.add(Settings.Global.DEVICE_PROVISIONED);
+    }
+
+    // Changes to these secure settings are synchronously persisted
+    private static final Set<String> CRITICAL_SECURE_SETTINGS = new ArraySet<>();
+    static {
+        CRITICAL_SECURE_SETTINGS.add(Settings.Secure.USER_SETUP_COMPLETE);
+    }
+
     // Per user secure settings that moved to the for all users global settings.
     static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>();
     static {
@@ -949,18 +961,18 @@
                 case MUTATION_OPERATION_INSERT: {
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_GLOBAL,
                             UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_DELETE: {
                     return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_GLOBAL,
-                            UserHandle.USER_SYSTEM, name, forceNotify);
+                            UserHandle.USER_SYSTEM, name, forceNotify, CRITICAL_GLOBAL_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_UPDATE: {
                     return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_GLOBAL,
                             UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_RESET: {
@@ -1156,18 +1168,18 @@
                 case MUTATION_OPERATION_INSERT: {
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
                             owningUserId, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_DELETE: {
                     return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SECURE,
-                            owningUserId, name, forceNotify);
+                            owningUserId, name, forceNotify, CRITICAL_SECURE_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_UPDATE: {
                     return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SECURE,
                             owningUserId, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_RESET: {
@@ -1304,18 +1316,20 @@
                 case MUTATION_OPERATION_INSERT: {
                     validateSystemSettingValue(name, value);
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM,
-                            owningUserId, name, value, null, false, getCallingPackage(), false);
+                            owningUserId, name, value, null, false, getCallingPackage(),
+                            false, null);
                 }
 
                 case MUTATION_OPERATION_DELETE: {
                     return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM,
-                            owningUserId, name, false);
+                            owningUserId, name, false, null);
                 }
 
                 case MUTATION_OPERATION_UPDATE: {
                     validateSystemSettingValue(name, value);
                     return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM,
-                            owningUserId, name, value, null, false, getCallingPackage(), false);
+                            owningUserId, name, value, null, false, getCallingPackage(),
+                            false, null);
                 }
             }
 
@@ -1689,7 +1703,7 @@
 
         return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
                 owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
-                tag, makeDefault, getCallingPackage(), forceNotify);
+                tag, makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
     }
 
     private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
@@ -2234,7 +2248,8 @@
         }
 
         public boolean insertSettingLocked(int type, int userId, String name, String value,
-                String tag, boolean makeDefault, String packageName, boolean forceNotify) {
+                String tag, boolean makeDefault, String packageName, boolean forceNotify,
+                Set<String> criticalSettings) {
             final int key = makeKey(type, userId);
 
             boolean success = false;
@@ -2244,13 +2259,18 @@
                         tag, makeDefault, packageName);
             }
 
+            if (success && criticalSettings != null && criticalSettings.contains(name)) {
+                settingsState.persistSyncLocked();
+            }
+
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
             }
             return success;
         }
 
-        public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify) {
+        public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify,
+                Set<String> criticalSettings) {
             final int key = makeKey(type, userId);
 
             boolean success = false;
@@ -2259,12 +2279,39 @@
                 success = settingsState.deleteSettingLocked(name);
             }
 
+            if (success && criticalSettings != null && criticalSettings.contains(name)) {
+                settingsState.persistSyncLocked();
+            }
+
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
             }
             return success;
         }
 
+        public boolean updateSettingLocked(int type, int userId, String name, String value,
+                String tag, boolean makeDefault, String packageName, boolean forceNotify,
+                Set<String> criticalSettings) {
+            final int key = makeKey(type, userId);
+
+            boolean success = false;
+            SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState != null) {
+                success = settingsState.updateSettingLocked(name, value, tag,
+                        makeDefault, packageName);
+            }
+
+            if (success && criticalSettings != null && criticalSettings.contains(name)) {
+                settingsState.persistSyncLocked();
+            }
+
+            if (forceNotify || success) {
+                notifyForSettingsChange(key, name);
+            }
+
+            return success;
+        }
+
         public Setting getSettingLocked(int type, int userId, String name) {
             final int key = makeKey(type, userId);
 
@@ -2277,24 +2324,6 @@
             return settingsState.getSettingLocked(name);
         }
 
-        public boolean updateSettingLocked(int type, int userId, String name, String value,
-                String tag, boolean makeDefault, String packageName, boolean forceNotify) {
-            final int key = makeKey(type, userId);
-
-            boolean success = false;
-            SettingsState settingsState = peekSettingsStateLocked(key);
-            if (settingsState != null) {
-                success = settingsState.updateSettingLocked(name, value, tag,
-                        makeDefault, packageName);
-            }
-
-            if (forceNotify || success) {
-                notifyForSettingsChange(key, name);
-            }
-
-            return success;
-        }
-
         public void resetSettingsLocked(int type, int userId, String packageName, int mode,
                 String tag) {
             final int key = makeKey(type, userId);
@@ -2306,56 +2335,78 @@
             switch (mode) {
                 case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
                     for (String name : settingsState.getSettingNamesLocked()) {
+                        boolean someSettingChanged = false;
                         Setting setting = settingsState.getSettingLocked(name);
                         if (packageName.equals(setting.getPackageName())) {
                             if (tag != null && !tag.equals(setting.getTag())) {
                                 continue;
                             }
-                            if (settingsState.resetSettingLocked(name, packageName)) {
+                            if (settingsState.resetSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
 
                 case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: {
                     for (String name : settingsState.getSettingNamesLocked()) {
+                        boolean someSettingChanged = false;
                         Setting setting = settingsState.getSettingLocked(name);
                         if (!SettingsState.isSystemPackage(getContext(),
                                 setting.getPackageName())) {
-                            if (settingsState.resetSettingLocked(name, packageName)) {
+                            if (settingsState.resetSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
 
                 case Settings.RESET_MODE_UNTRUSTED_CHANGES: {
                     for (String name : settingsState.getSettingNamesLocked()) {
+                        boolean someSettingChanged = false;
                         Setting setting = settingsState.getSettingLocked(name);
                         if (!SettingsState.isSystemPackage(getContext(),
                                 setting.getPackageName())) {
                             if (setting.isDefaultFromSystem()) {
-                                if (settingsState.resetSettingLocked(name, packageName)) {
+                                if (settingsState.resetSettingLocked(name)) {
+                                    someSettingChanged = true;
                                     notifyForSettingsChange(key, name);
                                 }
                             } else if (settingsState.deleteSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
 
                 case Settings.RESET_MODE_TRUSTED_DEFAULTS: {
                     for (String name : settingsState.getSettingNamesLocked()) {
                         Setting setting = settingsState.getSettingLocked(name);
+                        boolean someSettingChanged = false;
                         if (setting.isDefaultFromSystem()) {
-                            if (settingsState.resetSettingLocked(name, packageName)) {
+                            if (settingsState.resetSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         } else if (settingsState.deleteSettingLocked(name)) {
+                            someSettingChanged = true;
                             notifyForSettingsChange(key, name);
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
             }