• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content;
18 
19 import static android.provider.DocumentsContract.EXTRA_ORIENTATION;
20 
21 import android.accounts.Account;
22 import android.annotation.IntDef;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.RequiresPermission;
26 import android.annotation.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 an 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         // XXX would like to have an acquireExistingUnstableProvider for this.
924         IContentProvider provider = acquireExistingProvider(url);
925         if (provider != null) {
926             try {
927                 final StringResultListener resultListener = new StringResultListener();
928                 provider.getTypeAsync(url, new RemoteCallback(resultListener));
929                 resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
930                 if (resultListener.exception != null) {
931                     throw resultListener.exception;
932                 }
933                 return resultListener.result;
934             } catch (RemoteException e) {
935                 // Arbitrary and not worth documenting, as Activity
936                 // Manager will kill this process shortly anyway.
937                 return null;
938             } catch (java.lang.Exception e) {
939                 Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
940                 return null;
941             } finally {
942                 releaseProvider(provider);
943             }
944         }
945 
946         if (!SCHEME_CONTENT.equals(url.getScheme())) {
947             return null;
948         }
949 
950         try {
951             final StringResultListener resultListener = new StringResultListener();
952             ActivityManager.getService().getProviderMimeTypeAsync(
953                     ContentProvider.getUriWithoutUserId(url),
954                     resolveUserId(url),
955                     new RemoteCallback(resultListener));
956             resultListener.waitForResult(REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS);
957             if (resultListener.exception != null) {
958                 throw resultListener.exception;
959             }
960             return resultListener.result;
961         } catch (RemoteException e) {
962             // We just failed to send a oneway request to the System Server. Nothing to do.
963             return null;
964         } catch (java.lang.Exception e) {
965             Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
966             return null;
967         }
968     }
969 
970     private abstract static class ResultListener<T> implements RemoteCallback.OnResultListener {
971         @GuardedBy("this")
972         public boolean done;
973 
974         @GuardedBy("this")
975         public T result;
976 
977         @GuardedBy("this")
978         public RuntimeException exception;
979 
980         @Override
981         public void onResult(Bundle result) {
982             synchronized (this) {
983                 ParcelableException e = result.getParcelable(REMOTE_CALLBACK_ERROR);
984                 if (e != null) {
985                     Throwable t = e.getCause();
986                     if (t instanceof RuntimeException) {
987                         this.exception = (RuntimeException) t;
988                     } else {
989                         this.exception = new RuntimeException(t);
990                     }
991                 } else {
992                     this.result = getResultFromBundle(result);
993                 }
994                 done = true;
995                 notifyAll();
996             }
997         }
998 
999         protected abstract T getResultFromBundle(Bundle result);
1000 
1001         public void waitForResult(long timeout) {
1002             synchronized (this) {
1003                 if (!done) {
1004                     try {
1005                         wait(timeout);
1006                     } catch (InterruptedException e) {
1007                         // Ignore
1008                     }
1009                 }
1010             }
1011         }
1012     }
1013 
1014     private static class StringResultListener extends ResultListener<String> {
1015         @Override
1016         protected String getResultFromBundle(Bundle result) {
1017             return result.getString(REMOTE_CALLBACK_RESULT);
1018         }
1019     }
1020 
1021     private static class UriResultListener extends ResultListener<Uri> {
1022         @Override
1023         protected Uri getResultFromBundle(Bundle result) {
1024             return result.getParcelable(REMOTE_CALLBACK_RESULT);
1025         }
1026     }
1027 
1028     /**
1029      * Query for the possible MIME types for the representations the given
1030      * content URL can be returned when opened as as stream with
1031      * {@link #openTypedAssetFileDescriptor}.  Note that the types here are
1032      * not necessarily a superset of the type returned by {@link #getType} --
1033      * many content providers cannot return a raw stream for the structured
1034      * data that they contain.
1035      *
1036      * @param url A Uri identifying content (either a list or specific type),
1037      * using the content:// scheme.
1038      * @param mimeTypeFilter The desired MIME type.  This may be a pattern,
1039      * such as *&#47;*, to query for all available MIME types that match the
1040      * pattern.
1041      * @return Returns an array of MIME type strings for all available
1042      * data streams that match the given mimeTypeFilter.  If there are none,
1043      * null is returned.
1044      */
1045     @Override
1046     public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
1047         Objects.requireNonNull(url, "url");
1048         Objects.requireNonNull(mimeTypeFilter, "mimeTypeFilter");
1049 
1050         try {
1051             if (mWrapped != null) return mWrapped.getStreamTypes(url, mimeTypeFilter);
1052         } catch (RemoteException e) {
1053             return null;
1054         }
1055 
1056         IContentProvider provider = acquireProvider(url);
1057         if (provider == null) {
1058             return null;
1059         }
1060 
1061         try {
1062             return provider.getStreamTypes(url, mimeTypeFilter);
1063         } catch (RemoteException e) {
1064             // Arbitrary and not worth documenting, as Activity
1065             // Manager will kill this process shortly anyway.
1066             return null;
1067         } finally {
1068             releaseProvider(provider);
1069         }
1070     }
1071 
1072     /**
1073      * Query the given URI, returning a {@link Cursor} over the result set.
1074      * <p>
1075      * For best performance, the caller should follow these guidelines:
1076      * <ul>
1077      * <li>Provide an explicit projection, to prevent
1078      * reading data from storage that aren't going to be used.</li>
1079      * <li>Use question mark parameter markers such as 'phone=?' instead of
1080      * explicit values in the {@code selection} parameter, so that queries
1081      * that differ only by those values will be recognized as the same
1082      * for caching purposes.</li>
1083      * </ul>
1084      * </p>
1085      *
1086      * @param uri The URI, using the content:// scheme, for the content to
1087      *         retrieve.
1088      * @param projection A list of which columns to return. Passing null will
1089      *         return all columns, which is inefficient.
1090      * @param selection A filter declaring which rows to return, formatted as an
1091      *         SQL WHERE clause (excluding the WHERE itself). Passing null will
1092      *         return all rows for the given URI.
1093      * @param selectionArgs You may include ?s in selection, which will be
1094      *         replaced by the values from selectionArgs, in the order that they
1095      *         appear in the selection. The values will be bound as Strings.
1096      * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
1097      *         clause (excluding the ORDER BY itself). Passing null will use the
1098      *         default sort order, which may be unordered.
1099      * @return A Cursor object, which is positioned before the first entry. May return
1100      *         <code>null</code> if the underlying content provider returns <code>null</code>,
1101      *         or if it crashes.
1102      * @see Cursor
1103      */
1104     public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
1105             @Nullable String[] projection, @Nullable String selection,
1106             @Nullable String[] selectionArgs, @Nullable String sortOrder) {
1107         return query(uri, projection, selection, selectionArgs, sortOrder, null);
1108     }
1109 
1110     /**
1111      * Query the given URI, returning a {@link Cursor} over the result set
1112      * with optional support for cancellation.
1113      * <p>
1114      * For best performance, the caller should follow these guidelines:
1115      * <ul>
1116      * <li>Provide an explicit projection, to prevent
1117      * reading data from storage that aren't going to be used.</li>
1118      * <li>Use question mark parameter markers such as 'phone=?' instead of
1119      * explicit values in the {@code selection} parameter, so that queries
1120      * that differ only by those values will be recognized as the same
1121      * for caching purposes.</li>
1122      * </ul>
1123      * </p>
1124      *
1125      * @param uri The URI, using the content:// scheme, for the content to
1126      *         retrieve.
1127      * @param projection A list of which columns to return. Passing null will
1128      *         return all columns, which is inefficient.
1129      * @param selection A filter declaring which rows to return, formatted as an
1130      *         SQL WHERE clause (excluding the WHERE itself). Passing null will
1131      *         return all rows for the given URI.
1132      * @param selectionArgs You may include ?s in selection, which will be
1133      *         replaced by the values from selectionArgs, in the order that they
1134      *         appear in the selection. The values will be bound as Strings.
1135      * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
1136      *         clause (excluding the ORDER BY itself). Passing null will use the
1137      *         default sort order, which may be unordered.
1138      * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1139      * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1140      * when the query is executed.
1141      * @return A Cursor object, which is positioned before the first entry. May return
1142      *         <code>null</code> if the underlying content provider returns <code>null</code>,
1143      *         or if it crashes.
1144      * @see Cursor
1145      */
1146     public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
1147             @Nullable String[] projection, @Nullable String selection,
1148             @Nullable String[] selectionArgs, @Nullable String sortOrder,
1149             @Nullable CancellationSignal cancellationSignal) {
1150         Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder);
1151         return query(uri, projection, queryArgs, cancellationSignal);
1152     }
1153 
1154     /**
1155      * Query the given URI, returning a {@link Cursor} over the result set
1156      * with support for cancellation.
1157      *
1158      * <p>For best performance, the caller should follow these guidelines:
1159      *
1160      * <li>Provide an explicit projection, to prevent reading data from storage
1161      * that aren't going to be used.
1162      *
1163      * Provider must identify which QUERY_ARG_SORT* arguments were honored during
1164      * the preparation of the result set by including the respective argument keys
1165      * in the {@link Cursor} extras {@link Bundle}. See {@link #EXTRA_HONORED_ARGS}
1166      * for details.
1167      *
1168      * @see #QUERY_ARG_SORT_COLUMNS
1169      * @see #QUERY_ARG_SORT_DIRECTION
1170      * @see #QUERY_ARG_SORT_COLLATION
1171      *
1172      * @param uri The URI, using the content:// scheme, for the content to
1173      *         retrieve.
1174      * @param projection A list of which columns to return. Passing null will
1175      *         return all columns, which is inefficient.
1176      * @param queryArgs A Bundle containing additional information necessary for
1177      *            the operation. Arguments may include SQL style arguments, such
1178      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
1179      *            the documentation for each individual provider will indicate
1180      *            which arguments they support.
1181      * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
1182      * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1183      * when the query is executed.
1184      * @return A Cursor object, which is positioned before the first entry. May return
1185      *         <code>null</code> if the underlying content provider returns <code>null</code>,
1186      *         or if it crashes.
1187      * @see Cursor
1188      */
1189     @Override
1190     public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
1191             @Nullable String[] projection, @Nullable Bundle queryArgs,
1192             @Nullable CancellationSignal cancellationSignal) {
1193         Objects.requireNonNull(uri, "uri");
1194 
1195         try {
1196             if (mWrapped != null) {
1197                 return mWrapped.query(uri, projection, queryArgs, cancellationSignal);
1198             }
1199         } catch (RemoteException e) {
1200             return null;
1201         }
1202 
1203         IContentProvider unstableProvider = acquireUnstableProvider(uri);
1204         if (unstableProvider == null) {
1205             return null;
1206         }
1207         IContentProvider stableProvider = null;
1208         Cursor qCursor = null;
1209         try {
1210             long startTime = SystemClock.uptimeMillis();
1211 
1212             ICancellationSignal remoteCancellationSignal = null;
1213             if (cancellationSignal != null) {
1214                 cancellationSignal.throwIfCanceled();
1215                 remoteCancellationSignal = unstableProvider.createCancellationSignal();
1216                 cancellationSignal.setRemote(remoteCancellationSignal);
1217             }
1218             try {
1219                 qCursor = unstableProvider.query(mContext.getAttributionSource(), uri, projection,
1220                         queryArgs, remoteCancellationSignal);
1221             } catch (DeadObjectException e) {
1222                 // The remote process has died...  but we only hold an unstable
1223                 // reference though, so we might recover!!!  Let's try!!!!
1224                 // This is exciting!!1!!1!!!!1
1225                 unstableProviderDied(unstableProvider);
1226                 stableProvider = acquireProvider(uri);
1227                 if (stableProvider == null) {
1228                     return null;
1229                 }
1230                 qCursor = stableProvider.query(mContext.getAttributionSource(), uri, projection,
1231                         queryArgs, remoteCancellationSignal);
1232             }
1233             if (qCursor == null) {
1234                 return null;
1235             }
1236 
1237             // Force query execution.  Might fail and throw a runtime exception here.
1238             qCursor.getCount();
1239             long durationMillis = SystemClock.uptimeMillis() - startTime;
1240             maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
1241 
1242             // Wrap the cursor object into CursorWrapperInner object.
1243             final IContentProvider provider = (stableProvider != null) ? stableProvider
1244                     : acquireProvider(uri);
1245             final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
1246             stableProvider = null;
1247             qCursor = null;
1248             return wrapper;
1249         } catch (RemoteException e) {
1250             // Arbitrary and not worth documenting, as Activity
1251             // Manager will kill this process shortly anyway.
1252             return null;
1253         } finally {
1254             if (qCursor != null) {
1255                 qCursor.close();
1256             }
1257             if (cancellationSignal != null) {
1258                 cancellationSignal.setRemote(null);
1259             }
1260             if (unstableProvider != null) {
1261                 releaseUnstableProvider(unstableProvider);
1262             }
1263             if (stableProvider != null) {
1264                 releaseProvider(stableProvider);
1265             }
1266         }
1267     }
1268 
1269     /** {@hide} */
1270     public final @NonNull Uri canonicalizeOrElse(@NonNull Uri uri) {
1271         final Uri res = canonicalize(uri);
1272         return (res != null) ? res : uri;
1273     }
1274 
1275     /**
1276      * Transform the given <var>url</var> to a canonical representation of
1277      * its referenced resource, which can be used across devices, persisted,
1278      * backed up and restored, etc.  The returned Uri is still a fully capable
1279      * Uri for use with its content provider, allowing you to do all of the
1280      * same content provider operations as with the original Uri --
1281      * {@link #query}, {@link #openInputStream(android.net.Uri)}, etc.  The
1282      * only difference in behavior between the original and new Uris is that
1283      * the content provider may need to do some additional work at each call
1284      * using it to resolve it to the correct resource, especially if the
1285      * canonical Uri has been moved to a different environment.
1286      *
1287      * <p>If you are moving a canonical Uri between environments, you should
1288      * perform another call to {@link #canonicalize} with that original Uri to
1289      * re-canonicalize it for the current environment.  Alternatively, you may
1290      * want to use {@link #uncanonicalize} to transform it to a non-canonical
1291      * Uri that works only in the current environment but potentially more
1292      * efficiently than the canonical representation.</p>
1293      *
1294      * @param url The {@link Uri} that is to be transformed to a canonical
1295      * representation.  Like all resolver calls, the input can be either
1296      * a non-canonical or canonical Uri.
1297      *
1298      * @return Returns the official canonical representation of <var>url</var>,
1299      * or null if the content provider does not support a canonical representation
1300      * of the given Uri.  Many providers may not support canonicalization of some
1301      * or all of their Uris.
1302      *
1303      * @see #uncanonicalize
1304      */
1305     @Override
1306     public final @Nullable Uri canonicalize(@NonNull Uri url) {
1307         Objects.requireNonNull(url, "url");
1308 
1309         try {
1310             if (mWrapped != null) return mWrapped.canonicalize(url);
1311         } catch (RemoteException e) {
1312             return null;
1313         }
1314 
1315         IContentProvider provider = acquireProvider(url);
1316         if (provider == null) {
1317             return null;
1318         }
1319 
1320         try {
1321             final UriResultListener resultListener = new UriResultListener();
1322             provider.canonicalizeAsync(mContext.getAttributionSource(), url,
1323                     new RemoteCallback(resultListener));
1324             resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
1325             if (resultListener.exception != null) {
1326                 throw resultListener.exception;
1327             }
1328             return resultListener.result;
1329         } catch (RemoteException e) {
1330             // Arbitrary and not worth documenting, as Activity
1331             // Manager will kill this process shortly anyway.
1332             return null;
1333         } finally {
1334             releaseProvider(provider);
1335         }
1336     }
1337 
1338     /**
1339      * Given a canonical Uri previously generated by {@link #canonicalize}, convert
1340      * it to its local non-canonical form.  This can be useful in some cases where
1341      * you know that you will only be using the Uri in the current environment and
1342      * want to avoid any possible overhead when using it with the content
1343      * provider or want to verify that the referenced data exists at all in the
1344      * new environment.
1345      *
1346      * @param url The canonical {@link Uri} that is to be convered back to its
1347      * non-canonical form.
1348      *
1349      * @return Returns the non-canonical representation of <var>url</var>.  This will
1350      * return null if data identified by the canonical Uri can not be found in
1351      * the current environment; callers must always check for null and deal with
1352      * that by appropriately falling back to an alternative.
1353      *
1354      * @see #canonicalize
1355      */
1356     @Override
1357     public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
1358         Objects.requireNonNull(url, "url");
1359 
1360         try {
1361             if (mWrapped != null) return mWrapped.uncanonicalize(url);
1362         } catch (RemoteException e) {
1363             return null;
1364         }
1365 
1366         IContentProvider provider = acquireProvider(url);
1367         if (provider == null) {
1368             return null;
1369         }
1370 
1371         try {
1372             final UriResultListener resultListener = new UriResultListener();
1373             provider.uncanonicalizeAsync(mContext.getAttributionSource(), url,
1374                     new RemoteCallback(resultListener));
1375             resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
1376             if (resultListener.exception != null) {
1377                 throw resultListener.exception;
1378             }
1379             return resultListener.result;
1380         } catch (RemoteException e) {
1381             // Arbitrary and not worth documenting, as Activity
1382             // Manager will kill this process shortly anyway.
1383             return null;
1384         } finally {
1385             releaseProvider(provider);
1386         }
1387     }
1388 
1389     /**
1390      * This allows clients to request an explicit refresh of content identified
1391      * by {@code uri}.
1392      * <p>
1393      * Client code should only invoke this method when there is a strong
1394      * indication (such as a user initiated pull to refresh gesture) that the
1395      * content is stale.
1396      * <p>
1397      *
1398      * @param url The Uri identifying the data to refresh.
1399      * @param extras Additional options from the client. The definitions of
1400      *            these are specific to the content provider being called.
1401      * @param cancellationSignal A signal to cancel the operation in progress,
1402      *            or {@code null} if none. For example, if you called refresh on
1403      *            a particular uri, you should call
1404      *            {@link CancellationSignal#throwIfCanceled()} to check whether
1405      *            the client has canceled the refresh request.
1406      * @return true if the provider actually tried refreshing.
1407      */
1408     @Override
1409     public final boolean refresh(@NonNull Uri url, @Nullable Bundle extras,
1410             @Nullable CancellationSignal cancellationSignal) {
1411         Objects.requireNonNull(url, "url");
1412 
1413         try {
1414             if (mWrapped != null) return mWrapped.refresh(url, extras, cancellationSignal);
1415         } catch (RemoteException e) {
1416             return false;
1417         }
1418 
1419         IContentProvider provider = acquireProvider(url);
1420         if (provider == null) {
1421             return false;
1422         }
1423 
1424         try {
1425             ICancellationSignal remoteCancellationSignal = null;
1426             if (cancellationSignal != null) {
1427                 cancellationSignal.throwIfCanceled();
1428                 remoteCancellationSignal = provider.createCancellationSignal();
1429                 cancellationSignal.setRemote(remoteCancellationSignal);
1430             }
1431             return provider.refresh(mContext.getAttributionSource(), url, extras,
1432                     remoteCancellationSignal);
1433         } catch (RemoteException e) {
1434             // Arbitrary and not worth documenting, as Activity
1435             // Manager will kill this process shortly anyway.
1436             return false;
1437         } finally {
1438             releaseProvider(provider);
1439         }
1440     }
1441 
1442     /**
1443      * Perform a detailed internal check on a {@link Uri} to determine if a UID
1444      * is able to access it with specific mode flags.
1445      * <p>
1446      * This method is typically used when the provider implements more dynamic
1447      * access controls that cannot be expressed with {@code <path-permission>}
1448      * style static rules.
1449      * <p>
1450      * Because validation of these dynamic access controls has significant
1451      * system health impact, this feature is only available to providers that
1452      * are built into the system.
1453      *
1454      * @param uri the {@link Uri} to perform an access check on.
1455      * @param uid the UID to check the permission for.
1456      * @param modeFlags the access flags to use for the access check, such as
1457      *            {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
1458      * @return {@link PackageManager#PERMISSION_GRANTED} if access is allowed,
1459      *         otherwise {@link PackageManager#PERMISSION_DENIED}.
1460      * @hide
1461      */
1462     @Override
1463     @SystemApi
1464     public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
1465         Objects.requireNonNull(uri, "uri");
1466 
1467         try {
1468             if (mWrapped != null) return mWrapped.checkUriPermission(uri, uid, modeFlags);
1469         } catch (RemoteException e) {
1470             return PackageManager.PERMISSION_DENIED;
1471         }
1472 
1473         try (ContentProviderClient client = acquireUnstableContentProviderClient(uri)) {
1474             return client.checkUriPermission(uri, uid, modeFlags);
1475         } catch (RemoteException e) {
1476             return PackageManager.PERMISSION_DENIED;
1477         }
1478     }
1479 
1480     /**
1481      * Open a stream on to the content associated with a content URI.  If there
1482      * is no data associated with the URI, FileNotFoundException is thrown.
1483      *
1484      * <h5>Accepts the following URI schemes:</h5>
1485      * <ul>
1486      * <li>content ({@link #SCHEME_CONTENT})</li>
1487      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
1488      * <li>file ({@link #SCHEME_FILE})</li>
1489      * </ul>
1490      *
1491      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1492      * on these schemes.
1493      *
1494      * @param uri The desired URI.
1495      * @return InputStream or {@code null} if the provider recently crashed.
1496      * @throws FileNotFoundException if the provided URI could not be opened.
1497      * @see #openAssetFileDescriptor(Uri, String)
1498      */
1499     public final @Nullable InputStream openInputStream(@NonNull Uri uri)
1500             throws FileNotFoundException {
1501         Objects.requireNonNull(uri, "uri");
1502         String scheme = uri.getScheme();
1503         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
1504             // Note: left here to avoid breaking compatibility.  May be removed
1505             // with sufficient testing.
1506             OpenResourceIdResult r = getResourceId(uri);
1507             try {
1508                 InputStream stream = r.r.openRawResource(r.id);
1509                 return stream;
1510             } catch (Resources.NotFoundException ex) {
1511                 throw new FileNotFoundException("Resource does not exist: " + uri);
1512             }
1513         } else if (SCHEME_FILE.equals(scheme)) {
1514             // Note: left here to avoid breaking compatibility.  May be removed
1515             // with sufficient testing.
1516             return new FileInputStream(uri.getPath());
1517         } else {
1518             AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r", null);
1519             try {
1520                 return fd != null ? fd.createInputStream() : null;
1521             } catch (IOException e) {
1522                 throw new FileNotFoundException("Unable to create stream");
1523             }
1524         }
1525     }
1526 
1527     /**
1528      * Synonym for {@link #openOutputStream(Uri, String)
1529      * openOutputStream(uri, "w")}.
1530      *
1531      * @param uri The desired URI.
1532      * @return an OutputStream or {@code null} if the provider recently crashed.
1533      * @throws FileNotFoundException if the provided URI could not be opened.
1534      */
1535     public final @Nullable OutputStream openOutputStream(@NonNull Uri uri)
1536             throws FileNotFoundException {
1537         return openOutputStream(uri, "w");
1538     }
1539 
1540     /**
1541      * Open a stream on to the content associated with a content URI.  If there
1542      * is no data associated with the URI, FileNotFoundException is thrown.
1543      *
1544      * <h5>Accepts the following URI schemes:</h5>
1545      * <ul>
1546      * <li>content ({@link #SCHEME_CONTENT})</li>
1547      * <li>file ({@link #SCHEME_FILE})</li>
1548      * </ul>
1549      *
1550      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1551      * on these schemes.
1552      *
1553      * @param uri The desired URI.
1554      * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
1555      *             or "rwt". See{@link ParcelFileDescriptor#parseMode} for more details.
1556      * @return an OutputStream or {@code null} if the provider recently crashed.
1557      * @throws FileNotFoundException if the provided URI could not be opened.
1558      * @see #openAssetFileDescriptor(Uri, String)
1559      */
1560     public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode)
1561             throws FileNotFoundException {
1562         AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null);
1563         try {
1564             return fd != null ? fd.createOutputStream() : null;
1565         } catch (IOException e) {
1566             throw new FileNotFoundException("Unable to create stream");
1567         }
1568     }
1569 
1570     @Override
1571     public final @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
1572             @Nullable CancellationSignal signal) throws FileNotFoundException {
1573         try {
1574             if (mWrapped != null) return mWrapped.openFile(uri, mode, signal);
1575         } catch (RemoteException e) {
1576             return null;
1577         }
1578 
1579         return openFileDescriptor(uri, mode, signal);
1580     }
1581 
1582     /**
1583      * Open a raw file descriptor to access data under a URI.  This
1584      * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
1585      * underlying {@link ContentProvider#openFile}
1586      * ContentProvider.openFile()} method, so will <em>not</em> work with
1587      * providers that return sub-sections of files.  If at all possible,
1588      * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
1589      * will receive a FileNotFoundException exception if the provider returns a
1590      * sub-section of a file.
1591      *
1592      * <h5>Accepts the following URI schemes:</h5>
1593      * <ul>
1594      * <li>content ({@link #SCHEME_CONTENT})</li>
1595      * <li>file ({@link #SCHEME_FILE})</li>
1596      * </ul>
1597      *
1598      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1599      * on these schemes.
1600      * <p>
1601      * If opening with the exclusive "r" or "w" modes, the returned
1602      * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
1603      * of data. Opening with the "rw" mode implies a file on disk that supports
1604      * seeking. If possible, always use an exclusive mode to give the underlying
1605      * {@link ContentProvider} the most flexibility.
1606      * <p>
1607      * If you are writing a file, and need to communicate an error to the
1608      * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
1609      *
1610      * @param uri The desired URI to open.
1611      * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
1612      *             or "rwt". See{@link ParcelFileDescriptor#parseMode} for more details.
1613      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1614      * provider recently crashed. You own this descriptor and are responsible for closing it
1615      * when done.
1616      * @throws FileNotFoundException Throws FileNotFoundException if no
1617      * file exists under the URI or the mode is invalid.
1618      * @see #openAssetFileDescriptor(Uri, String)
1619      */
1620     public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
1621             @NonNull String mode) throws FileNotFoundException {
1622         return openFileDescriptor(uri, mode, null);
1623     }
1624 
1625     /**
1626      * Open a raw file descriptor to access data under a URI.  This
1627      * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
1628      * underlying {@link ContentProvider#openFile}
1629      * ContentProvider.openFile()} method, so will <em>not</em> work with
1630      * providers that return sub-sections of files.  If at all possible,
1631      * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
1632      * will receive a FileNotFoundException exception if the provider returns a
1633      * sub-section of a file.
1634      *
1635      * <h5>Accepts the following URI schemes:</h5>
1636      * <ul>
1637      * <li>content ({@link #SCHEME_CONTENT})</li>
1638      * <li>file ({@link #SCHEME_FILE})</li>
1639      * </ul>
1640      *
1641      * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
1642      * on these schemes.
1643      * <p>
1644      * If opening with the exclusive "r" or "w" modes, the returned
1645      * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
1646      * of data. Opening with the "rw" mode implies a file on disk that supports
1647      * seeking. If possible, always use an exclusive mode to give the underlying
1648      * {@link ContentProvider} the most flexibility.
1649      * <p>
1650      * If you are writing a file, and need to communicate an error to the
1651      * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
1652      *
1653      * @param uri The desired URI to open.
1654      * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
1655      *             or "rwt". See{@link ParcelFileDescriptor#parseMode} for more details.
1656      * @param cancellationSignal A signal to cancel the operation in progress,
1657      *         or null if none. If the operation is canceled, then
1658      *         {@link OperationCanceledException} will be thrown.
1659      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1660      * provider recently crashed. You own this descriptor and are responsible for closing it
1661      * when done.
1662      * @throws FileNotFoundException Throws FileNotFoundException if no
1663      * file exists under the URI or the mode is invalid.
1664      * @see #openAssetFileDescriptor(Uri, String)
1665      */
1666     public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
1667             @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
1668                     throws FileNotFoundException {
1669         try {
1670             if (mWrapped != null) return mWrapped.openFile(uri, mode, cancellationSignal);
1671         } catch (RemoteException e) {
1672             return null;
1673         }
1674 
1675         AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal);
1676         if (afd == null) {
1677             return null;
1678         }
1679 
1680         if (afd.getDeclaredLength() < 0) {
1681             // This is a full file!
1682             return afd.getParcelFileDescriptor();
1683         }
1684 
1685         // Client can't handle a sub-section of a file, so close what
1686         // we got and bail with an exception.
1687         try {
1688             afd.close();
1689         } catch (IOException e) {
1690         }
1691 
1692         throw new FileNotFoundException("Not a whole file");
1693     }
1694 
1695     @Override
1696     public final @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
1697             @Nullable CancellationSignal signal) throws FileNotFoundException {
1698         try {
1699             if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, signal);
1700         } catch (RemoteException e) {
1701             return null;
1702         }
1703 
1704         return openAssetFileDescriptor(uri, mode, signal);
1705     }
1706 
1707     /**
1708      * Open a raw file descriptor to access data under a URI.  This
1709      * interacts with the underlying {@link ContentProvider#openAssetFile}
1710      * method of the provider associated with the given URI, to retrieve any file stored there.
1711      *
1712      * <h5>Accepts the following URI schemes:</h5>
1713      * <ul>
1714      * <li>content ({@link #SCHEME_CONTENT})</li>
1715      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
1716      * <li>file ({@link #SCHEME_FILE})</li>
1717      * </ul>
1718      * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
1719      * <p>
1720      * A Uri object can be used to reference a resource in an APK file.  The
1721      * Uri should be one of the following formats:
1722      * <ul>
1723      * <li><code>android.resource://package_name/id_number</code><br/>
1724      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1725      * For example <code>com.example.myapp</code><br/>
1726      * <code>id_number</code> is the int form of the ID.<br/>
1727      * The easiest way to construct this form is
1728      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
1729      * </li>
1730      * <li><code>android.resource://package_name/type/name</code><br/>
1731      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1732      * For example <code>com.example.myapp</code><br/>
1733      * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
1734      * or <code>drawable</code>.
1735      * <code>name</code> is the string form of the resource name.  That is, whatever the file
1736      * name was in your res directory, without the type extension.
1737      * The easiest way to construct this form is
1738      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
1739      * </li>
1740      * </ul>
1741      *
1742      * <p>Note that if this function is called for read-only input (mode is "r")
1743      * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
1744      * for you with a MIME type of "*&#47;*".  This allows such callers to benefit
1745      * from any built-in data conversion that a provider implements.
1746      *
1747      * @param uri The desired URI to open.
1748      * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
1749      *             or "rwt". See{@link ParcelFileDescriptor#parseMode} for more details.
1750      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1751      * provider recently crashed. You own this descriptor and are responsible for closing it
1752      * when done.
1753      * @throws FileNotFoundException Throws FileNotFoundException of no
1754      * file exists under the URI or the mode is invalid.
1755      */
1756     public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
1757             @NonNull String mode) throws FileNotFoundException {
1758         return openAssetFileDescriptor(uri, mode, null);
1759     }
1760 
1761     /**
1762      * Open a raw file descriptor to access data under a URI.  This
1763      * interacts with the underlying {@link ContentProvider#openAssetFile}
1764      * method of the provider associated with the given URI, to retrieve any file stored there.
1765      *
1766      * <h5>Accepts the following URI schemes:</h5>
1767      * <ul>
1768      * <li>content ({@link #SCHEME_CONTENT})</li>
1769      * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
1770      * <li>file ({@link #SCHEME_FILE})</li>
1771      * </ul>
1772      * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
1773      * <p>
1774      * A Uri object can be used to reference a resource in an APK file.  The
1775      * Uri should be one of the following formats:
1776      * <ul>
1777      * <li><code>android.resource://package_name/id_number</code><br/>
1778      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1779      * For example <code>com.example.myapp</code><br/>
1780      * <code>id_number</code> is the int form of the ID.<br/>
1781      * The easiest way to construct this form is
1782      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
1783      * </li>
1784      * <li><code>android.resource://package_name/type/name</code><br/>
1785      * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
1786      * For example <code>com.example.myapp</code><br/>
1787      * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
1788      * or <code>drawable</code>.
1789      * <code>name</code> is the string form of the resource name.  That is, whatever the file
1790      * name was in your res directory, without the type extension.
1791      * The easiest way to construct this form is
1792      * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
1793      * </li>
1794      * </ul>
1795      *
1796      * <p>Note that if this function is called for read-only input (mode is "r")
1797      * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
1798      * for you with a MIME type of "*&#47;*".  This allows such callers to benefit
1799      * from any built-in data conversion that a provider implements.
1800      *
1801      * @param uri The desired URI to open.
1802      * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
1803      *             or "rwt". See{@link ParcelFileDescriptor#parseMode} for more details.
1804      * @param cancellationSignal A signal to cancel the operation in progress, or null if
1805      *            none. If the operation is canceled, then
1806      *            {@link OperationCanceledException} will be thrown.
1807      * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
1808      * provider recently crashed. You own this descriptor and are responsible for closing it
1809      * when done.
1810      * @throws FileNotFoundException Throws FileNotFoundException of no
1811      * file exists under the URI or the mode is invalid.
1812      */
1813     public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
1814             @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
1815                     throws FileNotFoundException {
1816         Objects.requireNonNull(uri, "uri");
1817         Objects.requireNonNull(mode, "mode");
1818 
1819         try {
1820             if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, cancellationSignal);
1821         } catch (RemoteException e) {
1822             return null;
1823         }
1824 
1825         String scheme = uri.getScheme();
1826         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
1827             if (!"r".equals(mode)) {
1828                 throw new FileNotFoundException("Can't write resources: " + uri);
1829             }
1830             OpenResourceIdResult r = getResourceId(uri);
1831             try {
1832                 return r.r.openRawResourceFd(r.id);
1833             } catch (Resources.NotFoundException ex) {
1834                 throw new FileNotFoundException("Resource does not exist: " + uri);
1835             }
1836         } else if (SCHEME_FILE.equals(scheme)) {
1837             ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
1838                     new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode));
1839             return new AssetFileDescriptor(pfd, 0, -1);
1840         } else {
1841             if ("r".equals(mode)) {
1842                 return openTypedAssetFileDescriptor(uri, "*/*", null, cancellationSignal);
1843             } else {
1844                 IContentProvider unstableProvider = acquireUnstableProvider(uri);
1845                 if (unstableProvider == null) {
1846                     throw new FileNotFoundException("No content provider: " + uri);
1847                 }
1848                 IContentProvider stableProvider = null;
1849                 AssetFileDescriptor fd = null;
1850 
1851                 try {
1852                     ICancellationSignal remoteCancellationSignal = null;
1853                     if (cancellationSignal != null) {
1854                         cancellationSignal.throwIfCanceled();
1855                         remoteCancellationSignal = unstableProvider.createCancellationSignal();
1856                         cancellationSignal.setRemote(remoteCancellationSignal);
1857                     }
1858 
1859                     try {
1860                         fd = unstableProvider.openAssetFile(
1861                                 mContext.getAttributionSource(), uri, mode,
1862                                 remoteCancellationSignal);
1863                         if (fd == null) {
1864                             // The provider will be released by the finally{} clause
1865                             return null;
1866                         }
1867                     } catch (DeadObjectException e) {
1868                         // The remote process has died...  but we only hold an unstable
1869                         // reference though, so we might recover!!!  Let's try!!!!
1870                         // This is exciting!!1!!1!!!!1
1871                         unstableProviderDied(unstableProvider);
1872                         stableProvider = acquireProvider(uri);
1873                         if (stableProvider == null) {
1874                             throw new FileNotFoundException("No content provider: " + uri);
1875                         }
1876                         fd = stableProvider.openAssetFile(mContext.getAttributionSource(),
1877                                 uri, mode, remoteCancellationSignal);
1878                         if (fd == null) {
1879                             // The provider will be released by the finally{} clause
1880                             return null;
1881                         }
1882                     }
1883 
1884                     if (stableProvider == null) {
1885                         stableProvider = acquireProvider(uri);
1886                     }
1887                     releaseUnstableProvider(unstableProvider);
1888                     unstableProvider = null;
1889                     ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
1890                             fd.getParcelFileDescriptor(), stableProvider);
1891 
1892                     // Success!  Don't release the provider when exiting, let
1893                     // ParcelFileDescriptorInner do that when it is closed.
1894                     stableProvider = null;
1895 
1896                     return new AssetFileDescriptor(pfd, fd.getStartOffset(),
1897                             fd.getDeclaredLength());
1898 
1899                 } catch (RemoteException e) {
1900                     // Whatever, whatever, we'll go away.
1901                     throw new FileNotFoundException(
1902                             "Failed opening content provider: " + uri);
1903                 } catch (FileNotFoundException e) {
1904                     throw e;
1905                 } finally {
1906                     if (cancellationSignal != null) {
1907                         cancellationSignal.setRemote(null);
1908                     }
1909                     if (stableProvider != null) {
1910                         releaseProvider(stableProvider);
1911                     }
1912                     if (unstableProvider != null) {
1913                         releaseUnstableProvider(unstableProvider);
1914                     }
1915                 }
1916             }
1917         }
1918     }
1919 
1920     @Override
1921     public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
1922             @NonNull String mimeTypeFilter, @Nullable Bundle opts,
1923             @Nullable CancellationSignal signal) throws FileNotFoundException {
1924         try {
1925             if (mWrapped != null) {
1926                 return mWrapped.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
1927             }
1928         } catch (RemoteException e) {
1929             return null;
1930         }
1931 
1932         return openTypedAssetFileDescriptor(uri, mimeTypeFilter, opts, signal);
1933     }
1934 
1935     /**
1936      * Open a raw file descriptor to access (potentially type transformed)
1937      * data from a "content:" URI.  This interacts with the underlying
1938      * {@link ContentProvider#openTypedAssetFile} method of the provider
1939      * associated with the given URI, to retrieve retrieve any appropriate
1940      * data stream for the data stored there.
1941      *
1942      * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
1943      * with "content:" URIs, because content providers are the only facility
1944      * with an associated MIME type to ensure that the returned data stream
1945      * is of the desired type.
1946      *
1947      * <p>All text/* streams are encoded in UTF-8.
1948      *
1949      * @param uri The desired URI to open.
1950      * @param mimeType The desired MIME type of the returned data.  This can
1951      * be a pattern such as *&#47;*, which will allow the content provider to
1952      * select a type, though there is no way for you to determine what type
1953      * it is returning.
1954      * @param opts Additional provider-dependent options.
1955      * @return Returns a new ParcelFileDescriptor from which you can read the
1956      * data stream from the provider or {@code null} if the provider recently crashed.
1957      * Note that this may be a pipe, meaning you can't seek in it.  The only seek you
1958      * should do is if the AssetFileDescriptor contains an offset, to move to that offset before
1959      * reading.  You own this descriptor and are responsible for closing it when done.
1960      * @throws FileNotFoundException Throws FileNotFoundException of no
1961      * data of the desired type exists under the URI.
1962      */
1963     public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
1964             @NonNull String mimeType, @Nullable Bundle opts) throws FileNotFoundException {
1965         return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
1966     }
1967 
1968     /**
1969      * Open a raw file descriptor to access (potentially type transformed)
1970      * data from a "content:" URI.  This interacts with the underlying
1971      * {@link ContentProvider#openTypedAssetFile} method of the provider
1972      * associated with the given URI, to retrieve retrieve any appropriate
1973      * data stream for the data stored there.
1974      *
1975      * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
1976      * with "content:" URIs, because content providers are the only facility
1977      * with an associated MIME type to ensure that the returned data stream
1978      * is of the desired type.
1979      *
1980      * <p>All text/* streams are encoded in UTF-8.
1981      *
1982      * @param uri The desired URI to open.
1983      * @param mimeType The desired MIME type of the returned data.  This can
1984      * be a pattern such as *&#47;*, which will allow the content provider to
1985      * select a type, though there is no way for you to determine what type
1986      * it is returning.
1987      * @param opts Additional provider-dependent options.
1988      * @param cancellationSignal A signal to cancel the operation in progress,
1989      *         or null if none. If the operation is canceled, then
1990      *         {@link OperationCanceledException} will be thrown.
1991      * @return Returns a new ParcelFileDescriptor from which you can read the
1992      * data stream from the provider or {@code null} if the provider recently crashed.
1993      * Note that this may be a pipe, meaning you can't seek in it.  The only seek you
1994      * should do is if the AssetFileDescriptor contains an offset, to move to that offset before
1995      * reading.  You own this descriptor and are responsible for closing it when done.
1996      * @throws FileNotFoundException Throws FileNotFoundException of no
1997      * data of the desired type exists under the URI.
1998      */
1999     public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
2000             @NonNull String mimeType, @Nullable Bundle opts,
2001             @Nullable CancellationSignal cancellationSignal) throws FileNotFoundException {
2002         Objects.requireNonNull(uri, "uri");
2003         Objects.requireNonNull(mimeType, "mimeType");
2004 
2005         try {
2006             if (mWrapped != null) return mWrapped.openTypedAssetFile(uri, mimeType, opts, cancellationSignal);
2007         } catch (RemoteException e) {
2008             return null;
2009         }
2010 
2011         IContentProvider unstableProvider = acquireUnstableProvider(uri);
2012         if (unstableProvider == null) {
2013             throw new FileNotFoundException("No content provider: " + uri);
2014         }
2015         IContentProvider stableProvider = null;
2016         AssetFileDescriptor fd = null;
2017 
2018         try {
2019             ICancellationSignal remoteCancellationSignal = null;
2020             if (cancellationSignal != null) {
2021                 cancellationSignal.throwIfCanceled();
2022                 remoteCancellationSignal = unstableProvider.createCancellationSignal();
2023                 cancellationSignal.setRemote(remoteCancellationSignal);
2024             }
2025 
2026             try {
2027                 fd = unstableProvider.openTypedAssetFile(
2028                         mContext.getAttributionSource(), uri, mimeType, opts,
2029                         remoteCancellationSignal);
2030                 if (fd == null) {
2031                     // The provider will be released by the finally{} clause
2032                     return null;
2033                 }
2034             } catch (DeadObjectException e) {
2035                 // The remote process has died...  but we only hold an unstable
2036                 // reference though, so we might recover!!!  Let's try!!!!
2037                 // This is exciting!!1!!1!!!!1
2038                 unstableProviderDied(unstableProvider);
2039                 stableProvider = acquireProvider(uri);
2040                 if (stableProvider == null) {
2041                     throw new FileNotFoundException("No content provider: " + uri);
2042                 }
2043                 fd = stableProvider.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             }
2051 
2052             if (stableProvider == null) {
2053                 stableProvider = acquireProvider(uri);
2054             }
2055             releaseUnstableProvider(unstableProvider);
2056             unstableProvider = null;
2057             ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
2058                     fd.getParcelFileDescriptor(), stableProvider);
2059 
2060             // Success!  Don't release the provider when exiting, let
2061             // ParcelFileDescriptorInner do that when it is closed.
2062             stableProvider = null;
2063 
2064             return new AssetFileDescriptor(pfd, fd.getStartOffset(),
2065                     fd.getDeclaredLength(), fd.getExtras());
2066 
2067         } catch (RemoteException e) {
2068             // Whatever, whatever, we'll go away.
2069             throw new FileNotFoundException(
2070                     "Failed opening content provider: " + uri);
2071         } catch (FileNotFoundException e) {
2072             throw e;
2073         } finally {
2074             if (cancellationSignal != null) {
2075                 cancellationSignal.setRemote(null);
2076             }
2077             if (stableProvider != null) {
2078                 releaseProvider(stableProvider);
2079             }
2080             if (unstableProvider != null) {
2081                 releaseUnstableProvider(unstableProvider);
2082             }
2083         }
2084     }
2085 
2086     /**
2087      * A resource identified by the {@link Resources} that contains it, and a resource id.
2088      *
2089      * @hide
2090      */
2091     public class OpenResourceIdResult {
2092         @UnsupportedAppUsage
2093         public Resources r;
2094         @UnsupportedAppUsage
2095         public int id;
2096     }
2097 
2098     /**
2099      * Resolves an android.resource URI to a {@link Resources} and a resource id.
2100      *
2101      * @hide
2102      */
2103     @UnsupportedAppUsage
2104     public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
2105         String authority = uri.getAuthority();
2106         Resources r;
2107         if (TextUtils.isEmpty(authority)) {
2108             throw new FileNotFoundException("No authority: " + uri);
2109         } else {
2110             try {
2111                 r = mContext.getPackageManager().getResourcesForApplication(authority);
2112             } catch (NameNotFoundException ex) {
2113                 throw new FileNotFoundException("No package found for authority: " + uri);
2114             }
2115         }
2116         List<String> path = uri.getPathSegments();
2117         if (path == null) {
2118             throw new FileNotFoundException("No path: " + uri);
2119         }
2120         int len = path.size();
2121         int id;
2122         if (len == 1) {
2123             try {
2124                 id = Integer.parseInt(path.get(0));
2125             } catch (NumberFormatException e) {
2126                 throw new FileNotFoundException("Single path segment is not a resource ID: " + uri);
2127             }
2128         } else if (len == 2) {
2129             id = r.getIdentifier(path.get(1), path.get(0), authority);
2130         } else {
2131             throw new FileNotFoundException("More than two path segments: " + uri);
2132         }
2133         if (id == 0) {
2134             throw new FileNotFoundException("No resource found for: " + uri);
2135         }
2136         OpenResourceIdResult res = new OpenResourceIdResult();
2137         res.r = r;
2138         res.id = id;
2139         return res;
2140     }
2141 
2142     /**
2143      * Inserts a row into a table at the given URL.
2144      *
2145      * If the content provider supports transactions the insertion will be atomic.
2146      *
2147      * @param url The URL of the table to insert into.
2148      * @param values The initial values for the newly inserted row. The key is the column name for
2149      *               the field. Passing an empty ContentValues will create an empty row.
2150      * @return the URL of the newly created row. May return <code>null</code> if the underlying
2151      *         content provider returns <code>null</code>, or if it crashes.
2152      */
2153     public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
2154                 @Nullable ContentValues values) {
2155         return insert(url, values, null);
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      * @param extras A Bundle containing additional information necessary for
2167      *            the operation. Arguments may include SQL style arguments, such
2168      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
2169      *            the documentation for each individual provider will indicate
2170      *            which arguments they support.
2171      * @return the URL of the newly created row. May return <code>null</code> if the underlying
2172      *         content provider returns <code>null</code>, or if it crashes.
2173      * @throws IllegalArgumentException if the provider doesn't support one of
2174      *             the requested Bundle arguments.
2175      */
2176     @Override
2177     public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
2178             @Nullable ContentValues values, @Nullable Bundle extras) {
2179         Objects.requireNonNull(url, "url");
2180 
2181         try {
2182             if (mWrapped != null) return mWrapped.insert(url, values, extras);
2183         } catch (RemoteException e) {
2184             return null;
2185         }
2186 
2187         IContentProvider provider = acquireProvider(url);
2188         if (provider == null) {
2189             throw new IllegalArgumentException("Unknown URL " + url);
2190         }
2191         try {
2192             long startTime = SystemClock.uptimeMillis();
2193             Uri createdRow = provider.insert(mContext.getAttributionSource(), url, values, extras);
2194             long durationMillis = SystemClock.uptimeMillis() - startTime;
2195             maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
2196             return createdRow;
2197         } catch (RemoteException e) {
2198             // Arbitrary and not worth documenting, as Activity
2199             // Manager will kill this process shortly anyway.
2200             return null;
2201         } finally {
2202             releaseProvider(provider);
2203         }
2204     }
2205 
2206     /**
2207      * Applies each of the {@link ContentProviderOperation} objects and returns an array
2208      * of their results. Passes through OperationApplicationException, which may be thrown
2209      * by the call to {@link ContentProviderOperation#apply}.
2210      * If all the applications succeed then a {@link ContentProviderResult} array with the
2211      * same number of elements as the operations will be returned. It is implementation-specific
2212      * how many, if any, operations will have been successfully applied if a call to
2213      * apply results in a {@link OperationApplicationException}.
2214      * @param authority the authority of the ContentProvider to which this batch should be applied
2215      * @param operations the operations to apply
2216      * @return the results of the applications
2217      * @throws OperationApplicationException thrown if an application fails.
2218      * See {@link ContentProviderOperation#apply} for more information.
2219      * @throws RemoteException thrown if a RemoteException is encountered while attempting
2220      *   to communicate with a remote provider.
2221      */
2222     @Override
2223     public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
2224             @NonNull ArrayList<ContentProviderOperation> operations)
2225                     throws RemoteException, OperationApplicationException {
2226         Objects.requireNonNull(authority, "authority");
2227         Objects.requireNonNull(operations, "operations");
2228 
2229         try {
2230             if (mWrapped != null) return mWrapped.applyBatch(authority, operations);
2231         } catch (RemoteException e) {
2232             return null;
2233         }
2234 
2235         ContentProviderClient provider = acquireContentProviderClient(authority);
2236         if (provider == null) {
2237             throw new IllegalArgumentException("Unknown authority " + authority);
2238         }
2239         try {
2240             return provider.applyBatch(operations);
2241         } finally {
2242             provider.release();
2243         }
2244     }
2245 
2246     /**
2247      * Inserts multiple rows into a table at the given URL.
2248      *
2249      * This function make no guarantees about the atomicity of the insertions.
2250      *
2251      * @param url The URL of the table to insert into.
2252      * @param values The initial values for the newly inserted rows. The key is the column name for
2253      *               the field. Passing null will create an empty row.
2254      * @return the number of newly created rows.
2255      */
2256     @Override
2257     public final int bulkInsert(@RequiresPermission.Write @NonNull Uri url,
2258                 @NonNull ContentValues[] values) {
2259         Objects.requireNonNull(url, "url");
2260         Objects.requireNonNull(values, "values");
2261 
2262         try {
2263             if (mWrapped != null) return mWrapped.bulkInsert(url, values);
2264         } catch (RemoteException e) {
2265             return 0;
2266         }
2267 
2268         IContentProvider provider = acquireProvider(url);
2269         if (provider == null) {
2270             throw new IllegalArgumentException("Unknown URL " + url);
2271         }
2272         try {
2273             long startTime = SystemClock.uptimeMillis();
2274             int rowsCreated = provider.bulkInsert(mContext.getAttributionSource(), url, values);
2275             long durationMillis = SystemClock.uptimeMillis() - startTime;
2276             maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
2277             return rowsCreated;
2278         } catch (RemoteException e) {
2279             // Arbitrary and not worth documenting, as Activity
2280             // Manager will kill this process shortly anyway.
2281             return 0;
2282         } finally {
2283             releaseProvider(provider);
2284         }
2285     }
2286 
2287     /**
2288      * Deletes row(s) specified by a content URI.
2289      *
2290      * If the content provider supports transactions, the deletion will be atomic.
2291      *
2292      * @param url The URL of the row to delete.
2293      * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause
2294                     (excluding the WHERE itself).
2295      * @return The number of rows deleted.
2296      */
2297     public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where,
2298             @Nullable String[] selectionArgs) {
2299         return delete(url, createSqlQueryBundle(where, selectionArgs));
2300     }
2301 
2302     /**
2303      * Deletes row(s) specified by a content URI.
2304      *
2305      * If the content provider supports transactions, the deletion will be atomic.
2306      *
2307      * @param url The URL of the row to delete.
2308      * @param extras A Bundle containing additional information necessary for
2309      *            the operation. Arguments may include SQL style arguments, such
2310      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
2311      *            the documentation for each individual provider will indicate
2312      *            which arguments they support.
2313      * @return The number of rows deleted.
2314      * @throws IllegalArgumentException if the provider doesn't support one of
2315      *             the requested Bundle arguments.
2316      */
2317     @Override
2318     public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) {
2319         Objects.requireNonNull(url, "url");
2320 
2321         try {
2322             if (mWrapped != null) return mWrapped.delete(url, extras);
2323         } catch (RemoteException e) {
2324             return 0;
2325         }
2326 
2327         IContentProvider provider = acquireProvider(url);
2328         if (provider == null) {
2329             throw new IllegalArgumentException("Unknown URL " + url);
2330         }
2331         try {
2332             long startTime = SystemClock.uptimeMillis();
2333             int rowsDeleted = provider.delete(mContext.getAttributionSource(), url, extras);
2334             long durationMillis = SystemClock.uptimeMillis() - startTime;
2335             maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
2336             return rowsDeleted;
2337         } catch (RemoteException e) {
2338             // Arbitrary and not worth documenting, as Activity
2339             // Manager will kill this process shortly anyway.
2340             return -1;
2341         } finally {
2342             releaseProvider(provider);
2343         }
2344     }
2345 
2346     /**
2347      * Update row(s) in a content URI.
2348      *
2349      * If the content provider supports transactions the update will be atomic.
2350      *
2351      * @param uri The URI to modify.
2352      * @param values The new field values. The key is the column name for the field.
2353                      A null value will remove an existing field value.
2354      * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause
2355                     (excluding the WHERE itself).
2356      * @return the number of rows updated.
2357      * @throws NullPointerException if uri or values are null
2358      */
2359     public final int update(@RequiresPermission.Write @NonNull Uri uri,
2360             @Nullable ContentValues values, @Nullable String where,
2361             @Nullable String[] selectionArgs) {
2362         return update(uri, values, createSqlQueryBundle(where, selectionArgs));
2363     }
2364 
2365     /**
2366      * Update row(s) in a content URI.
2367      *
2368      * If the content provider supports transactions the update will be atomic.
2369      *
2370      * @param uri The URI to modify.
2371      * @param values The new field values. The key is the column name for the field.
2372                      A null value will remove an existing field value.
2373      * @param extras A Bundle containing additional information necessary for
2374      *            the operation. Arguments may include SQL style arguments, such
2375      *            as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
2376      *            the documentation for each individual provider will indicate
2377      *            which arguments they support.
2378      * @return the number of rows updated.
2379      * @throws NullPointerException if uri or values are null
2380      * @throws IllegalArgumentException if the provider doesn't support one of
2381      *             the requested Bundle arguments.
2382      */
2383     @Override
2384     public final int update(@RequiresPermission.Write @NonNull Uri uri,
2385             @Nullable ContentValues values, @Nullable Bundle extras) {
2386         Objects.requireNonNull(uri, "uri");
2387 
2388         try {
2389             if (mWrapped != null) return mWrapped.update(uri, values, extras);
2390         } catch (RemoteException e) {
2391             return 0;
2392         }
2393 
2394         IContentProvider provider = acquireProvider(uri);
2395         if (provider == null) {
2396             throw new IllegalArgumentException("Unknown URI " + uri);
2397         }
2398         try {
2399             long startTime = SystemClock.uptimeMillis();
2400             int rowsUpdated = provider.update(mContext.getAttributionSource(),
2401                     uri, values, extras);
2402             long durationMillis = SystemClock.uptimeMillis() - startTime;
2403             maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
2404             return rowsUpdated;
2405         } catch (RemoteException e) {
2406             // Arbitrary and not worth documenting, as Activity
2407             // Manager will kill this process shortly anyway.
2408             return -1;
2409         } finally {
2410             releaseProvider(provider);
2411         }
2412     }
2413 
2414     /**
2415      * Call a provider-defined method.  This can be used to implement
2416      * read or write interfaces which are cheaper than using a Cursor and/or
2417      * do not fit into the traditional table model.
2418      *
2419      * @param method provider-defined method name to call.  Opaque to
2420      *   framework, but must be non-null.
2421      * @param arg provider-defined String argument.  May be null.
2422      * @param extras provider-defined Bundle argument.  May be null.
2423      * @return a result Bundle, possibly null.  Will be null if the ContentProvider
2424      *   does not implement call.
2425      * @throws NullPointerException if uri or method is null
2426      * @throws IllegalArgumentException if uri is not known
2427      */
2428     public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
2429             @Nullable String arg, @Nullable Bundle extras) {
2430         return call(uri.getAuthority(), method, arg, extras);
2431     }
2432 
2433     @Override
2434     public final @Nullable Bundle call(@NonNull String authority, @NonNull String method,
2435             @Nullable String arg, @Nullable Bundle extras) {
2436         Objects.requireNonNull(authority, "authority");
2437         Objects.requireNonNull(method, "method");
2438 
2439         try {
2440             if (mWrapped != null) return mWrapped.call(authority, method, arg, extras);
2441         } catch (RemoteException e) {
2442             return null;
2443         }
2444 
2445         IContentProvider provider = acquireProvider(authority);
2446         if (provider == null) {
2447             throw new IllegalArgumentException("Unknown authority " + authority);
2448         }
2449         try {
2450             final Bundle res = provider.call(mContext.getAttributionSource(),
2451                     authority, method, arg, extras);
2452             Bundle.setDefusable(res, true);
2453             return res;
2454         } catch (RemoteException e) {
2455             // Arbitrary and not worth documenting, as Activity
2456             // Manager will kill this process shortly anyway.
2457             return null;
2458         } finally {
2459             releaseProvider(provider);
2460         }
2461     }
2462 
2463     /**
2464      * Returns the content provider for the given content URI.
2465      *
2466      * @param uri The URI to a content provider
2467      * @return The ContentProvider for the given URI, or null if no content provider is found.
2468      * @hide
2469      */
2470     @UnsupportedAppUsage
2471     public final IContentProvider acquireProvider(Uri uri) {
2472         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
2473             return null;
2474         }
2475         final String auth = uri.getAuthority();
2476         if (auth != null) {
2477             return acquireProvider(mContext, auth);
2478         }
2479         return null;
2480     }
2481 
2482     /**
2483      * Returns the content provider for the given content URI if the process
2484      * already has a reference on it.
2485      *
2486      * @param uri The URI to a content provider
2487      * @return The ContentProvider for the given URI, or null if no content provider is found.
2488      * @hide
2489      */
2490     @UnsupportedAppUsage
2491     public final IContentProvider acquireExistingProvider(Uri uri) {
2492         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
2493             return null;
2494         }
2495         final String auth = uri.getAuthority();
2496         if (auth != null) {
2497             return acquireExistingProvider(mContext, auth);
2498         }
2499         return null;
2500     }
2501 
2502     /**
2503      * @hide
2504      */
2505     @UnsupportedAppUsage
2506     public final IContentProvider acquireProvider(String name) {
2507         if (name == null) {
2508             return null;
2509         }
2510         return acquireProvider(mContext, name);
2511     }
2512 
2513     /**
2514      * Returns the content provider for the given content URI.
2515      *
2516      * @param uri The URI to a content provider
2517      * @return The ContentProvider for the given URI, or null if no content provider is found.
2518      * @hide
2519      */
2520     public final IContentProvider acquireUnstableProvider(Uri uri) {
2521         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
2522             return null;
2523         }
2524         String auth = uri.getAuthority();
2525         if (auth != null) {
2526             return acquireUnstableProvider(mContext, uri.getAuthority());
2527         }
2528         return null;
2529     }
2530 
2531     /**
2532      * @hide
2533      */
2534     @UnsupportedAppUsage
2535     public final IContentProvider acquireUnstableProvider(String name) {
2536         if (name == null) {
2537             return null;
2538         }
2539         return acquireUnstableProvider(mContext, name);
2540     }
2541 
2542     /**
2543      * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2544      * that services the content at uri, starting the provider if necessary. Returns
2545      * null if there is no provider associated wih the uri. The caller must indicate that they are
2546      * done with the provider by calling {@link ContentProviderClient#release} which will allow
2547      * the system to release the provider if it determines that there is no other reason for
2548      * keeping it active.
2549      * @param uri specifies which provider should be acquired
2550      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2551      * that services the content at uri or null if there isn't one.
2552      */
2553     public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) {
2554         Objects.requireNonNull(uri, "uri");
2555         IContentProvider provider = acquireProvider(uri);
2556         if (provider != null) {
2557             return new ContentProviderClient(this, provider, uri.getAuthority(), true);
2558         }
2559         return null;
2560     }
2561 
2562     /**
2563      * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2564      * with the authority of name, starting the provider if necessary. Returns
2565      * null if there is no provider associated wih the uri. The caller must indicate that they are
2566      * done with the provider by calling {@link ContentProviderClient#release} which will allow
2567      * the system to release the provider if it determines that there is no other reason for
2568      * keeping it active.
2569      * @param name specifies which provider should be acquired
2570      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
2571      * with the authority of name or null if there isn't one.
2572      */
2573     public final @Nullable ContentProviderClient acquireContentProviderClient(
2574             @NonNull String name) {
2575         Objects.requireNonNull(name, "name");
2576         IContentProvider provider = acquireProvider(name);
2577         if (provider != null) {
2578             return new ContentProviderClient(this, provider, name, true);
2579         }
2580 
2581         return null;
2582     }
2583 
2584     /**
2585      * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do
2586      * not trust the stability of the target content provider.  This turns off
2587      * the mechanism in the platform clean up processes that are dependent on
2588      * a content provider if that content provider's process goes away.  Normally
2589      * you can safely assume that once you have acquired a provider, you can freely
2590      * use it as needed and it won't disappear, even if your process is in the
2591      * background.  If using this method, you need to take care to deal with any
2592      * failures when communicating with the provider, and be sure to close it
2593      * so that it can be re-opened later.  In particular, catching a
2594      * {@link android.os.DeadObjectException} from the calls there will let you
2595      * know that the content provider has gone away; at that point the current
2596      * ContentProviderClient object is invalid, and you should release it.  You
2597      * can acquire a new one if you would like to try to restart the provider
2598      * and perform new operations on it.
2599      */
2600     public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
2601             @NonNull Uri uri) {
2602         Objects.requireNonNull(uri, "uri");
2603         IContentProvider provider = acquireUnstableProvider(uri);
2604         if (provider != null) {
2605             return new ContentProviderClient(this, provider, uri.getAuthority(), false);
2606         }
2607 
2608         return null;
2609     }
2610 
2611     /**
2612      * Like {@link #acquireContentProviderClient(String)}, but for use when you do
2613      * not trust the stability of the target content provider.  This turns off
2614      * the mechanism in the platform clean up processes that are dependent on
2615      * a content provider if that content provider's process goes away.  Normally
2616      * you can safely assume that once you have acquired a provider, you can freely
2617      * use it as needed and it won't disappear, even if your process is in the
2618      * background.  If using this method, you need to take care to deal with any
2619      * failures when communicating with the provider, and be sure to close it
2620      * so that it can be re-opened later.  In particular, catching a
2621      * {@link android.os.DeadObjectException} from the calls there will let you
2622      * know that the content provider has gone away; at that point the current
2623      * ContentProviderClient object is invalid, and you should release it.  You
2624      * can acquire a new one if you would like to try to restart the provider
2625      * and perform new operations on it.
2626      */
2627     public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
2628             @NonNull String name) {
2629         Objects.requireNonNull(name, "name");
2630         IContentProvider provider = acquireUnstableProvider(name);
2631         if (provider != null) {
2632             return new ContentProviderClient(this, provider, name, false);
2633         }
2634 
2635         return null;
2636     }
2637 
2638     /**
2639      * Register an observer class that gets callbacks when data identified by a
2640      * given content URI changes.
2641      * <p>
2642      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2643      * notifications must be backed by a valid {@link ContentProvider}.
2644      *
2645      * @param uri The URI to watch for changes. This can be a specific row URI,
2646      *            or a base URI for a whole class of content.
2647      * @param notifyForDescendants When false, the observer will be notified
2648      *            whenever a change occurs to the exact URI specified by
2649      *            <code>uri</code> or to one of the URI's ancestors in the path
2650      *            hierarchy. When true, the observer will also be notified
2651      *            whenever a change occurs to the URI's descendants in the path
2652      *            hierarchy.
2653      * @param observer The object that receives callbacks when changes occur.
2654      * @see #unregisterContentObserver
2655      */
2656     public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendants,
2657             @NonNull ContentObserver observer) {
2658         Objects.requireNonNull(uri, "uri");
2659         Objects.requireNonNull(observer, "observer");
2660         registerContentObserver(
2661                 ContentProvider.getUriWithoutUserId(uri),
2662                 notifyForDescendants,
2663                 observer,
2664                 ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
2665     }
2666 
2667     /** @hide - designated user version */
2668     @UnsupportedAppUsage
2669     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
2670             ContentObserver observer, @UserIdInt int userHandle) {
2671         try {
2672             getContentService().registerContentObserver(uri, notifyForDescendents,
2673                     observer.getContentObserver(), userHandle, mTargetSdkVersion);
2674         } catch (RemoteException e) {
2675             throw e.rethrowFromSystemServer();
2676         }
2677     }
2678 
2679     /**
2680      * Unregisters a change observer.
2681      *
2682      * @param observer The previously registered observer that is no longer needed.
2683      * @see #registerContentObserver
2684      */
2685     public final void unregisterContentObserver(@NonNull ContentObserver observer) {
2686         Objects.requireNonNull(observer, "observer");
2687         try {
2688             IContentObserver contentObserver = observer.releaseContentObserver();
2689             if (contentObserver != null) {
2690                 getContentService().unregisterContentObserver(
2691                         contentObserver);
2692             }
2693         } catch (RemoteException e) {
2694             throw e.rethrowFromSystemServer();
2695         }
2696     }
2697 
2698     /**
2699      * Notify registered observers that a row was updated and attempt to sync
2700      * changes to the network.
2701      * <p>
2702      * To observe events sent through this call, use
2703      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2704      * <p>
2705      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2706      * notifications must be backed by a valid {@link ContentProvider}.
2707      *
2708      * @param uri The uri of the content that was changed.
2709      * @param observer The observer that originated the change, may be
2710      *            <code>null</null>. The observer that originated the change
2711      *            will only receive the notification if it has requested to
2712      *            receive self-change notifications by implementing
2713      *            {@link ContentObserver#deliverSelfNotifications()} to return
2714      *            true.
2715      */
2716     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
2717         notifyChange(uri, observer, true /* sync to network */);
2718     }
2719 
2720     /**
2721      * Notify registered observers that a row was updated.
2722      * <p>
2723      * To observe events sent through this call, use
2724      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2725      * <p>
2726      * If syncToNetwork is true, this will attempt to schedule a local sync
2727      * using the sync adapter that's registered for the authority of the
2728      * provided uri. No account will be passed to the sync adapter, so all
2729      * matching accounts will be synchronized.
2730      * <p>
2731      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2732      * notifications must be backed by a valid {@link ContentProvider}.
2733      *
2734      * @param uri The uri of the content that was changed.
2735      * @param observer The observer that originated the change, may be
2736      *            <code>null</null>. The observer that originated the change
2737      *            will only receive the notification if it has requested to
2738      *            receive self-change notifications by implementing
2739      *            {@link ContentObserver#deliverSelfNotifications()} to return
2740      *            true.
2741      * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
2742      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
2743      * @deprecated callers should consider migrating to
2744      *             {@link #notifyChange(Uri, ContentObserver, int)}, as it
2745      *             offers support for many more options than just
2746      *             {@link #NOTIFY_SYNC_TO_NETWORK}.
2747      */
2748     @Deprecated
2749     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
2750             boolean syncToNetwork) {
2751         notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0);
2752     }
2753 
2754     /**
2755      * Notify registered observers that a row was updated.
2756      * <p>
2757      * To observe events sent through this call, use
2758      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2759      * <p>
2760      * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule
2761      * a local sync using the sync adapter that's registered for the authority
2762      * of the provided uri. No account will be passed to the sync adapter, so
2763      * all matching accounts will be synchronized.
2764      * <p>
2765      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2766      * notifications must be backed by a valid {@link ContentProvider}.
2767      *
2768      * @param uri The uri of the content that was changed.
2769      * @param observer The observer that originated the change, may be
2770      *            <code>null</null>. The observer that originated the change
2771      *            will only receive the notification if it has requested to
2772      *            receive self-change notifications by implementing
2773      *            {@link ContentObserver#deliverSelfNotifications()} to return
2774      *            true.
2775      * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
2776      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
2777      */
2778     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
2779             @NotifyFlags int flags) {
2780         Objects.requireNonNull(uri, "uri");
2781         notifyChange(
2782                 ContentProvider.getUriWithoutUserId(uri),
2783                 observer,
2784                 flags,
2785                 ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
2786     }
2787 
2788     /** @removed */
2789     @Deprecated
2790     public void notifyChange(@NonNull Iterable<Uri> uris, @Nullable ContentObserver observer,
2791             @NotifyFlags int flags) {
2792         final Collection<Uri> asCollection = new ArrayList<>();
2793         uris.forEach(asCollection::add);
2794         notifyChange(asCollection, observer, flags);
2795     }
2796 
2797     /**
2798      * Notify registered observers that several rows have been updated.
2799      * <p>
2800      * To observe events sent through this call, use
2801      * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
2802      * <p>
2803      * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule
2804      * a local sync using the sync adapter that's registered for the authority
2805      * of the provided uri. No account will be passed to the sync adapter, so
2806      * all matching accounts will be synchronized.
2807      * <p>
2808      * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
2809      * notifications must be backed by a valid {@link ContentProvider}.
2810      *
2811      * @param uris The uris of the content that was changed.
2812      * @param observer The observer that originated the change, may be
2813      *            <code>null</null>. The observer that originated the change
2814      *            will only receive the notification if it has requested to
2815      *            receive self-change notifications by implementing
2816      *            {@link ContentObserver#deliverSelfNotifications()} to return
2817      *            true.
2818      * @param flags Flags such as {@link #NOTIFY_SYNC_TO_NETWORK} or
2819      *            {@link #NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS}.
2820      */
2821     public void notifyChange(@NonNull Collection<Uri> uris, @Nullable ContentObserver observer,
2822             @NotifyFlags int flags) {
2823         Objects.requireNonNull(uris, "uris");
2824 
2825         // Cluster based on user ID
2826         final SparseArray<ArrayList<Uri>> clusteredByUser = new SparseArray<>();
2827         for (Uri uri : uris) {
2828             final int userId = ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
2829             ArrayList<Uri> list = clusteredByUser.get(userId);
2830             if (list == null) {
2831                 list = new ArrayList<>();
2832                 clusteredByUser.put(userId, list);
2833             }
2834             list.add(ContentProvider.getUriWithoutUserId(uri));
2835         }
2836 
2837         for (int i = 0; i < clusteredByUser.size(); i++) {
2838             final int userId = clusteredByUser.keyAt(i);
2839             final ArrayList<Uri> list = clusteredByUser.valueAt(i);
2840             notifyChange(list.toArray(new Uri[list.size()]), observer, flags, userId);
2841         }
2842     }
2843 
2844     /**
2845      * Notify registered observers within the designated user(s) that a row was updated.
2846      *
2847      * @deprecated callers should consider migrating to
2848      *             {@link #notifyChange(Uri, ContentObserver, int)}, as it
2849      *             offers support for many more options than just
2850      *             {@link #NOTIFY_SYNC_TO_NETWORK}.
2851      * @hide
2852      */
2853     @Deprecated
2854     public void notifyChange(@NonNull Uri uri, ContentObserver observer, boolean syncToNetwork,
2855             @UserIdInt int userHandle) {
2856         notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0, userHandle);
2857     }
2858 
2859     /** {@hide} */
2860     public void notifyChange(@NonNull Uri uri, ContentObserver observer, @NotifyFlags int flags,
2861             @UserIdInt int userHandle) {
2862         notifyChange(new Uri[] { uri }, observer, flags, userHandle);
2863     }
2864 
2865     /**
2866      * Notify registered observers within the designated user(s) that a row was updated.
2867      *
2868      * @hide
2869      */
2870     public void notifyChange(@NonNull Uri[] uris, ContentObserver observer, @NotifyFlags int flags,
2871             @UserIdInt int userHandle) {
2872         try {
2873             getContentService().notifyChange(
2874                     uris, observer == null ? null : observer.getContentObserver(),
2875                     observer != null && observer.deliverSelfNotifications(), flags,
2876                     userHandle, mTargetSdkVersion, mContext.getPackageName());
2877         } catch (RemoteException e) {
2878             throw e.rethrowFromSystemServer();
2879         }
2880     }
2881 
2882     /**
2883      * Take a persistable URI permission grant that has been offered. Once
2884      * taken, the permission grant will be remembered across device reboots.
2885      * Only URI permissions granted with
2886      * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} can be persisted. If
2887      * the grant has already been persisted, taking it again will touch
2888      * {@link UriPermission#getPersistedTime()}.
2889      *
2890      * @see #getPersistedUriPermissions()
2891      */
2892     public void takePersistableUriPermission(@NonNull Uri uri,
2893             @Intent.AccessUriMode int modeFlags) {
2894         Objects.requireNonNull(uri, "uri");
2895         try {
2896             UriGrantsManager.getService().takePersistableUriPermission(
2897                     ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
2898                     resolveUserId(uri));
2899         } catch (RemoteException e) {
2900             throw e.rethrowFromSystemServer();
2901         }
2902     }
2903 
2904     /**
2905      * @hide
2906      */
2907     @UnsupportedAppUsage
2908     public void takePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri,
2909             @Intent.AccessUriMode int modeFlags) {
2910         Objects.requireNonNull(toPackage, "toPackage");
2911         Objects.requireNonNull(uri, "uri");
2912         try {
2913             UriGrantsManager.getService().takePersistableUriPermission(
2914                     ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage,
2915                     resolveUserId(uri));
2916         } catch (RemoteException e) {
2917             throw e.rethrowFromSystemServer();
2918         }
2919     }
2920 
2921     /**
2922      * Relinquish a persisted URI permission grant. The URI must have been
2923      * previously made persistent with
2924      * {@link #takePersistableUriPermission(Uri, int)}. Any non-persistent
2925      * grants to the calling package will remain intact.
2926      *
2927      * @see #getPersistedUriPermissions()
2928      */
2929     public void releasePersistableUriPermission(@NonNull Uri uri,
2930             @Intent.AccessUriMode int modeFlags) {
2931         Objects.requireNonNull(uri, "uri");
2932         try {
2933             UriGrantsManager.getService().releasePersistableUriPermission(
2934                     ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
2935                     resolveUserId(uri));
2936         } catch (RemoteException e) {
2937             throw e.rethrowFromSystemServer();
2938         }
2939     }
2940 
2941     /**
2942      * Return list of all URI permission grants that have been persisted by the
2943      * calling app. That is, the returned permissions have been granted
2944      * <em>to</em> the calling app. Only persistable grants taken with
2945      * {@link #takePersistableUriPermission(Uri, int)} are returned.
2946      * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked.
2947      *
2948      * @see #takePersistableUriPermission(Uri, int)
2949      * @see #releasePersistableUriPermission(Uri, int)
2950      */
2951     public @NonNull List<UriPermission> getPersistedUriPermissions() {
2952         try {
2953             return UriGrantsManager.getService().getUriPermissions(
2954                     mPackageName, true /* incoming */, true /* persistedOnly */).getList();
2955         } catch (RemoteException e) {
2956             throw e.rethrowFromSystemServer();
2957         }
2958     }
2959 
2960     /**
2961      * Return list of all persisted URI permission grants that are hosted by the
2962      * calling app. That is, the returned permissions have been granted
2963      * <em>from</em> the calling app. Only grants taken with
2964      * {@link #takePersistableUriPermission(Uri, int)} are returned.
2965      * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked.
2966      */
2967     public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
2968         try {
2969             return UriGrantsManager.getService().getUriPermissions(
2970                     mPackageName, false /* incoming */, true /* persistedOnly */).getList();
2971         } catch (RemoteException e) {
2972             throw e.rethrowFromSystemServer();
2973         }
2974     }
2975 
2976     /** @hide */
2977     public @NonNull List<UriPermission> getOutgoingUriPermissions() {
2978         try {
2979             return UriGrantsManager.getService().getUriPermissions(
2980                     mPackageName, false /* incoming */, false /* persistedOnly */).getList();
2981         } catch (RemoteException e) {
2982             throw e.rethrowFromSystemServer();
2983         }
2984     }
2985 
2986     /**
2987      * Start an asynchronous sync operation. If you want to monitor the progress
2988      * of the sync you may register a SyncObserver. Only values of the following
2989      * types may be used in the extras bundle:
2990      * <ul>
2991      * <li>Integer</li>
2992      * <li>Long</li>
2993      * <li>Boolean</li>
2994      * <li>Float</li>
2995      * <li>Double</li>
2996      * <li>String</li>
2997      * <li>Account</li>
2998      * <li>null</li>
2999      * </ul>
3000      *
3001      * @param uri the uri of the provider to sync or null to sync all providers.
3002      * @param extras any extras to pass to the SyncAdapter.
3003      * @deprecated instead use
3004      * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
3005      */
3006     @Deprecated
3007     public void startSync(Uri uri, Bundle extras) {
3008         Account account = null;
3009         if (extras != null) {
3010             String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT);
3011             if (!TextUtils.isEmpty(accountName)) {
3012                 // TODO: No references to Google in AOSP
3013                 account = new Account(accountName, "com.google");
3014             }
3015             extras.remove(SYNC_EXTRAS_ACCOUNT);
3016         }
3017         requestSync(account, uri != null ? uri.getAuthority() : null, extras);
3018     }
3019 
3020     /**
3021      * Start an asynchronous sync operation. If you want to monitor the progress
3022      * of the sync you may register a SyncObserver. Only values of the following
3023      * types may be used in the extras bundle:
3024      * <ul>
3025      * <li>Integer</li>
3026      * <li>Long</li>
3027      * <li>Boolean</li>
3028      * <li>Float</li>
3029      * <li>Double</li>
3030      * <li>String</li>
3031      * <li>Account</li>
3032      * <li>null</li>
3033      * </ul>
3034      *
3035      * @param account which account should be synced
3036      * @param authority which authority should be synced
3037      * @param extras any extras to pass to the SyncAdapter.
3038      */
3039     public static void requestSync(Account account, String authority, Bundle extras) {
3040         requestSyncAsUser(account, authority, UserHandle.myUserId(), extras);
3041     }
3042 
3043     /**
3044      * @see #requestSync(Account, String, Bundle)
3045      * @hide
3046      */
3047     public static void requestSyncAsUser(Account account, String authority, @UserIdInt int userId,
3048             Bundle extras) {
3049         if (extras == null) {
3050             throw new IllegalArgumentException("Must specify extras.");
3051         }
3052         SyncRequest request =
3053             new SyncRequest.Builder()
3054                 .setSyncAdapter(account, authority)
3055                 .setExtras(extras)
3056                 .syncOnce()     // Immediate sync.
3057                 .build();
3058         try {
3059             // Note ActivityThread.currentPackageName() may not be accurate in a shared process
3060             // case, but it's only for debugging.
3061             getContentService().syncAsUser(request, userId, ActivityThread.currentPackageName());
3062         } catch(RemoteException e) {
3063             throw e.rethrowFromSystemServer();
3064         }
3065     }
3066 
3067     /**
3068      * Register a sync with the SyncManager. These requests are built using the
3069      * {@link SyncRequest.Builder}.
3070      */
3071     public static void requestSync(SyncRequest request) {
3072         try {
3073             // Note ActivityThread.currentPackageName() may not be accurate in a shared process
3074             // case, but it's only for debugging.
3075             getContentService().sync(request, ActivityThread.currentPackageName());
3076         } catch(RemoteException e) {
3077             throw e.rethrowFromSystemServer();
3078         }
3079     }
3080 
3081     /**
3082      * Check that only values of the following types are in the Bundle:
3083      * <ul>
3084      * <li>Integer</li>
3085      * <li>Long</li>
3086      * <li>Boolean</li>
3087      * <li>Float</li>
3088      * <li>Double</li>
3089      * <li>String</li>
3090      * <li>Account</li>
3091      * <li>null</li>
3092      * </ul>
3093      * @param extras the Bundle to check
3094      */
3095     public static void validateSyncExtrasBundle(Bundle extras) {
3096         try {
3097             for (String key : extras.keySet()) {
3098                 Object value = extras.get(key);
3099                 if (value == null) continue;
3100                 if (value instanceof Long) continue;
3101                 if (value instanceof Integer) continue;
3102                 if (value instanceof Boolean) continue;
3103                 if (value instanceof Float) continue;
3104                 if (value instanceof Double) continue;
3105                 if (value instanceof String) continue;
3106                 if (value instanceof Account) continue;
3107                 throw new IllegalArgumentException("unexpected value type: "
3108                         + value.getClass().getName());
3109             }
3110         } catch (IllegalArgumentException e) {
3111             throw e;
3112         } catch (RuntimeException exc) {
3113             throw new IllegalArgumentException("error unparceling Bundle", exc);
3114         }
3115     }
3116 
3117     /**
3118      * Cancel any active or pending syncs that match the Uri. If the uri is null then
3119      * all syncs will be canceled.
3120      *
3121      * @param uri the uri of the provider to sync or null to sync all providers.
3122      * @deprecated instead use {@link #cancelSync(android.accounts.Account, String)}
3123      */
3124     @Deprecated
3125     public void cancelSync(Uri uri) {
3126         cancelSync(null /* all accounts */, uri != null ? uri.getAuthority() : null);
3127     }
3128 
3129     /**
3130      * Cancel any active or pending syncs that match account and authority. The account and
3131      * authority can each independently be set to null, which means that syncs with any account
3132      * or authority, respectively, will match.
3133      *
3134      * @param account filters the syncs that match by this account
3135      * @param authority filters the syncs that match by this authority
3136      */
3137     public static void cancelSync(Account account, String authority) {
3138         try {
3139             getContentService().cancelSync(account, authority, null);
3140         } catch (RemoteException e) {
3141             throw e.rethrowFromSystemServer();
3142         }
3143     }
3144 
3145     /**
3146      * @see #cancelSync(Account, String)
3147      * @hide
3148      */
3149     public static void cancelSyncAsUser(Account account, String authority, @UserIdInt int userId) {
3150         try {
3151             getContentService().cancelSyncAsUser(account, authority, null, userId);
3152         } catch (RemoteException e) {
3153             throw e.rethrowFromSystemServer();
3154         }
3155     }
3156 
3157     /**
3158      * Get information about the SyncAdapters that are known to the system.
3159      * @return an array of SyncAdapters that have registered with the system
3160      */
3161     public static SyncAdapterType[] getSyncAdapterTypes() {
3162         try {
3163             return getContentService().getSyncAdapterTypes();
3164         } catch (RemoteException e) {
3165             throw e.rethrowFromSystemServer();
3166         }
3167     }
3168 
3169     /**
3170      * @see #getSyncAdapterTypes()
3171      * @hide
3172      */
3173     public static SyncAdapterType[] getSyncAdapterTypesAsUser(@UserIdInt int userId) {
3174         try {
3175             return getContentService().getSyncAdapterTypesAsUser(userId);
3176         } catch (RemoteException e) {
3177             throw e.rethrowFromSystemServer();
3178         }
3179     }
3180 
3181     /**
3182      * @hide
3183      * Returns the package names of syncadapters that match a given user and authority.
3184      */
3185     @TestApi
3186     public static String[] getSyncAdapterPackagesForAuthorityAsUser(String authority,
3187             @UserIdInt int userId) {
3188         try {
3189             return getContentService().getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
3190         } catch (RemoteException e) {
3191             throw e.rethrowFromSystemServer();
3192         }
3193     }
3194 
3195     /**
3196      * Check if the provider should be synced when a network tickle is received
3197      * <p>This method requires the caller to hold the permission
3198      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3199      *
3200      * @param account the account whose setting we are querying
3201      * @param authority the provider whose setting we are querying
3202      * @return true if the provider should be synced when a network tickle is received
3203      */
3204     public static boolean getSyncAutomatically(Account account, String authority) {
3205         try {
3206             return getContentService().getSyncAutomatically(account, authority);
3207         } catch (RemoteException e) {
3208             throw e.rethrowFromSystemServer();
3209         }
3210     }
3211 
3212     /**
3213      * @see #getSyncAutomatically(Account, String)
3214      * @hide
3215      */
3216     public static boolean getSyncAutomaticallyAsUser(Account account, String authority,
3217             @UserIdInt int userId) {
3218         try {
3219             return getContentService().getSyncAutomaticallyAsUser(account, authority, userId);
3220         } catch (RemoteException e) {
3221             throw e.rethrowFromSystemServer();
3222         }
3223     }
3224 
3225     /**
3226      * Set whether or not the provider is synced when it receives a network tickle.
3227      * <p>This method requires the caller to hold the permission
3228      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3229      *
3230      * @param account the account whose setting we are querying
3231      * @param authority the provider whose behavior is being controlled
3232      * @param sync true if the provider should be synced when tickles are received for it
3233      */
3234     public static void setSyncAutomatically(Account account, String authority, boolean sync) {
3235         setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.myUserId());
3236     }
3237 
3238     /**
3239      * @see #setSyncAutomatically(Account, String, boolean)
3240      * @hide
3241      */
3242     public static void setSyncAutomaticallyAsUser(Account account, String authority, boolean sync,
3243             @UserIdInt int userId) {
3244         try {
3245             getContentService().setSyncAutomaticallyAsUser(account, authority, sync, userId);
3246         } catch (RemoteException e) {
3247             throw e.rethrowFromSystemServer();
3248         }
3249     }
3250 
3251     /**
3252      * {@hide}
3253      * Helper function to throw an <code>IllegalArgumentException</code> if any illegal
3254      * extras were set for a sync scheduled as an expedited job.
3255      *
3256      * @param extras bundle to validate.
3257      */
3258     public static boolean hasInvalidScheduleAsEjExtras(Bundle extras) {
3259         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING)
3260                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED);
3261     }
3262 
3263     /**
3264      * Specifies that a sync should be requested with the specified the account, authority,
3265      * and extras at the given frequency. If there is already another periodic sync scheduled
3266      * with the account, authority and extras then a new periodic sync won't be added, instead
3267      * the frequency of the previous one will be updated.
3268      * <p>
3269      * These periodic syncs honor the "syncAutomatically" and "masterSyncAutomatically" settings.
3270      * Although these sync are scheduled at the specified frequency, it may take longer for it to
3271      * actually be started if other syncs are ahead of it in the sync operation queue. This means
3272      * that the actual start time may drift.
3273      * <p>
3274      * Periodic syncs are not allowed to have any of {@link #SYNC_EXTRAS_DO_NOT_RETRY},
3275      * {@link #SYNC_EXTRAS_IGNORE_BACKOFF}, {@link #SYNC_EXTRAS_IGNORE_SETTINGS},
3276      * {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE},
3277      * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL},
3278      * {@link #SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB} set to true.
3279      * If any are supplied then an {@link IllegalArgumentException} will be thrown.
3280      *
3281      * <p>This method requires the caller to hold the permission
3282      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3283      * <p>The bundle for a periodic sync can be queried by applications with the correct
3284      * permissions using
3285      * {@link ContentResolver#getPeriodicSyncs(Account account, String provider)}, so no
3286      * sensitive data should be transferred here.
3287      *
3288      * @param account the account to specify in the sync
3289      * @param authority the provider to specify in the sync request
3290      * @param extras extra parameters to go along with the sync request
3291      * @param pollFrequency how frequently the sync should be performed, in seconds.
3292      * On Android API level 24 and above, a minmam interval of 15 minutes is enforced.
3293      * On previous versions, the minimum interval is 1 hour.
3294      * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters
3295      * are null.
3296      */
3297     public static void addPeriodicSync(Account account, String authority, Bundle extras,
3298             long pollFrequency) {
3299         validateSyncExtrasBundle(extras);
3300         if (invalidPeriodicExtras(extras)) {
3301             throw new IllegalArgumentException("illegal extras were set");
3302         }
3303         try {
3304              getContentService().addPeriodicSync(account, authority, extras, pollFrequency);
3305         } catch (RemoteException e) {
3306             throw e.rethrowFromSystemServer();
3307         }
3308     }
3309 
3310     /**
3311      * {@hide}
3312      * Helper function to throw an <code>IllegalArgumentException</code> if any illegal
3313      * extras were set for a periodic sync.
3314      *
3315      * @param extras bundle to validate.
3316      */
3317     public static boolean invalidPeriodicExtras(Bundle extras) {
3318         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)
3319                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
3320                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)
3321                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
3322                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)
3323                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)
3324                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)
3325                 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false);
3326     }
3327 
3328     /**
3329      * Remove a periodic sync. Has no affect if account, authority and extras don't match
3330      * an existing periodic sync.
3331      * <p>This method requires the caller to hold the permission
3332      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3333      *
3334      * @param account the account of the periodic sync to remove
3335      * @param authority the provider of the periodic sync to remove
3336      * @param extras the extras of the periodic sync to remove
3337      */
3338     public static void removePeriodicSync(Account account, String authority, Bundle extras) {
3339         validateSyncExtrasBundle(extras);
3340         try {
3341             getContentService().removePeriodicSync(account, authority, extras);
3342         } catch (RemoteException e) {
3343             throw e.rethrowFromSystemServer();
3344         }
3345     }
3346 
3347     /**
3348      * Remove the specified sync. This will cancel any pending or active syncs. If the request is
3349      * for a periodic sync, this call will remove any future occurrences.
3350      * <p>
3351      *     If a periodic sync is specified, the caller must hold the permission
3352      *     {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3353      *</p>
3354      * It is possible to cancel a sync using a SyncRequest object that is not the same object
3355      * with which you requested the sync. Do so by building a SyncRequest with the same
3356      * adapter, frequency, <b>and</b> extras bundle.
3357      *
3358      * @param request SyncRequest object containing information about sync to cancel.
3359      */
3360     public static void cancelSync(SyncRequest request) {
3361         if (request == null) {
3362             throw new IllegalArgumentException("request cannot be null");
3363         }
3364         try {
3365             getContentService().cancelRequest(request);
3366         } catch (RemoteException e) {
3367             throw e.rethrowFromSystemServer();
3368         }
3369     }
3370 
3371     /**
3372      * Get the list of information about the periodic syncs for the given account and authority.
3373      * <p>This method requires the caller to hold the permission
3374      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3375      *
3376      * @param account the account whose periodic syncs we are querying
3377      * @param authority the provider whose periodic syncs we are querying
3378      * @return a list of PeriodicSync objects. This list may be empty but will never be null.
3379      */
3380     public static List<PeriodicSync> getPeriodicSyncs(Account account, String authority) {
3381         try {
3382             return getContentService().getPeriodicSyncs(account, authority, null);
3383         } catch (RemoteException e) {
3384             throw e.rethrowFromSystemServer();
3385         }
3386     }
3387 
3388     /**
3389      * Check if this account/provider is syncable.
3390      * <p>This method requires the caller to hold the permission
3391      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3392      * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
3393      */
3394     public static int getIsSyncable(Account account, String authority) {
3395         try {
3396             return getContentService().getIsSyncable(account, authority);
3397         } catch (RemoteException e) {
3398             throw e.rethrowFromSystemServer();
3399         }
3400     }
3401 
3402     /**
3403      * @see #getIsSyncable(Account, String)
3404      * @hide
3405      */
3406     public static int getIsSyncableAsUser(Account account, String authority,
3407             @UserIdInt int userId) {
3408         try {
3409             return getContentService().getIsSyncableAsUser(account, authority, userId);
3410         } catch (RemoteException e) {
3411             throw e.rethrowFromSystemServer();
3412         }
3413     }
3414 
3415     /**
3416      * Set whether this account/provider is syncable.
3417      * <p>This method requires the caller to hold the permission
3418      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3419      * @param syncable >0 denotes syncable, 0 means not syncable, <0 means unknown
3420      */
3421     public static void setIsSyncable(Account account, String authority, int syncable) {
3422         try {
3423             getContentService().setIsSyncable(account, authority, syncable);
3424         } catch (RemoteException e) {
3425             throw e.rethrowFromSystemServer();
3426         }
3427     }
3428 
3429     /**
3430      * @see #setIsSyncable(Account, String, int)
3431      * @hide
3432      */
3433     public static void setIsSyncableAsUser(Account account, String authority, int syncable,
3434             int userId) {
3435         try {
3436             getContentService().setIsSyncableAsUser(account, authority, syncable, userId);
3437         } catch (RemoteException e) {
3438             throw e.rethrowFromSystemServer();
3439         }
3440     }
3441 
3442     /**
3443      * Gets the global auto-sync setting that applies to all the providers and accounts.
3444      * If this is false then the per-provider auto-sync setting is ignored.
3445      * <p>This method requires the caller to hold the permission
3446      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
3447      *
3448      * @return the global auto-sync setting that applies to all the providers and accounts
3449      */
3450     public static boolean getMasterSyncAutomatically() {
3451         try {
3452             return getContentService().getMasterSyncAutomatically();
3453         } catch (RemoteException e) {
3454             throw e.rethrowFromSystemServer();
3455         }
3456     }
3457 
3458     /**
3459      * @see #getMasterSyncAutomatically()
3460      * @hide
3461      */
3462     public static boolean getMasterSyncAutomaticallyAsUser(@UserIdInt int userId) {
3463         try {
3464             return getContentService().getMasterSyncAutomaticallyAsUser(userId);
3465         } catch (RemoteException e) {
3466             throw e.rethrowFromSystemServer();
3467         }
3468     }
3469 
3470     /**
3471      * Sets the global auto-sync setting that applies to all the providers and accounts.
3472      * If this is false then the per-provider auto-sync setting is ignored.
3473      * <p>This method requires the caller to hold the permission
3474      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
3475      *
3476      * @param sync the global auto-sync setting that applies to all the providers and accounts
3477      */
3478     public static void setMasterSyncAutomatically(boolean sync) {
3479         setMasterSyncAutomaticallyAsUser(sync, UserHandle.myUserId());
3480     }
3481 
3482     /**
3483      * @see #setMasterSyncAutomatically(boolean)
3484      * @hide
3485      */
3486     public static void setMasterSyncAutomaticallyAsUser(boolean sync, @UserIdInt int userId) {
3487         try {
3488             getContentService().setMasterSyncAutomaticallyAsUser(sync, userId);
3489         } catch (RemoteException e) {
3490             throw e.rethrowFromSystemServer();
3491         }
3492     }
3493 
3494     /**
3495      * Returns true if there is currently a sync operation for the given account or authority
3496      * actively being processed.
3497      * <p>This method requires the caller to hold the permission
3498      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3499      * @param account the account whose setting we are querying
3500      * @param authority the provider whose behavior is being queried
3501      * @return true if a sync is active for the given account or authority.
3502      */
3503     public static boolean isSyncActive(Account account, String authority) {
3504         if (account == null) {
3505             throw new IllegalArgumentException("account must not be null");
3506         }
3507         if (authority == null) {
3508             throw new IllegalArgumentException("authority must not be null");
3509         }
3510 
3511         try {
3512             return getContentService().isSyncActive(account, authority, null);
3513         } catch (RemoteException e) {
3514             throw e.rethrowFromSystemServer();
3515         }
3516     }
3517 
3518     /**
3519      * If a sync is active returns the information about it, otherwise returns null.
3520      * <p>
3521      * This method requires the caller to hold the permission
3522      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3523      * <p>
3524      * @return the SyncInfo for the currently active sync or null if one is not active.
3525      * @deprecated
3526      * Since multiple concurrent syncs are now supported you should use
3527      * {@link #getCurrentSyncs()} to get the accurate list of current syncs.
3528      * This method returns the first item from the list of current syncs
3529      * or null if there are none.
3530      */
3531     @Deprecated
3532     public static SyncInfo getCurrentSync() {
3533         try {
3534             final List<SyncInfo> syncs = getContentService().getCurrentSyncs();
3535             if (syncs.isEmpty()) {
3536                 return null;
3537             }
3538             return syncs.get(0);
3539         } catch (RemoteException e) {
3540             throw e.rethrowFromSystemServer();
3541         }
3542     }
3543 
3544     /**
3545      * Returns a list with information about all the active syncs. This list will be empty
3546      * if there are no active syncs.
3547      * <p>
3548      * This method requires the caller to hold the permission
3549      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3550      * <p>
3551      * @return a List of SyncInfo objects for the currently active syncs.
3552      */
3553     public static List<SyncInfo> getCurrentSyncs() {
3554         try {
3555             return getContentService().getCurrentSyncs();
3556         } catch (RemoteException e) {
3557             throw e.rethrowFromSystemServer();
3558         }
3559     }
3560 
3561     /**
3562      * @see #getCurrentSyncs()
3563      * @hide
3564      */
3565     public static List<SyncInfo> getCurrentSyncsAsUser(@UserIdInt int userId) {
3566         try {
3567             return getContentService().getCurrentSyncsAsUser(userId);
3568         } catch (RemoteException e) {
3569             throw e.rethrowFromSystemServer();
3570         }
3571     }
3572 
3573     /**
3574      * Returns the status that matches the authority.
3575      * @param account the account whose setting we are querying
3576      * @param authority the provider whose behavior is being queried
3577      * @return the SyncStatusInfo for the authority, or null if none exists
3578      * @hide
3579      */
3580     @UnsupportedAppUsage
3581     public static SyncStatusInfo getSyncStatus(Account account, String authority) {
3582         try {
3583             return getContentService().getSyncStatus(account, authority, null);
3584         } catch (RemoteException e) {
3585             throw e.rethrowFromSystemServer();
3586         }
3587     }
3588 
3589     /**
3590      * @see #getSyncStatus(Account, String)
3591      * @hide
3592      */
3593     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3594     public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
3595             @UserIdInt int userId) {
3596         try {
3597             return getContentService().getSyncStatusAsUser(account, authority, null, userId);
3598         } catch (RemoteException e) {
3599             throw e.rethrowFromSystemServer();
3600         }
3601     }
3602 
3603     /**
3604      * Return true if the pending status is true of any matching authorities.
3605      * <p>This method requires the caller to hold the permission
3606      * {@link android.Manifest.permission#READ_SYNC_STATS}.
3607      * @param account the account whose setting we are querying
3608      * @param authority the provider whose behavior is being queried
3609      * @return true if there is a pending sync with the matching account and authority
3610      */
3611     public static boolean isSyncPending(Account account, String authority) {
3612         return isSyncPendingAsUser(account, authority, UserHandle.myUserId());
3613     }
3614 
3615     /**
3616      * @see #requestSync(Account, String, Bundle)
3617      * @hide
3618      */
3619     public static boolean isSyncPendingAsUser(Account account, String authority,
3620             @UserIdInt int userId) {
3621         try {
3622             return getContentService().isSyncPendingAsUser(account, authority, null, userId);
3623         } catch (RemoteException e) {
3624             throw e.rethrowFromSystemServer();
3625         }
3626     }
3627 
3628     /**
3629      * Request notifications when the different aspects of the SyncManager change. The
3630      * different items that can be requested are:
3631      * <ul>
3632      * <li> {@link #SYNC_OBSERVER_TYPE_PENDING}
3633      * <li> {@link #SYNC_OBSERVER_TYPE_ACTIVE}
3634      * <li> {@link #SYNC_OBSERVER_TYPE_SETTINGS}
3635      * </ul>
3636      * The caller can set one or more of the status types in the mask for any
3637      * given listener registration.
3638      * @param mask the status change types that will cause the callback to be invoked
3639      * @param callback observer to be invoked when the status changes
3640      * @return a handle that can be used to remove the listener at a later time
3641      */
3642     public static Object addStatusChangeListener(int mask, final SyncStatusObserver callback) {
3643         if (callback == null) {
3644             throw new IllegalArgumentException("you passed in a null callback");
3645         }
3646         try {
3647             ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
3648                 @Override
3649                 public void onStatusChanged(int which) throws RemoteException {
3650                     callback.onStatusChanged(which);
3651                 }
3652             };
3653             getContentService().addStatusChangeListener(mask, observer);
3654             return observer;
3655         } catch (RemoteException e) {
3656             throw e.rethrowFromSystemServer();
3657         }
3658     }
3659 
3660     /**
3661      * Remove a previously registered status change listener.
3662      * @param handle the handle that was returned by {@link #addStatusChangeListener}
3663      */
3664     public static void removeStatusChangeListener(Object handle) {
3665         if (handle == null) {
3666             throw new IllegalArgumentException("you passed in a null handle");
3667         }
3668         try {
3669             getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle);
3670         } catch (RemoteException e) {
3671             throw e.rethrowFromSystemServer();
3672         }
3673     }
3674 
3675     /**
3676      * Store the given {@link Bundle} as a long-lived cached object within the
3677      * system. This can be useful to avoid expensive re-parsing when apps are
3678      * restarted multiple times on low-RAM devices.
3679      * <p>
3680      * The {@link Bundle} is automatically invalidated when a
3681      * {@link #notifyChange(Uri, ContentObserver)} event applies to the key.
3682      *
3683      * @hide
3684      */
3685     @SystemApi
3686     @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
3687     public void putCache(@NonNull Uri key, @Nullable Bundle value) {
3688         try {
3689             getContentService().putCache(mContext.getPackageName(), key, value,
3690                     mContext.getUserId());
3691         } catch (RemoteException e) {
3692             throw e.rethrowFromSystemServer();
3693         }
3694     }
3695 
3696     /**
3697      * Retrieve the last {@link Bundle} stored as a long-lived cached object
3698      * within the system.
3699      *
3700      * @return {@code null} if no cached object has been stored, or if the
3701      *         stored object has been invalidated due to a
3702      *         {@link #notifyChange(Uri, ContentObserver)} event.
3703      * @hide
3704      */
3705     @SystemApi
3706     @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
3707     public @Nullable Bundle getCache(@NonNull Uri key) {
3708         try {
3709             final Bundle bundle = getContentService().getCache(mContext.getPackageName(), key,
3710                     mContext.getUserId());
3711             if (bundle != null) bundle.setClassLoader(mContext.getClassLoader());
3712             return bundle;
3713         } catch (RemoteException e) {
3714             throw e.rethrowFromSystemServer();
3715         }
3716     }
3717 
3718     /** {@hide} */
3719     public int getTargetSdkVersion() {
3720         return mTargetSdkVersion;
3721     }
3722 
3723     /**
3724      * Returns sampling percentage for a given duration.
3725      *
3726      * Always returns at least 1%.
3727      */
3728     private int samplePercentForDuration(long durationMillis) {
3729         if (durationMillis >= SLOW_THRESHOLD_MILLIS) {
3730             return 100;
3731         }
3732         return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
3733     }
3734 
3735     private void maybeLogQueryToEventLog(
3736             long durationMillis, Uri uri, String[] projection, @Nullable Bundle queryArgs) {
3737         if (!ENABLE_CONTENT_SAMPLE) return;
3738         int samplePercent = samplePercentForDuration(durationMillis);
3739         if (samplePercent < 100) {
3740             synchronized (mRandom) {
3741                 if (mRandom.nextInt(100) >= samplePercent) {
3742                     return;
3743                 }
3744             }
3745         }
3746 
3747         // Ensure a non-null bundle.
3748         queryArgs = (queryArgs != null) ? queryArgs : Bundle.EMPTY;
3749 
3750         StringBuilder projectionBuffer = new StringBuilder(100);
3751         if (projection != null) {
3752             for (int i = 0; i < projection.length; ++i) {
3753                 // Note: not using a comma delimiter here, as the
3754                 // multiple arguments to EventLog.writeEvent later
3755                 // stringify with a comma delimiter, which would make
3756                 // parsing uglier later.
3757                 if (i != 0) projectionBuffer.append('/');
3758                 projectionBuffer.append(projection[i]);
3759             }
3760         }
3761 
3762         // ActivityThread.currentPackageName() only returns non-null if the
3763         // current thread is an application main thread.  This parameter tells
3764         // us whether an event loop is blocked, and if so, which app it is.
3765         String blockingPackage = AppGlobals.getInitialPackage();
3766 
3767         EventLog.writeEvent(
3768             EventLogTags.CONTENT_QUERY_SAMPLE,
3769             uri.toString(),
3770             projectionBuffer.toString(),
3771             queryArgs.getString(QUERY_ARG_SQL_SELECTION, ""),
3772             queryArgs.getString(QUERY_ARG_SQL_SORT_ORDER, ""),
3773             durationMillis,
3774             blockingPackage != null ? blockingPackage : "",
3775             samplePercent);
3776     }
3777 
3778     private void maybeLogUpdateToEventLog(
3779         long durationMillis, Uri uri, String operation, String selection) {
3780         if (!ENABLE_CONTENT_SAMPLE) return;
3781         int samplePercent = samplePercentForDuration(durationMillis);
3782         if (samplePercent < 100) {
3783             synchronized (mRandom) {
3784                 if (mRandom.nextInt(100) >= samplePercent) {
3785                     return;
3786                 }
3787             }
3788         }
3789         String blockingPackage = AppGlobals.getInitialPackage();
3790         EventLog.writeEvent(
3791             EventLogTags.CONTENT_UPDATE_SAMPLE,
3792             uri.toString(),
3793             operation,
3794             selection != null ? selection : "",
3795             durationMillis,
3796             blockingPackage != null ? blockingPackage : "",
3797             samplePercent);
3798     }
3799 
3800     private final class CursorWrapperInner extends CrossProcessCursorWrapper {
3801         private final IContentProvider mContentProvider;
3802         private final AtomicBoolean mProviderReleased = new AtomicBoolean();
3803 
3804         private final CloseGuard mCloseGuard = CloseGuard.get();
3805 
3806         CursorWrapperInner(Cursor cursor, IContentProvider contentProvider) {
3807             super(cursor);
3808             mContentProvider = contentProvider;
3809             mCloseGuard.open("close");
3810         }
3811 
3812         @Override
3813         public void close() {
3814             mCloseGuard.close();
3815             super.close();
3816 
3817             if (mProviderReleased.compareAndSet(false, true)) {
3818                 ContentResolver.this.releaseProvider(mContentProvider);
3819             }
3820         }
3821 
3822         @Override
3823         protected void finalize() throws Throwable {
3824             try {
3825                 if (mCloseGuard != null) {
3826                     mCloseGuard.warnIfOpen();
3827                 }
3828 
3829                 close();
3830             } finally {
3831                 super.finalize();
3832             }
3833         }
3834     }
3835 
3836     private final class ParcelFileDescriptorInner extends ParcelFileDescriptor {
3837         private final IContentProvider mContentProvider;
3838         private final AtomicBoolean mProviderReleased = new AtomicBoolean();
3839 
3840         ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) {
3841             super(pfd);
3842             mContentProvider = icp;
3843         }
3844 
3845         @Override
3846         public void releaseResources() {
3847             if (mProviderReleased.compareAndSet(false, true)) {
3848                 ContentResolver.this.releaseProvider(mContentProvider);
3849             }
3850         }
3851     }
3852 
3853     /** @hide */
3854     public static final String CONTENT_SERVICE_NAME = "content";
3855 
3856     /** @hide */
3857     @UnsupportedAppUsage
3858     public static IContentService getContentService() {
3859         if (sContentService != null) {
3860             return sContentService;
3861         }
3862         IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME);
3863         sContentService = IContentService.Stub.asInterface(b);
3864         return sContentService;
3865     }
3866 
3867     /** @hide */
3868     @UnsupportedAppUsage
3869     public String getPackageName() {
3870         return mContext.getOpPackageName();
3871     }
3872 
3873     /** @hide */
3874     public @Nullable String getAttributionTag() {
3875         return mContext.getAttributionTag();
3876     }
3877 
3878     /** @hide */
3879     public @NonNull AttributionSource getAttributionSource() {
3880         return mContext.getAttributionSource();
3881     }
3882 
3883     @UnsupportedAppUsage
3884     private static volatile IContentService sContentService;
3885     @UnsupportedAppUsage
3886     private final Context mContext;
3887 
3888     @Deprecated
3889     @UnsupportedAppUsage
3890     final String mPackageName;
3891     final int mTargetSdkVersion;
3892     final ContentInterface mWrapped;
3893 
3894     private static final String TAG = "ContentResolver";
3895 
3896     /** @hide */
3897     public int resolveUserId(Uri uri) {
3898         return ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
3899     }
3900 
3901     /** @hide */
3902     public int getUserId() {
3903         return mContext.getUserId();
3904     }
3905 
3906     /** {@hide} */
3907     @Deprecated
3908     public Drawable getTypeDrawable(String mimeType) {
3909         return getTypeInfo(mimeType).getIcon().loadDrawable(mContext);
3910     }
3911 
3912     /**
3913      * Return a detailed description of the given MIME type, including an icon
3914      * and label that describe the type.
3915      *
3916      * @param mimeType Valid, concrete MIME type.
3917      */
3918     public final @NonNull MimeTypeInfo getTypeInfo(@NonNull String mimeType) {
3919         Objects.requireNonNull(mimeType);
3920         return MimeIconUtils.getTypeInfo(mimeType);
3921     }
3922 
3923     /**
3924      * Detailed description of a specific MIME type, including an icon and label
3925      * that describe the type.
3926      */
3927     public static final class MimeTypeInfo {
3928         private final Icon mIcon;
3929         private final CharSequence mLabel;
3930         private final CharSequence mContentDescription;
3931 
3932         /** {@hide} */
3933         public MimeTypeInfo(@NonNull Icon icon, @NonNull CharSequence label,
3934                 @NonNull CharSequence contentDescription) {
3935             mIcon = Objects.requireNonNull(icon);
3936             mLabel = Objects.requireNonNull(label);
3937             mContentDescription = Objects.requireNonNull(contentDescription);
3938         }
3939 
3940         /**
3941          * Return a visual representation of this MIME type. This can be styled
3942          * using {@link Icon#setTint(int)} to match surrounding UI.
3943          *
3944          * @see Icon#loadDrawable(Context)
3945          * @see android.widget.ImageView#setImageDrawable(Drawable)
3946          */
3947         public @NonNull Icon getIcon() {
3948             return mIcon;
3949         }
3950 
3951         /**
3952          * Return a textual representation of this MIME type.
3953          *
3954          * @see android.widget.TextView#setText(CharSequence)
3955          */
3956         public @NonNull CharSequence getLabel() {
3957             return mLabel;
3958         }
3959 
3960         /**
3961          * Return a content description for this MIME type.
3962          *
3963          * @see android.view.View#setContentDescription(CharSequence)
3964          */
3965         public @NonNull CharSequence getContentDescription() {
3966             return mContentDescription;
3967         }
3968     }
3969 
3970     /**
3971      * @hide
3972      */
3973     public static @Nullable Bundle createSqlQueryBundle(
3974             @Nullable String selection,
3975             @Nullable String[] selectionArgs) {
3976         return createSqlQueryBundle(selection, selectionArgs, null);
3977     }
3978 
3979     /**
3980      * @hide
3981      */
3982     public static @Nullable Bundle createSqlQueryBundle(
3983             @Nullable String selection,
3984             @Nullable String[] selectionArgs,
3985             @Nullable String sortOrder) {
3986 
3987         if (selection == null && selectionArgs == null && sortOrder == null) {
3988             return null;
3989         }
3990 
3991         Bundle queryArgs = new Bundle();
3992         if (selection != null) {
3993             queryArgs.putString(QUERY_ARG_SQL_SELECTION, selection);
3994         }
3995         if (selectionArgs != null) {
3996             queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs);
3997         }
3998         if (sortOrder != null) {
3999             queryArgs.putString(QUERY_ARG_SQL_SORT_ORDER, sortOrder);
4000         }
4001         return queryArgs;
4002     }
4003 
4004     /** @hide */
4005     public static @NonNull Bundle includeSqlSelectionArgs(@NonNull Bundle queryArgs,
4006             @Nullable String selection, @Nullable String[] selectionArgs) {
4007         if (selection != null) {
4008             queryArgs.putString(QUERY_ARG_SQL_SELECTION, selection);
4009         }
4010         if (selectionArgs != null) {
4011             queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs);
4012         }
4013         return queryArgs;
4014     }
4015 
4016     /**
4017      * Returns structured sort args formatted as an SQL sort clause.
4018      *
4019      * NOTE: Collator clauses are suitable for use with non text fields. We might
4020      * choose to omit any collation clause since we don't know the underlying
4021      * type of data to be collated. Imperical testing shows that sqlite3 doesn't
4022      * appear to care much about the presence of collate clauses in queries
4023      * when ordering by numeric fields. For this reason we include collate
4024      * clause unilaterally when {@link #QUERY_ARG_SORT_COLLATION} is present
4025      * in query args bundle.
4026      *
4027      * TODO: Would be nice to explicitly validate that colums referenced in
4028      * {@link #QUERY_ARG_SORT_COLUMNS} are present in the associated projection.
4029      *
4030      * @hide
4031      */
4032     public static String createSqlSortClause(Bundle queryArgs) {
4033         String[] columns = queryArgs.getStringArray(QUERY_ARG_SORT_COLUMNS);
4034         if (columns == null || columns.length == 0) {
4035             throw new IllegalArgumentException("Can't create sort clause without columns.");
4036         }
4037 
4038         String query = TextUtils.join(", ", columns);
4039 
4040         // Interpret PRIMARY and SECONDARY collation strength as no-case collation based
4041         // on their javadoc descriptions.
4042         int collation = queryArgs.getInt(
4043                 ContentResolver.QUERY_ARG_SORT_COLLATION, java.text.Collator.IDENTICAL);
4044         if (collation == java.text.Collator.PRIMARY || collation == java.text.Collator.SECONDARY) {
4045             query += " COLLATE NOCASE";
4046         }
4047 
4048         int sortDir = queryArgs.getInt(QUERY_ARG_SORT_DIRECTION, Integer.MIN_VALUE);
4049         if (sortDir != Integer.MIN_VALUE) {
4050             switch (sortDir) {
4051                 case QUERY_SORT_DIRECTION_ASCENDING:
4052                     query += " ASC";
4053                     break;
4054                 case QUERY_SORT_DIRECTION_DESCENDING:
4055                     query += " DESC";
4056                     break;
4057                 default:
4058                     throw new IllegalArgumentException("Unsupported sort direction value."
4059                             + " See ContentResolver documentation for details.");
4060             }
4061         }
4062         return query;
4063     }
4064 
4065     /**
4066      * Convenience method that efficiently loads a visual thumbnail for the
4067      * given {@link Uri}. Internally calls
4068      * {@link ContentProvider#openTypedAssetFile} on the remote provider, but
4069      * also defensively resizes any returned content to match the requested
4070      * target size.
4071      *
4072      * @param uri The item that should be visualized as a thumbnail.
4073      * @param size The target area on the screen where this thumbnail will be
4074      *            shown. This is passed to the provider as {@link #EXTRA_SIZE}
4075      *            to help it avoid downloading or generating heavy resources.
4076      * @param signal A signal to cancel the operation in progress.
4077      * @return Valid {@link Bitmap} which is a visual thumbnail.
4078      * @throws IOException If any trouble was encountered while generating or
4079      *             loading the thumbnail, or if
4080      *             {@link CancellationSignal#cancel()} was invoked.
4081      */
4082     public @NonNull Bitmap loadThumbnail(@NonNull Uri uri, @NonNull Size size,
4083             @Nullable CancellationSignal signal) throws IOException {
4084         return loadThumbnail(this, uri, size, signal, ImageDecoder.ALLOCATOR_SOFTWARE);
4085     }
4086 
4087     /** {@hide} */
4088     public static Bitmap loadThumbnail(@NonNull ContentInterface content, @NonNull Uri uri,
4089             @NonNull Size size, @Nullable CancellationSignal signal, int allocator)
4090             throws IOException {
4091         Objects.requireNonNull(content);
4092         Objects.requireNonNull(uri);
4093         Objects.requireNonNull(size);
4094 
4095         // Convert to Point, since that's what the API is defined as
4096         final Bundle opts = new Bundle();
4097         opts.putParcelable(EXTRA_SIZE, new Point(size.getWidth(), size.getHeight()));
4098         final Int64Ref orientation = new Int64Ref(0);
4099 
4100         Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> {
4101             final AssetFileDescriptor afd = content.openTypedAssetFile(uri, "image/*", opts,
4102                     signal);
4103             final Bundle extras = afd.getExtras();
4104             orientation.value = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0;
4105             return afd;
4106         }), (ImageDecoder decoder, ImageInfo info, Source source) -> {
4107                 decoder.setAllocator(allocator);
4108 
4109                 // One last-ditch check to see if we've been canceled.
4110                 if (signal != null) signal.throwIfCanceled();
4111 
4112                 // We requested a rough thumbnail size, but the remote size may have
4113                 // returned something giant, so defensively scale down as needed.
4114                 final int widthSample = info.getSize().getWidth() / size.getWidth();
4115                 final int heightSample = info.getSize().getHeight() / size.getHeight();
4116                 final int sample = Math.max(widthSample, heightSample);
4117                 if (sample > 1) {
4118                     decoder.setTargetSampleSize(sample);
4119                 }
4120         });
4121 
4122         // Transform the bitmap if requested. We use a side-channel to
4123         // communicate the orientation, since EXIF thumbnails don't contain
4124         // the rotation flags of the original image.
4125         if (orientation.value != 0) {
4126             final int width = bitmap.getWidth();
4127             final int height = bitmap.getHeight();
4128 
4129             final Matrix m = new Matrix();
4130             m.setRotate(orientation.value, width / 2, height / 2);
4131             bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false);
4132         }
4133 
4134         return bitmap;
4135     }
4136 
4137     /** {@hide} */
4138     public static void onDbCorruption(String tag, String message, Throwable stacktrace) {
4139         try {
4140             getContentService().onDbCorruption(tag, message, Log.getStackTraceString(stacktrace));
4141         } catch (RemoteException e) {
4142             e.rethrowFromSystemServer();
4143         }
4144     }
4145 
4146     /**
4147      * Decode a path generated by {@link #encodeToFile(Uri)} back into
4148      * the original {@link Uri}.
4149      * <p>
4150      * This is used to offer a way to intercept filesystem calls in
4151      * {@link ContentProvider} unaware code and redirect them to a
4152      * {@link ContentProvider} when they attempt to use {@code _DATA} columns
4153      * that are otherwise deprecated.
4154      *
4155      * @hide
4156      */
4157     @SystemApi
4158     // We can't accept an already-opened FD here, since these methods are
4159     // rewriting actual filesystem paths
4160     @SuppressLint("StreamFiles")
4161     public static @NonNull Uri decodeFromFile(@NonNull File file) {
4162         return translateDeprecatedDataPath(file.getAbsolutePath());
4163     }
4164 
4165     /**
4166      * Encode a {@link Uri} into an opaque filesystem path which can then be
4167      * resurrected by {@link #decodeFromFile(File)}.
4168      * <p>
4169      * This is used to offer a way to intercept filesystem calls in
4170      * {@link ContentProvider} unaware code and redirect them to a
4171      * {@link ContentProvider} when they attempt to use {@code _DATA} columns
4172      * that are otherwise deprecated.
4173      *
4174      * @hide
4175      */
4176     @SystemApi
4177     // We can't accept an already-opened FD here, since these methods are
4178     // rewriting actual filesystem paths
4179     @SuppressLint("StreamFiles")
4180     public static @NonNull File encodeToFile(@NonNull Uri uri) {
4181         return new File(translateDeprecatedDataPath(uri));
4182     }
4183 
4184     /** {@hide} */
4185     public static @NonNull Uri translateDeprecatedDataPath(@NonNull String path) {
4186         final String ssp = "//" + path.substring(DEPRECATE_DATA_PREFIX.length());
4187         return Uri.parse(new Uri.Builder().scheme(SCHEME_CONTENT)
4188                 .encodedOpaquePart(ssp).build().toString());
4189     }
4190 
4191     /** {@hide} */
4192     public static @NonNull String translateDeprecatedDataPath(@NonNull Uri uri) {
4193         return DEPRECATE_DATA_PREFIX + uri.getEncodedSchemeSpecificPart().substring(2);
4194     }
4195 }
4196