PageRenderTime 84ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/frameworks/base/cmds/content/src/com/android/commands/content/Content.java

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
Java | 465 lines | 385 code | 34 blank | 46 comment | 86 complexity | 0c66265827af9a55c7be160c507729d1 MD5 | raw file
  1. /*
  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. package com.android.commands.content;
  17. import android.app.ActivityManagerNative;
  18. import android.app.IActivityManager;
  19. import android.app.IActivityManager.ContentProviderHolder;
  20. import android.content.ContentValues;
  21. import android.content.IContentProvider;
  22. import android.database.Cursor;
  23. import android.net.Uri;
  24. import android.os.Binder;
  25. import android.os.IBinder;
  26. import android.os.UserHandle;
  27. import android.text.TextUtils;
  28. /**
  29. * This class is a command line utility for manipulating content. A client
  30. * can insert, update, and remove records in a content provider. For example,
  31. * some settings may be configured before running the CTS tests, etc.
  32. * <p>
  33. * Examples:
  34. * <ul>
  35. * <li>
  36. * # Add "new_setting" secure setting with value "new_value".</br>
  37. * adb shell content insert --uri content://settings/secure --bind name:s:new_setting
  38. * --bind value:s:new_value
  39. * </li>
  40. * <li>
  41. * # Change "new_setting" secure setting to "newer_value" (You have to escape single quotes in
  42. * the where clause).</br>
  43. * adb shell content update --uri content://settings/secure --bind value:s:newer_value
  44. * --where "name=\'new_setting\'"
  45. * </li>
  46. * <li>
  47. * # Remove "new_setting" secure setting.</br>
  48. * adb shell content delete --uri content://settings/secure --where "name=\'new_setting\'"
  49. * </li>
  50. * <li>
  51. * # Query \"name\" and \"value\" columns from secure settings where \"name\" is equal to"
  52. * \"new_setting\" and sort the result by name in ascending order.\n"
  53. * adb shell content query --uri content://settings/secure --projection name:value
  54. * --where "name=\'new_setting\'" --sort \"name ASC\"
  55. * </li>
  56. * </ul>
  57. * </p>
  58. */
  59. public class Content {
  60. private static final String USAGE =
  61. "usage: adb shell content [subcommand] [options]\n"
  62. + "\n"
  63. + "usage: adb shell content insert --uri <URI> [--user <USER_ID>]"
  64. + " --bind <BINDING> [--bind <BINDING>...]\n"
  65. + " <URI> a content provider URI.\n"
  66. + " <BINDING> binds a typed value to a column and is formatted:\n"
  67. + " <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:\n"
  68. + " <TYPE> specifies data type such as:\n"
  69. + " b - boolean, s - string, i - integer, l - long, f - float, d - double\n"
  70. + " Note: Omit the value for passing an empty string, e.g column:s:\n"
  71. + " Example:\n"
  72. + " # Add \"new_setting\" secure setting with value \"new_value\".\n"
  73. + " adb shell content insert --uri content://settings/secure --bind name:s:new_setting"
  74. + " --bind value:s:new_value\n"
  75. + "\n"
  76. + "usage: adb shell content update --uri <URI> [--user <USER_ID>] [--where <WHERE>]\n"
  77. + " <WHERE> is a SQL style where clause in quotes (You have to escape single quotes"
  78. + " - see example below).\n"
  79. + " Example:\n"
  80. + " # Change \"new_setting\" secure setting to \"newer_value\".\n"
  81. + " adb shell content update --uri content://settings/secure --bind"
  82. + " value:s:newer_value --where \"name=\\'new_setting\\'\"\n"
  83. + "\n"
  84. + "usage: adb shell content delete --uri <URI> [--user <USER_ID>] --bind <BINDING>"
  85. + " [--bind <BINDING>...] [--where <WHERE>]\n"
  86. + " Example:\n"
  87. + " # Remove \"new_setting\" secure setting.\n"
  88. + " adb shell content delete --uri content://settings/secure "
  89. + "--where \"name=\\'new_setting\\'\"\n"
  90. + "\n"
  91. + "usage: adb shell content query --uri <URI> [--user <USER_ID>]"
  92. + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n"
  93. + " <PROJECTION> is a list of colon separated column names and is formatted:\n"
  94. + " <COLUMN_NAME>[:<COLUMN_NAME>...]\n"
  95. + " <SORT_OREDER> is the order in which rows in the result should be sorted.\n"
  96. + " Example:\n"
  97. + " # Select \"name\" and \"value\" columns from secure settings where \"name\" is "
  98. + "equal to \"new_setting\" and sort the result by name in ascending order.\n"
  99. + " adb shell content query --uri content://settings/secure --projection name:value"
  100. + " --where \"name=\\'new_setting\\'\" --sort \"name ASC\"\n"
  101. + "\n";
  102. private static class Parser {
  103. private static final String ARGUMENT_INSERT = "insert";
  104. private static final String ARGUMENT_DELETE = "delete";
  105. private static final String ARGUMENT_UPDATE = "update";
  106. private static final String ARGUMENT_QUERY = "query";
  107. private static final String ARGUMENT_WHERE = "--where";
  108. private static final String ARGUMENT_BIND = "--bind";
  109. private static final String ARGUMENT_URI = "--uri";
  110. private static final String ARGUMENT_USER = "--user";
  111. private static final String ARGUMENT_PROJECTION = "--projection";
  112. private static final String ARGUMENT_SORT = "--sort";
  113. private static final String TYPE_BOOLEAN = "b";
  114. private static final String TYPE_STRING = "s";
  115. private static final String TYPE_INTEGER = "i";
  116. private static final String TYPE_LONG = "l";
  117. private static final String TYPE_FLOAT = "f";
  118. private static final String TYPE_DOUBLE = "d";
  119. private static final String COLON = ":";
  120. private static final String ARGUMENT_PREFIX = "--";
  121. private final Tokenizer mTokenizer;
  122. public Parser(String[] args) {
  123. mTokenizer = new Tokenizer(args);
  124. }
  125. public Command parseCommand() {
  126. try {
  127. String operation = mTokenizer.nextArg();
  128. if (ARGUMENT_INSERT.equals(operation)) {
  129. return parseInsertCommand();
  130. } else if (ARGUMENT_DELETE.equals(operation)) {
  131. return parseDeleteCommand();
  132. } else if (ARGUMENT_UPDATE.equals(operation)) {
  133. return parseUpdateCommand();
  134. } else if (ARGUMENT_QUERY.equals(operation)) {
  135. return parseQueryCommand();
  136. } else {
  137. throw new IllegalArgumentException("Unsupported operation: " + operation);
  138. }
  139. } catch (IllegalArgumentException iae) {
  140. System.out.println(USAGE);
  141. System.out.println("[ERROR] " + iae.getMessage());
  142. return null;
  143. }
  144. }
  145. private InsertCommand parseInsertCommand() {
  146. Uri uri = null;
  147. int userId = UserHandle.USER_OWNER;
  148. ContentValues values = new ContentValues();
  149. for (String argument; (argument = mTokenizer.nextArg()) != null;) {
  150. if (ARGUMENT_URI.equals(argument)) {
  151. uri = Uri.parse(argumentValueRequired(argument));
  152. } else if (ARGUMENT_USER.equals(argument)) {
  153. userId = Integer.parseInt(argumentValueRequired(argument));
  154. } else if (ARGUMENT_BIND.equals(argument)) {
  155. parseBindValue(values);
  156. } else {
  157. throw new IllegalArgumentException("Unsupported argument: " + argument);
  158. }
  159. }
  160. if (uri == null) {
  161. throw new IllegalArgumentException("Content provider URI not specified."
  162. + " Did you specify --uri argument?");
  163. }
  164. if (values.size() == 0) {
  165. throw new IllegalArgumentException("Bindings not specified."
  166. + " Did you specify --bind argument(s)?");
  167. }
  168. return new InsertCommand(uri, userId, values);
  169. }
  170. private DeleteCommand parseDeleteCommand() {
  171. Uri uri = null;
  172. int userId = UserHandle.USER_OWNER;
  173. String where = null;
  174. for (String argument; (argument = mTokenizer.nextArg())!= null;) {
  175. if (ARGUMENT_URI.equals(argument)) {
  176. uri = Uri.parse(argumentValueRequired(argument));
  177. } else if (ARGUMENT_USER.equals(argument)) {
  178. userId = Integer.parseInt(argumentValueRequired(argument));
  179. } else if (ARGUMENT_WHERE.equals(argument)) {
  180. where = argumentValueRequired(argument);
  181. } else {
  182. throw new IllegalArgumentException("Unsupported argument: " + argument);
  183. }
  184. }
  185. if (uri == null) {
  186. throw new IllegalArgumentException("Content provider URI not specified."
  187. + " Did you specify --uri argument?");
  188. }
  189. return new DeleteCommand(uri, userId, where);
  190. }
  191. private UpdateCommand parseUpdateCommand() {
  192. Uri uri = null;
  193. int userId = UserHandle.USER_OWNER;
  194. String where = null;
  195. ContentValues values = new ContentValues();
  196. for (String argument; (argument = mTokenizer.nextArg())!= null;) {
  197. if (ARGUMENT_URI.equals(argument)) {
  198. uri = Uri.parse(argumentValueRequired(argument));
  199. } else if (ARGUMENT_USER.equals(argument)) {
  200. userId = Integer.parseInt(argumentValueRequired(argument));
  201. } else if (ARGUMENT_WHERE.equals(argument)) {
  202. where = argumentValueRequired(argument);
  203. } 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. }
  217. return new UpdateCommand(uri, userId, values, where);
  218. }
  219. public QueryCommand parseQueryCommand() {
  220. Uri uri = null;
  221. int userId = UserHandle.USER_OWNER;
  222. String[] projection = null;
  223. String sort = null;
  224. String where = null;
  225. for (String argument; (argument = mTokenizer.nextArg())!= null;) {
  226. if (ARGUMENT_URI.equals(argument)) {
  227. uri = Uri.parse(argumentValueRequired(argument));
  228. } else if (ARGUMENT_USER.equals(argument)) {
  229. userId = Integer.parseInt(argumentValueRequired(argument));
  230. } else if (ARGUMENT_WHERE.equals(argument)) {
  231. where = argumentValueRequired(argument);
  232. } else if (ARGUMENT_SORT.equals(argument)) {
  233. sort = argumentValueRequired(argument);
  234. } else if (ARGUMENT_PROJECTION.equals(argument)) {
  235. projection = argumentValueRequired(argument).split("[\\s]*:[\\s]*");
  236. } else {
  237. throw new IllegalArgumentException("Unsupported argument: " + argument);
  238. }
  239. }
  240. if (uri == null) {
  241. throw new IllegalArgumentException("Content provider URI not specified."
  242. + " Did you specify --uri argument?");
  243. }
  244. return new QueryCommand(uri, userId, projection, where, sort);
  245. }
  246. private void parseBindValue(ContentValues values) {
  247. String argument = mTokenizer.nextArg();
  248. if (TextUtils.isEmpty(argument)) {
  249. throw new IllegalArgumentException("Binding not well formed: " + argument);
  250. }
  251. final int firstColonIndex = argument.indexOf(COLON);
  252. if (firstColonIndex < 0) {
  253. throw new IllegalArgumentException("Binding not well formed: " + argument);
  254. }
  255. final int secondColonIndex = argument.indexOf(COLON, firstColonIndex + 1);
  256. if (secondColonIndex < 0) {
  257. throw new IllegalArgumentException("Binding not well formed: " + argument);
  258. }
  259. String column = argument.substring(0, firstColonIndex);
  260. String type = argument.substring(firstColonIndex + 1, secondColonIndex);
  261. String value = argument.substring(secondColonIndex + 1);
  262. if (TYPE_STRING.equals(type)) {
  263. values.put(column, value);
  264. } else if (TYPE_BOOLEAN.equalsIgnoreCase(type)) {
  265. values.put(column, Boolean.parseBoolean(value));
  266. } else if (TYPE_INTEGER.equalsIgnoreCase(type) || TYPE_LONG.equalsIgnoreCase(type)) {
  267. values.put(column, Long.parseLong(value));
  268. } else if (TYPE_FLOAT.equalsIgnoreCase(type) || TYPE_DOUBLE.equalsIgnoreCase(type)) {
  269. values.put(column, Double.parseDouble(value));
  270. } else {
  271. throw new IllegalArgumentException("Unsupported type: " + type);
  272. }
  273. }
  274. private String argumentValueRequired(String argument) {
  275. String value = mTokenizer.nextArg();
  276. if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) {
  277. throw new IllegalArgumentException("No value for argument: " + argument);
  278. }
  279. return value;
  280. }
  281. }
  282. private static class Tokenizer {
  283. private final String[] mArgs;
  284. private int mNextArg;
  285. public Tokenizer(String[] args) {
  286. mArgs = args;
  287. }
  288. private String nextArg() {
  289. if (mNextArg < mArgs.length) {
  290. return mArgs[mNextArg++];
  291. } else {
  292. return null;
  293. }
  294. }
  295. }
  296. private static abstract class Command {
  297. final Uri mUri;
  298. final int mUserId;
  299. public Command(Uri uri, int userId) {
  300. mUri = uri;
  301. mUserId = userId;
  302. }
  303. public final void execute() {
  304. String providerName = mUri.getAuthority();
  305. try {
  306. IActivityManager activityManager = ActivityManagerNative.getDefault();
  307. IContentProvider provider = null;
  308. IBinder token = new Binder();
  309. try {
  310. ContentProviderHolder holder = activityManager.getContentProviderExternal(
  311. providerName, mUserId, token);
  312. if (holder == null) {
  313. throw new IllegalStateException("Could not find provider: " + providerName);
  314. }
  315. provider = holder.provider;
  316. onExecute(provider);
  317. } finally {
  318. if (provider != null) {
  319. activityManager.removeContentProviderExternal(providerName, token);
  320. }
  321. }
  322. } catch (Exception e) {
  323. System.err.println("Error while accessing provider:" + providerName);
  324. e.printStackTrace();
  325. }
  326. }
  327. protected abstract void onExecute(IContentProvider provider) throws Exception;
  328. }
  329. private static class InsertCommand extends Command {
  330. final ContentValues mContentValues;
  331. public InsertCommand(Uri uri, int userId, ContentValues contentValues) {
  332. super(uri, userId);
  333. mContentValues = contentValues;
  334. }
  335. @Override
  336. public void onExecute(IContentProvider provider) throws Exception {
  337. provider.insert(mUri, mContentValues);
  338. }
  339. }
  340. private static class DeleteCommand extends Command {
  341. final String mWhere;
  342. public DeleteCommand(Uri uri, int userId, String where) {
  343. super(uri, userId);
  344. mWhere = where;
  345. }
  346. @Override
  347. public void onExecute(IContentProvider provider) throws Exception {
  348. provider.delete(mUri, mWhere, null);
  349. }
  350. }
  351. private static class QueryCommand extends DeleteCommand {
  352. final String[] mProjection;
  353. final String mSortOrder;
  354. public QueryCommand(
  355. Uri uri, int userId, String[] projection, String where, String sortOrder) {
  356. super(uri, userId, where);
  357. mProjection = projection;
  358. mSortOrder = sortOrder;
  359. }
  360. @Override
  361. public void onExecute(IContentProvider provider) throws Exception {
  362. Cursor cursor = provider.query(mUri, mProjection, mWhere, null, mSortOrder, null);
  363. if (cursor == null) {
  364. System.out.println("No result found.");
  365. return;
  366. }
  367. try {
  368. if (cursor.moveToFirst()) {
  369. int rowIndex = 0;
  370. StringBuilder builder = new StringBuilder();
  371. do {
  372. builder.setLength(0);
  373. builder.append("Row: ").append(rowIndex).append(" ");
  374. rowIndex++;
  375. final int columnCount = cursor.getColumnCount();
  376. for (int i = 0; i < columnCount; i++) {
  377. if (i > 0) {
  378. builder.append(", ");
  379. }
  380. String columnName = cursor.getColumnName(i);
  381. String columnValue = null;
  382. final int columnIndex = cursor.getColumnIndex(columnName);
  383. final int type = cursor.getType(columnIndex);
  384. switch (type) {
  385. case Cursor.FIELD_TYPE_FLOAT:
  386. columnValue = String.valueOf(cursor.getFloat(columnIndex));
  387. break;
  388. case Cursor.FIELD_TYPE_INTEGER:
  389. columnValue = String.valueOf(cursor.getInt(columnIndex));
  390. break;
  391. case Cursor.FIELD_TYPE_STRING:
  392. columnValue = cursor.getString(columnIndex);
  393. break;
  394. case Cursor.FIELD_TYPE_BLOB:
  395. columnValue = "BLOB";
  396. break;
  397. case Cursor.FIELD_TYPE_NULL:
  398. columnValue = "NULL";
  399. break;
  400. }
  401. builder.append(columnName).append("=").append(columnValue);
  402. }
  403. System.out.println(builder);
  404. } while (cursor.moveToNext());
  405. } else {
  406. System.out.println("No reuslt found.");
  407. }
  408. } finally {
  409. cursor.close();
  410. }
  411. }
  412. }
  413. private static class UpdateCommand extends InsertCommand {
  414. final String mWhere;
  415. public UpdateCommand(Uri uri, int userId, ContentValues contentValues, String where) {
  416. super(uri, userId, contentValues);
  417. mWhere = where;
  418. }
  419. @Override
  420. public void onExecute(IContentProvider provider) throws Exception {
  421. provider.update(mUri, mContentValues, mWhere, null);
  422. }
  423. }
  424. public static void main(String[] args) {
  425. Parser parser = new Parser(args);
  426. Command command = parser.parseCommand();
  427. if (command != null) {
  428. command.execute();
  429. }
  430. }
  431. }