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 static android.provider.DocumentsContract.EXTRA_ORIENTATION;
20 
21 import android.accounts.Account;
22 import android.annotation.IntDef;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.RequiresPermission;
26 import android.annotation.SuppressLint;
27 import android.annotation.SystemApi;
28 import android.annotation.TestApi;
29 import android.annotation.UserIdInt;
30 import android.app.ActivityManager;
31 import android.app.ActivityThread;
32 import android.app.AppGlobals;
33 import android.app.UriGrantsManager;
34 import android.compat.annotation.UnsupportedAppUsage;
35 import android.content.pm.PackageManager;
36 import android.content.pm.PackageManager.NameNotFoundException;
37 import android.content.res.AssetFileDescriptor;
38 import android.content.res.Resources;
39 import android.database.ContentObserver;
40 import android.database.CrossProcessCursorWrapper;
41 import android.database.Cursor;
42 import android.database.IContentObserver;
43 import android.graphics.Bitmap;
44 import android.graphics.ImageDecoder;
45 import android.graphics.ImageDecoder.ImageInfo;
46 import android.graphics.ImageDecoder.Source;
47 import android.graphics.Matrix;
48 import android.graphics.Point;
49 import android.graphics.drawable.Drawable;
50 import android.graphics.drawable.Icon;
51 import android.net.Uri;
52 import android.os.Bundle;
53 import android.os.CancellationSignal;
54 import android.os.DeadObjectException;
55 import android.os.IBinder;
56 import android.os.ICancellationSignal;
57 import android.os.OperationCanceledException;
58 import android.os.ParcelFileDescriptor;
59 import android.os.ParcelableException;
60 import android.os.RemoteCallback;
61 import android.os.RemoteException;
62 import android.os.ServiceManager;
63 import android.os.SystemClock;
64 import android.os.UserHandle;
65 import android.os.storage.StorageManager;
66 import android.system.Int32Ref;
67 import android.text.TextUtils;
68 import android.util.EventLog;
69 import android.util.Log;
70 import android.util.Size;
71 import android.util.SparseArray;
72 
73 import com.android.internal.annotations.GuardedBy;
74 import com.android.internal.util.MimeIconUtils;
75 
76 import dalvik.system.CloseGuard;
77 
78 import java.io.File;
79 import java.io.FileInputStream;
80 import java.io.FileNotFoundException;
81 import java.io.IOException;
82 import java.io.InputStream;
83 import java.io.OutputStream;
84 import java.lang.annotation.Retention;
85 import java.lang.annotation.RetentionPolicy;
86 import java.util.ArrayList;
87 import java.util.Collection;
88 import java.util.List;
89 import java.util.Objects;
90 import java.util.Random;
91 import java.util.concurrent.atomic.AtomicBoolean;
92 
93 /**
94  * This class provides applications access to the content model.
95  *
96  * <div class="special reference">
97  * <h3>Developer Guides</h3>
98  * <p>For more information about using a ContentResolver with content providers, read the
99  * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
100  * developer guide.</p>
101  * </div>
102  */
103 public abstract class ContentResolver implements ContentInterface {
104     /**
105      * Enables logic that supports deprecation of {@code _data} columns,
106      * typically by replacing values with fake paths that the OS then offers to
107      * redirect to {@link #openFileDescriptor(Uri, String)}, which developers
108      * should be using directly.
109      *
110      * @hide
111      */
112     public static final boolean DEPRECATE_DATA_COLUMNS = StorageManager.hasIsolatedStorage();
113 
114     /**
115      * Special filesystem path prefix which indicates that a path should be
116      * treated as a {@code content://} {@link Uri} when
117      * {@link #DEPRECATE_DATA_COLUMNS} is enabled.
118      * <p>
119      * The remainder of the path after this prefix is a
120      * {@link Uri#getSchemeSpecificPart()} value, which includes authority, path
121      * segments, and query parameters.
122      *
123      * @hide
124      */
125     public static final String DEPRECATE_DATA_PREFIX = "/mnt/content/";
126 
127     /**
128      * @deprecated instead use
129      * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
130      */
131     @Deprecated
132     public static final String SYNC_EXTRAS_ACCOUNT = "account";
133 
134     /**
135      * If this extra is set to true, the sync request will be scheduled
136      * at the front of the sync request queue and without any delay
137      */
138     public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
139 
140     /**
141      * If this extra is set to true, the sync request will be scheduled
142      * only when the device is plugged in. This is equivalent to calling
143      * setRequiresCharging(true) on {@link SyncRequest}.
144      */
145     public static final String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
146 
147     /**
148      * @deprecated instead use
149      * {@link #SYNC_EXTRAS_MANUAL}
150      */
151     @Deprecated
152     public static final String SYNC_EXTRAS_FORCE = "force";
153 
154     /**
155      * If this extra is set to true then the sync settings (like getSyncAutomatically())
156      * are ignored by the sync scheduler.
157      */
158     public static final String SYNC_EXTRAS_IGNORE_SETTINGS = "ignore_settings";
159 
160     /**
161      * If this extra is set to true then any backoffs for the initial attempt (e.g. due to retries)
162      * are ignored by the sync scheduler. If this request fails and gets rescheduled then the
163      * retries will still honor the backoff.
164      */
165     public static final String SYNC_EXTRAS_IGNORE_BACKOFF = "ignore_backoff";
166 
167     /**
168      * If this extra is set to true then the request will not be retried if it fails.
169      */
170     public static final String SYNC_EXTRAS_DO_NOT_RETRY = "do_not_retry";
171 
172     /**
173      * Setting this extra is the equivalent of setting both {@link #SYNC_EXTRAS_IGNORE_SETTINGS}
174      * and {@link #SYNC_EXTRAS_IGNORE_BACKOFF}
175      */
176     public static final String SYNC_EXTRAS_MANUAL = "force";
177 
178     /**
179      * Indicates that this sync is intended to only upload local changes to the server.
180      * For example, this will be set to true if the sync is initiated by a call to
181      * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}
182      */
183     public static final String SYNC_EXTRAS_UPLOAD = "upload";
184 
185     /**
186      * Indicates that the sync adapter should proceed with the delete operations,
187      * even if it determines that there are too many.
188      * See {@link SyncResult#tooManyDeletions}
189      */
190     public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
191 
192     /**
193      * Indicates that the sync adapter should not proceed with the delete operations,
194      * if it determines that there are too many.
195      * See {@link SyncResult#tooManyDeletions}
196      */
197     public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
198 
199     /* Extensions to API. TODO: Not clear if we will keep these as public flags. */
200     /** {@hide} User-specified flag for expected upload size. */
201     public static final String SYNC_EXTRAS_EXPECTED_UPLOAD = "expected_upload";
202 
203     /** {@hide} User-specified flag for expected download size. */
204     public static final String SYNC_EXTRAS_EXPECTED_DOWNLOAD = "expected_download";
205 
206     /** {@hide} Priority of this sync with respect to other syncs scheduled for this application. */
207     public static final String SYNC_EXTRAS_PRIORITY = "sync_priority";
208 
209     /** {@hide} Flag to allow sync to occur on metered network. */
210     public static final String SYNC_EXTRAS_DISALLOW_METERED = "allow_metered";
211 
212     /**
213      * {@hide} Integer extra containing a SyncExemption flag.
214      *
215      * Only the system and the shell user can set it.
216      *
217      * This extra is "virtual". Once passed to the system server, it'll be removed from the bundle.
218      */
219     public static final String SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG = "v_exemption";
220 
221     /**
222      * Set by the SyncManager to request that the SyncAdapter initialize itself for
223      * the given account/authority pair. One required initialization step is to
224      * ensure that {@link #setIsSyncable(android.accounts.Account, String, int)} has been
225      * called with a >= 0 value. When this flag is set the SyncAdapter does not need to
226      * do a full sync, though it is allowed to do so.
227      */
228     public static final String SYNC_EXTRAS_INITIALIZE = "initialize";
229 
230     /** @hide */
231     public static final Intent ACTION_SYNC_CONN_STATUS_CHANGED =
232             new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
233 
234     public static final String SCHEME_CONTENT = "content";
235     public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
236     public static final String SCHEME_FILE = "file";
237 
238     /**
239      * An extra {@link Point} describing the optimal size for a requested image
240      * resource, in pixels. If a provider has multiple sizes of the image, it
241      * should return the image closest to this size.
242      *
243      * @see #openTypedAssetFileDescriptor(Uri, String, Bundle)
244      * @see #openTypedAssetFileDescriptor(Uri, String, Bundle,
245      *      CancellationSignal)
246      */
247     public static final String EXTRA_SIZE = "android.content.extra.SIZE";
248 
249     /**
250      * An extra boolean describing whether a particular provider supports refresh
251      * or not. If a provider supports refresh, it should include this key in its
252      * returned Cursor as part of its query call.
253      *
254      */
255     public static final String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
256 
257     /**
258      * Key for an SQL style selection string that may be present in the query Bundle argument
259      * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}
260      * when called by a legacy client.
261      *
262      * <p>Clients should never include user supplied values directly in the selection string,
263      * as this presents an avenue for SQL injection attacks. In lieu of this, a client
264      * should use standard placeholder notation to represent values in a selection string,
265      * then supply a corresponding value in {@value #QUERY_ARG_SQL_SELECTION_ARGS}.
266      *
267      * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
268      * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
269      *
270      * @see #QUERY_ARG_SORT_COLUMNS
271      * @see #QUERY_ARG_SORT_DIRECTION
272      * @see #QUERY_ARG_SORT_COLLATION
273      * @see #QUERY_ARG_SORT_LOCALE
274      */
275     public static final String QUERY_ARG_SQL_SELECTION = "android:query-arg-sql-selection";
276 
277     /**
278      * Key for SQL selection string arguments list.
279      *
280      * <p>Clients should never include user supplied values directly in the selection string,
281      * as this presents an avenue for SQL injection attacks. In lieu of this, a client
282      * should use standard placeholder notation to represent values in a selection string,
283      * then supply a corresponding value in {@value #QUERY_ARG_SQL_SELECTION_ARGS}.
284      *
285      * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
286      * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
287      *
288      * @see #QUERY_ARG_SORT_COLUMNS
289      * @see #QUERY_ARG_SORT_DIRECTION
290      * @see #QUERY_ARG_SORT_COLLATION
291      * @see #QUERY_ARG_SORT_LOCALE
292      */
293     public static final String QUERY_ARG_SQL_SELECTION_ARGS =
294             "android:query-arg-sql-selection-args";
295 
296     /**
297      * Key for an SQL style sort string that may be present in the query Bundle argument
298      * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}
299      * when called by a legacy client.
300      *
301      * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
302      * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
303      *
304      * @see #QUERY_ARG_SORT_COLUMNS
305      * @see #QUERY_ARG_SORT_DIRECTION
306      * @see #QUERY_ARG_SORT_COLLATION
307      * @see #QUERY_ARG_SORT_LOCALE
308      */
309     public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
310 
311     /**
312      * Key for an SQL style {@code GROUP BY} string that may be present in the
313      * query Bundle argument passed to
314      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
315      *
316      * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
317      * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
318      *
319      * @see #QUERY_ARG_GROUP_COLUMNS
320      */
321     public static final String QUERY_ARG_SQL_GROUP_BY = "android:query-arg-sql-group-by";
322 
323     /**
324      * Key for an SQL style {@code HAVING} string that may be present in the
325      * query Bundle argument passed to
326      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
327      *
328      * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
329      * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
330      */
331     public static final String QUERY_ARG_SQL_HAVING = "android:query-arg-sql-having";
332 
333     /**
334      * Key for an SQL style {@code LIMIT} string that may be present in the
335      * query Bundle argument passed to
336      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
337      *
338      * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
339      * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
340      *
341      * @see #QUERY_ARG_LIMIT
342      * @see #QUERY_ARG_OFFSET
343      */
344     public static final String QUERY_ARG_SQL_LIMIT = "android:query-arg-sql-limit";
345 
346     /**
347      * Specifies the list of columns (stored as a {@code String[]}) against
348      * which to sort results. When first column values are identical, records
349      * are then sorted based on second column values, and so on.
350      * <p>
351      * Columns present in this list must also be included in the projection
352      * supplied to
353      * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
354      * <p>
355      * Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher:
356      * <li>{@link ContentProvider} implementations: When preparing data in
357      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
358      * if sort columns is reflected in the returned Cursor, it is strongly
359      * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the
360      * array of honored arguments reflected in {@link Cursor} extras
361      * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
362      * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in
363      * the arguments {@link Bundle}, the Content framework will attempt to
364      * synthesize an QUERY_ARG_SQL* argument using the corresponding
365      * QUERY_ARG_SORT* values.
366      */
367     public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns";
368 
369     /**
370      * Specifies desired sort order. When unspecified a provider may provide a default
371      * sort direction, or choose to return unsorted results.
372      *
373      * <p>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher:
374      *
375      * <li>{@link ContentProvider} implementations: When preparing data in
376      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, if sort direction
377      * is reflected in the returned Cursor, it is  strongly recommended that
378      * {@link #QUERY_ARG_SORT_DIRECTION} then be included in the array of honored arguments
379      * reflected in {@link Cursor} extras {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
380      *
381      * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the
382      * arguments {@link Bundle}, the Content framework will attempt to synthesize
383      * a QUERY_ARG_SQL* argument using the corresponding QUERY_ARG_SORT* values.
384      *
385      * @see #QUERY_SORT_DIRECTION_ASCENDING
386      * @see #QUERY_SORT_DIRECTION_DESCENDING
387      */
388     public static final String QUERY_ARG_SORT_DIRECTION = "android:query-arg-sort-direction";
389 
390     /**
391      * Allows client to specify a hint to the provider declaring which collation
392      * to use when sorting values.
393      * <p>
394      * Providers may support custom collators. When specifying a custom collator
395      * the value is determined by the Provider.
396      * <p>
397      * {@link ContentProvider} implementations: When preparing data in
398      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
399      * if sort collation is reflected in the returned Cursor, it is strongly
400      * recommended that {@link #QUERY_ARG_SORT_COLLATION} then be included in
401      * the array of honored arguments reflected in {@link Cursor} extras
402      * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
403      * <p>
404      * When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the
405      * arguments {@link Bundle}, the Content framework will attempt to
406      * synthesize a QUERY_ARG_SQL* argument using the corresponding
407      * QUERY_ARG_SORT* values.
408      *
409      * @see java.text.Collator#PRIMARY
410      * @see java.text.Collator#SECONDARY
411      * @see java.text.Collator#TERTIARY
412      * @see java.text.Collator#IDENTICAL
413      */
414     public static final String QUERY_ARG_SORT_COLLATION = "android:query-arg-sort-collation";
415 
416     /**
417      * Allows client to specify a hint to the provider declaring which locale to
418      * use when sorting values.
419      * <p>
420      * The value is defined as a RFC 3066 locale ID followed by an optional
421      * keyword list, which is the locale format used to configure ICU through
422      * classes like {@link android.icu.util.ULocale}. This supports requesting
423      * advanced sorting options, such as {@code de@collation=phonebook},
424      * {@code zh@collation=pinyin}, etc.
425      * <p>
426      * {@link ContentProvider} implementations: When preparing data in
427      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
428      * if sort locale is reflected in the returned Cursor, it is strongly
429      * recommended that {@link #QUERY_ARG_SORT_LOCALE} then be included in the
430      * array of honored arguments reflected in {@link Cursor} extras
431      * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
432      *
433      * @see java.util.Locale#Locale(String)
434      * @see android.icu.util.ULocale#ULocale(String)
435      */
436     public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale";
437 
438     /**
439      * Specifies the list of columns (stored as a {@code String[]}) against
440      * which to group results. When column values are identical, multiple
441      * records are collapsed together into a single record.
442      * <p>
443      * Columns present in this list must also be included in the projection
444      * supplied to
445      * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
446      * <p>
447      * Apps targeting {@link android.os.Build.VERSION_CODES#R} or higher:
448      * <li>{@link ContentProvider} implementations: When preparing data in
449      * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
450      * if group columns is reflected in the returned Cursor, it is strongly
451      * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the
452      * array of honored arguments reflected in {@link Cursor} extras
453      * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
454      * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in
455      * the arguments {@link Bundle}, the Content framework will attempt to
456      * synthesize an QUERY_ARG_SQL* argument using the corresponding
457      * QUERY_ARG_SORT* values.
458      */
459     public static final String QUERY_ARG_GROUP_COLUMNS = "android:query-arg-group-columns";
460 
461     /**
462      * Allows provider to report back to client which query keys are honored in a Cursor.
463      *
464      * <p>Key identifying a {@code String[]} containing all QUERY_ARG_SORT* arguments
465      * honored by the provider. Include this in {@link Cursor} extras {@link Bundle}
466      * when any QUERY_ARG_SORT* value was honored during the preparation of the
467      * results {@link Cursor}.
468      *
469      * <p>If present, ALL honored arguments are enumerated in this extra’s payload.
470      *
471      * @see #QUERY_ARG_SORT_COLUMNS
472      * @see #QUERY_ARG_SORT_DIRECTION
473      * @see #QUERY_ARG_SORT_COLLATION
474      * @see #QUERY_ARG_SORT_LOCALE
475      * @see #QUERY_ARG_GROUP_COLUMNS
476      */
477     public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
478 
479     /** @hide */
480     @IntDef(flag = false, prefix = { "QUERY_SORT_DIRECTION_" }, value = {
481             QUERY_SORT_DIRECTION_ASCENDING,
482             QUERY_SORT_DIRECTION_DESCENDING
483     })
484     @Retention(RetentionPolicy.SOURCE)
485     public @interface SortDirection {}
486     public static final int QUERY_SORT_DIRECTION_ASCENDING = 0;
487     public static final int QUERY_SORT_DIRECTION_DESCENDING = 1;
488 
489     /**
490      * @see {@link java.text.Collector} for details on respective collation strength.
491      * @hide
492      */
493     @IntDef(flag = false, value = {
494             java.text.Collator.PRIMARY,
495             java.text.Collator.SECONDARY,
496             java.text.Collator.TERTIARY,
497             java.text.Collator.IDENTICAL
498     })
499     @Retention(RetentionPolicy.SOURCE)
500     public @interface QueryCollator {}
501 
502     /**
503      * Specifies the offset row index within a Cursor.
504      */
505     public static final String QUERY_ARG_OFFSET = "android:query-arg-offset";
506 
507     /**
508      * Specifies the max number of rows to include in a Cursor.
509      */
510     public static final String QUERY_ARG_LIMIT = "android:query-arg-limit";
511 
512     /**
513      * Added to {@link Cursor} extras {@link Bundle} to indicate total row count of
514      * recordset when paging is supported. Providers must include this when
515      * implementing paging support.
516      *
517      * <p>A provider may return -1 that row count of the recordset is unknown.
518      *
519      * <p>Providers having returned -1 in a previous query are recommended to
520      * send content change notification once (if) full recordset size becomes
521      * known.
522      */
523     public static final String EXTRA_TOTAL_COUNT = "android.content.extra.TOTAL_COUNT";
524 
525     /**
526      * This is the Android platform's base MIME type for a content: URI
527      * containing a Cursor of a single item.  Applications should use this
528      * as the base type along with their own sub-type of their content: URIs
529      * that represent a particular item.  For example, hypothetical IMAP email
530      * client may have a URI
531      * <code>content://com.company.provider.imap/inbox/1</code> for a particular
532      * message in the inbox, whose MIME type would be reported as
533      * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code>
534      *
535      * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}.
536      */
537     public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
538 
539     /**
540      * This is the Android platform's base MIME type for a content: URI
541      * containing a Cursor of zero or more items.  Applications should use this
542      * as the base type along with their own sub-type of their content: URIs
543      * that represent a directory of items.  For example, hypothetical IMAP email
544      * client may have a URI
545      * <code>content://com.company.provider.imap/inbox</code> for all of the
546      * messages in its inbox, whose MIME type would be reported as
547      * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code>
548      *
549      * <p>Note how the base MIME type varies between this and
550      * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is
551      * one single item or multiple items in the data set, while the sub-type
552      * remains the same because in either case the data structure contained
553      * in the cursor is the same.
554      */
555     public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
556 
557     /**
558      * This is the Android platform's generic MIME type to match any MIME
559      * type of the form "{@link #CURSOR_ITEM_BASE_TYPE}/{@code SUB_TYPE}".
560      * {@code SUB_TYPE} is the sub-type of the application-dependent
561      * content, e.g., "audio", "video", "playlist".
562      */
563     public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
564 
565     /** {@hide} */
566     @Deprecated
567     public static final String MIME_TYPE_DEFAULT = ClipDescription.MIMETYPE_UNKNOWN;
568 
569     /** @hide */
570     @UnsupportedAppUsage
571     public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
572     /** @hide */
573     public static final int SYNC_ERROR_AUTHENTICATION = 2;
574     /** @hide */
575     public static final int SYNC_ERROR_IO = 3;
576     /** @hide */
577     public static final int SYNC_ERROR_PARSE = 4;
578     /** @hide */
579     public static final int SYNC_ERROR_CONFLICT = 5;
580     /** @hide */
581     public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6;
582     /** @hide */
583     public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7;
584     /** @hide */
585     public static final int SYNC_ERROR_INTERNAL = 8;
586 
587     private static final String[] SYNC_ERROR_NAMES = new String[] {
588           "already-in-progress",
589           "authentication-error",
590           "io-error",
591           "parse-error",
592           "conflict",
593           "too-many-deletions",
594           "too-many-retries",
595           "internal-error",
596     };
597 
598     /** @hide */
syncErrorToString(int error)599     public static String syncErrorToString(int error) {
600         if (error < 1 || error > SYNC_ERROR_NAMES.length) {
601             return String.valueOf(error);
602         }
603         return SYNC_ERROR_NAMES[error - 1];
604     }
605 
606     /** @hide */
syncErrorStringToInt(String error)607     public static int syncErrorStringToInt(String error) {
608         for (int i = 0, n = SYNC_ERROR_NAMES.length; i < n; i++) {
609             if (SYNC_ERROR_NAMES[i].equals(error)) {
610                 return i + 1;
611             }
612         }
613         if (error != null) {
614             try {
615                 return Integer.parseInt(error);
616             } catch (NumberFormatException e) {
617                 Log.d(TAG, "error parsing sync error: " + error);
618             }
619         }
620         return 0;
621     }
622 
623     public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0;
624     public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
625     public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
626     /** @hide */
627     @UnsupportedAppUsage
628     public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3;
629     /** @hide */
630     public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
631 
632     /** @hide */
633     @IntDef(flag = true, prefix = { "NOTIFY_" }, value = {
634             NOTIFY_SYNC_TO_NETWORK,
635             NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS,
636             NOTIFY_INSERT,
637             NOTIFY_UPDATE,
638             NOTIFY_DELETE
639     })
640     @Retention(RetentionPolicy.SOURCE)
641     public @interface NotifyFlags {}
642 
643     /**
644      * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: attempt to sync the change
645      * to the network.
646      */
647     public static final int NOTIFY_SYNC_TO_NETWORK = 1<<0;
648 
649     /**
650      * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: if set, this notification
651      * will be skipped if it is being delivered to the root URI of a ContentObserver that is
652      * using "notify for descendants."  The purpose of this is to allow the provide to send
653      * a general notification of "something under X" changed that observers of that specific
654      * URI can receive, while also sending a specific URI under X.  It would use this flag
655      * when sending the former, so that observers of "X and descendants" only see the latter.
656      */
657     public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1;
658 
659     /**
660      * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set
661      * by a {@link ContentProvider} to indicate that this notification is the
662      * result of an {@link ContentProvider#insert} call.
663      * <p>
664      * Sending these detailed flags are optional, but providers are strongly
665      * recommended to send them.
666      */
667     public static final int NOTIFY_INSERT = 1 << 2;
668 
669     /**
670      * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set
671      * by a {@link ContentProvider} to indicate that this notification is the
672      * result of an {@link ContentProvider#update} call.
673      * <p>
674      * Sending these detailed flags are optional, but providers are strongly
675      * recommended to send them.
676      */
677     public static final int NOTIFY_UPDATE = 1 << 3;
678 
679     /**
680      * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set
681      * by a {@link ContentProvider} to indicate that this notification is the
682      * result of a {@link ContentProvider#delete} call.
683      * <p>
684      * Sending these detailed flags are optional, but providers are strongly
685      * recommended to send them.
686      */
687     public static final int NOTIFY_DELETE = 1 << 4;
688 
689     /**
690      * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set
691      * by a {@link ContentProvider} to indicate that this notification should
692      * not be subject to any delays when dispatching to apps running in the
693      * background.
694      * <p>
695      * Using this flag may negatively impact system health and performance, and
696      * should be used sparingly.
697      *
698      * @hide
699      */
700     public static final int NOTIFY_NO_DELAY = 1 << 15;
701 
702     /**
703      * No exception, throttled by app standby normally.
704      * @hide
705      */
706     public static final int SYNC_EXEMPTION_NONE = 0;
707 
708     /**
709      * Exemption given to a sync request made by a foreground app (including
710      * PROCESS_STATE_IMPORTANT_FOREGROUND).
711      *
712      * At the schedule time, we promote the sync adapter app for a higher bucket:
713      * - If the device is not dozing (so the sync will start right away)
714      *   promote to ACTIVE for 1 hour.
715      * - If the device is dozing (so the sync *won't* start right away),
716      * promote to WORKING_SET for 4 hours, so it'll get a higher chance to be started once the
717      * device comes out of doze.
718      * - When the sync actually starts, we promote the sync adapter app to ACTIVE for 10 minutes,
719      * so it can schedule and start more syncs without getting throttled, even when the first
720      * operation was canceled and now we're retrying.
721      *
722      *
723      * @hide
724      */
725     public static final int SYNC_EXEMPTION_PROMOTE_BUCKET = 1;
726 
727     /**
728      * In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the
729      * temp whitelist for 10 minutes, so that even RARE apps can run syncs right away.
730      * @hide
731      */
732     public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2;
733 
734     /** @hide */
735     @IntDef(flag = false, prefix = { "SYNC_EXEMPTION_" }, value = {
736             SYNC_EXEMPTION_NONE,
737             SYNC_EXEMPTION_PROMOTE_BUCKET,
738             SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP,
739     })
740     @Retention(RetentionPolicy.SOURCE)
741     public @interface SyncExemption {}
742 
743     // Always log queries which take 500ms+; shorter queries are
744     // sampled accordingly.
745     private static final boolean ENABLE_CONTENT_SAMPLE = false;
746     private static final int SLOW_THRESHOLD_MILLIS = 500;
747     private final Random mRandom = new Random();  // guarded by itself
748 
749     /** @hide */
750     public static final String REMOTE_CALLBACK_RESULT = "result";
751 
752     /** @hide */
753     public static final String REMOTE_CALLBACK_ERROR = "error";
754 
755     /**
756      * How long we wait for an attached process to publish its content providers
757      * before we decide it must be hung.
758      * @hide
759      */
760     public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000;
761 
762     /**
763      * How long we wait for an provider to be published. Should be longer than
764      * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}.
765      * @hide
766      */
767     public static final int CONTENT_PROVIDER_READY_TIMEOUT_MILLIS =
768             CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000;
769 
770     // Timeout given a ContentProvider that has already been started and connected to.
771     private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = 3 * 1000;
772 
773     // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how
774     // long ActivityManagerService is giving a content provider to get published if a new process
775     // needs to be started for that.
776     private static final int REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS =
777             CONTENT_PROVIDER_READY_TIMEOUT_MILLIS + CONTENT_PROVIDER_TIMEOUT_MILLIS;
778 
ContentResolver(@ullable Context context)779     public ContentResolver(@Nullable Context context) {
780         this(context, null);
781     }
782 
783     /** {@hide} */
ContentResolver(@ullable Context context, @Nullable ContentInterface wrapped)784     public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) {
785         mContext = context != null ? context : ActivityThread.currentApplication();
786         mPackageName = mContext.getOpPackageName();
787         mAttributionTag = mContext.getAttributionTag();
788         mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
789         mWrapped = wrapped;
790     }
791 
792     /** {@hide} */
wrap(@onNull ContentInterface wrapped)793     public static @NonNull ContentResolver wrap(@NonNull ContentInterface wrapped) {
794         Objects.requireNonNull(wrapped);
795 
796         return new ContentResolver(null, wrapped) {
797             @Override
798             public void unstableProviderDied(IContentProvider icp) {
799                 throw new UnsupportedOperationException();
800             }
801             @Override
802             public boolean releaseUnstableProvider(IContentProvider icp) {
803                 throw new UnsupportedOperationException();
804             }
805             @Override
806             public boolean releaseProvider(IContentProvider icp) {
807                 throw new UnsupportedOperationException();
808             }
809             @Override
810             protected IContentProvider acquireUnstableProvider(Context c, String name) {
811                 throw new UnsupportedOperationException();
812             }
813             @Override
814             protected IContentProvider acquireProvider(Context c, String name) {
815                 throw new UnsupportedOperationException();
816             }
817         };
818     }
819 
820     /**
821      * Create a {@link ContentResolver} instance that redirects all its methods
822      * to the given {@link ContentProvider}.
823      */
824     public static @NonNull ContentResolver wrap(@NonNull ContentProvider wrapped) {
825         return wrap((ContentInterface) wrapped);
826     }
827 
828     /**
829      * Create a {@link ContentResolver} instance that redirects all its methods
830      * to the given {@link ContentProviderClient}.
831      */
832     public static @NonNull ContentResolver wrap(@NonNull ContentProviderClient wrapped) {
833         return wrap((ContentInterface) wrapped);
834     }
835 
836     /** @hide */
837     @UnsupportedAppUsage
838     protected abstract IContentProvider acquireProvider(Context c, String name);
839 
840     /**
841      * Providing a default implementation of this, to avoid having to change a
842      * lot of other things, but implementations of ContentResolver should
843      * implement it.
844      *
845      * @hide
846      */
847     @UnsupportedAppUsage
848     protected IContentProvider acquireExistingProvider(Context c, String name) {
849         return acquireProvider(c, name);
850     }
851 
852     /** @hide */
853     @UnsupportedAppUsage
854     public abstract boolean releaseProvider(IContentProvider icp);
855     /** @hide */
856     @UnsupportedAppUsage
857     protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
858     /** @hide */
859     @UnsupportedAppUsage
860     public abstract boolean releaseUnstableProvider(IContentProvider icp);
861     /** @hide */
862     @UnsupportedAppUsage
863     public abstract void unstableProviderDied(IContentProvider icp);
864 
865     /** @hide */
866     public void appNotRespondingViaProvider(IContentProvider icp) {
867         throw new UnsupportedOperationException("appNotRespondingViaProvider");
868     }
869 
870     /**
871      * Return the MIME type of the given content URL.
872      *
873      * @param url A Uri identifying content (either a list or specific type),
874      * using the content:// scheme.
875      * @return A MIME type for the content, or null if the URL is invalid or the type is unknown
876      */
877     @Override
878     public final @Nullable String getType(@NonNull Uri url) {
879         Objects.requireNonNull(url, "url");
880 
881         try {
882             if (mWrapped != null) return mWrapped.getType(url);
883         } catch (RemoteException e) {
884             return null;
885         }
886 
887         // XXX would like to have an acquireExistingUnstableProvider for this.
888         IContentProvider provider = acquireExistingProvider(url);
889         if (provider != null) {
890             try {
891                 final StringResultListener resultListener = new StringResultListener();
892                 provider.getTypeAsync(url, new RemoteCallback(resultListener));
893                 resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
894                 if (resultListener.exception != null) {
895                     throw resultListener.exception;
896                 }
897                 return resultListener.result;
898             } catch (RemoteException e) {
899                 // Arbitrary and not worth documenting, as Activity
900                 // Manager will kill this process shortly anyway.
901                 return null;
902             } catch (java.lang.Exception e) {
903                 Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
904                 return null;
905             } finally {
906                 releaseProvider(provider);
907             }
908         }
909 
910         if (!SCHEME_CONTENT.equals(url.getScheme())) {
911             return null;
912         }
913 
914         try {
915             final StringResultListener resultListener = new StringResultListener();
916             ActivityManager.getService().getProviderMimeTypeAsync(
917                     ContentProvider.getUriWithoutUserId(url),
918                     resolveUserId(url),
919                     new RemoteCallback(resultListener));
920             resultListener.waitForResult(REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS);
921             if (resultListener.exception != null) {
922                 throw resultListener.exception;
923             }
924             return resultListener.result;
925         } catch (RemoteException e) {
926             // We just failed to send a oneway request to the System Server. Nothing to do.
927             return null;
928         } catch (java.lang.Exception e) {
929             Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
930             return null;
931         }
932     }
933 
934     private abstract static class ResultListener<T> implements RemoteCallback.OnResultListener {
935         @GuardedBy("this")
936         public boolean done;
937 
938         @GuardedBy("this")
939         public T result;
940 
941         @GuardedBy("this")
942         public RuntimeException exception;
943 
944         @Override
945         public void onResult(Bundle result) {
946             synchronized (this) {
947                 ParcelableException e = result.getParcelable(REMOTE_CALLBACK_ERROR);
948                 if (e != null) {
949                     Throwable t = e.getCause();
950                     if (t instanceof RuntimeException) {
951                         this.exception = (RuntimeException) t;
952                     } else {
953                         this.exception = new RuntimeException(t);
954                     }
955                 } else {
956                     this.result = getResultFromBundle(result);
957                 }
958                 done = true;
959                 notifyAll();
960             }
961         }
962 
963         protected abstract T getResultFromBundle(Bundle result);
964 
965         public void waitForResult(long timeout) {
966             synchronized (this) {
967                 if (!done) {
968                     try {
969                         wait(timeout);
970                     } catch (InterruptedException e) {
971                         // Ignore
972                     }
973                 }
974             }
975         }
976     }
977 
978     private static class StringResultListener extends ResultListener<String> {
979         @Override
980         protected String getResultFromBundle(Bundle result) {
981             return result.getString(REMOTE_CALLBACK_RESULT);
982         }
983     }
984 
985     private static class UriResultListener extends ResultListener<Uri> {
986         @Override
987         protected Uri getResultFromBundle(Bundle result) {
988             return result.getParcelable(REMOTE_CALLBACK_RESULT);
989         }
990     }
991 
992     /**
993      * Query for the possible MIME types for the representations the given
994      * content URL can be returned when opened as as stream with
995      * {@link #openTypedAssetFileDescriptor}.  Note that the types here are
996      * not necessarily a superset of the type returned by {@link #getType} --
997      * many content providers cannot return a raw stream for the structured
998      * data that they contain.
999      *
1000      * @param url A Uri identifying content (either a list or specific type),
1001      * using the content:// scheme.
1002      * @param mimeTypeFilter The desired MIME type.  This may be a pattern,
1003      * such as *&#47;*, to query for all available MIME types that match the
1004      * pattern.
1005      * @return Returns an array of MIME type strings for all available
1006      * data streams that match the given mimeTypeFilter.  If there are none,
1007      * null is returned.
1008      */
1009     @Override
1010     public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
1011         Objects.requireNonNull(url, "url");
1012         Objects.requireNonNull(mimeTypeFilter, "mimeTypeFilter");
1013 
1014         try {
1015             if (mWrapped != null) return mWrapped.getStreamTypes(url, mimeTypeFilter);
1016         } catch (RemoteException e) {
1017             return null;
1018         }
1019 
1020         IContentProvider provider = acquireProvider(url);
1021         if (provider == null) {
1022             return null;
1023         }
1024 
1025         try {
1026             return provider.getStreamTypes(url, mimeTypeFilter);
1027         } catch (RemoteException e) {
1028             // Arbitrary and not worth documenting, as Activity
1029             // Manager will kill this process shortly anyway.
1030             return null;
1031         } finally {
1032             releaseProvider(provider);
1033         }
1034     }
1035 
1036     /**
1037      * Query the given URI, returning a {@link Cursor} over the result set.
1038      * <p>
1039      * For best performance, the caller should follow these guidelines:
1040      * <ul>
1041      * <li>Provide an explicit projection, to prevent
1042      * reading data from storage that aren't going to be used.</li>
1043      * <li>Use question mark parameter markers such as 'phone=?' instead of
1044      * explicit values in the {@code selection} parameter, so that queries
1045      * that differ only by those values will be recognized as the same
1046      * for caching purposes.</li>
1047      * </ul>
1048      * </p>
1049      *
1050      * @param uri The URI, using the content:// scheme, for the content to
1051      *         retrieve.
1052      * @param projection A list of which columns to return. Passing null will
1053      *         return all columns, which is inefficient.
1054      * @param selection A filter declaring which rows to return, formatted as an
1055      *         SQL WHERE clause (excluding the WHERE itself). Passing null will
1056      *         return all rows for the given URI.
1057      * @param selectionArgs You may include ?s in selection, which will be
1058      *         replaced by the values from selectionArgs, in the order that they
1059      *         appear in the selection. The values will be bound as Strings.
1060      * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
1061      *         clause (excluding the ORDER BY itself). Passing null will use the
1062      *         default sort order, which may be unordered.
1063      * @return A Cursor object, which is positioned before the first entry. May return
1064      *         <code>null</code> if the underlying content provider returns <code>null</code>,
1065      *         or if it crashes.
1066      * @see Cursor
1067      */
1068     public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
1069             @Nullable String[] projection, @Nullable String selection,
1070             @Nullable String[] selectionArgs, @Nullable String sortOrder) {
1071         return query(uri, projection, selection, selectionArgs, sortOrder, null);
1072     }
1073 
1074     /**
1075      * Query the given URI, returning a {@link Cursor} over the result set
1076      * with optional support for cancellation.
1077      * <p>
1078      * For best performance, the caller should follow these guidelines:
1079      * <ul>
1080      * <li>Provide an explicit projection, to prevent
1081      * reading data from storage that aren't going to be used.</li>
1082      * <li>Use question mark parameter markers such as 'phone=?' instead of
1083      * explicit values in the {@code selection} parameter, so that queries
1084      * that differ only by those values will be recognized as the same
1085      * for caching purposes.</li>
1086      * </ul>
1087      * </p>
1088      *
1089      * @param uri The URI, using the content:// scheme, for the content to
1090      *         retrieve.
1091      * @param projection A list of which columns to return. Passing null will
1092      *         return all columns, which is inefficient.
1093      * @param selection A filter declaring which rows to return, formatted as an
1094      *         SQL WHERE clause (excluding the WHERE itself). Passing null will
1095      *         return all rows for the given URI.
1096      * @param selectionArgs You may include ?s in selection, which will be
1097      *         replaced by the values from selectionArgs, in the order that they
1098      *         appear in the selection. The values will be bound as Strings.
1099      * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
1100      *         clause (excluding the ORDER BY itself). Passing null will use the
1101      *         default sort order, which may be unordered.
1102      * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1103      * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1104      * when the query is executed.
1105      * @return A Cursor object, which is positioned before the first entry. May return
1106      *         <code>null</code> if the underlying content provider returns <code>null</code>,
1107      *         or if it crashes.
1108      * @see Cursor
1109      */
1110     public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
1111             @Nullable String[] projection, @Nullable String selection,
1112             @Nullable String[] selectionArgs, @Nullable String sortOrder,
1113             @Nullable CancellationSignal cancellationSignal) {
1114         Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder);
1115         return query(uri, projection, queryArgs, cancellationSignal);
1116     }
1117 
1118     /**
1119      * Query the given URI, returning a {@link Cursor} over the result set
1120      * with support for cancellation.
1121      *
1122      * <p>For best performance, the caller should follow these guidelines:
1123      *
1124      * <li>Provide an explicit projection, to prevent reading data from storage
1125      * that aren't going to be used.
1126      *
1127      * Provider must identify which QUERY_ARG_SORT* arguments were honored during
1128      * the preparation of the result set by including the respective argument keys
1129      * in the {@link Cursor} extras {@link Bundle}. See {@link #EXTRA_HONORED_ARGS}
1130      * for details.
1131      *
1132      * @see #QUERY_ARG_SORT_COLUMNS
1133      * @see #QUERY_ARG_SORT_DIRECTION
1134      * @see #QUERY_ARG_SORT_COLLATION
1135      *
1136      * @param uri The URI, using the content:// scheme, for the content to
1137      *         retrieve.
1138      * @param projection A list of which columns to return. Passing null will
1139      *         return all columns, which is inefficient.
1140      * @param queryArgs A Bundle containing additional information necessary for
1141      *            the operation. Arguments may include SQL style arguments, such
1142      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
1143      *            the documentation for each individual provider will indicate
1144      *            which arguments they support.
1145      * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1146      * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1147      * when the query is executed.
1148      * @return A Cursor object, which is positioned before the first entry. May return
1149      *         <code>null</code> if the underlying content provider returns <code>null</code>,
1150      *         or if it crashes.
1151      * @see Cursor
1152      */
1153     @Override
1154     public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
1155             @Nullable String[] projection, @Nullable Bundle queryArgs,
1156             @Nullable CancellationSignal cancellationSignal) {
1157         Objects.requireNonNull(uri, "uri");
1158 
1159         try {
1160             if (mWrapped != null) {
1161                 return mWrapped.query(uri, projection, queryArgs, cancellationSignal);
1162             }
1163         } catch (RemoteException e) {
1164             return null;
1165         }
1166 
1167         IContentProvider unstableProvider = acquireUnstableProvider(uri);
1168         if (unstableProvider == null) {
1169             return null;
1170         }
1171         IContentProvider stableProvider = null;
1172         Cursor qCursor = null;
1173         try {
1174             long startTime = SystemClock.uptimeMillis();
1175 
1176             ICancellationSignal remoteCancellationSignal = null;
1177             if (cancellationSignal != null) {
1178                 cancellationSignal.throwIfCanceled();
1179                 remoteCancellationSignal = unstableProvider.createCancellationSignal();
1180                 cancellationSignal.setRemote(remoteCancellationSignal);
1181             }
1182             try {
1183                 qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,
1184                         queryArgs, remoteCancellationSignal);
1185             } catch (DeadObjectException e) {
1186                 // The remote process has died...  but we only hold an unstable
1187                 // reference though, so we might recover!!!  Let's try!!!!
1188                 // This is exciting!!1!!1!!!!1
1189                 unstableProviderDied(unstableProvider);
1190                 stableProvider = acquireProvider(uri);
1191                 if (stableProvider == null) {
1192                     return null;
1193                 }
1194                 qCursor = stableProvider.query(mPackageName, mAttributionTag, uri, projection,
1195                         queryArgs, remoteCancellationSignal);
1196             }
1197             if (qCursor == null) {
1198                 return null;
1199             }
1200 
1201             // Force query execution.  Might fail and throw a runtime exception here.
1202             qCursor.getCount();
1203             long durationMillis = SystemClock.uptimeMillis() - startTime;
1204             maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
1205 
1206             // Wrap the cursor object into CursorWrapperInner object.
1207             final IContentProvider provider = (stableProvider != null) ? stableProvider
1208                     : acquireProvider(uri);
1209             final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
1210             stableProvider = null;
1211             qCursor = null;
1212             return wrapper;
1213         } catch (RemoteException e) {
1214             // Arbitrary and not worth documenting, as Activity
1215             // Manager will kill this process shortly anyway.
1216             return null;
1217         } finally {
1218             if (qCursor != null) {
1219                 qCursor.close();
1220             }
1221             if (cancellationSignal != null) {
1222                 cancellationSignal.setRemote(null);
1223             }
1224             if (unstableProvider != null) {
1225                 releaseUnstableProvider(unstableProvider);
1226             }
1227             if (stableProvider != null) {
1228                 releaseProvider(stableProvider);
1229             }
1230         }
1231     }
1232 
1233     /** {@hide} */
1234     public final @NonNull Uri canonicalizeOrElse(@NonNull Uri uri) {
1235         final Uri res = canonicalize(uri);
1236         return (res != null) ? res : uri;
1237     }
1238 
1239     /**
1240      * Transform the given <var>url</var> to a canonical representation of
1241      * its referenced resource, which can be used across devices, persisted,
1242      * backed up and restored, etc.  The returned Uri is still a fully capable
1243      * Uri for use with its content provider, allowing you to do all of the
1244      * same content provider operations as with the original Uri --
1245      * {@link #query}, {@link #openInputStream(android.net.Uri)}, etc.  The
1246      * only difference in behavior between the original and new Uris is that
1247      * the content provider may need to do some additional work at each call
1248      * using it to resolve it to the correct resource, especially if the
1249      * canonical Uri has been moved to a different environment.
1250      *
1251      * <p>If you are moving a canonical Uri between environments, you should
1252      * perform another call to {@link #canonicalize} with that original Uri to
1253      * re-canonicalize it for the current environment.  Alternatively, you may
1254      * want to use {@link #uncanonicalize} to transform it to a non-canonical
1255      * Uri that works only in the current environment but potentially more
1256      * efficiently than the canonical representation.</p>
1257      *
1258      * @param url The {@link Uri} that is to be transformed to a canonical
1259      * representation.  Like all resolver calls, the input can be either
1260      * a non-canonical or canonical Uri.
1261      *
1262      * @return Returns the official canonical representation of <var>url</var>,
1263      * or null if the content provider does not support a canonical representation
1264      * of the given Uri.  Many providers may not support canonicalization of some
1265      * or all of their Uris.
1266      *
1267      * @see #uncanonicalize
1268      */
1269     @Override
1270     public final @Nullable Uri canonicalize(@NonNull Uri url) {
1271         Objects.requireNonNull(url, "url");
1272 
1273         try {
1274             if (mWrapped != null) return mWrapped.canonicalize(url);
1275         } catch (RemoteException e) {
1276             return null;
1277         }
1278 
1279         IContentProvider provider = acquireProvider(url);
1280         if (provider == null) {
1281             return null;
1282         }
1283 
1284         try {
1285             final UriResultListener resultListener = new UriResultListener();
1286             provider.canonicalizeAsync(mPackageName, mAttributionTag, url,
1287                     new RemoteCallback(resultListener));
1288             resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
1289             if (resultListener.exception != null) {
1290                 throw resultListener.exception;
1291             }
1292             return resultListener.result;
1293         } catch (RemoteException e) {
1294             // Arbitrary and not worth documenting, as Activity
1295             // Manager will kill this process shortly anyway.
1296             return null;
1297         } finally {
1298             releaseProvider(provider);
1299         }
1300     }
1301 
1302     /**
1303      * Given a canonical Uri previously generated by {@link #canonicalize}, convert
1304      * it to its local non-canonical form.  This can be useful in some cases where
1305      * you know that you will only be using the Uri in the current environment and
1306      * want to avoid any possible overhead when using it with the content
1307      * provider or want to verify that the referenced data exists at all in the
1308      * new environment.
1309      *
1310      * @param url The canonical {@link Uri} that is to be convered back to its
1311      * non-canonical form.
1312      *
1313      * @return Returns the non-canonical representation of <var>url</var>.  This will
1314      * return null if data identified by the canonical Uri can not be found in
1315      * the current environment; callers must always check for null and deal with
1316      * that by appropriately falling back to an alternative.
1317      *
1318      * @see #canonicalize
1319      */
1320     @Override
1321     public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
1322         Objects.requireNonNull(url, "url");
1323 
1324         try {
1325             if (mWrapped != null) return mWrapped.uncanonicalize(url);
1326         } catch (RemoteException e) {
1327             return null;
1328         }
1329 
1330         IContentProvider provider = acquireProvider(url);
1331         if (provider == null) {
1332             return null;
1333         }
1334 
1335         try {
1336             return provider.uncanonicalize(mPackageName, mAttributionTag, url);
1337         } catch (RemoteException e) {
1338             // Arbitrary and not worth documenting, as Activity
1339             // Manager will kill this process shortly anyway.
1340             return null;
1341         } finally {
1342             releaseProvider(provider);
1343         }
1344     }
1345 
1346     /**
1347      * This allows clients to request an explicit refresh of content identified
1348      * by {@code uri}.
1349      * <p>
1350      * Client code should only invoke this method when there is a strong
1351      * indication (such as a user initiated pull to refresh gesture) that the
1352      * content is stale.
1353      * <p>
1354      *
1355      * @param url The Uri identifying the data to refresh.
1356      * @param extras Additional options from the client. The definitions of
1357      *            these are specific to the content provider being called.
1358      * @param cancellationSignal A signal to cancel the operation in progress,
1359      *            or {@code null} if none. For example, if you called refresh on
1360      *            a particular uri, you should call
1361      *            {@link CancellationSignal#throwIfCanceled()} to check whether
1362      *            the client has canceled the refresh request.
1363      * @return true if the provider actually tried refreshing.
1364      */
1365     @Override
1366     public final boolean refresh(@NonNull Uri url, @Nullable Bundle extras,
1367             @Nullable CancellationSignal cancellationSignal) {
1368         Objects.requireNonNull(url, "url");
1369 
1370         try {
1371             if (mWrapped != null) return mWrapped.refresh(url, extras, cancellationSignal);
1372         } catch (RemoteException e) {
1373             return false;
1374         }
1375 
1376         IContentProvider provider = acquireProvider(url);
1377         if (provider == null) {
1378             return false;
1379         }
1380 
1381         try {
1382             ICancellationSignal remoteCancellationSignal = null;
1383             if (cancellationSignal != null) {
1384                 cancellationSignal.throwIfCanceled();
1385                 remoteCancellationSignal = provider.createCancellationSignal();
1386                 cancellationSignal.setRemote(remoteCancellationSignal);
1387             }
1388             return provider.refresh(mPackageName, mAttributionTag, url, extras,
1389                     remoteCancellationSignal);
1390         } catch (RemoteException e) {
1391             // Arbitrary and not worth documenting, as Activity
1392             // Manager will kill this process shortly anyway.
1393             return false;
1394         } finally {
1395             releaseProvider(provider);
1396         }
1397     }
1398 
1399     /**
1400      * Perform a detailed internal check on a {@link Uri} to determine if a UID
1401      * is able to access it with specific mode flags.
1402      * <p>
1403      * This method is typically used when the provider implements more dynamic
1404      * access controls that cannot be expressed with {@code <path-permission>}
1405      * style static rules.
1406      * <p>
1407      * Because validation of these dynamic access controls has significant
1408      * system health impact, this feature is only available to providers that
1409      * are built into the system.
1410      *
1411      * @param uri the {@link Uri} to perform an access check on.
1412      * @param uid the UID to check the permission for.
1413      * @param modeFlags the access flags to use for the access check, such as
1414      *            {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
1415      * @return {@link PackageManager#PERMISSION_GRANTED} if access is allowed,
1416      *         otherwise {@link PackageManager#PERMISSION_DENIED}.
1417      * @hide
1418      */
1419     @Override
1420     @SystemApi
1421     public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
1422         Objects.requireNonNull(uri, "uri");
1423 
1424         try {
1425             if (mWrapped != null) return mWrapped.checkUriPermission(uri, uid, modeFlags);
1426         } catch (RemoteException e) {
1427             return PackageManager.PERMISSION_DENIED;
1428         }
1429 
1430         try (ContentProviderClient client = acquireUnstableContentProviderClient(uri)) {
1431             return client.checkUriPermission(uri, uid, modeFlags);
1432         } catch (RemoteException e) {
1433             return PackageManager.PERMISSION_DENIED;
1434         }
1435     }
1436 
1437     /**
1438      * Open a stream on to the content associated with a content URI.  If there
1439      * is no data associated with the URI, FileNotFoundException is thrown.
1440      *
1441      * <h5>Accepts the following URI schemes:</h5>
1442      * <ul>
1443      * <li>content ({@link #SCHEME_CONTENT})</li>
1444      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
1445      * <li>file ({@link #SCHEME_FILE})</li>
1446      * </ul>
1447      *
1448      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1449      * on these schemes.
1450      *
1451      * @param uri The desired URI.
1452      * @return InputStream or {@code null} if the provider recently crashed.
1453      * @throws FileNotFoundException if the provided URI could not be opened.
1454      * @see #openAssetFileDescriptor(Uri, String)
1455      */
1456     public final @Nullable InputStream openInputStream(@NonNull Uri uri)
1457             throws FileNotFoundException {
1458         Objects.requireNonNull(uri, "uri");
1459         String scheme = uri.getScheme();
1460         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
1461             // Note: left here to avoid breaking compatibility.  May be removed
1462             // with sufficient testing.
1463             OpenResourceIdResult r = getResourceId(uri);
1464             try {
1465                 InputStream stream = r.r.openRawResource(r.id);
1466                 return stream;
1467             } catch (Resources.NotFoundException ex) {
1468                 throw new FileNotFoundException("Resource does not exist: " + uri);
1469             }
1470         } else if (SCHEME_FILE.equals(scheme)) {
1471             // Note: left here to avoid breaking compatibility.  May be removed
1472             // with sufficient testing.
1473             return new FileInputStream(uri.getPath());
1474         } else {
1475             AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r", null);
1476             try {
1477                 return fd != null ? fd.createInputStream() : null;
1478             } catch (IOException e) {
1479                 throw new FileNotFoundException("Unable to create stream");
1480             }
1481         }
1482     }
1483 
1484     /**
1485      * Synonym for {@link #openOutputStream(Uri, String)
1486      * openOutputStream(uri, "w")}.
1487      *
1488      * @param uri The desired URI.
1489      * @return an OutputStream or {@code null} if the provider recently crashed.
1490      * @throws FileNotFoundException if the provided URI could not be opened.
1491      */
1492     public final @Nullable OutputStream openOutputStream(@NonNull Uri uri)
1493             throws FileNotFoundException {
1494         return openOutputStream(uri, "w");
1495     }
1496 
1497     /**
1498      * Open a stream on to the content associated with a content URI.  If there
1499      * is no data associated with the URI, FileNotFoundException is thrown.
1500      *
1501      * <h5>Accepts the following URI schemes:</h5>
1502      * <ul>
1503      * <li>content ({@link #SCHEME_CONTENT})</li>
1504      * <li>file ({@link #SCHEME_FILE})</li>
1505      * </ul>
1506      *
1507      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1508      * on these schemes.
1509      *
1510      * @param uri The desired URI.
1511      * @param mode May be "w", "wa", "rw", or "rwt".
1512      * @return an OutputStream or {@code null} if the provider recently crashed.
1513      * @throws FileNotFoundException if the provided URI could not be opened.
1514      * @see #openAssetFileDescriptor(Uri, String)
1515      */
1516     public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode)
1517             throws FileNotFoundException {
1518         AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null);
1519         try {
1520             return fd != null ? fd.createOutputStream() : null;
1521         } catch (IOException e) {
1522             throw new FileNotFoundException("Unable to create stream");
1523         }
1524     }
1525 
1526     @Override
1527     public final @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
1528             @Nullable CancellationSignal signal) throws FileNotFoundException {
1529         try {
1530             if (mWrapped != null) return mWrapped.openFile(uri, mode, signal);
1531         } catch (RemoteException e) {
1532             return null;
1533         }
1534 
1535         return openFileDescriptor(uri, mode, signal);
1536     }
1537 
1538     /**
1539      * Open a raw file descriptor to access data under a URI.  This
1540      * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
1541      * underlying {@link ContentProvider#openFile}
1542      * ContentProvider.openFile()} method, so will <em>not</em> work with
1543      * providers that return sub-sections of files.  If at all possible,
1544      * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
1545      * will receive a FileNotFoundException exception if the provider returns a
1546      * sub-section of a file.
1547      *
1548      * <h5>Accepts the following URI schemes:</h5>
1549      * <ul>
1550      * <li>content ({@link #SCHEME_CONTENT})</li>
1551      * <li>file ({@link #SCHEME_FILE})</li>
1552      * </ul>
1553      *
1554      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1555      * on these schemes.
1556      * <p>
1557      * If opening with the exclusive "r" or "w" modes, the returned
1558      * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
1559      * of data. Opening with the "rw" mode implies a file on disk that supports
1560      * seeking. If possible, always use an exclusive mode to give the underlying
1561      * {@link ContentProvider} the most flexibility.
1562      * <p>
1563      * If you are writing a file, and need to communicate an error to the
1564      * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
1565      *
1566      * @param uri The desired URI to open.
1567      * @param mode The file mode to use, as per {@link ContentProvider#openFile
1568      * ContentProvider.openFile}.
1569      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1570      * provider recently crashed. You own this descriptor and are responsible for closing it
1571      * when done.
1572      * @throws FileNotFoundException Throws FileNotFoundException if no
1573      * file exists under the URI or the mode is invalid.
1574      * @see #openAssetFileDescriptor(Uri, String)
1575      */
1576     public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
1577             @NonNull String mode) throws FileNotFoundException {
1578         return openFileDescriptor(uri, mode, null);
1579     }
1580 
1581     /**
1582      * Open a raw file descriptor to access data under a URI.  This
1583      * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
1584      * underlying {@link ContentProvider#openFile}
1585      * ContentProvider.openFile()} method, so will <em>not</em> work with
1586      * providers that return sub-sections of files.  If at all possible,
1587      * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
1588      * will receive a FileNotFoundException exception if the provider returns a
1589      * sub-section of a file.
1590      *
1591      * <h5>Accepts the following URI schemes:</h5>
1592      * <ul>
1593      * <li>content ({@link #SCHEME_CONTENT})</li>
1594      * <li>file ({@link #SCHEME_FILE})</li>
1595      * </ul>
1596      *
1597      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1598      * on these schemes.
1599      * <p>
1600      * If opening with the exclusive "r" or "w" modes, the returned
1601      * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
1602      * of data. Opening with the "rw" mode implies a file on disk that supports
1603      * seeking. If possible, always use an exclusive mode to give the underlying
1604      * {@link ContentProvider} the most flexibility.
1605      * <p>
1606      * If you are writing a file, and need to communicate an error to the
1607      * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
1608      *
1609      * @param uri The desired URI to open.
1610      * @param mode The file mode to use, as per {@link ContentProvider#openFile
1611      * ContentProvider.openFile}.
1612      * @param cancellationSignal A signal to cancel the operation in progress,
1613      *         or null if none. If the operation is canceled, then
1614      *         {@link OperationCanceledException} will be thrown.
1615      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1616      * provider recently crashed. You own this descriptor and are responsible for closing it
1617      * when done.
1618      * @throws FileNotFoundException Throws FileNotFoundException if no
1619      * file exists under the URI or the mode is invalid.
1620      * @see #openAssetFileDescriptor(Uri, String)
1621      */
1622     public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
1623             @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
1624                     throws FileNotFoundException {
1625         try {
1626             if (mWrapped != null) return mWrapped.openFile(uri, mode, cancellationSignal);
1627         } catch (RemoteException e) {
1628             return null;
1629         }
1630 
1631         AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal);
1632         if (afd == null) {
1633             return null;
1634         }
1635 
1636         if (afd.getDeclaredLength() < 0) {
1637             // This is a full file!
1638             return afd.getParcelFileDescriptor();
1639         }
1640 
1641         // Client can't handle a sub-section of a file, so close what
1642         // we got and bail with an exception.
1643         try {
1644             afd.close();
1645         } catch (IOException e) {
1646         }
1647 
1648         throw new FileNotFoundException("Not a whole file");
1649     }
1650 
1651     @Override
1652     public final @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
1653             @Nullable CancellationSignal signal) throws FileNotFoundException {
1654         try {
1655             if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, signal);
1656         } catch (RemoteException e) {
1657             return null;
1658         }
1659 
1660         return openAssetFileDescriptor(uri, mode, signal);
1661     }
1662 
1663     /**
1664      * Open a raw file descriptor to access data under a URI.  This
1665      * interacts with the underlying {@link ContentProvider#openAssetFile}
1666      * method of the provider associated with the given URI, to retrieve any file stored there.
1667      *
1668      * <h5>Accepts the following URI schemes:</h5>
1669      * <ul>
1670      * <li>content ({@link #SCHEME_CONTENT})</li>
1671      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
1672      * <li>file ({@link #SCHEME_FILE})</li>
1673      * </ul>
1674      * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
1675      * <p>
1676      * A Uri object can be used to reference a resource in an APK file.  The
1677      * Uri should be one of the following formats:
1678      * <ul>
1679      * <li><code>android.resource://package_name/id_number</code><br/>
1680      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1681      * For example <code>com.example.myapp</code><br/>
1682      * <code>id_number</code> is the int form of the ID.<br/>
1683      * The easiest way to construct this form is
1684      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
1685      * </li>
1686      * <li><code>android.resource://package_name/type/name</code><br/>
1687      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1688      * For example <code>com.example.myapp</code><br/>
1689      * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
1690      * or <code>drawable</code>.
1691      * <code>name</code> is the string form of the resource name.  That is, whatever the file
1692      * name was in your res directory, without the type extension.
1693      * The easiest way to construct this form is
1694      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
1695      * </li>
1696      * </ul>
1697      *
1698      * <p>Note that if this function is called for read-only input (mode is "r")
1699      * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
1700      * for you with a MIME type of "*&#47;*".  This allows such callers to benefit
1701      * from any built-in data conversion that a provider implements.
1702      *
1703      * @param uri The desired URI to open.
1704      * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
1705      * ContentProvider.openAssetFile}.
1706      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1707      * provider recently crashed. You own this descriptor and are responsible for closing it
1708      * when done.
1709      * @throws FileNotFoundException Throws FileNotFoundException of no
1710      * file exists under the URI or the mode is invalid.
1711      */
1712     public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
1713             @NonNull String mode) throws FileNotFoundException {
1714         return openAssetFileDescriptor(uri, mode, null);
1715     }
1716 
1717     /**
1718      * Open a raw file descriptor to access data under a URI.  This
1719      * interacts with the underlying {@link ContentProvider#openAssetFile}
1720      * method of the provider associated with the given URI, to retrieve any file stored there.
1721      *
1722      * <h5>Accepts the following URI schemes:</h5>
1723      * <ul>
1724      * <li>content ({@link #SCHEME_CONTENT})</li>
1725      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
1726      * <li>file ({@link #SCHEME_FILE})</li>
1727      * </ul>
1728      * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
1729      * <p>
1730      * A Uri object can be used to reference a resource in an APK file.  The
1731      * Uri should be one of the following formats:
1732      * <ul>
1733      * <li><code>android.resource://package_name/id_number</code><br/>
1734      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1735      * For example <code>com.example.myapp</code><br/>
1736      * <code>id_number</code> is the int form of the ID.<br/>
1737      * The easiest way to construct this form is
1738      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
1739      * </li>
1740      * <li><code>android.resource://package_name/type/name</code><br/>
1741      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1742      * For example <code>com.example.myapp</code><br/>
1743      * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
1744      * or <code>drawable</code>.
1745      * <code>name</code> is the string form of the resource name.  That is, whatever the file
1746      * name was in your res directory, without the type extension.
1747      * The easiest way to construct this form is
1748      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
1749      * </li>
1750      * </ul>
1751      *
1752      * <p>Note that if this function is called for read-only input (mode is "r")
1753      * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
1754      * for you with a MIME type of "*&#47;*".  This allows such callers to benefit
1755      * from any built-in data conversion that a provider implements.
1756      *
1757      * @param uri The desired URI to open.
1758      * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
1759      * ContentProvider.openAssetFile}.
1760      * @param cancellationSignal A signal to cancel the operation in progress, or null if
1761      *            none. If the operation is canceled, then
1762      *            {@link OperationCanceledException} will be thrown.
1763      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1764      * provider recently crashed. You own this descriptor and are responsible for closing it
1765      * when done.
1766      * @throws FileNotFoundException Throws FileNotFoundException of no
1767      * file exists under the URI or the mode is invalid.
1768      */
1769     public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
1770             @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
1771                     throws FileNotFoundException {
1772         Objects.requireNonNull(uri, "uri");
1773         Objects.requireNonNull(mode, "mode");
1774 
1775         try {
1776             if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, cancellationSignal);
1777         } catch (RemoteException e) {
1778             return null;
1779         }
1780 
1781         String scheme = uri.getScheme();
1782         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
1783             if (!"r".equals(mode)) {
1784                 throw new FileNotFoundException("Can't write resources: " + uri);
1785             }
1786             OpenResourceIdResult r = getResourceId(uri);
1787             try {
1788                 return r.r.openRawResourceFd(r.id);
1789             } catch (Resources.NotFoundException ex) {
1790                 throw new FileNotFoundException("Resource does not exist: " + uri);
1791             }
1792         } else if (SCHEME_FILE.equals(scheme)) {
1793             ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
1794                     new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode));
1795             return new AssetFileDescriptor(pfd, 0, -1);
1796         } else {
1797             if ("r".equals(mode)) {
1798                 return openTypedAssetFileDescriptor(uri, "*/*", null, cancellationSignal);
1799             } else {
1800                 IContentProvider unstableProvider = acquireUnstableProvider(uri);
1801                 if (unstableProvider == null) {
1802                     throw new FileNotFoundException("No content provider: " + uri);
1803                 }
1804                 IContentProvider stableProvider = null;
1805                 AssetFileDescriptor fd = null;
1806 
1807                 try {
1808                     ICancellationSignal remoteCancellationSignal = null;
1809                     if (cancellationSignal != null) {
1810                         cancellationSignal.throwIfCanceled();
1811                         remoteCancellationSignal = unstableProvider.createCancellationSignal();
1812                         cancellationSignal.setRemote(remoteCancellationSignal);
1813                     }
1814 
1815                     try {
1816                         fd = unstableProvider.openAssetFile(
1817                                 mPackageName, mAttributionTag, uri, mode,
1818                                 remoteCancellationSignal);
1819                         if (fd == null) {
1820                             // The provider will be released by the finally{} clause
1821                             return null;
1822                         }
1823                     } catch (DeadObjectException e) {
1824                         // The remote process has died...  but we only hold an unstable
1825                         // reference though, so we might recover!!!  Let's try!!!!
1826                         // This is exciting!!1!!1!!!!1
1827                         unstableProviderDied(unstableProvider);
1828                         stableProvider = acquireProvider(uri);
1829                         if (stableProvider == null) {
1830                             throw new FileNotFoundException("No content provider: " + uri);
1831                         }
1832                         fd = stableProvider.openAssetFile(
1833                                 mPackageName, mAttributionTag, uri, mode, remoteCancellationSignal);
1834                         if (fd == null) {
1835                             // The provider will be released by the finally{} clause
1836                             return null;
1837                         }
1838                     }
1839 
1840                     if (stableProvider == null) {
1841                         stableProvider = acquireProvider(uri);
1842                     }
1843                     releaseUnstableProvider(unstableProvider);
1844                     unstableProvider = null;
1845                     ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
1846                             fd.getParcelFileDescriptor(), stableProvider);
1847 
1848                     // Success!  Don't release the provider when exiting, let
1849                     // ParcelFileDescriptorInner do that when it is closed.
1850                     stableProvider = null;
1851 
1852                     return new AssetFileDescriptor(pfd, fd.getStartOffset(),
1853                             fd.getDeclaredLength());
1854 
1855                 } catch (RemoteException e) {
1856                     // Whatever, whatever, we'll go away.
1857                     throw new FileNotFoundException(
1858                             "Failed opening content provider: " + uri);
1859                 } catch (FileNotFoundException e) {
1860                     throw e;
1861                 } finally {
1862                     if (cancellationSignal != null) {
1863                         cancellationSignal.setRemote(null);
1864                     }
1865                     if (stableProvider != null) {
1866                         releaseProvider(stableProvider);
1867                     }
1868                     if (unstableProvider != null) {
1869                         releaseUnstableProvider(unstableProvider);
1870                     }
1871                 }
1872             }
1873         }
1874     }
1875 
1876     @Override
1877     public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
1878             @NonNull String mimeTypeFilter, @Nullable Bundle opts,
1879             @Nullable CancellationSignal signal) throws FileNotFoundException {
1880         try {
1881             if (mWrapped != null) {
1882                 return mWrapped.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
1883             }
1884         } catch (RemoteException e) {
1885             return null;
1886         }
1887 
1888         return openTypedAssetFileDescriptor(uri, mimeTypeFilter, opts, signal);
1889     }
1890 
1891     /**
1892      * Open a raw file descriptor to access (potentially type transformed)
1893      * data from a "content:" URI.  This interacts with the underlying
1894      * {@link ContentProvider#openTypedAssetFile} method of the provider
1895      * associated with the given URI, to retrieve retrieve any appropriate
1896      * data stream for the data stored there.
1897      *
1898      * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
1899      * with "content:" URIs, because content providers are the only facility
1900      * with an associated MIME type to ensure that the returned data stream
1901      * is of the desired type.
1902      *
1903      * <p>All text/* streams are encoded in UTF-8.
1904      *
1905      * @param uri The desired URI to open.
1906      * @param mimeType The desired MIME type of the returned data.  This can
1907      * be a pattern such as *&#47;*, which will allow the content provider to
1908      * select a type, though there is no way for you to determine what type
1909      * it is returning.
1910      * @param opts Additional provider-dependent options.
1911      * @return Returns a new ParcelFileDescriptor from which you can read the
1912      * data stream from the provider or {@code null} if the provider recently crashed.
1913      * Note that this may be a pipe, meaning you can't seek in it.  The only seek you
1914      * should do is if the AssetFileDescriptor contains an offset, to move to that offset before
1915      * reading.  You own this descriptor and are responsible for closing it when done.
1916      * @throws FileNotFoundException Throws FileNotFoundException of no
1917      * data of the desired type exists under the URI.
1918      */
1919     public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
1920             @NonNull String mimeType, @Nullable Bundle opts) throws FileNotFoundException {
1921         return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
1922     }
1923 
1924     /**
1925      * Open a raw file descriptor to access (potentially type transformed)
1926      * data from a "content:" URI.  This interacts with the underlying
1927      * {@link ContentProvider#openTypedAssetFile} method of the provider
1928      * associated with the given URI, to retrieve retrieve any appropriate
1929      * data stream for the data stored there.
1930      *
1931      * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
1932      * with "content:" URIs, because content providers are the only facility
1933      * with an associated MIME type to ensure that the returned data stream
1934      * is of the desired type.
1935      *
1936      * <p>All text/* streams are encoded in UTF-8.
1937      *
1938      * @param uri The desired URI to open.
1939      * @param mimeType The desired MIME type of the returned data.  This can
1940      * be a pattern such as *&#47;*, which will allow the content provider to
1941      * select a type, though there is no way for you to determine what type
1942      * it is returning.
1943      * @param opts Additional provider-dependent options.
1944      * @param cancellationSignal A signal to cancel the operation in progress,
1945      *         or null if none. If the operation is canceled, then
1946      *         {@link OperationCanceledException} will be thrown.
1947      * @return Returns a new ParcelFileDescriptor from which you can read the
1948      * data stream from the provider or {@code null} if the provider recently crashed.
1949      * Note that this may be a pipe, meaning you can't seek in it.  The only seek you
1950      * should do is if the AssetFileDescriptor contains an offset, to move to that offset before
1951      * reading.  You own this descriptor and are responsible for closing it when done.
1952      * @throws FileNotFoundException Throws FileNotFoundException of no
1953      * data of the desired type exists under the URI.
1954      */
1955     public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
1956             @NonNull String mimeType, @Nullable Bundle opts,
1957             @Nullable CancellationSignal cancellationSignal) throws FileNotFoundException {
1958         Objects.requireNonNull(uri, "uri");
1959         Objects.requireNonNull(mimeType, "mimeType");
1960 
1961         try {
1962             if (mWrapped != null) return mWrapped.openTypedAssetFile(uri, mimeType, opts, cancellationSignal);
1963         } catch (RemoteException e) {
1964             return null;
1965         }
1966 
1967         IContentProvider unstableProvider = acquireUnstableProvider(uri);
1968         if (unstableProvider == null) {
1969             throw new FileNotFoundException("No content provider: " + uri);
1970         }
1971         IContentProvider stableProvider = null;
1972         AssetFileDescriptor fd = null;
1973 
1974         try {
1975             ICancellationSignal remoteCancellationSignal = null;
1976             if (cancellationSignal != null) {
1977                 cancellationSignal.throwIfCanceled();
1978                 remoteCancellationSignal = unstableProvider.createCancellationSignal();
1979                 cancellationSignal.setRemote(remoteCancellationSignal);
1980             }
1981 
1982             try {
1983                 fd = unstableProvider.openTypedAssetFile(
1984                         mPackageName, mAttributionTag, uri, mimeType, opts,
1985                         remoteCancellationSignal);
1986                 if (fd == null) {
1987                     // The provider will be released by the finally{} clause
1988                     return null;
1989                 }
1990             } catch (DeadObjectException e) {
1991                 // The remote process has died...  but we only hold an unstable
1992                 // reference though, so we might recover!!!  Let's try!!!!
1993                 // This is exciting!!1!!1!!!!1
1994                 unstableProviderDied(unstableProvider);
1995                 stableProvider = acquireProvider(uri);
1996                 if (stableProvider == null) {
1997                     throw new FileNotFoundException("No content provider: " + uri);
1998                 }
1999                 fd = stableProvider.openTypedAssetFile(
2000                         mPackageName, mAttributionTag, uri, mimeType, opts,
2001                         remoteCancellationSignal);
2002                 if (fd == null) {
2003                     // The provider will be released by the finally{} clause
2004                     return null;
2005                 }
2006             }
2007 
2008             if (stableProvider == null) {
2009                 stableProvider = acquireProvider(uri);
2010             }
2011             releaseUnstableProvider(unstableProvider);
2012             unstableProvider = null;
2013             ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
2014                     fd.getParcelFileDescriptor(), stableProvider);
2015 
2016             // Success!  Don't release the provider when exiting, let
2017             // ParcelFileDescriptorInner do that when it is closed.
2018             stableProvider = null;
2019 
2020             return new AssetFileDescriptor(pfd, fd.getStartOffset(),
2021                     fd.getDeclaredLength(), fd.getExtras());
2022 
2023         } catch (RemoteException e) {
2024             // Whatever, whatever, we'll go away.
2025             throw new FileNotFoundException(
2026                     "Failed opening content provider: " + uri);
2027         } catch (FileNotFoundException e) {
2028             throw e;
2029         } finally {
2030             if (cancellationSignal != null) {
2031                 cancellationSignal.setRemote(null);
2032             }
2033             if (stableProvider != null) {
2034                 releaseProvider(stableProvider);
2035             }
2036             if (unstableProvider != null) {
2037                 releaseUnstableProvider(unstableProvider);
2038             }
2039         }
2040     }
2041 
2042     /**
2043      * A resource identified by the {@link Resources} that contains it, and a resource id.
2044      *
2045      * @hide
2046      */
2047     public class OpenResourceIdResult {
2048         @UnsupportedAppUsage
2049         public Resources r;
2050         @UnsupportedAppUsage
2051         public int id;
2052     }
2053 
2054     /**
2055      * Resolves an android.resource URI to a {@link Resources} and a resource id.
2056      *
2057      * @hide
2058      */
2059     @UnsupportedAppUsage
2060     public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
2061         String authority = uri.getAuthority();
2062         Resources r;
2063         if (TextUtils.isEmpty(authority)) {
2064             throw new FileNotFoundException("No authority: " + uri);
2065         } else {
2066             try {
2067                 r = mContext.getPackageManager().getResourcesForApplication(authority);
2068             } catch (NameNotFoundException ex) {
2069                 throw new FileNotFoundException("No package found for authority: " + uri);
2070             }
2071         }
2072         List<String> path = uri.getPathSegments();
2073         if (path == null) {
2074             throw new FileNotFoundException("No path: " + uri);
2075         }
2076         int len = path.size();
2077         int id;
2078         if (len == 1) {
2079             try {
2080                 id = Integer.parseInt(path.get(0));
2081             } catch (NumberFormatException e) {
2082                 throw new FileNotFoundException("Single path segment is not a resource ID: " + uri);
2083             }
2084         } else if (len == 2) {
2085             id = r.getIdentifier(path.get(1), path.get(0), authority);
2086         } else {
2087             throw new FileNotFoundException("More than two path segments: " + uri);
2088         }
2089         if (id == 0) {
2090             throw new FileNotFoundException("No resource found for: " + uri);
2091         }
2092         OpenResourceIdResult res = new OpenResourceIdResult();
2093         res.r = r;
2094         res.id = id;
2095         return res;
2096     }
2097 
2098     /**
2099      * Inserts a row into a table at the given URL.
2100      *
2101      * If the content provider supports transactions the insertion will be atomic.
2102      *
2103      * @param url The URL of the table to insert into.
2104      * @param values The initial values for the newly inserted row. The key is the column name for
2105      *               the field. Passing an empty ContentValues will create an empty row.
2106      * @return the URL of the newly created row. May return <code>null</code> if the underlying
2107      *         content provider returns <code>null</code>, or if it crashes.
2108      */
2109     public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
2110                 @Nullable ContentValues values) {
2111         return insert(url, values, null);
2112     }
2113 
2114     /**
2115      * Inserts a row into a table at the given URL.
2116      *
2117      * If the content provider supports transactions the insertion will be atomic.
2118      *
2119      * @param url The URL of the table to insert into.
2120      * @param values The initial values for the newly inserted row. The key is the column name for
2121      *               the field. Passing an empty ContentValues will create an empty row.
2122      * @param extras A Bundle containing additional information necessary for
2123      *            the operation. Arguments may include SQL style arguments, such
2124      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
2125      *            the documentation for each individual provider will indicate
2126      *            which arguments they support.
2127      * @return the URL of the newly created row. May return <code>null</code> if the underlying
2128      *         content provider returns <code>null</code>, or if it crashes.
2129      * @throws IllegalArgumentException if the provider doesn't support one of
2130      *             the requested Bundle arguments.
2131      */
2132     @Override
2133     public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
2134             @Nullable ContentValues values, @Nullable Bundle extras) {
2135         Objects.requireNonNull(url, "url");
2136 
2137         try {
2138             if (mWrapped != null) return mWrapped.insert(url, values, extras);
2139         } catch (RemoteException e) {
2140             return null;
2141         }
2142 
2143         IContentProvider provider = acquireProvider(url);
2144         if (provider == null) {
2145             throw new IllegalArgumentException("Unknown URL " + url);
2146         }
2147         try {
2148             long startTime = SystemClock.uptimeMillis();
2149             Uri createdRow = provider.insert(mPackageName, mAttributionTag, url, values, extras);
2150             long durationMillis = SystemClock.uptimeMillis() - startTime;
2151             maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
2152             return createdRow;
2153         } catch (RemoteException e) {
2154             // Arbitrary and not worth documenting, as Activity
2155             // Manager will kill this process shortly anyway.
2156             return null;
2157         } finally {
2158             releaseProvider(provider);
2159         }
2160     }
2161 
2162     /**
2163      * Applies each of the {@link ContentProviderOperation} objects and returns an array
2164      * of their results. Passes through OperationApplicationException, which may be thrown
2165      * by the call to {@link ContentProviderOperation#apply}.
2166      * If all the applications succeed then a {@link ContentProviderResult} array with the
2167      * same number of elements as the operations will be returned. It is implementation-specific
2168      * how many, if any, operations will have been successfully applied if a call to
2169      * apply results in a {@link OperationApplicationException}.
2170      * @param authority the authority of the ContentProvider to which this batch should be applied
2171      * @param operations the operations to apply
2172      * @return the results of the applications
2173      * @throws OperationApplicationException thrown if an application fails.
2174      * See {@link ContentProviderOperation#apply} for more information.
2175      * @throws RemoteException thrown if a RemoteException is encountered while attempting
2176      *   to communicate with a remote provider.
2177      */
2178     @Override
2179     public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
2180             @NonNull ArrayList<ContentProviderOperation> operations)
2181                     throws RemoteException, OperationApplicationException {
2182         Objects.requireNonNull(authority, "authority");
2183         Objects.requireNonNull(operations, "operations");
2184 
2185         try {
2186             if (mWrapped != null) return mWrapped.applyBatch(authority, operations);
2187         } catch (RemoteException e) {
2188             return null;
2189         }
2190 
2191         ContentProviderClient provider = acquireContentProviderClient(authority);
2192         if (provider == null) {
2193             throw new IllegalArgumentException("Unknown authority " + authority);
2194         }
2195         try {
2196             return provider.applyBatch(operations);
2197         } finally {
2198             provider.release();
2199         }
2200     }
2201 
2202     /**
2203      * Inserts multiple rows into a table at the given URL.
2204      *
2205      * This function make no guarantees about the atomicity of the insertions.
2206      *
2207      * @param url The URL of the table to insert into.
2208      * @param values The initial values for the newly inserted rows. The key is the column name for
2209      *               the field. Passing null will create an empty row.
2210      * @return the number of newly created rows.
2211      */
2212     @Override
2213     public final int bulkInsert(@RequiresPermission.Write @NonNull Uri url,
2214                 @NonNull ContentValues[] values) {
2215         Objects.requireNonNull(url, "url");
2216         Objects.requireNonNull(values, "values");
2217 
2218         try {
2219             if (mWrapped != null) return mWrapped.bulkInsert(url, values);
2220         } catch (RemoteException e) {
2221             return 0;
2222         }
2223 
2224         IContentProvider provider = acquireProvider(url);
2225         if (provider == null) {
2226             throw new IllegalArgumentException("Unknown URL " + url);
2227         }
2228         try {
2229             long startTime = SystemClock.uptimeMillis();
2230             int rowsCreated = provider.bulkInsert(mPackageName, mAttributionTag, url, values);
2231             long durationMillis = SystemClock.uptimeMillis() - startTime;
2232             maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
2233             return rowsCreated;
2234         } catch (RemoteException e) {
2235             // Arbitrary and not worth documenting, as Activity
2236             // Manager will kill this process shortly anyway.
2237             return 0;
2238         } finally {
2239             releaseProvider(provider);
2240         }
2241     }
2242 
2243     /**
2244      * Deletes row(s) specified by a content URI.
2245      *
2246      * If the content provider supports transactions, the deletion will be atomic.
2247      *
2248      * @param url The URL of the row to delete.
2249      * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause
2250                     (excluding the WHERE itself).
2251      * @return The number of rows deleted.
2252      */
2253     public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where,
2254             @Nullable String[] selectionArgs) {
2255         return delete(url, createSqlQueryBundle(where, selectionArgs));
2256     }
2257 
2258     /**
2259      * Deletes row(s) specified by a content URI.
2260      *
2261      * If the content provider supports transactions, the deletion will be atomic.
2262      *
2263      * @param url The URL of the row to delete.
2264      * @param extras A Bundle containing additional information necessary for
2265      *            the operation. Arguments may include SQL style arguments, such
2266      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
2267      *            the documentation for each individual provider will indicate
2268      *            which arguments they support.
2269      * @return The number of rows deleted.
2270      * @throws IllegalArgumentException if the provider doesn't support one of
2271      *             the requested Bundle arguments.
2272      */
2273     @Override
2274     public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) {
2275         Objects.requireNonNull(url, "url");
2276 
2277         try {
2278             if (mWrapped != null) return mWrapped.delete(url, extras);
2279         } catch (RemoteException e) {
2280             return 0;
2281         }
2282 
2283         IContentProvider provider = acquireProvider(url);
2284         if (provider == null) {
2285             throw new IllegalArgumentException("Unknown URL " + url);
2286         }
2287         try {
2288             long startTime = SystemClock.uptimeMillis();
2289             int rowsDeleted = provider.delete(mPackageName, mAttributionTag, url, extras);
2290             long durationMillis = SystemClock.uptimeMillis() - startTime;
2291             maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
2292             return rowsDeleted;
2293         } catch (RemoteException e) {
2294             // Arbitrary and not worth documenting, as Activity
2295             // Manager will kill this process shortly anyway.
2296             return -1;
2297         } finally {
2298             releaseProvider(provider);
2299         }
2300     }
2301 
2302     /**
2303      * Update row(s) in a content URI.
2304      *
2305      * If the content provider supports transactions the update will be atomic.
2306      *
2307      * @param uri The URI to modify.
2308      * @param values The new field values. The key is the column name for the field.
2309                      A null value will remove an existing field value.
2310      * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause
2311                     (excluding the WHERE itself).
2312      * @return the number of rows updated.
2313      * @throws NullPointerException if uri or values are null
2314      */
2315     public final int update(@RequiresPermission.Write @NonNull Uri uri,
2316             @Nullable ContentValues values, @Nullable String where,
2317             @Nullable String[] selectionArgs) {
2318         return update(uri, values, createSqlQueryBundle(where, selectionArgs));
2319     }
2320 
2321     /**
2322      * Update row(s) in a content URI.
2323      *
2324      * If the content provider supports transactions the update will be atomic.
2325      *
2326      * @param uri The URI to modify.
2327      * @param values The new field values. The key is the column name for the field.
2328                      A null value will remove an existing field value.
2329      * @param extras A Bundle containing additional information necessary for
2330      *            the operation. Arguments may include SQL style arguments, such
2331      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
2332      *            the documentation for each individual provider will indicate
2333      *            which arguments they support.
2334      * @return the number of rows updated.
2335      * @throws NullPointerException if uri or values are null
2336      * @throws IllegalArgumentException if the provider doesn't support one of
2337      *             the requested Bundle arguments.
2338      */
2339     @Override
2340     public final int update(@RequiresPermission.Write @NonNull Uri uri,
2341             @Nullable ContentValues values, @Nullable Bundle extras) {
2342         Objects.requireNonNull(uri, "uri");
2343 
2344         try {
2345             if (mWrapped != null) return mWrapped.update(uri, values, extras);
2346         } catch (RemoteException e) {
2347             return 0;
2348         }
2349 
2350         IContentProvider provider = acquireProvider(uri);
2351         if (provider == null) {
2352             throw new IllegalArgumentException("Unknown URI " + uri);
2353         }
2354         try {
2355             long startTime = SystemClock.uptimeMillis();
2356             int rowsUpdated = provider.update(mPackageName, mAttributionTag, uri, values, extras);
2357             long durationMillis = SystemClock.uptimeMillis() - startTime;
2358             maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
2359             return rowsUpdated;
2360         } catch (RemoteException e) {
2361             // Arbitrary and not worth documenting, as Activity
2362             // Manager will kill this process shortly anyway.
2363             return -1;
2364         } finally {
2365             releaseProvider(provider);
2366         }
2367     }
2368 
2369     /**
2370      * Call a provider-defined method.  This can be used to implement
2371      * read or write interfaces which are cheaper than using a Cursor and/or
2372      * do not fit into the traditional table model.
2373      *
2374      * @param method provider-defined method name to call.  Opaque to
2375      *   framework, but must be non-null.
2376      * @param arg provider-defined String argument.  May be null.
2377      * @param extras provider-defined Bundle argument.  May be null.
2378      * @return a result Bundle, possibly null.  Will be null if the ContentProvider
2379      *   does not implement call.
2380      * @throws NullPointerException if uri or method is null
2381      * @throws IllegalArgumentException if uri is not known
2382      */
2383     public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
2384             @Nullable String arg, @Nullable Bundle extras) {
2385         return call(uri.getAuthority(), method, arg, extras);
2386     }
2387 
2388     @Override
2389     public final @Nullable Bundle call(@NonNull String authority, @NonNull String method,
2390             @Nullable String arg, @Nullable Bundle extras) {
2391         Objects.requireNonNull(authority, "authority");
2392         Objects.requireNonNull(method, "method");
2393 
2394         try {
2395             if (mWrapped != null) return mWrapped.call(authority, method, arg, extras);
2396         } catch (RemoteException e) {
2397             return null;
2398         }
2399 
2400         IContentProvider provider = acquireProvider(authority);
2401         if (provider == null) {
2402             throw new IllegalArgumentException("Unknown authority " + authority);
2403         }
2404         try {
2405             final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg,
2406                     extras);
2407             Bundle.setDefusable(res, true);
2408             return res;
2409         } catch (RemoteException e) {
2410             // Arbitrary and not worth documenting, as Activity
2411             // Manager will kill this process shortly anyway.
2412             return null;
2413         } finally {
2414             releaseProvider(provider);
2415         }
2416     }
2417 
2418     /**
2419      * Returns the content provider for the given content URI.
2420      *
2421      * @param uri The URI to a content provider
2422      * @return The ContentProvider for the given URI, or null if no content provider is found.
2423      * @hide
2424      */
2425     @UnsupportedAppUsage
2426     public final IContentProvider acquireProvider(Uri uri) {
2427         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
2428             return null;
2429         }
2430         final String auth = uri.getAuthority();
2431         if (auth != null) {
2432             return acquireProvider(mContext, auth);
2433         }
2434         return null;
2435     }
2436 
2437     /**
2438      * Returns the content provider for the given content URI if the process
2439      * already has a reference on it.
2440      *
2441      * @param uri The URI to a content provider
2442      * @return The ContentProvider for the given URI, or null if no content provider is found.
2443      * @hide
2444      */
2445     @UnsupportedAppUsage
2446     public final IContentProvider acquireExistingProvider(Uri uri) {
2447         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
2448             return null;
2449         }
2450         final String auth = uri.getAuthority();
2451         if (auth != null) {
2452             return acquireExistingProvider(mContext, auth);
2453         }
2454         return null;
2455     }
2456 
2457     /**
2458      * @hide
2459      */
2460     @UnsupportedAppUsage
2461     public final IContentProvider acquireProvider(String name) {
2462         if (name == null) {
2463             return null;
2464         }
2465         return acquireProvider(mContext, name);
2466     }
2467 
2468     /**
2469      * Returns the content provider for the given content URI.
2470      *
2471      * @param uri The URI to a content provider
2472      * @return The ContentProvider for the given URI, or null if no content provider is found.
2473      * @hide
2474      */
2475     public final IContentProvider acquireUnstableProvider(Uri uri) {
2476         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
2477             return null;
2478         }
2479         String auth = uri.getAuthority();
2480         if (auth != null) {
2481             return acquireUnstableProvider(mContext, uri.getAuthority());
2482         }
2483         return null;
2484     }
2485 
2486     /**
2487      * @hide
2488      */
2489     @UnsupportedAppUsage
2490     public final IContentProvider acquireUnstableProvider(String name) {
2491         if (name == null) {
2492             return null;
2493         }
2494         return acquireUnstableProvider(mContext, name);
2495     }
2496 
2497     /**
2498      * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2499      * that services the content at uri, starting the provider if necessary. Returns
2500      * null if there is no provider associated wih the uri. The caller must indicate that they are
2501      * done with the provider by calling {@link ContentProviderClient#release} which will allow
2502      * the system to release the provider if it determines that there is no other reason for
2503      * keeping it active.
2504      * @param uri specifies which provider should be acquired
2505      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2506      * that services the content at uri or null if there isn't one.
2507      */
2508     public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) {
2509         Objects.requireNonNull(uri, "uri");
2510         IContentProvider provider = acquireProvider(uri);
2511         if (provider != null) {
2512             return new ContentProviderClient(this, provider, uri.getAuthority(), true);
2513         }
2514         return null;
2515     }
2516 
2517     /**
2518      * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2519      * with the authority of name, starting the provider if necessary. Returns
2520      * null if there is no provider associated wih the uri. The caller must indicate that they are
2521      * done with the provider by calling {@link ContentProviderClient#release} which will allow
2522      * the system to release the provider if it determines that there is no other reason for
2523      * keeping it active.
2524      * @param name specifies which provider should be acquired
2525      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2526      * with the authority of name or null if there isn't one.
2527      */
2528     public final @Nullable ContentProviderClient acquireContentProviderClient(
2529             @NonNull String name) {
2530         Objects.requireNonNull(name, "name");
2531         IContentProvider provider = acquireProvider(name);
2532         if (provider != null) {
2533             return new ContentProviderClient(this, provider, name, true);
2534         }
2535 
2536         return null;
2537     }
2538 
2539     /**
2540      * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do
2541      * not trust the stability of the target content provider.  This turns off
2542      * the mechanism in the platform clean up processes that are dependent on
2543      * a content provider if that content provider's process goes away.  Normally
2544      * you can safely assume that once you have acquired a provider, you can freely
2545      * use it as needed and it won't disappear, even if your process is in the
2546      * background.  If using this method, you need to take care to deal with any
2547      * failures when communicating with the provider, and be sure to close it
2548      * so that it can be re-opened later.  In particular, catching a
2549      * {@link android.os.DeadObjectException} from the calls there will let you
2550      * know that the content provider has gone away; at that point the current
2551      * ContentProviderClient object is invalid, and you should release it.  You
2552      * can acquire a new one if you would like to try to restart the provider
2553      * and perform new operations on it.
2554      */
2555     public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
2556             @NonNull Uri uri) {
2557         Objects.requireNonNull(uri, "uri");
2558         IContentProvider provider = acquireUnstableProvider(uri);
2559         if (provider != null) {
2560             return new ContentProviderClient(this, provider, uri.getAuthority(), false);
2561         }
2562 
2563         return null;
2564     }
2565 
2566     /**
2567      * Like {@link #acquireContentProviderClient(String)}, but for use when you do
2568      * not trust the stability of the target content provider.  This turns off
2569      * the mechanism in the platform clean up processes that are dependent on
2570      * a content provider if that content provider's process goes away.  Normally
2571      * you can safely assume that once you have acquired a provider, you can freely
2572      * use it as needed and it won't disappear, even if your process is in the
2573      * background.  If using this method, you need to take care to deal with any
2574      * failures when communicating with the provider, and be sure to close it
2575      * so that it can be re-opened later.  In particular, catching a
2576      * {@link android.os.DeadObjectException} from the calls there will let you
2577      * know that the content provider has gone away; at that point the current
2578      * ContentProviderClient object is invalid, and you should release it.  You
2579      * can acquire a new one if you would like to try to restart the provider
2580      * and perform new operations on it.
2581      */
2582     public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
2583             @NonNull String name) {
2584         Objects.requireNonNull(name, "name");
2585         IContentProvider provider = acquireUnstableProvider(name);
2586         if (provider != null) {
2587             return new ContentProviderClient(this, provider, name, false);
2588         }
2589 
2590         return null;
2591     }
2592 
2593     /**
2594      * Register an observer class that gets callbacks when data identified by a
2595      * given content URI changes.
2596      * <p>
2597      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2598      * notifications must be backed by a valid {@link ContentProvider}.
2599      *
2600      * @param uri The URI to watch for changes. This can be a specific row URI,
2601      *            or a base URI for a whole class of content.
2602      * @param notifyForDescendants When false, the observer will be notified
2603      *            whenever a change occurs to the exact URI specified by
2604      *            <code>uri</code> or to one of the URI's ancestors in the path
2605      *            hierarchy. When true, the observer will also be notified
2606      *            whenever a change occurs to the URI's descendants in the path
2607      *            hierarchy.
2608      * @param observer The object that receives callbacks when changes occur.
2609      * @see #unregisterContentObserver
2610      */
2611     public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendants,
2612             @NonNull ContentObserver observer) {
2613         Objects.requireNonNull(uri, "uri");
2614         Objects.requireNonNull(observer, "observer");
2615         registerContentObserver(
2616                 ContentProvider.getUriWithoutUserId(uri),
2617                 notifyForDescendants,
2618                 observer,
2619                 ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
2620     }
2621 
2622     /** @hide - designated user version */
2623     @UnsupportedAppUsage
2624     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
2625             ContentObserver observer, @UserIdInt int userHandle) {
2626         try {
2627             getContentService().registerContentObserver(uri, notifyForDescendents,
2628                     observer.getContentObserver(), userHandle, mTargetSdkVersion);
2629         } catch (RemoteException e) {
2630             throw e.rethrowFromSystemServer();
2631         }
2632     }
2633 
2634     /**
2635      * Unregisters a change observer.
2636      *
2637      * @param observer The previously registered observer that is no longer needed.
2638      * @see #registerContentObserver
2639      */
2640     public final void unregisterContentObserver(@NonNull ContentObserver observer) {
2641         Objects.requireNonNull(observer, "observer");
2642         try {
2643             IContentObserver contentObserver = observer.releaseContentObserver();
2644             if (contentObserver != null) {
2645                 getContentService().unregisterContentObserver(
2646                         contentObserver);
2647             }
2648         } catch (RemoteException e) {
2649             throw e.rethrowFromSystemServer();
2650         }
2651     }
2652 
2653     /**
2654      * Notify registered observers that a row was updated and attempt to sync
2655      * changes to the network.
2656      * <p>
2657      * To observe events sent through this call, use
2658      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2659      * <p>
2660      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2661      * notifications must be backed by a valid {@link ContentProvider}.
2662      *
2663      * @param uri The uri of the content that was changed.
2664      * @param observer The observer that originated the change, may be
2665      *            <code>null</null>. The observer that originated the change
2666      *            will only receive the notification if it has requested to
2667      *            receive self-change notifications by implementing
2668      *            {@link ContentObserver#deliverSelfNotifications()} to return
2669      *            true.
2670      */
2671     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
2672         notifyChange(uri, observer, true /* sync to network */);
2673     }
2674 
2675     /**
2676      * Notify registered observers that a row was updated.
2677      * <p>
2678      * To observe events sent through this call, use
2679      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2680      * <p>
2681      * If syncToNetwork is true, this will attempt to schedule a local sync
2682      * using the sync adapter that's registered for the authority of the
2683      * provided uri. No account will be passed to the sync adapter, so all
2684      * matching accounts will be synchronized.
2685      * <p>
2686      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2687      * notifications must be backed by a valid {@link ContentProvider}.
2688      *
2689      * @param uri The uri of the content that was changed.
2690      * @param observer The observer that originated the change, may be
2691      *            <code>null</null>. The observer that originated the change
2692      *            will only receive the notification if it has requested to
2693      *            receive self-change notifications by implementing
2694      *            {@link ContentObserver#deliverSelfNotifications()} to return
2695      *            true.
2696      * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
2697      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
2698      * @deprecated callers should consider migrating to
2699      *             {@link #notifyChange(Uri, ContentObserver, int)}, as it
2700      *             offers support for many more options than just
2701      *             {@link #NOTIFY_SYNC_TO_NETWORK}.
2702      */
2703     @Deprecated
2704     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
2705             boolean syncToNetwork) {
2706         notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0);
2707     }
2708 
2709     /**
2710      * Notify registered observers that a row was updated.
2711      * <p>
2712      * To observe events sent through this call, use
2713      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2714      * <p>
2715      * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule
2716      * a local sync using the sync adapter that's registered for the authority
2717      * of the provided uri. No account will be passed to the sync adapter, so
2718      * all matching accounts will be synchronized.
2719      * <p>
2720      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2721      * notifications must be backed by a valid {@link ContentProvider}.
2722      *
2723      * @param uri The uri of the content that was changed.
2724      * @param observer The observer that originated the change, may be
2725      *            <code>null</null>. The observer that originated the change
2726      *            will only receive the notification if it has requested to
2727      *            receive self-change notifications by implementing
2728      *            {@link ContentObserver#deliverSelfNotifications()} to return
2729      *            true.
2730      * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
2731      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
2732      */
2733     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
2734             @NotifyFlags int flags) {
2735         Objects.requireNonNull(uri, "uri");
2736         notifyChange(
2737                 ContentProvider.getUriWithoutUserId(uri),
2738                 observer,
2739                 flags,
2740                 ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
2741     }
2742 
2743     /** @removed */
2744     @Deprecated
2745     public void notifyChange(@NonNull Iterable<Uri> uris, @Nullable ContentObserver observer,
2746             @NotifyFlags int flags) {
2747         final Collection<Uri> asCollection = new ArrayList<>();
2748         uris.forEach(asCollection::add);
2749         notifyChange(asCollection, observer, flags);
2750     }
2751 
2752     /**
2753      * Notify registered observers that several rows have been updated.
2754      * <p>
2755      * To observe events sent through this call, use
2756      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2757      * <p>
2758      * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule
2759      * a local sync using the sync adapter that's registered for the authority
2760      * of the provided uri. No account will be passed to the sync adapter, so
2761      * all matching accounts will be synchronized.
2762      * <p>
2763      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2764      * notifications must be backed by a valid {@link ContentProvider}.
2765      *
2766      * @param uris The uris of the content that was changed.
2767      * @param observer The observer that originated the change, may be
2768      *            <code>null</null>. The observer that originated the change
2769      *            will only receive the notification if it has requested to
2770      *            receive self-change notifications by implementing
2771      *            {@link ContentObserver#deliverSelfNotifications()} to return
2772      *            true.
2773      * @param flags Flags such as {@link #NOTIFY_SYNC_TO_NETWORK} or
2774      *            {@link #NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS}.
2775      */
2776     public void notifyChange(@NonNull Collection<Uri> uris, @Nullable ContentObserver observer,
2777             @NotifyFlags int flags) {
2778         Objects.requireNonNull(uris, "uris");
2779 
2780         // Cluster based on user ID
2781         final SparseArray<ArrayList<Uri>> clusteredByUser = new SparseArray<>();
2782         for (Uri uri : uris) {
2783             final int userId = ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
2784             ArrayList<Uri> list = clusteredByUser.get(userId);
2785             if (list == null) {
2786                 list = new ArrayList<>();
2787                 clusteredByUser.put(userId, list);
2788             }
2789             list.add(ContentProvider.getUriWithoutUserId(uri));
2790         }
2791 
2792         for (int i = 0; i < clusteredByUser.size(); i++) {
2793             final int userId = clusteredByUser.keyAt(i);
2794             final ArrayList<Uri> list = clusteredByUser.valueAt(i);
2795             notifyChange(list.toArray(new Uri[list.size()]), observer, flags, userId);
2796         }
2797     }
2798 
2799     /**
2800      * Notify registered observers within the designated user(s) that a row was updated.
2801      *
2802      * @deprecated callers should consider migrating to
2803      *             {@link #notifyChange(Uri, ContentObserver, int)}, as it
2804      *             offers support for many more options than just
2805      *             {@link #NOTIFY_SYNC_TO_NETWORK}.
2806      * @hide
2807      */
2808     @Deprecated
2809     public void notifyChange(@NonNull Uri uri, ContentObserver observer, boolean syncToNetwork,
2810             @UserIdInt int userHandle) {
2811         notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0, userHandle);
2812     }
2813 
2814     /** {@hide} */
2815     public void notifyChange(@NonNull Uri uri, ContentObserver observer, @NotifyFlags int flags,
2816             @UserIdInt int userHandle) {
2817         notifyChange(new Uri[] { uri }, observer, flags, userHandle);
2818     }
2819 
2820     /**
2821      * Notify registered observers within the designated user(s) that a row was updated.
2822      *
2823      * @hide
2824      */
2825     public void notifyChange(@NonNull Uri[] uris, ContentObserver observer, @NotifyFlags int flags,
2826             @UserIdInt int userHandle) {
2827         try {
2828             getContentService().notifyChange(
2829                     uris, observer == null ? null : observer.getContentObserver(),
2830                     observer != null && observer.deliverSelfNotifications(), flags,
2831                     userHandle, mTargetSdkVersion, mContext.getPackageName());
2832         } catch (RemoteException e) {
2833             throw e.rethrowFromSystemServer();
2834         }
2835     }
2836 
2837     /**
2838      * Take a persistable URI permission grant that has been offered. Once
2839      * taken, the permission grant will be remembered across device reboots.
2840      * Only URI permissions granted with
2841      * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} can be persisted. If
2842      * the grant has already been persisted, taking it again will touch
2843      * {@link UriPermission#getPersistedTime()}.
2844      *
2845      * @see #getPersistedUriPermissions()
2846      */
2847     public void takePersistableUriPermission(@NonNull Uri uri,
2848             @Intent.AccessUriMode int modeFlags) {
2849         Objects.requireNonNull(uri, "uri");
2850         try {
2851             UriGrantsManager.getService().takePersistableUriPermission(
2852                     ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
2853                     resolveUserId(uri));
2854         } catch (RemoteException e) {
2855             throw e.rethrowFromSystemServer();
2856         }
2857     }
2858 
2859     /**
2860      * @hide
2861      */
2862     @UnsupportedAppUsage
2863     public void takePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri,
2864             @Intent.AccessUriMode int modeFlags) {
2865         Objects.requireNonNull(toPackage, "toPackage");
2866         Objects.requireNonNull(uri, "uri");
2867         try {
2868             UriGrantsManager.getService().takePersistableUriPermission(
2869                     ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage,
2870                     resolveUserId(uri));
2871         } catch (RemoteException e) {
2872             throw e.rethrowFromSystemServer();
2873         }
2874     }
2875 
2876     /**
2877      * Relinquish a persisted URI permission grant. The URI must have been
2878      * previously made persistent with
2879      * {@link #takePersistableUriPermission(Uri, int)}. Any non-persistent
2880      * grants to the calling package will remain intact.
2881      *
2882      * @see #getPersistedUriPermissions()
2883      */
2884     public void releasePersistableUriPermission(@NonNull Uri uri,
2885             @Intent.AccessUriMode int modeFlags) {
2886         Objects.requireNonNull(uri, "uri");
2887         try {
2888             UriGrantsManager.getService().releasePersistableUriPermission(
2889                     ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
2890                     resolveUserId(uri));
2891         } catch (RemoteException e) {
2892             throw e.rethrowFromSystemServer();
2893         }
2894     }
2895 
2896     /**
2897      * Return list of all URI permission grants that have been persisted by the
2898      * calling app. That is, the returned permissions have been granted
2899      * <em>to</em> the calling app. Only persistable grants taken with
2900      * {@link #takePersistableUriPermission(Uri, int)} are returned.
2901      * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked.
2902      *
2903      * @see #takePersistableUriPermission(Uri, int)
2904      * @see #releasePersistableUriPermission(Uri, int)
2905      */
2906     public @NonNull List<UriPermission> getPersistedUriPermissions() {
2907         try {
2908             return UriGrantsManager.getService().getUriPermissions(
2909                     mPackageName, true /* incoming */, true /* persistedOnly */).getList();
2910         } catch (RemoteException e) {
2911             throw e.rethrowFromSystemServer();
2912         }
2913     }
2914 
2915     /**
2916      * Return list of all persisted URI permission grants that are hosted by the
2917      * calling app. That is, the returned permissions have been granted
2918      * <em>from</em> the calling app. Only grants taken with
2919      * {@link #takePersistableUriPermission(Uri, int)} are returned.
2920      * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked.
2921      */
2922     public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
2923         try {
2924             return UriGrantsManager.getService().getUriPermissions(
2925                     mPackageName, false /* incoming */, true /* persistedOnly */).getList();
2926         } catch (RemoteException e) {
2927             throw e.rethrowFromSystemServer();
2928         }
2929     }
2930 
2931     /** @hide */
2932     public @NonNull List<UriPermission> getOutgoingUriPermissions() {
2933         try {
2934             return UriGrantsManager.getService().getUriPermissions(
2935                     mPackageName, false /* incoming */, false /* persistedOnly */).getList();
2936         } catch (RemoteException e) {
2937             throw e.rethrowFromSystemServer();
2938         }
2939     }
2940 
2941     /**
2942      * Start an asynchronous sync operation. If you want to monitor the progress
2943      * of the sync you may register a SyncObserver. Only values of the following
2944      * types may be used in the extras bundle:
2945      * <ul>
2946      * <li>Integer</li>
2947      * <li>Long</li>
2948      * <li>Boolean</li>
2949      * <li>Float</li>
2950      * <li>Double</li>
2951      * <li>String</li>
2952      * <li>Account</li>
2953      * <li>null</li>
2954      * </ul>
2955      *
2956      * @param uri the uri of the provider to sync or null to sync all providers.
2957      * @param extras any extras to pass to the SyncAdapter.
2958      * @deprecated instead use
2959      * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
2960      */
2961     @Deprecated
2962     public void startSync(Uri uri, Bundle extras) {
2963         Account account = null;
2964         if (extras != null) {
2965             String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT);
2966             if (!TextUtils.isEmpty(accountName)) {
2967                 // TODO: No references to Google in AOSP
2968                 account = new Account(accountName, "com.google");
2969             }
2970             extras.remove(SYNC_EXTRAS_ACCOUNT);
2971         }
2972         requestSync(account, uri != null ? uri.getAuthority() : null, extras);
2973     }
2974 
2975     /**
2976      * Start an asynchronous sync operation. If you want to monitor the progress
2977      * of the sync you may register a SyncObserver. Only values of the following
2978      * types may be used in the extras bundle:
2979      * <ul>
2980      * <li>Integer</li>
2981      * <li>Long</li>
2982      * <li>Boolean</li>
2983      * <li>Float</li>
2984      * <li>Double</li>
2985      * <li>String</li>
2986      * <li>Account</li>
2987      * <li>null</li>
2988      * </ul>
2989      *
2990      * @param account which account should be synced
2991      * @param authority which authority should be synced
2992      * @param extras any extras to pass to the SyncAdapter.
2993      */
2994     public static void requestSync(Account account, String authority, Bundle extras) {
2995         requestSyncAsUser(account, authority, UserHandle.myUserId(), extras);
2996     }
2997 
2998     /**
2999      * @see #requestSync(Account, String, Bundle)
3000      * @hide
3001      */
3002     public static void requestSyncAsUser(Account account, String authority, @UserIdInt int userId,
3003             Bundle extras) {
3004         if (extras == null) {
3005             throw new IllegalArgumentException("Must specify extras.");
3006         }
3007         SyncRequest request =
3008             new SyncRequest.Builder()
3009                 .setSyncAdapter(account, authority)
3010                 .setExtras(extras)
3011                 .syncOnce()     // Immediate sync.
3012                 .build();
3013         try {
3014             // Note ActivityThread.currentPackageName() may not be accurate in a shared process
3015             // case, but it's only for debugging.
3016             getContentService().syncAsUser(request, userId, ActivityThread.currentPackageName());
3017         } catch(RemoteException e) {
3018             throw e.rethrowFromSystemServer();
3019         }
3020     }
3021 
3022     /**
3023      * Register a sync with the SyncManager. These requests are built using the
3024      * {@link SyncRequest.Builder}.
3025      */
3026     public static void requestSync(SyncRequest request) {
3027         try {
3028             // Note ActivityThread.currentPackageName() may not be accurate in a shared process
3029             // case, but it's only for debugging.
3030             getContentService().sync(request, ActivityThread.currentPackageName());
3031         } catch(RemoteException e) {
3032             throw e.rethrowFromSystemServer();
3033         }
3034     }
3035 
3036     /**
3037      * Check that only values of the following types are in the Bundle:
3038      * <ul>
3039      * <li>Integer</li>
3040      * <li>Long</li>
3041      * <li>Boolean</li>
3042      * <li>Float</li>
3043      * <li>Double</li>
3044      * <li>String</li>
3045      * <li>Account</li>
3046      * <li>null</li>
3047      * </ul>
3048      * @param extras the Bundle to check
3049      */
3050     public static void validateSyncExtrasBundle(Bundle extras) {
3051         try {
3052             for (String key : extras.keySet()) {
3053                 Object value = extras.get(key);
3054                 if (value == null) continue;
3055                 if (value instanceof Long) continue;
3056                 if (value instanceof Integer) continue;
3057                 if (value instanceof Boolean) continue;
3058                 if (value instanceof Float) continue;
3059                 if (value instanceof Double) continue;
3060                 if (value instanceof String) continue;
3061                 if (value instanceof Account) continue;
3062                 throw new IllegalArgumentException("unexpected value type: "
3063                         + value.getClass().getName());
3064             }
3065         } catch (IllegalArgumentException e) {
3066             throw e;
3067         } catch (RuntimeException exc) {
3068             throw new IllegalArgumentException("error unparceling Bundle", exc);
3069         }
3070     }
3071 
3072     /**
3073      * Cancel any active or pending syncs that match the Uri. If the uri is null then
3074      * all syncs will be canceled.
3075      *
3076      * @param uri the uri of the provider to sync or null to sync all providers.
3077      * @deprecated instead use {@link #cancelSync(android.accounts.Account, String)}
3078      */
3079     @Deprecated
3080     public void cancelSync(Uri uri) {
3081         cancelSync(null /* all accounts */, uri != null ? uri.getAuthority() : null);
3082     }
3083 
3084     /**
3085      * Cancel any active or pending syncs that match account and authority. The account and
3086      * authority can each independently be set to null, which means that syncs with any account
3087      * or authority, respectively, will match.
3088      *
3089      * @param account filters the syncs that match by this account
3090      * @param authority filters the syncs that match by this authority
3091      */
3092     public static void cancelSync(Account account, String authority) {
3093         try {
3094             getContentService().cancelSync(account, authority, null);
3095         } catch (RemoteException e) {
3096             throw e.rethrowFromSystemServer();
3097         }
3098     }
3099 
3100     /**
3101      * @see #cancelSync(Account, String)
3102      * @hide
3103      */
3104     public static void cancelSyncAsUser(Account account, String authority, @UserIdInt int userId) {
3105         try {
3106             getContentService().cancelSyncAsUser(account, authority, null, userId);
3107         } catch (RemoteException e) {
3108             throw e.rethrowFromSystemServer();
3109         }
3110     }
3111 
3112     /**
3113      * Get information about the SyncAdapters that are known to the system.
3114      * @return an array of SyncAdapters that have registered with the system
3115      */
3116     public static SyncAdapterType[] getSyncAdapterTypes() {
3117         try {
3118             return getContentService().getSyncAdapterTypes();
3119         } catch (RemoteException e) {
3120             throw e.rethrowFromSystemServer();
3121         }
3122     }
3123 
3124     /**
3125      * @see #getSyncAdapterTypes()
3126      * @hide
3127      */
3128     public static SyncAdapterType[] getSyncAdapterTypesAsUser(@UserIdInt int userId) {
3129         try {
3130             return getContentService().getSyncAdapterTypesAsUser(userId);
3131         } catch (RemoteException e) {
3132             throw e.rethrowFromSystemServer();
3133         }
3134     }
3135 
3136     /**
3137      * @hide
3138      * Returns the package names of syncadapters that match a given user and authority.
3139      */
3140     @TestApi
3141     public static String[] getSyncAdapterPackagesForAuthorityAsUser(String authority,
3142             @UserIdInt int userId) {
3143         try {
3144             return getContentService().getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
3145         } catch (RemoteException e) {
3146             throw e.rethrowFromSystemServer();
3147         }
3148     }
3149 
3150     /**
3151      * Check if the provider should be synced when a network tickle is received
3152      * <p>This method requires the caller to hold the permission
3153      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3154      *
3155      * @param account the account whose setting we are querying
3156      * @param authority the provider whose setting we are querying
3157      * @return true if the provider should be synced when a network tickle is received
3158      */
3159     public static boolean getSyncAutomatically(Account account, String authority) {
3160         try {
3161             return getContentService().getSyncAutomatically(account, authority);
3162         } catch (RemoteException e) {
3163             throw e.rethrowFromSystemServer();
3164         }
3165     }
3166 
3167     /**
3168      * @see #getSyncAutomatically(Account, String)
3169      * @hide
3170      */
3171     public static boolean getSyncAutomaticallyAsUser(Account account, String authority,
3172             @UserIdInt int userId) {
3173         try {
3174             return getContentService().getSyncAutomaticallyAsUser(account, authority, userId);
3175         } catch (RemoteException e) {
3176             throw e.rethrowFromSystemServer();
3177         }
3178     }
3179 
3180     /**
3181      * Set whether or not the provider is synced when it receives a network tickle.
3182      * <p>This method requires the caller to hold the permission
3183      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3184      *
3185      * @param account the account whose setting we are querying
3186      * @param authority the provider whose behavior is being controlled
3187      * @param sync true if the provider should be synced when tickles are received for it
3188      */
3189     public static void setSyncAutomatically(Account account, String authority, boolean sync) {
3190         setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.myUserId());
3191     }
3192 
3193     /**
3194      * @see #setSyncAutomatically(Account, String, boolean)
3195      * @hide
3196      */
3197     public static void setSyncAutomaticallyAsUser(Account account, String authority, boolean sync,
3198             @UserIdInt int userId) {
3199         try {
3200             getContentService().setSyncAutomaticallyAsUser(account, authority, sync, userId);
3201         } catch (RemoteException e) {
3202             throw e.rethrowFromSystemServer();
3203         }
3204     }
3205 
3206     /**
3207      * Specifies that a sync should be requested with the specified the account, authority,
3208      * and extras at the given frequency. If there is already another periodic sync scheduled
3209      * with the account, authority and extras then a new periodic sync won't be added, instead
3210      * the frequency of the previous one will be updated.
3211      * <p>
3212      * These periodic syncs honor the "syncAutomatically" and "masterSyncAutomatically" settings.
3213      * Although these sync are scheduled at the specified frequency, it may take longer for it to
3214      * actually be started if other syncs are ahead of it in the sync operation queue. This means
3215      * that the actual start time may drift.
3216      * <p>
3217      * Periodic syncs are not allowed to have any of {@link #SYNC_EXTRAS_DO_NOT_RETRY},
3218      * {@link #SYNC_EXTRAS_IGNORE_BACKOFF}, {@link #SYNC_EXTRAS_IGNORE_SETTINGS},
3219      * {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE},
3220      * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL} set to true.
3221      * If any are supplied then an {@link IllegalArgumentException} will be thrown.
3222      *
3223      * <p>This method requires the caller to hold the permission
3224      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3225      * <p>The bundle for a periodic sync can be queried by applications with the correct
3226      * permissions using
3227      * {@link ContentResolver#getPeriodicSyncs(Account account, String provider)}, so no
3228      * sensitive data should be transferred here.
3229      *
3230      * @param account the account to specify in the sync
3231      * @param authority the provider to specify in the sync request
3232      * @param extras extra parameters to go along with the sync request
3233      * @param pollFrequency how frequently the sync should be performed, in seconds.
3234      * On Android API level 24 and above, a minmam interval of 15 minutes is enforced.
3235      * On previous versions, the minimum interval is 1 hour.
3236      * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters
3237      * are null.
3238      */
3239     public static void addPeriodicSync(Account account, String authority, Bundle extras,
3240             long pollFrequency) {
3241         validateSyncExtrasBundle(extras);
3242         if (invalidPeriodicExtras(extras)) {
3243             throw new IllegalArgumentException("illegal extras were set");
3244         }
3245         try {
3246              getContentService().addPeriodicSync(account, authority, extras, pollFrequency);
3247         } catch (RemoteException e) {
3248             throw e.rethrowFromSystemServer();
3249         }
3250     }
3251 
3252     /**
3253      * {@hide}
3254      * Helper function to throw an <code>IllegalArgumentException</code> if any illegal
3255      * extras were set for a periodic sync.
3256      *
3257      * @param extras bundle to validate.
3258      */
3259     public static boolean invalidPeriodicExtras(Bundle extras) {
3260         if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)
3261                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
3262                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)
3263                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
3264                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)
3265                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)
3266                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
3267             return true;
3268         }
3269         return false;
3270     }
3271 
3272     /**
3273      * Remove a periodic sync. Has no affect if account, authority and extras don't match
3274      * an existing periodic sync.
3275      * <p>This method requires the caller to hold the permission
3276      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3277      *
3278      * @param account the account of the periodic sync to remove
3279      * @param authority the provider of the periodic sync to remove
3280      * @param extras the extras of the periodic sync to remove
3281      */
3282     public static void removePeriodicSync(Account account, String authority, Bundle extras) {
3283         validateSyncExtrasBundle(extras);
3284         try {
3285             getContentService().removePeriodicSync(account, authority, extras);
3286         } catch (RemoteException e) {
3287             throw e.rethrowFromSystemServer();
3288         }
3289     }
3290 
3291     /**
3292      * Remove the specified sync. This will cancel any pending or active syncs. If the request is
3293      * for a periodic sync, this call will remove any future occurrences.
3294      * <p>
3295      *     If a periodic sync is specified, the caller must hold the permission
3296      *     {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3297      *</p>
3298      * It is possible to cancel a sync using a SyncRequest object that is not the same object
3299      * with which you requested the sync. Do so by building a SyncRequest with the same
3300      * adapter, frequency, <b>and</b> extras bundle.
3301      *
3302      * @param request SyncRequest object containing information about sync to cancel.
3303      */
3304     public static void cancelSync(SyncRequest request) {
3305         if (request == null) {
3306             throw new IllegalArgumentException("request cannot be null");
3307         }
3308         try {
3309             getContentService().cancelRequest(request);
3310         } catch (RemoteException e) {
3311             throw e.rethrowFromSystemServer();
3312         }
3313     }
3314 
3315     /**
3316      * Get the list of information about the periodic syncs for the given account and authority.
3317      * <p>This method requires the caller to hold the permission
3318      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3319      *
3320      * @param account the account whose periodic syncs we are querying
3321      * @param authority the provider whose periodic syncs we are querying
3322      * @return a list of PeriodicSync objects. This list may be empty but will never be null.
3323      */
3324     public static List<PeriodicSync> getPeriodicSyncs(Account account, String authority) {
3325         try {
3326             return getContentService().getPeriodicSyncs(account, authority, null);
3327         } catch (RemoteException e) {
3328             throw e.rethrowFromSystemServer();
3329         }
3330     }
3331 
3332     /**
3333      * Check if this account/provider is syncable.
3334      * <p>This method requires the caller to hold the permission
3335      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3336      * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
3337      */
3338     public static int getIsSyncable(Account account, String authority) {
3339         try {
3340             return getContentService().getIsSyncable(account, authority);
3341         } catch (RemoteException e) {
3342             throw e.rethrowFromSystemServer();
3343         }
3344     }
3345 
3346     /**
3347      * @see #getIsSyncable(Account, String)
3348      * @hide
3349      */
3350     public static int getIsSyncableAsUser(Account account, String authority,
3351             @UserIdInt int userId) {
3352         try {
3353             return getContentService().getIsSyncableAsUser(account, authority, userId);
3354         } catch (RemoteException e) {
3355             throw e.rethrowFromSystemServer();
3356         }
3357     }
3358 
3359     /**
3360      * Set whether this account/provider is syncable.
3361      * <p>This method requires the caller to hold the permission
3362      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3363      * @param syncable >0 denotes syncable, 0 means not syncable, <0 means unknown
3364      */
3365     public static void setIsSyncable(Account account, String authority, int syncable) {
3366         try {
3367             getContentService().setIsSyncable(account, authority, syncable);
3368         } catch (RemoteException e) {
3369             throw e.rethrowFromSystemServer();
3370         }
3371     }
3372 
3373     /**
3374      * @see #setIsSyncable(Account, String, int)
3375      * @hide
3376      */
3377     public static void setIsSyncableAsUser(Account account, String authority, int syncable,
3378             int userId) {
3379         try {
3380             getContentService().setIsSyncableAsUser(account, authority, syncable, userId);
3381         } catch (RemoteException e) {
3382             throw e.rethrowFromSystemServer();
3383         }
3384     }
3385 
3386     /**
3387      * Gets the master auto-sync setting that applies to all the providers and accounts.
3388      * If this is false then the per-provider auto-sync setting is ignored.
3389      * <p>This method requires the caller to hold the permission
3390      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3391      *
3392      * @return the master auto-sync setting that applies to all the providers and accounts
3393      */
3394     public static boolean getMasterSyncAutomatically() {
3395         try {
3396             return getContentService().getMasterSyncAutomatically();
3397         } catch (RemoteException e) {
3398             throw e.rethrowFromSystemServer();
3399         }
3400     }
3401 
3402     /**
3403      * @see #getMasterSyncAutomatically()
3404      * @hide
3405      */
3406     public static boolean getMasterSyncAutomaticallyAsUser(@UserIdInt int userId) {
3407         try {
3408             return getContentService().getMasterSyncAutomaticallyAsUser(userId);
3409         } catch (RemoteException e) {
3410             throw e.rethrowFromSystemServer();
3411         }
3412     }
3413 
3414     /**
3415      * Sets the master auto-sync setting that applies to all the providers and accounts.
3416      * If this is false then the per-provider auto-sync setting is ignored.
3417      * <p>This method requires the caller to hold the permission
3418      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3419      *
3420      * @param sync the master auto-sync setting that applies to all the providers and accounts
3421      */
3422     public static void setMasterSyncAutomatically(boolean sync) {
3423         setMasterSyncAutomaticallyAsUser(sync, UserHandle.myUserId());
3424     }
3425 
3426     /**
3427      * @see #setMasterSyncAutomatically(boolean)
3428      * @hide
3429      */
3430     public static void setMasterSyncAutomaticallyAsUser(boolean sync, @UserIdInt int userId) {
3431         try {
3432             getContentService().setMasterSyncAutomaticallyAsUser(sync, userId);
3433         } catch (RemoteException e) {
3434             throw e.rethrowFromSystemServer();
3435         }
3436     }
3437 
3438     /**
3439      * Returns true if there is currently a sync operation for the given account or authority
3440      * actively being processed.
3441      * <p>This method requires the caller to hold the permission
3442      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3443      * @param account the account whose setting we are querying
3444      * @param authority the provider whose behavior is being queried
3445      * @return true if a sync is active for the given account or authority.
3446      */
3447     public static boolean isSyncActive(Account account, String authority) {
3448         if (account == null) {
3449             throw new IllegalArgumentException("account must not be null");
3450         }
3451         if (authority == null) {
3452             throw new IllegalArgumentException("authority must not be null");
3453         }
3454 
3455         try {
3456             return getContentService().isSyncActive(account, authority, null);
3457         } catch (RemoteException e) {
3458             throw e.rethrowFromSystemServer();
3459         }
3460     }
3461 
3462     /**
3463      * If a sync is active returns the information about it, otherwise returns null.
3464      * <p>
3465      * This method requires the caller to hold the permission
3466      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3467      * <p>
3468      * @return the SyncInfo for the currently active sync or null if one is not active.
3469      * @deprecated
3470      * Since multiple concurrent syncs are now supported you should use
3471      * {@link #getCurrentSyncs()} to get the accurate list of current syncs.
3472      * This method returns the first item from the list of current syncs
3473      * or null if there are none.
3474      */
3475     @Deprecated
3476     public static SyncInfo getCurrentSync() {
3477         try {
3478             final List<SyncInfo> syncs = getContentService().getCurrentSyncs();
3479             if (syncs.isEmpty()) {
3480                 return null;
3481             }
3482             return syncs.get(0);
3483         } catch (RemoteException e) {
3484             throw e.rethrowFromSystemServer();
3485         }
3486     }
3487 
3488     /**
3489      * Returns a list with information about all the active syncs. This list will be empty
3490      * if there are no active syncs.
3491      * <p>
3492      * This method requires the caller to hold the permission
3493      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3494      * <p>
3495      * @return a List of SyncInfo objects for the currently active syncs.
3496      */
3497     public static List<SyncInfo> getCurrentSyncs() {
3498         try {
3499             return getContentService().getCurrentSyncs();
3500         } catch (RemoteException e) {
3501             throw e.rethrowFromSystemServer();
3502         }
3503     }
3504 
3505     /**
3506      * @see #getCurrentSyncs()
3507      * @hide
3508      */
3509     public static List<SyncInfo> getCurrentSyncsAsUser(@UserIdInt int userId) {
3510         try {
3511             return getContentService().getCurrentSyncsAsUser(userId);
3512         } catch (RemoteException e) {
3513             throw e.rethrowFromSystemServer();
3514         }
3515     }
3516 
3517     /**
3518      * Returns the status that matches the authority.
3519      * @param account the account whose setting we are querying
3520      * @param authority the provider whose behavior is being queried
3521      * @return the SyncStatusInfo for the authority, or null if none exists
3522      * @hide
3523      */
3524     @UnsupportedAppUsage
3525     public static SyncStatusInfo getSyncStatus(Account account, String authority) {
3526         try {
3527             return getContentService().getSyncStatus(account, authority, null);
3528         } catch (RemoteException e) {
3529             throw e.rethrowFromSystemServer();
3530         }
3531     }
3532 
3533     /**
3534      * @see #getSyncStatus(Account, String)
3535      * @hide
3536      */
3537     @UnsupportedAppUsage
3538     public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
3539             @UserIdInt int userId) {
3540         try {
3541             return getContentService().getSyncStatusAsUser(account, authority, null, userId);
3542         } catch (RemoteException e) {
3543             throw e.rethrowFromSystemServer();
3544         }
3545     }
3546 
3547     /**
3548      * Return true if the pending status is true of any matching authorities.
3549      * <p>This method requires the caller to hold the permission
3550      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3551      * @param account the account whose setting we are querying
3552      * @param authority the provider whose behavior is being queried
3553      * @return true if there is a pending sync with the matching account and authority
3554      */
3555     public static boolean isSyncPending(Account account, String authority) {
3556         return isSyncPendingAsUser(account, authority, UserHandle.myUserId());
3557     }
3558 
3559     /**
3560      * @see #requestSync(Account, String, Bundle)
3561      * @hide
3562      */
3563     public static boolean isSyncPendingAsUser(Account account, String authority,
3564             @UserIdInt int userId) {
3565         try {
3566             return getContentService().isSyncPendingAsUser(account, authority, null, userId);
3567         } catch (RemoteException e) {
3568             throw e.rethrowFromSystemServer();
3569         }
3570     }
3571 
3572     /**
3573      * Request notifications when the different aspects of the SyncManager change. The
3574      * different items that can be requested are:
3575      * <ul>
3576      * <li> {@link #SYNC_OBSERVER_TYPE_PENDING}
3577      * <li> {@link #SYNC_OBSERVER_TYPE_ACTIVE}
3578      * <li> {@link #SYNC_OBSERVER_TYPE_SETTINGS}
3579      * </ul>
3580      * The caller can set one or more of the status types in the mask for any
3581      * given listener registration.
3582      * @param mask the status change types that will cause the callback to be invoked
3583      * @param callback observer to be invoked when the status changes
3584      * @return a handle that can be used to remove the listener at a later time
3585      */
3586     public static Object addStatusChangeListener(int mask, final SyncStatusObserver callback) {
3587         if (callback == null) {
3588             throw new IllegalArgumentException("you passed in a null callback");
3589         }
3590         try {
3591             ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
3592                 @Override
3593                 public void onStatusChanged(int which) throws RemoteException {
3594                     callback.onStatusChanged(which);
3595                 }
3596             };
3597             getContentService().addStatusChangeListener(mask, observer);
3598             return observer;
3599         } catch (RemoteException e) {
3600             throw e.rethrowFromSystemServer();
3601         }
3602     }
3603 
3604     /**
3605      * Remove a previously registered status change listener.
3606      * @param handle the handle that was returned by {@link #addStatusChangeListener}
3607      */
3608     public static void removeStatusChangeListener(Object handle) {
3609         if (handle == null) {
3610             throw new IllegalArgumentException("you passed in a null handle");
3611         }
3612         try {
3613             getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle);
3614         } catch (RemoteException e) {
3615             throw e.rethrowFromSystemServer();
3616         }
3617     }
3618 
3619     /**
3620      * Store the given {@link Bundle} as a long-lived cached object within the
3621      * system. This can be useful to avoid expensive re-parsing when apps are
3622      * restarted multiple times on low-RAM devices.
3623      * <p>
3624      * The {@link Bundle} is automatically invalidated when a
3625      * {@link #notifyChange(Uri, ContentObserver)} event applies to the key.
3626      *
3627      * @hide
3628      */
3629     @SystemApi
3630     @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
3631     public void putCache(@NonNull Uri key, @Nullable Bundle value) {
3632         try {
3633             getContentService().putCache(mContext.getPackageName(), key, value,
3634                     mContext.getUserId());
3635         } catch (RemoteException e) {
3636             throw e.rethrowFromSystemServer();
3637         }
3638     }
3639 
3640     /**
3641      * Retrieve the last {@link Bundle} stored as a long-lived cached object
3642      * within the system.
3643      *
3644      * @return {@code null} if no cached object has been stored, or if the
3645      *         stored object has been invalidated due to a
3646      *         {@link #notifyChange(Uri, ContentObserver)} event.
3647      * @hide
3648      */
3649     @SystemApi
3650     @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
3651     public @Nullable Bundle getCache(@NonNull Uri key) {
3652         try {
3653             final Bundle bundle = getContentService().getCache(mContext.getPackageName(), key,
3654                     mContext.getUserId());
3655             if (bundle != null) bundle.setClassLoader(mContext.getClassLoader());
3656             return bundle;
3657         } catch (RemoteException e) {
3658             throw e.rethrowFromSystemServer();
3659         }
3660     }
3661 
3662     /** {@hide} */
3663     public int getTargetSdkVersion() {
3664         return mTargetSdkVersion;
3665     }
3666 
3667     /**
3668      * Returns sampling percentage for a given duration.
3669      *
3670      * Always returns at least 1%.
3671      */
3672     private int samplePercentForDuration(long durationMillis) {
3673         if (durationMillis >= SLOW_THRESHOLD_MILLIS) {
3674             return 100;
3675         }
3676         return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
3677     }
3678 
3679     private void maybeLogQueryToEventLog(
3680             long durationMillis, Uri uri, String[] projection, @Nullable Bundle queryArgs) {
3681         if (!ENABLE_CONTENT_SAMPLE) return;
3682         int samplePercent = samplePercentForDuration(durationMillis);
3683         if (samplePercent < 100) {
3684             synchronized (mRandom) {
3685                 if (mRandom.nextInt(100) >= samplePercent) {
3686                     return;
3687                 }
3688             }
3689         }
3690 
3691         // Ensure a non-null bundle.
3692         queryArgs = (queryArgs != null) ? queryArgs : Bundle.EMPTY;
3693 
3694         StringBuilder projectionBuffer = new StringBuilder(100);
3695         if (projection != null) {
3696             for (int i = 0; i < projection.length; ++i) {
3697                 // Note: not using a comma delimiter here, as the
3698                 // multiple arguments to EventLog.writeEvent later
3699                 // stringify with a comma delimiter, which would make
3700                 // parsing uglier later.
3701                 if (i != 0) projectionBuffer.append('/');
3702                 projectionBuffer.append(projection[i]);
3703             }
3704         }
3705 
3706         // ActivityThread.currentPackageName() only returns non-null if the
3707         // current thread is an application main thread.  This parameter tells
3708         // us whether an event loop is blocked, and if so, which app it is.
3709         String blockingPackage = AppGlobals.getInitialPackage();
3710 
3711         EventLog.writeEvent(
3712             EventLogTags.CONTENT_QUERY_SAMPLE,
3713             uri.toString(),
3714             projectionBuffer.toString(),
3715             queryArgs.getString(QUERY_ARG_SQL_SELECTION, ""),
3716             queryArgs.getString(QUERY_ARG_SQL_SORT_ORDER, ""),
3717             durationMillis,
3718             blockingPackage != null ? blockingPackage : "",
3719             samplePercent);
3720     }
3721 
3722     private void maybeLogUpdateToEventLog(
3723         long durationMillis, Uri uri, String operation, String selection) {
3724         if (!ENABLE_CONTENT_SAMPLE) return;
3725         int samplePercent = samplePercentForDuration(durationMillis);
3726         if (samplePercent < 100) {
3727             synchronized (mRandom) {
3728                 if (mRandom.nextInt(100) >= samplePercent) {
3729                     return;
3730                 }
3731             }
3732         }
3733         String blockingPackage = AppGlobals.getInitialPackage();
3734         EventLog.writeEvent(
3735             EventLogTags.CONTENT_UPDATE_SAMPLE,
3736             uri.toString(),
3737             operation,
3738             selection != null ? selection : "",
3739             durationMillis,
3740             blockingPackage != null ? blockingPackage : "",
3741             samplePercent);
3742     }
3743 
3744     private final class CursorWrapperInner extends CrossProcessCursorWrapper {
3745         private final IContentProvider mContentProvider;
3746         private final AtomicBoolean mProviderReleased = new AtomicBoolean();
3747 
3748         private final CloseGuard mCloseGuard = CloseGuard.get();
3749 
3750         CursorWrapperInner(Cursor cursor, IContentProvider contentProvider) {
3751             super(cursor);
3752             mContentProvider = contentProvider;
3753             mCloseGuard.open("close");
3754         }
3755 
3756         @Override
3757         public void close() {
3758             mCloseGuard.close();
3759             super.close();
3760 
3761             if (mProviderReleased.compareAndSet(false, true)) {
3762                 ContentResolver.this.releaseProvider(mContentProvider);
3763             }
3764         }
3765 
3766         @Override
3767         protected void finalize() throws Throwable {
3768             try {
3769                 if (mCloseGuard != null) {
3770                     mCloseGuard.warnIfOpen();
3771                 }
3772 
3773                 close();
3774             } finally {
3775                 super.finalize();
3776             }
3777         }
3778     }
3779 
3780     private final class ParcelFileDescriptorInner extends ParcelFileDescriptor {
3781         private final IContentProvider mContentProvider;
3782         private final AtomicBoolean mProviderReleased = new AtomicBoolean();
3783 
3784         ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) {
3785             super(pfd);
3786             mContentProvider = icp;
3787         }
3788 
3789         @Override
3790         public void releaseResources() {
3791             if (mProviderReleased.compareAndSet(false, true)) {
3792                 ContentResolver.this.releaseProvider(mContentProvider);
3793             }
3794         }
3795     }
3796 
3797     /** @hide */
3798     public static final String CONTENT_SERVICE_NAME = "content";
3799 
3800     /** @hide */
3801     @UnsupportedAppUsage
3802     public static IContentService getContentService() {
3803         if (sContentService != null) {
3804             return sContentService;
3805         }
3806         IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME);
3807         sContentService = IContentService.Stub.asInterface(b);
3808         return sContentService;
3809     }
3810 
3811     /** @hide */
3812     @UnsupportedAppUsage
3813     public String getPackageName() {
3814         return mPackageName;
3815     }
3816 
3817     /** @hide */
3818     public @Nullable String getAttributionTag() {
3819         return mAttributionTag;
3820     }
3821 
3822     @UnsupportedAppUsage
3823     private static volatile IContentService sContentService;
3824     @UnsupportedAppUsage
3825     private final Context mContext;
3826 
3827     @UnsupportedAppUsage
3828     final String mPackageName;
3829     final @Nullable String mAttributionTag;
3830     final int mTargetSdkVersion;
3831     final ContentInterface mWrapped;
3832 
3833     private static final String TAG = "ContentResolver";
3834 
3835     /** @hide */
3836     public int resolveUserId(Uri uri) {
3837         return ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
3838     }
3839 
3840     /** @hide */
3841     public int getUserId() {
3842         return mContext.getUserId();
3843     }
3844 
3845     /** {@hide} */
3846     @Deprecated
3847     public Drawable getTypeDrawable(String mimeType) {
3848         return getTypeInfo(mimeType).getIcon().loadDrawable(mContext);
3849     }
3850 
3851     /**
3852      * Return a detailed description of the given MIME type, including an icon
3853      * and label that describe the type.
3854      *
3855      * @param mimeType Valid, concrete MIME type.
3856      */
3857     public final @NonNull MimeTypeInfo getTypeInfo(@NonNull String mimeType) {
3858         Objects.requireNonNull(mimeType);
3859         return MimeIconUtils.getTypeInfo(mimeType);
3860     }
3861 
3862     /**
3863      * Detailed description of a specific MIME type, including an icon and label
3864      * that describe the type.
3865      */
3866     public static final class MimeTypeInfo {
3867         private final Icon mIcon;
3868         private final CharSequence mLabel;
3869         private final CharSequence mContentDescription;
3870 
3871         /** {@hide} */
3872         public MimeTypeInfo(@NonNull Icon icon, @NonNull CharSequence label,
3873                 @NonNull CharSequence contentDescription) {
3874             mIcon = Objects.requireNonNull(icon);
3875             mLabel = Objects.requireNonNull(label);
3876             mContentDescription = Objects.requireNonNull(contentDescription);
3877         }
3878 
3879         /**
3880          * Return a visual representation of this MIME type. This can be styled
3881          * using {@link Icon#setTint(int)} to match surrounding UI.
3882          *
3883          * @see Icon#loadDrawable(Context)
3884          * @see android.widget.ImageView#setImageDrawable(Drawable)
3885          */
3886         public @NonNull Icon getIcon() {
3887             return mIcon;
3888         }
3889 
3890         /**
3891          * Return a textual representation of this MIME type.
3892          *
3893          * @see android.widget.TextView#setText(CharSequence)
3894          */
3895         public @NonNull CharSequence getLabel() {
3896             return mLabel;
3897         }
3898 
3899         /**
3900          * Return a content description for this MIME type.
3901          *
3902          * @see android.view.View#setContentDescription(CharSequence)
3903          */
3904         public @NonNull CharSequence getContentDescription() {
3905             return mContentDescription;
3906         }
3907     }
3908 
3909     /**
3910      * @hide
3911      */
3912     public static @Nullable Bundle createSqlQueryBundle(
3913             @Nullable String selection,
3914             @Nullable String[] selectionArgs) {
3915         return createSqlQueryBundle(selection, selectionArgs, null);
3916     }
3917 
3918     /**
3919      * @hide
3920      */
3921     public static @Nullable Bundle createSqlQueryBundle(
3922             @Nullable String selection,
3923             @Nullable String[] selectionArgs,
3924             @Nullable String sortOrder) {
3925 
3926         if (selection == null && selectionArgs == null && sortOrder == null) {
3927             return null;
3928         }
3929 
3930         Bundle queryArgs = new Bundle();
3931         if (selection != null) {
3932             queryArgs.putString(QUERY_ARG_SQL_SELECTION, selection);
3933         }
3934         if (selectionArgs != null) {
3935             queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs);
3936         }
3937         if (sortOrder != null) {
3938             queryArgs.putString(QUERY_ARG_SQL_SORT_ORDER, sortOrder);
3939         }
3940         return queryArgs;
3941     }
3942 
3943     /** @hide */
3944     public static @NonNull Bundle includeSqlSelectionArgs(@NonNull Bundle queryArgs,
3945             @Nullable String selection, @Nullable String[] selectionArgs) {
3946         if (selection != null) {
3947             queryArgs.putString(QUERY_ARG_SQL_SELECTION, selection);
3948         }
3949         if (selectionArgs != null) {
3950             queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs);
3951         }
3952         return queryArgs;
3953     }
3954 
3955     /**
3956      * Returns structured sort args formatted as an SQL sort clause.
3957      *
3958      * NOTE: Collator clauses are suitable for use with non text fields. We might
3959      * choose to omit any collation clause since we don't know the underlying
3960      * type of data to be collated. Imperical testing shows that sqlite3 doesn't
3961      * appear to care much about the presence of collate clauses in queries
3962      * when ordering by numeric fields. For this reason we include collate
3963      * clause unilaterally when {@link #QUERY_ARG_SORT_COLLATION} is present
3964      * in query args bundle.
3965      *
3966      * TODO: Would be nice to explicitly validate that colums referenced in
3967      * {@link #QUERY_ARG_SORT_COLUMNS} are present in the associated projection.
3968      *
3969      * @hide
3970      */
3971     public static String createSqlSortClause(Bundle queryArgs) {
3972         String[] columns = queryArgs.getStringArray(QUERY_ARG_SORT_COLUMNS);
3973         if (columns == null || columns.length == 0) {
3974             throw new IllegalArgumentException("Can't create sort clause without columns.");
3975         }
3976 
3977         String query = TextUtils.join(", ", columns);
3978 
3979         // Interpret PRIMARY and SECONDARY collation strength as no-case collation based
3980         // on their javadoc descriptions.
3981         int collation = queryArgs.getInt(
3982                 ContentResolver.QUERY_ARG_SORT_COLLATION, java.text.Collator.IDENTICAL);
3983         if (collation == java.text.Collator.PRIMARY || collation == java.text.Collator.SECONDARY) {
3984             query += " COLLATE NOCASE";
3985         }
3986 
3987         int sortDir = queryArgs.getInt(QUERY_ARG_SORT_DIRECTION, Integer.MIN_VALUE);
3988         if (sortDir != Integer.MIN_VALUE) {
3989             switch (sortDir) {
3990                 case QUERY_SORT_DIRECTION_ASCENDING:
3991                     query += " ASC";
3992                     break;
3993                 case QUERY_SORT_DIRECTION_DESCENDING:
3994                     query += " DESC";
3995                     break;
3996                 default:
3997                     throw new IllegalArgumentException("Unsupported sort direction value."
3998                             + " See ContentResolver documentation for details.");
3999             }
4000         }
4001         return query;
4002     }
4003 
4004     /**
4005      * Convenience method that efficiently loads a visual thumbnail for the
4006      * given {@link Uri}. Internally calls
4007      * {@link ContentProvider#openTypedAssetFile} on the remote provider, but
4008      * also defensively resizes any returned content to match the requested
4009      * target size.
4010      *
4011      * @param uri The item that should be visualized as a thumbnail.
4012      * @param size The target area on the screen where this thumbnail will be
4013      *            shown. This is passed to the provider as {@link #EXTRA_SIZE}
4014      *            to help it avoid downloading or generating heavy resources.
4015      * @param signal A signal to cancel the operation in progress.
4016      * @return Valid {@link Bitmap} which is a visual thumbnail.
4017      * @throws IOException If any trouble was encountered while generating or
4018      *             loading the thumbnail, or if
4019      *             {@link CancellationSignal#cancel()} was invoked.
4020      */
4021     public @NonNull Bitmap loadThumbnail(@NonNull Uri uri, @NonNull Size size,
4022             @Nullable CancellationSignal signal) throws IOException {
4023         return loadThumbnail(this, uri, size, signal, ImageDecoder.ALLOCATOR_SOFTWARE);
4024     }
4025 
4026     /** {@hide} */
4027     public static Bitmap loadThumbnail(@NonNull ContentInterface content, @NonNull Uri uri,
4028             @NonNull Size size, @Nullable CancellationSignal signal, int allocator)
4029             throws IOException {
4030         Objects.requireNonNull(content);
4031         Objects.requireNonNull(uri);
4032         Objects.requireNonNull(size);
4033 
4034         // Convert to Point, since that's what the API is defined as
4035         final Bundle opts = new Bundle();
4036         opts.putParcelable(EXTRA_SIZE, Point.convert(size));
4037         final Int32Ref orientation = new Int32Ref(0);
4038 
4039         Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> {
4040             final AssetFileDescriptor afd = content.openTypedAssetFile(uri, "image/*", opts,
4041                     signal);
4042             final Bundle extras = afd.getExtras();
4043             orientation.value = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0;
4044             return afd;
4045         }), (ImageDecoder decoder, ImageInfo info, Source source) -> {
4046                 decoder.setAllocator(allocator);
4047 
4048                 // One last-ditch check to see if we've been canceled.
4049                 if (signal != null) signal.throwIfCanceled();
4050 
4051                 // We requested a rough thumbnail size, but the remote size may have
4052                 // returned something giant, so defensively scale down as needed.
4053                 final int widthSample = info.getSize().getWidth() / size.getWidth();
4054                 final int heightSample = info.getSize().getHeight() / size.getHeight();
4055                 final int sample = Math.max(widthSample, heightSample);
4056                 if (sample > 1) {
4057                     decoder.setTargetSampleSize(sample);
4058                 }
4059         });
4060 
4061         // Transform the bitmap if requested. We use a side-channel to
4062         // communicate the orientation, since EXIF thumbnails don't contain
4063         // the rotation flags of the original image.
4064         if (orientation.value != 0) {
4065             final int width = bitmap.getWidth();
4066             final int height = bitmap.getHeight();
4067 
4068             final Matrix m = new Matrix();
4069             m.setRotate(orientation.value, width / 2, height / 2);
4070             bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false);
4071         }
4072 
4073         return bitmap;
4074     }
4075 
4076     /** {@hide} */
4077     public static void onDbCorruption(String tag, String message, Throwable stacktrace) {
4078         try {
4079             getContentService().onDbCorruption(tag, message, Log.getStackTraceString(stacktrace));
4080         } catch (RemoteException e) {
4081             e.rethrowFromSystemServer();
4082         }
4083     }
4084 
4085     /**
4086      * Decode a path generated by {@link #encodeToFile(Uri)} back into
4087      * the original {@link Uri}.
4088      * <p>
4089      * This is used to offer a way to intercept filesystem calls in
4090      * {@link ContentProvider} unaware code and redirect them to a
4091      * {@link ContentProvider} when they attempt to use {@code _DATA} columns
4092      * that are otherwise deprecated.
4093      *
4094      * @hide
4095      */
4096     @SystemApi
4097     @TestApi
4098     // We can't accept an already-opened FD here, since these methods are
4099     // rewriting actual filesystem paths
4100     @SuppressLint("StreamFiles")
4101     public static @NonNull Uri decodeFromFile(@NonNull File file) {
4102         return translateDeprecatedDataPath(file.getAbsolutePath());
4103     }
4104 
4105     /**
4106      * Encode a {@link Uri} into an opaque filesystem path which can then be
4107      * resurrected by {@link #decodeFromFile(File)}.
4108      * <p>
4109      * This is used to offer a way to intercept filesystem calls in
4110      * {@link ContentProvider} unaware code and redirect them to a
4111      * {@link ContentProvider} when they attempt to use {@code _DATA} columns
4112      * that are otherwise deprecated.
4113      *
4114      * @hide
4115      */
4116     @SystemApi
4117     @TestApi
4118     // We can't accept an already-opened FD here, since these methods are
4119     // rewriting actual filesystem paths
4120     @SuppressLint("StreamFiles")
4121     public static @NonNull File encodeToFile(@NonNull Uri uri) {
4122         return new File(translateDeprecatedDataPath(uri));
4123     }
4124 
4125     /** {@hide} */
4126     public static @NonNull Uri translateDeprecatedDataPath(@NonNull String path) {
4127         final String ssp = "//" + path.substring(DEPRECATE_DATA_PREFIX.length());
4128         return Uri.parse(new Uri.Builder().scheme(SCHEME_CONTENT)
4129                 .encodedOpaquePart(ssp).build().toString());
4130     }
4131 
4132     /** {@hide} */
4133     public static @NonNull String translateDeprecatedDataPath(@NonNull Uri uri) {
4134         return DEPRECATE_DATA_PREFIX + uri.getEncodedSchemeSpecificPart().substring(2);
4135     }
4136 }
4137