19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.content;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrickimport android.accounts.Account;
20673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkeyimport android.annotation.NonNull;
219f78f6528f1afad260be51d2058c37717851e3a2Scott Kennedyimport android.annotation.Nullable;
22cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackbornimport android.app.ActivityManagerNative;
2366a017b63461a22842b3678c9520f803d5ddadfcJeff Sharkeyimport android.app.ActivityThread;
2401e4cfc47d0a2c7e7ab383d2fb23224ec52c0301Dianne Hackbornimport android.app.AppGlobals;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager.NameNotFoundException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetFileDescriptor;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver;
29825c5132bff21e72c1448241f4c6868563c8d624Jeff Brownimport android.database.CrossProcessCursorWrapper;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.IContentObserver;
325b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkeyimport android.graphics.Point;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
35a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.CancellationSignal;
366ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackbornimport android.os.DeadObjectException;
37231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.IBinder;
38a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.ICancellationSignal;
39a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.OperationCanceledException;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
42231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.ServiceManager;
43d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrickimport android.os.SystemClock;
445e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackbornimport android.os.UserHandle;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
46a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrickimport android.util.EventLog;
47231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.Log;
4808da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey
4908da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkeyimport dalvik.system.CloseGuard;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5137a40c24deb02bca3868a8085069afae112f22e4Amith Yamasaniimport com.android.internal.util.ArrayUtils;
52673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkeyimport com.android.internal.util.Preconditions;
53673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream;
6003f0292744094ec107ffce71301c394503a31dedGilles Debunneimport java.util.ArrayList;
6137a40c24deb02bca3868a8085069afae112f22e4Amith Yamasaniimport java.util.Collections;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
63a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrickimport java.util.Random;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides applications access to the content model.
67558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez *
68558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <div class="special reference">
69558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <h3>Developer Guides</h3>
70558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <p>For more information about using a ContentResolver with content providers, read the
71558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
72558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * developer guide.</p>
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class ContentResolver {
75ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
76ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @deprecated instead use
77ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
78ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
794a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana    @Deprecated
80ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final String SYNC_EXTRAS_ACCOUNT = "account";
81b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov
82b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov    /**
83b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * If this extra is set to true, the sync request will be scheduled
84b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * at the front of the sync request queue and without any delay
85b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     */
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
87b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov
88ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
89ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @deprecated instead use
90ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * {@link #SYNC_EXTRAS_MANUAL}
91ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
924a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana    @Deprecated
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SYNC_EXTRAS_FORCE = "force";
9453bd2522ca7767f46646606123b6e2689b811850Fred Quintana
9553bd2522ca7767f46646606123b6e2689b811850Fred Quintana    /**
9653bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * If this extra is set to true then the sync settings (like getSyncAutomatically())
9753bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * are ignored by the sync scheduler.
9853bd2522ca7767f46646606123b6e2689b811850Fred Quintana     */
9953bd2522ca7767f46646606123b6e2689b811850Fred Quintana    public static final String SYNC_EXTRAS_IGNORE_SETTINGS = "ignore_settings";
10053bd2522ca7767f46646606123b6e2689b811850Fred Quintana
10153bd2522ca7767f46646606123b6e2689b811850Fred Quintana    /**
10253bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * If this extra is set to true then any backoffs for the initial attempt (e.g. due to retries)
10353bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * are ignored by the sync scheduler. If this request fails and gets rescheduled then the
10453bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * retries will still honor the backoff.
10553bd2522ca7767f46646606123b6e2689b811850Fred Quintana     */
10653bd2522ca7767f46646606123b6e2689b811850Fred Quintana    public static final String SYNC_EXTRAS_IGNORE_BACKOFF = "ignore_backoff";
10753bd2522ca7767f46646606123b6e2689b811850Fred Quintana
10853bd2522ca7767f46646606123b6e2689b811850Fred Quintana    /**
10953bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * If this extra is set to true then the request will not be retried if it fails.
11053bd2522ca7767f46646606123b6e2689b811850Fred Quintana     */
11153bd2522ca7767f46646606123b6e2689b811850Fred Quintana    public static final String SYNC_EXTRAS_DO_NOT_RETRY = "do_not_retry";
11253bd2522ca7767f46646606123b6e2689b811850Fred Quintana
11353bd2522ca7767f46646606123b6e2689b811850Fred Quintana    /**
11453bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * Setting this extra is the equivalent of setting both {@link #SYNC_EXTRAS_IGNORE_SETTINGS}
11553bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * and {@link #SYNC_EXTRAS_IGNORE_BACKOFF}
11653bd2522ca7767f46646606123b6e2689b811850Fred Quintana     */
117ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final String SYNC_EXTRAS_MANUAL = "force";
11853bd2522ca7767f46646606123b6e2689b811850Fred Quintana
119b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov    /**
120b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * Indicates that this sync is intended to only upload local changes to the server.
121b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * For example, this will be set to true if the sync is initiated by a call to
122b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}
123b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     */
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SYNC_EXTRAS_UPLOAD = "upload";
125b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov
126b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov    /**
127b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * Indicates that the sync adapter should proceed with the delete operations,
128b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * even if it determines that there are too many.
129b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * See {@link SyncResult#tooManyDeletions}
130b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     */
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
132b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov
133b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov    /**
134b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * Indicates that the sync adapter should not proceed with the delete operations,
135b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * if it determines that there are too many.
136b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     * See {@link SyncResult#tooManyDeletions}
137b3395575a3441d9339423a4e624cb9806dd07a49Georgi Nikolov     */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
140fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /* Extensions to API. TODO: Not clear if we will keep these as public flags. */
141fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** {@hide} User-specified flag for expected upload size. */
142fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public static final String SYNC_EXTRAS_EXPECTED_UPLOAD = "expected_upload";
143fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
144fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** {@hide} User-specified flag for expected download size. */
145fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public static final String SYNC_EXTRAS_EXPECTED_DOWNLOAD = "expected_download";
146fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
147fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** {@hide} Priority of this sync with respect to other syncs scheduled for this application. */
148fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public static final String SYNC_EXTRAS_PRIORITY = "sync_priority";
149fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
150fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** {@hide} Flag to allow sync to occur on metered network. */
15156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static final String SYNC_EXTRAS_DISALLOW_METERED = "allow_metered";
152fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
1534a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana    /**
1544a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana     * Set by the SyncManager to request that the SyncAdapter initialize itself for
1554a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana     * the given account/authority pair. One required initialization step is to
1564a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana     * ensure that {@link #setIsSyncable(android.accounts.Account, String, int)} has been
1574a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana     * called with a >= 0 value. When this flag is set the SyncAdapter does not need to
1584a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana     * do a full sync, though it is allowed to do so.
1594a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana     */
1604a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana    public static final String SYNC_EXTRAS_INITIALIZE = "initialize";
1614a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana
1627a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey    /** @hide */
1637a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey    public static final Intent ACTION_SYNC_CONN_STATUS_CHANGED =
1647a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey            new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
1657a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SCHEME_CONTENT = "content";
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String SCHEME_FILE = "file";
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1715b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     * An extra {@link Point} describing the optimal size for a requested image
1725b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     * resource, in pixels. If a provider has multiple sizes of the image, it
1735b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     * should return the image closest to this size.
1745b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     *
1755b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     * @see #openTypedAssetFileDescriptor(Uri, String, Bundle)
1765b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     * @see #openTypedAssetFileDescriptor(Uri, String, Bundle,
1775b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     *      CancellationSignal)
1785b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey     */
1795b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey    public static final String EXTRA_SIZE = "android.content.extra.SIZE";
1805b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey
1815b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey    /**
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is the Android platform's base MIME type for a content: URI
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * containing a Cursor of a single item.  Applications should use this
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * as the base type along with their own sub-type of their content: URIs
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that represent a particular item.  For example, hypothetical IMAP email
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * client may have a URI
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>content://com.company.provider.imap/inbox/1</code> for a particular
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * message in the inbox, whose MIME type would be reported as
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code>
1900ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     *
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
1940ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is the Android platform's base MIME type for a content: URI
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * containing a Cursor of zero or more items.  Applications should use this
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * as the base type along with their own sub-type of their content: URIs
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that represent a directory of items.  For example, hypothetical IMAP email
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * client may have a URI
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>content://com.company.provider.imap/inbox</code> for all of the
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * messages in its inbox, whose MIME type would be reported as
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code>
2040ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     *
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note how the base MIME type varies between this and
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one single item or multiple items in the data set, while the sub-type
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * remains the same because in either case the data structure contained
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in the cursor is the same.
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
212ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
213bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey    /**
214bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey     * This is the Android platform's generic MIME type to match any MIME
215bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey     * type of the form "{@link #CURSOR_ITEM_BASE_TYPE}/{@code SUB_TYPE}".
216bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey     * {@code SUB_TYPE} is the sub-type of the application-dependent
217bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey     * content, e.g., "audio", "video", "playlist".
218bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey     */
219bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey    public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
220bd7bcf0fba1a991e80ea279b090aa584707fdabfMatt Casey
221ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
222ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
223ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
224ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_AUTHENTICATION = 2;
225ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
226ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_IO = 3;
227ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
228ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_PARSE = 4;
229ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
230ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_CONFLICT = 5;
231ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
232ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6;
233ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
234ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7;
235ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
236ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_ERROR_INTERNAL = 8;
237ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
23857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    private static final String[] SYNC_ERROR_NAMES = new String[] {
23957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "already-in-progress",
24057286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "authentication-error",
24157286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "io-error",
24257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "parse-error",
24357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "conflict",
24457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "too-many-deletions",
24557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "too-many-retries",
24657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert          "internal-error",
24757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    };
24857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert
24957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    /** @hide */
2507a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey    public static String syncErrorToString(int error) {
25157286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        if (error < 1 || error > SYNC_ERROR_NAMES.length) {
25257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            return String.valueOf(error);
25357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        }
25457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        return SYNC_ERROR_NAMES[error - 1];
25557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    }
25657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert
2575c113faba6b644d1851c9281614aa0edd175fc48Alon Albert    /** @hide */
2585c113faba6b644d1851c9281614aa0edd175fc48Alon Albert    public static int syncErrorStringToInt(String error) {
2595c113faba6b644d1851c9281614aa0edd175fc48Alon Albert        for (int i = 0, n = SYNC_ERROR_NAMES.length; i < n; i++) {
2605c113faba6b644d1851c9281614aa0edd175fc48Alon Albert            if (SYNC_ERROR_NAMES[i].equals(error)) {
2615c113faba6b644d1851c9281614aa0edd175fc48Alon Albert                return i + 1;
2625c113faba6b644d1851c9281614aa0edd175fc48Alon Albert            }
2635c113faba6b644d1851c9281614aa0edd175fc48Alon Albert        }
2645c113faba6b644d1851c9281614aa0edd175fc48Alon Albert        if (error != null) {
2655c113faba6b644d1851c9281614aa0edd175fc48Alon Albert            try {
2665c113faba6b644d1851c9281614aa0edd175fc48Alon Albert                return Integer.parseInt(error);
2675c113faba6b644d1851c9281614aa0edd175fc48Alon Albert            } catch (NumberFormatException e) {
2685c113faba6b644d1851c9281614aa0edd175fc48Alon Albert                Log.d(TAG, "error parsing sync error: " + error);
2695c113faba6b644d1851c9281614aa0edd175fc48Alon Albert            }
2705c113faba6b644d1851c9281614aa0edd175fc48Alon Albert        }
2715c113faba6b644d1851c9281614aa0edd175fc48Alon Albert        return 0;
2725c113faba6b644d1851c9281614aa0edd175fc48Alon Albert    }
2735c113faba6b644d1851c9281614aa0edd175fc48Alon Albert
274ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0;
275ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
276ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
277ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
278ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3;
279ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /** @hide */
280ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
281ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
28225880968cbde25c9edb162c0d70d45dc75239456Brad Fitzpatrick    // Always log queries which take 500ms+; shorter queries are
283a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    // sampled accordingly.
2842b4d22cda3c44f5d731c15306b85045417071408Jeff Sharkey    private static final boolean ENABLE_CONTENT_SAMPLE = false;
28525880968cbde25c9edb162c0d70d45dc75239456Brad Fitzpatrick    private static final int SLOW_THRESHOLD_MILLIS = 500;
286a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    private final Random mRandom = new Random();  // guarded by itself
287a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick
288231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ContentResolver(Context context) {
28966a017b63461a22842b3678c9520f803d5ddadfcJeff Sharkey        mContext = context != null ? context : ActivityThread.currentApplication();
29095d785346b4dae808a2d8f77356175e55a572d96Dianne Hackborn        mPackageName = mContext.getOpPackageName();
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** @hide */
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected abstract IContentProvider acquireProvider(Context c, String name);
295e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey
296e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey    /**
297e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * Providing a default implementation of this, to avoid having to change a
298e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * lot of other things, but implementations of ContentResolver should
299e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * implement it.
300e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     *
301e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * @hide
302e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     */
303cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn    protected IContentProvider acquireExistingProvider(Context c, String name) {
304cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        return acquireProvider(c, name);
305cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn    }
306e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** @hide */
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract boolean releaseProvider(IContentProvider icp);
309652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    /** @hide */
310652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
311652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    /** @hide */
312652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    public abstract boolean releaseUnstableProvider(IContentProvider icp);
3136ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn    /** @hide */
3146ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn    public abstract void unstableProviderDied(IContentProvider icp);
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3167aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey    /** @hide */
3177aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey    public void appNotRespondingViaProvider(IContentProvider icp) {
3187aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey        throw new UnsupportedOperationException("appNotRespondingViaProvider");
3197aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey    }
3207aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the MIME type of the given content URL.
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url A Uri identifying content (either a list or specific type),
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * using the content:// scheme.
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A MIME type for the content, or null if the URL is invalid or the type is unknown
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
328673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable String getType(@NonNull Uri url) {
329673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(url, "url");
330673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey
3316ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        // XXX would like to have an acquireExistingUnstableProvider for this.
332cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        IContentProvider provider = acquireExistingProvider(url);
333cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        if (provider != null) {
334cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn            try {
335cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn                return provider.getType(url);
336cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn            } catch (RemoteException e) {
337cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn                return null;
338cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn            } catch (java.lang.Exception e) {
339145e6c4975536d927e506634514a06c43313df17Ola Olsson                Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
340cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn                return null;
341cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn            } finally {
342cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn                releaseProvider(provider);
343cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn            }
344cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        }
345cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn
346cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        if (!SCHEME_CONTENT.equals(url.getScheme())) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
349cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3515e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            String type = ActivityManagerNative.getDefault().getProviderMimeType(
3521dddc7fc790f14208516b4551ff12b2db8528864Nicolas Prevot                    ContentProvider.getUriWithoutUserId(url), resolveUserId(url));
353cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn            return type;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
355534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
356534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
358145e6c4975536d927e506634514a06c43313df17Ola Olsson        } catch (java.lang.Exception e) {
359145e6c4975536d927e506634514a06c43313df17Ola Olsson            Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
360145e6c4975536d927e506634514a06c43313df17Ola Olsson            return null;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
36523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Query for the possible MIME types for the representations the given
36623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * content URL can be returned when opened as as stream with
36723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * {@link #openTypedAssetFileDescriptor}.  Note that the types here are
36823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * not necessarily a superset of the type returned by {@link #getType} --
369bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * many content providers cannot return a raw stream for the structured
37023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * data that they contain.
37123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
37223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param url A Uri identifying content (either a list or specific type),
37323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * using the content:// scheme.
37423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeTypeFilter The desired MIME type.  This may be a pattern,
3753390018c6b45acffa6edf97a4174ca49f1e8c76dJohn Spurlock     * such as *&#47;*, to query for all available MIME types that match the
37623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * pattern.
377acb69bb909d098cea284df47d794c17171d84c91Dianne Hackborn     * @return Returns an array of MIME type strings for all available
37823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * data streams that match the given mimeTypeFilter.  If there are none,
37923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * null is returned.
38023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
381673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
382673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(url, "url");
383673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
384673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey
38523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        IContentProvider provider = acquireProvider(url);
38623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        if (provider == null) {
38723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return null;
38823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
38964bbbb471ed78ae06f411224849a4556a30fd362Dianne Hackborn
39023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        try {
39123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return provider.getStreamTypes(url, mimeTypeFilter);
39223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        } catch (RemoteException e) {
393534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
394534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
39523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return null;
39623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        } finally {
397534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            releaseProvider(provider);
398534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        }
39923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
40023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
40123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Query the given URI, returning a {@link Cursor} over the result set.
4030ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * <p>
4040ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * For best performance, the caller should follow these guidelines:
4050ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * <ul>
4060ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * <li>Provide an explicit projection, to prevent
4070ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * reading data from storage that aren't going to be used.</li>
4080ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * <li>Use question mark parameter markers such as 'phone=?' instead of
4090ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * explicit values in the {@code selection} parameter, so that queries
4100ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * that differ only by those values will be recognized as the same
4110ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * for caching purposes.</li>
4120ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * </ul>
4130ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     * </p>
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI, using the content:// scheme, for the content to
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         retrieve.
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param projection A list of which columns to return. Passing null will
4180ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     *         return all columns, which is inefficient.
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selection A filter declaring which rows to return, formatted as an
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         SQL WHERE clause (excluding the WHERE itself). Passing null will
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         return all rows for the given URI.
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selectionArgs You may include ?s in selection, which will be
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         replaced by the values from selectionArgs, in the order that they
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         appear in the selection. The values will be bound as Strings.
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         clause (excluding the ORDER BY itself). Passing null will use the
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         default sort order, which may be unordered.
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A Cursor object, which is positioned before the first entry, or null
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see Cursor
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
431673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
432673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable String selection, @Nullable String[] selectionArgs,
433673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable String sortOrder) {
43475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown        return query(uri, projection, selection, selectionArgs, sortOrder, null);
43575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown    }
43675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown
43775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown    /**
438c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown     * Query the given URI, returning a {@link Cursor} over the result set
439c64ff3782c71ce7b5a92b7d91199a922ea0a37d9Jeff Brown     * with optional support for cancellation.
44075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * <p>
44175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * For best performance, the caller should follow these guidelines:
44275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * <ul>
44375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * <li>Provide an explicit projection, to prevent
44475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * reading data from storage that aren't going to be used.</li>
44575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * <li>Use question mark parameter markers such as 'phone=?' instead of
44675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * explicit values in the {@code selection} parameter, so that queries
44775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * that differ only by those values will be recognized as the same
44875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * for caching purposes.</li>
44975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * </ul>
45075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * </p>
45175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *
45275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * @param uri The URI, using the content:// scheme, for the content to
45375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         retrieve.
45475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * @param projection A list of which columns to return. Passing null will
45575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         return all columns, which is inefficient.
45675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * @param selection A filter declaring which rows to return, formatted as an
45775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         SQL WHERE clause (excluding the WHERE itself). Passing null will
45875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         return all rows for the given URI.
45975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * @param selectionArgs You may include ?s in selection, which will be
46075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         replaced by the values from selectionArgs, in the order that they
46175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         appear in the selection. The values will be bound as Strings.
46275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
46375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         clause (excluding the ORDER BY itself). Passing null will use the
46475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     *         default sort order, which may be unordered.
4654c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown     * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
46675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * If the operation is canceled, then {@link OperationCanceledException} will be thrown
46775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * when the query is executed.
46875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * @return A Cursor object, which is positioned before the first entry, or null
46975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     * @see Cursor
47075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown     */
471673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable Cursor query(final @NonNull Uri uri, @Nullable String[] projection,
472673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable String selection, @Nullable String[] selectionArgs,
473673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
474673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
4756ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        IContentProvider unstableProvider = acquireUnstableProvider(uri);
4766ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        if (unstableProvider == null) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4796ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        IContentProvider stableProvider = null;
480c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown        Cursor qCursor = null;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
482d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long startTime = SystemClock.uptimeMillis();
48375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown
4844c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown            ICancellationSignal remoteCancellationSignal = null;
4854c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown            if (cancellationSignal != null) {
4864c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown                cancellationSignal.throwIfCanceled();
4876ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                remoteCancellationSignal = unstableProvider.createCancellationSignal();
4884c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown                cancellationSignal.setRemote(remoteCancellationSignal);
48975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            }
4906ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            try {
49135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                qCursor = unstableProvider.query(mPackageName, uri, projection,
4926ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        selection, selectionArgs, sortOrder, remoteCancellationSignal);
4936ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            } catch (DeadObjectException e) {
4946ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                // The remote process has died...  but we only hold an unstable
4956ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                // reference though, so we might recover!!!  Let's try!!!!
4966ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                // This is exciting!!1!!1!!!!1
4976ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                unstableProviderDied(unstableProvider);
4986ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                stableProvider = acquireProvider(uri);
4996ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                if (stableProvider == null) {
5006ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    return null;
5016ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                }
50235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                qCursor = stableProvider.query(mPackageName, uri, projection,
5036ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        selection, selectionArgs, sortOrder, remoteCancellationSignal);
5046ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            }
505a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            if (qCursor == null) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
508c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown
509c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // Force query execution.  Might fail and throw a runtime exception here.
510020e5345795a157d7829ebbe4d7864595dafc576Vasu Nori            qCursor.getCount();
511d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long durationMillis = SystemClock.uptimeMillis() - startTime;
512a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
513c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown
514c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // Wrap the cursor object into CursorWrapperInner object.
5156ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            CursorWrapperInner wrapper = new CursorWrapperInner(qCursor,
5166ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    stableProvider != null ? stableProvider : acquireProvider(uri));
5176ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            stableProvider = null;
518c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            qCursor = null;
5196ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            return wrapper;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
521534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
522534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
5246ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        } finally {
525c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            if (qCursor != null) {
526c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                qCursor.close();
527c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            }
528bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            if (cancellationSignal != null) {
529bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                cancellationSignal.setRemote(null);
530bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            }
5316ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            if (unstableProvider != null) {
5326ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                releaseUnstableProvider(unstableProvider);
5336ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            }
5346ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            if (stableProvider != null) {
5356ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                releaseProvider(stableProvider);
5366ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5408943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    /**
54138ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * Transform the given <var>url</var> to a canonical representation of
54238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * its referenced resource, which can be used across devices, persisted,
54338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * backed up and restored, etc.  The returned Uri is still a fully capable
54438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * Uri for use with its content provider, allowing you to do all of the
54538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * same content provider operations as with the original Uri --
54638ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * {@link #query}, {@link #openInputStream(android.net.Uri)}, etc.  The
54738ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * only difference in behavior between the original and new Uris is that
54838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * the content provider may need to do some additional work at each call
54938ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * using it to resolve it to the correct resource, especially if the
55038ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * canonical Uri has been moved to a different environment.
55138ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     *
55238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * <p>If you are moving a canonical Uri between environments, you should
55338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * perform another call to {@link #canonicalize} with that original Uri to
55438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * re-canonicalize it for the current environment.  Alternatively, you may
55538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * want to use {@link #uncanonicalize} to transform it to a non-canonical
55638ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * Uri that works only in the current environment but potentially more
55738ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * efficiently than the canonical representation.</p>
55838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     *
55938ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * @param url The {@link Uri} that is to be transformed to a canonical
56038ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * representation.  Like all resolver calls, the input can be either
56138ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * a non-canonical or canonical Uri.
56238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     *
56338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * @return Returns the official canonical representation of <var>url</var>,
56438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * or null if the content provider does not support a canonical representation
56538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * of the given Uri.  Many providers may not support canonicalization of some
56638ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * or all of their Uris.
56738ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     *
56838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * @see #uncanonicalize
56938ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     */
570673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable Uri canonicalize(@NonNull Uri url) {
571673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(url, "url");
57238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        IContentProvider provider = acquireProvider(url);
57338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        if (provider == null) {
57438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            return null;
57538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        }
57638ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn
57738ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        try {
57838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            return provider.canonicalize(mPackageName, url);
57938ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        } catch (RemoteException e) {
58038ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            // Arbitrary and not worth documenting, as Activity
58138ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            // Manager will kill this process shortly anyway.
58238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            return null;
58338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        } finally {
58438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            releaseProvider(provider);
58538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        }
58638ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn    }
58738ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn
58838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn    /**
58938ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * Given a canonical Uri previously generated by {@link #canonicalize}, convert
59038ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * it to its local non-canonical form.  This can be useful in some cases where
59138ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * you know that you will only be using the Uri in the current environment and
59238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * want to avoid any possible overhead when using it with the content
593b3ac67a0ece71bcf484dd92914dc3599dadffb05Dianne Hackborn     * provider or want to verify that the referenced data exists at all in the
594b3ac67a0ece71bcf484dd92914dc3599dadffb05Dianne Hackborn     * new environment.
59538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     *
59638ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * @param url The canonical {@link Uri} that is to be convered back to its
59738ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * non-canonical form.
59838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     *
599b3ac67a0ece71bcf484dd92914dc3599dadffb05Dianne Hackborn     * @return Returns the non-canonical representation of <var>url</var>.  This will
600b3ac67a0ece71bcf484dd92914dc3599dadffb05Dianne Hackborn     * return null if data identified by the canonical Uri can not be found in
601b3ac67a0ece71bcf484dd92914dc3599dadffb05Dianne Hackborn     * the current environment; callers must always check for null and deal with
602b3ac67a0ece71bcf484dd92914dc3599dadffb05Dianne Hackborn     * that by appropriately falling back to an alternative.
60338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     *
60438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     * @see #canonicalize
60538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn     */
606673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
607673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(url, "url");
60838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        IContentProvider provider = acquireProvider(url);
60938ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        if (provider == null) {
61038ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            return null;
61138ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        }
61238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn
61338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        try {
61438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            return provider.uncanonicalize(mPackageName, url);
61538ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        } catch (RemoteException e) {
61638ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            // Arbitrary and not worth documenting, as Activity
61738ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            // Manager will kill this process shortly anyway.
61838ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            return null;
61938ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        } finally {
62038ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn            releaseProvider(provider);
62138ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn        }
62238ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn    }
62338ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn
62438ed2a471a2291383821fb187bfa18450f0581c2Dianne Hackborn    /**
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Open a stream on to the content associated with a content URI.  If there
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is no data associated with the URI, FileNotFoundException is thrown.
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <h5>Accepts the following URI schemes:</h5>
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>content ({@link #SCHEME_CONTENT})</li>
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>file ({@link #SCHEME_FILE})</li>
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
6340ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     *
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * on these schemes.
6370ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     *
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The desired URI.
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return InputStream
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException if the provided URI could not be opened.
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openAssetFileDescriptor(Uri, String)
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
643673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable InputStream openInputStream(@NonNull Uri uri)
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
645673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String scheme = uri.getScheme();
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Note: left here to avoid breaking compatibility.  May be removed
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // with sufficient testing.
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            OpenResourceIdResult r = getResourceId(uri);
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputStream stream = r.r.openRawResource(r.id);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return stream;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Resources.NotFoundException ex) {
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("Resource does not exist: " + uri);
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (SCHEME_FILE.equals(scheme)) {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Note: left here to avoid breaking compatibility.  May be removed
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // with sufficient testing.
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new FileInputStream(uri.getPath());
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
662bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r", null);
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return fd != null ? fd.createInputStream() : null;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("Unable to create stream");
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Synonym for {@link #openOutputStream(Uri, String)
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * openOutputStream(uri, "w")}.
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException if the provided URI could not be opened.
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
676673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable OutputStream openOutputStream(@NonNull Uri uri)
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return openOutputStream(uri, "w");
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Open a stream on to the content associated with a content URI.  If there
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is no data associated with the URI, FileNotFoundException is thrown.
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <h5>Accepts the following URI schemes:</h5>
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>content ({@link #SCHEME_CONTENT})</li>
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>file ({@link #SCHEME_FILE})</li>
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * on these schemes.
6930ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     *
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The desired URI.
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode May be "w", "wa", "rw", or "rwt".
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return OutputStream
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException if the provided URI could not be opened.
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openAssetFileDescriptor(Uri, String)
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
700673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode)
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
702bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey        AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return fd != null ? fd.createOutputStream() : null;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("Unable to create stream");
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
71123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Open a raw file descriptor to access data under a URI.  This
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * underlying {@link ContentProvider#openFile}
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ContentProvider.openFile()} method, so will <em>not</em> work with
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * providers that return sub-sections of files.  If at all possible,
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will receive a FileNotFoundException exception if the provider returns a
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * sub-section of a file.
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <h5>Accepts the following URI schemes:</h5>
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>content ({@link #SCHEME_CONTENT})</li>
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>file ({@link #SCHEME_FILE})</li>
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * on these schemes.
728bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>
729bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * If opening with the exclusive "r" or "w" modes, the returned
730bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
731bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * of data. Opening with the "rw" mode implies a file on disk that supports
732bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * seeking. If possible, always use an exclusive mode to give the underlying
733bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * {@link ContentProvider} the most flexibility.
734bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>
735bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * If you are writing a file, and need to communicate an error to the
736bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
737bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
738bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @param uri The desired URI to open.
739bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @param mode The file mode to use, as per {@link ContentProvider#openFile
740bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * ContentProvider.openFile}.
741bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @return Returns a new ParcelFileDescriptor pointing to the file.  You
742bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * own this descriptor and are responsible for closing it when done.
743bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @throws FileNotFoundException Throws FileNotFoundException if no
744bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * file exists under the URI or the mode is invalid.
745bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @see #openAssetFileDescriptor(Uri, String)
746bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     */
747673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
748673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String mode) throws FileNotFoundException {
749bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey        return openFileDescriptor(uri, mode, null);
750bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey    }
751bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey
752bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey    /**
753bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * Open a raw file descriptor to access data under a URI.  This
754bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
755bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * underlying {@link ContentProvider#openFile}
756bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * ContentProvider.openFile()} method, so will <em>not</em> work with
757bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * providers that return sub-sections of files.  If at all possible,
758bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
759bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * will receive a FileNotFoundException exception if the provider returns a
760bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * sub-section of a file.
761bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
762bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <h5>Accepts the following URI schemes:</h5>
763bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <ul>
764bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <li>content ({@link #SCHEME_CONTENT})</li>
765bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <li>file ({@link #SCHEME_FILE})</li>
766bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * </ul>
767bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
768bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
769bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * on these schemes.
770bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>
771bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * If opening with the exclusive "r" or "w" modes, the returned
772bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
773bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * of data. Opening with the "rw" mode implies a file on disk that supports
774bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * seeking. If possible, always use an exclusive mode to give the underlying
775bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * {@link ContentProvider} the most flexibility.
776bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>
777bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * If you are writing a file, and need to communicate an error to the
778bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
7790ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill     *
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The desired URI to open.
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode The file mode to use, as per {@link ContentProvider#openFile
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ContentProvider.openFile}.
78394366313331a789440a3c077173aafcb85cabe78Ying Wang     * @param cancellationSignal A signal to cancel the operation in progress,
78494366313331a789440a3c077173aafcb85cabe78Ying Wang     *         or null if none. If the operation is canceled, then
78594366313331a789440a3c077173aafcb85cabe78Ying Wang     *         {@link OperationCanceledException} will be thrown.
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new ParcelFileDescriptor pointing to the file.  You
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * own this descriptor and are responsible for closing it when done.
788f9c5176a51a49fea18712338429b4d125e550a4aYury Zhauniarovich     * @throws FileNotFoundException Throws FileNotFoundException if no
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * file exists under the URI or the mode is invalid.
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openAssetFileDescriptor(Uri, String)
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
792673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
793673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
794673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey                    throws FileNotFoundException {
795bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey        AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (afd == null) {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7990ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (afd.getDeclaredLength() < 0) {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is a full file!
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return afd.getParcelFileDescriptor();
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8040ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Client can't handle a sub-section of a file, so close what
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // we got and bail with an exception.
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            afd.close();
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8110ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new FileNotFoundException("Not a whole file");
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
81623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Open a raw file descriptor to access data under a URI.  This
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * interacts with the underlying {@link ContentProvider#openAssetFile}
81803f0292744094ec107ffce71301c394503a31dedGilles Debunne     * method of the provider associated with the given URI, to retrieve any file stored there.
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <h5>Accepts the following URI schemes:</h5>
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>content ({@link #SCHEME_CONTENT})</li>
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>file ({@link #SCHEME_FILE})</li>
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A Uri object can be used to reference a resource in an APK file.  The
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Uri should be one of the following formats:
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li><code>android.resource://package_name/id_number</code><br/>
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For example <code>com.example.myapp</code><br/>
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>id_number</code> is the int form of the ID.<br/>
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The easiest way to construct this form is
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </li>
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li><code>android.resource://package_name/type/name</code><br/>
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For example <code>com.example.myapp</code><br/>
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or <code>drawable</code>.
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>name</code> is the string form of the resource name.  That is, whatever the file
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * name was in your res directory, without the type extension.
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The easiest way to construct this form is
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </li>
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
85023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * <p>Note that if this function is called for read-only input (mode is "r")
85123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
8523390018c6b45acffa6edf97a4174ca49f1e8c76dJohn Spurlock     * for you with a MIME type of "*&#47;*".  This allows such callers to benefit
85323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * from any built-in data conversion that a provider implements.
85423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The desired URI to open.
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ContentProvider.openAssetFile}.
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new ParcelFileDescriptor pointing to the file.  You
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * own this descriptor and are responsible for closing it when done.
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException Throws FileNotFoundException of no
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * file exists under the URI or the mode is invalid.
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
863673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
864673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String mode) throws FileNotFoundException {
865bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey        return openAssetFileDescriptor(uri, mode, null);
866bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey    }
867bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey
868bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey    /**
869bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * Open a raw file descriptor to access data under a URI.  This
870bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * interacts with the underlying {@link ContentProvider#openAssetFile}
871bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * method of the provider associated with the given URI, to retrieve any file stored there.
872bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
873bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <h5>Accepts the following URI schemes:</h5>
874bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <ul>
875bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <li>content ({@link #SCHEME_CONTENT})</li>
876bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
877bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <li>file ({@link #SCHEME_FILE})</li>
878bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * </ul>
879bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
880bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>
881bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * A Uri object can be used to reference a resource in an APK file.  The
882bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * Uri should be one of the following formats:
883bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <ul>
884bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <li><code>android.resource://package_name/id_number</code><br/>
885bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
886bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * For example <code>com.example.myapp</code><br/>
887bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <code>id_number</code> is the int form of the ID.<br/>
888bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * The easiest way to construct this form is
889bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
890bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * </li>
891bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <li><code>android.resource://package_name/type/name</code><br/>
892bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
893bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * For example <code>com.example.myapp</code><br/>
894bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <code>type</code> is the string form of the resource type.  For example, <code>raw</code>
895bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * or <code>drawable</code>.
896bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <code>name</code> is the string form of the resource name.  That is, whatever the file
897bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * name was in your res directory, without the type extension.
898bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * The easiest way to construct this form is
899bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
900bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * </li>
901bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * </ul>
902bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
903bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>Note that if this function is called for read-only input (mode is "r")
904bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
9053390018c6b45acffa6edf97a4174ca49f1e8c76dJohn Spurlock     * for you with a MIME type of "*&#47;*".  This allows such callers to benefit
906bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * from any built-in data conversion that a provider implements.
907bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
908bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @param uri The desired URI to open.
909bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
910bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * ContentProvider.openAssetFile}.
91194366313331a789440a3c077173aafcb85cabe78Ying Wang     * @param cancellationSignal A signal to cancel the operation in progress, or null if
912bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *            none. If the operation is canceled, then
913bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *            {@link OperationCanceledException} will be thrown.
914bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @return Returns a new ParcelFileDescriptor pointing to the file.  You
915bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * own this descriptor and are responsible for closing it when done.
916bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @throws FileNotFoundException Throws FileNotFoundException of no
917bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * file exists under the URI or the mode is invalid.
918bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     */
919673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
920673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
921673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey                    throws FileNotFoundException {
922673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
923673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(mode, "mode");
924673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String scheme = uri.getScheme();
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!"r".equals(mode)) {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("Can't write resources: " + uri);
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            OpenResourceIdResult r = getResourceId(uri);
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r.r.openRawResourceFd(r.id);
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Resources.NotFoundException ex) {
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("Resource does not exist: " + uri);
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (SCHEME_FILE.equals(scheme)) {
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
938eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski                    new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode));
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new AssetFileDescriptor(pfd, 0, -1);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
94123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            if ("r".equals(mode)) {
942bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                return openTypedAssetFileDescriptor(uri, "*/*", null, cancellationSignal);
94323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            } else {
9446ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                IContentProvider unstableProvider = acquireUnstableProvider(uri);
9456ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                if (unstableProvider == null) {
9466ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    throw new FileNotFoundException("No content provider: " + uri);
9476ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                }
9486ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                IContentProvider stableProvider = null;
9496ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                AssetFileDescriptor fd = null;
9506ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
9516ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                try {
952bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                    ICancellationSignal remoteCancellationSignal = null;
953bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                    if (cancellationSignal != null) {
954bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        cancellationSignal.throwIfCanceled();
955bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        remoteCancellationSignal = unstableProvider.createCancellationSignal();
956bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        cancellationSignal.setRemote(remoteCancellationSignal);
957bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                    }
958bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey
959652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                    try {
960bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        fd = unstableProvider.openAssetFile(
961bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                                mPackageName, uri, mode, remoteCancellationSignal);
962652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                        if (fd == null) {
963652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                            // The provider will be released by the finally{} clause
964652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                            return null;
965652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                        }
9666ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    } catch (DeadObjectException e) {
9676ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        // The remote process has died...  but we only hold an unstable
9686ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        // reference though, so we might recover!!!  Let's try!!!!
9696ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        // This is exciting!!1!!1!!!!1
9706ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        unstableProviderDied(unstableProvider);
9716ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        stableProvider = acquireProvider(uri);
9726ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        if (stableProvider == null) {
9736ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                            throw new FileNotFoundException("No content provider: " + uri);
974652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                        }
975bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        fd = stableProvider.openAssetFile(
976bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                                mPackageName, uri, mode, remoteCancellationSignal);
9776ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        if (fd == null) {
9786ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                            // The provider will be released by the finally{} clause
9796ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                            return null;
980652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                        }
98123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    }
9826ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
9836ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    if (stableProvider == null) {
9846ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        stableProvider = acquireProvider(uri);
9856ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    }
9866ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    releaseUnstableProvider(unstableProvider);
9876ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
9886ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                            fd.getParcelFileDescriptor(), stableProvider);
9896ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
9906ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    // Success!  Don't release the provider when exiting, let
9916ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    // ParcelFileDescriptorInner do that when it is closed.
9926ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    stableProvider = null;
9936ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
9946ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    return new AssetFileDescriptor(pfd, fd.getStartOffset(),
9956ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                            fd.getDeclaredLength());
9966ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
9976ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                } catch (RemoteException e) {
9986ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    // Whatever, whatever, we'll go away.
9996ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    throw new FileNotFoundException(
10006ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                            "Failed opening content provider: " + uri);
10016ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                } catch (FileNotFoundException e) {
10026ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    throw e;
10036ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                } finally {
1004bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                    if (cancellationSignal != null) {
1005bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        cancellationSignal.setRemote(null);
1006bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                    }
10076ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    if (stableProvider != null) {
10086ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        releaseProvider(stableProvider);
10096ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    }
10106ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    if (unstableProvider != null) {
10116ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                        releaseUnstableProvider(unstableProvider);
10126ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    }
101323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                }
101423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            }
101523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
101623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
101723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
101823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
101923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Open a raw file descriptor to access (potentially type transformed)
102023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * data from a "content:" URI.  This interacts with the underlying
102123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * {@link ContentProvider#openTypedAssetFile} method of the provider
102223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * associated with the given URI, to retrieve retrieve any appropriate
102323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * data stream for the data stored there.
102423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
102523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
102623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * with "content:" URIs, because content providers are the only facility
102723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * with an associated MIME type to ensure that the returned data stream
102823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * is of the desired type.
102923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
103023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * <p>All text/* streams are encoded in UTF-8.
103123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
103223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param uri The desired URI to open.
103323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeType The desired MIME type of the returned data.  This can
10343390018c6b45acffa6edf97a4174ca49f1e8c76dJohn Spurlock     * be a pattern such as *&#47;*, which will allow the content provider to
103523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * select a type, though there is no way for you to determine what type
103623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * it is returning.
103723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param opts Additional provider-dependent options.
103823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @return Returns a new ParcelFileDescriptor from which you can read the
103923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * data stream from the provider.  Note that this may be a pipe, meaning
104023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * you can't seek in it.  The only seek you should do is if the
104123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * AssetFileDescriptor contains an offset, to move to that offset before
104223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * reading.  You own this descriptor and are responsible for closing it when done.
104323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @throws FileNotFoundException Throws FileNotFoundException of no
104423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * data of the desired type exists under the URI.
104523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
1046673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
1047673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String mimeType, @Nullable Bundle opts) throws FileNotFoundException {
1048bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey        return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
1049bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey    }
1050bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey
1051bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey    /**
1052bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * Open a raw file descriptor to access (potentially type transformed)
1053bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * data from a "content:" URI.  This interacts with the underlying
1054bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * {@link ContentProvider#openTypedAssetFile} method of the provider
1055bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * associated with the given URI, to retrieve retrieve any appropriate
1056bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * data stream for the data stored there.
1057bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
1058bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>Unlike {@link #openAssetFileDescriptor}, this function only works
1059bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * with "content:" URIs, because content providers are the only facility
1060bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * with an associated MIME type to ensure that the returned data stream
1061bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * is of the desired type.
1062bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
1063bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * <p>All text/* streams are encoded in UTF-8.
1064bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     *
1065bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @param uri The desired URI to open.
1066bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @param mimeType The desired MIME type of the returned data.  This can
10673390018c6b45acffa6edf97a4174ca49f1e8c76dJohn Spurlock     * be a pattern such as *&#47;*, which will allow the content provider to
1068bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * select a type, though there is no way for you to determine what type
1069bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * it is returning.
1070bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @param opts Additional provider-dependent options.
107194366313331a789440a3c077173aafcb85cabe78Ying Wang     * @param cancellationSignal A signal to cancel the operation in progress,
107294366313331a789440a3c077173aafcb85cabe78Ying Wang     *         or null if none. If the operation is canceled, then
107394366313331a789440a3c077173aafcb85cabe78Ying Wang     *         {@link OperationCanceledException} will be thrown.
1074bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @return Returns a new ParcelFileDescriptor from which you can read the
1075bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * data stream from the provider.  Note that this may be a pipe, meaning
1076bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * you can't seek in it.  The only seek you should do is if the
1077bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * AssetFileDescriptor contains an offset, to move to that offset before
1078bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * reading.  You own this descriptor and are responsible for closing it when done.
1079bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * @throws FileNotFoundException Throws FileNotFoundException of no
1080bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     * data of the desired type exists under the URI.
1081bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey     */
1082673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
1083673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String mimeType, @Nullable Bundle opts,
1084673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable CancellationSignal cancellationSignal) throws FileNotFoundException {
1085673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
1086673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(mimeType, "mimeType");
1087673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey
10886ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        IContentProvider unstableProvider = acquireUnstableProvider(uri);
10896ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        if (unstableProvider == null) {
10906ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            throw new FileNotFoundException("No content provider: " + uri);
10916ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        }
10926ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        IContentProvider stableProvider = null;
10936ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        AssetFileDescriptor fd = null;
10946ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
10956ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        try {
1096bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            ICancellationSignal remoteCancellationSignal = null;
1097bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            if (cancellationSignal != null) {
1098bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                cancellationSignal.throwIfCanceled();
1099bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                remoteCancellationSignal = unstableProvider.createCancellationSignal();
1100bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                cancellationSignal.setRemote(remoteCancellationSignal);
1101bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            }
1102bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey
1103652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            try {
1104bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                fd = unstableProvider.openTypedAssetFile(
1105bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        mPackageName, uri, mimeType, opts, remoteCancellationSignal);
1106652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                if (fd == null) {
1107652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                    // The provider will be released by the finally{} clause
1108652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                    return null;
1109652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                }
11106ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            } catch (DeadObjectException e) {
11116ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                // The remote process has died...  but we only hold an unstable
11126ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                // reference though, so we might recover!!!  Let's try!!!!
11136ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                // This is exciting!!1!!1!!!!1
11146ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                unstableProviderDied(unstableProvider);
11156ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                stableProvider = acquireProvider(uri);
11166ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                if (stableProvider == null) {
11176ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    throw new FileNotFoundException("No content provider: " + uri);
1118652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                }
1119bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                fd = stableProvider.openTypedAssetFile(
1120bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                        mPackageName, uri, mimeType, opts, remoteCancellationSignal);
11216ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                if (fd == null) {
11226ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    // The provider will be released by the finally{} clause
11236ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    return null;
1124652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn                }
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11266ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
11276ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            if (stableProvider == null) {
11286ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                stableProvider = acquireProvider(uri);
11296ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            }
11306ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            releaseUnstableProvider(unstableProvider);
11316ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
11326ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    fd.getParcelFileDescriptor(), stableProvider);
11336ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
11346ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            // Success!  Don't release the provider when exiting, let
11356ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            // ParcelFileDescriptorInner do that when it is closed.
11366ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            stableProvider = null;
11376ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
11386ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            return new AssetFileDescriptor(pfd, fd.getStartOffset(),
11396ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    fd.getDeclaredLength());
11406ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn
11416ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        } catch (RemoteException e) {
11426ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            // Whatever, whatever, we'll go away.
11436ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            throw new FileNotFoundException(
11446ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                    "Failed opening content provider: " + uri);
11456ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        } catch (FileNotFoundException e) {
11466ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            throw e;
11476ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        } finally {
1148bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            if (cancellationSignal != null) {
1149bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey                cancellationSignal.setRemote(null);
1150bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey            }
11516ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            if (stableProvider != null) {
11526ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                releaseProvider(stableProvider);
11536ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            }
11546ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            if (unstableProvider != null) {
11556ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                releaseUnstableProvider(unstableProvider);
11566ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            }
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11604c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert    /**
11614c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     * A resource identified by the {@link Resources} that contains it, and a resource id.
11624c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     *
11634c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     * @hide
11644c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     */
11654c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert    public class OpenResourceIdResult {
11664c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert        public Resources r;
11674c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert        public int id;
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11694c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert
11704c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert    /**
11714c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     * Resolves an android.resource URI to a {@link Resources} and a resource id.
11724c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     *
11734c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     * @hide
11744c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert     */
11754c87a3f26a7c0c75fa371024a8726b59a108fd0fBjorn Bringert    public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String authority = uri.getAuthority();
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r;
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (TextUtils.isEmpty(authority)) {
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("No authority: " + uri);
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r = mContext.getPackageManager().getResourcesForApplication(authority);
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (NameNotFoundException ex) {
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("No package found for authority: " + uri);
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<String> path = uri.getPathSegments();
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (path == null) {
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("No path: " + uri);
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int len = path.size();
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int id;
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len == 1) {
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                id = Integer.parseInt(path.get(0));
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (NumberFormatException e) {
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("Single path segment is not a resource ID: " + uri);
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (len == 2) {
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            id = r.getIdentifier(path.get(1), path.get(0), authority);
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("More than two path segments: " + uri);
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id == 0) {
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("No resource found for: " + uri);
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        OpenResourceIdResult res = new OpenResourceIdResult();
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res.r = r;
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res.id = id;
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return res;
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12120ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inserts a row into a table at the given URL.
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the content provider supports transactions the insertion will be atomic.
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The URL of the table to insert into.
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values The initial values for the newly inserted row. The key is the column name for
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               the field. Passing an empty ContentValues will create an empty row.
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the URL of the newly created row.
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
122334796bd07f871bc762d8ebd55cfbb80fcff4aecaJeff Sharkey    public final @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues values) {
1224673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(url, "url");
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IContentProvider provider = acquireProvider(url);
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (provider == null) {
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown URL " + url);
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1230d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long startTime = SystemClock.uptimeMillis();
123135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Uri createdRow = provider.insert(mPackageName, url, values);
1232d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long durationMillis = SystemClock.uptimeMillis() - startTime;
1233a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
1234a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            return createdRow;
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
1236534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
1237534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            releaseProvider(provider);
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12448943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    /**
12458943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * Applies each of the {@link ContentProviderOperation} objects and returns an array
12468943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * of their results. Passes through OperationApplicationException, which may be thrown
12478943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * by the call to {@link ContentProviderOperation#apply}.
12488943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * If all the applications succeed then a {@link ContentProviderResult} array with the
12498943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * same number of elements as the operations will be returned. It is implementation-specific
12508943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * how many, if any, operations will have been successfully applied if a call to
12518943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * apply results in a {@link OperationApplicationException}.
12528943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * @param authority the authority of the ContentProvider to which this batch should be applied
12538943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * @param operations the operations to apply
12548943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * @return the results of the applications
12558943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * @throws OperationApplicationException thrown if an application fails.
12568943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * See {@link ContentProviderOperation#apply} for more information.
12578943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     * @throws RemoteException thrown if a RemoteException is encountered while attempting
12588943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     *   to communicate with a remote provider.
12598943737692169f564cd34a9c8d471f3a5d438712Fred Quintana     */
1260673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
1261673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull ArrayList<ContentProviderOperation> operations)
1262673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey                    throws RemoteException, OperationApplicationException {
1263673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(authority, "authority");
1264673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(operations, "operations");
12658943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        ContentProviderClient provider = acquireContentProviderClient(authority);
12666a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana        if (provider == null) {
12678943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            throw new IllegalArgumentException("Unknown authority " + authority);
12686a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana        }
12696a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana        try {
12708943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            return provider.applyBatch(operations);
12716a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana        } finally {
12726a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana            provider.release();
12736a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana        }
12746a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana    }
12756a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inserts multiple rows into a table at the given URL.
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This function make no guarantees about the atomicity of the insertions.
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The URL of the table to insert into.
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values The initial values for the newly inserted rows. The key is the column name for
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               the field. Passing null will create an empty row.
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the number of newly created rows.
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1286673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] values) {
1287673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(url, "url");
1288673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(values, "values");
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IContentProvider provider = acquireProvider(url);
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (provider == null) {
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown URL " + url);
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1294d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long startTime = SystemClock.uptimeMillis();
129535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            int rowsCreated = provider.bulkInsert(mPackageName, url, values);
1296d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long durationMillis = SystemClock.uptimeMillis() - startTime;
1297a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
1298a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            return rowsCreated;
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
1300534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
1301534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            releaseProvider(provider);
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Deletes row(s) specified by a content URI.
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the content provider supports transactions, the deletion will be atomic.
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The URL of the row to delete.
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    (excluding the WHERE itself).
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of rows deleted.
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1318673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final int delete(@NonNull Uri url, @Nullable String where,
1319673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable String[] selectionArgs) {
1320673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(url, "url");
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IContentProvider provider = acquireProvider(url);
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (provider == null) {
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown URL " + url);
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1326d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long startTime = SystemClock.uptimeMillis();
132735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            int rowsDeleted = provider.delete(mPackageName, url, where, selectionArgs);
1328d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long durationMillis = SystemClock.uptimeMillis() - startTime;
1329a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
1330a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            return rowsDeleted;
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
1332534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
1333534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            releaseProvider(provider);
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Update row(s) in a content URI.
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the content provider supports transactions the update will be atomic.
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to modify.
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values The new field values. The key is the column name for the field.
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     A null value will remove an existing field value.
1348d2a2daaa89865d19e881ab9af133ce0f3902c820Omari Stephens     * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    (excluding the WHERE itself).
1350534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @return the number of rows updated.
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws NullPointerException if uri or values are null
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
135334796bd07f871bc762d8ebd55cfbb80fcff4aecaJeff Sharkey    public final int update(@NonNull Uri uri, @Nullable ContentValues values,
1354673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable String where, @Nullable String[] selectionArgs) {
1355673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IContentProvider provider = acquireProvider(uri);
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (provider == null) {
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown URI " + uri);
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1361d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long startTime = SystemClock.uptimeMillis();
136235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            int rowsUpdated = provider.update(mPackageName, uri, values, where, selectionArgs);
1363d72f718c9cc4bd5e4701f4c5cdab51b4d8cf6435Brad Fitzpatrick            long durationMillis = SystemClock.uptimeMillis() - startTime;
1364a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
1365a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            return rowsUpdated;
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
1367534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
1368534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            releaseProvider(provider);
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1376f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa     * Call a provider-defined method.  This can be used to implement
1377534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * read or write interfaces which are cheaper than using a Cursor and/or
1378534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * do not fit into the traditional table model.
1379534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     *
1380534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @param method provider-defined method name to call.  Opaque to
1381534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     *   framework, but must be non-null.
1382534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @param arg provider-defined String argument.  May be null.
1383534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @param extras provider-defined Bundle argument.  May be null.
1384534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @return a result Bundle, possibly null.  Will be null if the ContentProvider
1385534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     *   does not implement call.
1386534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @throws NullPointerException if uri or method is null
1387534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @throws IllegalArgumentException if uri is not known
1388534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     */
1389673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
1390673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Nullable String arg, @Nullable Bundle extras) {
1391673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
1392673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(method, "method");
1393534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        IContentProvider provider = acquireProvider(uri);
1394534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        if (provider == null) {
1395534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            throw new IllegalArgumentException("Unknown URI " + uri);
1396534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        }
1397534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        try {
139835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            return provider.call(mPackageName, method, arg, extras);
1399534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        } catch (RemoteException e) {
1400534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Arbitrary and not worth documenting, as Activity
1401534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            // Manager will kill this process shortly anyway.
1402534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            return null;
1403534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        } finally {
1404534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            releaseProvider(provider);
1405534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        }
1406534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick    }
1407534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick
1408534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick    /**
1409cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * Returns the content provider for the given content URI.
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to a content provider
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The ContentProvider for the given URI, or null if no content provider is found.
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1415cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn    public final IContentProvider acquireProvider(Uri uri) {
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!SCHEME_CONTENT.equals(uri.getScheme())) {
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1419f9c5176a51a49fea18712338429b4d125e550a4aYury Zhauniarovich        final String auth = uri.getAuthority();
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (auth != null) {
1421f9c5176a51a49fea18712338429b4d125e550a4aYury Zhauniarovich            return acquireProvider(mContext, auth);
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1427cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * Returns the content provider for the given content URI if the process
1428cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * already has a reference on it.
1429cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     *
1430cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * @param uri The URI to a content provider
1431cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * @return The ContentProvider for the given URI, or null if no content provider is found.
1432cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * @hide
1433cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     */
1434cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn    public final IContentProvider acquireExistingProvider(Uri uri) {
1435cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        if (!SCHEME_CONTENT.equals(uri.getScheme())) {
1436cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn            return null;
1437cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        }
1438f9c5176a51a49fea18712338429b4d125e550a4aYury Zhauniarovich        final String auth = uri.getAuthority();
1439cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        if (auth != null) {
1440f9c5176a51a49fea18712338429b4d125e550a4aYury Zhauniarovich            return acquireExistingProvider(mContext, auth);
1441cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        }
1442cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn        return null;
1443cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn    }
1444cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn
1445cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn    /**
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final IContentProvider acquireProvider(String name) {
14491877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick        if (name == null) {
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return acquireProvider(mContext, name);
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1456652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * Returns the content provider for the given content URI.
1457652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     *
1458652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * @param uri The URI to a content provider
1459652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * @return The ContentProvider for the given URI, or null if no content provider is found.
1460652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * @hide
1461652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     */
1462652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    public final IContentProvider acquireUnstableProvider(Uri uri) {
1463652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        if (!SCHEME_CONTENT.equals(uri.getScheme())) {
1464652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            return null;
1465652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        }
1466652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        String auth = uri.getAuthority();
1467652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        if (auth != null) {
1468652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            return acquireUnstableProvider(mContext, uri.getAuthority());
1469652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        }
1470652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        return null;
1471652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    }
1472652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn
1473652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    /**
1474652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * @hide
1475652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     */
1476652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    public final IContentProvider acquireUnstableProvider(String name) {
1477652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        if (name == null) {
1478652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            return null;
1479652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        }
14806ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        return acquireUnstableProvider(mContext, name);
1481652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    }
1482652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn
1483652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    /**
1484718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1485718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * that services the content at uri, starting the provider if necessary. Returns
1486718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * null if there is no provider associated wih the uri. The caller must indicate that they are
1487718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * done with the provider by calling {@link ContentProviderClient#release} which will allow
1488718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * the system to release the provider it it determines that there is no other reason for
1489718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * keeping it active.
1490718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * @param uri specifies which provider should be acquired
1491718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1492718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * that services the content at uri or null if there isn't one.
1493718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     */
1494673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) {
1495673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
1496718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        IContentProvider provider = acquireProvider(uri);
1497718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        if (provider != null) {
1498652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            return new ContentProviderClient(this, provider, true);
1499718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        }
1500718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        return null;
1501718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana    }
1502718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana
1503718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana    /**
1504718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1505718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * with the authority of name, starting the provider if necessary. Returns
1506718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * null if there is no provider associated wih the uri. The caller must indicate that they are
1507718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * done with the provider by calling {@link ContentProviderClient#release} which will allow
1508718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * the system to release the provider it it determines that there is no other reason for
1509718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * keeping it active.
1510718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * @param name specifies which provider should be acquired
1511718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
1512718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     * with the authority of name or null if there isn't one.
1513718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana     */
1514673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable ContentProviderClient acquireContentProviderClient(
1515673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String name) {
1516673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(name, "name");
1517718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        IContentProvider provider = acquireProvider(name);
1518718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        if (provider != null) {
1519652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            return new ContentProviderClient(this, provider, true);
1520652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        }
1521652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn
1522652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        return null;
1523652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    }
1524652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn
1525652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    /**
1526652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do
1527652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * not trust the stability of the target content provider.  This turns off
1528652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * the mechanism in the platform clean up processes that are dependent on
1529652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * a content provider if that content provider's process goes away.  Normally
1530652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * you can safely assume that once you have acquired a provider, you can freely
1531652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * use it as needed and it won't disappear, even if your process is in the
1532652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * background.  If using this method, you need to take care to deal with any
1533652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * failures when communicating with the provider, and be sure to close it
15346ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * so that it can be re-opened later.  In particular, catching a
15356ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * {@link android.os.DeadObjectException} from the calls there will let you
15366ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * know that the content provider has gone away; at that point the current
15376ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * ContentProviderClient object is invalid, and you should release it.  You
15386ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * can acquire a new one if you would like to try to restart the provider
15396ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * and perform new operations on it.
1540652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     */
1541673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
1542673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull Uri uri) {
1543673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
15446ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        IContentProvider provider = acquireUnstableProvider(uri);
1545652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        if (provider != null) {
1546652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            return new ContentProviderClient(this, provider, false);
1547652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        }
1548652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn
1549652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        return null;
1550652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    }
1551652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn
1552652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn    /**
1553652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * Like {@link #acquireContentProviderClient(String)}, but for use when you do
1554652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * not trust the stability of the target content provider.  This turns off
1555652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * the mechanism in the platform clean up processes that are dependent on
1556652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * a content provider if that content provider's process goes away.  Normally
1557652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * you can safely assume that once you have acquired a provider, you can freely
1558652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * use it as needed and it won't disappear, even if your process is in the
1559652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * background.  If using this method, you need to take care to deal with any
1560652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     * failures when communicating with the provider, and be sure to close it
15616ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * so that it can be re-opened later.  In particular, catching a
15626ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * {@link android.os.DeadObjectException} from the calls there will let you
15636ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * know that the content provider has gone away; at that point the current
15646ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * ContentProviderClient object is invalid, and you should release it.  You
15656ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * can acquire a new one if you would like to try to restart the provider
15666ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn     * and perform new operations on it.
1567652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn     */
1568673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
1569673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull String name) {
1570673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(name, "name");
15716ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn        IContentProvider provider = acquireUnstableProvider(name);
1572652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn        if (provider != null) {
1573652b6d1e591f6684cda4b93d4712920f287991b4Dianne Hackborn            return new ContentProviderClient(this, provider, false);
1574718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        }
1575718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana
1576718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana        return null;
1577718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana    }
1578718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana
1579718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana    /**
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register an observer class that gets callbacks when data identified by a
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * given content URI changes.
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for a whole class of content.
1585143739cb6b0468804f83f2398b3666eb21280de6Jeff Brown     * @param notifyForDescendents When false, the observer will be notified whenever a
1586143739cb6b0468804f83f2398b3666eb21280de6Jeff Brown     * change occurs to the exact URI specified by <code>uri</code> or to one of the
1587143739cb6b0468804f83f2398b3666eb21280de6Jeff Brown     * URI's ancestors in the path hierarchy.  When true, the observer will also be notified
1588143739cb6b0468804f83f2398b3666eb21280de6Jeff Brown     * whenever a change occurs to the URI's descendants in the path hierarchy.
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param observer The object that receives callbacks when changes occur.
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #unregisterContentObserver
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1592673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendents,
1593673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @NonNull ContentObserver observer) {
1594673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
1595673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(observer, "observer");
1596adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz        registerContentObserver(
1597adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                ContentProvider.getUriWithoutUserId(uri),
1598adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                notifyForDescendents,
1599adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                observer,
1600adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
160116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate    }
160216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate
160316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate    /** @hide - designated user version */
160416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate    public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
1605143739cb6b0468804f83f2398b3666eb21280de6Jeff Brown            ContentObserver observer, int userHandle) {
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1607231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            getContentService().registerContentObserver(uri, notifyForDescendents,
160816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate                    observer.getContentObserver(), userHandle);
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a change observer.
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param observer The previously registered observer that is no longer needed.
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #registerContentObserver
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1619673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public final void unregisterContentObserver(@NonNull ContentObserver observer) {
1620673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(observer, "observer");
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IContentObserver contentObserver = observer.releaseContentObserver();
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (contentObserver != null) {
1624231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                getContentService().unregisterContentObserver(
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        contentObserver);
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1632d7a1aada2d1245eaeef973bc3e37619ce8e6d593Steve Pomeroy     * Notify registered observers that a row was updated and attempt to sync changes
1633d7a1aada2d1245eaeef973bc3e37619ce8e6d593Steve Pomeroy     * to the network.
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * By default, CursorAdapter objects will get this notification.
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
163786de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @param uri The uri of the content that was changed.
163886de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @param observer The observer that originated the change, may be <code>null</null>.
163986de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * The observer that originated the change will only receive the notification if it
164086de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * has requested to receive self-change notifications by implementing
164186de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * {@link ContentObserver#deliverSelfNotifications()} to return true.
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1643673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notifyChange(uri, observer, true /* sync to network */);
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notify registered observers that a row was updated.
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * By default, CursorAdapter objects will get this notification.
1651d7a1aada2d1245eaeef973bc3e37619ce8e6d593Steve Pomeroy     * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
1652d7a1aada2d1245eaeef973bc3e37619ce8e6d593Steve Pomeroy     * adapter that's registered for the authority of the provided uri. No account will be
1653d7a1aada2d1245eaeef973bc3e37619ce8e6d593Steve Pomeroy     * passed to the sync adapter, so all matching accounts will be synchronized.
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
165586de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @param uri The uri of the content that was changed.
165686de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @param observer The observer that originated the change, may be <code>null</null>.
165786de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * The observer that originated the change will only receive the notification if it
165886de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * has requested to receive self-change notifications by implementing
165986de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * {@link ContentObserver#deliverSelfNotifications()} to return true.
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param syncToNetwork If true, attempt to sync the change to the network.
1661d7a1aada2d1245eaeef973bc3e37619ce8e6d593Steve Pomeroy     * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1663673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
1664673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            boolean syncToNetwork) {
1665673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
1666adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz        notifyChange(
1667adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                ContentProvider.getUriWithoutUserId(uri),
1668adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                observer,
1669adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                syncToNetwork,
1670adea1918bef942b6214cf549b1316affd2b10280Benjamin Franz                ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
167116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate    }
167216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate
167316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate    /**
167416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate     * Notify registered observers within the designated user(s) that a row was updated.
167516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate     *
167616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate     * @hide
167716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate     */
167816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate    public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
167916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate            int userHandle) {
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1681231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            getContentService().notifyChange(
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    uri, observer == null ? null : observer.getContentObserver(),
168316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate                    observer != null && observer.deliverSelfNotifications(), syncToNetwork,
168416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate                    userHandle);
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1690adef88a0a9d65e7f5ae812594e8c039747388cddJeff Sharkey     * Take a persistable URI permission grant that has been offered. Once
1691e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * taken, the permission grant will be remembered across device reboots.
1692adef88a0a9d65e7f5ae812594e8c039747388cddJeff Sharkey     * Only URI permissions granted with
1693e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} can be persisted. If
1694e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * the grant has already been persisted, taking it again will touch
1695e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * {@link UriPermission#getPersistedTime()}.
169608da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey     *
1697e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * @see #getPersistedUriPermissions()
169808da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey     */
1699673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public void takePersistableUriPermission(@NonNull Uri uri,
1700673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Intent.AccessUriMode int modeFlags) {
1701673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
170208da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey        try {
1703d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            ActivityManagerNative.getDefault().takePersistableUriPermission(
1704d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot                    ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
170508da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey        } catch (RemoteException e) {
170608da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey        }
170708da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey    }
170808da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey
170908da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey    /**
1710adef88a0a9d65e7f5ae812594e8c039747388cddJeff Sharkey     * Relinquish a persisted URI permission grant. The URI must have been
1711e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * previously made persistent with
1712e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * {@link #takePersistableUriPermission(Uri, int)}. Any non-persistent
1713e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * grants to the calling package will remain intact.
171408da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey     *
1715e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * @see #getPersistedUriPermissions()
1716e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     */
1717673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public void releasePersistableUriPermission(@NonNull Uri uri,
1718673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey            @Intent.AccessUriMode int modeFlags) {
1719673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey        Preconditions.checkNotNull(uri, "uri");
1720e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey        try {
1721d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            ActivityManagerNative.getDefault().releasePersistableUriPermission(
1722d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot                    ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
1723e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey        } catch (RemoteException e) {
1724e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey        }
1725e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey    }
1726e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey
1727e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey    /**
1728adef88a0a9d65e7f5ae812594e8c039747388cddJeff Sharkey     * Return list of all URI permission grants that have been persisted by the
1729bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey     * calling app. That is, the returned permissions have been granted
1730bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey     * <em>to</em> the calling app. Only persistable grants taken with
1731e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * {@link #takePersistableUriPermission(Uri, int)} are returned.
173208da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey     *
1733e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * @see #takePersistableUriPermission(Uri, int)
1734e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey     * @see #releasePersistableUriPermission(Uri, int)
173508da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey     */
1736673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public @NonNull List<UriPermission> getPersistedUriPermissions() {
173708da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey        try {
1738bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey            return ActivityManagerNative.getDefault()
1739bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey                    .getPersistedUriPermissions(mPackageName, true).getList();
1740bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey        } catch (RemoteException e) {
1741bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey            throw new RuntimeException("Activity manager has died", e);
1742bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey        }
1743bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey    }
1744bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey
1745bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey    /**
1746adef88a0a9d65e7f5ae812594e8c039747388cddJeff Sharkey     * Return list of all persisted URI permission grants that are hosted by the
1747bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey     * calling app. That is, the returned permissions have been granted
1748bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey     * <em>from</em> the calling app. Only grants taken with
1749bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey     * {@link #takePersistableUriPermission(Uri, int)} are returned.
1750bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey     */
1751673db44fb3da4558059ef9746a496a63157f10bcJeff Sharkey    public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
1752bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey        try {
1753bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey            return ActivityManagerNative.getDefault()
1754bcaac0adecc8f9d7e66548df39e0f5c9f759e38cJeff Sharkey                    .getPersistedUriPermissions(mPackageName, false).getList();
175508da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey        } catch (RemoteException e) {
1756e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey            throw new RuntimeException("Activity manager has died", e);
175708da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey        }
175808da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey    }
175908da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey
176008da7a1143b0c9cfb703971d882e0886bbd7d9deJeff Sharkey    /**
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Start an asynchronous sync operation. If you want to monitor the progress
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the sync you may register a SyncObserver. Only values of the following
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * types may be used in the extras bundle:
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Integer</li>
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Long</li>
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Boolean</li>
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Float</li>
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Double</li>
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>String</li>
1771fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * <li>Account</li>
1772fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * <li>null</li>
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri the uri of the provider to sync or null to sync all providers.
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param extras any extras to pass to the SyncAdapter.
1777ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @deprecated instead use
1778ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17804a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startSync(Uri uri, Bundle extras) {
1782ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        Account account = null;
1783ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        if (extras != null) {
1784ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT);
1785ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!TextUtils.isEmpty(accountName)) {
17863348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                account = new Account(accountName, "com.google");
1787ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            }
1788ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            extras.remove(SYNC_EXTRAS_ACCOUNT);
1789ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
1790ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        requestSync(account, uri != null ? uri.getAuthority() : null, extras);
1791ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
1792ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1793ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
1794ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Start an asynchronous sync operation. If you want to monitor the progress
1795ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * of the sync you may register a SyncObserver. Only values of the following
1796ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * types may be used in the extras bundle:
1797ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * <ul>
1798ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * <li>Integer</li>
1799ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * <li>Long</li>
1800ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * <li>Boolean</li>
1801ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * <li>Float</li>
1802ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * <li>Double</li>
1803ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * <li>String</li>
1804fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * <li>Account</li>
1805fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * <li>null</li>
1806ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * </ul>
1807ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     *
1808ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account which account should be synced
1809ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority which authority should be synced
1810ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param extras any extras to pass to the SyncAdapter.
1811ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
1812ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static void requestSync(Account account, String authority, Bundle extras) {
181303e1e836976f44ed729fa0a41898d7ce4df34788Alexandra Gherghina        requestSyncAsUser(account, authority, UserHandle.myUserId(), extras);
18140363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
18150363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
18160363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
18170363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #requestSync(Account, String, Bundle)
18180363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
18190363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
18200363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static void requestSyncAsUser(Account account, String authority, int userId,
18210363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            Bundle extras) {
1822d8abd6a163f8ab4332b88035e77080c48b4b71b9Matthew Williams        if (extras == null) {
1823d8abd6a163f8ab4332b88035e77080c48b4b71b9Matthew Williams            throw new IllegalArgumentException("Must specify extras.");
1824d8abd6a163f8ab4332b88035e77080c48b4b71b9Matthew Williams        }
1825fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        SyncRequest request =
1826fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            new SyncRequest.Builder()
1827fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                .setSyncAdapter(account, authority)
1828fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                .setExtras(extras)
182969002ae2a2afd0f759c22ea47d669ddc33b3255aNick Kralevich                .syncOnce()     // Immediate sync.
1830fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                .build();
18310363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
18320363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            getContentService().syncAsUser(request, userId);
18330363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch(RemoteException e) {
18340363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            // Shouldn't happen.
18350363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
1836fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
1837fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
1838fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
1839fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Register a sync with the SyncManager. These requests are built using the
1840fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * {@link SyncRequest.Builder}.
1841fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
1842fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public static void requestSync(SyncRequest request) {
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1844fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            getContentService().sync(request);
1845fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        } catch(RemoteException e) {
1846fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            // Shouldn't happen.
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Check that only values of the following types are in the Bundle:
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Integer</li>
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Long</li>
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Boolean</li>
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Float</li>
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Double</li>
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>String</li>
1859d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana     * <li>Account</li>
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>null</li>
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param extras the Bundle to check
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void validateSyncExtrasBundle(Bundle extras) {
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String key : extras.keySet()) {
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Object value = extras.get(key);
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value == null) continue;
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value instanceof Long) continue;
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value instanceof Integer) continue;
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value instanceof Boolean) continue;
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value instanceof Float) continue;
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value instanceof Double) continue;
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value instanceof String) continue;
1875d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana                if (value instanceof Account) continue;
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("unexpected value type: "
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + value.getClass().getName());
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IllegalArgumentException e) {
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException exc) {
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("error unparceling Bundle", exc);
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1886ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
1887ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Cancel any active or pending syncs that match the Uri. If the uri is null then
1888ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * all syncs will be canceled.
1889ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     *
1890ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param uri the uri of the provider to sync or null to sync all providers.
1891ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @deprecated instead use {@link #cancelSync(android.accounts.Account, String)}
1892ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
18934a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void cancelSync(Uri uri) {
1895ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        cancelSync(null /* all accounts */, uri != null ? uri.getAuthority() : null);
1896ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
1897ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1898ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
1899ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Cancel any active or pending syncs that match account and authority. The account and
1900ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * authority can each independently be set to null, which means that syncs with any account
1901ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * or authority, respectively, will match.
1902ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     *
1903ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account filters the syncs that match by this account
1904ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority filters the syncs that match by this authority
1905ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
1906ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static void cancelSync(Account account, String authority) {
1907ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
190856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            getContentService().cancelSync(account, authority, null);
1909ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
1910ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
1911ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
1912ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1913ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
19140363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #cancelSync(Account, String)
19150363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
19160363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
19170363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static void cancelSyncAsUser(Account account, String authority, int userId) {
19180363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
19190363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            getContentService().cancelSyncAsUser(account, authority, null, userId);
19200363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch (RemoteException e) {
19210363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
19220363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
19230363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
19240363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
1925ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Get information about the SyncAdapters that are known to the system.
1926ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return an array of SyncAdapters that have registered with the system
1927ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
1928ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static SyncAdapterType[] getSyncAdapterTypes() {
1929ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
1930ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return getContentService().getSyncAdapterTypes();
1931ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
1932ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
1933ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
1934ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
1935ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1936ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
19370363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #getSyncAdapterTypes()
19380363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
19390363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
19400363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) {
19410363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
19420363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            return getContentService().getSyncAdapterTypesAsUser(userId);
19430363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch (RemoteException e) {
19440363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            throw new RuntimeException("the ContentService should always be reachable", e);
19450363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
19460363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
19470363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
19480363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
194937a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani     * @hide
195037a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani     * Returns the package names of syncadapters that match a given user and authority.
195137a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani     */
195237a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani    public static String[] getSyncAdapterPackagesForAuthorityAsUser(String authority,
195337a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani            int userId) {
195437a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani        try {
195537a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani            return getContentService().getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
195637a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani        } catch (RemoteException e) {
195737a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani        }
195837a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani        return ArrayUtils.emptyArray(String.class);
195937a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani    }
196037a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani
196137a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani    /**
1962ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Check if the provider should be synced when a network tickle is received
19639530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
19649530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
1965ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     *
1966ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account the account whose setting we are querying
1967ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority the provider whose setting we are querying
1968ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return true if the provider should be synced when a network tickle is received
1969ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
1970ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static boolean getSyncAutomatically(Account account, String authority) {
1971ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
1972ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return getContentService().getSyncAutomatically(account, authority);
1973ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
1974ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
1975ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
1976ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
1977ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1978ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
19790363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #getSyncAutomatically(Account, String)
19800363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
19810363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
19820363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static boolean getSyncAutomaticallyAsUser(Account account, String authority,
19830363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            int userId) {
19840363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
19850363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            return getContentService().getSyncAutomaticallyAsUser(account, authority, userId);
19860363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch (RemoteException e) {
19870363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            throw new RuntimeException("the ContentService should always be reachable", e);
19880363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
19890363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
19900363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
19910363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
1992ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Set whether or not the provider is synced when it receives a network tickle.
19939530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
19949530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
1995ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     *
1996ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account the account whose setting we are querying
1997ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority the provider whose behavior is being controlled
1998ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param sync true if the provider should be synced when tickles are received for it
1999ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
2000ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static void setSyncAutomatically(Account account, String authority, boolean sync) {
200103e1e836976f44ed729fa0a41898d7ce4df34788Alexandra Gherghina        setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.myUserId());
2002cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina    }
2003cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina
2004cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina    /**
2005cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina     * @see #setSyncAutomatically(Account, String, boolean)
2006cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina     * @hide
2007cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina     */
2008cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina    public static void setSyncAutomaticallyAsUser(Account account, String authority, boolean sync,
2009cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina            int userId) {
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2011cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina            getContentService().setSyncAutomaticallyAsUser(account, authority, sync, userId);
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
2013ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            // exception ignored; if this is thrown then it means the runtime is in the midst of
20145e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            // being restarted
20155e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
20165e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
20175e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
20185e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    /**
2019c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * Specifies that a sync should be requested with the specified the account, authority,
2020c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * and extras at the given frequency. If there is already another periodic sync scheduled
2021c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * with the account, authority and extras then a new periodic sync won't be added, instead
2022c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * the frequency of the previous one will be updated.
2023c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * <p>
2024c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * These periodic syncs honor the "syncAutomatically" and "masterSyncAutomatically" settings.
2025c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * Although these sync are scheduled at the specified frequency, it may take longer for it to
2026c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * actually be started if other syncs are ahead of it in the sync operation queue. This means
2027c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * that the actual start time may drift.
202853bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * <p>
202953bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * Periodic syncs are not allowed to have any of {@link #SYNC_EXTRAS_DO_NOT_RETRY},
203053bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * {@link #SYNC_EXTRAS_IGNORE_BACKOFF}, {@link #SYNC_EXTRAS_IGNORE_SETTINGS},
203153bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE},
203253bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL} set to true.
203353bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * If any are supplied then an {@link IllegalArgumentException} will be thrown.
2034c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     *
20359530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
20369530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
203756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * <p>The bundle for a periodic sync can be queried by applications with the correct
203856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * permissions using
203956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * {@link ContentResolver#getPeriodicSyncs(Account account, String provider)}, so no
204056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * sensitive data should be transferred here.
20419530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     *
2042c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param account the account to specify in the sync
2043c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param authority the provider to specify in the sync request
2044c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param extras extra parameters to go along with the sync request
2045c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param pollFrequency how frequently the sync should be performed, in seconds.
204653bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters
204753bd2522ca7767f46646606123b6e2689b811850Fred Quintana     * are null.
2048c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
2049c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public static void addPeriodicSync(Account account, String authority, Bundle extras,
2050c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            long pollFrequency) {
2051c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        validateSyncExtrasBundle(extras);
205253bd2522ca7767f46646606123b6e2689b811850Fred Quintana        if (extras.getBoolean(SYNC_EXTRAS_MANUAL, false)
205353bd2522ca7767f46646606123b6e2689b811850Fred Quintana                || extras.getBoolean(SYNC_EXTRAS_DO_NOT_RETRY, false)
205453bd2522ca7767f46646606123b6e2689b811850Fred Quintana                || extras.getBoolean(SYNC_EXTRAS_IGNORE_BACKOFF, false)
205553bd2522ca7767f46646606123b6e2689b811850Fred Quintana                || extras.getBoolean(SYNC_EXTRAS_IGNORE_SETTINGS, false)
205653bd2522ca7767f46646606123b6e2689b811850Fred Quintana                || extras.getBoolean(SYNC_EXTRAS_INITIALIZE, false)
205753bd2522ca7767f46646606123b6e2689b811850Fred Quintana                || extras.getBoolean(SYNC_EXTRAS_FORCE, false)
205853bd2522ca7767f46646606123b6e2689b811850Fred Quintana                || extras.getBoolean(SYNC_EXTRAS_EXPEDITED, false)) {
205953bd2522ca7767f46646606123b6e2689b811850Fred Quintana            throw new IllegalArgumentException("illegal extras were set");
206053bd2522ca7767f46646606123b6e2689b811850Fred Quintana        }
2061c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
2062fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams             getContentService().addPeriodicSync(account, authority, extras, pollFrequency);
2063c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (RemoteException e) {
2064c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            // exception ignored; if this is thrown then it means the runtime is in the midst of
2065c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            // being restarted
2066c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
2067c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
2068c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
2069c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
207056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * {@hide}
207156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Helper function to throw an <code>IllegalArgumentException</code> if any illegal
207256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * extras were set for a periodic sync.
207356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     *
207456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * @param extras bundle to validate.
207556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     */
207656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static boolean invalidPeriodicExtras(Bundle extras) {
207756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)
207856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
207956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)
208056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
208156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)
208256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)
208356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
208456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return true;
208556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
208656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        return false;
208756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
208856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
208956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
2090c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * Remove a periodic sync. Has no affect if account, authority and extras don't match
2091c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * an existing periodic sync.
20929530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
20939530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
2094c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     *
2095c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param account the account of the periodic sync to remove
2096c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param authority the provider of the periodic sync to remove
2097c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param extras the extras of the periodic sync to remove
2098c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
2099c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public static void removePeriodicSync(Account account, String authority, Bundle extras) {
2100c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        validateSyncExtrasBundle(extras);
2101c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
2102c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            getContentService().removePeriodicSync(account, authority, extras);
2103c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (RemoteException e) {
2104c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
2105c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
2106c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
2107c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
2108c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
210956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Remove the specified sync. This will cancel any pending or active syncs. If the request is
211056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * for a periodic sync, this call will remove any future occurrences.
21115a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams     * <p>
21125a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams     *     If a periodic sync is specified, the caller must hold the permission
21135a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams     *     {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
21145a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams     *</p>
21155a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams     * It is possible to cancel a sync using a SyncRequest object that is not the same object
211656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * with which you requested the sync. Do so by building a SyncRequest with the same
21175a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams     * adapter, frequency, <b>and</b> extras bundle.
2118fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     *
2119fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * @param request SyncRequest object containing information about sync to cancel.
2120fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
2121fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public static void cancelSync(SyncRequest request) {
212256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (request == null) {
212356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            throw new IllegalArgumentException("request cannot be null");
212456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
212556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        try {
212656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            getContentService().cancelRequest(request);
212756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } catch (RemoteException e) {
212856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // exception ignored; if this is thrown then it means the runtime is in the midst of
212956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // being restarted
213056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
2131fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
2132fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
2133fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
2134c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * Get the list of information about the periodic syncs for the given account and authority.
21359530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
21369530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
2137c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     *
2138c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param account the account whose periodic syncs we are querying
2139c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @param authority the provider whose periodic syncs we are querying
2140c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @return a list of PeriodicSync objects. This list may be empty but will never be null.
2141c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
2142c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public static List<PeriodicSync> getPeriodicSyncs(Account account, String authority) {
2143c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
214456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return getContentService().getPeriodicSyncs(account, authority, null);
214556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } catch (RemoteException e) {
214656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            throw new RuntimeException("the ContentService should always be reachable", e);
214756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
214856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
214956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
215056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
21515e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana     * Check if this account/provider is syncable.
21529530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
21539530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
21545e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana     * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
21555e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana     */
215620ea6ce0e8a758cc5c33eb2577495bf9f4dce16eJim Miller    public static int getIsSyncable(Account account, String authority) {
21575e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        try {
21585e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            return getContentService().getIsSyncable(account, authority);
21595e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        } catch (RemoteException e) {
21605e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
21615e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
21625e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
21635e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
21645e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    /**
21650363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #getIsSyncable(Account, String)
21660363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
21670363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
21680363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static int getIsSyncableAsUser(Account account, String authority, int userId) {
21690363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
21700363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            return getContentService().getIsSyncableAsUser(account, authority, userId);
21710363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch (RemoteException e) {
21720363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            throw new RuntimeException("the ContentService should always be reachable", e);
21730363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
21740363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
21750363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
21760363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
21775e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana     * Set whether this account/provider is syncable.
21789530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
21799530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
2180718671b441c6318276e6d954a41a95db0d7e6c49Fred Quintana     * @param syncable >0 denotes syncable, 0 means not syncable, <0 means unknown
21815e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana     */
218220ea6ce0e8a758cc5c33eb2577495bf9f4dce16eJim Miller    public static void setIsSyncable(Account account, String authority, int syncable) {
21835e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        try {
21845e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            getContentService().setIsSyncable(account, authority, syncable);
21855e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        } catch (RemoteException e) {
21865e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            // exception ignored; if this is thrown then it means the runtime is in the midst of
2187ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            // being restarted
21889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2191ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
2192ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Gets the master auto-sync setting that applies to all the providers and accounts.
2193ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * If this is false then the per-provider auto-sync setting is ignored.
21949530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
21959530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
2196ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     *
2197ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return the master auto-sync setting that applies to all the providers and accounts
2198ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
2199ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static boolean getMasterSyncAutomatically() {
2200ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
2201ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return getContentService().getMasterSyncAutomatically();
2202ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
2203ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
2204ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
2205ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
2206ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
2207ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
22080363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #getMasterSyncAutomatically()
22090363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
22100363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
22110363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static boolean getMasterSyncAutomaticallyAsUser(int userId) {
22120363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
22130363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            return getContentService().getMasterSyncAutomaticallyAsUser(userId);
22140363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch (RemoteException e) {
22150363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            throw new RuntimeException("the ContentService should always be reachable", e);
22160363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
22170363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
22180363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
22190363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
2220ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Sets the master auto-sync setting that applies to all the providers and accounts.
2221ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * If this is false then the per-provider auto-sync setting is ignored.
22229530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
22239530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
2224ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     *
2225ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param sync the master auto-sync setting that applies to all the providers and accounts
2226ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
2227ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static void setMasterSyncAutomatically(boolean sync) {
222803e1e836976f44ed729fa0a41898d7ce4df34788Alexandra Gherghina        setMasterSyncAutomaticallyAsUser(sync, UserHandle.myUserId());
22290e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina    }
22300e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina
22310e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina    /**
22320e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina     * @see #setMasterSyncAutomatically(boolean)
22330e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina     * @hide
22340e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina     */
22350e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina    public static void setMasterSyncAutomaticallyAsUser(boolean sync, int userId) {
2236ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
22370e9ac20d7e0c9aca8cd342d97465adfac4c7e6e1Alexandra Gherghina            getContentService().setMasterSyncAutomaticallyAsUser(sync, userId);
2238ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
2239ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            // exception ignored; if this is thrown then it means the runtime is in the midst of
2240ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            // being restarted
2241ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
2242ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
2243ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
2244ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
224556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Returns true if there is currently a sync operation for the given account or authority
224656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * actively being processed.
22479530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
22489530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_STATS}.
2249ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account the account whose setting we are querying
2250ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority the provider whose behavior is being queried
2251ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return true if a sync is active for the given account or authority.
2252ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
2253ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static boolean isSyncActive(Account account, String authority) {
225456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (account == null) {
225556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            throw new IllegalArgumentException("account must not be null");
225656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
225756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (authority == null) {
225856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            throw new IllegalArgumentException("authority must not be null");
225956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
226056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
2261ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
226256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return getContentService().isSyncActive(account, authority, null);
226356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } catch (RemoteException e) {
226456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            throw new RuntimeException("the ContentService should always be reachable", e);
226556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
226656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
226756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
2268ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
2269c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * If a sync is active returns the information about it, otherwise returns null.
2270c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * <p>
22719530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * This method requires the caller to hold the permission
22729530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_STATS}.
22739530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>
2274d5e4fdc8a4743abc0d9fe3cb952a78f9ad078c6bFred Quintana     * @return the SyncInfo for the currently active sync or null if one is not active.
2275c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * @deprecated
2276c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * Since multiple concurrent syncs are now supported you should use
2277c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * {@link #getCurrentSyncs()} to get the accurate list of current syncs.
2278c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * This method returns the first item from the list of current syncs
2279c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * or null if there are none.
2280ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
2281c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana    @Deprecated
2282d5e4fdc8a4743abc0d9fe3cb952a78f9ad078c6bFred Quintana    public static SyncInfo getCurrentSync() {
2283ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
2284c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana            final List<SyncInfo> syncs = getContentService().getCurrentSyncs();
2285c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana            if (syncs.isEmpty()) {
2286c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana                return null;
2287c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana            }
2288c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana            return syncs.get(0);
2289c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana        } catch (RemoteException e) {
2290c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
2291c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana        }
2292c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana    }
2293c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana
2294c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana    /**
2295c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * Returns a list with information about all the active syncs. This list will be empty
2296c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * if there are no active syncs.
22979530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>
22989530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * This method requires the caller to hold the permission
22999530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_STATS}.
23009530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>
2301c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     * @return a List of SyncInfo objects for the currently active syncs.
2302c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana     */
2303c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana    public static List<SyncInfo> getCurrentSyncs() {
2304c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana        try {
2305c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana            return getContentService().getCurrentSyncs();
2306ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
2307ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
2308ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
2309ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
2310ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
2311ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
23120363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #getCurrentSyncs()
23130363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
23140363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
23150363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static List<SyncInfo> getCurrentSyncsAsUser(int userId) {
23160363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
23170363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            return getContentService().getCurrentSyncsAsUser(userId);
23180363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch (RemoteException e) {
23190363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            throw new RuntimeException("the ContentService should always be reachable", e);
23200363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
23210363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
23220363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
23230363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
23244a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana     * Returns the status that matches the authority.
2325ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account the account whose setting we are querying
2326ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority the provider whose behavior is being queried
2327ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return the SyncStatusInfo for the authority, or null if none exists
2328ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @hide
2329ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
2330ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static SyncStatusInfo getSyncStatus(Account account, String authority) {
2331ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
233256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return getContentService().getSyncStatus(account, authority, null);
2333ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
2334ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
2335ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
2336ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
2337ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
2338ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
23390363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @see #getSyncStatus(Account, String)
23400363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     * @hide
23410363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina     */
23420363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
23430363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            int userId) {
23440363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        try {
23450363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            return getContentService().getSyncStatusAsUser(account, authority, null, userId);
23460363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        } catch (RemoteException e) {
23470363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina            throw new RuntimeException("the ContentService should always be reachable", e);
23480363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina        }
23490363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    }
23500363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina
23510363c3eb089afd4474bfd6ae6ee8a500d6e97614Alexandra Gherghina    /**
2352ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Return true if the pending status is true of any matching authorities.
23539530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
23549530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#READ_SYNC_STATS}.
2355ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account the account whose setting we are querying
2356ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority the provider whose behavior is being queried
2357ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return true if there is a pending sync with the matching account and authority
2358ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
2359ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static boolean isSyncPending(Account account, String authority) {
236003e1e836976f44ed729fa0a41898d7ce4df34788Alexandra Gherghina        return isSyncPendingAsUser(account, authority, UserHandle.myUserId());
2361cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina    }
2362cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina
2363cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina    /**
2364cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina     * @see #requestSync(Account, String, Bundle)
2365cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina     * @hide
2366cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina     */
2367cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina    public static boolean isSyncPendingAsUser(Account account, String authority, int userId) {
2368ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
2369cb22807ffcf79db1b62162842d0a90251a463ea7Alexandra Gherghina            return getContentService().isSyncPendingAsUser(account, authority, null, userId);
237056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } catch (RemoteException e) {
237156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            throw new RuntimeException("the ContentService should always be reachable", e);
237256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
237356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
237456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
23751b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana    /**
23761b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * Request notifications when the different aspects of the SyncManager change. The
23771b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * different items that can be requested are:
23781b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * <ul>
23791b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * <li> {@link #SYNC_OBSERVER_TYPE_PENDING}
23801b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * <li> {@link #SYNC_OBSERVER_TYPE_ACTIVE}
23811b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * <li> {@link #SYNC_OBSERVER_TYPE_SETTINGS}
23821b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * </ul>
23831b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * The caller can set one or more of the status types in the mask for any
23841b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * given listener registration.
23851b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * @param mask the status change types that will cause the callback to be invoked
23861b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * @param callback observer to be invoked when the status changes
23871b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * @return a handle that can be used to remove the listener at a later time
23881b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     */
2389ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static Object addStatusChangeListener(int mask, final SyncStatusObserver callback) {
23901b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana        if (callback == null) {
23911b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana            throw new IllegalArgumentException("you passed in a null callback");
23921b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana        }
2393ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
2394ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
2395ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                public void onStatusChanged(int which) throws RemoteException {
2396ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    callback.onStatusChanged(which);
2397ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                }
2398ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            };
2399ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            getContentService().addStatusChangeListener(mask, observer);
2400ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return observer;
2401ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
2402ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            throw new RuntimeException("the ContentService should always be reachable", e);
2403ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
2404ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
2405ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
24061b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana    /**
24071b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * Remove a previously registered status change listener.
24081b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     * @param handle the handle that was returned by {@link #addStatusChangeListener}
24091b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana     */
2410ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public static void removeStatusChangeListener(Object handle) {
24111b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana        if (handle == null) {
24121b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana            throw new IllegalArgumentException("you passed in a null handle");
24131b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana        }
2414ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
2415ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle);
2416ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } catch (RemoteException e) {
2417ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            // exception ignored; if this is thrown then it means the runtime is in the midst of
2418ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            // being restarted
2419ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
2420ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
2421ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
2422a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    /**
2423a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick     * Returns sampling percentage for a given duration.
2424a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick     *
2425a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick     * Always returns at least 1%.
2426a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick     */
2427a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    private int samplePercentForDuration(long durationMillis) {
2428a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        if (durationMillis >= SLOW_THRESHOLD_MILLIS) {
2429a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            return 100;
2430a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        }
2431a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
2432a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    }
2433a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick
2434a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    private void maybeLogQueryToEventLog(long durationMillis,
2435a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                                         Uri uri, String[] projection,
2436a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                                         String selection, String sortOrder) {
24372b4d22cda3c44f5d731c15306b85045417071408Jeff Sharkey        if (!ENABLE_CONTENT_SAMPLE) return;
2438a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        int samplePercent = samplePercentForDuration(durationMillis);
2439a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        if (samplePercent < 100) {
2440a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            synchronized (mRandom) {
2441a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                if (mRandom.nextInt(100) >= samplePercent) {
2442a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                    return;
2443a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                }
2444a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            }
2445a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        }
2446a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick
2447a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        StringBuilder projectionBuffer = new StringBuilder(100);
2448a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        if (projection != null) {
2449a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            for (int i = 0; i < projection.length; ++i) {
2450a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                // Note: not using a comma delimiter here, as the
2451a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                // multiple arguments to EventLog.writeEvent later
2452a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                // stringify with a comma delimiter, which would make
2453a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                // parsing uglier later.
2454a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                if (i != 0) projectionBuffer.append('/');
2455a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                projectionBuffer.append(projection[i]);
2456a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            }
2457a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        }
2458a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick
2459a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        // ActivityThread.currentPackageName() only returns non-null if the
2460a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        // current thread is an application main thread.  This parameter tells
2461a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        // us whether an event loop is blocked, and if so, which app it is.
246201e4cfc47d0a2c7e7ab383d2fb23224ec52c0301Dianne Hackborn        String blockingPackage = AppGlobals.getInitialPackage();
2463a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick
2464a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        EventLog.writeEvent(
2465a8fbedbf5e274581ba0cbb20da34ade286fc1cfcBrad Fitzpatrick            EventLogTags.CONTENT_QUERY_SAMPLE,
2466a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            uri.toString(),
2467a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            projectionBuffer.toString(),
2468a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            selection != null ? selection : "",
2469a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            sortOrder != null ? sortOrder : "",
2470a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            durationMillis,
2471a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            blockingPackage != null ? blockingPackage : "",
2472a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            samplePercent);
2473a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    }
2474a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick
2475a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    private void maybeLogUpdateToEventLog(
2476a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        long durationMillis, Uri uri, String operation, String selection) {
24772b4d22cda3c44f5d731c15306b85045417071408Jeff Sharkey        if (!ENABLE_CONTENT_SAMPLE) return;
2478a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        int samplePercent = samplePercentForDuration(durationMillis);
2479a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        if (samplePercent < 100) {
2480a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            synchronized (mRandom) {
2481a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                if (mRandom.nextInt(100) >= samplePercent) {
2482a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                    return;
2483a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick                }
2484a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            }
2485a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        }
248601e4cfc47d0a2c7e7ab383d2fb23224ec52c0301Dianne Hackborn        String blockingPackage = AppGlobals.getInitialPackage();
2487a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick        EventLog.writeEvent(
2488a8fbedbf5e274581ba0cbb20da34ade286fc1cfcBrad Fitzpatrick            EventLogTags.CONTENT_UPDATE_SAMPLE,
2489a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            uri.toString(),
2490a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            operation,
2491a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            selection != null ? selection : "",
2492a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            durationMillis,
2493a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            blockingPackage != null ? blockingPackage : "",
2494a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick            samplePercent);
2495a63730d1f103f78589faef461d2af7351fc49f42Brad Fitzpatrick    }
2496ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
2497825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown    private final class CursorWrapperInner extends CrossProcessCursorWrapper {
249803f0292744094ec107ffce71301c394503a31dedGilles Debunne        private final IContentProvider mContentProvider;
24999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final String TAG="CursorWrapperInner";
2500baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown
2501baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown        private final CloseGuard mCloseGuard = CloseGuard.get();
2502baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown        private boolean mProviderReleased;
25039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CursorWrapperInner(Cursor cursor, IContentProvider icp) {
25059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(cursor);
25069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContentProvider = icp;
2507baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown            mCloseGuard.open("close");
25089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
25119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void close() {
25129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.close();
25139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver.this.releaseProvider(mContentProvider);
2514baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown            mProviderReleased = true;
2515baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown
2516baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown            if (mCloseGuard != null) {
2517baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                mCloseGuard.close();
2518baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown            }
25199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
25229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void finalize() throws Throwable {
25239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2524baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                if (mCloseGuard != null) {
2525baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                    mCloseGuard.warnIfOpen();
2526baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                }
2527baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown
2528baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                if (!mProviderReleased && mContentProvider != null) {
2529baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                    // Even though we are using CloseGuard, log this anyway so that
2530baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                    // application developers always see the message in the log.
2531872a52c6b637faf75262b83fe68ff4e0d9fe044cJohannes Carlsson                    Log.w(TAG, "Cursor finalized without prior close()");
2532baaf8c3f55d9d95b9d2cd9279e2ce1725da0dc52Jeff Brown                    ContentResolver.this.releaseProvider(mContentProvider);
25339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
25349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
25359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                super.finalize();
25369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class ParcelFileDescriptorInner extends ParcelFileDescriptor {
254103f0292744094ec107ffce71301c394503a31dedGilles Debunne        private final IContentProvider mContentProvider;
2542da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey        private boolean mProviderReleased;
25439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) {
25459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(pfd);
25469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContentProvider = icp;
25479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2550487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani        public void releaseResources() {
2551da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey            if (!mProviderReleased) {
25526ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                ContentResolver.this.releaseProvider(mContentProvider);
2553da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey                mProviderReleased = true;
25549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** @hide */
2559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String CONTENT_SERVICE_NAME = "content";
25600ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill
2561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** @hide */
2562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static IContentService getContentService() {
2563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (sContentService != null) {
2564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return sContentService;
2565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME);
256743a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false) Log.v("ContentService", "default service binder = " + b);
2568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        sContentService = IContentService.Stub.asInterface(b);
256943a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false) Log.v("ContentService", "default service = " + sContentService);
2570231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return sContentService;
2571231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
25720ba1cb06c6a0332b76c469bd54dcf6f98128ac82Tom O'Neill
257335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    /** @hide */
257435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public String getPackageName() {
257535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return mPackageName;
257635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
257735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
2578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static IContentService sContentService;
25799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
258035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final String mPackageName;
25819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "ContentResolver";
2582d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot
2583d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    /** @hide */
2584d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    public int resolveUserId(Uri uri) {
2585d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        return ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
2586d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    }
25879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2588