ContentProvider.java revision 18cb28756caf02bf2b2f5e67c68451edaf719b47
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
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
202af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackbornimport android.content.pm.PathPermission;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ProviderInfo;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetFileDescriptor;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Configuration;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.SQLException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
2723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport android.os.AsyncTask;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
291877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrickimport android.os.Bundle;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackbornimport android.os.Process;
320c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Noriimport android.util.Log;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
3518cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissenimport java.io.FileDescriptor;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
3723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport java.io.IOException;
3818cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissenimport java.io.PrintWriter;
3903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintanaimport java.util.ArrayList;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Content providers are one of the primary building blocks of Android applications, providing
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * content to applications. They encapsulate data and provide it to applications through the single
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ContentResolver} interface. A content provider is only required if you need to share
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data between multiple applications. For example, the contacts data is used by multiple
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * applications and must be stored in a content provider. If you don't need to share data amongst
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple applications you can use a database directly via
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.database.sqlite.SQLiteDatabase}.
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When a request is made via
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link ContentResolver} the system inspects the authority of the given URI and passes the
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request to the content provider registered with the authority. The content provider can interpret
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * URIs.</p>
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The primary methods that need to be implemented are:
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
586fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor *   <li>{@link #onCreate} which is called to initialize the provider</li>
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #query} which returns data to the caller</li>
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #insert} which inserts new data into the content provider</li>
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #update} which updates existing data in the content provider</li>
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #delete} which deletes data from the content provider</li>
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #getType} which returns the MIME type of data in the content provider</li>
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul></p>
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
666fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p class="caution">Data access methods (such as {@link #insert} and
676fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link #update}) may be called from many threads at once, and must be thread-safe.
686fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Other methods (such as {@link #onCreate}) are only called from the application
696fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * main thread, and must avoid performing lengthy operations.  See the method
706fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * descriptions for their expected thread behavior.</p>
716fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor *
726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate
736fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * ContentProvider instance, so subclasses don't have to worry about the details of
746fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * cross-process calls.</p>
75558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez *
76558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <div class="special reference">
77558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <h3>Developer Guides</h3>
78558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <p>For more information about using content providers, read the
79558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
80558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * developer guide.</p>
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
82c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackbornpublic abstract class ContentProvider implements ComponentCallbacks2 {
830c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    private static final String TAG = "ContentProvider";
840c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori
858280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    /*
868280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * Note: if you add methods to ContentProvider, you must add similar methods to
878280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     *       MockContentProvider.
888280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     */
898280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext = null;
912af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    private int mMyUid;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mReadPermission;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mWritePermission;
942af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    private PathPermission[] mPathPermissions;
95b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn    private boolean mExported;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Transport mTransport = new Transport();
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
996fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor    /**
1006fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Construct a ContentProvider instance.  Content providers must be
1016fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared
1026fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * in the manifest</a>, accessed with {@link ContentResolver}, and created
1036fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * automatically by the system, so applications usually do not create
1046fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * ContentProvider instances directly.
1056fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
1066fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>At construction time, the object is uninitialized, and most fields and
1076fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * methods are unavailable.  Subclasses should initialize themselves in
1086fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link #onCreate}, not the constructor.
1096fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
1106fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>Content providers are created on the application main thread at
1116fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * application launch time.  The constructor must not perform lengthy
1126fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * operations, or application startup will be delayed.
1136fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
1148280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    public ContentProvider() {
1158280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    }
1168280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa
1178280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    /**
1188280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * Constructor just for mocking.
1198280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     *
1208280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param context A Context object which should be some mock instance (like the
1218280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * instance of {@link android.test.mock.MockContext}).
1228280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param readPermission The read permision you want this instance should have in the
1238280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * test, which is available via {@link #getReadPermission()}.
1248280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param writePermission The write permission you want this instance should have
1258280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * in the test, which is available via {@link #getWritePermission()}.
1268280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param pathPermissions The PathPermissions you want this instance should have
1278280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * in the test, which is available via {@link #getPathPermissions()}.
1288280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @hide
1298280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     */
1308280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    public ContentProvider(
1318280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            Context context,
1328280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            String readPermission,
1338280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            String writePermission,
1348280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            PathPermission[] pathPermissions) {
1358280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mContext = context;
1368280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mReadPermission = readPermission;
1378280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mWritePermission = writePermission;
1388280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mPathPermissions = pathPermissions;
1398280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    }
1408280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Given an IContentProvider, try to coerce it back to the real
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ContentProvider object if it is running in the local process.  This can
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be used if you know you are running in the same process as a provider,
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and want to get direct access to its implementation details.  Most
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clients should not nor have a reason to use it.
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param abstractInterface The ContentProvider interface that is to be
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *              coerced.
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return If the IContentProvider is non-null and local, returns its actual
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ContentProvider instance.  Otherwise returns null.
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ContentProvider coerceToLocalContentProvider(
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IContentProvider abstractInterface) {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (abstractInterface instanceof Transport) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ((Transport)abstractInterface).getContentProvider();
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Binder object that deals with remoting.
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class Transport extends ContentProviderNative {
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentProvider getContentProvider() {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
172d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        @Override
173d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        public String getProviderName() {
174d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return getContentProvider().getClass().getName();
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Cursor query(Uri uri, String[] projection,
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String selection, String[] selectionArgs, String sortOrder) {
1792af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceReadPermission(uri);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.query(uri, projection, selection,
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    selectionArgs, sortOrder);
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String getType(Uri uri) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.getType(uri);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Uri insert(Uri uri, ContentValues initialValues) {
1902af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.insert(uri, initialValues);
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int bulkInsert(Uri uri, ContentValues[] initialValues) {
1952af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.bulkInsert(uri, initialValues);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
2008943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                throws OperationApplicationException {
2018943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            for (ContentProviderOperation operation : operations) {
2028943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                if (operation.isReadOperation()) {
203e3f054411b9f025848f68389c4e2c325e76b3826Dianne Hackborn                    enforceReadPermission(operation.getUri());
2048943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                }
2058943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
2068943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                if (operation.isWriteOperation()) {
207e3f054411b9f025848f68389c4e2c325e76b3826Dianne Hackborn                    enforceWritePermission(operation.getUri());
2088943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                }
2098943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            }
2108943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            return ContentProvider.this.applyBatch(operations);
2116a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana        }
2126a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int delete(Uri uri, String selection, String[] selectionArgs) {
2142af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.delete(uri, selection, selectionArgs);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int update(Uri uri, ContentValues values, String selection,
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String[] selectionArgs) {
2202af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.update(uri, values, selection, selectionArgs);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ParcelFileDescriptor openFile(Uri uri, String mode)
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throws FileNotFoundException {
2262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
2272af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            else enforceReadPermission(uri);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.openFile(uri, mode);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public AssetFileDescriptor openAssetFile(Uri uri, String mode)
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throws FileNotFoundException {
2332af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
2342af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            else enforceReadPermission(uri);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.openAssetFile(uri, mode);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
238534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick        public Bundle call(String method, String arg, Bundle extras) {
239534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick            return ContentProvider.this.call(method, arg, extras);
2401877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick        }
2411877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick
24223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        @Override
24323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
24423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
24523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
24623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
24723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        @Override
24823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeType, Bundle opts)
24923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                throws FileNotFoundException {
25023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            enforceReadPermission(uri);
25123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return ContentProvider.this.openTypedAssetFile(uri, mimeType, opts);
25223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
25323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
2542af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        private void enforceReadPermission(Uri uri) {
2552af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final int uid = Binder.getCallingUid();
2562af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (uid == mMyUid) {
2572af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return;
2582af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
2592af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
2602af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final Context context = getContext();
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String rperm = getReadPermission();
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int pid = Binder.getCallingPid();
263b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn            if (mExported && (rperm == null
2642af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    || context.checkPermission(rperm, pid, uid)
265b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn                    == PackageManager.PERMISSION_GRANTED)) {
2662af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return;
2672af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
2682af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
2692af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            PathPermission[] pps = getPathPermissions();
2702af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (pps != null) {
2712af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                final String path = uri.getPath();
2722af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                int i = pps.length;
2732af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                while (i > 0) {
2742af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    i--;
2752af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final PathPermission pp = pps[i];
2762af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final String pprperm = pp.getReadPermission();
2772af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    if (pprperm != null && pp.match(path)) {
2782af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        if (context.checkPermission(pprperm, pid, uid)
2792af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                                == PackageManager.PERMISSION_GRANTED) {
2802af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                            return;
2812af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        }
2822af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    }
2832af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                }
2842af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
2852af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
2862af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (context.checkUriPermission(uri, pid, uid,
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Intent.FLAG_GRANT_READ_URI_PERMISSION)
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    == PackageManager.PERMISSION_GRANTED) {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2912af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String msg = "Permission Denial: reading "
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ContentProvider.this.getClass().getName()
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid()
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " requires " + rperm;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(msg);
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3002af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        private boolean hasWritePermission(Uri uri) {
3012af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final int uid = Binder.getCallingUid();
3022af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (uid == mMyUid) {
3032af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return true;
3042af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3052af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3062af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final Context context = getContext();
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String wperm = getWritePermission();
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int pid = Binder.getCallingPid();
309b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn            if (mExported && (wperm == null
3102af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    || context.checkPermission(wperm, pid, uid)
311b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn                    == PackageManager.PERMISSION_GRANTED)) {
3122af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return true;
3132af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3142af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3152af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            PathPermission[] pps = getPathPermissions();
3162af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (pps != null) {
3172af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                final String path = uri.getPath();
3182af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                int i = pps.length;
3192af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                while (i > 0) {
3202af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    i--;
3212af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final PathPermission pp = pps[i];
3222af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final String ppwperm = pp.getWritePermission();
3232af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    if (ppwperm != null && pp.match(path)) {
3242af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        if (context.checkPermission(ppwperm, pid, uid)
3252af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                                == PackageManager.PERMISSION_GRANTED) {
3262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                            return true;
3272af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        }
3282af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    }
3292af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                }
3302af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3322af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (context.checkUriPermission(uri, pid, uid,
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    == PackageManager.PERMISSION_GRANTED) {
3352af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return true;
3362af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3372af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3382af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            return false;
3392af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        }
3402af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3412af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        private void enforceWritePermission(Uri uri) {
3422af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (hasWritePermission(uri)) {
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3452af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String msg = "Permission Denial: writing "
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ContentProvider.this.getClass().getName()
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid()
3502af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    + " requires " + getWritePermission();
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(msg);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3576fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Retrieves the Context this provider is running in.  Only available once
3586fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link #onCreate} has been called -- this will return null in the
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constructor.
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Context getContext() {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Change the permission required to read data from the content
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * provider.  This is normally set for you from its manifest information
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is first created.
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param permission Name of the permission required for read-only access.
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final void setReadPermission(String permission) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mReadPermission = permission;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the name of the permission required for read-only access to
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this content provider.  This method can be called from multiple
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * threads, as described in
3807aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
3817aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final String getReadPermission() {
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mReadPermission;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Change the permission required to read and write data in the content
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * provider.  This is normally set for you from its manifest information
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is first created.
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param permission Name of the permission required for read/write access.
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final void setWritePermission(String permission) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWritePermission = permission;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the name of the permission required for read/write access to
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this content provider.  This method can be called from multiple
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * threads, as described in
4027aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
4037aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final String getWritePermission() {
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWritePermission;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4102af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * Change the path-based permission required to read and/or write data in
4112af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * the content provider.  This is normally set for you from its manifest
4122af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * information when the provider is first created.
4132af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     *
4142af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * @param permissions Array of path permission descriptions.
4152af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     */
4162af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    protected final void setPathPermissions(PathPermission[] permissions) {
4172af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        mPathPermissions = permissions;
4182af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    }
4192af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
4202af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    /**
4212af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * Return the path-based permissions required for read and/or write access to
4222af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * this content provider.  This method can be called from multiple
4232af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * threads, as described in
4247aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
4257aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
4262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     */
4272af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    public final PathPermission[] getPathPermissions() {
4282af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        return mPathPermissions;
4292af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    }
4302af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
4312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    /**
4326fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to initialize your content provider on startup.
4336fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method is called for all registered content providers on the
4346fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * application main thread at application launch time.  It must not perform
4356fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * lengthy operations, or application startup will be delayed.
4366fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
4376fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>You should defer nontrivial initialization (such as opening,
4386fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * upgrading, and scanning databases) until the content provider is used
4396fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * (via {@link #query}, {@link #insert}, etc).  Deferred initialization
4406fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * keeps application startup fast, avoids unnecessary work if the provider
4416fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * turns out not to be needed, and stops database errors (such as a full
4426fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * disk) from halting application launch.
4436fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
44417876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper}
4456fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * is a helpful utility class that makes it easy to manage databases,
4466fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * and will automatically defer opening until first use.  If you do use
4476fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * SQLiteOpenHelper, make sure to avoid calling
4486fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or
4496fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase}
4506fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * from this method.  (Instead, override
4516fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the
4526fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * database when it is first opened.)
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the provider was successfully loaded, false otherwise
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract boolean onCreate();
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4586fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor    /**
4596fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@inheritDoc}
4606fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method is always called on the application main thread, and must
4616fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * not perform lengthy operations.
4626fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
4636fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>The default content provider implementation does nothing.
4646fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Override this method to take appropriate action.
4656fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * (Content providers do not usually care about things like screen
4666fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * orientation, but may want to know about locale changes.)
4676fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onConfigurationChanged(Configuration newConfig) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4706fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor
4716fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor    /**
4726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@inheritDoc}
4736fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method is always called on the application main thread, and must
4746fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * not perform lengthy operations.
4756fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
4766fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>The default content provider implementation does nothing.
4776fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Subclasses may override this method to take appropriate action.
4786fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onLowMemory() {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
482c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn    public void onTrimMemory(int level) {
483c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn    }
484c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4866fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle query requests from clients.
4876fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
4887aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
4897aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example client call:<p>
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>// Request a specific record.
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Cursor managedCursor = managedQuery(
49481a476f654155df27aa564a4aebf931eab588e6dAlan Jones                ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                projection,    // Which columns to return.
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                null,          // WHERE clause.
49781a476f654155df27aa564a4aebf931eab588e6dAlan Jones                null,          // WHERE clause value substitution
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                People.NAME + " ASC");   // Sort order.</pre>
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example implementation:<p>
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>// SQLiteQueryBuilder is a helper class that creates the
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // proper SQL syntax for us.
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set the table we're querying.
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        qBuilder.setTables(DATABASE_TABLE_NAME);
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the query ends in a specific record number, we're
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // being asked for a specific record, so set the
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // WHERE clause in our query.
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            qBuilder.appendWhere("_id=" + uri.getPathLeafId());
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Make the query.
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Cursor c = qBuilder.query(mDb,
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                projection,
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                selection,
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                selectionArgs,
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                groupBy,
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                having,
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sortOrder);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.setNotificationUri(getContext().getContentResolver(), uri);
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return c;</pre>
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to query. This will be the full URI sent by the client;
52681a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      if the client is requesting a specific record, the URI will end in a record number
52781a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      that the implementation should parse and add to a WHERE or HAVING clause, specifying
52881a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      that _id value.
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param projection The list of columns to put into the cursor. If
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      null all columns are included.
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selection A selection criteria to apply when filtering rows.
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      If null then all rows are included.
53381a476f654155df27aa564a4aebf931eab588e6dAlan Jones     * @param selectionArgs You may include ?s in selection, which will be replaced by
53481a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      the values from selectionArgs, in order that they appear in the selection.
53581a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      The values will be bound as Strings.
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sortOrder How the rows in the cursor should be sorted.
53781a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      If null then the provider is free to define the sort order.
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a Cursor or null.
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract Cursor query(Uri uri, String[] projection,
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String selection, String[] selectionArgs, String sortOrder);
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5435bba632d877c2878384ff21566c8eb6a1a22f37bFred Quintana    /**
5446fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle requests for the MIME type of the data at the
5456fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * given URI.  The returned MIME type should start with
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>vnd.android.cursor.item</code> for a single record,
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or <code>vnd.android.cursor.dir/</code> for multiple items.
5486fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
5497aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
5507aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
552cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * <p>Note that there are no permissions needed for an application to
553cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * access this information; if your content provider requires read and/or
554cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * write permissions, or is not exported, all applications can still call
555cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * this method regardless of their access permissions.  This allows them
556cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     * to retrieve the MIME type for a URI when dispatching intents.
557cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn     *
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri the URI to query.
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a MIME type string, or null if there is no type.
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract String getType(Uri uri);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5646fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle requests to insert a new row.
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after inserting.
5676fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
5687aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
5697aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The content:// URI of the insertion request.
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values A set of column_name/value pairs to add to the database.
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The URI for the newly inserted item.
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract Uri insert(Uri uri, ContentValues values);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5776fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Override this to handle requests to insert a set of new rows, or the
5786fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * default implementation will iterate over the values and call
5796fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link #insert} on each of them.
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after inserting.
5826fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
5837aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
5847aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The content:// URI of the insertion request.
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values An array of sets of column_name/value pairs to add to the database.
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of values that were inserted.
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int bulkInsert(Uri uri, ContentValues[] values) {
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numValues = values.length;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < numValues; i++) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            insert(uri, values[i]);
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return numValues;
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5996fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle requests to delete one or more rows.
6006fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * The implementation should apply the selection clause when performing
6016fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * deletion, allowing the operation to affect multiple rows in a directory.
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after deleting.
6046fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6057aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
6067aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The implementation is responsible for parsing out a row ID at the end
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the URI, if a specific row is being deleted. That is, the client would
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pass in <code>content://contacts/people/22</code> and the implementation is
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * responsible for parsing the record number (22) when creating a SQL statement.
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The full URI to query, including a row ID (if a specific record is requested).
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selection An optional restriction to apply to rows when deleting.
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of rows affected.
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws SQLException
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract int delete(Uri uri, String selection, String[] selectionArgs);
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
62117876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * Implement this to handle requests to update one or more rows.
6226fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * The implementation should update all rows matching the selection
6236fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * to set the columns according to the provided values map.
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after updating.
6266fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6277aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
6287aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to query. This can potentially have a record ID if this
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is an update request for a specific record.
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values A Bundle mapping from column names to new column values (NULL is a
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               valid value).
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selection An optional filter to match rows to update.
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the number of rows affected.
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract int update(Uri uri, ContentValues values, String selection,
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String[] selectionArgs);
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
64117876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * Override this to handle requests to open a file blob.
6426fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * The default implementation always throws {@link FileNotFoundException}.
6436fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6447aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
6457aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
6466fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
64717876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * <p>This method returns a ParcelFileDescriptor, which is returned directly
64817876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * to the caller.  This way large data (such as images and documents) can be
6496fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * returned without copying the content.
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * their responsibility to close it when done.  That is, the implementation
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of this method should create a new ParcelFileDescriptor for each call.
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI whose file is to be opened.
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode Access mode for the file.  May be "r" for read-only access,
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "rw" for read and write access, or "rwt" for read and write access
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that truncates any existing file.
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new ParcelFileDescriptor which you can use to access
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file.
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException Throws FileNotFoundException if there is
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no file associated with the given URI or the mode is invalid.
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws SecurityException Throws SecurityException if the caller does
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not have permission to access the file.
6676fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openAssetFile(Uri, String)
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openFileHelper(Uri, String)
6706fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ParcelFileDescriptor openFile(Uri uri, String mode)
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new FileNotFoundException("No files supported by provider at "
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + uri);
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6766fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is like {@link #openFile}, but can be implemented by providers
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that need to be able to return sub-sections of files, often assets
6806fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * inside of their .apk.
6816fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6827aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
6837aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
6846fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
6856fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>If you implement this, your clients must be able to deal with such
68617876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * file slices, either directly with
6876fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * methods.
6916fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
6926fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p class="note">If you are implementing this to return a full file, you
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should create the AssetFileDescriptor with
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
6956fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * applications that can not handle sub-sections of files.</p>
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI whose file is to be opened.
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode Access mode for the file.  May be "r" for read-only access,
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "w" for write-only access (erasing whatever data is currently in
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file), "wa" for write-only access to append to any existing data,
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "rw" for read and write access on any existing data, and "rwt" for read
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and write access that truncates any existing file.
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new AssetFileDescriptor which you can use to access
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file.
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException Throws FileNotFoundException if there is
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no file associated with the given URI or the mode is invalid.
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws SecurityException Throws SecurityException if the caller does
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not have permission to access the file.
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openFile(Uri, String)
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openFileHelper(Uri, String)
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AssetFileDescriptor openAssetFile(Uri uri, String mode)
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ParcelFileDescriptor fd = openFile(uri, mode);
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convenience for subclasses that wish to implement {@link #openFile}
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by looking up a column named "_data" at the given URI.
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to be opened.
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode The file mode.  May be "r" for read-only access,
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "w" for write-only access (erasing whatever data is currently in
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file), "wa" for write-only access to append to any existing data,
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "rw" for read and write access on any existing data, and "rwt" for read
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and write access that truncates any existing file.
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new ParcelFileDescriptor that can be used by the
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * client to access the file.
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final ParcelFileDescriptor openFileHelper(Uri uri,
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String mode) throws FileNotFoundException {
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Cursor c = query(uri, new String[]{"_data"}, null, null, null);
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int count = (c != null) ? c.getCount() : 0;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (count != 1) {
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If there is not exactly one result, throw an appropriate
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // exception.
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (c != null) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                c.close();
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (count == 0) {
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("No entry for " + uri);
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("Multiple items at " + uri);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.moveToFirst();
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i = c.getColumnIndex("_data");
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String path = (i >= 0 ? c.getString(i) : null);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.close();
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (path == null) {
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("Column _data not found.");
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int modeBits = ContentResolver.modeToMode(uri, mode);
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ParcelFileDescriptor.open(new File(path), modeBits);
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
76423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Called by a client to determine the types of data streams that this
76523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * content provider supports for the given URI.  The default implementation
76623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * returns null, meaning no types.  If your content provider stores data
76723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * of a particular type, return that MIME type if it matches the given
76823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * mimeTypeFilter.  If it can perform type conversions, return an array
76923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * of all supported MIME types that match mimeTypeFilter.
77023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
77123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param uri The data in the content provider being queried.
77223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeTypeFilter The type of data the client desires.  May be
77323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * a pattern, such as *\/* to retrieve all possible data types.
7743f00be5bd0b46e7937b68909baeff295b86215ccDianne Hackborn     * @return Returns null if there are no possible data streams for the
77523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * given mimeTypeFilter.  Otherwise returns an array of all available
77623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * concrete MIME types.
77723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
77823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #getType(Uri)
77923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #openTypedAssetFile(Uri, String, Bundle)
7801040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn     * @see ClipDescription#compareMimeTypes(String, String)
78123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
78223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
78323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        return null;
78423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
78523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
78623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
78723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Called by a client to open a read-only stream containing data of a
78823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * particular MIME type.  This is like {@link #openAssetFile(Uri, String)},
78923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * except the file can only be read-only and the content provider may
79023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * perform data conversions to generate data of the desired type.
79123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
79223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * <p>The default implementation compares the given mimeType against the
79323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * result of {@link #getType(Uri)} and, if the match, simple calls
79423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * {@link #openAssetFile(Uri, String)}.
79523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
7961040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn     * <p>See {@link ClipData} for examples of the use and implementation
79723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * of this method.
79823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
79923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param uri The data in the content provider being queried.
80023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeTypeFilter The type of data the client desires.  May be
80123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * a pattern, such as *\/*, if the caller does not have specific type
80223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * requirements; in this case the content provider will pick its best
80323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * type matching the pattern.
80423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param opts Additional options from the client.  The definitions of
80523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * these are specific to the content provider being called.
80623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
80723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @return Returns a new AssetFileDescriptor from which the client can
80823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * read data of the desired type.
80923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
81023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @throws FileNotFoundException Throws FileNotFoundException if there is
81123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * no file associated with the given URI or the mode is invalid.
81223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @throws SecurityException Throws SecurityException if the caller does
81323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * not have permission to access the data.
81423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @throws IllegalArgumentException Throws IllegalArgumentException if the
81523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * content provider does not support the requested MIME type.
81623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
81723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #getStreamTypes(Uri, String)
81823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #openAssetFile(Uri, String)
8191040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn     * @see ClipDescription#compareMimeTypes(String, String)
82023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
82123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
82223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            throws FileNotFoundException {
82302dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn        if ("*/*".equals(mimeTypeFilter)) {
82402dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn            // If they can take anything, the untyped open call is good enough.
82502dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn            return openAssetFile(uri, "r");
82602dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn        }
82723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        String baseType = getType(uri);
8281040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn        if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) {
82902dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn            // Use old untyped open call if this provider has a type for this
83002dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn            // URI and it matches the request.
83123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return openAssetFile(uri, "r");
83223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
83323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter);
83423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
83523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
83623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
83723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Interface to write a stream of data to a pipe.  Use with
83823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * {@link ContentProvider#openPipeHelper}.
83923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
84023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public interface PipeDataWriter<T> {
84123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        /**
84223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * Called from a background thread to stream data out to a pipe.
84323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * Note that the pipe is blocking, so this thread can block on
84423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * writes for an arbitrary amount of time if the client is slow
84523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * at reading.
84623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         *
84723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param output The pipe where data should be written.  This will be
84823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * closed for you upon returning from this function.
84923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param uri The URI whose data is to be written.
85023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param mimeType The desired type of data to be written.
85123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param opts Options supplied by caller.
85223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param args Your own custom arguments.
85323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         */
85423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
85523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                Bundle opts, T args);
85623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
85723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
85823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
85923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * A helper function for implementing {@link #openTypedAssetFile}, for
86023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * creating a data pipe and background thread allowing you to stream
86123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * generated data back to the client.  This function returns a new
86223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * ParcelFileDescriptor that should be returned to the caller (the caller
86323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * is responsible for closing it).
86423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
86523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param uri The URI whose data is to be written.
86623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeType The desired type of data to be written.
86723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param opts Options supplied by caller.
86823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param args Your own custom arguments.
86923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param func Interface implementing the function that will actually
87023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * stream the data.
87123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @return Returns a new ParcelFileDescriptor holding the read side of
87223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * the pipe.  This should be returned to the caller for reading; the caller
87323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * is responsible for closing it when done.
87423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
87523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType,
87623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            final Bundle opts, final T args, final PipeDataWriter<T> func)
87723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            throws FileNotFoundException {
87823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        try {
87923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
88023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
88123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
88223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                @Override
88323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                protected Object doInBackground(Object... params) {
88423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    func.writeDataToPipe(fds[1], uri, mimeType, opts, args);
88523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    try {
88623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                        fds[1].close();
88723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    } catch (IOException e) {
88823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                        Log.w(TAG, "Failure closing pipe", e);
88923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    }
89023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    return null;
89123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                }
89223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            };
8935d9d03a0234faa3cffd11502f973057045cafe82Dianne Hackborn            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null);
89423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
89523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return fds[0];
89623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        } catch (IOException e) {
89723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            throw new FileNotFoundException("failure making pipe");
89823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
89923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
90023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
90123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if this instance is a temporary content provider.
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if this instance is a temporary content provider
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean isTemporary() {
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the Binder object for this provider.
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the Binder object for this provider
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public IContentProvider getIContentProvider() {
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTransport;
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * After being instantiated, this is called to tell the content provider
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * about itself.
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context The context this provider is running in
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info Registered information about this content provider
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void attachInfo(Context context, ProviderInfo info) {
92723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        /*
92823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * We may be using AsyncTask from binder threads.  Make it init here
92923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * so its static handler is on the main thread.
93023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         */
93123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        AsyncTask.init();
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Only allow it to be set once, so after the content service gives
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * this to us clients can't change it.
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext == null) {
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext = context;
9392af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            mMyUid = Process.myUid();
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (info != null) {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setReadPermission(info.readPermission);
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setWritePermission(info.writePermission);
9432af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                setPathPermissions(info.pathPermissions);
944b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn                mExported = info.exported;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentProvider.this.onCreate();
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
949ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
950ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
95117876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * Override this to handle requests to perform a batch of operations, or the
95217876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * default implementation will iterate over the operations and call
95317876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * {@link ContentProviderOperation#apply} on each of them.
95417876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * If all calls to {@link ContentProviderOperation#apply} succeed
95517876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * then a {@link ContentProviderResult} array with as many
95617876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * elements as there were operations will be returned.  If any of the calls
9576fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * fail, it is up to the implementation how many of the others take effect.
9586fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
9597aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
9607aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main     * and Threads</a>.
9616fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
962ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param operations the operations to apply
963ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return the results of the applications
9646fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * @throws OperationApplicationException thrown if any operation fails.
9656fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * @see ContentProviderOperation#apply
966ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
96703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
968ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            throws OperationApplicationException {
96903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        final int numOperations = operations.size();
97003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        final ContentProviderResult[] results = new ContentProviderResult[numOperations];
97103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        for (int i = 0; i < numOperations; i++) {
97203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            results[i] = operations.get(i).apply(this, results, i);
973ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
974ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return results;
975ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
9761877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick
9771877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick    /**
9782c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * Call a provider-defined method.  This can be used to implement
979534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * interfaces that are cheaper and/or unnatural for a table-like
980534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * model.
9811877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     *
982534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @param method method name to call.  Opaque to framework, but should not be null.
983534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @param arg provider-defined String argument.  May be null.
984534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @param extras provider-defined Bundle argument.  May be null.
985534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     * @return provider-defined return value.  May be null.  Null is also
986534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick     *   the default for providers which don't implement any call methods.
9871877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     */
988534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick    public Bundle call(String method, String arg, Bundle extras) {
9891877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick        return null;
9901877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick    }
9910c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori
9920c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    /**
9932c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * Implement this to shut down the ContentProvider instance. You can then
9942c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * invoke this method in unit tests.
9952c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     *
9960c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * <p>
9972c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * Android normally handles ContentProvider startup and shutdown
9982c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * automatically. You do not need to start up or shut down a
9992c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * ContentProvider. When you invoke a test method on a ContentProvider,
10002c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * however, a ContentProvider instance is started and keeps running after
10012c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * the test finishes, even if a succeeding test instantiates another
10022c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * ContentProvider. A conflict develops because the two instances are
10032c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * usually running against the same underlying data source (for example, an
10042c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * sqlite database).
10052c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * </p>
10060c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * <p>
10072c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * Implementing shutDown() avoids this conflict by providing a way to
10082c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * terminate the ContentProvider. This method can also prevent memory leaks
10092c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * from multiple instantiations of the ContentProvider, and it can ensure
10102c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * unit test isolation by allowing you to completely clean up the test
10112c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * fixture before moving on to the next test.
10122c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman     * </p>
10130c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     */
10140c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    public void shutdown() {
10150c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori        Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " +
10160c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori                "connections are gracefully shutdown");
10170c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    }
101818cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen
101918cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen    /**
102018cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * Print the Provider's state into the given stream.  This gets invoked if
102118cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * you run "adb shell dumpsys activity provider <provider_component_name>".
102218cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     *
102318cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * @param prefix Desired prefix to prepend at each line of output.
102418cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * @param fd The raw file descriptor that the dump is being sent to.
102518cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * @param writer The PrintWriter to which you should dump your state.  This will be
102618cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * closed for you after you return.
102718cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * @param args additional arguments to the dump request.
102818cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     * @hide
102918cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen     */
103018cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
103118cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen        writer.println("nothing to dump");
103218cb28756caf02bf2b2f5e67c68451edaf719b47Marco Nelissen    }
10331877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick}
1034