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