settings command list by user

bug: 119872843
Test: $ adb -e shell settings list
Bad arguments
$ adb -e shell settings list secure
$ adb -e shell settings list gl
Invalid namespace 'gl'
$ adb -e shell settings list global
...
$ adb -e shell settings list --user 10 global
...
$ adb -e shell settings list --user 0 global
...
$ adb -e shell settings put --user 10 secure zzz.test true
$ adb -e shell settings get --user 10 secure zzz.test
true
$ adb -e shell settings get --user 0 secure zzz.test
null
$ adb -e shell settings list --user 0 secure
... zzz.test not present ...
$ adb -e shell settings list --user 10 secure
...
zzz.test=true

Change-Id: I8ab3d20cbe9221a52f85151d97e0c6d92bf7bb43
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 2227642..00ea45c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -186,6 +186,7 @@
             Settings.NameValueTable.VALUE, null);
 
     public static final String RESULT_ROWS_DELETED = "result_rows_deleted";
+    public static final String RESULT_SETTINGS_LIST = "result_settings_list";
 
     // Overlay specified settings whitelisted for Instant Apps
     private static final Set<String> OVERLAY_ALLOWED_GLOBAL_INSTANT_APP_SETTINGS = new ArraySet<>();
@@ -483,6 +484,27 @@
                 return result;
             }
 
+            case Settings.CALL_METHOD_LIST_SYSTEM: {
+                Bundle result = new Bundle();
+                result.putStringArrayList(RESULT_SETTINGS_LIST,
+                        buildSettingsList(getAllSystemSettings(requestingUserId, null)));
+                return result;
+            }
+
+            case Settings.CALL_METHOD_LIST_SECURE: {
+                Bundle result = new Bundle();
+                result.putStringArrayList(RESULT_SETTINGS_LIST,
+                        buildSettingsList(getAllSecureSettings(requestingUserId, null)));
+                return result;
+            }
+
+            case Settings.CALL_METHOD_LIST_GLOBAL: {
+                Bundle result = new Bundle();
+                result.putStringArrayList(RESULT_SETTINGS_LIST,
+                        buildSettingsList(getAllGlobalSettings(null)));
+                return result;
+            }
+
             default: {
                 Slog.w(LOG_TAG, "call() with invalid method: " + method);
             } break;
@@ -552,6 +574,20 @@
         }
     }
 
+    private ArrayList<String> buildSettingsList(Cursor cursor) {
+        final ArrayList<String> lines = new ArrayList<String>();
+        try {
+            while (cursor != null && cursor.moveToNext()) {
+                lines.add(cursor.getString(1) + "=" + cursor.getString(2));
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return lines;
+    }
+
     @Override
     public Uri insert(Uri uri, ContentValues values) {
         if (DEBUG) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index f8445fd..13537c4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -19,8 +19,6 @@
 import android.app.ActivityManager;
 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;
@@ -265,9 +263,6 @@
             }
             if (mUser < 0) {
                 mUser = UserHandle.USER_SYSTEM;
-            } else if (mVerb == CommandVerb.LIST) {
-                perr.println("--user not supported for list.");
-                return -1;
             }
             UserManager userManager = UserManager.get(mProvider.getContext());
             if (userManager.getUserInfo(mUser) == null) {
@@ -304,27 +299,22 @@
             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;
+        List<String> listForUser(IContentProvider provider, int userHandle, String table) {
+            final String callListCommand;
+            if ("system".equals(table)) callListCommand = Settings.CALL_METHOD_LIST_SYSTEM;
+            else if ("secure".equals(table)) callListCommand = Settings.CALL_METHOD_LIST_SECURE;
+            else if ("global".equals(table)) callListCommand = Settings.CALL_METHOD_LIST_GLOBAL;
+            else {
+                getErrPrintWriter().println("Invalid table; no list performed");
+                throw new IllegalArgumentException("Invalid table " + table);
             }
+            final ArrayList<String> lines = new ArrayList<String>();
             try {
-                final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null,
-                        null);
-                try {
-                    while (cursor != null && cursor.moveToNext()) {
-                        lines.add(cursor.getString(1) + "=" + cursor.getString(2));
-                    }
-                } finally {
-                    if (cursor != null) {
-                        cursor.close();
-                    }
-                }
+                Bundle arg = new Bundle();
+                arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+                Bundle result =
+                        provider.call(resolveCallingPackage(), callListCommand, null, arg);
+                lines.addAll(result.getStringArrayList(SettingsProvider.RESULT_SETTINGS_LIST));
                 Collections.sort(lines);
             } catch (RemoteException e) {
                 throw new RuntimeException("Failed in IPC", e);
@@ -483,7 +473,7 @@
                 pw.println("  reset [--user <USER_ID> | current] NAMESPACE {PACKAGE_NAME | RESET_MODE}");
                 pw.println("      Reset the global/secure table for a package with mode.");
                 pw.println("      RESET_MODE is one of {untrusted_defaults, untrusted_clear, trusted_defaults}, case-insensitive");
-                pw.println("  list NAMESPACE");
+                pw.println("  list [--user <USER_ID> | current] NAMESPACE");
                 pw.println("      Print all defined keys.");
                 pw.println("      NAMESPACE is one of {system, secure, global}, case-insensitive");
             }