diff options
Diffstat (limited to 'cmds/content/src')
-rw-r--r-- | cmds/content/src/com/android/commands/content/Content.java | 193 |
1 files changed, 114 insertions, 79 deletions
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java index 59544a971e5f..ca1d598ee7d7 100644 --- a/cmds/content/src/com/android/commands/content/Content.java +++ b/cmds/content/src/com/android/commands/content/Content.java @@ -32,8 +32,11 @@ import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.UserHandle; import android.text.TextUtils; +import android.util.Pair; import java.io.FileDescriptor; +import java.util.ArrayList; +import java.util.List; /** * This class is a command line utility for manipulating content. A client @@ -72,7 +75,7 @@ public class Content { "usage: adb shell content [subcommand] [options]\n" + "\n" + "usage: adb shell content insert --uri <URI> [--user <USER_ID>]" - + " --bind <BINDING> [--bind <BINDING>...]\n" + + " --bind <BINDING> [--bind <BINDING>...] [--extra <BINDING>...]\n" + " <URI> a content provider URI.\n" + " <BINDING> binds a typed value to a column and is formatted:\n" + " <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:\n" @@ -84,7 +87,8 @@ public class Content { + " adb shell content insert --uri content://settings/secure --bind name:s:new_setting" + " --bind value:s:new_value\n" + "\n" - + "usage: adb shell content update --uri <URI> [--user <USER_ID>] [--where <WHERE>]\n" + + "usage: adb shell content update --uri <URI> [--user <USER_ID>]" + + " [--where <WHERE>] [--extra <BINDING>...]\n" + " <WHERE> is a SQL style where clause in quotes (You have to escape single quotes" + " - see example below).\n" + " Example:\n" @@ -93,14 +97,15 @@ public class Content { + " value:s:newer_value --where \"name=\'new_setting\'\"\n" + "\n" + "usage: adb shell content delete --uri <URI> [--user <USER_ID>] --bind <BINDING>" - + " [--bind <BINDING>...] [--where <WHERE>]\n" + + " [--bind <BINDING>...] [--where <WHERE>] [--extra <BINDING>...]\n" + " Example:\n" + " # Remove \"new_setting\" secure setting.\n" + " adb shell content delete --uri content://settings/secure " + "--where \"name=\'new_setting\'\"\n" + "\n" + "usage: adb shell content query --uri <URI> [--user <USER_ID>]" - + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n" + + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]" + + " [--extra <BINDING>...]\n" + " <PROJECTION> is a list of colon separated column names and is formatted:\n" + " <COLUMN_NAME>[:<COLUMN_NAME>...]\n" + " <SORT_ORDER> is the order in which rows in the result should be sorted.\n" @@ -196,6 +201,7 @@ public class Content { Uri uri = null; int userId = UserHandle.USER_SYSTEM; ContentValues values = new ContentValues(); + Bundle extras = new Bundle(); for (String argument; (argument = mTokenizer.nextArg()) != null;) { if (ARGUMENT_URI.equals(argument)) { uri = Uri.parse(argumentValueRequired(argument)); @@ -203,6 +209,8 @@ public class Content { userId = Integer.parseInt(argumentValueRequired(argument)); } else if (ARGUMENT_BIND.equals(argument)) { parseBindValue(values); + } else if (ARGUMENT_EXTRA.equals(argument)) { + parseBindValue(extras); } else { throw new IllegalArgumentException("Unsupported argument: " + argument); } @@ -215,20 +223,23 @@ public class Content { throw new IllegalArgumentException("Bindings not specified." + " Did you specify --bind argument(s)?"); } - return new InsertCommand(uri, userId, values); + return new InsertCommand(uri, userId, values, extras); } private DeleteCommand parseDeleteCommand() { Uri uri = null; int userId = UserHandle.USER_SYSTEM; - String where = null; + Bundle extras = new Bundle(); for (String argument; (argument = mTokenizer.nextArg())!= null;) { if (ARGUMENT_URI.equals(argument)) { uri = Uri.parse(argumentValueRequired(argument)); } else if (ARGUMENT_USER.equals(argument)) { userId = Integer.parseInt(argumentValueRequired(argument)); } else if (ARGUMENT_WHERE.equals(argument)) { - where = argumentValueRequired(argument); + extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, + argumentValueRequired(argument)); + } else if (ARGUMENT_EXTRA.equals(argument)) { + parseBindValue(extras); } else { throw new IllegalArgumentException("Unsupported argument: " + argument); } @@ -237,23 +248,26 @@ public class Content { throw new IllegalArgumentException("Content provider URI not specified." + " Did you specify --uri argument?"); } - return new DeleteCommand(uri, userId, where); + return new DeleteCommand(uri, userId, extras); } private UpdateCommand parseUpdateCommand() { Uri uri = null; int userId = UserHandle.USER_SYSTEM; - String where = null; ContentValues values = new ContentValues(); + Bundle extras = new Bundle(); for (String argument; (argument = mTokenizer.nextArg())!= null;) { if (ARGUMENT_URI.equals(argument)) { uri = Uri.parse(argumentValueRequired(argument)); } else if (ARGUMENT_USER.equals(argument)) { userId = Integer.parseInt(argumentValueRequired(argument)); } else if (ARGUMENT_WHERE.equals(argument)) { - where = argumentValueRequired(argument); + extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, + argumentValueRequired(argument)); } else if (ARGUMENT_BIND.equals(argument)) { parseBindValue(values); + } else if (ARGUMENT_EXTRA.equals(argument)) { + parseBindValue(extras); } else { throw new IllegalArgumentException("Unsupported argument: " + argument); } @@ -266,7 +280,7 @@ public class Content { throw new IllegalArgumentException("Bindings not specified." + " Did you specify --bind argument(s)?"); } - return new UpdateCommand(uri, userId, values, where); + return new UpdateCommand(uri, userId, values, extras); } public CallCommand parseCallCommand() { @@ -274,7 +288,7 @@ public class Content { int userId = UserHandle.USER_SYSTEM; String arg = null; Uri uri = null; - ContentValues values = new ContentValues(); + Bundle extras = new Bundle(); for (String argument; (argument = mTokenizer.nextArg())!= null;) { if (ARGUMENT_URI.equals(argument)) { uri = Uri.parse(argumentValueRequired(argument)); @@ -285,11 +299,10 @@ public class Content { } else if (ARGUMENT_ARG.equals(argument)) { arg = argumentValueRequired(argument); } else if (ARGUMENT_EXTRA.equals(argument)) { - parseBindValue(values); + parseBindValue(extras); } else { throw new IllegalArgumentException("Unsupported argument: " + argument); } - } if (uri == null) { throw new IllegalArgumentException("Content provider URI not specified." @@ -298,7 +311,7 @@ public class Content { if (method == null) { throw new IllegalArgumentException("Content provider method not specified."); } - return new CallCommand(uri, userId, method, arg, values); + return new CallCommand(uri, userId, method, arg, extras); } private GetTypeCommand parseGetTypeCommand() { @@ -363,19 +376,22 @@ public class Content { Uri uri = null; int userId = UserHandle.USER_SYSTEM; String[] projection = null; - String sort = null; - String where = null; + Bundle extras = new Bundle(); for (String argument; (argument = mTokenizer.nextArg())!= null;) { if (ARGUMENT_URI.equals(argument)) { uri = Uri.parse(argumentValueRequired(argument)); } else if (ARGUMENT_USER.equals(argument)) { userId = Integer.parseInt(argumentValueRequired(argument)); } else if (ARGUMENT_WHERE.equals(argument)) { - where = argumentValueRequired(argument); + extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, + argumentValueRequired(argument)); } else if (ARGUMENT_SORT.equals(argument)) { - sort = argumentValueRequired(argument); + extras.putString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER, + argumentValueRequired(argument)); } else if (ARGUMENT_PROJECTION.equals(argument)) { projection = argumentValueRequired(argument).split("[\\s]*:[\\s]*"); + } else if (ARGUMENT_EXTRA.equals(argument)) { + parseBindValue(extras); } else { throw new IllegalArgumentException("Unsupported argument: " + argument); } @@ -384,40 +400,76 @@ public class Content { throw new IllegalArgumentException("Content provider URI not specified." + " Did you specify --uri argument?"); } - return new QueryCommand(uri, userId, projection, where, sort); + return new QueryCommand(uri, userId, projection, extras); + } + + private List<String> splitWithEscaping(String argument, char splitChar) { + final List<String> res = new ArrayList<>(); + final StringBuilder cur = new StringBuilder(); + for (int i = 0; i < argument.length(); i++) { + char c = argument.charAt(i); + if (c == '\\') { + if (++i == argument.length()) { + throw new IllegalArgumentException("Invalid escaping"); + } else { + // Skip escaping char and insert next + c = argument.charAt(i); + cur.append(c); + } + } else if (c == splitChar) { + // Splitting char means next string + res.add(cur.toString()); + cur.setLength(0); + } else { + // Copy non-escaping and non-splitting char + cur.append(c); + } + } + res.add(cur.toString()); + return res; } - private void parseBindValue(ContentValues values) { + private Pair<String, Object> parseBindValue() { String argument = mTokenizer.nextArg(); if (TextUtils.isEmpty(argument)) { throw new IllegalArgumentException("Binding not well formed: " + argument); } - final int firstColonIndex = argument.indexOf(COLON); - if (firstColonIndex < 0) { + final List<String> split = splitWithEscaping(argument, COLON.charAt(0)); + if (split.size() != 3) { throw new IllegalArgumentException("Binding not well formed: " + argument); } - final int secondColonIndex = argument.indexOf(COLON, firstColonIndex + 1); - if (secondColonIndex < 0) { - throw new IllegalArgumentException("Binding not well formed: " + argument); - } - String column = argument.substring(0, firstColonIndex); - String type = argument.substring(firstColonIndex + 1, secondColonIndex); - String value = argument.substring(secondColonIndex + 1); + String column = split.get(0); + String type = split.get(1); + String value = split.get(2); if (TYPE_STRING.equals(type)) { - values.put(column, value); + return Pair.create(column, value); } else if (TYPE_BOOLEAN.equalsIgnoreCase(type)) { - values.put(column, Boolean.parseBoolean(value)); - } else if (TYPE_INTEGER.equalsIgnoreCase(type) || TYPE_LONG.equalsIgnoreCase(type)) { - values.put(column, Long.parseLong(value)); - } else if (TYPE_FLOAT.equalsIgnoreCase(type) || TYPE_DOUBLE.equalsIgnoreCase(type)) { - values.put(column, Double.parseDouble(value)); + return Pair.create(column, Boolean.parseBoolean(value)); + } else if (TYPE_INTEGER.equalsIgnoreCase(type)) { + return Pair.create(column, Integer.parseInt(value)); + } else if (TYPE_LONG.equalsIgnoreCase(type)) { + return Pair.create(column, Long.parseLong(value)); + } else if (TYPE_FLOAT.equalsIgnoreCase(type)) { + return Pair.create(column, Float.parseFloat(value)); + } else if (TYPE_DOUBLE.equalsIgnoreCase(type)) { + return Pair.create(column, Double.parseDouble(value)); } else if (TYPE_NULL.equalsIgnoreCase(type)) { - values.putNull(column); + return Pair.create(column, null); } else { throw new IllegalArgumentException("Unsupported type: " + type); } } + private void parseBindValue(ContentValues values) { + final Pair<String, Object> columnValue = parseBindValue(); + values.putObject(columnValue.first, columnValue.second); + } + + private void parseBindValue(Bundle extras) { + final Pair<String, Object> columnValue = parseBindValue(); + extras.putObject(columnValue.first, columnValue.second); + } + private String argumentValueRequired(String argument) { String value = mTokenizer.nextArg(); if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) { @@ -500,60 +552,43 @@ public class Content { private static class InsertCommand extends Command { final ContentValues mContentValues; + final Bundle mExtras; - public InsertCommand(Uri uri, int userId, ContentValues contentValues) { + public InsertCommand(Uri uri, int userId, ContentValues contentValues, Bundle extras) { super(uri, userId); mContentValues = contentValues; + mExtras = extras; } @Override public void onExecute(IContentProvider provider) throws Exception { - provider.insert(resolveCallingPackage(), null, mUri, mContentValues, null); + provider.insert(resolveCallingPackage(), null, mUri, mContentValues, mExtras); } } private static class DeleteCommand extends Command { - final String mWhere; + final Bundle mExtras; - public DeleteCommand(Uri uri, int userId, String where) { + public DeleteCommand(Uri uri, int userId, Bundle extras) { super(uri, userId); - mWhere = where; + mExtras = extras; } @Override public void onExecute(IContentProvider provider) throws Exception { - provider.delete(resolveCallingPackage(), null, mUri, - ContentResolver.createSqlQueryBundle(mWhere, null)); + provider.delete(resolveCallingPackage(), null, mUri, mExtras); } } private static class CallCommand extends Command { final String mMethod, mArg; - Bundle mExtras = null; + final Bundle mExtras; - public CallCommand(Uri uri, int userId, String method, String arg, ContentValues values) { + public CallCommand(Uri uri, int userId, String method, String arg, Bundle extras) { super(uri, userId); mMethod = method; mArg = arg; - if (values != null) { - mExtras = new Bundle(); - for (String key : values.keySet()) { - final Object val = values.get(key); - if (val instanceof String) { - mExtras.putString(key, (String) val); - } else if (val instanceof Float) { - mExtras.putFloat(key, (Float) val); - } else if (val instanceof Double) { - mExtras.putDouble(key, (Double) val); - } else if (val instanceof Boolean) { - mExtras.putBoolean(key, (Boolean) val); - } else if (val instanceof Integer) { - mExtras.putInt(key, (Integer) val); - } else if (val instanceof Long) { - mExtras.putLong(key, (Long) val); - } - } - } + mExtras = extras; } @Override @@ -604,21 +639,20 @@ public class Content { } } - private static class QueryCommand extends DeleteCommand { + private static class QueryCommand extends Command { final String[] mProjection; - final String mSortOrder; + final Bundle mExtras; - public QueryCommand( - Uri uri, int userId, String[] projection, String where, String sortOrder) { - super(uri, userId, where); + public QueryCommand(Uri uri, int userId, String[] projection, Bundle extras) { + super(uri, userId); mProjection = projection; - mSortOrder = sortOrder; + mExtras = extras; } @Override public void onExecute(IContentProvider provider) throws Exception { Cursor cursor = provider.query(resolveCallingPackage(), null, mUri, mProjection, - ContentResolver.createSqlQueryBundle(mWhere, null, mSortOrder), null); + mExtras, null); if (cursor == null) { System.out.println("No result found."); return; @@ -670,18 +704,19 @@ public class Content { } } - private static class UpdateCommand extends InsertCommand { - final String mWhere; + private static class UpdateCommand extends Command { + final ContentValues mValues; + final Bundle mExtras; - public UpdateCommand(Uri uri, int userId, ContentValues contentValues, String where) { - super(uri, userId, contentValues); - mWhere = where; + public UpdateCommand(Uri uri, int userId, ContentValues values, Bundle extras) { + super(uri, userId); + mValues = values; + mExtras = extras; } @Override public void onExecute(IContentProvider provider) throws Exception { - provider.update(resolveCallingPackage(), null, mUri, mContentValues, - ContentResolver.createSqlQueryBundle(mWhere, null)); + provider.update(resolveCallingPackage(), null, mUri, mValues, mExtras); } } |