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