Implement support for method calls in the content tool.

$ content call
    --uri content://com.example
    --method methodname
    [--arg optional_string_arg]
    [--extra name:s:foo --extra value:i:0]

The URI is just used to resolve the provider. --extra has
the same syntax as --bind.

Change-Id: I98cb89f0174a00e7c29ca0d8c8d809d453de3623
This commit is contained in:
Daniel Sandler
2013-01-29 13:47:04 -05:00
parent 572ec703d5
commit d2c0c1021e

View File

@@ -24,6 +24,7 @@ import android.content.IContentProvider;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -102,6 +103,12 @@ public class Content {
+ "equal to \"new_setting\" and sort the result by name in ascending order.\n"
+ " adb shell content query --uri content://settings/secure --projection name:value"
+ " --where \"name=\'new_setting\'\" --sort \"name ASC\"\n"
+ "\n"
+ "usage: adb shell content call --uri <URI> --method <METHOD> [--arg <ARG>]\n"
+ " [--extra <BINDING> ...]\n"
+ " <METHOD> is the name of a provider-defined method\n"
+ " <ARG> is an optional string argument\n"
+ " <BINDING> is like --bind above, typed data of the form <KEY>:{b,s,i,l,f,d}:<VAL>\n"
+ "\n";
private static class Parser {
@@ -109,12 +116,16 @@ public class Content {
private static final String ARGUMENT_DELETE = "delete";
private static final String ARGUMENT_UPDATE = "update";
private static final String ARGUMENT_QUERY = "query";
private static final String ARGUMENT_CALL = "call";
private static final String ARGUMENT_WHERE = "--where";
private static final String ARGUMENT_BIND = "--bind";
private static final String ARGUMENT_URI = "--uri";
private static final String ARGUMENT_USER = "--user";
private static final String ARGUMENT_PROJECTION = "--projection";
private static final String ARGUMENT_SORT = "--sort";
private static final String ARGUMENT_METHOD = "--method";
private static final String ARGUMENT_ARG = "--arg";
private static final String ARGUMENT_EXTRA = "--extra";
private static final String TYPE_BOOLEAN = "b";
private static final String TYPE_STRING = "s";
private static final String TYPE_INTEGER = "i";
@@ -141,6 +152,8 @@ public class Content {
return parseUpdateCommand();
} else if (ARGUMENT_QUERY.equals(operation)) {
return parseQueryCommand();
} else if (ARGUMENT_CALL.equals(operation)) {
return parseCallCommand();
} else {
throw new IllegalArgumentException("Unsupported operation: " + operation);
}
@@ -228,6 +241,38 @@ public class Content {
return new UpdateCommand(uri, userId, values, where);
}
public CallCommand parseCallCommand() {
String method = null;
int userId = UserHandle.USER_OWNER;
String arg = null;
Uri uri = null;
ContentValues values = new ContentValues();
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_METHOD.equals(argument)) {
method = argumentValueRequired(argument);
} else if (ARGUMENT_ARG.equals(argument)) {
arg = argumentValueRequired(argument);
} else if (ARGUMENT_EXTRA.equals(argument)) {
parseBindValue(values);
} else {
throw new IllegalArgumentException("Unsupported argument: " + argument);
}
}
if (uri == null) {
throw new IllegalArgumentException("Content provider URI not specified."
+ " Did you specify --uri argument?");
}
if (method == null) {
throw new IllegalArgumentException("Content provider method not specified.");
}
return new CallCommand(uri, userId, method, arg, values);
}
public QueryCommand parseQueryCommand() {
Uri uri = null;
int userId = UserHandle.USER_OWNER;
@@ -376,6 +421,43 @@ public class Content {
}
}
private static class CallCommand extends Command {
final String mMethod, mArg;
Bundle mExtras = null;
public CallCommand(Uri uri, int userId, String method, String arg, ContentValues values) {
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);
}
}
}
}
@Override
public void onExecute(IContentProvider provider) throws Exception {
Bundle result = provider.call(null, mMethod, mArg, mExtras);
final int size = result.size(); // unpack
System.out.println("Result: " + result);
}
}
private static class QueryCommand extends DeleteCommand {
final String[] mProjection;
final String mSortOrder;