Merge "Ensure settings provider joins the rescue party"

This commit is contained in:
TreeHugger Robot
2017-01-27 09:04:27 +00:00
committed by Android (Google) Code Review
5 changed files with 122 additions and 65 deletions

View File

@@ -182,6 +182,18 @@ public class SettingsProvider extends ContentProvider {
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 @@ public class SettingsProvider extends ContentProvider {
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 @@ public class SettingsProvider extends ContentProvider {
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 @@ public class SettingsProvider extends ContentProvider {
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 @@ public class SettingsProvider extends ContentProvider {
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 class SettingsProvider extends ContentProvider {
}
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 @@ public class SettingsProvider extends ContentProvider {
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 @@ public class SettingsProvider extends ContentProvider {
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 @@ public class SettingsProvider extends ContentProvider {
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 @@ public class SettingsProvider extends ContentProvider {
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;
}

View File

@@ -113,7 +113,7 @@ final public class SettingsService extends Binder {
String mKey = null;
String mValue = null;
String mPackageName = null;
String mToken = null;
String mTag = null;
int mResetMode = -1;
boolean mMakeDefault;
@@ -185,7 +185,7 @@ final public class SettingsService extends Binder {
if (peekNextArg() == null) {
valid = true;
} else {
mToken = getNextArg();
mTag = getNextArg();
if (peekNextArg() == null) {
valid = true;
} else {
@@ -218,10 +218,10 @@ final public class SettingsService extends Binder {
// what we have so far is a valid command
valid = true;
// keep going; there may be another PUT arg
} else if (mToken == null) {
mToken = arg;
if ("default".equalsIgnoreCase(mToken)) {
mToken = null;
} else if (mTag == null) {
mTag = arg;
if ("default".equalsIgnoreCase(mTag)) {
mTag = null;
mMakeDefault = true;
if (peekNextArg() == null) {
valid = true;
@@ -282,7 +282,7 @@ final public class SettingsService extends Binder {
pout.println(getForUser(iprovider, mUser, mTable, mKey));
break;
case PUT:
putForUser(iprovider, mUser, mTable, mKey, mValue, mToken, mMakeDefault);
putForUser(iprovider, mUser, mTable, mKey, mValue, mTag, mMakeDefault);
break;
case DELETE:
pout.println("Deleted "
@@ -294,7 +294,7 @@ final public class SettingsService extends Binder {
}
break;
case RESET:
resetForUser(iprovider, mUser, mTable, mToken);
resetForUser(iprovider, mUser, mTable, mTag);
break;
default:
perr.println("Unspecified command");
@@ -358,7 +358,7 @@ final public class SettingsService extends Binder {
}
void putForUser(IContentProvider provider, int userHandle, final String table,
final String key, final String value, String token, boolean makeDefault) {
final String key, final String value, String tag, boolean makeDefault) {
final String callPutCommand;
if ("system".equals(table)) {
callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
@@ -378,7 +378,9 @@ final public class SettingsService extends Binder {
Bundle arg = new Bundle();
arg.putString(Settings.NameValueTable.VALUE, value);
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
arg.putString(Settings.CALL_METHOD_TAG_KEY, token);
if (tag != null) {
arg.putString(Settings.CALL_METHOD_TAG_KEY, tag);
}
if (makeDefault) {
arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
}
@@ -409,7 +411,7 @@ final public class SettingsService extends Binder {
}
void resetForUser(IContentProvider provider, int userHandle,
String table, String token) {
String table, String tag) {
final String callResetCommand;
if ("secure".equals(table)) callResetCommand = Settings.CALL_METHOD_RESET_SECURE;
else if ("global".equals(table)) callResetCommand = Settings.CALL_METHOD_RESET_GLOBAL;
@@ -422,7 +424,9 @@ final public class SettingsService extends Binder {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
arg.putInt(Settings.CALL_METHOD_RESET_MODE_KEY, mResetMode);
arg.putString(Settings.CALL_METHOD_TAG_KEY, token);
if (tag != null) {
arg.putString(Settings.CALL_METHOD_TAG_KEY, tag);
}
String packageName = mPackageName != null ? mPackageName : resolveCallingPackage();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
provider.call(packageName, callResetCommand, null, arg);
@@ -465,9 +469,9 @@ final public class SettingsService extends Binder {
pw.println(" Print this help text.");
pw.println(" get [--user <USER_ID> | current] NAMESPACE KEY");
pw.println(" Retrieve the current value of KEY.");
pw.println(" put [--user <USER_ID> | current] NAMESPACE KEY VALUE [TOKEN] [default]");
pw.println(" put [--user <USER_ID> | current] NAMESPACE KEY VALUE [TAG] [default]");
pw.println(" Change the contents of KEY to VALUE.");
pw.println(" TOKEN to associate with the setting.");
pw.println(" TAG to associate with the setting.");
pw.println(" {default} to set as the default, case-insensitive only for global/secure namespace");
pw.println(" delete NAMESPACE KEY");
pw.println(" Delete the entry for KEY.");

View File

@@ -64,6 +64,7 @@ import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* This class contains the state for one type of settings. It is responsible
@@ -129,7 +130,7 @@ final class SettingsState {
private static final String HISTORICAL_OPERATION_INITIALIZE = "initialize";
private static final String HISTORICAL_OPERATION_RESET = "reset";
private static final String SHELL_PACKAGE_NAME = "shell";
private static final String SHELL_PACKAGE_NAME = "com.android.shell";
private static final String ROOT_PACKAGE_NAME = "root";
private static final String NULL_VALUE = "null";
@@ -307,7 +308,7 @@ final class SettingsState {
Setting newState;
if (oldState != null) {
if (!oldState.update(value, makeDefault, packageName, tag)) {
if (!oldState.update(value, makeDefault, packageName, tag, false)) {
return false;
}
newState = oldState;
@@ -351,7 +352,7 @@ final class SettingsState {
}
// The settings provider must hold its lock when calling here.
public boolean resetSettingLocked(String name, String packageName) {
public boolean resetSettingLocked(String name) {
if (TextUtils.isEmpty(name) || !hasSettingLocked(name)) {
return false;
}
@@ -362,7 +363,7 @@ final class SettingsState {
String oldValue = setting.getValue();
String oldDefaultValue = setting.getDefaultValue();
if (!setting.reset(packageName)) {
if (!setting.reset()) {
return false;
}
@@ -817,7 +818,7 @@ final class SettingsState {
public Setting(String name, String value, boolean makeDefault, String packageName,
String tag) {
this.name = name;
update(value, makeDefault, packageName, tag);
update(value, makeDefault, packageName, tag, false);
}
public Setting(String name, String value, String defaultValue,
@@ -877,16 +878,18 @@ final class SettingsState {
}
/** @return whether the value changed */
public boolean reset(String packageName) {
return update(this.defaultValue, false, packageName, null);
public boolean reset() {
return update(this.defaultValue, false, packageName, null, true);
}
public boolean update(String value, boolean setDefault, String packageName, String tag) {
public boolean update(String value, boolean setDefault, String packageName, String tag,
boolean forceNonSystemPackage) {
if (NULL_VALUE.equals(value)) {
value = null;
}
final boolean callerSystem = !isNull() && isSystemPackage(mContext, packageName);
final boolean callerSystem = !forceNonSystemPackage &&
!isNull() && isSystemPackage(mContext, packageName);
// Settings set by the system are always defaults.
if (callerSystem) {
setDefault = true;

View File

@@ -206,19 +206,22 @@ abstract class BaseSettingsProviderTest {
resetToDefaultsViaShell(type, packageName, null);
}
protected static void resetToDefaultsViaShell(int type, String packageName, String token)
protected static void resetToDefaultsViaShell(int type, String packageName, String tag)
throws IOException {
switch (type) {
case SETTING_TYPE_GLOBAL: {
executeShellCommand("settings reset global " + packageName + " " + token);
executeShellCommand("settings reset global " + packageName + " "
+ (tag != null ? tag : ""));
} break;
case SETTING_TYPE_SECURE: {
executeShellCommand("settings reset secure " + packageName + " " + token);
executeShellCommand("settings reset secure " + packageName + " "
+ (tag != null ? tag : ""));
} break;
case SETTING_TYPE_SYSTEM: {
executeShellCommand("settings reset system " + packageName + " " + token);
executeShellCommand("settings reset system " + packageName + " "
+ (tag != null ? tag : ""));
} break;
default: {

View File

@@ -59,8 +59,6 @@ public class RescueParty {
private static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;
private static final int LEVEL_FACTORY_RESET = 4;
private static final boolean DISABLE_RESET_SETTINGS = true;
/** Threshold for boot loops */
private static final Threshold sBoot = new BootThreshold();
/** Threshold for app crash loops */
@@ -181,8 +179,6 @@ public class RescueParty {
}
private static void resetAllSettings(Context context, int mode) throws Exception {
if (DISABLE_RESET_SETTINGS) return;
// Try our best to reset all settings possible, and once finished
// rethrow any exception that we encountered
Exception res = null;