summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java120
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java375
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java7
3 files changed, 459 insertions, 43 deletions
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index e7f5f4f9f6ba..f1d1b1f6e240 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -42,7 +42,6 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.Debug;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
@@ -53,6 +52,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
@@ -62,6 +62,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
@@ -75,6 +76,7 @@ import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.security.SecureRandom;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -114,7 +116,7 @@ import java.util.regex.Pattern;
*/
@SuppressWarnings("deprecation")
public class SettingsProvider extends ContentProvider {
- private static final boolean DEBUG = false;
+ static final boolean DEBUG = false;
private static final boolean DROP_DATABASE_ON_MIGRATION = true;
@@ -264,6 +266,7 @@ public class SettingsProvider extends ContentProvider {
}
registerBroadcastReceivers();
startWatchingUserRestrictionChanges();
+ ServiceManager.addService("settings", new SettingsService(this));
return true;
}
@@ -560,16 +563,14 @@ public class SettingsProvider extends ContentProvider {
return cacheDir;
}
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mLock) {
final long identity = Binder.clearCallingIdentity();
try {
- List<UserInfo> users = mUserManager.getUsers(true);
+ SparseBooleanArray users = mSettingsRegistry.getKnownUsersLocked();
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
- UserInfo user = users.get(i);
- dumpForUserLocked(user.id, pw);
+ dumpForUserLocked(users.keyAt(i), pw);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -580,49 +581,53 @@ public class SettingsProvider extends ContentProvider {
private void dumpForUserLocked(int userId, PrintWriter pw) {
if (userId == UserHandle.USER_SYSTEM) {
pw.println("GLOBAL SETTINGS (user " + userId + ")");
- Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS);
- dumpSettings(globalCursor, pw);
- pw.println();
-
SettingsState globalSettings = mSettingsRegistry.getSettingsLocked(
SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
+ if (globalSettings != null) {
+ dumpSettingsLocked(globalSettings, pw);
+ }
+ pw.println();
+
globalSettings.dumpHistoricalOperations(pw);
}
pw.println("SECURE SETTINGS (user " + userId + ")");
- Cursor secureCursor = getAllSecureSettings(userId, ALL_COLUMNS);
- dumpSettings(secureCursor, pw);
- pw.println();
-
SettingsState secureSettings = mSettingsRegistry.getSettingsLocked(
SETTINGS_TYPE_SECURE, userId);
+ if (secureSettings != null) {
+ dumpSettingsLocked(secureSettings, pw);
+ }
+ pw.println();
+
secureSettings.dumpHistoricalOperations(pw);
pw.println("SYSTEM SETTINGS (user " + userId + ")");
- Cursor systemCursor = getAllSystemSettings(userId, ALL_COLUMNS);
- dumpSettings(systemCursor, pw);
- pw.println();
-
SettingsState systemSettings = mSettingsRegistry.getSettingsLocked(
SETTINGS_TYPE_SYSTEM, userId);
+ if (systemSettings != null) {
+ dumpSettingsLocked(systemSettings, pw);
+ }
+ pw.println();
+
systemSettings.dumpHistoricalOperations(pw);
}
- private void dumpSettings(Cursor cursor, PrintWriter pw) {
- if (cursor == null || !cursor.moveToFirst()) {
- return;
- }
+ private void dumpSettingsLocked(SettingsState settingsState, PrintWriter pw) {
+ List<String> names = settingsState.getSettingNamesLocked();
- final int idColumnIdx = cursor.getColumnIndex(Settings.NameValueTable._ID);
- final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
- final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
+ final int nameCount = names.size();
- do {
- pw.append("_id:").append(toDumpString(cursor.getString(idColumnIdx)));
- pw.append(" name:").append(toDumpString(cursor.getString(nameColumnIdx)));
- pw.append(" value:").append(toDumpString(cursor.getString(valueColumnIdx)));
+ for (int i = 0; i < nameCount; i++) {
+ String name = names.get(i);
+ Setting setting = settingsState.getSettingLocked(name);
+ pw.print("_id:"); pw.print(toDumpString(setting.getId()));
+ pw.print(" name:"); pw.print(toDumpString(name));
+ if (setting.getPackageName() != null) {
+ pw.print(" pkg:"); pw.print(toDumpString(setting.getPackageName()));
+ }
+ pw.print(" value:"); pw.print(toDumpString(setting.getValue()));
pw.println();
- } while (cursor.moveToNext());
+ }
}
private static String toDumpString(String s) {
@@ -916,8 +921,9 @@ public class SettingsProvider extends ContentProvider {
// Special case for location (sigh).
if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
- return mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
- owningUserId).getNullSetting();
+ SettingsState settings = mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
+ owningUserId);
+ return settings != null ? settings.getNullSetting() : null;
}
// Get the value.
@@ -1267,7 +1273,8 @@ public class SettingsProvider extends ContentProvider {
&& (parentId = getGroupParentLocked(userId)) != userId) {
// The setting has a dependency and the profile has a parent
String dependency = sSystemCloneFromParentOnDependency.get(setting);
- if (getSecureSetting(dependency, userId).getValue().equals("1")) {
+ Setting settingObj = getSecureSetting(dependency, userId);
+ if (settingObj != null && settingObj.getValue().equals("1")) {
return parentId;
}
}
@@ -1405,6 +1412,9 @@ public class SettingsProvider extends ContentProvider {
Setting settingValue = getSecureSetting(
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
+ if (settingValue == null) {
+ return false;
+ }
String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
@@ -1491,14 +1501,14 @@ public class SettingsProvider extends ContentProvider {
private Bundle packageValueForCallResult(Setting setting,
boolean trackingGeneration) {
if (!trackingGeneration) {
- if (setting.isNull()) {
+ if (setting == null || setting.isNull()) {
return NULL_SETTING_BUNDLE;
}
return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
}
Bundle result = new Bundle();
result.putString(Settings.NameValueTable.VALUE,
- !setting.isNull() ? setting.getValue() : null);
+ setting != null && !setting.isNull() ? setting.getValue() : null);
mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getkey());
return result;
}
@@ -1554,7 +1564,7 @@ public class SettingsProvider extends ContentProvider {
}
private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
- if (setting.isNull()) {
+ if (setting == null || setting.isNull()) {
return;
}
final int columnCount = cursor.getColumnCount();
@@ -1700,15 +1710,32 @@ public class SettingsProvider extends ContentProvider {
public List<String> getSettingsNamesLocked(int type, int userId) {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
+ if (settingsState == null) {
+ return new ArrayList<String>();
+ }
return settingsState.getSettingNamesLocked();
}
+ public SparseBooleanArray getKnownUsersLocked() {
+ SparseBooleanArray users = new SparseBooleanArray();
+ for (int i = mSettingsStates.size()-1; i >= 0; i--) {
+ users.put(getUserIdFromKey(mSettingsStates.keyAt(i)), true);
+ }
+ return users;
+ }
+
public SettingsState getSettingsLocked(int type, int userId) {
final int key = makeKey(type, userId);
return peekSettingsStateLocked(key);
}
- public void ensureSettingsForUserLocked(int userId) {
+ public boolean ensureSettingsForUserLocked(int userId) {
+ // First make sure this user actually exists.
+ if (mUserManager.getUserInfo(userId) == null) {
+ Slog.wtf(LOG_TAG, "Requested user " + userId + " does not exist");
+ return false;
+ }
+
// Migrate the setting for this user if needed.
migrateLegacySettingsForUserIfNeededLocked(userId);
@@ -1733,6 +1760,7 @@ public class SettingsProvider extends ContentProvider {
// Upgrade the settings to the latest version.
UpgradeController upgrader = new UpgradeController(userId);
upgrader.upgradeIfNeededLocked();
+ return true;
}
private void ensureSettingsStateLocked(int key) {
@@ -1790,7 +1818,8 @@ public class SettingsProvider extends ContentProvider {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
- final boolean success = settingsState.insertSettingLocked(name, value, packageName);
+ final boolean success = settingsState != null
+ && settingsState.insertSettingLocked(name, value, packageName);
if (forceNotify || success) {
notifyForSettingsChange(key, name);
@@ -1802,6 +1831,9 @@ public class SettingsProvider extends ContentProvider {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
+ if (settingsState == null) {
+ return false;
+ }
final boolean success = settingsState.deleteSettingLocked(name);
if (forceNotify || success) {
@@ -1814,6 +1846,9 @@ public class SettingsProvider extends ContentProvider {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
+ if (settingsState == null) {
+ return null;
+ }
return settingsState.getSettingLocked(name);
}
@@ -1822,7 +1857,8 @@ public class SettingsProvider extends ContentProvider {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
- final boolean success = settingsState.updateSettingLocked(name, value, packageName);
+ final boolean success = settingsState != null
+ && settingsState.updateSettingLocked(name, value, packageName);
if (forceNotify || success) {
notifyForSettingsChange(key, name);
@@ -1850,7 +1886,9 @@ public class SettingsProvider extends ContentProvider {
return settingsState;
}
- ensureSettingsForUserLocked(getUserIdFromKey(key));
+ if (!ensureSettingsForUserLocked(getUserIdFromKey(key))) {
+ return null;
+ }
return mSettingsStates.get(key);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
new file mode 100644
index 000000000000..169b01f66881
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.app.ActivityManagerNative;
+import android.content.IContentProvider;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+final public class SettingsService extends Binder {
+ final SettingsProvider mProvider;
+
+ public SettingsService(SettingsProvider provider) {
+ mProvider = provider;
+ }
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ (new MyShellCommand(mProvider, false)).exec(
+ this, in, out, err, args, callback, resultReceiver);
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mProvider.getContext().checkCallingPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump SettingsProvider from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " without permission "
+ + android.Manifest.permission.DUMP);
+ return;
+ }
+
+ int opti = 0;
+ while (opti < args.length) {
+ String opt = args[opti];
+ if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
+ break;
+ }
+ opti++;
+ if ("-h".equals(opt)) {
+ MyShellCommand.dumpHelp(pw, true);
+ return;
+ } else {
+ pw.println("Unknown argument: " + opt + "; use -h for help");
+ }
+ }
+
+ long caller = Binder.clearCallingIdentity();
+ try {
+ mProvider.dumpInternal(fd, pw, args);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+
+ final static class MyShellCommand extends ShellCommand {
+ final SettingsProvider mProvider;
+ final boolean mDumping;
+
+ enum CommandVerb {
+ UNSPECIFIED,
+ GET,
+ PUT,
+ DELETE,
+ LIST,
+ }
+
+ int mUser = -1; // unspecified
+ CommandVerb mVerb = CommandVerb.UNSPECIFIED;
+ String mTable = null;
+ String mKey = null;
+ String mValue = null;
+
+
+ MyShellCommand(SettingsProvider provider, boolean dumping) {
+ mProvider = provider;
+ mDumping = dumping;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ final PrintWriter perr = getErrPrintWriter();
+
+ boolean valid = false;
+ String arg = cmd;
+ do {
+ if ("--user".equals(arg)) {
+ if (mUser != -1) {
+ // --user specified more than once; invalid
+ break;
+ }
+ arg = getNextArgRequired();
+ if ("current".equals(arg) || "cur".equals(arg)) {
+ mUser = UserHandle.USER_CURRENT;
+ } else {
+ mUser = Integer.parseInt(arg);
+ }
+ } else if (mVerb == CommandVerb.UNSPECIFIED) {
+ if ("get".equalsIgnoreCase(arg)) {
+ mVerb = CommandVerb.GET;
+ } else if ("put".equalsIgnoreCase(arg)) {
+ mVerb = CommandVerb.PUT;
+ } else if ("delete".equalsIgnoreCase(arg)) {
+ mVerb = CommandVerb.DELETE;
+ } else if ("list".equalsIgnoreCase(arg)) {
+ mVerb = CommandVerb.LIST;
+ } else {
+ // invalid
+ perr.println("Invalid command: " + arg);
+ return -1;
+ }
+ } else if (mTable == null) {
+ if (!"system".equalsIgnoreCase(arg)
+ && !"secure".equalsIgnoreCase(arg)
+ && !"global".equalsIgnoreCase(arg)) {
+ perr.println("Invalid namespace '" + arg + "'");
+ return -1;
+ }
+ mTable = arg.toLowerCase();
+ if (mVerb == CommandVerb.LIST) {
+ valid = true;
+ break;
+ }
+ } else if (mVerb == CommandVerb.GET || mVerb == CommandVerb.DELETE) {
+ mKey = arg;
+ if (peekNextArg() == null) {
+ valid = true;
+ } else {
+ perr.println("Too many arguments");
+ return -1;
+ }
+ break;
+ } else if (mKey == null) {
+ mKey = arg;
+ // keep going; there's another PUT arg
+ } else { // PUT, final arg
+ mValue = arg;
+ if (peekNextArg() == null) {
+ valid = true;
+ } else {
+ perr.println("Too many arguments");
+ return -1;
+ }
+ break;
+ }
+ } while ((arg = getNextArg()) != null);
+
+ if (!valid) {
+ perr.println("Bad arguments");
+ return -1;
+ }
+
+ if (mUser == UserHandle.USER_CURRENT) {
+ try {
+ mUser = ActivityManagerNative.getDefault().getCurrentUser().id;
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed in IPC", e);
+ }
+ }
+ if (mUser < 0) {
+ mUser = UserHandle.USER_SYSTEM;
+ } else if (mVerb == CommandVerb.DELETE || mVerb == CommandVerb.LIST) {
+ perr.println("--user not supported for delete and list.");
+ return -1;
+ }
+ UserManager userManager = UserManager.get(mProvider.getContext());
+ if (userManager.getUserInfo(mUser) == null) {
+ perr.println("Invalid user: " + mUser);
+ return -1;
+ }
+
+ final IContentProvider iprovider = mProvider.getIContentProvider();
+ final PrintWriter pout = getOutPrintWriter();
+ switch (mVerb) {
+ case GET:
+ pout.println(getForUser(iprovider, mUser, mTable, mKey));
+ break;
+ case PUT:
+ putForUser(iprovider, mUser, mTable, mKey, mValue);
+ break;
+ case DELETE:
+ pout.println("Deleted "
+ + deleteForUser(iprovider, mUser, mTable, mKey) + " rows");
+ break;
+ case LIST:
+ for (String line : listForUser(iprovider, mUser, mTable)) {
+ pout.println(line);
+ }
+ break;
+ default:
+ perr.println("Unspecified command");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ private List<String> listForUser(IContentProvider provider, int userHandle, String table) {
+ final Uri uri = "system".equals(table) ? Settings.System.CONTENT_URI
+ : "secure".equals(table) ? Settings.Secure.CONTENT_URI
+ : "global".equals(table) ? Settings.Global.CONTENT_URI
+ : null;
+ final ArrayList<String> lines = new ArrayList<String>();
+ if (uri == null) {
+ return lines;
+ }
+ try {
+ final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null, null,
+ null, null);
+ try {
+ while (cursor != null && cursor.moveToNext()) {
+ lines.add(cursor.getString(1) + "=" + cursor.getString(2));
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ Collections.sort(lines);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed in IPC", e);
+ }
+ return lines;
+ }
+
+ String getForUser(IContentProvider provider, int userHandle,
+ final String table, final String key) {
+ final String callGetCommand;
+ if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM;
+ else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE;
+ else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL;
+ else {
+ getErrPrintWriter().println("Invalid table; no put performed");
+ throw new IllegalArgumentException("Invalid table " + table);
+ }
+
+ String result = null;
+ try {
+ Bundle arg = new Bundle();
+ arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+ Bundle b = provider.call(resolveCallingPackage(), callGetCommand, key, arg);
+ if (b != null) {
+ result = b.getPairValue();
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed in IPC", e);
+ }
+ return result;
+ }
+
+ void putForUser(IContentProvider provider, int userHandle,
+ final String table, final String key, final String value) {
+ final String callPutCommand;
+ if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
+ else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
+ else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
+ else {
+ getErrPrintWriter().println("Invalid table; no put performed");
+ return;
+ }
+
+ try {
+ Bundle arg = new Bundle();
+ arg.putString(Settings.NameValueTable.VALUE, value);
+ arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+ provider.call(resolveCallingPackage(), callPutCommand, key, arg);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed in IPC", e);
+ }
+ }
+
+ int deleteForUser(IContentProvider provider, int userHandle,
+ final String table, final String key) {
+ Uri targetUri;
+ if ("system".equals(table)) targetUri = Settings.System.getUriFor(key);
+ else if ("secure".equals(table)) targetUri = Settings.Secure.getUriFor(key);
+ else if ("global".equals(table)) targetUri = Settings.Global.getUriFor(key);
+ else {
+ getErrPrintWriter().println("Invalid table; no delete performed");
+ throw new IllegalArgumentException("Invalid table " + table);
+ }
+
+ int num = 0;
+ try {
+ num = provider.delete(resolveCallingPackage(), targetUri, null, null);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed in IPC", e);
+ }
+ return num;
+ }
+
+ public static String resolveCallingPackage() {
+ switch (Binder.getCallingUid()) {
+ case Process.ROOT_UID: {
+ return "root";
+ }
+
+ case Process.SHELL_UID: {
+ return "com.android.shell";
+ }
+
+ default: {
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ dumpHelp(pw, mDumping);
+ }
+
+ static void dumpHelp(PrintWriter pw, boolean dumping) {
+ if (dumping) {
+ pw.println("Settings provider dump options:");
+ pw.println(" [-h]");
+ pw.println(" -h: print this help.");
+ } else {
+ pw.println("Settings provider (settings) commands:");
+ pw.println(" help");
+ 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");
+ pw.println(" Change the contents of KEY to VALUE.");
+ pw.println(" delete NAMESPACE KEY");
+ pw.println(" Delete the entry for KEY.");
+ pw.println(" list NAMESPACE");
+ pw.println(" Print all defined keys.");
+ pw.println();
+ pw.println(" NAMESPACE is one of {system, secure, global}, case-insensitive");
+ }
+ }
+ }
+}
+
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 832c9d95cc60..d682fe9aa5f4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -350,8 +350,11 @@ final class SettingsState {
pw.print(" ");
pw.print(operation.mOperation);
if (operation.mSetting != null) {
- pw.print(" ");
- pw.print(operation.mSetting);
+ pw.print(" ");
+ // Only print the name of the setting, since we don't know the
+ // historical package and values for it so they would be misleading
+ // to print here (all we could print is what the current data is).
+ pw.print(operation.mSetting.getName());
}
pw.println();
}