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