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