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