PageRenderTime 129ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/frameworks/base/core/java/android/content/ContentResolver.java

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
Java | 1167 lines | 569 code | 66 blank | 532 comment | 118 complexity | 0568131b1f777412e0b9399cacd9049e MD5 | raw file
  1. /*
  2. * Copyright (C) 2006 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 android.content;
  17. import dalvik.system.CloseGuard;
  18. import android.accounts.Account;
  19. import android.app.ActivityManagerNative;
  20. import android.app.AppGlobals;
  21. import android.content.pm.PackageManager.NameNotFoundException;
  22. import android.content.res.AssetFileDescriptor;
  23. import android.content.res.Resources;
  24. import android.database.ContentObserver;
  25. import android.database.CrossProcessCursorWrapper;
  26. import android.database.Cursor;
  27. import android.database.IContentObserver;
  28. import android.net.Uri;
  29. import android.os.Bundle;
  30. import android.os.CancellationSignal;
  31. import android.os.DeadObjectException;
  32. import android.os.IBinder;
  33. import android.os.ICancellationSignal;
  34. import android.os.OperationCanceledException;
  35. import android.os.ParcelFileDescriptor;
  36. import android.os.RemoteException;
  37. import android.os.ServiceManager;
  38. import android.os.SystemClock;
  39. import android.os.UserHandle;
  40. import android.text.TextUtils;
  41. import android.util.EventLog;
  42. import android.util.Log;
  43. import java.io.File;
  44. import java.io.FileInputStream;
  45. import java.io.FileNotFoundException;
  46. import java.io.IOException;
  47. import java.io.InputStream;
  48. import java.io.OutputStream;
  49. import java.util.ArrayList;
  50. import java.util.List;
  51. import java.util.Random;
  52. /**
  53. * This class provides applications access to the content model.
  54. *
  55. * <div class="special reference">
  56. * <h3>Developer Guides</h3>
  57. * <p>For more information about using a ContentResolver with content providers, read the
  58. * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
  59. * developer guide.</p>
  60. */
  61. public abstract class ContentResolver {
  62. /**
  63. * @deprecated instead use
  64. * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
  65. */
  66. @Deprecated
  67. public static final String SYNC_EXTRAS_ACCOUNT = "account";
  68. public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
  69. /**
  70. * @deprecated instead use
  71. * {@link #SYNC_EXTRAS_MANUAL}
  72. */
  73. @Deprecated
  74. public static final String SYNC_EXTRAS_FORCE = "force";
  75. /**
  76. * If this extra is set to true then the sync settings (like getSyncAutomatically())
  77. * are ignored by the sync scheduler.
  78. */
  79. public static final String SYNC_EXTRAS_IGNORE_SETTINGS = "ignore_settings";
  80. /**
  81. * If this extra is set to true then any backoffs for the initial attempt (e.g. due to retries)
  82. * are ignored by the sync scheduler. If this request fails and gets rescheduled then the
  83. * retries will still honor the backoff.
  84. */
  85. public static final String SYNC_EXTRAS_IGNORE_BACKOFF = "ignore_backoff";
  86. /**
  87. * If this extra is set to true then the request will not be retried if it fails.
  88. */
  89. public static final String SYNC_EXTRAS_DO_NOT_RETRY = "do_not_retry";
  90. /**
  91. * Setting this extra is the equivalent of setting both {@link #SYNC_EXTRAS_IGNORE_SETTINGS}
  92. * and {@link #SYNC_EXTRAS_IGNORE_BACKOFF}
  93. */
  94. public static final String SYNC_EXTRAS_MANUAL = "force";
  95. public static final String SYNC_EXTRAS_UPLOAD = "upload";
  96. public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
  97. public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
  98. /**
  99. * Set by the SyncManager to request that the SyncAdapter initialize itself for
  100. * the given account/authority pair. One required initialization step is to
  101. * ensure that {@link #setIsSyncable(android.accounts.Account, String, int)} has been
  102. * called with a >= 0 value. When this flag is set the SyncAdapter does not need to
  103. * do a full sync, though it is allowed to do so.
  104. */
  105. public static final String SYNC_EXTRAS_INITIALIZE = "initialize";
  106. public static final String SCHEME_CONTENT = "content";
  107. public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
  108. public static final String SCHEME_FILE = "file";
  109. /**
  110. * This is the Android platform's base MIME type for a content: URI
  111. * containing a Cursor of a single item. Applications should use this
  112. * as the base type along with their own sub-type of their content: URIs
  113. * that represent a particular item. For example, hypothetical IMAP email
  114. * client may have a URI
  115. * <code>content://com.company.provider.imap/inbox/1</code> for a particular
  116. * message in the inbox, whose MIME type would be reported as
  117. * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code>
  118. *
  119. * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}.
  120. */
  121. public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
  122. /**
  123. * This is the Android platform's base MIME type for a content: URI
  124. * containing a Cursor of zero or more items. Applications should use this
  125. * as the base type along with their own sub-type of their content: URIs
  126. * that represent a directory of items. For example, hypothetical IMAP email
  127. * client may have a URI
  128. * <code>content://com.company.provider.imap/inbox</code> for all of the
  129. * messages in its inbox, whose MIME type would be reported as
  130. * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code>
  131. *
  132. * <p>Note how the base MIME type varies between this and
  133. * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is
  134. * one single item or multiple items in the data set, while the sub-type
  135. * remains the same because in either case the data structure contained
  136. * in the cursor is the same.
  137. */
  138. public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
  139. /** @hide */
  140. public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
  141. /** @hide */
  142. public static final int SYNC_ERROR_AUTHENTICATION = 2;
  143. /** @hide */
  144. public static final int SYNC_ERROR_IO = 3;
  145. /** @hide */
  146. public static final int SYNC_ERROR_PARSE = 4;
  147. /** @hide */
  148. public static final int SYNC_ERROR_CONFLICT = 5;
  149. /** @hide */
  150. public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6;
  151. /** @hide */
  152. public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7;
  153. /** @hide */
  154. public static final int SYNC_ERROR_INTERNAL = 8;
  155. public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0;
  156. public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
  157. public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
  158. /** @hide */
  159. public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3;
  160. /** @hide */
  161. public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
  162. // Always log queries which take 500ms+; shorter queries are
  163. // sampled accordingly.
  164. private static final int SLOW_THRESHOLD_MILLIS = 500;
  165. private final Random mRandom = new Random(); // guarded by itself
  166. public ContentResolver(Context context) {
  167. mContext = context;
  168. }
  169. /** @hide */
  170. protected abstract IContentProvider acquireProvider(Context c, String name);
  171. /** Providing a default implementation of this, to avoid having to change
  172. * a lot of other things, but implementations of ContentResolver should
  173. * implement it. @hide */
  174. protected IContentProvider acquireExistingProvider(Context c, String name) {
  175. return acquireProvider(c, name);
  176. }
  177. /** @hide */
  178. public abstract boolean releaseProvider(IContentProvider icp);
  179. /** @hide */
  180. protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
  181. /** @hide */
  182. public abstract boolean releaseUnstableProvider(IContentProvider icp);
  183. /** @hide */
  184. public abstract void unstableProviderDied(IContentProvider icp);
  185. /**
  186. * Return the MIME type of the given content URL.
  187. *
  188. * @param url A Uri identifying content (either a list or specific type),
  189. * using the content:// scheme.
  190. * @return A MIME type for the content, or null if the URL is invalid or the type is unknown
  191. */
  192. public final String getType(Uri url) {
  193. // XXX would like to have an acquireExistingUnstableProvider for this.
  194. IContentProvider provider = acquireExistingProvider(url);
  195. if (provider != null) {
  196. try {
  197. return provider.getType(url);
  198. } catch (RemoteException e) {
  199. return null;
  200. } catch (java.lang.Exception e) {
  201. Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
  202. return null;
  203. } finally {
  204. releaseProvider(provider);
  205. }
  206. }
  207. if (!SCHEME_CONTENT.equals(url.getScheme())) {
  208. return null;
  209. }
  210. try {
  211. String type = ActivityManagerNative.getDefault().getProviderMimeType(
  212. url, UserHandle.myUserId());
  213. return type;
  214. } catch (RemoteException e) {
  215. // Arbitrary and not worth documenting, as Activity
  216. // Manager will kill this process shortly anyway.
  217. return null;
  218. } catch (java.lang.Exception e) {
  219. Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
  220. return null;
  221. }
  222. }
  223. /**
  224. * Query for the possible MIME types for the representations the given
  225. * content URL can be returned when opened as as stream with
  226. * {@link #openTypedAssetFileDescriptor}. Note that the types here are
  227. * not necessarily a superset of the type returned by {@link #getType} --
  228. * many content providers can not return a raw stream for the structured
  229. * data that they contain.
  230. *
  231. * @param url A Uri identifying content (either a list or specific type),
  232. * using the content:// scheme.
  233. * @param mimeTypeFilter The desired MIME type. This may be a pattern,
  234. * such as *\/*, to query for all available MIME types that match the
  235. * pattern.
  236. * @return Returns an array of MIME type strings for all available
  237. * data streams that match the given mimeTypeFilter. If there are none,
  238. * null is returned.
  239. */
  240. public String[] getStreamTypes(Uri url, String mimeTypeFilter) {
  241. IContentProvider provider = acquireProvider(url);
  242. if (provider == null) {
  243. return null;
  244. }
  245. try {
  246. return provider.getStreamTypes(url, mimeTypeFilter);
  247. } catch (RemoteException e) {
  248. // Arbitrary and not worth documenting, as Activity
  249. // Manager will kill this process shortly anyway.
  250. return null;
  251. } finally {
  252. releaseProvider(provider);
  253. }
  254. }
  255. /**
  256. * <p>
  257. * Query the given URI, returning a {@link Cursor} over the result set.
  258. * </p>
  259. * <p>
  260. * For best performance, the caller should follow these guidelines:
  261. * <ul>
  262. * <li>Provide an explicit projection, to prevent
  263. * reading data from storage that aren't going to be used.</li>
  264. * <li>Use question mark parameter markers such as 'phone=?' instead of
  265. * explicit values in the {@code selection} parameter, so that queries
  266. * that differ only by those values will be recognized as the same
  267. * for caching purposes.</li>
  268. * </ul>
  269. * </p>
  270. *
  271. * @param uri The URI, using the content:// scheme, for the content to
  272. * retrieve.
  273. * @param projection A list of which columns to return. Passing null will
  274. * return all columns, which is inefficient.
  275. * @param selection A filter declaring which rows to return, formatted as an
  276. * SQL WHERE clause (excluding the WHERE itself). Passing null will
  277. * return all rows for the given URI.
  278. * @param selectionArgs You may include ?s in selection, which will be
  279. * replaced by the values from selectionArgs, in the order that they
  280. * appear in the selection. The values will be bound as Strings.
  281. * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
  282. * clause (excluding the ORDER BY itself). Passing null will use the
  283. * default sort order, which may be unordered.
  284. * @return A Cursor object, which is positioned before the first entry, or null
  285. * @see Cursor
  286. */
  287. public final Cursor query(Uri uri, String[] projection,
  288. String selection, String[] selectionArgs, String sortOrder) {
  289. return query(uri, projection, selection, selectionArgs, sortOrder, null);
  290. }
  291. /**
  292. * <p>
  293. * Query the given URI, returning a {@link Cursor} over the result set.
  294. * </p>
  295. * <p>
  296. * For best performance, the caller should follow these guidelines:
  297. * <ul>
  298. * <li>Provide an explicit projection, to prevent
  299. * reading data from storage that aren't going to be used.</li>
  300. * <li>Use question mark parameter markers such as 'phone=?' instead of
  301. * explicit values in the {@code selection} parameter, so that queries
  302. * that differ only by those values will be recognized as the same
  303. * for caching purposes.</li>
  304. * </ul>
  305. * </p>
  306. *
  307. * @param uri The URI, using the content:// scheme, for the content to
  308. * retrieve.
  309. * @param projection A list of which columns to return. Passing null will
  310. * return all columns, which is inefficient.
  311. * @param selection A filter declaring which rows to return, formatted as an
  312. * SQL WHERE clause (excluding the WHERE itself). Passing null will
  313. * return all rows for the given URI.
  314. * @param selectionArgs You may include ?s in selection, which will be
  315. * replaced by the values from selectionArgs, in the order that they
  316. * appear in the selection. The values will be bound as Strings.
  317. * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
  318. * clause (excluding the ORDER BY itself). Passing null will use the
  319. * default sort order, which may be unordered.
  320. * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
  321. * If the operation is canceled, then {@link OperationCanceledException} will be thrown
  322. * when the query is executed.
  323. * @return A Cursor object, which is positioned before the first entry, or null
  324. * @see Cursor
  325. */
  326. public final Cursor query(final Uri uri, String[] projection,
  327. String selection, String[] selectionArgs, String sortOrder,
  328. CancellationSignal cancellationSignal) {
  329. IContentProvider unstableProvider = acquireUnstableProvider(uri);
  330. if (unstableProvider == null) {
  331. return null;
  332. }
  333. IContentProvider stableProvider = null;
  334. try {
  335. long startTime = SystemClock.uptimeMillis();
  336. ICancellationSignal remoteCancellationSignal = null;
  337. if (cancellationSignal != null) {
  338. cancellationSignal.throwIfCanceled();
  339. remoteCancellationSignal = unstableProvider.createCancellationSignal();
  340. cancellationSignal.setRemote(remoteCancellationSignal);
  341. }
  342. Cursor qCursor;
  343. try {
  344. qCursor = unstableProvider.query(uri, projection,
  345. selection, selectionArgs, sortOrder, remoteCancellationSignal);
  346. } catch (DeadObjectException e) {
  347. // The remote process has died... but we only hold an unstable
  348. // reference though, so we might recover!!! Let's try!!!!
  349. // This is exciting!!1!!1!!!!1
  350. unstableProviderDied(unstableProvider);
  351. stableProvider = acquireProvider(uri);
  352. if (stableProvider == null) {
  353. return null;
  354. }
  355. qCursor = stableProvider.query(uri, projection,
  356. selection, selectionArgs, sortOrder, remoteCancellationSignal);
  357. }
  358. if (qCursor == null) {
  359. return null;
  360. }
  361. // force query execution
  362. qCursor.getCount();
  363. long durationMillis = SystemClock.uptimeMillis() - startTime;
  364. maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
  365. // Wrap the cursor object into CursorWrapperInner object
  366. CursorWrapperInner wrapper = new CursorWrapperInner(qCursor,
  367. stableProvider != null ? stableProvider : acquireProvider(uri));
  368. stableProvider = null;
  369. return wrapper;
  370. } catch (RemoteException e) {
  371. // Arbitrary and not worth documenting, as Activity
  372. // Manager will kill this process shortly anyway.
  373. return null;
  374. } finally {
  375. if (unstableProvider != null) {
  376. releaseUnstableProvider(unstableProvider);
  377. }
  378. if (stableProvider != null) {
  379. releaseProvider(stableProvider);
  380. }
  381. }
  382. }
  383. /**
  384. * Open a stream on to the content associated with a content URI. If there
  385. * is no data associated with the URI, FileNotFoundException is thrown.
  386. *
  387. * <h5>Accepts the following URI schemes:</h5>
  388. * <ul>
  389. * <li>content ({@link #SCHEME_CONTENT})</li>
  390. * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
  391. * <li>file ({@link #SCHEME_FILE})</li>
  392. * </ul>
  393. *
  394. * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
  395. * on these schemes.
  396. *
  397. * @param uri The desired URI.
  398. * @return InputStream
  399. * @throws FileNotFoundException if the provided URI could not be opened.
  400. * @see #openAssetFileDescriptor(Uri, String)
  401. */
  402. public final InputStream openInputStream(Uri uri)
  403. throws FileNotFoundException {
  404. String scheme = uri.getScheme();
  405. if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
  406. // Note: left here to avoid breaking compatibility. May be removed
  407. // with sufficient testing.
  408. OpenResourceIdResult r = getResourceId(uri);
  409. try {
  410. InputStream stream = r.r.openRawResource(r.id);
  411. return stream;
  412. } catch (Resources.NotFoundException ex) {
  413. throw new FileNotFoundException("Resource does not exist: " + uri);
  414. }
  415. } else if (SCHEME_FILE.equals(scheme)) {
  416. // Note: left here to avoid breaking compatibility. May be removed
  417. // with sufficient testing.
  418. return new FileInputStream(uri.getPath());
  419. } else {
  420. AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r");
  421. try {
  422. return fd != null ? fd.createInputStream() : null;
  423. } catch (IOException e) {
  424. throw new FileNotFoundException("Unable to create stream");
  425. }
  426. }
  427. }
  428. /**
  429. * Synonym for {@link #openOutputStream(Uri, String)
  430. * openOutputStream(uri, "w")}.
  431. * @throws FileNotFoundException if the provided URI could not be opened.
  432. */
  433. public final OutputStream openOutputStream(Uri uri)
  434. throws FileNotFoundException {
  435. return openOutputStream(uri, "w");
  436. }
  437. /**
  438. * Open a stream on to the content associated with a content URI. If there
  439. * is no data associated with the URI, FileNotFoundException is thrown.
  440. *
  441. * <h5>Accepts the following URI schemes:</h5>
  442. * <ul>
  443. * <li>content ({@link #SCHEME_CONTENT})</li>
  444. * <li>file ({@link #SCHEME_FILE})</li>
  445. * </ul>
  446. *
  447. * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
  448. * on these schemes.
  449. *
  450. * @param uri The desired URI.
  451. * @param mode May be "w", "wa", "rw", or "rwt".
  452. * @return OutputStream
  453. * @throws FileNotFoundException if the provided URI could not be opened.
  454. * @see #openAssetFileDescriptor(Uri, String)
  455. */
  456. public final OutputStream openOutputStream(Uri uri, String mode)
  457. throws FileNotFoundException {
  458. AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode);
  459. try {
  460. return fd != null ? fd.createOutputStream() : null;
  461. } catch (IOException e) {
  462. throw new FileNotFoundException("Unable to create stream");
  463. }
  464. }
  465. /**
  466. * Open a raw file descriptor to access data under a URI. This
  467. * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
  468. * underlying {@link ContentProvider#openFile}
  469. * ContentProvider.openFile()} method, so will <em>not</em> work with
  470. * providers that return sub-sections of files. If at all possible,
  471. * you should use {@link #openAssetFileDescriptor(Uri, String)}. You
  472. * will receive a FileNotFoundException exception if the provider returns a
  473. * sub-section of a file.
  474. *
  475. * <h5>Accepts the following URI schemes:</h5>
  476. * <ul>
  477. * <li>content ({@link #SCHEME_CONTENT})</li>
  478. * <li>file ({@link #SCHEME_FILE})</li>
  479. * </ul>
  480. *
  481. * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
  482. * on these schemes.
  483. *
  484. * @param uri The desired URI to open.
  485. * @param mode The file mode to use, as per {@link ContentProvider#openFile
  486. * ContentProvider.openFile}.
  487. * @return Returns a new ParcelFileDescriptor pointing to the file. You
  488. * own this descriptor and are responsible for closing it when done.
  489. * @throws FileNotFoundException Throws FileNotFoundException of no
  490. * file exists under the URI or the mode is invalid.
  491. * @see #openAssetFileDescriptor(Uri, String)
  492. */
  493. public final ParcelFileDescriptor openFileDescriptor(Uri uri,
  494. String mode) throws FileNotFoundException {
  495. AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode);
  496. if (afd == null) {
  497. return null;
  498. }
  499. if (afd.getDeclaredLength() < 0) {
  500. // This is a full file!
  501. return afd.getParcelFileDescriptor();
  502. }
  503. // Client can't handle a sub-section of a file, so close what
  504. // we got and bail with an exception.
  505. try {
  506. afd.close();
  507. } catch (IOException e) {
  508. }
  509. throw new FileNotFoundException("Not a whole file");
  510. }
  511. /**
  512. * Open a raw file descriptor to access data under a URI. This
  513. * interacts with the underlying {@link ContentProvider#openAssetFile}
  514. * method of the provider associated with the given URI, to retrieve any file stored there.
  515. *
  516. * <h5>Accepts the following URI schemes:</h5>
  517. * <ul>
  518. * <li>content ({@link #SCHEME_CONTENT})</li>
  519. * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
  520. * <li>file ({@link #SCHEME_FILE})</li>
  521. * </ul>
  522. * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
  523. * <p>
  524. * A Uri object can be used to reference a resource in an APK file. The
  525. * Uri should be one of the following formats:
  526. * <ul>
  527. * <li><code>android.resource://package_name/id_number</code><br/>
  528. * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
  529. * For example <code>com.example.myapp</code><br/>
  530. * <code>id_number</code> is the int form of the ID.<br/>
  531. * The easiest way to construct this form is
  532. * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
  533. * </li>
  534. * <li><code>android.resource://package_name/type/name</code><br/>
  535. * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
  536. * For example <code>com.example.myapp</code><br/>
  537. * <code>type</code> is the string form of the resource type. For example, <code>raw</code>
  538. * or <code>drawable</code>.
  539. * <code>name</code> is the string form of the resource name. That is, whatever the file
  540. * name was in your res directory, without the type extension.
  541. * The easiest way to construct this form is
  542. * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
  543. * </li>
  544. * </ul>
  545. *
  546. * <p>Note that if this function is called for read-only input (mode is "r")
  547. * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
  548. * for you with a MIME type of "*\/*". This allows such callers to benefit
  549. * from any built-in data conversion that a provider implements.
  550. *
  551. * @param uri The desired URI to open.
  552. * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
  553. * ContentProvider.openAssetFile}.
  554. * @return Returns a new ParcelFileDescriptor pointing to the file. You
  555. * own this descriptor and are responsible for closing it when done.
  556. * @throws FileNotFoundException Throws FileNotFoundException of no
  557. * file exists under the URI or the mode is invalid.
  558. */
  559. public final AssetFileDescriptor openAssetFileDescriptor(Uri uri,
  560. String mode) throws FileNotFoundException {
  561. String scheme = uri.getScheme();
  562. if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
  563. if (!"r".equals(mode)) {
  564. throw new FileNotFoundException("Can't write resources: " + uri);
  565. }
  566. OpenResourceIdResult r = getResourceId(uri);
  567. try {
  568. return r.r.openRawResourceFd(r.id);
  569. } catch (Resources.NotFoundException ex) {
  570. throw new FileNotFoundException("Resource does not exist: " + uri);
  571. }
  572. } else if (SCHEME_FILE.equals(scheme)) {
  573. ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
  574. new File(uri.getPath()), modeToMode(uri, mode));
  575. return new AssetFileDescriptor(pfd, 0, -1);
  576. } else {
  577. if ("r".equals(mode)) {
  578. return openTypedAssetFileDescriptor(uri, "*/*", null);
  579. } else {
  580. IContentProvider unstableProvider = acquireUnstableProvider(uri);
  581. if (unstableProvider == null) {
  582. throw new FileNotFoundException("No content provider: " + uri);
  583. }
  584. IContentProvider stableProvider = null;
  585. AssetFileDescriptor fd = null;
  586. try {
  587. try {
  588. fd = unstableProvider.openAssetFile(uri, mode);
  589. if (fd == null) {
  590. // The provider will be released by the finally{} clause
  591. return null;
  592. }
  593. } catch (DeadObjectException e) {
  594. // The remote process has died... but we only hold an unstable
  595. // reference though, so we might recover!!! Let's try!!!!
  596. // This is exciting!!1!!1!!!!1
  597. unstableProviderDied(unstableProvider);
  598. stableProvider = acquireProvider(uri);
  599. if (stableProvider == null) {
  600. throw new FileNotFoundException("No content provider: " + uri);
  601. }
  602. fd = stableProvider.openAssetFile(uri, mode);
  603. if (fd == null) {
  604. // The provider will be released by the finally{} clause
  605. return null;
  606. }
  607. }
  608. if (stableProvider == null) {
  609. stableProvider = acquireProvider(uri);
  610. }
  611. releaseUnstableProvider(unstableProvider);
  612. ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
  613. fd.getParcelFileDescriptor(), stableProvider);
  614. // Success! Don't release the provider when exiting, let
  615. // ParcelFileDescriptorInner do that when it is closed.
  616. stableProvider = null;
  617. return new AssetFileDescriptor(pfd, fd.getStartOffset(),
  618. fd.getDeclaredLength());
  619. } catch (RemoteException e) {
  620. // Whatever, whatever, we'll go away.
  621. throw new FileNotFoundException(
  622. "Failed opening content provider: " + uri);
  623. } catch (FileNotFoundException e) {
  624. throw e;
  625. } finally {
  626. if (stableProvider != null) {
  627. releaseProvider(stableProvider);
  628. }
  629. if (unstableProvider != null) {
  630. releaseUnstableProvider(unstableProvider);
  631. }
  632. }
  633. }
  634. }
  635. }
  636. /**
  637. * Open a raw file descriptor to access (potentially type transformed)
  638. * data from a "content:" URI. This interacts with the underlying
  639. * {@link ContentProvider#openTypedAssetFile} method of the provider
  640. * associated with the given URI, to retrieve retrieve any appropriate
  641. * data stream for the data stored there.
  642. *
  643. * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
  644. * with "content:" URIs, because content providers are the only facility
  645. * with an associated MIME type to ensure that the returned data stream
  646. * is of the desired type.
  647. *
  648. * <p>All text/* streams are encoded in UTF-8.
  649. *
  650. * @param uri The desired URI to open.
  651. * @param mimeType The desired MIME type of the returned data. This can
  652. * be a pattern such as *\/*, which will allow the content provider to
  653. * select a type, though there is no way for you to determine what type
  654. * it is returning.
  655. * @param opts Additional provider-dependent options.
  656. * @return Returns a new ParcelFileDescriptor from which you can read the
  657. * data stream from the provider. Note that this may be a pipe, meaning
  658. * you can't seek in it. The only seek you should do is if the
  659. * AssetFileDescriptor contains an offset, to move to that offset before
  660. * reading. You own this descriptor and are responsible for closing it when done.
  661. * @throws FileNotFoundException Throws FileNotFoundException of no
  662. * data of the desired type exists under the URI.
  663. */
  664. public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
  665. String mimeType, Bundle opts) throws FileNotFoundException {
  666. IContentProvider unstableProvider = acquireUnstableProvider(uri);
  667. if (unstableProvider == null) {
  668. throw new FileNotFoundException("No content provider: " + uri);
  669. }
  670. IContentProvider stableProvider = null;
  671. AssetFileDescriptor fd = null;
  672. try {
  673. try {
  674. fd = unstableProvider.openTypedAssetFile(uri, mimeType, opts);
  675. if (fd == null) {
  676. // The provider will be released by the finally{} clause
  677. return null;
  678. }
  679. } catch (DeadObjectException e) {
  680. // The remote process has died... but we only hold an unstable
  681. // reference though, so we might recover!!! Let's try!!!!
  682. // This is exciting!!1!!1!!!!1
  683. unstableProviderDied(unstableProvider);
  684. stableProvider = acquireProvider(uri);
  685. if (stableProvider == null) {
  686. throw new FileNotFoundException("No content provider: " + uri);
  687. }
  688. fd = stableProvider.openTypedAssetFile(uri, mimeType, opts);
  689. if (fd == null) {
  690. // The provider will be released by the finally{} clause
  691. return null;
  692. }
  693. }
  694. if (stableProvider == null) {
  695. stableProvider = acquireProvider(uri);
  696. }
  697. releaseUnstableProvider(unstableProvider);
  698. ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
  699. fd.getParcelFileDescriptor(), stableProvider);
  700. // Success! Don't release the provider when exiting, let
  701. // ParcelFileDescriptorInner do that when it is closed.
  702. stableProvider = null;
  703. return new AssetFileDescriptor(pfd, fd.getStartOffset(),
  704. fd.getDeclaredLength());
  705. } catch (RemoteException e) {
  706. // Whatever, whatever, we'll go away.
  707. throw new FileNotFoundException(
  708. "Failed opening content provider: " + uri);
  709. } catch (FileNotFoundException e) {
  710. throw e;
  711. } finally {
  712. if (stableProvider != null) {
  713. releaseProvider(stableProvider);
  714. }
  715. if (unstableProvider != null) {
  716. releaseUnstableProvider(unstableProvider);
  717. }
  718. }
  719. }
  720. /**
  721. * A resource identified by the {@link Resources} that contains it, and a resource id.
  722. *
  723. * @hide
  724. */
  725. public class OpenResourceIdResult {
  726. public Resources r;
  727. public int id;
  728. }
  729. /**
  730. * Resolves an android.resource URI to a {@link Resources} and a resource id.
  731. *
  732. * @hide
  733. */
  734. public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
  735. String authority = uri.getAuthority();
  736. Resources r;
  737. if (TextUtils.isEmpty(authority)) {
  738. throw new FileNotFoundException("No authority: " + uri);
  739. } else {
  740. try {
  741. r = mContext.getPackageManager().getResourcesForApplication(authority);
  742. } catch (NameNotFoundException ex) {
  743. throw new FileNotFoundException("No package found for authority: " + uri);
  744. }
  745. }
  746. List<String> path = uri.getPathSegments();
  747. if (path == null) {
  748. throw new FileNotFoundException("No path: " + uri);
  749. }
  750. int len = path.size();
  751. int id;
  752. if (len == 1) {
  753. try {
  754. id = Integer.parseInt(path.get(0));
  755. } catch (NumberFormatException e) {
  756. throw new FileNotFoundException("Single path segment is not a resource ID: " + uri);
  757. }
  758. } else if (len == 2) {
  759. id = r.getIdentifier(path.get(1), path.get(0), authority);
  760. } else {
  761. throw new FileNotFoundException("More than two path segments: " + uri);
  762. }
  763. if (id == 0) {
  764. throw new FileNotFoundException("No resource found for: " + uri);
  765. }
  766. OpenResourceIdResult res = new OpenResourceIdResult();
  767. res.r = r;
  768. res.id = id;
  769. return res;
  770. }
  771. /** @hide */
  772. static public int modeToMode(Uri uri, String mode) throws FileNotFoundException {
  773. int modeBits;
  774. if ("r".equals(mode)) {
  775. modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
  776. } else if ("w".equals(mode) || "wt".equals(mode)) {
  777. modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
  778. | ParcelFileDescriptor.MODE_CREATE
  779. | ParcelFileDescriptor.MODE_TRUNCATE;
  780. } else if ("wa".equals(mode)) {
  781. modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
  782. | ParcelFileDescriptor.MODE_CREATE
  783. | ParcelFileDescriptor.MODE_APPEND;
  784. } else if ("rw".equals(mode)) {
  785. modeBits = ParcelFileDescriptor.MODE_READ_WRITE
  786. | ParcelFileDescriptor.MODE_CREATE;
  787. } else if ("rwt".equals(mode)) {
  788. modeBits = ParcelFileDescriptor.MODE_READ_WRITE
  789. | ParcelFileDescriptor.MODE_CREATE
  790. | ParcelFileDescriptor.MODE_TRUNCATE;
  791. } else {
  792. throw new FileNotFoundException("Bad mode for " + uri + ": "
  793. + mode);
  794. }
  795. return modeBits;
  796. }
  797. /**
  798. * Inserts a row into a table at the given URL.
  799. *
  800. * If the content provider supports transactions the insertion will be atomic.
  801. *
  802. * @param url The URL of the table to insert into.
  803. * @param values The initial values for the newly inserted row. The key is the column name for
  804. * the field. Passing an empty ContentValues will create an empty row.
  805. * @return the URL of the newly created row.
  806. */
  807. public final Uri insert(Uri url, ContentValues values)
  808. {
  809. IContentProvider provider = acquireProvider(url);
  810. if (provider == null) {
  811. throw new IllegalArgumentException("Unknown URL " + url);
  812. }
  813. try {
  814. long startTime = SystemClock.uptimeMillis();
  815. Uri createdRow = provider.insert(url, values);
  816. long durationMillis = SystemClock.uptimeMillis() - startTime;
  817. maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
  818. return createdRow;
  819. } catch (RemoteException e) {
  820. // Arbitrary and not worth documenting, as Activity
  821. // Manager will kill this process shortly anyway.
  822. return null;
  823. } finally {
  824. releaseProvider(provider);
  825. }
  826. }
  827. /**
  828. * Applies each of the {@link ContentProviderOperation} objects and returns an array
  829. * of their results. Passes through OperationApplicationException, which may be thrown
  830. * by the call to {@link ContentProviderOperation#apply}.
  831. * If all the applications succeed then a {@link ContentProviderResult} array with the
  832. * same number of elements as the operations will be returned. It is implementation-specific
  833. * how many, if any, operations will have been successfully applied if a call to
  834. * apply results in a {@link OperationApplicationException}.
  835. * @param authority the authority of the ContentProvider to which this batch should be applied
  836. * @param operations the operations to apply
  837. * @return the results of the applications
  838. * @throws OperationApplicationException thrown if an application fails.
  839. * See {@link ContentProviderOperation#apply} for more information.
  840. * @throws RemoteException thrown if a RemoteException is encountered while attempting
  841. * to communicate with a remote provider.
  842. */
  843. public ContentProviderResult[] applyBatch(String authority,
  844. ArrayList<ContentProviderOperation> operations)
  845. throws RemoteException, OperationApplicationException {
  846. ContentProviderClient provider = acquireContentProviderClient(authority);
  847. if (provider == null) {
  848. throw new IllegalArgumentException("Unknown authority " + authority);
  849. }
  850. try {
  851. return provider.applyBatch(operations);
  852. } finally {
  853. provider.release();
  854. }
  855. }
  856. /**
  857. * Inserts multiple rows into a table at the given URL.
  858. *
  859. * This function make no guarantees about the atomicity of the insertions.
  860. *
  861. * @param url The URL of the table to insert into.
  862. * @param values The initial values for the newly inserted rows. The key is the column name for
  863. * the field. Passing null will create an empty row.
  864. * @return the number of newly created rows.
  865. */
  866. public final int bulkInsert(Uri url, ContentValues[] values)
  867. {
  868. IContentProvider provider = acquireProvider(url);
  869. if (provider == null) {
  870. throw new IllegalArgumentException("Unknown URL " + url);
  871. }
  872. try {
  873. long startTime = SystemClock.uptimeMillis();
  874. int rowsCreated = provider.bulkInsert(url, values);
  875. long durationMillis = SystemClock.uptimeMillis() - startTime;
  876. maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
  877. return rowsCreated;
  878. } catch (RemoteException e) {
  879. // Arbitrary and not worth documenting, as Activity
  880. // Manager will kill this process shortly anyway.
  881. return 0;
  882. } finally {
  883. releaseProvider(provider);
  884. }
  885. }
  886. /**
  887. * Deletes row(s) specified by a content URI.
  888. *
  889. * If the content provider supports transactions, the deletion will be atomic.
  890. *
  891. * @param url The URL of the row to delete.
  892. * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause
  893. (excluding the WHERE itself).
  894. * @return The number of rows deleted.
  895. */
  896. public final int delete(Uri url, String where, String[] selectionArgs)
  897. {
  898. IContentProvider provider = acquireProvider(url);
  899. if (provider == null) {
  900. throw new IllegalArgumentException("Unknown URL " + url);
  901. }
  902. try {
  903. long startTime = SystemClock.uptimeMillis();
  904. int rowsDeleted = provider.delete(url, where, selectionArgs);
  905. long durationMillis = SystemClock.uptimeMillis() - startTime;
  906. maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
  907. return rowsDeleted;
  908. } catch (RemoteException e) {
  909. // Arbitrary and not worth documenting, as Activity
  910. // Manager will kill this process shortly anyway.
  911. return -1;
  912. } finally {
  913. releaseProvider(provider);
  914. }
  915. }
  916. /**
  917. * Update row(s) in a content URI.
  918. *
  919. * If the content provider supports transactions the update will be atomic.
  920. *
  921. * @param uri The URI to modify.
  922. * @param values The new field values. The key is the column name for the field.
  923. A null value will remove an existing field value.
  924. * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause
  925. (excluding the WHERE itself).
  926. * @return the number of rows updated.
  927. * @throws NullPointerException if uri or values are null
  928. */
  929. public final int update(Uri uri, ContentValues values, String where,
  930. String[] selectionArgs) {
  931. IContentProvider provider = acquireProvider(uri);
  932. if (provider == null) {
  933. throw new IllegalArgumentException("Unknown URI " + uri);
  934. }
  935. try {
  936. long startTime = SystemClock.uptimeMillis();
  937. int rowsUpdated = provider.update(uri, values, where, selectionArgs);
  938. long durationMillis = SystemClock.uptimeMillis() - startTime;
  939. maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
  940. return rowsUpdated;
  941. } catch (RemoteException e) {
  942. // Arbitrary and not worth documenting, as Activity
  943. // Manager will kill this process shortly anyway.
  944. return -1;
  945. } finally {
  946. releaseProvider(provider);
  947. }
  948. }
  949. /**
  950. * Call a provider-defined method. This can be used to implement
  951. * read or write interfaces which are cheaper than using a Cursor and/or
  952. * do not fit into the traditional table model.
  953. *
  954. * @param method provider-defined method name to call. Opaque to
  955. * framework, but must be non-null.
  956. * @param arg provider-defined String argument. May be null.
  957. * @param extras provider-defined Bundle argument. May be null.
  958. * @return a result Bundle, possibly null. Will be null if the ContentProvider
  959. * does not implement call.
  960. * @throws NullPointerException if uri or method is null
  961. * @throws IllegalArgumentException if uri is not known
  962. */
  963. public final Bundle call(Uri uri, String method, String arg, Bundle extras) {
  964. if (uri == null) {
  965. throw new NullPointerException("uri == null");
  966. }
  967. if (method == null) {
  968. throw new NullPointerException("method == null");
  969. }
  970. IContentProvider provider = acquireProvider(uri);
  971. if (provider == null) {
  972. throw new IllegalArgumentException("Unknown URI " + uri);
  973. }
  974. try {
  975. return provider.call(method, arg, extras);
  976. } catch (RemoteException e) {
  977. // Arbitrary and not worth documenting, as Activity
  978. // Manager will kill this process shortly anyway.
  979. return null;
  980. } finally {
  981. releaseProvider(provider);
  982. }
  983. }
  984. /**
  985. * Returns the content provider for the given content URI.
  986. *
  987. * @param uri The URI to a content provider
  988. * @return The ContentProvider for the given URI, or null if no content provider is found.
  989. * @hide
  990. */
  991. public final IContentProvider acquireProvider(Uri uri) {
  992. if (!SCHEME_CONTENT.equals(uri.getScheme())) {
  993. return null;
  994. }
  995. String auth = uri.getAuthority();
  996. if (auth != null) {
  997. return acquireProvider(mContext, uri.getAuthority());
  998. }
  999. return null;
  1000. }
  1001. /**
  1002. * Returns the content provider for the given content URI if the process
  1003. * already has a reference on it.
  1004. *
  1005. * @param uri The URI to a content provider
  1006. * @return The ContentProvider for the given URI, or null if no content provider is found.
  1007. * @hide
  1008. */
  1009. public final IContentProvider acquireExistingProvider(Uri uri) {
  1010. if (!SCHEME_CONTENT.equals(uri.getScheme())) {
  1011. return null;
  1012. }
  1013. String auth = uri.getAuthority();
  1014. if (auth != null) {
  1015. return acquireExistingProvider(mContext, uri.getAuthority());
  1016. }
  1017. return null;
  1018. }
  1019. /**
  1020. * @hide
  1021. */
  1022. public final IContentProvider acquireProvider(String name) {
  1023. if (name == null) {
  1024. return null;
  1025. }
  1026. return acquireProvider(mContext, name);
  1027. }
  1028. /**
  1029. * Returns the content provider for the given content URI.
  1030. *
  1031. * @param uri The URI to a content provider
  1032. * @return The ContentProvider for the given URI, or null if no content provider is found.
  1033. * @hide
  1034. */
  1035. public final IContentProvider acquireUnstableProvider(Uri uri) {
  1036. if (!SCHEME_CONTENT.equals(uri.getScheme())) {
  1037. return null;
  1038. }
  1039. String auth = uri.getAuthority();
  1040. if (auth != null) {
  1041. return acquireUnstableProvider(mContext, uri.getAuthority());
  1042. }
  1043. return null;
  1044. }
  1045. /**
  1046. * @hide
  1047. */
  1048. public final IContentProvider acquireUnstableProvider(String name) {
  1049. if (name == null) {
  1050. return null;
  1051. }
  1052. return acquireUnstableProvider(mContext, name);
  1053. }
  1054. /**
  1055. * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
  1056. * that services the content at uri, starting the provider if necessary. Returns
  1057. * null if there is no provider associated wih the uri. The caller must indicate that they are
  1058. * done with the provider by calling {@link ContentProviderClient#release} which will allow
  1059. * the system to release the provider it it determines that there is no other reason for
  1060. * keeping it active.
  1061. * @param uri specifies which provider should be acquired
  1062. * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
  1063. * that services the content at uri or null if there isn't one.
  1064. */
  1065. public final ContentProviderClient acquireContentProviderClient(Uri uri) {
  1066. IContentProvider provider = acquireProvider(uri);
  1067. if (provider != null) {
  1068. return new ContentProviderClient(this, provider, true);
  1069. }
  1070. return null;
  1071. }
  1072. /**
  1073. * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
  1074. * with the authority of name, starting the provider if necessary. Returns
  1075. * null if there is no provider associated wih the uri. The caller must indicate that they are
  1076. * done with the provider by calling {@link ContentProviderClient#release} which will allow
  1077. * the system to release the provider it it determines that there is no other reason for
  1078. * keeping it active.
  1079. * @param name specifies which provider should be acquired
  1080. * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
  1081. * with the authority of name or null if there isn't one.
  1082. */
  1083. public final ContentProviderClient acquireContentProviderClient(String name) {
  1084. IContentProvider provider = acquireProvider(name);
  1085. if (provider != null) {
  1086. return new ContentProviderClient(this, provider, true);
  1087. }
  1088. return null;
  1089. }
  1090. /**
  1091. * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do
  1092. * not trust the stability of the target content provider. This turns off
  1093. * the mechanism in the platform clean up processes that are dependent on
  1094. * a content provider if that content provider's process goes away. Normally
  1095. * you can safely assume that once you have acquired a provider, you can freely
  1096. * use it as needed and it won't disappear, even if your process is in the
  1097. * background. If using this method, you need to take care to deal with any
  1098. * failures when communicating with the provider, and be sure to close it
  1099. * so that it can be re-opened later. In particular, catching a
  1100. * {@link android.os.DeadObjectException} from the calls there will let you
  1101. * know that the content provider has gone away;