blob: 3687f10f9974ca0424321003cc52e9ae1d97346e [file] [log] [blame]
Svetoslav Ganov25872aa2012-02-03 19:19:09 -08001/*
2** Copyright 2012, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17package com.android.commands.content;
18
Sudheer Shankadc589ac2016-11-10 15:30:17 -080019import android.app.ActivityManager;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070020import android.app.ContentProviderHolder;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080021import android.app.IActivityManager;
Steve McKayea93fe72016-12-02 11:35:35 -080022import android.content.ContentResolver;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080023import android.content.ContentValues;
24import android.content.IContentProvider;
25import android.database.Cursor;
26import android.net.Uri;
27import android.os.Binder;
Daniel Sandlerd2c0c102013-01-29 13:47:04 -050028import android.os.Bundle;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080029import android.os.IBinder;
John Spurlockcee823e2014-04-15 11:36:20 -040030import android.os.ParcelFileDescriptor;
Svetoslava8c61112015-03-02 16:21:35 -080031import android.os.Process;
Jeff Sharkey6d515712012-09-20 16:06:08 -070032import android.os.UserHandle;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080033import android.text.TextUtils;
34
John Spurlockcee823e2014-04-15 11:36:20 -040035import java.io.FileInputStream;
36import java.io.IOException;
37import java.io.InputStream;
38import java.io.OutputStream;
39
40import libcore.io.IoUtils;
41
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080042/**
43 * This class is a command line utility for manipulating content. A client
44 * can insert, update, and remove records in a content provider. For example,
45 * some settings may be configured before running the CTS tests, etc.
46 * <p>
47 * Examples:
48 * <ul>
49 * <li>
50 * # Add "new_setting" secure setting with value "new_value".</br>
51 * adb shell content insert --uri content://settings/secure --bind name:s:new_setting
52 * --bind value:s:new_value
53 * </li>
54 * <li>
55 * # Change "new_setting" secure setting to "newer_value" (You have to escape single quotes in
56 * the where clause).</br>
57 * adb shell content update --uri content://settings/secure --bind value:s:newer_value
58 * --where "name=\'new_setting\'"
59 * </li>
60 * <li>
61 * # Remove "new_setting" secure setting.</br>
62 * adb shell content delete --uri content://settings/secure --where "name=\'new_setting\'"
63 * </li>
64 * <li>
65 * # Query \"name\" and \"value\" columns from secure settings where \"name\" is equal to"
66 * \"new_setting\" and sort the result by name in ascending order.\n"
67 * adb shell content query --uri content://settings/secure --projection name:value
68 * --where "name=\'new_setting\'" --sort \"name ASC\"
69 * </li>
70 * </ul>
71 * </p>
72 */
73public class Content {
74
75 private static final String USAGE =
Makoto Onukice348812016-08-31 15:14:10 -070076 "usage: adb shell content [subcommand] [options]\n"
77 + "\n"
78 + "usage: adb shell content insert --uri <URI> [--user <USER_ID>]"
79 + " --bind <BINDING> [--bind <BINDING>...]\n"
80 + " <URI> a content provider URI.\n"
81 + " <BINDING> binds a typed value to a column and is formatted:\n"
82 + " <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:\n"
83 + " <TYPE> specifies data type such as:\n"
84 + " b - boolean, s - string, i - integer, l - long, f - float, d - double\n"
85 + " Note: Omit the value for passing an empty string, e.g column:s:\n"
86 + " Example:\n"
87 + " # Add \"new_setting\" secure setting with value \"new_value\".\n"
88 + " adb shell content insert --uri content://settings/secure --bind name:s:new_setting"
89 + " --bind value:s:new_value\n"
90 + "\n"
91 + "usage: adb shell content update --uri <URI> [--user <USER_ID>] [--where <WHERE>]\n"
92 + " <WHERE> is a SQL style where clause in quotes (You have to escape single quotes"
93 + " - see example below).\n"
94 + " Example:\n"
95 + " # Change \"new_setting\" secure setting to \"newer_value\".\n"
96 + " adb shell content update --uri content://settings/secure --bind"
97 + " value:s:newer_value --where \"name=\'new_setting\'\"\n"
98 + "\n"
99 + "usage: adb shell content delete --uri <URI> [--user <USER_ID>] --bind <BINDING>"
100 + " [--bind <BINDING>...] [--where <WHERE>]\n"
101 + " Example:\n"
102 + " # Remove \"new_setting\" secure setting.\n"
103 + " adb shell content delete --uri content://settings/secure "
104 + "--where \"name=\'new_setting\'\"\n"
105 + "\n"
106 + "usage: adb shell content query --uri <URI> [--user <USER_ID>]"
107 + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n"
108 + " <PROJECTION> is a list of colon separated column names and is formatted:\n"
109 + " <COLUMN_NAME>[:<COLUMN_NAME>...]\n"
110 + " <SORT_ORDER> is the order in which rows in the result should be sorted.\n"
111 + " Example:\n"
112 + " # Select \"name\" and \"value\" columns from secure settings where \"name\" is "
113 + "equal to \"new_setting\" and sort the result by name in ascending order.\n"
114 + " adb shell content query --uri content://settings/secure --projection name:value"
115 + " --where \"name=\'new_setting\'\" --sort \"name ASC\"\n"
116 + "\n"
117 + "usage: adb shell content call --uri <URI> --method <METHOD> [--arg <ARG>]\n"
118 + " [--extra <BINDING> ...]\n"
119 + " <METHOD> is the name of a provider-defined method\n"
120 + " <ARG> is an optional string argument\n"
121 + " <BINDING> is like --bind above, typed data of the form <KEY>:{b,s,i,l,f,d}:<VAL>\n"
122 + "\n"
123 + "usage: adb shell content read --uri <URI> [--user <USER_ID>]\n"
124 + " Example:\n"
125 + " # cat default ringtone to a file, then pull to host\n"
126 + " adb shell 'content read --uri content://settings/system/ringtone >"
127 + " /mnt/sdcard/tmp.ogg' && adb pull /mnt/sdcard/tmp.ogg\n"
128 + "\n"
129 + "usage: adb shell content gettype --uri <URI> [--user <USER_ID>]\n"
130 + " Example:\n"
131 + " # Show the mime-type of the URI\n"
132 + " adb shell content gettype --uri content://media/internal/audio/media/\n"
133 + "\n";
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800134
135 private static class Parser {
136 private static final String ARGUMENT_INSERT = "insert";
137 private static final String ARGUMENT_DELETE = "delete";
138 private static final String ARGUMENT_UPDATE = "update";
139 private static final String ARGUMENT_QUERY = "query";
Daniel Sandlerd2c0c102013-01-29 13:47:04 -0500140 private static final String ARGUMENT_CALL = "call";
John Spurlockcee823e2014-04-15 11:36:20 -0400141 private static final String ARGUMENT_READ = "read";
Makoto Onukice348812016-08-31 15:14:10 -0700142 private static final String ARGUMENT_GET_TYPE = "gettype";
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800143 private static final String ARGUMENT_WHERE = "--where";
144 private static final String ARGUMENT_BIND = "--bind";
145 private static final String ARGUMENT_URI = "--uri";
Jeff Sharkey6d515712012-09-20 16:06:08 -0700146 private static final String ARGUMENT_USER = "--user";
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800147 private static final String ARGUMENT_PROJECTION = "--projection";
148 private static final String ARGUMENT_SORT = "--sort";
Daniel Sandlerd2c0c102013-01-29 13:47:04 -0500149 private static final String ARGUMENT_METHOD = "--method";
150 private static final String ARGUMENT_ARG = "--arg";
151 private static final String ARGUMENT_EXTRA = "--extra";
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800152 private static final String TYPE_BOOLEAN = "b";
153 private static final String TYPE_STRING = "s";
154 private static final String TYPE_INTEGER = "i";
155 private static final String TYPE_LONG = "l";
156 private static final String TYPE_FLOAT = "f";
157 private static final String TYPE_DOUBLE = "d";
158 private static final String COLON = ":";
159 private static final String ARGUMENT_PREFIX = "--";
160
161 private final Tokenizer mTokenizer;
162
163 public Parser(String[] args) {
164 mTokenizer = new Tokenizer(args);
165 }
166
167 public Command parseCommand() {
168 try {
169 String operation = mTokenizer.nextArg();
170 if (ARGUMENT_INSERT.equals(operation)) {
171 return parseInsertCommand();
172 } else if (ARGUMENT_DELETE.equals(operation)) {
173 return parseDeleteCommand();
174 } else if (ARGUMENT_UPDATE.equals(operation)) {
175 return parseUpdateCommand();
176 } else if (ARGUMENT_QUERY.equals(operation)) {
177 return parseQueryCommand();
Daniel Sandlerd2c0c102013-01-29 13:47:04 -0500178 } else if (ARGUMENT_CALL.equals(operation)) {
179 return parseCallCommand();
John Spurlockcee823e2014-04-15 11:36:20 -0400180 } else if (ARGUMENT_READ.equals(operation)) {
181 return parseReadCommand();
Makoto Onukice348812016-08-31 15:14:10 -0700182 } else if (ARGUMENT_GET_TYPE.equals(operation)) {
183 return parseGetTypeCommand();
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800184 } else {
185 throw new IllegalArgumentException("Unsupported operation: " + operation);
186 }
187 } catch (IllegalArgumentException iae) {
188 System.out.println(USAGE);
189 System.out.println("[ERROR] " + iae.getMessage());
190 return null;
191 }
192 }
193
194 private InsertCommand parseInsertCommand() {
195 Uri uri = null;
Xiaohui Chenb52c7332015-08-06 14:05:35 -0700196 int userId = UserHandle.USER_SYSTEM;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800197 ContentValues values = new ContentValues();
198 for (String argument; (argument = mTokenizer.nextArg()) != null;) {
199 if (ARGUMENT_URI.equals(argument)) {
200 uri = Uri.parse(argumentValueRequired(argument));
Jeff Sharkey6d515712012-09-20 16:06:08 -0700201 } else if (ARGUMENT_USER.equals(argument)) {
202 userId = Integer.parseInt(argumentValueRequired(argument));
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800203 } else if (ARGUMENT_BIND.equals(argument)) {
204 parseBindValue(values);
205 } else {
206 throw new IllegalArgumentException("Unsupported argument: " + argument);
207 }
208 }
209 if (uri == null) {
210 throw new IllegalArgumentException("Content provider URI not specified."
211 + " Did you specify --uri argument?");
212 }
213 if (values.size() == 0) {
214 throw new IllegalArgumentException("Bindings not specified."
215 + " Did you specify --bind argument(s)?");
216 }
Jeff Sharkey6d515712012-09-20 16:06:08 -0700217 return new InsertCommand(uri, userId, values);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800218 }
219
220 private DeleteCommand parseDeleteCommand() {
221 Uri uri = null;
Xiaohui Chenb52c7332015-08-06 14:05:35 -0700222 int userId = UserHandle.USER_SYSTEM;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800223 String where = null;
224 for (String argument; (argument = mTokenizer.nextArg())!= null;) {
225 if (ARGUMENT_URI.equals(argument)) {
226 uri = Uri.parse(argumentValueRequired(argument));
Jeff Sharkey6d515712012-09-20 16:06:08 -0700227 } else if (ARGUMENT_USER.equals(argument)) {
228 userId = Integer.parseInt(argumentValueRequired(argument));
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800229 } else if (ARGUMENT_WHERE.equals(argument)) {
230 where = argumentValueRequired(argument);
231 } else {
232 throw new IllegalArgumentException("Unsupported argument: " + argument);
233 }
234 }
235 if (uri == null) {
236 throw new IllegalArgumentException("Content provider URI not specified."
237 + " Did you specify --uri argument?");
238 }
Jeff Sharkey6d515712012-09-20 16:06:08 -0700239 return new DeleteCommand(uri, userId, where);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800240 }
241
242 private UpdateCommand parseUpdateCommand() {
243 Uri uri = null;
Xiaohui Chenb52c7332015-08-06 14:05:35 -0700244 int userId = UserHandle.USER_SYSTEM;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800245 String where = null;
246 ContentValues values = new ContentValues();
247 for (String argument; (argument = mTokenizer.nextArg())!= null;) {
248 if (ARGUMENT_URI.equals(argument)) {
249 uri = Uri.parse(argumentValueRequired(argument));
Jeff Sharkey6d515712012-09-20 16:06:08 -0700250 } else if (ARGUMENT_USER.equals(argument)) {
251 userId = Integer.parseInt(argumentValueRequired(argument));
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800252 } else if (ARGUMENT_WHERE.equals(argument)) {
253 where = argumentValueRequired(argument);
254 } else if (ARGUMENT_BIND.equals(argument)) {
255 parseBindValue(values);
256 } else {
257 throw new IllegalArgumentException("Unsupported argument: " + argument);
258 }
259 }
260 if (uri == null) {
261 throw new IllegalArgumentException("Content provider URI not specified."
262 + " Did you specify --uri argument?");
263 }
264 if (values.size() == 0) {
265 throw new IllegalArgumentException("Bindings not specified."
266 + " Did you specify --bind argument(s)?");
267 }
Jeff Sharkey6d515712012-09-20 16:06:08 -0700268 return new UpdateCommand(uri, userId, values, where);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800269 }
270
Daniel Sandlerd2c0c102013-01-29 13:47:04 -0500271 public CallCommand parseCallCommand() {
272 String method = null;
Xiaohui Chenb52c7332015-08-06 14:05:35 -0700273 int userId = UserHandle.USER_SYSTEM;
Daniel Sandlerd2c0c102013-01-29 13:47:04 -0500274 String arg = null;
275 Uri uri = null;
276 ContentValues values = new ContentValues();
277 for (String argument; (argument = mTokenizer.nextArg())!= null;) {
278 if (ARGUMENT_URI.equals(argument)) {
279 uri = Uri.parse(argumentValueRequired(argument));
280 } else if (ARGUMENT_USER.equals(argument)) {
281 userId = Integer.parseInt(argumentValueRequired(argument));
282 } else if (ARGUMENT_METHOD.equals(argument)) {
283 method = argumentValueRequired(argument);
284 } else if (ARGUMENT_ARG.equals(argument)) {
285 arg = argumentValueRequired(argument);
286 } else if (ARGUMENT_EXTRA.equals(argument)) {
287 parseBindValue(values);
288 } else {
289 throw new IllegalArgumentException("Unsupported argument: " + argument);
290 }
291
292 }
293 if (uri == null) {
294 throw new IllegalArgumentException("Content provider URI not specified."
295 + " Did you specify --uri argument?");
296 }
297 if (method == null) {
298 throw new IllegalArgumentException("Content provider method not specified.");
299 }
300 return new CallCommand(uri, userId, method, arg, values);
301 }
302
Makoto Onukice348812016-08-31 15:14:10 -0700303 private GetTypeCommand parseGetTypeCommand() {
304 Uri uri = null;
305 int userId = UserHandle.USER_SYSTEM;
306
307 for (String argument; (argument = mTokenizer.nextArg()) != null;) {
308 if (ARGUMENT_URI.equals(argument)) {
309 uri = Uri.parse(argumentValueRequired(argument));
310 } else if (ARGUMENT_USER.equals(argument)) {
311 userId = Integer.parseInt(argumentValueRequired(argument));
312 } else {
313 throw new IllegalArgumentException("Unsupported argument: " + argument);
314 }
315 }
316 if (uri == null) {
317 throw new IllegalArgumentException("Content provider URI not specified."
318 + " Did you specify --uri argument?");
319 }
320 return new GetTypeCommand(uri, userId);
321 }
322
John Spurlockcee823e2014-04-15 11:36:20 -0400323 private ReadCommand parseReadCommand() {
324 Uri uri = null;
Xiaohui Chenb52c7332015-08-06 14:05:35 -0700325 int userId = UserHandle.USER_SYSTEM;
John Spurlockcee823e2014-04-15 11:36:20 -0400326 for (String argument; (argument = mTokenizer.nextArg())!= null;) {
327 if (ARGUMENT_URI.equals(argument)) {
328 uri = Uri.parse(argumentValueRequired(argument));
329 } else if (ARGUMENT_USER.equals(argument)) {
330 userId = Integer.parseInt(argumentValueRequired(argument));
331 } else {
332 throw new IllegalArgumentException("Unsupported argument: " + argument);
333 }
334 }
335 if (uri == null) {
336 throw new IllegalArgumentException("Content provider URI not specified."
337 + " Did you specify --uri argument?");
338 }
339 return new ReadCommand(uri, userId);
340 }
341
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800342 public QueryCommand parseQueryCommand() {
343 Uri uri = null;
Xiaohui Chenb52c7332015-08-06 14:05:35 -0700344 int userId = UserHandle.USER_SYSTEM;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800345 String[] projection = null;
346 String sort = null;
347 String where = null;
348 for (String argument; (argument = mTokenizer.nextArg())!= null;) {
349 if (ARGUMENT_URI.equals(argument)) {
350 uri = Uri.parse(argumentValueRequired(argument));
Jeff Sharkey6d515712012-09-20 16:06:08 -0700351 } else if (ARGUMENT_USER.equals(argument)) {
352 userId = Integer.parseInt(argumentValueRequired(argument));
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800353 } else if (ARGUMENT_WHERE.equals(argument)) {
354 where = argumentValueRequired(argument);
355 } else if (ARGUMENT_SORT.equals(argument)) {
356 sort = argumentValueRequired(argument);
357 } else if (ARGUMENT_PROJECTION.equals(argument)) {
358 projection = argumentValueRequired(argument).split("[\\s]*:[\\s]*");
359 } else {
360 throw new IllegalArgumentException("Unsupported argument: " + argument);
361 }
362 }
363 if (uri == null) {
364 throw new IllegalArgumentException("Content provider URI not specified."
365 + " Did you specify --uri argument?");
366 }
Jeff Sharkey6d515712012-09-20 16:06:08 -0700367 return new QueryCommand(uri, userId, projection, where, sort);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800368 }
369
370 private void parseBindValue(ContentValues values) {
371 String argument = mTokenizer.nextArg();
372 if (TextUtils.isEmpty(argument)) {
373 throw new IllegalArgumentException("Binding not well formed: " + argument);
374 }
Svetoslav Ganov8486bc12012-02-29 14:02:06 -0800375 final int firstColonIndex = argument.indexOf(COLON);
376 if (firstColonIndex < 0) {
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800377 throw new IllegalArgumentException("Binding not well formed: " + argument);
378 }
Svetoslav Ganov8486bc12012-02-29 14:02:06 -0800379 final int secondColonIndex = argument.indexOf(COLON, firstColonIndex + 1);
380 if (secondColonIndex < 0) {
381 throw new IllegalArgumentException("Binding not well formed: " + argument);
382 }
383 String column = argument.substring(0, firstColonIndex);
384 String type = argument.substring(firstColonIndex + 1, secondColonIndex);
385 String value = argument.substring(secondColonIndex + 1);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800386 if (TYPE_STRING.equals(type)) {
387 values.put(column, value);
388 } else if (TYPE_BOOLEAN.equalsIgnoreCase(type)) {
389 values.put(column, Boolean.parseBoolean(value));
390 } else if (TYPE_INTEGER.equalsIgnoreCase(type) || TYPE_LONG.equalsIgnoreCase(type)) {
391 values.put(column, Long.parseLong(value));
392 } else if (TYPE_FLOAT.equalsIgnoreCase(type) || TYPE_DOUBLE.equalsIgnoreCase(type)) {
393 values.put(column, Double.parseDouble(value));
394 } else {
395 throw new IllegalArgumentException("Unsupported type: " + type);
396 }
397 }
398
399 private String argumentValueRequired(String argument) {
400 String value = mTokenizer.nextArg();
401 if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) {
402 throw new IllegalArgumentException("No value for argument: " + argument);
403 }
404 return value;
405 }
406 }
407
408 private static class Tokenizer {
409 private final String[] mArgs;
410 private int mNextArg;
411
412 public Tokenizer(String[] args) {
413 mArgs = args;
414 }
415
416 private String nextArg() {
417 if (mNextArg < mArgs.length) {
418 return mArgs[mNextArg++];
419 } else {
420 return null;
421 }
422 }
423 }
424
425 private static abstract class Command {
426 final Uri mUri;
Jeff Sharkey6d515712012-09-20 16:06:08 -0700427 final int mUserId;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800428
Jeff Sharkey6d515712012-09-20 16:06:08 -0700429 public Command(Uri uri, int userId) {
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800430 mUri = uri;
Jeff Sharkey6d515712012-09-20 16:06:08 -0700431 mUserId = userId;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800432 }
433
434 public final void execute() {
435 String providerName = mUri.getAuthority();
436 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800437 IActivityManager activityManager = ActivityManager.getService();
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800438 IContentProvider provider = null;
439 IBinder token = new Binder();
440 try {
441 ContentProviderHolder holder = activityManager.getContentProviderExternal(
Jeff Sharkey6d515712012-09-20 16:06:08 -0700442 providerName, mUserId, token);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800443 if (holder == null) {
444 throw new IllegalStateException("Could not find provider: " + providerName);
445 }
446 provider = holder.provider;
447 onExecute(provider);
448 } finally {
449 if (provider != null) {
450 activityManager.removeContentProviderExternal(providerName, token);
451 }
452 }
453 } catch (Exception e) {
454 System.err.println("Error while accessing provider:" + providerName);
455 e.printStackTrace();
456 }
457 }
458
Svetoslava8c61112015-03-02 16:21:35 -0800459 public static String resolveCallingPackage() {
460 switch (Process.myUid()) {
461 case Process.ROOT_UID: {
462 return "root";
463 }
464
465 case Process.SHELL_UID: {
466 return "com.android.shell";
467 }
468
469 default: {
470 return null;
471 }
472 }
473 }
474
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800475 protected abstract void onExecute(IContentProvider provider) throws Exception;
476 }
477
478 private static class InsertCommand extends Command {
479 final ContentValues mContentValues;
480
Jeff Sharkey6d515712012-09-20 16:06:08 -0700481 public InsertCommand(Uri uri, int userId, ContentValues contentValues) {
482 super(uri, userId);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800483 mContentValues = contentValues;
484 }
485
486 @Override
487 public void onExecute(IContentProvider provider) throws Exception {
Svetoslava8c61112015-03-02 16:21:35 -0800488 provider.insert(resolveCallingPackage(), mUri, mContentValues);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800489 }
490 }
491
492 private static class DeleteCommand extends Command {
493 final String mWhere;
494
Jeff Sharkey6d515712012-09-20 16:06:08 -0700495 public DeleteCommand(Uri uri, int userId, String where) {
496 super(uri, userId);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800497 mWhere = where;
498 }
499
500 @Override
501 public void onExecute(IContentProvider provider) throws Exception {
Svetoslava8c61112015-03-02 16:21:35 -0800502 provider.delete(resolveCallingPackage(), mUri, mWhere, null);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800503 }
504 }
505
Daniel Sandlerd2c0c102013-01-29 13:47:04 -0500506 private static class CallCommand extends Command {
507 final String mMethod, mArg;
508 Bundle mExtras = null;
509
510 public CallCommand(Uri uri, int userId, String method, String arg, ContentValues values) {
511 super(uri, userId);
512 mMethod = method;
513 mArg = arg;
514 if (values != null) {
515 mExtras = new Bundle();
516 for (String key : values.keySet()) {
517 final Object val = values.get(key);
518 if (val instanceof String) {
519 mExtras.putString(key, (String) val);
520 } else if (val instanceof Float) {
521 mExtras.putFloat(key, (Float) val);
522 } else if (val instanceof Double) {
523 mExtras.putDouble(key, (Double) val);
524 } else if (val instanceof Boolean) {
525 mExtras.putBoolean(key, (Boolean) val);
526 } else if (val instanceof Integer) {
527 mExtras.putInt(key, (Integer) val);
528 } else if (val instanceof Long) {
529 mExtras.putLong(key, (Long) val);
530 }
531 }
532 }
533 }
534
535 @Override
536 public void onExecute(IContentProvider provider) throws Exception {
537 Bundle result = provider.call(null, mMethod, mArg, mExtras);
538 final int size = result.size(); // unpack
539 System.out.println("Result: " + result);
540 }
541 }
542
Makoto Onukice348812016-08-31 15:14:10 -0700543 private static class GetTypeCommand extends Command {
544 public GetTypeCommand(Uri uri, int userId) {
545 super(uri, userId);
546 }
547
548 @Override
549 public void onExecute(IContentProvider provider) throws Exception {
550 String type = provider.getType(mUri);
551 System.out.println("Result: " + type);
552 }
553 }
554
John Spurlockcee823e2014-04-15 11:36:20 -0400555 private static class ReadCommand extends Command {
556 public ReadCommand(Uri uri, int userId) {
557 super(uri, userId);
558 }
559
560 @Override
561 public void onExecute(IContentProvider provider) throws Exception {
Dianne Hackbornff170242014-11-19 10:59:01 -0800562 final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null, null);
John Spurlockcee823e2014-04-15 11:36:20 -0400563 copy(new FileInputStream(fd.getFileDescriptor()), System.out);
564 }
565
566 private static void copy(InputStream is, OutputStream os) throws IOException {
567 final byte[] buffer = new byte[8 * 1024];
568 int read;
569 try {
570 while ((read = is.read(buffer)) > -1) {
571 os.write(buffer, 0, read);
572 }
573 } finally {
574 IoUtils.closeQuietly(is);
575 IoUtils.closeQuietly(os);
576 }
577 }
578 }
579
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800580 private static class QueryCommand extends DeleteCommand {
581 final String[] mProjection;
582 final String mSortOrder;
583
Jeff Sharkey6d515712012-09-20 16:06:08 -0700584 public QueryCommand(
585 Uri uri, int userId, String[] projection, String where, String sortOrder) {
586 super(uri, userId, where);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800587 mProjection = projection;
588 mSortOrder = sortOrder;
589 }
590
591 @Override
592 public void onExecute(IContentProvider provider) throws Exception {
Steve McKayea93fe72016-12-02 11:35:35 -0800593 Cursor cursor = provider.query(resolveCallingPackage(), mUri, mProjection,
594 ContentResolver.createSqlQueryBundle(mWhere, null, mSortOrder), null);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800595 if (cursor == null) {
596 System.out.println("No result found.");
597 return;
598 }
599 try {
600 if (cursor.moveToFirst()) {
601 int rowIndex = 0;
602 StringBuilder builder = new StringBuilder();
603 do {
604 builder.setLength(0);
605 builder.append("Row: ").append(rowIndex).append(" ");
606 rowIndex++;
607 final int columnCount = cursor.getColumnCount();
608 for (int i = 0; i < columnCount; i++) {
609 if (i > 0) {
610 builder.append(", ");
611 }
612 String columnName = cursor.getColumnName(i);
613 String columnValue = null;
614 final int columnIndex = cursor.getColumnIndex(columnName);
615 final int type = cursor.getType(columnIndex);
616 switch (type) {
617 case Cursor.FIELD_TYPE_FLOAT:
618 columnValue = String.valueOf(cursor.getFloat(columnIndex));
619 break;
620 case Cursor.FIELD_TYPE_INTEGER:
Marco Nelissen8964cbb2013-12-20 14:09:22 -0800621 columnValue = String.valueOf(cursor.getLong(columnIndex));
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800622 break;
623 case Cursor.FIELD_TYPE_STRING:
624 columnValue = cursor.getString(columnIndex);
625 break;
626 case Cursor.FIELD_TYPE_BLOB:
627 columnValue = "BLOB";
628 break;
629 case Cursor.FIELD_TYPE_NULL:
630 columnValue = "NULL";
631 break;
632 }
633 builder.append(columnName).append("=").append(columnValue);
634 }
635 System.out.println(builder);
636 } while (cursor.moveToNext());
637 } else {
Marco Nelissena4256d12012-11-01 13:55:28 -0700638 System.out.println("No result found.");
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800639 }
640 } finally {
641 cursor.close();
642 }
643 }
644 }
645
646 private static class UpdateCommand extends InsertCommand {
647 final String mWhere;
648
Jeff Sharkey6d515712012-09-20 16:06:08 -0700649 public UpdateCommand(Uri uri, int userId, ContentValues contentValues, String where) {
650 super(uri, userId, contentValues);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800651 mWhere = where;
652 }
653
654 @Override
655 public void onExecute(IContentProvider provider) throws Exception {
Svetoslava8c61112015-03-02 16:21:35 -0800656 provider.update(resolveCallingPackage(), mUri, mContentValues, mWhere, null);
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800657 }
658 }
659
660 public static void main(String[] args) {
661 Parser parser = new Parser(args);
662 Command command = parser.parseCommand();
663 if (command != null) {
664 command.execute();
665 }
666 }
667}