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