PageRenderTime 60ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/core/java/android/content/ContentResolver.java

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