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