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