• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.content;
18 
19 import android.accounts.Account;
20 import android.app.ActivityManagerNative;
21 import android.app.ActivityThread;
22 import android.app.AppGlobals;
23 import android.content.pm.PackageManager.NameNotFoundException;
24 import android.content.res.AssetFileDescriptor;
25 import android.content.res.Resources;
26 import android.database.ContentObserver;
27 import android.database.CrossProcessCursorWrapper;
28 import android.database.Cursor;
29 import android.database.IContentObserver;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.os.CancellationSignal;
33 import android.os.DeadObjectException;
34 import android.os.IBinder;
35 import android.os.ICancellationSignal;
36 import android.os.OperationCanceledException;
37 import android.os.ParcelFileDescriptor;
38 import android.os.RemoteException;
39 import android.os.ServiceManager;
40 import android.os.SystemClock;
41 import android.os.UserHandle;
42 import android.text.TextUtils;
43 import android.util.EventLog;
44 import android.util.Log;
45 
46 import dalvik.system.CloseGuard;
47 
48 import java.io.File;
49 import java.io.FileInputStream;
50 import java.io.FileNotFoundException;
51 import java.io.IOException;
52 import java.io.InputStream;
53 import java.io.OutputStream;
54 import java.util.ArrayList;
55 import java.util.List;
56 import java.util.Random;
57 
58 /**
59  * This class provides applications access to the content model.
60  *
61  * <div class="special reference">
62  * <h3>Developer Guides</h3>
63  * <p>For more information about using a ContentResolver with content providers, read the
64  * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
65  * developer guide.</p>
66  */
67 public abstract class ContentResolver {
68     /**
69      * @deprecated instead use
70      * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
71      */
72     @Deprecated
73     public static final String SYNC_EXTRAS_ACCOUNT = "account";
74 
75     /**
76      * If this extra is set to true, the sync request will be scheduled
77      * at the front of the sync request queue and without any delay
78      */
79     public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
80 
81     /**
82      * @deprecated instead use
83      * {@link #SYNC_EXTRAS_MANUAL}
84      */
85     @Deprecated
86     public static final String SYNC_EXTRAS_FORCE = "force";
87 
88     /**
89      * If this extra is set to true then the sync settings (like getSyncAutomatically())
90      * are ignored by the sync scheduler.
91      */
92     public static final String SYNC_EXTRAS_IGNORE_SETTINGS = "ignore_settings";
93 
94     /**
95      * If this extra is set to true then any backoffs for the initial attempt (e.g. due to retries)
96      * are ignored by the sync scheduler. If this request fails and gets rescheduled then the
97      * retries will still honor the backoff.
98      */
99     public static final String SYNC_EXTRAS_IGNORE_BACKOFF = "ignore_backoff";
100 
101     /**
102      * If this extra is set to true then the request will not be retried if it fails.
103      */
104     public static final String SYNC_EXTRAS_DO_NOT_RETRY = "do_not_retry";
105 
106     /**
107      * Setting this extra is the equivalent of setting both {@link #SYNC_EXTRAS_IGNORE_SETTINGS}
108      * and {@link #SYNC_EXTRAS_IGNORE_BACKOFF}
109      */
110     public static final String SYNC_EXTRAS_MANUAL = "force";
111 
112     /**
113      * Indicates that this sync is intended to only upload local changes to the server.
114      * For example, this will be set to true if the sync is initiated by a call to
115      * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}
116      */
117     public static final String SYNC_EXTRAS_UPLOAD = "upload";
118 
119     /**
120      * Indicates that the sync adapter should proceed with the delete operations,
121      * even if it determines that there are too many.
122      * See {@link SyncResult#tooManyDeletions}
123      */
124     public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
125 
126     /**
127      * Indicates that the sync adapter should not proceed with the delete operations,
128      * if it determines that there are too many.
129      * See {@link SyncResult#tooManyDeletions}
130      */
131     public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
132 
133     /* Extensions to API. TODO: Not clear if we will keep these as public flags. */
134     /** {@hide} User-specified flag for expected upload size. */
135     public static final String SYNC_EXTRAS_EXPECTED_UPLOAD = "expected_upload";
136 
137     /** {@hide} User-specified flag for expected download size. */
138     public static final String SYNC_EXTRAS_EXPECTED_DOWNLOAD = "expected_download";
139 
140     /** {@hide} Priority of this sync with respect to other syncs scheduled for this application. */
141     public static final String SYNC_EXTRAS_PRIORITY = "sync_priority";
142 
143     /** {@hide} Flag to allow sync to occur on metered network. */
144     public static final String SYNC_EXTRAS_DISALLOW_METERED = "disallow_metered";
145 
146     /**
147      * Set by the SyncManager to request that the SyncAdapter initialize itself for
148      * the given account/authority pair. One required initialization step is to
149      * ensure that {@link #setIsSyncable(android.accounts.Account, String, int)} has been
150      * called with a >= 0 value. When this flag is set the SyncAdapter does not need to
151      * do a full sync, though it is allowed to do so.
152      */
153     public static final String SYNC_EXTRAS_INITIALIZE = "initialize";
154 
155     /** @hide */
156     public static final Intent ACTION_SYNC_CONN_STATUS_CHANGED =
157             new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
158 
159     public static final String SCHEME_CONTENT = "content";
160     public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
161     public static final String SCHEME_FILE = "file";
162 
163     /**
164      * This is the Android platform's base MIME type for a content: URI
165      * containing a Cursor of a single item.  Applications should use this
166      * as the base type along with their own sub-type of their content: URIs
167      * that represent a particular item.  For example, hypothetical IMAP email
168      * client may have a URI
169      * <code>content://com.company.provider.imap/inbox/1</code> for a particular
170      * message in the inbox, whose MIME type would be reported as
171      * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code>
172      *
173      * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}.
174      */
175     public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
176 
177     /**
178      * This is the Android platform's base MIME type for a content: URI
179      * containing a Cursor of zero or more items.  Applications should use this
180      * as the base type along with their own sub-type of their content: URIs
181      * that represent a directory of items.  For example, hypothetical IMAP email
182      * client may have a URI
183      * <code>content://com.company.provider.imap/inbox</code> for all of the
184      * messages in its inbox, whose MIME type would be reported as
185      * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code>
186      *
187      * <p>Note how the base MIME type varies between this and
188      * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is
189      * one single item or multiple items in the data set, while the sub-type
190      * remains the same because in either case the data structure contained
191      * in the cursor is the same.
192      */
193     public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
194 
195     /** @hide */
196     public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
197     /** @hide */
198     public static final int SYNC_ERROR_AUTHENTICATION = 2;
199     /** @hide */
200     public static final int SYNC_ERROR_IO = 3;
201     /** @hide */
202     public static final int SYNC_ERROR_PARSE = 4;
203     /** @hide */
204     public static final int SYNC_ERROR_CONFLICT = 5;
205     /** @hide */
206     public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6;
207     /** @hide */
208     public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7;
209     /** @hide */
210     public static final int SYNC_ERROR_INTERNAL = 8;
211 
212     private static final String[] SYNC_ERROR_NAMES = new String[] {
213           "already-in-progress",
214           "authentication-error",
215           "io-error",
216           "parse-error",
217           "conflict",
218           "too-many-deletions",
219           "too-many-retries",
220           "internal-error",
221     };
222 
223     /** @hide */
syncErrorToString(int error)224     public static String syncErrorToString(int error) {
225         if (error < 1 || error > SYNC_ERROR_NAMES.length) {
226             return String.valueOf(error);
227         }
228         return SYNC_ERROR_NAMES[error - 1];
229     }
230 
231     /** @hide */
syncErrorStringToInt(String error)232     public static int syncErrorStringToInt(String error) {
233         for (int i = 0, n = SYNC_ERROR_NAMES.length; i < n; i++) {
234             if (SYNC_ERROR_NAMES[i].equals(error)) {
235                 return i + 1;
236             }
237         }
238         if (error != null) {
239             try {
240                 return Integer.parseInt(error);
241             } catch (NumberFormatException e) {
242                 Log.d(TAG, "error parsing sync error: " + error);
243             }
244         }
245         return 0;
246     }
247 
248     public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0;
249     public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
250     public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
251     /** @hide */
252     public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3;
253     /** @hide */
254     public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
255 
256     // Always log queries which take 500ms+; shorter queries are
257     // sampled accordingly.
258     private static final boolean ENABLE_CONTENT_SAMPLE = false;
259     private static final int SLOW_THRESHOLD_MILLIS = 500;
260     private final Random mRandom = new Random();  // guarded by itself
261 
ContentResolver(Context context)262     public ContentResolver(Context context) {
263         mContext = context != null ? context : ActivityThread.currentApplication();
264         mPackageName = mContext.getOpPackageName();
265     }
266 
267     /** @hide */
acquireProvider(Context c, String name)268     protected abstract IContentProvider acquireProvider(Context c, String name);
269 
270     /**
271      * Providing a default implementation of this, to avoid having to change a
272      * lot of other things, but implementations of ContentResolver should
273      * implement it.
274      *
275      * @hide
276      */
acquireExistingProvider(Context c, String name)277     protected IContentProvider acquireExistingProvider(Context c, String name) {
278         return acquireProvider(c, name);
279     }
280 
281     /** @hide */
releaseProvider(IContentProvider icp)282     public abstract boolean releaseProvider(IContentProvider icp);
283     /** @hide */
acquireUnstableProvider(Context c, String name)284     protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
285     /** @hide */
releaseUnstableProvider(IContentProvider icp)286     public abstract boolean releaseUnstableProvider(IContentProvider icp);
287     /** @hide */
unstableProviderDied(IContentProvider icp)288     public abstract void unstableProviderDied(IContentProvider icp);
289 
290     /** @hide */
appNotRespondingViaProvider(IContentProvider icp)291     public void appNotRespondingViaProvider(IContentProvider icp) {
292         throw new UnsupportedOperationException("appNotRespondingViaProvider");
293     }
294 
295     /**
296      * Return the MIME type of the given content URL.
297      *
298      * @param url A Uri identifying content (either a list or specific type),
299      * using the content:// scheme.
300      * @return A MIME type for the content, or null if the URL is invalid or the type is unknown
301      */
getType(Uri url)302     public final String getType(Uri url) {
303         // XXX would like to have an acquireExistingUnstableProvider for this.
304         IContentProvider provider = acquireExistingProvider(url);
305         if (provider != null) {
306             try {
307                 return provider.getType(url);
308             } catch (RemoteException e) {
309                 return null;
310             } catch (java.lang.Exception e) {
311                 Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
312                 return null;
313             } finally {
314                 releaseProvider(provider);
315             }
316         }
317 
318         if (!SCHEME_CONTENT.equals(url.getScheme())) {
319             return null;
320         }
321 
322         try {
323             String type = ActivityManagerNative.getDefault().getProviderMimeType(
324                     url, UserHandle.myUserId());
325             return type;
326         } catch (RemoteException e) {
327             // Arbitrary and not worth documenting, as Activity
328             // Manager will kill this process shortly anyway.
329             return null;
330         } catch (java.lang.Exception e) {
331             Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
332             return null;
333         }
334     }
335 
336     /**
337      * Query for the possible MIME types for the representations the given
338      * content URL can be returned when opened as as stream with
339      * {@link #openTypedAssetFileDescriptor}.  Note that the types here are
340      * not necessarily a superset of the type returned by {@link #getType} --
341      * many content providers cannot return a raw stream for the structured
342      * data that they contain.
343      *
344      * @param url A Uri identifying content (either a list or specific type),
345      * using the content:// scheme.
346      * @param mimeTypeFilter The desired MIME type.  This may be a pattern,
347      * such as *\/*, to query for all available MIME types that match the
348      * pattern.
349      * @return Returns an array of MIME type strings for all available
350      * data streams that match the given mimeTypeFilter.  If there are none,
351      * null is returned.
352      */
getStreamTypes(Uri url, String mimeTypeFilter)353     public String[] getStreamTypes(Uri url, String mimeTypeFilter) {
354         IContentProvider provider = acquireProvider(url);
355         if (provider == null) {
356             return null;
357         }
358 
359         try {
360             return provider.getStreamTypes(url, mimeTypeFilter);
361         } catch (RemoteException e) {
362             // Arbitrary and not worth documenting, as Activity
363             // Manager will kill this process shortly anyway.
364             return null;
365         } finally {
366             releaseProvider(provider);
367         }
368     }
369 
370     /**
371      * <p>
372      * Query the given URI, returning a {@link Cursor} over the result set.
373      * </p>
374      * <p>
375      * For best performance, the caller should follow these guidelines:
376      * <ul>
377      * <li>Provide an explicit projection, to prevent
378      * reading data from storage that aren't going to be used.</li>
379      * <li>Use question mark parameter markers such as 'phone=?' instead of
380      * explicit values in the {@code selection} parameter, so that queries
381      * that differ only by those values will be recognized as the same
382      * for caching purposes.</li>
383      * </ul>
384      * </p>
385      *
386      * @param uri The URI, using the content:// scheme, for the content to
387      *         retrieve.
388      * @param projection A list of which columns to return. Passing null will
389      *         return all columns, which is inefficient.
390      * @param selection A filter declaring which rows to return, formatted as an
391      *         SQL WHERE clause (excluding the WHERE itself). Passing null will
392      *         return all rows for the given URI.
393      * @param selectionArgs You may include ?s in selection, which will be
394      *         replaced by the values from selectionArgs, in the order that they
395      *         appear in the selection. The values will be bound as Strings.
396      * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
397      *         clause (excluding the ORDER BY itself). Passing null will use the
398      *         default sort order, which may be unordered.
399      * @return A Cursor object, which is positioned before the first entry, or null
400      * @see Cursor
401      */
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)402     public final Cursor query(Uri uri, String[] projection,
403             String selection, String[] selectionArgs, String sortOrder) {
404         return query(uri, projection, selection, selectionArgs, sortOrder, null);
405     }
406 
407     /**
408      * <p>
409      * Query the given URI, returning a {@link Cursor} over the result set.
410      * </p>
411      * <p>
412      * For best performance, the caller should follow these guidelines:
413      * <ul>
414      * <li>Provide an explicit projection, to prevent
415      * reading data from storage that aren't going to be used.</li>
416      * <li>Use question mark parameter markers such as 'phone=?' instead of
417      * explicit values in the {@code selection} parameter, so that queries
418      * that differ only by those values will be recognized as the same
419      * for caching purposes.</li>
420      * </ul>
421      * </p>
422      *
423      * @param uri The URI, using the content:// scheme, for the content to
424      *         retrieve.
425      * @param projection A list of which columns to return. Passing null will
426      *         return all columns, which is inefficient.
427      * @param selection A filter declaring which rows to return, formatted as an
428      *         SQL WHERE clause (excluding the WHERE itself). Passing null will
429      *         return all rows for the given URI.
430      * @param selectionArgs You may include ?s in selection, which will be
431      *         replaced by the values from selectionArgs, in the order that they
432      *         appear in the selection. The values will be bound as Strings.
433      * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
434      *         clause (excluding the ORDER BY itself). Passing null will use the
435      *         default sort order, which may be unordered.
436      * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
437      * If the operation is canceled, then {@link OperationCanceledException} will be thrown
438      * when the query is executed.
439      * @return A Cursor object, which is positioned before the first entry, or null
440      * @see Cursor
441      */
query(final Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)442     public final Cursor query(final Uri uri, String[] projection,
443             String selection, String[] selectionArgs, String sortOrder,
444             CancellationSignal cancellationSignal) {
445         IContentProvider unstableProvider = acquireUnstableProvider(uri);
446         if (unstableProvider == null) {
447             return null;
448         }
449         IContentProvider stableProvider = null;
450         Cursor qCursor = null;
451         try {
452             long startTime = SystemClock.uptimeMillis();
453 
454             ICancellationSignal remoteCancellationSignal = null;
455             if (cancellationSignal != null) {
456                 cancellationSignal.throwIfCanceled();
457                 remoteCancellationSignal = unstableProvider.createCancellationSignal();
458                 cancellationSignal.setRemote(remoteCancellationSignal);
459             }
460             try {
461                 qCursor = unstableProvider.query(mPackageName, uri, projection,
462                         selection, selectionArgs, sortOrder, remoteCancellationSignal);
463             } catch (DeadObjectException e) {
464                 // The remote process has died...  but we only hold an unstable
465                 // reference though, so we might recover!!!  Let's try!!!!
466                 // This is exciting!!1!!1!!!!1
467                 unstableProviderDied(unstableProvider);
468                 stableProvider = acquireProvider(uri);
469                 if (stableProvider == null) {
470                     return null;
471                 }
472                 qCursor = stableProvider.query(mPackageName, uri, projection,
473                         selection, selectionArgs, sortOrder, remoteCancellationSignal);
474             }
475             if (qCursor == null) {
476                 return null;
477             }
478 
479             // Force query execution.  Might fail and throw a runtime exception here.
480             qCursor.getCount();
481             long durationMillis = SystemClock.uptimeMillis() - startTime;
482             maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
483 
484             // Wrap the cursor object into CursorWrapperInner object.
485             CursorWrapperInner wrapper = new CursorWrapperInner(qCursor,
486                     stableProvider != null ? stableProvider : acquireProvider(uri));
487             stableProvider = null;
488             qCursor = null;
489             return wrapper;
490         } catch (RemoteException e) {
491             // Arbitrary and not worth documenting, as Activity
492             // Manager will kill this process shortly anyway.
493             return null;
494         } finally {
495             if (qCursor != null) {
496                 qCursor.close();
497             }
498             if (cancellationSignal != null) {
499                 cancellationSignal.setRemote(null);
500             }
501             if (unstableProvider != null) {
502                 releaseUnstableProvider(unstableProvider);
503             }
504             if (stableProvider != null) {
505                 releaseProvider(stableProvider);
506             }
507         }
508     }
509 
510     /**
511      * Transform the given <var>url</var> to a canonical representation of
512      * its referenced resource, which can be used across devices, persisted,
513      * backed up and restored, etc.  The returned Uri is still a fully capable
514      * Uri for use with its content provider, allowing you to do all of the
515      * same content provider operations as with the original Uri --
516      * {@link #query}, {@link #openInputStream(android.net.Uri)}, etc.  The
517      * only difference in behavior between the original and new Uris is that
518      * the content provider may need to do some additional work at each call
519      * using it to resolve it to the correct resource, especially if the
520      * canonical Uri has been moved to a different environment.
521      *
522      * <p>If you are moving a canonical Uri between environments, you should
523      * perform another call to {@link #canonicalize} with that original Uri to
524      * re-canonicalize it for the current environment.  Alternatively, you may
525      * want to use {@link #uncanonicalize} to transform it to a non-canonical
526      * Uri that works only in the current environment but potentially more
527      * efficiently than the canonical representation.</p>
528      *
529      * @param url The {@link Uri} that is to be transformed to a canonical
530      * representation.  Like all resolver calls, the input can be either
531      * a non-canonical or canonical Uri.
532      *
533      * @return Returns the official canonical representation of <var>url</var>,
534      * or null if the content provider does not support a canonical representation
535      * of the given Uri.  Many providers may not support canonicalization of some
536      * or all of their Uris.
537      *
538      * @see #uncanonicalize
539      */
canonicalize(Uri url)540     public final Uri canonicalize(Uri url) {
541         IContentProvider provider = acquireProvider(url);
542         if (provider == null) {
543             return null;
544         }
545 
546         try {
547             return provider.canonicalize(mPackageName, url);
548         } catch (RemoteException e) {
549             // Arbitrary and not worth documenting, as Activity
550             // Manager will kill this process shortly anyway.
551             return null;
552         } finally {
553             releaseProvider(provider);
554         }
555     }
556 
557     /**
558      * Given a canonical Uri previously generated by {@link #canonicalize}, convert
559      * it to its local non-canonical form.  This can be useful in some cases where
560      * you know that you will only be using the Uri in the current environment and
561      * want to avoid any possible overhead when using it with the content
562      * provider or want to verify that the referenced data exists at all in the
563      * new environment.
564      *
565      * @param url The canonical {@link Uri} that is to be convered back to its
566      * non-canonical form.
567      *
568      * @return Returns the non-canonical representation of <var>url</var>.  This will
569      * return null if data identified by the canonical Uri can not be found in
570      * the current environment; callers must always check for null and deal with
571      * that by appropriately falling back to an alternative.
572      *
573      * @see #canonicalize
574      */
uncanonicalize(Uri url)575     public final Uri uncanonicalize(Uri url) {
576         IContentProvider provider = acquireProvider(url);
577         if (provider == null) {
578             return null;
579         }
580 
581         try {
582             return provider.uncanonicalize(mPackageName, url);
583         } catch (RemoteException e) {
584             // Arbitrary and not worth documenting, as Activity
585             // Manager will kill this process shortly anyway.
586             return null;
587         } finally {
588             releaseProvider(provider);
589         }
590     }
591 
592     /**
593      * Open a stream on to the content associated with a content URI.  If there
594      * is no data associated with the URI, FileNotFoundException is thrown.
595      *
596      * <h5>Accepts the following URI schemes:</h5>
597      * <ul>
598      * <li>content ({@link #SCHEME_CONTENT})</li>
599      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
600      * <li>file ({@link #SCHEME_FILE})</li>
601      * </ul>
602      *
603      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
604      * on these schemes.
605      *
606      * @param uri The desired URI.
607      * @return InputStream
608      * @throws FileNotFoundException if the provided URI could not be opened.
609      * @see #openAssetFileDescriptor(Uri, String)
610      */
openInputStream(Uri uri)611     public final InputStream openInputStream(Uri uri)
612             throws FileNotFoundException {
613         String scheme = uri.getScheme();
614         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
615             // Note: left here to avoid breaking compatibility.  May be removed
616             // with sufficient testing.
617             OpenResourceIdResult r = getResourceId(uri);
618             try {
619                 InputStream stream = r.r.openRawResource(r.id);
620                 return stream;
621             } catch (Resources.NotFoundException ex) {
622                 throw new FileNotFoundException("Resource does not exist: " + uri);
623             }
624         } else if (SCHEME_FILE.equals(scheme)) {
625             // Note: left here to avoid breaking compatibility.  May be removed
626             // with sufficient testing.
627             return new FileInputStream(uri.getPath());
628         } else {
629             AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r", null);
630             try {
631                 return fd != null ? fd.createInputStream() : null;
632             } catch (IOException e) {
633                 throw new FileNotFoundException("Unable to create stream");
634             }
635         }
636     }
637 
638     /**
639      * Synonym for {@link #openOutputStream(Uri, String)
640      * openOutputStream(uri, "w")}.
641      * @throws FileNotFoundException if the provided URI could not be opened.
642      */
openOutputStream(Uri uri)643     public final OutputStream openOutputStream(Uri uri)
644             throws FileNotFoundException {
645         return openOutputStream(uri, "w");
646     }
647 
648     /**
649      * Open a stream on to the content associated with a content URI.  If there
650      * is no data associated with the URI, FileNotFoundException is thrown.
651      *
652      * <h5>Accepts the following URI schemes:</h5>
653      * <ul>
654      * <li>content ({@link #SCHEME_CONTENT})</li>
655      * <li>file ({@link #SCHEME_FILE})</li>
656      * </ul>
657      *
658      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
659      * on these schemes.
660      *
661      * @param uri The desired URI.
662      * @param mode May be "w", "wa", "rw", or "rwt".
663      * @return OutputStream
664      * @throws FileNotFoundException if the provided URI could not be opened.
665      * @see #openAssetFileDescriptor(Uri, String)
666      */
openOutputStream(Uri uri, String mode)667     public final OutputStream openOutputStream(Uri uri, String mode)
668             throws FileNotFoundException {
669         AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null);
670         try {
671             return fd != null ? fd.createOutputStream() : null;
672         } catch (IOException e) {
673             throw new FileNotFoundException("Unable to create stream");
674         }
675     }
676 
677     /**
678      * Open a raw file descriptor to access data under a URI.  This
679      * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
680      * underlying {@link ContentProvider#openFile}
681      * ContentProvider.openFile()} method, so will <em>not</em> work with
682      * providers that return sub-sections of files.  If at all possible,
683      * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
684      * will receive a FileNotFoundException exception if the provider returns a
685      * sub-section of a file.
686      *
687      * <h5>Accepts the following URI schemes:</h5>
688      * <ul>
689      * <li>content ({@link #SCHEME_CONTENT})</li>
690      * <li>file ({@link #SCHEME_FILE})</li>
691      * </ul>
692      *
693      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
694      * on these schemes.
695      * <p>
696      * If opening with the exclusive "r" or "w" modes, the returned
697      * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
698      * of data. Opening with the "rw" mode implies a file on disk that supports
699      * seeking. If possible, always use an exclusive mode to give the underlying
700      * {@link ContentProvider} the most flexibility.
701      * <p>
702      * If you are writing a file, and need to communicate an error to the
703      * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
704      *
705      * @param uri The desired URI to open.
706      * @param mode The file mode to use, as per {@link ContentProvider#openFile
707      * ContentProvider.openFile}.
708      * @return Returns a new ParcelFileDescriptor pointing to the file.  You
709      * own this descriptor and are responsible for closing it when done.
710      * @throws FileNotFoundException Throws FileNotFoundException if no
711      * file exists under the URI or the mode is invalid.
712      * @see #openAssetFileDescriptor(Uri, String)
713      */
openFileDescriptor(Uri uri, String mode)714     public final ParcelFileDescriptor openFileDescriptor(Uri uri, String mode)
715             throws FileNotFoundException {
716         return openFileDescriptor(uri, mode, null);
717     }
718 
719     /**
720      * Open a raw file descriptor to access data under a URI.  This
721      * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
722      * underlying {@link ContentProvider#openFile}
723      * ContentProvider.openFile()} method, so will <em>not</em> work with
724      * providers that return sub-sections of files.  If at all possible,
725      * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
726      * will receive a FileNotFoundException exception if the provider returns a
727      * sub-section of a file.
728      *
729      * <h5>Accepts the following URI schemes:</h5>
730      * <ul>
731      * <li>content ({@link #SCHEME_CONTENT})</li>
732      * <li>file ({@link #SCHEME_FILE})</li>
733      * </ul>
734      *
735      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
736      * on these schemes.
737      * <p>
738      * If opening with the exclusive "r" or "w" modes, the returned
739      * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
740      * of data. Opening with the "rw" mode implies a file on disk that supports
741      * seeking. If possible, always use an exclusive mode to give the underlying
742      * {@link ContentProvider} the most flexibility.
743      * <p>
744      * If you are writing a file, and need to communicate an error to the
745      * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
746      *
747      * @param uri The desired URI to open.
748      * @param mode The file mode to use, as per {@link ContentProvider#openFile
749      * ContentProvider.openFile}.
750      * @param cancellationSignal A signal to cancel the operation in progress,
751      *         or null if none. If the operation is canceled, then
752      *         {@link OperationCanceledException} will be thrown.
753      * @return Returns a new ParcelFileDescriptor pointing to the file.  You
754      * own this descriptor and are responsible for closing it when done.
755      * @throws FileNotFoundException Throws FileNotFoundException if no
756      * file exists under the URI or the mode is invalid.
757      * @see #openAssetFileDescriptor(Uri, String)
758      */
openFileDescriptor(Uri uri, String mode, CancellationSignal cancellationSignal)759     public final ParcelFileDescriptor openFileDescriptor(Uri uri,
760             String mode, CancellationSignal cancellationSignal) throws FileNotFoundException {
761         AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal);
762         if (afd == null) {
763             return null;
764         }
765 
766         if (afd.getDeclaredLength() < 0) {
767             // This is a full file!
768             return afd.getParcelFileDescriptor();
769         }
770 
771         // Client can't handle a sub-section of a file, so close what
772         // we got and bail with an exception.
773         try {
774             afd.close();
775         } catch (IOException e) {
776         }
777 
778         throw new FileNotFoundException("Not a whole file");
779     }
780 
781     /**
782      * Open a raw file descriptor to access data under a URI.  This
783      * interacts with the underlying {@link ContentProvider#openAssetFile}
784      * method of the provider associated with the given URI, to retrieve any file stored there.
785      *
786      * <h5>Accepts the following URI schemes:</h5>
787      * <ul>
788      * <li>content ({@link #SCHEME_CONTENT})</li>
789      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
790      * <li>file ({@link #SCHEME_FILE})</li>
791      * </ul>
792      * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
793      * <p>
794      * A Uri object can be used to reference a resource in an APK file.  The
795      * Uri should be one of the following formats:
796      * <ul>
797      * <li><code>android.resource://package_name/id_number</code><br/>
798      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
799      * For example <code>com.example.myapp</code><br/>
800      * <code>id_number</code> is the int form of the ID.<br/>
801      * The easiest way to construct this form is
802      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
803      * </li>
804      * <li><code>android.resource://package_name/type/name</code><br/>
805      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
806      * For example <code>com.example.myapp</code><br/>
807      * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
808      * or <code>drawable</code>.
809      * <code>name</code> is the string form of the resource name.  That is, whatever the file
810      * name was in your res directory, without the type extension.
811      * The easiest way to construct this form is
812      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
813      * </li>
814      * </ul>
815      *
816      * <p>Note that if this function is called for read-only input (mode is "r")
817      * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
818      * for you with a MIME type of "*\/*".  This allows such callers to benefit
819      * from any built-in data conversion that a provider implements.
820      *
821      * @param uri The desired URI to open.
822      * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
823      * ContentProvider.openAssetFile}.
824      * @return Returns a new ParcelFileDescriptor pointing to the file.  You
825      * own this descriptor and are responsible for closing it when done.
826      * @throws FileNotFoundException Throws FileNotFoundException of no
827      * file exists under the URI or the mode is invalid.
828      */
openAssetFileDescriptor(Uri uri, String mode)829     public final AssetFileDescriptor openAssetFileDescriptor(Uri uri, String mode)
830             throws FileNotFoundException {
831         return openAssetFileDescriptor(uri, mode, null);
832     }
833 
834     /**
835      * Open a raw file descriptor to access data under a URI.  This
836      * interacts with the underlying {@link ContentProvider#openAssetFile}
837      * method of the provider associated with the given URI, to retrieve any file stored there.
838      *
839      * <h5>Accepts the following URI schemes:</h5>
840      * <ul>
841      * <li>content ({@link #SCHEME_CONTENT})</li>
842      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
843      * <li>file ({@link #SCHEME_FILE})</li>
844      * </ul>
845      * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
846      * <p>
847      * A Uri object can be used to reference a resource in an APK file.  The
848      * Uri should be one of the following formats:
849      * <ul>
850      * <li><code>android.resource://package_name/id_number</code><br/>
851      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
852      * For example <code>com.example.myapp</code><br/>
853      * <code>id_number</code> is the int form of the ID.<br/>
854      * The easiest way to construct this form is
855      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
856      * </li>
857      * <li><code>android.resource://package_name/type/name</code><br/>
858      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
859      * For example <code>com.example.myapp</code><br/>
860      * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
861      * or <code>drawable</code>.
862      * <code>name</code> is the string form of the resource name.  That is, whatever the file
863      * name was in your res directory, without the type extension.
864      * The easiest way to construct this form is
865      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
866      * </li>
867      * </ul>
868      *
869      * <p>Note that if this function is called for read-only input (mode is "r")
870      * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
871      * for you with a MIME type of "*\/*".  This allows such callers to benefit
872      * from any built-in data conversion that a provider implements.
873      *
874      * @param uri The desired URI to open.
875      * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
876      * ContentProvider.openAssetFile}.
877      * @param cancellationSignal A signal to cancel the operation in progress, or null if
878      *            none. If the operation is canceled, then
879      *            {@link OperationCanceledException} will be thrown.
880      * @return Returns a new ParcelFileDescriptor pointing to the file.  You
881      * own this descriptor and are responsible for closing it when done.
882      * @throws FileNotFoundException Throws FileNotFoundException of no
883      * file exists under the URI or the mode is invalid.
884      */
openAssetFileDescriptor(Uri uri, String mode, CancellationSignal cancellationSignal)885     public final AssetFileDescriptor openAssetFileDescriptor(Uri uri,
886             String mode, CancellationSignal cancellationSignal) throws FileNotFoundException {
887         String scheme = uri.getScheme();
888         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
889             if (!"r".equals(mode)) {
890                 throw new FileNotFoundException("Can't write resources: " + uri);
891             }
892             OpenResourceIdResult r = getResourceId(uri);
893             try {
894                 return r.r.openRawResourceFd(r.id);
895             } catch (Resources.NotFoundException ex) {
896                 throw new FileNotFoundException("Resource does not exist: " + uri);
897             }
898         } else if (SCHEME_FILE.equals(scheme)) {
899             ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
900                     new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode));
901             return new AssetFileDescriptor(pfd, 0, -1);
902         } else {
903             if ("r".equals(mode)) {
904                 return openTypedAssetFileDescriptor(uri, "*/*", null, cancellationSignal);
905             } else {
906                 IContentProvider unstableProvider = acquireUnstableProvider(uri);
907                 if (unstableProvider == null) {
908                     throw new FileNotFoundException("No content provider: " + uri);
909                 }
910                 IContentProvider stableProvider = null;
911                 AssetFileDescriptor fd = null;
912 
913                 try {
914                     ICancellationSignal remoteCancellationSignal = null;
915                     if (cancellationSignal != null) {
916                         cancellationSignal.throwIfCanceled();
917                         remoteCancellationSignal = unstableProvider.createCancellationSignal();
918                         cancellationSignal.setRemote(remoteCancellationSignal);
919                     }
920 
921                     try {
922                         fd = unstableProvider.openAssetFile(
923                                 mPackageName, uri, mode, remoteCancellationSignal);
924                         if (fd == null) {
925                             // The provider will be released by the finally{} clause
926                             return null;
927                         }
928                     } catch (DeadObjectException e) {
929                         // The remote process has died...  but we only hold an unstable
930                         // reference though, so we might recover!!!  Let's try!!!!
931                         // This is exciting!!1!!1!!!!1
932                         unstableProviderDied(unstableProvider);
933                         stableProvider = acquireProvider(uri);
934                         if (stableProvider == null) {
935                             throw new FileNotFoundException("No content provider: " + uri);
936                         }
937                         fd = stableProvider.openAssetFile(
938                                 mPackageName, uri, mode, remoteCancellationSignal);
939                         if (fd == null) {
940                             // The provider will be released by the finally{} clause
941                             return null;
942                         }
943                     }
944 
945                     if (stableProvider == null) {
946                         stableProvider = acquireProvider(uri);
947                     }
948                     releaseUnstableProvider(unstableProvider);
949                     ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
950                             fd.getParcelFileDescriptor(), stableProvider);
951 
952                     // Success!  Don't release the provider when exiting, let
953                     // ParcelFileDescriptorInner do that when it is closed.
954                     stableProvider = null;
955 
956                     return new AssetFileDescriptor(pfd, fd.getStartOffset(),
957                             fd.getDeclaredLength());
958 
959                 } catch (RemoteException e) {
960                     // Whatever, whatever, we'll go away.
961                     throw new FileNotFoundException(
962                             "Failed opening content provider: " + uri);
963                 } catch (FileNotFoundException e) {
964                     throw e;
965                 } finally {
966                     if (cancellationSignal != null) {
967                         cancellationSignal.setRemote(null);
968                     }
969                     if (stableProvider != null) {
970                         releaseProvider(stableProvider);
971                     }
972                     if (unstableProvider != null) {
973                         releaseUnstableProvider(unstableProvider);
974                     }
975                 }
976             }
977         }
978     }
979 
980     /**
981      * Open a raw file descriptor to access (potentially type transformed)
982      * data from a "content:" URI.  This interacts with the underlying
983      * {@link ContentProvider#openTypedAssetFile} method of the provider
984      * associated with the given URI, to retrieve retrieve any appropriate
985      * data stream for the data stored there.
986      *
987      * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
988      * with "content:" URIs, because content providers are the only facility
989      * with an associated MIME type to ensure that the returned data stream
990      * is of the desired type.
991      *
992      * <p>All text/* streams are encoded in UTF-8.
993      *
994      * @param uri The desired URI to open.
995      * @param mimeType The desired MIME type of the returned data.  This can
996      * be a pattern such as *\/*, which will allow the content provider to
997      * select a type, though there is no way for you to determine what type
998      * it is returning.
999      * @param opts Additional provider-dependent options.
1000      * @return Returns a new ParcelFileDescriptor from which you can read the
1001      * data stream from the provider.  Note that this may be a pipe, meaning
1002      * you can't seek in it.  The only seek you should do is if the
1003      * AssetFileDescriptor contains an offset, to move to that offset before
1004      * reading.  You own this descriptor and are responsible for closing it when done.
1005      * @throws FileNotFoundException Throws FileNotFoundException of no
1006      * data of the desired type exists under the URI.
1007      */
openTypedAssetFileDescriptor( Uri uri, String mimeType, Bundle opts)1008     public final AssetFileDescriptor openTypedAssetFileDescriptor(
1009             Uri uri, String mimeType, Bundle opts) throws FileNotFoundException {
1010         return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
1011     }
1012 
1013     /**
1014      * Open a raw file descriptor to access (potentially type transformed)
1015      * data from a "content:" URI.  This interacts with the underlying
1016      * {@link ContentProvider#openTypedAssetFile} method of the provider
1017      * associated with the given URI, to retrieve retrieve any appropriate
1018      * data stream for the data stored there.
1019      *
1020      * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
1021      * with "content:" URIs, because content providers are the only facility
1022      * with an associated MIME type to ensure that the returned data stream
1023      * is of the desired type.
1024      *
1025      * <p>All text/* streams are encoded in UTF-8.
1026      *
1027      * @param uri The desired URI to open.
1028      * @param mimeType The desired MIME type of the returned data.  This can
1029      * be a pattern such as *\/*, which will allow the content provider to
1030      * select a type, though there is no way for you to determine what type
1031      * it is returning.
1032      * @param opts Additional provider-dependent options.
1033      * @param cancellationSignal A signal to cancel the operation in progress,
1034      *         or null if none. If the operation is canceled, then
1035      *         {@link OperationCanceledException} will be thrown.
1036      * @return Returns a new ParcelFileDescriptor from which you can read the
1037      * data stream from the provider.  Note that this may be a pipe, meaning
1038      * you can't seek in it.  The only seek you should do is if the
1039      * AssetFileDescriptor contains an offset, to move to that offset before
1040      * reading.  You own this descriptor and are responsible for closing it when done.
1041      * @throws FileNotFoundException Throws FileNotFoundException of no
1042      * data of the desired type exists under the URI.
1043      */
openTypedAssetFileDescriptor(Uri uri, String mimeType, Bundle opts, CancellationSignal cancellationSignal)1044     public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
1045             String mimeType, Bundle opts, CancellationSignal cancellationSignal)
1046             throws FileNotFoundException {
1047         IContentProvider unstableProvider = acquireUnstableProvider(uri);
1048         if (unstableProvider == null) {
1049             throw new FileNotFoundException("No content provider: " + uri);
1050         }
1051         IContentProvider stableProvider = null;
1052         AssetFileDescriptor fd = null;
1053 
1054         try {
1055             ICancellationSignal remoteCancellationSignal = null;
1056             if (cancellationSignal != null) {
1057                 cancellationSignal.throwIfCanceled();
1058                 remoteCancellationSignal = unstableProvider.createCancellationSignal();
1059                 cancellationSignal.setRemote(remoteCancellationSignal);
1060             }
1061 
1062             try {
1063                 fd = unstableProvider.openTypedAssetFile(
1064                         mPackageName, uri, mimeType, opts, remoteCancellationSignal);
1065                 if (fd == null) {
1066                     // The provider will be released by the finally{} clause
1067                     return null;
1068                 }
1069             } catch (DeadObjectException e) {
1070                 // The remote process has died...  but we only hold an unstable
1071                 // reference though, so we might recover!!!  Let's try!!!!
1072                 // This is exciting!!1!!1!!!!1
1073                 unstableProviderDied(unstableProvider);
1074                 stableProvider = acquireProvider(uri);
1075                 if (stableProvider == null) {
1076                     throw new FileNotFoundException("No content provider: " + uri);
1077                 }
1078                 fd = stableProvider.openTypedAssetFile(
1079                         mPackageName, uri, mimeType, opts, remoteCancellationSignal);
1080                 if (fd == null) {
1081                     // The provider will be released by the finally{} clause
1082                     return null;
1083                 }
1084             }
1085 
1086             if (stableProvider == null) {
1087                 stableProvider = acquireProvider(uri);
1088             }
1089             releaseUnstableProvider(unstableProvider);
1090             ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
1091                     fd.getParcelFileDescriptor(), stableProvider);
1092 
1093             // Success!  Don't release the provider when exiting, let
1094             // ParcelFileDescriptorInner do that when it is closed.
1095             stableProvider = null;
1096 
1097             return new AssetFileDescriptor(pfd, fd.getStartOffset(),
1098                     fd.getDeclaredLength());
1099 
1100         } catch (RemoteException e) {
1101             // Whatever, whatever, we'll go away.
1102             throw new FileNotFoundException(
1103                     "Failed opening content provider: " + uri);
1104         } catch (FileNotFoundException e) {
1105             throw e;
1106         } finally {
1107             if (cancellationSignal != null) {
1108                 cancellationSignal.setRemote(null);
1109             }
1110             if (stableProvider != null) {
1111                 releaseProvider(stableProvider);
1112             }
1113             if (unstableProvider != null) {
1114                 releaseUnstableProvider(unstableProvider);
1115             }
1116         }
1117     }
1118 
1119     /**
1120      * A resource identified by the {@link Resources} that contains it, and a resource id.
1121      *
1122      * @hide
1123      */
1124     public class OpenResourceIdResult {
1125         public Resources r;
1126         public int id;
1127     }
1128 
1129     /**
1130      * Resolves an android.resource URI to a {@link Resources} and a resource id.
1131      *
1132      * @hide
1133      */
getResourceId(Uri uri)1134     public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
1135         String authority = uri.getAuthority();
1136         Resources r;
1137         if (TextUtils.isEmpty(authority)) {
1138             throw new FileNotFoundException("No authority: " + uri);
1139         } else {
1140             try {
1141                 r = mContext.getPackageManager().getResourcesForApplication(authority);
1142             } catch (NameNotFoundException ex) {
1143                 throw new FileNotFoundException("No package found for authority: " + uri);
1144             }
1145         }
1146         List<String> path = uri.getPathSegments();
1147         if (path == null) {
1148             throw new FileNotFoundException("No path: " + uri);
1149         }
1150         int len = path.size();
1151         int id;
1152         if (len == 1) {
1153             try {
1154                 id = Integer.parseInt(path.get(0));
1155             } catch (NumberFormatException e) {
1156                 throw new FileNotFoundException("Single path segment is not a resource ID: " + uri);
1157             }
1158         } else if (len == 2) {
1159             id = r.getIdentifier(path.get(1), path.get(0), authority);
1160         } else {
1161             throw new FileNotFoundException("More than two path segments: " + uri);
1162         }
1163         if (id == 0) {
1164             throw new FileNotFoundException("No resource found for: " + uri);
1165         }
1166         OpenResourceIdResult res = new OpenResourceIdResult();
1167         res.r = r;
1168         res.id = id;
1169         return res;
1170     }
1171 
1172     /**
1173      * Inserts a row into a table at the given URL.
1174      *
1175      * If the content provider supports transactions the insertion will be atomic.
1176      *
1177      * @param url The URL of the table to insert into.
1178      * @param values The initial values for the newly inserted row. The key is the column name for
1179      *               the field. Passing an empty ContentValues will create an empty row.
1180      * @return the URL of the newly created row.
1181      */
insert(Uri url, ContentValues values)1182     public final Uri insert(Uri url, ContentValues values)
1183     {
1184         IContentProvider provider = acquireProvider(url);
1185         if (provider == null) {
1186             throw new IllegalArgumentException("Unknown URL " + url);
1187         }
1188         try {
1189             long startTime = SystemClock.uptimeMillis();
1190             Uri createdRow = provider.insert(mPackageName, url, values);
1191             long durationMillis = SystemClock.uptimeMillis() - startTime;
1192             maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
1193             return createdRow;
1194         } catch (RemoteException e) {
1195             // Arbitrary and not worth documenting, as Activity
1196             // Manager will kill this process shortly anyway.
1197             return null;
1198         } finally {
1199             releaseProvider(provider);
1200         }
1201     }
1202 
1203     /**
1204      * Applies each of the {@link ContentProviderOperation} objects and returns an array
1205      * of their results. Passes through OperationApplicationException, which may be thrown
1206      * by the call to {@link ContentProviderOperation#apply}.
1207      * If all the applications succeed then a {@link ContentProviderResult} array with the
1208      * same number of elements as the operations will be returned. It is implementation-specific
1209      * how many, if any, operations will have been successfully applied if a call to
1210      * apply results in a {@link OperationApplicationException}.
1211      * @param authority the authority of the ContentProvider to which this batch should be applied
1212      * @param operations the operations to apply
1213      * @return the results of the applications
1214      * @throws OperationApplicationException thrown if an application fails.
1215      * See {@link ContentProviderOperation#apply} for more information.
1216      * @throws RemoteException thrown if a RemoteException is encountered while attempting
1217      *   to communicate with a remote provider.
1218      */
applyBatch(String authority, ArrayList<ContentProviderOperation> operations)1219     public ContentProviderResult[] applyBatch(String authority,
1220             ArrayList<ContentProviderOperation> operations)
1221             throws RemoteException, OperationApplicationException {
1222         ContentProviderClient provider = acquireContentProviderClient(authority);
1223         if (provider == null) {
1224             throw new IllegalArgumentException("Unknown authority " + authority);
1225         }
1226         try {
1227             return provider.applyBatch(operations);
1228         } finally {
1229             provider.release();
1230         }
1231     }
1232 
1233     /**
1234      * Inserts multiple rows into a table at the given URL.
1235      *
1236      * This function make no guarantees about the atomicity of the insertions.
1237      *
1238      * @param url The URL of the table to insert into.
1239      * @param values The initial values for the newly inserted rows. The key is the column name for
1240      *               the field. Passing null will create an empty row.
1241      * @return the number of newly created rows.
1242      */
bulkInsert(Uri url, ContentValues[] values)1243     public final int bulkInsert(Uri url, ContentValues[] values)
1244     {
1245         IContentProvider provider = acquireProvider(url);
1246         if (provider == null) {
1247             throw new IllegalArgumentException("Unknown URL " + url);
1248         }
1249         try {
1250             long startTime = SystemClock.uptimeMillis();
1251             int rowsCreated = provider.bulkInsert(mPackageName, url, values);
1252             long durationMillis = SystemClock.uptimeMillis() - startTime;
1253             maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
1254             return rowsCreated;
1255         } catch (RemoteException e) {
1256             // Arbitrary and not worth documenting, as Activity
1257             // Manager will kill this process shortly anyway.
1258             return 0;
1259         } finally {
1260             releaseProvider(provider);
1261         }
1262     }
1263 
1264     /**
1265      * Deletes row(s) specified by a content URI.
1266      *
1267      * If the content provider supports transactions, the deletion will be atomic.
1268      *
1269      * @param url The URL of the row to delete.
1270      * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause
1271                     (excluding the WHERE itself).
1272      * @return The number of rows deleted.
1273      */
delete(Uri url, String where, String[] selectionArgs)1274     public final int delete(Uri url, String where, String[] selectionArgs)
1275     {
1276         IContentProvider provider = acquireProvider(url);
1277         if (provider == null) {
1278             throw new IllegalArgumentException("Unknown URL " + url);
1279         }
1280         try {
1281             long startTime = SystemClock.uptimeMillis();
1282             int rowsDeleted = provider.delete(mPackageName, url, where, selectionArgs);
1283             long durationMillis = SystemClock.uptimeMillis() - startTime;
1284             maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
1285             return rowsDeleted;
1286         } catch (RemoteException e) {
1287             // Arbitrary and not worth documenting, as Activity
1288             // Manager will kill this process shortly anyway.
1289             return -1;
1290         } finally {
1291             releaseProvider(provider);
1292         }
1293     }
1294 
1295     /**
1296      * Update row(s) in a content URI.
1297      *
1298      * If the content provider supports transactions the update will be atomic.
1299      *
1300      * @param uri The URI to modify.
1301      * @param values The new field values. The key is the column name for the field.
1302                      A null value will remove an existing field value.
1303      * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause
1304                     (excluding the WHERE itself).
1305      * @return the number of rows updated.
1306      * @throws NullPointerException if uri or values are null
1307      */
update(Uri uri, ContentValues values, String where, String[] selectionArgs)1308     public final int update(Uri uri, ContentValues values, String where,
1309             String[] selectionArgs) {
1310         IContentProvider provider = acquireProvider(uri);
1311         if (provider == null) {
1312             throw new IllegalArgumentException("Unknown URI " + uri);
1313         }
1314         try {
1315             long startTime = SystemClock.uptimeMillis();
1316             int rowsUpdated = provider.update(mPackageName, uri, values, where, selectionArgs);
1317             long durationMillis = SystemClock.uptimeMillis() - startTime;
1318             maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
1319             return rowsUpdated;
1320         } catch (RemoteException e) {
1321             // Arbitrary and not worth documenting, as Activity
1322             // Manager will kill this process shortly anyway.
1323             return -1;
1324         } finally {
1325             releaseProvider(provider);
1326         }
1327     }
1328 
1329     /**
1330      * Call a provider-defined method.  This can be used to implement
1331      * read or write interfaces which are cheaper than using a Cursor and/or
1332      * do not fit into the traditional table model.
1333      *
1334      * @param method provider-defined method name to call.  Opaque to
1335      *   framework, but must be non-null.
1336      * @param arg provider-defined String argument.  May be null.
1337      * @param extras provider-defined Bundle argument.  May be null.
1338      * @return a result Bundle, possibly null.  Will be null if the ContentProvider
1339      *   does not implement call.
1340      * @throws NullPointerException if uri or method is null
1341      * @throws IllegalArgumentException if uri is not known
1342      */
call(Uri uri, String method, String arg, Bundle extras)1343     public final Bundle call(Uri uri, String method, String arg, Bundle extras) {
1344         if (uri == null) {
1345             throw new NullPointerException("uri == null");
1346         }
1347         if (method == null) {
1348             throw new NullPointerException("method == null");
1349         }
1350         IContentProvider provider = acquireProvider(uri);
1351         if (provider == null) {
1352             throw new IllegalArgumentException("Unknown URI " + uri);
1353         }
1354         try {
1355             return provider.call(mPackageName, method, arg, extras);
1356         } catch (RemoteException e) {
1357             // Arbitrary and not worth documenting, as Activity
1358             // Manager will kill this process shortly anyway.
1359             return null;
1360         } finally {
1361             releaseProvider(provider);
1362         }
1363     }
1364 
1365     /**
1366      * Returns the content provider for the given content URI.
1367      *
1368      * @param uri The URI to a content provider
1369      * @return The ContentProvider for the given URI, or null if no content provider is found.
1370      * @hide
1371      */
acquireProvider(Uri uri)1372     public final IContentProvider acquireProvider(Uri uri) {
1373         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
1374             return null;
1375         }
1376         final String auth = uri.getAuthority();
1377         if (auth != null) {
1378             return acquireProvider(mContext, auth);
1379         }
1380         return null;
1381     }
1382 
1383     /**
1384      * Returns the content provider for the given content URI if the process
1385      * already has a reference on it.
1386      *
1387      * @param uri The URI to a content provider
1388      * @return The ContentProvider for the given URI, or null if no content provider is found.
1389      * @hide
1390      */
acquireExistingProvider(Uri uri)1391     public final IContentProvider acquireExistingProvider(Uri uri) {
1392         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
1393             return null;
1394         }
1395         final String auth = uri.getAuthority();
1396         if (auth != null) {
1397             return acquireExistingProvider(mContext, auth);
1398         }
1399         return null;
1400     }
1401 
1402     /**
1403      * @hide
1404      */
acquireProvider(String name)1405     public final IContentProvider acquireProvider(String name) {
1406         if (name == null) {
1407             return null;
1408         }
1409         return acquireProvider(mContext, name);
1410     }
1411 
1412     /**
1413      * Returns the content provider for the given content URI.
1414      *
1415      * @param uri The URI to a content provider
1416      * @return The ContentProvider for the given URI, or null if no content provider is found.
1417      * @hide
1418      */
acquireUnstableProvider(Uri uri)1419     public final IContentProvider acquireUnstableProvider(Uri uri) {
1420         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
1421             return null;
1422         }
1423         String auth = uri.getAuthority();
1424         if (auth != null) {
1425             return acquireUnstableProvider(mContext, uri.getAuthority());
1426         }
1427         return null;
1428     }
1429 
1430     /**
1431      * @hide
1432      */
acquireUnstableProvider(String name)1433     public final IContentProvider acquireUnstableProvider(String name) {
1434         if (name == null) {
1435             return null;
1436         }
1437         return acquireUnstableProvider(mContext, name);
1438     }
1439 
1440     /**
1441      * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1442      * that services the content at uri, starting the provider if necessary. Returns
1443      * null if there is no provider associated wih the uri. The caller must indicate that they are
1444      * done with the provider by calling {@link ContentProviderClient#release} which will allow
1445      * the system to release the provider it it determines that there is no other reason for
1446      * keeping it active.
1447      * @param uri specifies which provider should be acquired
1448      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1449      * that services the content at uri or null if there isn't one.
1450      */
acquireContentProviderClient(Uri uri)1451     public final ContentProviderClient acquireContentProviderClient(Uri uri) {
1452         IContentProvider provider = acquireProvider(uri);
1453         if (provider != null) {
1454             return new ContentProviderClient(this, provider, true);
1455         }
1456 
1457         return null;
1458     }
1459 
1460     /**
1461      * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1462      * with the authority of name, starting the provider if necessary. Returns
1463      * null if there is no provider associated wih the uri. The caller must indicate that they are
1464      * done with the provider by calling {@link ContentProviderClient#release} which will allow
1465      * the system to release the provider it it determines that there is no other reason for
1466      * keeping it active.
1467      * @param name specifies which provider should be acquired
1468      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1469      * with the authority of name or null if there isn't one.
1470      */
acquireContentProviderClient(String name)1471     public final ContentProviderClient acquireContentProviderClient(String name) {
1472         IContentProvider provider = acquireProvider(name);
1473         if (provider != null) {
1474             return new ContentProviderClient(this, provider, true);
1475         }
1476 
1477         return null;
1478     }
1479 
1480     /**
1481      * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do
1482      * not trust the stability of the target content provider.  This turns off
1483      * the mechanism in the platform clean up processes that are dependent on
1484      * a content provider if that content provider's process goes away.  Normally
1485      * you can safely assume that once you have acquired a provider, you can freely
1486      * use it as needed and it won't disappear, even if your process is in the
1487      * background.  If using this method, you need to take care to deal with any
1488      * failures when communicating with the provider, and be sure to close it
1489      * so that it can be re-opened later.  In particular, catching a
1490      * {@link android.os.DeadObjectException} from the calls there will let you
1491      * know that the content provider has gone away; at that point the current
1492      * ContentProviderClient object is invalid, and you should release it.  You
1493      * can acquire a new one if you would like to try to restart the provider
1494      * and perform new operations on it.
1495      */
acquireUnstableContentProviderClient(Uri uri)1496     public final ContentProviderClient acquireUnstableContentProviderClient(Uri uri) {
1497         IContentProvider provider = acquireUnstableProvider(uri);
1498         if (provider != null) {
1499             return new ContentProviderClient(this, provider, false);
1500         }
1501 
1502         return null;
1503     }
1504 
1505     /**
1506      * Like {@link #acquireContentProviderClient(String)}, but for use when you do
1507      * not trust the stability of the target content provider.  This turns off
1508      * the mechanism in the platform clean up processes that are dependent on
1509      * a content provider if that content provider's process goes away.  Normally
1510      * you can safely assume that once you have acquired a provider, you can freely
1511      * use it as needed and it won't disappear, even if your process is in the
1512      * background.  If using this method, you need to take care to deal with any
1513      * failures when communicating with the provider, and be sure to close it
1514      * so that it can be re-opened later.  In particular, catching a
1515      * {@link android.os.DeadObjectException} from the calls there will let you
1516      * know that the content provider has gone away; at that point the current
1517      * ContentProviderClient object is invalid, and you should release it.  You
1518      * can acquire a new one if you would like to try to restart the provider
1519      * and perform new operations on it.
1520      */
acquireUnstableContentProviderClient(String name)1521     public final ContentProviderClient acquireUnstableContentProviderClient(String name) {
1522         IContentProvider provider = acquireUnstableProvider(name);
1523         if (provider != null) {
1524             return new ContentProviderClient(this, provider, false);
1525         }
1526 
1527         return null;
1528     }
1529 
1530     /**
1531      * Register an observer class that gets callbacks when data identified by a
1532      * given content URI changes.
1533      *
1534      * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
1535      * for a whole class of content.
1536      * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code>
1537      * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI
1538      * specified by <em>uri</em> will cause notifications to be sent. If true, than any URI values
1539      * at or below the specified URI will also trigger a match.
1540      * @param observer The object that receives callbacks when changes occur.
1541      * @see #unregisterContentObserver
1542      */
registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)1543     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
1544             ContentObserver observer)
1545     {
1546         registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
1547     }
1548 
1549     /** @hide - designated user version */
registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer, int userHandle)1550     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
1551             ContentObserver observer, int userHandle)
1552     {
1553         try {
1554             getContentService().registerContentObserver(uri, notifyForDescendents,
1555                     observer.getContentObserver(), userHandle);
1556         } catch (RemoteException e) {
1557         }
1558     }
1559 
1560     /**
1561      * Unregisters a change observer.
1562      *
1563      * @param observer The previously registered observer that is no longer needed.
1564      * @see #registerContentObserver
1565      */
unregisterContentObserver(ContentObserver observer)1566     public final void unregisterContentObserver(ContentObserver observer) {
1567         try {
1568             IContentObserver contentObserver = observer.releaseContentObserver();
1569             if (contentObserver != null) {
1570                 getContentService().unregisterContentObserver(
1571                         contentObserver);
1572             }
1573         } catch (RemoteException e) {
1574         }
1575     }
1576 
1577     /**
1578      * Notify registered observers that a row was updated and attempt to sync changes
1579      * to the network.
1580      * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
1581      * By default, CursorAdapter objects will get this notification.
1582      *
1583      * @param uri The uri of the content that was changed.
1584      * @param observer The observer that originated the change, may be <code>null</null>.
1585      * The observer that originated the change will only receive the notification if it
1586      * has requested to receive self-change notifications by implementing
1587      * {@link ContentObserver#deliverSelfNotifications()} to return true.
1588      */
notifyChange(Uri uri, ContentObserver observer)1589     public void notifyChange(Uri uri, ContentObserver observer) {
1590         notifyChange(uri, observer, true /* sync to network */);
1591     }
1592 
1593     /**
1594      * Notify registered observers that a row was updated.
1595      * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
1596      * By default, CursorAdapter objects will get this notification.
1597      * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
1598      * adapter that's registered for the authority of the provided uri. No account will be
1599      * passed to the sync adapter, so all matching accounts will be synchronized.
1600      *
1601      * @param uri The uri of the content that was changed.
1602      * @param observer The observer that originated the change, may be <code>null</null>.
1603      * The observer that originated the change will only receive the notification if it
1604      * has requested to receive self-change notifications by implementing
1605      * {@link ContentObserver#deliverSelfNotifications()} to return true.
1606      * @param syncToNetwork If true, attempt to sync the change to the network.
1607      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
1608      */
notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork)1609     public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
1610         notifyChange(uri, observer, syncToNetwork, UserHandle.getCallingUserId());
1611     }
1612 
1613     /**
1614      * Notify registered observers within the designated user(s) that a row was updated.
1615      *
1616      * @hide
1617      */
notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork, int userHandle)1618     public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
1619             int userHandle) {
1620         try {
1621             getContentService().notifyChange(
1622                     uri, observer == null ? null : observer.getContentObserver(),
1623                     observer != null && observer.deliverSelfNotifications(), syncToNetwork,
1624                     userHandle);
1625         } catch (RemoteException e) {
1626         }
1627     }
1628 
1629     /**
1630      * Take a persistable URI permission grant that has been offered. Once
1631      * taken, the permission grant will be remembered across device reboots.
1632      * Only URI permissions granted with
1633      * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} can be persisted. If
1634      * the grant has already been persisted, taking it again will touch
1635      * {@link UriPermission#getPersistedTime()}.
1636      *
1637      * @see #getPersistedUriPermissions()
1638      */
takePersistableUriPermission(Uri uri, int modeFlags)1639     public void takePersistableUriPermission(Uri uri, int modeFlags) {
1640         try {
1641             ActivityManagerNative.getDefault().takePersistableUriPermission(uri, modeFlags);
1642         } catch (RemoteException e) {
1643         }
1644     }
1645 
1646     /**
1647      * Relinquish a persisted URI permission grant. The URI must have been
1648      * previously made persistent with
1649      * {@link #takePersistableUriPermission(Uri, int)}. Any non-persistent
1650      * grants to the calling package will remain intact.
1651      *
1652      * @see #getPersistedUriPermissions()
1653      */
releasePersistableUriPermission(Uri uri, int modeFlags)1654     public void releasePersistableUriPermission(Uri uri, int modeFlags) {
1655         try {
1656             ActivityManagerNative.getDefault().releasePersistableUriPermission(uri, modeFlags);
1657         } catch (RemoteException e) {
1658         }
1659     }
1660 
1661     /**
1662      * Return list of all URI permission grants that have been persisted by the
1663      * calling app. That is, the returned permissions have been granted
1664      * <em>to</em> the calling app. Only persistable grants taken with
1665      * {@link #takePersistableUriPermission(Uri, int)} are returned.
1666      *
1667      * @see #takePersistableUriPermission(Uri, int)
1668      * @see #releasePersistableUriPermission(Uri, int)
1669      */
getPersistedUriPermissions()1670     public List<UriPermission> getPersistedUriPermissions() {
1671         try {
1672             return ActivityManagerNative.getDefault()
1673                     .getPersistedUriPermissions(mPackageName, true).getList();
1674         } catch (RemoteException e) {
1675             throw new RuntimeException("Activity manager has died", e);
1676         }
1677     }
1678 
1679     /**
1680      * Return list of all persisted URI permission grants that are hosted by the
1681      * calling app. That is, the returned permissions have been granted
1682      * <em>from</em> the calling app. Only grants taken with
1683      * {@link #takePersistableUriPermission(Uri, int)} are returned.
1684      */
getOutgoingPersistedUriPermissions()1685     public List<UriPermission> getOutgoingPersistedUriPermissions() {
1686         try {
1687             return ActivityManagerNative.getDefault()
1688                     .getPersistedUriPermissions(mPackageName, false).getList();
1689         } catch (RemoteException e) {
1690             throw new RuntimeException("Activity manager has died", e);
1691         }
1692     }
1693 
1694     /**
1695      * Start an asynchronous sync operation. If you want to monitor the progress
1696      * of the sync you may register a SyncObserver. Only values of the following
1697      * types may be used in the extras bundle:
1698      * <ul>
1699      * <li>Integer</li>
1700      * <li>Long</li>
1701      * <li>Boolean</li>
1702      * <li>Float</li>
1703      * <li>Double</li>
1704      * <li>String</li>
1705      * <li>Account</li>
1706      * <li>null</li>
1707      * </ul>
1708      *
1709      * @param uri the uri of the provider to sync or null to sync all providers.
1710      * @param extras any extras to pass to the SyncAdapter.
1711      * @deprecated instead use
1712      * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
1713      */
1714     @Deprecated
startSync(Uri uri, Bundle extras)1715     public void startSync(Uri uri, Bundle extras) {
1716         Account account = null;
1717         if (extras != null) {
1718             String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT);
1719             if (!TextUtils.isEmpty(accountName)) {
1720                 account = new Account(accountName, "com.google");
1721             }
1722             extras.remove(SYNC_EXTRAS_ACCOUNT);
1723         }
1724         requestSync(account, uri != null ? uri.getAuthority() : null, extras);
1725     }
1726 
1727     /**
1728      * Start an asynchronous sync operation. If you want to monitor the progress
1729      * of the sync you may register a SyncObserver. Only values of the following
1730      * types may be used in the extras bundle:
1731      * <ul>
1732      * <li>Integer</li>
1733      * <li>Long</li>
1734      * <li>Boolean</li>
1735      * <li>Float</li>
1736      * <li>Double</li>
1737      * <li>String</li>
1738      * <li>Account</li>
1739      * <li>null</li>
1740      * </ul>
1741      *
1742      * @param account which account should be synced
1743      * @param authority which authority should be synced
1744      * @param extras any extras to pass to the SyncAdapter.
1745      */
requestSync(Account account, String authority, Bundle extras)1746     public static void requestSync(Account account, String authority, Bundle extras) {
1747         if (extras == null) {
1748             throw new IllegalArgumentException("Must specify extras.");
1749         }
1750         SyncRequest request =
1751             new SyncRequest.Builder()
1752                 .setSyncAdapter(account, authority)
1753                 .setExtras(extras)
1754                 .syncOnce()
1755                 .build();
1756         requestSync(request);
1757     }
1758 
1759     /**
1760      * Register a sync with the SyncManager. These requests are built using the
1761      * {@link SyncRequest.Builder}.
1762      *
1763      * @param request The immutable SyncRequest object containing the sync parameters. Use
1764      * {@link SyncRequest.Builder} to construct these.
1765      */
requestSync(SyncRequest request)1766     public static void requestSync(SyncRequest request) {
1767         try {
1768             getContentService().sync(request);
1769         } catch(RemoteException e) {
1770             // Shouldn't happen.
1771         }
1772     }
1773 
1774     /**
1775      * Check that only values of the following types are in the Bundle:
1776      * <ul>
1777      * <li>Integer</li>
1778      * <li>Long</li>
1779      * <li>Boolean</li>
1780      * <li>Float</li>
1781      * <li>Double</li>
1782      * <li>String</li>
1783      * <li>Account</li>
1784      * <li>null</li>
1785      * </ul>
1786      * @param extras the Bundle to check
1787      */
validateSyncExtrasBundle(Bundle extras)1788     public static void validateSyncExtrasBundle(Bundle extras) {
1789         try {
1790             for (String key : extras.keySet()) {
1791                 Object value = extras.get(key);
1792                 if (value == null) continue;
1793                 if (value instanceof Long) continue;
1794                 if (value instanceof Integer) continue;
1795                 if (value instanceof Boolean) continue;
1796                 if (value instanceof Float) continue;
1797                 if (value instanceof Double) continue;
1798                 if (value instanceof String) continue;
1799                 if (value instanceof Account) continue;
1800                 throw new IllegalArgumentException("unexpected value type: "
1801                         + value.getClass().getName());
1802             }
1803         } catch (IllegalArgumentException e) {
1804             throw e;
1805         } catch (RuntimeException exc) {
1806             throw new IllegalArgumentException("error unparceling Bundle", exc);
1807         }
1808     }
1809 
1810     /**
1811      * Cancel any active or pending syncs that match the Uri. If the uri is null then
1812      * all syncs will be canceled.
1813      *
1814      * @param uri the uri of the provider to sync or null to sync all providers.
1815      * @deprecated instead use {@link #cancelSync(android.accounts.Account, String)}
1816      */
1817     @Deprecated
cancelSync(Uri uri)1818     public void cancelSync(Uri uri) {
1819         cancelSync(null /* all accounts */, uri != null ? uri.getAuthority() : null);
1820     }
1821 
1822     /**
1823      * Cancel any active or pending syncs that match account and authority. The account and
1824      * authority can each independently be set to null, which means that syncs with any account
1825      * or authority, respectively, will match.
1826      *
1827      * @param account filters the syncs that match by this account
1828      * @param authority filters the syncs that match by this authority
1829      */
cancelSync(Account account, String authority)1830     public static void cancelSync(Account account, String authority) {
1831         try {
1832             getContentService().cancelSync(account, authority);
1833         } catch (RemoteException e) {
1834         }
1835     }
1836 
1837     /**
1838      * Get information about the SyncAdapters that are known to the system.
1839      * @return an array of SyncAdapters that have registered with the system
1840      */
getSyncAdapterTypes()1841     public static SyncAdapterType[] getSyncAdapterTypes() {
1842         try {
1843             return getContentService().getSyncAdapterTypes();
1844         } catch (RemoteException e) {
1845             throw new RuntimeException("the ContentService should always be reachable", e);
1846         }
1847     }
1848 
1849     /**
1850      * Check if the provider should be synced when a network tickle is received
1851      * <p>This method requires the caller to hold the permission
1852      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
1853      *
1854      * @param account the account whose setting we are querying
1855      * @param authority the provider whose setting we are querying
1856      * @return true if the provider should be synced when a network tickle is received
1857      */
getSyncAutomatically(Account account, String authority)1858     public static boolean getSyncAutomatically(Account account, String authority) {
1859         try {
1860             return getContentService().getSyncAutomatically(account, authority);
1861         } catch (RemoteException e) {
1862             throw new RuntimeException("the ContentService should always be reachable", e);
1863         }
1864     }
1865 
1866     /**
1867      * Set whether or not the provider is synced when it receives a network tickle.
1868      * <p>This method requires the caller to hold the permission
1869      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
1870      *
1871      * @param account the account whose setting we are querying
1872      * @param authority the provider whose behavior is being controlled
1873      * @param sync true if the provider should be synced when tickles are received for it
1874      */
setSyncAutomatically(Account account, String authority, boolean sync)1875     public static void setSyncAutomatically(Account account, String authority, boolean sync) {
1876         try {
1877             getContentService().setSyncAutomatically(account, authority, sync);
1878         } catch (RemoteException e) {
1879             // exception ignored; if this is thrown then it means the runtime is in the midst of
1880             // being restarted
1881         }
1882     }
1883 
1884     /**
1885      * Specifies that a sync should be requested with the specified the account, authority,
1886      * and extras at the given frequency. If there is already another periodic sync scheduled
1887      * with the account, authority and extras then a new periodic sync won't be added, instead
1888      * the frequency of the previous one will be updated.
1889      * <p>
1890      * These periodic syncs honor the "syncAutomatically" and "masterSyncAutomatically" settings.
1891      * Although these sync are scheduled at the specified frequency, it may take longer for it to
1892      * actually be started if other syncs are ahead of it in the sync operation queue. This means
1893      * that the actual start time may drift.
1894      * <p>
1895      * Periodic syncs are not allowed to have any of {@link #SYNC_EXTRAS_DO_NOT_RETRY},
1896      * {@link #SYNC_EXTRAS_IGNORE_BACKOFF}, {@link #SYNC_EXTRAS_IGNORE_SETTINGS},
1897      * {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE},
1898      * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL} set to true.
1899      * If any are supplied then an {@link IllegalArgumentException} will be thrown.
1900      * <p>As of API level 19 this function introduces a default flexibility of ~4% (up to a maximum
1901      * of one hour in the day) into the requested period. Use
1902      * {@link SyncRequest.Builder#syncPeriodic(long, long)} to set this flexibility manually.
1903      *
1904      * <p>This method requires the caller to hold the permission
1905      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
1906      *
1907      * @param account the account to specify in the sync
1908      * @param authority the provider to specify in the sync request
1909      * @param extras extra parameters to go along with the sync request
1910      * @param pollFrequency how frequently the sync should be performed, in seconds.
1911      * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters
1912      * are null.
1913      */
addPeriodicSync(Account account, String authority, Bundle extras, long pollFrequency)1914     public static void addPeriodicSync(Account account, String authority, Bundle extras,
1915             long pollFrequency) {
1916         validateSyncExtrasBundle(extras);
1917         if (extras.getBoolean(SYNC_EXTRAS_MANUAL, false)
1918                 || extras.getBoolean(SYNC_EXTRAS_DO_NOT_RETRY, false)
1919                 || extras.getBoolean(SYNC_EXTRAS_IGNORE_BACKOFF, false)
1920                 || extras.getBoolean(SYNC_EXTRAS_IGNORE_SETTINGS, false)
1921                 || extras.getBoolean(SYNC_EXTRAS_INITIALIZE, false)
1922                 || extras.getBoolean(SYNC_EXTRAS_FORCE, false)
1923                 || extras.getBoolean(SYNC_EXTRAS_EXPEDITED, false)) {
1924             throw new IllegalArgumentException("illegal extras were set");
1925         }
1926         try {
1927              getContentService().addPeriodicSync(account, authority, extras, pollFrequency);
1928         } catch (RemoteException e) {
1929             // exception ignored; if this is thrown then it means the runtime is in the midst of
1930             // being restarted
1931         }
1932     }
1933 
1934     /**
1935      * Remove a periodic sync. Has no affect if account, authority and extras don't match
1936      * an existing periodic sync.
1937      * <p>This method requires the caller to hold the permission
1938      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
1939      *
1940      * @param account the account of the periodic sync to remove
1941      * @param authority the provider of the periodic sync to remove
1942      * @param extras the extras of the periodic sync to remove
1943      */
removePeriodicSync(Account account, String authority, Bundle extras)1944     public static void removePeriodicSync(Account account, String authority, Bundle extras) {
1945         validateSyncExtrasBundle(extras);
1946         try {
1947             getContentService().removePeriodicSync(account, authority, extras);
1948         } catch (RemoteException e) {
1949             throw new RuntimeException("the ContentService should always be reachable", e);
1950         }
1951     }
1952 
1953     /**
1954      * Get the list of information about the periodic syncs for the given account and authority.
1955      * <p>This method requires the caller to hold the permission
1956      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
1957      *
1958      * @param account the account whose periodic syncs we are querying
1959      * @param authority the provider whose periodic syncs we are querying
1960      * @return a list of PeriodicSync objects. This list may be empty but will never be null.
1961      */
getPeriodicSyncs(Account account, String authority)1962     public static List<PeriodicSync> getPeriodicSyncs(Account account, String authority) {
1963         try {
1964             return getContentService().getPeriodicSyncs(account, authority);
1965         } catch (RemoteException e) {
1966             throw new RuntimeException("the ContentService should always be reachable", e);
1967         }
1968     }
1969 
1970     /**
1971      * Check if this account/provider is syncable.
1972      * <p>This method requires the caller to hold the permission
1973      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
1974      * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
1975      */
getIsSyncable(Account account, String authority)1976     public static int getIsSyncable(Account account, String authority) {
1977         try {
1978             return getContentService().getIsSyncable(account, authority);
1979         } catch (RemoteException e) {
1980             throw new RuntimeException("the ContentService should always be reachable", e);
1981         }
1982     }
1983 
1984     /**
1985      * Set whether this account/provider is syncable.
1986      * <p>This method requires the caller to hold the permission
1987      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
1988      * @param syncable >0 denotes syncable, 0 means not syncable, <0 means unknown
1989      */
setIsSyncable(Account account, String authority, int syncable)1990     public static void setIsSyncable(Account account, String authority, int syncable) {
1991         try {
1992             getContentService().setIsSyncable(account, authority, syncable);
1993         } catch (RemoteException e) {
1994             // exception ignored; if this is thrown then it means the runtime is in the midst of
1995             // being restarted
1996         }
1997     }
1998 
1999     /**
2000      * Gets the master auto-sync setting that applies to all the providers and accounts.
2001      * If this is false then the per-provider auto-sync setting is ignored.
2002      * <p>This method requires the caller to hold the permission
2003      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
2004      *
2005      * @return the master auto-sync setting that applies to all the providers and accounts
2006      */
getMasterSyncAutomatically()2007     public static boolean getMasterSyncAutomatically() {
2008         try {
2009             return getContentService().getMasterSyncAutomatically();
2010         } catch (RemoteException e) {
2011             throw new RuntimeException("the ContentService should always be reachable", e);
2012         }
2013     }
2014 
2015     /**
2016      * Sets the master auto-sync setting that applies to all the providers and accounts.
2017      * If this is false then the per-provider auto-sync setting is ignored.
2018      * <p>This method requires the caller to hold the permission
2019      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
2020      *
2021      * @param sync the master auto-sync setting that applies to all the providers and accounts
2022      */
setMasterSyncAutomatically(boolean sync)2023     public static void setMasterSyncAutomatically(boolean sync) {
2024         try {
2025             getContentService().setMasterSyncAutomatically(sync);
2026         } catch (RemoteException e) {
2027             // exception ignored; if this is thrown then it means the runtime is in the midst of
2028             // being restarted
2029         }
2030     }
2031 
2032     /**
2033      * Returns true if there is currently a sync operation for the given
2034      * account or authority in the pending list, or actively being processed.
2035      * <p>This method requires the caller to hold the permission
2036      * {@link android.Manifest.permission#READ_SYNC_STATS}.
2037      * @param account the account whose setting we are querying
2038      * @param authority the provider whose behavior is being queried
2039      * @return true if a sync is active for the given account or authority.
2040      */
isSyncActive(Account account, String authority)2041     public static boolean isSyncActive(Account account, String authority) {
2042         try {
2043             return getContentService().isSyncActive(account, authority);
2044         } catch (RemoteException e) {
2045             throw new RuntimeException("the ContentService should always be reachable", e);
2046         }
2047     }
2048 
2049     /**
2050      * If a sync is active returns the information about it, otherwise returns null.
2051      * <p>
2052      * This method requires the caller to hold the permission
2053      * {@link android.Manifest.permission#READ_SYNC_STATS}.
2054      * <p>
2055      * @return the SyncInfo for the currently active sync or null if one is not active.
2056      * @deprecated
2057      * Since multiple concurrent syncs are now supported you should use
2058      * {@link #getCurrentSyncs()} to get the accurate list of current syncs.
2059      * This method returns the first item from the list of current syncs
2060      * or null if there are none.
2061      */
2062     @Deprecated
getCurrentSync()2063     public static SyncInfo getCurrentSync() {
2064         try {
2065             final List<SyncInfo> syncs = getContentService().getCurrentSyncs();
2066             if (syncs.isEmpty()) {
2067                 return null;
2068             }
2069             return syncs.get(0);
2070         } catch (RemoteException e) {
2071             throw new RuntimeException("the ContentService should always be reachable", e);
2072         }
2073     }
2074 
2075     /**
2076      * Returns a list with information about all the active syncs. This list will be empty
2077      * if there are no active syncs.
2078      * <p>
2079      * This method requires the caller to hold the permission
2080      * {@link android.Manifest.permission#READ_SYNC_STATS}.
2081      * <p>
2082      * @return a List of SyncInfo objects for the currently active syncs.
2083      */
getCurrentSyncs()2084     public static List<SyncInfo> getCurrentSyncs() {
2085         try {
2086             return getContentService().getCurrentSyncs();
2087         } catch (RemoteException e) {
2088             throw new RuntimeException("the ContentService should always be reachable", e);
2089         }
2090     }
2091 
2092     /**
2093      * Returns the status that matches the authority.
2094      * @param account the account whose setting we are querying
2095      * @param authority the provider whose behavior is being queried
2096      * @return the SyncStatusInfo for the authority, or null if none exists
2097      * @hide
2098      */
getSyncStatus(Account account, String authority)2099     public static SyncStatusInfo getSyncStatus(Account account, String authority) {
2100         try {
2101             return getContentService().getSyncStatus(account, authority);
2102         } catch (RemoteException e) {
2103             throw new RuntimeException("the ContentService should always be reachable", e);
2104         }
2105     }
2106 
2107     /**
2108      * Return true if the pending status is true of any matching authorities.
2109      * <p>This method requires the caller to hold the permission
2110      * {@link android.Manifest.permission#READ_SYNC_STATS}.
2111      * @param account the account whose setting we are querying
2112      * @param authority the provider whose behavior is being queried
2113      * @return true if there is a pending sync with the matching account and authority
2114      */
isSyncPending(Account account, String authority)2115     public static boolean isSyncPending(Account account, String authority) {
2116         try {
2117             return getContentService().isSyncPending(account, authority);
2118         } catch (RemoteException e) {
2119             throw new RuntimeException("the ContentService should always be reachable", e);
2120         }
2121     }
2122 
2123     /**
2124      * Request notifications when the different aspects of the SyncManager change. The
2125      * different items that can be requested are:
2126      * <ul>
2127      * <li> {@link #SYNC_OBSERVER_TYPE_PENDING}
2128      * <li> {@link #SYNC_OBSERVER_TYPE_ACTIVE}
2129      * <li> {@link #SYNC_OBSERVER_TYPE_SETTINGS}
2130      * </ul>
2131      * The caller can set one or more of the status types in the mask for any
2132      * given listener registration.
2133      * @param mask the status change types that will cause the callback to be invoked
2134      * @param callback observer to be invoked when the status changes
2135      * @return a handle that can be used to remove the listener at a later time
2136      */
addStatusChangeListener(int mask, final SyncStatusObserver callback)2137     public static Object addStatusChangeListener(int mask, final SyncStatusObserver callback) {
2138         if (callback == null) {
2139             throw new IllegalArgumentException("you passed in a null callback");
2140         }
2141         try {
2142             ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
2143                 public void onStatusChanged(int which) throws RemoteException {
2144                     callback.onStatusChanged(which);
2145                 }
2146             };
2147             getContentService().addStatusChangeListener(mask, observer);
2148             return observer;
2149         } catch (RemoteException e) {
2150             throw new RuntimeException("the ContentService should always be reachable", e);
2151         }
2152     }
2153 
2154     /**
2155      * Remove a previously registered status change listener.
2156      * @param handle the handle that was returned by {@link #addStatusChangeListener}
2157      */
removeStatusChangeListener(Object handle)2158     public static void removeStatusChangeListener(Object handle) {
2159         if (handle == null) {
2160             throw new IllegalArgumentException("you passed in a null handle");
2161         }
2162         try {
2163             getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle);
2164         } catch (RemoteException e) {
2165             // exception ignored; if this is thrown then it means the runtime is in the midst of
2166             // being restarted
2167         }
2168     }
2169 
2170     /**
2171      * Returns sampling percentage for a given duration.
2172      *
2173      * Always returns at least 1%.
2174      */
samplePercentForDuration(long durationMillis)2175     private int samplePercentForDuration(long durationMillis) {
2176         if (durationMillis >= SLOW_THRESHOLD_MILLIS) {
2177             return 100;
2178         }
2179         return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
2180     }
2181 
maybeLogQueryToEventLog(long durationMillis, Uri uri, String[] projection, String selection, String sortOrder)2182     private void maybeLogQueryToEventLog(long durationMillis,
2183                                          Uri uri, String[] projection,
2184                                          String selection, String sortOrder) {
2185         if (!ENABLE_CONTENT_SAMPLE) return;
2186         int samplePercent = samplePercentForDuration(durationMillis);
2187         if (samplePercent < 100) {
2188             synchronized (mRandom) {
2189                 if (mRandom.nextInt(100) >= samplePercent) {
2190                     return;
2191                 }
2192             }
2193         }
2194 
2195         StringBuilder projectionBuffer = new StringBuilder(100);
2196         if (projection != null) {
2197             for (int i = 0; i < projection.length; ++i) {
2198                 // Note: not using a comma delimiter here, as the
2199                 // multiple arguments to EventLog.writeEvent later
2200                 // stringify with a comma delimiter, which would make
2201                 // parsing uglier later.
2202                 if (i != 0) projectionBuffer.append('/');
2203                 projectionBuffer.append(projection[i]);
2204             }
2205         }
2206 
2207         // ActivityThread.currentPackageName() only returns non-null if the
2208         // current thread is an application main thread.  This parameter tells
2209         // us whether an event loop is blocked, and if so, which app it is.
2210         String blockingPackage = AppGlobals.getInitialPackage();
2211 
2212         EventLog.writeEvent(
2213             EventLogTags.CONTENT_QUERY_SAMPLE,
2214             uri.toString(),
2215             projectionBuffer.toString(),
2216             selection != null ? selection : "",
2217             sortOrder != null ? sortOrder : "",
2218             durationMillis,
2219             blockingPackage != null ? blockingPackage : "",
2220             samplePercent);
2221     }
2222 
maybeLogUpdateToEventLog( long durationMillis, Uri uri, String operation, String selection)2223     private void maybeLogUpdateToEventLog(
2224         long durationMillis, Uri uri, String operation, String selection) {
2225         if (!ENABLE_CONTENT_SAMPLE) return;
2226         int samplePercent = samplePercentForDuration(durationMillis);
2227         if (samplePercent < 100) {
2228             synchronized (mRandom) {
2229                 if (mRandom.nextInt(100) >= samplePercent) {
2230                     return;
2231                 }
2232             }
2233         }
2234         String blockingPackage = AppGlobals.getInitialPackage();
2235         EventLog.writeEvent(
2236             EventLogTags.CONTENT_UPDATE_SAMPLE,
2237             uri.toString(),
2238             operation,
2239             selection != null ? selection : "",
2240             durationMillis,
2241             blockingPackage != null ? blockingPackage : "",
2242             samplePercent);
2243     }
2244 
2245     private final class CursorWrapperInner extends CrossProcessCursorWrapper {
2246         private final IContentProvider mContentProvider;
2247         public static final String TAG="CursorWrapperInner";
2248 
2249         private final CloseGuard mCloseGuard = CloseGuard.get();
2250         private boolean mProviderReleased;
2251 
CursorWrapperInner(Cursor cursor, IContentProvider icp)2252         CursorWrapperInner(Cursor cursor, IContentProvider icp) {
2253             super(cursor);
2254             mContentProvider = icp;
2255             mCloseGuard.open("close");
2256         }
2257 
2258         @Override
close()2259         public void close() {
2260             super.close();
2261             ContentResolver.this.releaseProvider(mContentProvider);
2262             mProviderReleased = true;
2263 
2264             if (mCloseGuard != null) {
2265                 mCloseGuard.close();
2266             }
2267         }
2268 
2269         @Override
finalize()2270         protected void finalize() throws Throwable {
2271             try {
2272                 if (mCloseGuard != null) {
2273                     mCloseGuard.warnIfOpen();
2274                 }
2275 
2276                 if (!mProviderReleased && mContentProvider != null) {
2277                     // Even though we are using CloseGuard, log this anyway so that
2278                     // application developers always see the message in the log.
2279                     Log.w(TAG, "Cursor finalized without prior close()");
2280                     ContentResolver.this.releaseProvider(mContentProvider);
2281                 }
2282             } finally {
2283                 super.finalize();
2284             }
2285         }
2286     }
2287 
2288     private final class ParcelFileDescriptorInner extends ParcelFileDescriptor {
2289         private final IContentProvider mContentProvider;
2290         private boolean mProviderReleased;
2291 
ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp)2292         ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) {
2293             super(pfd);
2294             mContentProvider = icp;
2295         }
2296 
2297         @Override
releaseResources()2298         public void releaseResources() {
2299             if (!mProviderReleased) {
2300                 ContentResolver.this.releaseProvider(mContentProvider);
2301                 mProviderReleased = true;
2302             }
2303         }
2304     }
2305 
2306     /** @hide */
2307     public static final String CONTENT_SERVICE_NAME = "content";
2308 
2309     /** @hide */
getContentService()2310     public static IContentService getContentService() {
2311         if (sContentService != null) {
2312             return sContentService;
2313         }
2314         IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME);
2315         if (false) Log.v("ContentService", "default service binder = " + b);
2316         sContentService = IContentService.Stub.asInterface(b);
2317         if (false) Log.v("ContentService", "default service = " + sContentService);
2318         return sContentService;
2319     }
2320 
2321     /** @hide */
getPackageName()2322     public String getPackageName() {
2323         return mPackageName;
2324     }
2325 
2326     private static IContentService sContentService;
2327     private final Context mContext;
2328     final String mPackageName;
2329     private static final String TAG = "ContentResolver";
2330 }
2331