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