ContentProvider.java revision 23fdaf6fb62a9b5154b2508916a21c678462c5d0
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.CursorToBulkCursorAdaptor;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.CursorWindow;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.IBulkCursor;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.IContentObserver;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.SQLException;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
3123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport android.os.AsyncTask;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
331877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrickimport android.os.Bundle;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
352af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackbornimport android.os.Process;
360c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Noriimport android.util.Log;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
4023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackbornimport java.io.IOException;
4103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintanaimport java.util.ArrayList;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Content providers are one of the primary building blocks of Android applications, providing
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * content to applications. They encapsulate data and provide it to applications through the single
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ContentResolver} interface. A content provider is only required if you need to share
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data between multiple applications. For example, the contacts data is used by multiple
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * applications and must be stored in a content provider. If you don't need to share data amongst
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple applications you can use a database directly via
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.database.sqlite.SQLiteDatabase}.
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>For more information, read <a href="{@docRoot}guide/topics/providers/content-providers.html">Content
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Providers</a>.</p>
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When a request is made via
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link ContentResolver} the system inspects the authority of the given URI and passes the
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * request to the content provider registered with the authority. The content provider can interpret
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * URIs.</p>
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The primary methods that need to be implemented are:
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
636fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor *   <li>{@link #onCreate} which is called to initialize the provider</li>
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #query} which returns data to the caller</li>
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #insert} which inserts new data into the content provider</li>
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #update} which updates existing data in the content provider</li>
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #delete} which deletes data from the content provider</li>
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>{@link #getType} which returns the MIME type of data in the content provider</li>
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul></p>
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
716fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p class="caution">Data access methods (such as {@link #insert} and
726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link #update}) may be called from many threads at once, and must be thread-safe.
736fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Other methods (such as {@link #onCreate}) are only called from the application
746fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * main thread, and must avoid performing lengthy operations.  See the method
756fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * descriptions for their expected thread behavior.</p>
766fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor *
776fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate
786fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * ContentProvider instance, so subclasses don't have to worry about the details of
796fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * cross-process calls.</p>
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class ContentProvider implements ComponentCallbacks {
820c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    private static final String TAG = "ContentProvider";
830c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori
848280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    /*
858280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * Note: if you add methods to ContentProvider, you must add similar methods to
868280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     *       MockContentProvider.
878280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     */
888280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext = null;
902af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    private int mMyUid;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mReadPermission;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mWritePermission;
932af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    private PathPermission[] mPathPermissions;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Transport mTransport = new Transport();
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
976fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor    /**
986fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Construct a ContentProvider instance.  Content providers must be
996fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared
1006fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * in the manifest</a>, accessed with {@link ContentResolver}, and created
1016fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * automatically by the system, so applications usually do not create
1026fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * ContentProvider instances directly.
1036fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
1046fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>At construction time, the object is uninitialized, and most fields and
1056fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * methods are unavailable.  Subclasses should initialize themselves in
1066fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link #onCreate}, not the constructor.
1076fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
1086fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>Content providers are created on the application main thread at
1096fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * application launch time.  The constructor must not perform lengthy
1106fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * operations, or application startup will be delayed.
1116fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
1128280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    public ContentProvider() {
1138280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    }
1148280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa
1158280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    /**
1168280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * Constructor just for mocking.
1178280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     *
1188280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param context A Context object which should be some mock instance (like the
1198280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * instance of {@link android.test.mock.MockContext}).
1208280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param readPermission The read permision you want this instance should have in the
1218280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * test, which is available via {@link #getReadPermission()}.
1228280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param writePermission The write permission you want this instance should have
1238280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * in the test, which is available via {@link #getWritePermission()}.
1248280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @param pathPermissions The PathPermissions you want this instance should have
1258280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * in the test, which is available via {@link #getPathPermissions()}.
1268280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     * @hide
1278280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa     */
1288280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    public ContentProvider(
1298280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            Context context,
1308280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            String readPermission,
1318280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            String writePermission,
1328280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa            PathPermission[] pathPermissions) {
1338280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mContext = context;
1348280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mReadPermission = readPermission;
1358280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mWritePermission = writePermission;
1368280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa        mPathPermissions = pathPermissions;
1378280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa    }
1388280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Given an IContentProvider, try to coerce it back to the real
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ContentProvider object if it is running in the local process.  This can
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be used if you know you are running in the same process as a provider,
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and want to get direct access to its implementation details.  Most
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clients should not nor have a reason to use it.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param abstractInterface The ContentProvider interface that is to be
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *              coerced.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return If the IContentProvider is non-null and local, returns its actual
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ContentProvider instance.  Otherwise returns null.
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ContentProvider coerceToLocalContentProvider(
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IContentProvider abstractInterface) {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (abstractInterface instanceof Transport) {
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ((Transport)abstractInterface).getContentProvider();
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Binder object that deals with remoting.
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class Transport extends ContentProviderNative {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentProvider getContentProvider() {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Remote version of a query, which returns an IBulkCursor. The bulk
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * cursor should be wrapped with BulkCursorToCursorAdaptor before use.
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public IBulkCursor bulkQuery(Uri uri, String[] projection,
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String selection, String[] selectionArgs, String sortOrder,
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IContentObserver observer, CursorWindow window) {
1772af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceReadPermission(uri);
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Cursor cursor = ContentProvider.this.query(uri, projection,
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    selection, selectionArgs, sortOrder);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cursor == null) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new CursorToBulkCursorAdaptor(cursor, observer,
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ContentProvider.this.getClass().getName(),
1852af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    hasWritePermission(uri), window);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Cursor query(Uri uri, String[] projection,
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String selection, String[] selectionArgs, String sortOrder) {
1902af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceReadPermission(uri);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.query(uri, projection, selection,
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    selectionArgs, sortOrder);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String getType(Uri uri) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.getType(uri);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Uri insert(Uri uri, ContentValues initialValues) {
2012af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.insert(uri, initialValues);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int bulkInsert(Uri uri, ContentValues[] initialValues) {
2062af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.bulkInsert(uri, initialValues);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
2118943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                throws OperationApplicationException {
2128943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            for (ContentProviderOperation operation : operations) {
2138943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                if (operation.isReadOperation()) {
214e3f054411b9f025848f68389c4e2c325e76b3826Dianne Hackborn                    enforceReadPermission(operation.getUri());
2158943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                }
2168943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
2178943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                if (operation.isWriteOperation()) {
218e3f054411b9f025848f68389c4e2c325e76b3826Dianne Hackborn                    enforceWritePermission(operation.getUri());
2198943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                }
2208943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            }
2218943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            return ContentProvider.this.applyBatch(operations);
2226a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana        }
2236a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int delete(Uri uri, String selection, String[] selectionArgs) {
2252af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.delete(uri, selection, selectionArgs);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int update(Uri uri, ContentValues values, String selection,
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String[] selectionArgs) {
2312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            enforceWritePermission(uri);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.update(uri, values, selection, selectionArgs);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ParcelFileDescriptor openFile(Uri uri, String mode)
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throws FileNotFoundException {
2372af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
2382af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            else enforceReadPermission(uri);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.openFile(uri, mode);
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public AssetFileDescriptor openAssetFile(Uri uri, String mode)
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throws FileNotFoundException {
2442af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
2452af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            else enforceReadPermission(uri);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ContentProvider.this.openAssetFile(uri, mode);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2491877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick        /**
2501877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick         * @hide
2511877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick         */
2521877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick        public Bundle call(String method, String request, Bundle args) {
2531877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick            return ContentProvider.this.call(method, request, args);
2541877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick        }
2551877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick
25623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        @Override
25723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
25823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
25923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
26023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
26123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        @Override
26223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeType, Bundle opts)
26323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                throws FileNotFoundException {
26423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            enforceReadPermission(uri);
26523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return ContentProvider.this.openTypedAssetFile(uri, mimeType, opts);
26623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
26723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
2682af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        private void enforceReadPermission(Uri uri) {
2692af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final int uid = Binder.getCallingUid();
2702af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (uid == mMyUid) {
2712af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return;
2722af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
2732af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
2742af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final Context context = getContext();
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String rperm = getReadPermission();
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int pid = Binder.getCallingPid();
2772af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (rperm == null
2782af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    || context.checkPermission(rperm, pid, uid)
2792af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    == PackageManager.PERMISSION_GRANTED) {
2802af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return;
2812af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
2822af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
2832af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            PathPermission[] pps = getPathPermissions();
2842af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (pps != null) {
2852af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                final String path = uri.getPath();
2862af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                int i = pps.length;
2872af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                while (i > 0) {
2882af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    i--;
2892af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final PathPermission pp = pps[i];
2902af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final String pprperm = pp.getReadPermission();
2912af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    if (pprperm != null && pp.match(path)) {
2922af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        if (context.checkPermission(pprperm, pid, uid)
2932af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                                == PackageManager.PERMISSION_GRANTED) {
2942af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                            return;
2952af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        }
2962af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    }
2972af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                }
2982af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
2992af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3002af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (context.checkUriPermission(uri, pid, uid,
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Intent.FLAG_GRANT_READ_URI_PERMISSION)
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    == PackageManager.PERMISSION_GRANTED) {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3052af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String msg = "Permission Denial: reading "
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ContentProvider.this.getClass().getName()
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid()
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " requires " + rperm;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(msg);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3142af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        private boolean hasWritePermission(Uri uri) {
3152af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final int uid = Binder.getCallingUid();
3162af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (uid == mMyUid) {
3172af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return true;
3182af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3192af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3202af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            final Context context = getContext();
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String wperm = getWritePermission();
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int pid = Binder.getCallingPid();
3232af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (wperm == null
3242af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    || context.checkPermission(wperm, pid, uid)
3252af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    == PackageManager.PERMISSION_GRANTED) {
3262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return true;
3272af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3282af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3292af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            PathPermission[] pps = getPathPermissions();
3302af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (pps != null) {
3312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                final String path = uri.getPath();
3322af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                int i = pps.length;
3332af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                while (i > 0) {
3342af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    i--;
3352af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final PathPermission pp = pps[i];
3362af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    final String ppwperm = pp.getWritePermission();
3372af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    if (ppwperm != null && pp.match(path)) {
3382af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        if (context.checkPermission(ppwperm, pid, uid)
3392af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                                == PackageManager.PERMISSION_GRANTED) {
3402af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                            return true;
3412af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                        }
3422af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    }
3432af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                }
3442af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3452af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3462af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (context.checkUriPermission(uri, pid, uid,
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    == PackageManager.PERMISSION_GRANTED) {
3492af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                return true;
3502af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            }
3512af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3522af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            return false;
3532af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        }
3542af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3552af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        private void enforceWritePermission(Uri uri) {
3562af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            if (hasWritePermission(uri)) {
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3592af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String msg = "Permission Denial: writing "
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ContentProvider.this.getClass().getName()
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid()
3642af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                    + " requires " + getWritePermission();
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(msg);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3716fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Retrieves the Context this provider is running in.  Only available once
3726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link #onCreate} has been called -- this will return null in the
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constructor.
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Context getContext() {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Change the permission required to read data from the content
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * provider.  This is normally set for you from its manifest information
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is first created.
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param permission Name of the permission required for read-only access.
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final void setReadPermission(String permission) {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mReadPermission = permission;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the name of the permission required for read-only access to
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this content provider.  This method can be called from multiple
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * threads, as described in
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final String getReadPermission() {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mReadPermission;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Change the permission required to read and write data in the content
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * provider.  This is normally set for you from its manifest information
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is first created.
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param permission Name of the permission required for read/write access.
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final void setWritePermission(String permission) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWritePermission = permission;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the name of the permission required for read/write access to
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this content provider.  This method can be called from multiple
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * threads, as described in
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final String getWritePermission() {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWritePermission;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4242af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * Change the path-based permission required to read and/or write data in
4252af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * the content provider.  This is normally set for you from its manifest
4262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * information when the provider is first created.
4272af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     *
4282af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * @param permissions Array of path permission descriptions.
4292af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     */
4302af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    protected final void setPathPermissions(PathPermission[] permissions) {
4312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        mPathPermissions = permissions;
4322af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    }
4332af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
4342af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    /**
4352af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * Return the path-based permissions required for read and/or write access to
4362af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * this content provider.  This method can be called from multiple
4372af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * threads, as described in
4382af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
4392af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     * Processes and Threads</a>.
4402af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn     */
4412af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    public final PathPermission[] getPathPermissions() {
4422af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn        return mPathPermissions;
4432af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    }
4442af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn
4452af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn    /**
4466fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to initialize your content provider on startup.
4476fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method is called for all registered content providers on the
4486fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * application main thread at application launch time.  It must not perform
4496fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * lengthy operations, or application startup will be delayed.
4506fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
4516fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>You should defer nontrivial initialization (such as opening,
4526fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * upgrading, and scanning databases) until the content provider is used
4536fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * (via {@link #query}, {@link #insert}, etc).  Deferred initialization
4546fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * keeps application startup fast, avoids unnecessary work if the provider
4556fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * turns out not to be needed, and stops database errors (such as a full
4566fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * disk) from halting application launch.
4576fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
45817876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper}
4596fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * is a helpful utility class that makes it easy to manage databases,
4606fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * and will automatically defer opening until first use.  If you do use
4616fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * SQLiteOpenHelper, make sure to avoid calling
4626fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or
4636fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase}
4646fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * from this method.  (Instead, override
4656fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the
4666fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * database when it is first opened.)
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the provider was successfully loaded, false otherwise
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract boolean onCreate();
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor    /**
4736fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@inheritDoc}
4746fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method is always called on the application main thread, and must
4756fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * not perform lengthy operations.
4766fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
4776fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>The default content provider implementation does nothing.
4786fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Override this method to take appropriate action.
4796fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * (Content providers do not usually care about things like screen
4806fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * orientation, but may want to know about locale changes.)
4816fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onConfigurationChanged(Configuration newConfig) {
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4846fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor
4856fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor    /**
4866fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@inheritDoc}
4876fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method is always called on the application main thread, and must
4886fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * not perform lengthy operations.
4896fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
4906fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>The default content provider implementation does nothing.
4916fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Subclasses may override this method to take appropriate action.
4926fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onLowMemory() {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4976fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle query requests from clients.
4986fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example client call:<p>
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>// Request a specific record.
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Cursor managedCursor = managedQuery(
50581a476f654155df27aa564a4aebf931eab588e6dAlan Jones                ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                projection,    // Which columns to return.
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                null,          // WHERE clause.
50881a476f654155df27aa564a4aebf931eab588e6dAlan Jones                null,          // WHERE clause value substitution
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                People.NAME + " ASC");   // Sort order.</pre>
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example implementation:<p>
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>// SQLiteQueryBuilder is a helper class that creates the
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // proper SQL syntax for us.
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set the table we're querying.
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        qBuilder.setTables(DATABASE_TABLE_NAME);
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the query ends in a specific record number, we're
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // being asked for a specific record, so set the
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // WHERE clause in our query.
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            qBuilder.appendWhere("_id=" + uri.getPathLeafId());
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Make the query.
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Cursor c = qBuilder.query(mDb,
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                projection,
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                selection,
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                selectionArgs,
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                groupBy,
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                having,
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sortOrder);
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.setNotificationUri(getContext().getContentResolver(), uri);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return c;</pre>
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to query. This will be the full URI sent by the client;
53781a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      if the client is requesting a specific record, the URI will end in a record number
53881a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      that the implementation should parse and add to a WHERE or HAVING clause, specifying
53981a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      that _id value.
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param projection The list of columns to put into the cursor. If
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      null all columns are included.
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selection A selection criteria to apply when filtering rows.
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      If null then all rows are included.
54481a476f654155df27aa564a4aebf931eab588e6dAlan Jones     * @param selectionArgs You may include ?s in selection, which will be replaced by
54581a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      the values from selectionArgs, in order that they appear in the selection.
54681a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      The values will be bound as Strings.
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sortOrder How the rows in the cursor should be sorted.
54881a476f654155df27aa564a4aebf931eab588e6dAlan Jones     *      If null then the provider is free to define the sort order.
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a Cursor or null.
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract Cursor query(Uri uri, String[] projection,
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String selection, String[] selectionArgs, String sortOrder);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5545bba632d877c2878384ff21566c8eb6a1a22f37bFred Quintana    /**
5556fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle requests for the MIME type of the data at the
5566fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * given URI.  The returned MIME type should start with
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>vnd.android.cursor.item</code> for a single record,
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or <code>vnd.android.cursor.dir/</code> for multiple items.
5596fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri the URI to query.
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a MIME type string, or null if there is no type.
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract String getType(Uri uri);
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5696fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle requests to insert a new row.
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after inserting.
5726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The content:// URI of the insertion request.
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values A set of column_name/value pairs to add to the database.
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The URI for the newly inserted item.
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract Uri insert(Uri uri, ContentValues values);
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5826fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Override this to handle requests to insert a set of new rows, or the
5836fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * default implementation will iterate over the values and call
5846fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link #insert} on each of them.
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after inserting.
5876fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The content:// URI of the insertion request.
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values An array of sets of column_name/value pairs to add to the database.
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of values that were inserted.
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int bulkInsert(Uri uri, ContentValues[] values) {
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numValues = values.length;
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < numValues; i++) {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            insert(uri, values[i]);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return numValues;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6046fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Implement this to handle requests to delete one or more rows.
6056fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * The implementation should apply the selection clause when performing
6066fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * deletion, allowing the operation to affect multiple rows in a directory.
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after deleting.
6096fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The implementation is responsible for parsing out a row ID at the end
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the URI, if a specific row is being deleted. That is, the client would
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pass in <code>content://contacts/people/22</code> and the implementation is
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * responsible for parsing the record number (22) when creating a SQL statement.
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The full URI to query, including a row ID (if a specific record is requested).
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selection An optional restriction to apply to rows when deleting.
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of rows affected.
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws SQLException
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract int delete(Uri uri, String selection, String[] selectionArgs);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
62617876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * Implement this to handle requests to update one or more rows.
6276fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * The implementation should update all rows matching the selection
6286fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * to set the columns according to the provided values map.
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * after updating.
6316fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to query. This can potentially have a record ID if this
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is an update request for a specific record.
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values A Bundle mapping from column names to new column values (NULL is a
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               valid value).
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selection An optional filter to match rows to update.
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the number of rows affected.
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract int update(Uri uri, ContentValues values, String selection,
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String[] selectionArgs);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
64617876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * Override this to handle requests to open a file blob.
6476fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * The default implementation always throws {@link FileNotFoundException}.
6486fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Processes and Threads</a>.
6516fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
65217876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * <p>This method returns a ParcelFileDescriptor, which is returned directly
65317876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * to the caller.  This way large data (such as images and documents) can be
6546fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * returned without copying the content.
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * their responsibility to close it when done.  That is, the implementation
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of this method should create a new ParcelFileDescriptor for each call.
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI whose file is to be opened.
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode Access mode for the file.  May be "r" for read-only access,
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "rw" for read and write access, or "rwt" for read and write access
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that truncates any existing file.
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new ParcelFileDescriptor which you can use to access
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file.
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException Throws FileNotFoundException if there is
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no file associated with the given URI or the mode is invalid.
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws SecurityException Throws SecurityException if the caller does
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not have permission to access the file.
6726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openAssetFile(Uri, String)
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openFileHelper(Uri, String)
6756fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     */
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ParcelFileDescriptor openFile(Uri uri, String mode)
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new FileNotFoundException("No files supported by provider at "
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + uri);
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6816fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is like {@link #openFile}, but can be implemented by providers
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that need to be able to return sub-sections of files, often assets
6856fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * inside of their .apk.
6866fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
6876fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
6886fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Processes and Threads</a>.
6896fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
6906fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p>If you implement this, your clients must be able to deal with such
69117876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * file slices, either directly with
6926fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * methods.
6966fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
6976fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <p class="note">If you are implementing this to return a full file, you
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should create the AssetFileDescriptor with
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
7006fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * applications that can not handle sub-sections of files.</p>
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI whose file is to be opened.
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode Access mode for the file.  May be "r" for read-only access,
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "w" for write-only access (erasing whatever data is currently in
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file), "wa" for write-only access to append to any existing data,
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "rw" for read and write access on any existing data, and "rwt" for read
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and write access that truncates any existing file.
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new AssetFileDescriptor which you can use to access
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file.
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException Throws FileNotFoundException if there is
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no file associated with the given URI or the mode is invalid.
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws SecurityException Throws SecurityException if the caller does
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not have permission to access the file.
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openFile(Uri, String)
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #openFileHelper(Uri, String)
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AssetFileDescriptor openAssetFile(Uri uri, String mode)
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ParcelFileDescriptor fd = openFile(uri, mode);
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convenience for subclasses that wish to implement {@link #openFile}
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by looking up a column named "_data" at the given URI.
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uri The URI to be opened.
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode The file mode.  May be "r" for read-only access,
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "w" for write-only access (erasing whatever data is currently in
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the file), "wa" for write-only access to append to any existing data,
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "rw" for read and write access on any existing data, and "rwt" for read
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and write access that truncates any existing file.
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new ParcelFileDescriptor that can be used by the
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * client to access the file.
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected final ParcelFileDescriptor openFileHelper(Uri uri,
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String mode) throws FileNotFoundException {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Cursor c = query(uri, new String[]{"_data"}, null, null, null);
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int count = (c != null) ? c.getCount() : 0;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (count != 1) {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If there is not exactly one result, throw an appropriate
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // exception.
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (c != null) {
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                c.close();
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (count == 0) {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new FileNotFoundException("No entry for " + uri);
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("Multiple items at " + uri);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.moveToFirst();
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i = c.getColumnIndex("_data");
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String path = (i >= 0 ? c.getString(i) : null);
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.close();
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (path == null) {
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException("Column _data not found.");
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int modeBits = ContentResolver.modeToMode(uri, mode);
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ParcelFileDescriptor.open(new File(path), modeBits);
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
76923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Helper to compare two MIME types, where one may be a pattern.
77023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param concreteType A fully-specified MIME type.
77123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param desiredType A desired MIME type that may be a pattern such as *\/*.
77223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @return Returns true if the two MIME types match.
77323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
77423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public static boolean compareMimeTypes(String concreteType, String desiredType) {
77523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        final int typeLength = desiredType.length();
77623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        if (typeLength == 3 && desiredType.equals("*/*")) {
77723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return true;
77823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
77923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
78023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        final int slashpos = desiredType.indexOf('/');
78123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        if (slashpos > 0) {
78223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            if (typeLength == slashpos+2 && desiredType.charAt(slashpos+1) == '*') {
78323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                if (desiredType.regionMatches(0, concreteType, 0, slashpos+1)) {
78423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    return true;
78523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                }
78623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            } else if (desiredType.equals(concreteType)) {
78723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                return true;
78823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            }
78923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
79023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
79123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        return false;
79223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
79323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
79423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
79523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Called by a client to determine the types of data streams that this
79623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * content provider supports for the given URI.  The default implementation
79723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * returns null, meaning no types.  If your content provider stores data
79823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * of a particular type, return that MIME type if it matches the given
79923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * mimeTypeFilter.  If it can perform type conversions, return an array
80023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * of all supported MIME types that match mimeTypeFilter.
80123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
80223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param uri The data in the content provider being queried.
80323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeTypeFilter The type of data the client desires.  May be
80423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * a pattern, such as *\/* to retrieve all possible data types.
80523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @returns Returns null if there are no possible data streams for the
80623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * given mimeTypeFilter.  Otherwise returns an array of all available
80723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * concrete MIME types.
80823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
80923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #getType(Uri)
81023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #openTypedAssetFile(Uri, String, Bundle)
81123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #compareMimeTypes(String, String)
81223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
81323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
81423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        return null;
81523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
81623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
81723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
81823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Called by a client to open a read-only stream containing data of a
81923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * particular MIME type.  This is like {@link #openAssetFile(Uri, String)},
82023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * except the file can only be read-only and the content provider may
82123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * perform data conversions to generate data of the desired type.
82223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
82323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * <p>The default implementation compares the given mimeType against the
82423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * result of {@link #getType(Uri)} and, if the match, simple calls
82523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * {@link #openAssetFile(Uri, String)}.
82623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
82723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * <p>See {@link ClippedData} for examples of the use and implementation
82823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * of this method.
82923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
83023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param uri The data in the content provider being queried.
83123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeTypeFilter The type of data the client desires.  May be
83223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * a pattern, such as *\/*, if the caller does not have specific type
83323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * requirements; in this case the content provider will pick its best
83423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * type matching the pattern.
83523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param opts Additional options from the client.  The definitions of
83623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * these are specific to the content provider being called.
83723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
83823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @return Returns a new AssetFileDescriptor from which the client can
83923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * read data of the desired type.
84023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
84123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @throws FileNotFoundException Throws FileNotFoundException if there is
84223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * no file associated with the given URI or the mode is invalid.
84323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @throws SecurityException Throws SecurityException if the caller does
84423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * not have permission to access the data.
84523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @throws IllegalArgumentException Throws IllegalArgumentException if the
84623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * content provider does not support the requested MIME type.
84723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
84823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #getStreamTypes(Uri, String)
84923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #openAssetFile(Uri, String)
85023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @see #compareMimeTypes(String, String)
85123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
85223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
85323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            throws FileNotFoundException {
85423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        String baseType = getType(uri);
85523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        if (baseType != null && compareMimeTypes(baseType, mimeTypeFilter)) {
85623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return openAssetFile(uri, "r");
85723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
85823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter);
85923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
86023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
86123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
86223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * Interface to write a stream of data to a pipe.  Use with
86323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * {@link ContentProvider#openPipeHelper}.
86423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
86523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public interface PipeDataWriter<T> {
86623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        /**
86723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * Called from a background thread to stream data out to a pipe.
86823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * Note that the pipe is blocking, so this thread can block on
86923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * writes for an arbitrary amount of time if the client is slow
87023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * at reading.
87123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         *
87223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param output The pipe where data should be written.  This will be
87323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * closed for you upon returning from this function.
87423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param uri The URI whose data is to be written.
87523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param mimeType The desired type of data to be written.
87623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param opts Options supplied by caller.
87723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * @param args Your own custom arguments.
87823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         */
87923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
88023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                Bundle opts, T args);
88123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
88223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
88323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
88423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * A helper function for implementing {@link #openTypedAssetFile}, for
88523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * creating a data pipe and background thread allowing you to stream
88623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * generated data back to the client.  This function returns a new
88723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * ParcelFileDescriptor that should be returned to the caller (the caller
88823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * is responsible for closing it).
88923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     *
89023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param uri The URI whose data is to be written.
89123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param mimeType The desired type of data to be written.
89223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param opts Options supplied by caller.
89323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param args Your own custom arguments.
89423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @param func Interface implementing the function that will actually
89523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * stream the data.
89623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * @return Returns a new ParcelFileDescriptor holding the read side of
89723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * the pipe.  This should be returned to the caller for reading; the caller
89823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     * is responsible for closing it when done.
89923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn     */
90023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType,
90123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            final Bundle opts, final T args, final PipeDataWriter<T> func)
90223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            throws FileNotFoundException {
90323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        try {
90423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
90523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
90623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
90723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                @Override
90823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                protected Object doInBackground(Object... params) {
90923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    func.writeDataToPipe(fds[1], uri, mimeType, opts, args);
91023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    try {
91123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                        fds[1].close();
91223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    } catch (IOException e) {
91323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                        Log.w(TAG, "Failure closing pipe", e);
91423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    }
91523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                    return null;
91623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn                }
91723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            };
91823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            task.execute((Object[])null);
91923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
92023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            return fds[0];
92123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        } catch (IOException e) {
92223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn            throw new FileNotFoundException("failure making pipe");
92323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        }
92423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    }
92523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn
92623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn    /**
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if this instance is a temporary content provider.
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if this instance is a temporary content provider
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean isTemporary() {
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the Binder object for this provider.
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the Binder object for this provider
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public IContentProvider getIContentProvider() {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTransport;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * After being instantiated, this is called to tell the content provider
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * about itself.
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context The context this provider is running in
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info Registered information about this content provider
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void attachInfo(Context context, ProviderInfo info) {
95223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        /*
95323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * We may be using AsyncTask from binder threads.  Make it init here
95423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         * so its static handler is on the main thread.
95523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn         */
95623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn        AsyncTask.init();
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Only allow it to be set once, so after the content service gives
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * this to us clients can't change it.
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext == null) {
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext = context;
9642af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn            mMyUid = Process.myUid();
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (info != null) {
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setReadPermission(info.readPermission);
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setWritePermission(info.writePermission);
9682af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn                setPathPermissions(info.pathPermissions);
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentProvider.this.onCreate();
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
973ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
974ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
97517876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * Override this to handle requests to perform a batch of operations, or the
97617876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * default implementation will iterate over the operations and call
97717876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * {@link ContentProviderOperation#apply} on each of them.
97817876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * If all calls to {@link ContentProviderOperation#apply} succeed
97917876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * then a {@link ContentProviderResult} array with as many
98017876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor     * elements as there were operations will be returned.  If any of the calls
9816fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * fail, it is up to the implementation how many of the others take effect.
9826fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * This method can be called from multiple threads, as described in
9836fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
9846fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * Processes and Threads</a>.
9856fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     *
986ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param operations the operations to apply
987ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return the results of the applications
9886fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * @throws OperationApplicationException thrown if any operation fails.
9896fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor     * @see ContentProviderOperation#apply
990ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
99103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
992ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            throws OperationApplicationException {
99303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        final int numOperations = operations.size();
99403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        final ContentProviderResult[] results = new ContentProviderResult[numOperations];
99503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        for (int i = 0; i < numOperations; i++) {
99603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            results[i] = operations.get(i).apply(this, results, i);
997ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
998ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return results;
999ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
10001877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick
10011877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick    /**
10021877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     * @hide -- until interface has proven itself
10031877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     *
10041877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     * Call an provider-defined method.  This can be used to implement
10051877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     * interfaces that are cheaper than using a Cursor.
10061877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     *
10071877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     * @param method Method name to call.  Opaque to framework.
10081877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     * @param request Nullable String argument passed to method.
10091877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     * @param args Nullable Bundle argument passed to method.
10101877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick     */
10111877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick    public Bundle call(String method, String request, Bundle args) {
10121877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick        return null;
10131877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick    }
10140c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori
10150c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    /**
10160c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * Shuts down this instance of the ContentProvider. It is useful when writing tests that use
10170c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * the ContentProvider.
10180c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * <p>
10190c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * If a unittest starts the ContentProvider in its test(..() methods, it could run into sqlite
10200c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * errors "disk I/O error" or "corruption" in the following scenario:
10210c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * <ul>
10220c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>Say, there are 2 test methods in the unittest</li>
10230c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>test1() (or setUp()) causes ContentProvider object to be initialized and
10240c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   assume it opens a database connection to "foo.db"</li>
10250c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>est1() completes and test2() starts</li>
10260c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>During the execution of test2() there will be 2 connections to "foo.db"</li>
10270c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>Different threads in the ContentProvider may have one of these two connection
10280c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   handles. This is not a problem per se</li>
10290c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>But if the two threads with 2 database connections don't interact correctly,
10300c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   there could be unexpected errors from sqlite</li>
10310c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>Some of those unexpected errros are "disk I/O error" or "corruption" error</li>
10320c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>Common practice in tearDown() is to delete test directory (and the database files)</li>
10330c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   <li>If this is done while some threads are still holding unclosed database connections,
10340c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     *   sqlite quite easily gets into corruption and disk I/O errors</li>
10350c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * </ul>
10360c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * <p>
10370c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * tearDown() in the unittests should call this method to have ContentProvider gracefully
10380c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     * shutdown all database connections.
10390c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori     */
10400c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    public void shutdown() {
10410c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori        Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " +
10420c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori                "connections are gracefully shutdown");
10430c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori    }
10441877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick}
1045