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