ContentProvider.java revision c68c913d357e2955d4bd7ca52829071e531c7825
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 */ 81c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackbornpublic abstract class ContentProvider implements ComponentCallbacks2 { 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; 94b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn private boolean mExported; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Transport mTransport = new Transport(); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 986fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor /** 996fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Construct a ContentProvider instance. Content providers must be 1006fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared 1016fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * in the manifest</a>, accessed with {@link ContentResolver}, and created 1026fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * automatically by the system, so applications usually do not create 1036fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * ContentProvider instances directly. 1046fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 1056fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>At construction time, the object is uninitialized, and most fields and 1066fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * methods are unavailable. Subclasses should initialize themselves in 1076fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link #onCreate}, not the constructor. 1086fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 1096fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>Content providers are created on the application main thread at 1106fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * application launch time. The constructor must not perform lengthy 1116fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * operations, or application startup will be delayed. 1126fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor */ 1138280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa public ContentProvider() { 1148280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa } 1158280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa 1168280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa /** 1178280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * Constructor just for mocking. 1188280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * 1198280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * @param context A Context object which should be some mock instance (like the 1208280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * instance of {@link android.test.mock.MockContext}). 1218280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * @param readPermission The read permision you want this instance should have in the 1228280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * test, which is available via {@link #getReadPermission()}. 1238280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * @param writePermission The write permission you want this instance should have 1248280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * in the test, which is available via {@link #getWritePermission()}. 1258280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * @param pathPermissions The PathPermissions you want this instance should have 1268280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * in the test, which is available via {@link #getPathPermissions()}. 1278280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa * @hide 1288280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa */ 1298280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa public ContentProvider( 1308280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa Context context, 1318280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa String readPermission, 1328280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa String writePermission, 1338280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa PathPermission[] pathPermissions) { 1348280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa mContext = context; 1358280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa mReadPermission = readPermission; 1368280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa mWritePermission = writePermission; 1378280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa mPathPermissions = pathPermissions; 1388280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa } 1398280c2b15f6875b2d387c05df23d264864eb9cd5Daisuke Miyakawa 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Given an IContentProvider, try to coerce it back to the real 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ContentProvider object if it is running in the local process. This can 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be used if you know you are running in the same process as a provider, 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and want to get direct access to its implementation details. Most 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * clients should not nor have a reason to use it. 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param abstractInterface The ContentProvider interface that is to be 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * coerced. 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return If the IContentProvider is non-null and local, returns its actual 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ContentProvider instance. Otherwise returns null. 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static ContentProvider coerceToLocalContentProvider( 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IContentProvider abstractInterface) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (abstractInterface instanceof Transport) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((Transport)abstractInterface).getContentProvider(); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Binder object that deals with remoting. 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class Transport extends ContentProviderNative { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentProvider getContentProvider() { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remote version of a query, which returns an IBulkCursor. The bulk 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursor should be wrapped with BulkCursorToCursorAdaptor before use. 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IBulkCursor bulkQuery(Uri uri, String[] projection, 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String selection, String[] selectionArgs, String sortOrder, 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IContentObserver observer, CursorWindow window) { 1782af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn enforceReadPermission(uri); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor cursor = ContentProvider.this.query(uri, projection, 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selection, selectionArgs, sortOrder); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursor == null) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new CursorToBulkCursorAdaptor(cursor, observer, 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentProvider.this.getClass().getName(), 1862af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn hasWritePermission(uri), window); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor query(Uri uri, String[] projection, 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String selection, String[] selectionArgs, String sortOrder) { 1912af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn enforceReadPermission(uri); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.query(uri, projection, selection, 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectionArgs, sortOrder); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getType(Uri uri) { 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.getType(uri); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Uri insert(Uri uri, ContentValues initialValues) { 2022af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn enforceWritePermission(uri); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.insert(uri, initialValues); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int bulkInsert(Uri uri, ContentValues[] initialValues) { 2072af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn enforceWritePermission(uri); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.bulkInsert(uri, initialValues); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2128943737692169f564cd34a9c8d471f3a5d438712Fred Quintana throws OperationApplicationException { 2138943737692169f564cd34a9c8d471f3a5d438712Fred Quintana for (ContentProviderOperation operation : operations) { 2148943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (operation.isReadOperation()) { 215e3f054411b9f025848f68389c4e2c325e76b3826Dianne Hackborn enforceReadPermission(operation.getUri()); 2168943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 2178943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 2188943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (operation.isWriteOperation()) { 219e3f054411b9f025848f68389c4e2c325e76b3826Dianne Hackborn enforceWritePermission(operation.getUri()); 2208943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 2218943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 2228943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return ContentProvider.this.applyBatch(operations); 2236a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana } 2246a8d5332f00bdfade6674b312e7166940aa28348Fred Quintana 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int delete(Uri uri, String selection, String[] selectionArgs) { 2262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn enforceWritePermission(uri); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.delete(uri, selection, selectionArgs); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int update(Uri uri, ContentValues values, String selection, 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] selectionArgs) { 2322af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn enforceWritePermission(uri); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.update(uri, values, selection, selectionArgs); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ParcelFileDescriptor openFile(Uri uri, String mode) 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FileNotFoundException { 2382af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); 2392af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn else enforceReadPermission(uri); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.openFile(uri, mode); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AssetFileDescriptor openAssetFile(Uri uri, String mode) 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FileNotFoundException { 2452af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); 2462af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn else enforceReadPermission(uri); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentProvider.this.openAssetFile(uri, mode); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 250534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick public Bundle call(String method, String arg, Bundle extras) { 251534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick return ContentProvider.this.call(method, arg, extras); 2521877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick } 2531877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick 25423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn @Override 25523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { 25623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter); 25723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 25823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 25923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn @Override 26023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeType, Bundle opts) 26123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn throws FileNotFoundException { 26223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn enforceReadPermission(uri); 26323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return ContentProvider.this.openTypedAssetFile(uri, mimeType, opts); 26423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 26523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 2662af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn private void enforceReadPermission(Uri uri) { 2672af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final int uid = Binder.getCallingUid(); 2682af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (uid == mMyUid) { 2692af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return; 2702af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 2712af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 2722af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final Context context = getContext(); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String rperm = getReadPermission(); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int pid = Binder.getCallingPid(); 275b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn if (mExported && (rperm == null 2762af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn || context.checkPermission(rperm, pid, uid) 277b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn == PackageManager.PERMISSION_GRANTED)) { 2782af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return; 2792af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 2802af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 2812af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn PathPermission[] pps = getPathPermissions(); 2822af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (pps != null) { 2832af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final String path = uri.getPath(); 2842af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn int i = pps.length; 2852af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn while (i > 0) { 2862af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn i--; 2872af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final PathPermission pp = pps[i]; 2882af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final String pprperm = pp.getReadPermission(); 2892af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (pprperm != null && pp.match(path)) { 2902af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (context.checkPermission(pprperm, pid, uid) 2912af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn == PackageManager.PERMISSION_GRANTED) { 2922af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return; 2932af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 2942af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 2952af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 2962af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 2972af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 2982af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (context.checkUriPermission(uri, pid, uid, 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent.FLAG_GRANT_READ_URI_PERMISSION) 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3032af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Permission Denial: reading " 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ContentProvider.this.getClass().getName() 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " uri " + uri + " from pid=" + Binder.getCallingPid() 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid() 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " requires " + rperm; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException(msg); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3122af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn private boolean hasWritePermission(Uri uri) { 3132af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final int uid = Binder.getCallingUid(); 3142af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (uid == mMyUid) { 3152af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return true; 3162af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3172af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 3182af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final Context context = getContext(); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String wperm = getWritePermission(); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int pid = Binder.getCallingPid(); 321b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn if (mExported && (wperm == null 3222af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn || context.checkPermission(wperm, pid, uid) 323b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn == PackageManager.PERMISSION_GRANTED)) { 3242af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return true; 3252af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 3272af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn PathPermission[] pps = getPathPermissions(); 3282af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (pps != null) { 3292af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final String path = uri.getPath(); 3302af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn int i = pps.length; 3312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn while (i > 0) { 3322af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn i--; 3332af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final PathPermission pp = pps[i]; 3342af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn final String ppwperm = pp.getWritePermission(); 3352af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (ppwperm != null && pp.match(path)) { 3362af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (context.checkPermission(ppwperm, pid, uid) 3372af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn == PackageManager.PERMISSION_GRANTED) { 3382af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return true; 3392af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3402af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3412af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3422af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3432af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 3442af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (context.checkUriPermission(uri, pid, uid, 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 3472af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return true; 3482af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3492af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 3502af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return false; 3512af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 3522af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 3532af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn private void enforceWritePermission(Uri uri) { 3542af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn if (hasWritePermission(uri)) { 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3572af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Permission Denial: writing " 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ContentProvider.this.getClass().getName() 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " uri " + uri + " from pid=" + Binder.getCallingPid() 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid() 3622af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn + " requires " + getWritePermission(); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException(msg); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3696fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Retrieves the Context this provider is running in. Only available once 3706fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link #onCreate} has been called -- this will return null in the 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * constructor. 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Context getContext() { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mContext; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Change the permission required to read data from the content 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provider. This is normally set for you from its manifest information 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when the provider is first created. 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param permission Name of the permission required for read-only access. 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final void setReadPermission(String permission) { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReadPermission = permission; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the name of the permission required for read-only access to 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this content provider. This method can be called from multiple 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * threads, as described in 3927aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 3937aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final String getReadPermission() { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mReadPermission; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Change the permission required to read and write data in the content 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provider. This is normally set for you from its manifest information 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when the provider is first created. 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param permission Name of the permission required for read/write access. 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final void setWritePermission(String permission) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWritePermission = permission; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the name of the permission required for read/write access to 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this content provider. This method can be called from multiple 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * threads, as described in 4147aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 4157aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final String getWritePermission() { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mWritePermission; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4222af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * Change the path-based permission required to read and/or write data in 4232af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * the content provider. This is normally set for you from its manifest 4242af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * information when the provider is first created. 4252af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * 4262af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * @param permissions Array of path permission descriptions. 4272af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn */ 4282af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn protected final void setPathPermissions(PathPermission[] permissions) { 4292af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn mPathPermissions = permissions; 4302af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 4312af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 4322af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn /** 4332af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * Return the path-based permissions required for read and/or write access to 4342af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * this content provider. This method can be called from multiple 4352af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn * threads, as described in 4367aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 4377aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 4382af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn */ 4392af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn public final PathPermission[] getPathPermissions() { 4402af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn return mPathPermissions; 4412af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn } 4422af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn 4432af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn /** 4446fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Implement this to initialize your content provider on startup. 4456fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method is called for all registered content providers on the 4466fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * application main thread at application launch time. It must not perform 4476fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * lengthy operations, or application startup will be delayed. 4486fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 4496fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>You should defer nontrivial initialization (such as opening, 4506fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * upgrading, and scanning databases) until the content provider is used 4516fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * (via {@link #query}, {@link #insert}, etc). Deferred initialization 4526fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * keeps application startup fast, avoids unnecessary work if the provider 4536fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * turns out not to be needed, and stops database errors (such as a full 4546fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * disk) from halting application launch. 4556fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 45617876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper} 4576fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * is a helpful utility class that makes it easy to manage databases, 4586fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * and will automatically defer opening until first use. If you do use 4596fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * SQLiteOpenHelper, make sure to avoid calling 4606fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or 4616fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 4626fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * from this method. (Instead, override 4636fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the 4646fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * database when it is first opened.) 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the provider was successfully loaded, false otherwise 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract boolean onCreate(); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4706fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor /** 4716fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@inheritDoc} 4726fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method is always called on the application main thread, and must 4736fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * not perform lengthy operations. 4746fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 4756fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>The default content provider implementation does nothing. 4766fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Override this method to take appropriate action. 4776fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * (Content providers do not usually care about things like screen 4786fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * orientation, but may want to know about locale changes.) 4796fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor */ 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onConfigurationChanged(Configuration newConfig) { 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4826fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor 4836fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor /** 4846fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@inheritDoc} 4856fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method is always called on the application main thread, and must 4866fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * not perform lengthy operations. 4876fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 4886fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>The default content provider implementation does nothing. 4896fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Subclasses may override this method to take appropriate action. 4906fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor */ 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onLowMemory() { 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 494c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn public void onTrimMemory(int level) { 495c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn } 496c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4986fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Implement this to handle query requests from clients. 4996fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 5007aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 5017aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Example client call:<p> 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>// Request a specific record. 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Cursor managedCursor = managedQuery( 50681a476f654155df27aa564a4aebf931eab588e6dAlan Jones ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project projection, // Which columns to return. 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project null, // WHERE clause. 50981a476f654155df27aa564a4aebf931eab588e6dAlan Jones null, // WHERE clause value substitution 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project People.NAME + " ASC"); // Sort order.</pre> 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Example implementation:<p> 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>// SQLiteQueryBuilder is a helper class that creates the 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // proper SQL syntax for us. 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the table we're querying. 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project qBuilder.setTables(DATABASE_TABLE_NAME); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the query ends in a specific record number, we're 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // being asked for a specific record, so set the 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // WHERE clause in our query. 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make the query. 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor c = qBuilder.query(mDb, 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project projection, 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selection, 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectionArgs, 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project groupBy, 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project having, 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sortOrder); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.setNotificationUri(getContext().getContentResolver(), uri); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c;</pre> 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The URI to query. This will be the full URI sent by the client; 53881a476f654155df27aa564a4aebf931eab588e6dAlan Jones * if the client is requesting a specific record, the URI will end in a record number 53981a476f654155df27aa564a4aebf931eab588e6dAlan Jones * that the implementation should parse and add to a WHERE or HAVING clause, specifying 54081a476f654155df27aa564a4aebf931eab588e6dAlan Jones * that _id value. 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param projection The list of columns to put into the cursor. If 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * null all columns are included. 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selection A selection criteria to apply when filtering rows. 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If null then all rows are included. 54581a476f654155df27aa564a4aebf931eab588e6dAlan Jones * @param selectionArgs You may include ?s in selection, which will be replaced by 54681a476f654155df27aa564a4aebf931eab588e6dAlan Jones * the values from selectionArgs, in order that they appear in the selection. 54781a476f654155df27aa564a4aebf931eab588e6dAlan Jones * The values will be bound as Strings. 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sortOrder How the rows in the cursor should be sorted. 54981a476f654155df27aa564a4aebf931eab588e6dAlan Jones * If null then the provider is free to define the sort order. 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a Cursor or null. 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract Cursor query(Uri uri, String[] projection, 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String selection, String[] selectionArgs, String sortOrder); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5555bba632d877c2878384ff21566c8eb6a1a22f37bFred Quintana /** 5566fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Implement this to handle requests for the MIME type of the data at the 5576fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * given URI. The returned MIME type should start with 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>vnd.android.cursor.item</code> for a single record, 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or <code>vnd.android.cursor.dir/</code> for multiple items. 5606fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 5617aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 5627aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 564cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn * <p>Note that there are no permissions needed for an application to 565cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn * access this information; if your content provider requires read and/or 566cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn * write permissions, or is not exported, all applications can still call 567cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn * this method regardless of their access permissions. This allows them 568cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn * to retrieve the MIME type for a URI when dispatching intents. 569cca1f0e3476edd09cdd81b075a6b7780a2959b46Dianne Hackborn * 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri the URI to query. 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a MIME type string, or null if there is no type. 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract String getType(Uri uri); 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5766fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Implement this to handle requests to insert a new row. 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after inserting. 5796fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 5807aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 5817aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The content:// URI of the insertion request. 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values A set of column_name/value pairs to add to the database. 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The URI for the newly inserted item. 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract Uri insert(Uri uri, ContentValues values); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5896fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Override this to handle requests to insert a set of new rows, or the 5906fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * default implementation will iterate over the values and call 5916fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link #insert} on each of them. 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after inserting. 5946fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 5957aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 5967aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The content:// URI of the insertion request. 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values An array of sets of column_name/value pairs to add to the database. 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The number of values that were inserted. 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int bulkInsert(Uri uri, ContentValues[] values) { 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numValues = values.length; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numValues; i++) { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project insert(uri, values[i]); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return numValues; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6116fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * Implement this to handle requests to delete one or more rows. 6126fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * The implementation should apply the selection clause when performing 6136fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * deletion, allowing the operation to affect multiple rows in a directory. 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()} 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after deleting. 6166fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 6177aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 6187aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The implementation is responsible for parsing out a row ID at the end 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the URI, if a specific row is being deleted. That is, the client would 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pass in <code>content://contacts/people/22</code> and the implementation is 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * responsible for parsing the record number (22) when creating a SQL statement. 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The full URI to query, including a row ID (if a specific record is requested). 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selection An optional restriction to apply to rows when deleting. 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The number of rows affected. 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SQLException 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int delete(Uri uri, String selection, String[] selectionArgs); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 63317876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * Implement this to handle requests to update one or more rows. 6346fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * The implementation should update all rows matching the selection 6356fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * to set the columns according to the provided values map. 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after updating. 6386fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 6397aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 6407aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The URI to query. This can potentially have a record ID if this 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is an update request for a specific record. 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values A Bundle mapping from column names to new column values (NULL is a 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * valid value). 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selection An optional filter to match rows to update. 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of rows affected. 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int update(Uri uri, ContentValues values, String selection, 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] selectionArgs); 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 65317876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * Override this to handle requests to open a file blob. 6546fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * The default implementation always throws {@link FileNotFoundException}. 6556fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 6567aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 6577aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 6586fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 65917876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * <p>This method returns a ParcelFileDescriptor, which is returned directly 66017876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * to the caller. This way large data (such as images and documents) can be 6616fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * returned without copying the content. 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The returned ParcelFileDescriptor is owned by the caller, so it is 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * their responsibility to close it when done. That is, the implementation 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of this method should create a new ParcelFileDescriptor for each call. 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The URI whose file is to be opened. 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param mode Access mode for the file. May be "r" for read-only access, 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "rw" for read and write access, or "rwt" for read and write access 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that truncates any existing file. 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns a new ParcelFileDescriptor which you can use to access 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the file. 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws FileNotFoundException Throws FileNotFoundException if there is 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * no file associated with the given URI or the mode is invalid. 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SecurityException Throws SecurityException if the caller does 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have permission to access the file. 6796fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #openAssetFile(Uri, String) 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #openFileHelper(Uri, String) 6826fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor */ 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ParcelFileDescriptor openFile(Uri uri, String mode) 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FileNotFoundException { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FileNotFoundException("No files supported by provider at " 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + uri); 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6886fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is like {@link #openFile}, but can be implemented by providers 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that need to be able to return sub-sections of files, often assets 6926fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * inside of their .apk. 6936fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 6947aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 6957aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 6966fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 6976fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p>If you implement this, your clients must be able to deal with such 69817876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * file slices, either directly with 6996fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * methods. 7036fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 7046fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * <p class="note">If you are implementing this to return a full file, you 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should create the AssetFileDescriptor with 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 7076fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * applications that can not handle sub-sections of files.</p> 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The URI whose file is to be opened. 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param mode Access mode for the file. May be "r" for read-only access, 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "w" for write-only access (erasing whatever data is currently in 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the file), "wa" for write-only access to append to any existing data, 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "rw" for read and write access on any existing data, and "rwt" for read 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and write access that truncates any existing file. 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns a new AssetFileDescriptor which you can use to access 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the file. 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws FileNotFoundException Throws FileNotFoundException if there is 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * no file associated with the given URI or the mode is invalid. 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SecurityException Throws SecurityException if the caller does 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have permission to access the file. 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #openFile(Uri, String) 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #openFileHelper(Uri, String) 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AssetFileDescriptor openAssetFile(Uri uri, String mode) 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws FileNotFoundException { 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ParcelFileDescriptor fd = openFile(uri, mode); 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null; 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convenience for subclasses that wish to implement {@link #openFile} 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by looking up a column named "_data" at the given URI. 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri The URI to be opened. 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param mode The file mode. May be "r" for read-only access, 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "w" for write-only access (erasing whatever data is currently in 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the file), "wa" for write-only access to append to any existing data, 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "rw" for read and write access on any existing data, and "rwt" for read 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and write access that truncates any existing file. 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns a new ParcelFileDescriptor that can be used by the 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * client to access the file. 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final ParcelFileDescriptor openFileHelper(Uri uri, 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String mode) throws FileNotFoundException { 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor c = query(uri, new String[]{"_data"}, null, null, null); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = (c != null) ? c.getCount() : 0; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count != 1) { 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If there is not exactly one result, throw an appropriate 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // exception. 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != null) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.close(); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FileNotFoundException("No entry for " + uri); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FileNotFoundException("Multiple items at " + uri); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.moveToFirst(); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i = c.getColumnIndex("_data"); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String path = (i >= 0 ? c.getString(i) : null); 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.close(); 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (path == null) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FileNotFoundException("Column _data not found."); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int modeBits = ContentResolver.modeToMode(uri, mode); 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ParcelFileDescriptor.open(new File(path), modeBits); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 77623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Called by a client to determine the types of data streams that this 77723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * content provider supports for the given URI. The default implementation 77823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * returns null, meaning no types. If your content provider stores data 77923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * of a particular type, return that MIME type if it matches the given 78023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * mimeTypeFilter. If it can perform type conversions, return an array 78123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * of all supported MIME types that match mimeTypeFilter. 78223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 78323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param uri The data in the content provider being queried. 78423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param mimeTypeFilter The type of data the client desires. May be 78523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * a pattern, such as *\/* to retrieve all possible data types. 7863f00be5bd0b46e7937b68909baeff295b86215ccDianne Hackborn * @return Returns null if there are no possible data streams for the 78723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * given mimeTypeFilter. Otherwise returns an array of all available 78823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * concrete MIME types. 78923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 79023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @see #getType(Uri) 79123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @see #openTypedAssetFile(Uri, String, Bundle) 7921040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @see ClipDescription#compareMimeTypes(String, String) 79323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 79423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { 79523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return null; 79623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 79723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 79823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 79923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Called by a client to open a read-only stream containing data of a 80023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 80123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * except the file can only be read-only and the content provider may 80223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * perform data conversions to generate data of the desired type. 80323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 80423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * <p>The default implementation compares the given mimeType against the 80523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * result of {@link #getType(Uri)} and, if the match, simple calls 80623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * {@link #openAssetFile(Uri, String)}. 80723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 8081040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * <p>See {@link ClipData} for examples of the use and implementation 80923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * of this method. 81023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 81123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param uri The data in the content provider being queried. 81223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param mimeTypeFilter The type of data the client desires. May be 81323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * a pattern, such as *\/*, if the caller does not have specific type 81423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * requirements; in this case the content provider will pick its best 81523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * type matching the pattern. 81623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param opts Additional options from the client. The definitions of 81723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * these are specific to the content provider being called. 81823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 81923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @return Returns a new AssetFileDescriptor from which the client can 82023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * read data of the desired type. 82123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 82223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @throws FileNotFoundException Throws FileNotFoundException if there is 82323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * no file associated with the given URI or the mode is invalid. 82423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @throws SecurityException Throws SecurityException if the caller does 82523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * not have permission to access the data. 82623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @throws IllegalArgumentException Throws IllegalArgumentException if the 82723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * content provider does not support the requested MIME type. 82823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 82923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @see #getStreamTypes(Uri, String) 83023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @see #openAssetFile(Uri, String) 8311040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn * @see ClipDescription#compareMimeTypes(String, String) 83223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 83323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts) 83423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn throws FileNotFoundException { 83502dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn if ("*/*".equals(mimeTypeFilter)) { 83602dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn // If they can take anything, the untyped open call is good enough. 83702dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn return openAssetFile(uri, "r"); 83802dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn } 83923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn String baseType = getType(uri); 8401040dc465cbf5ca8f834a87c949e476abefa3f76Dianne Hackborn if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) { 84102dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn // Use old untyped open call if this provider has a type for this 84202dfd2630437ea5591942e503606fdeff29eb11eDianne Hackborn // URI and it matches the request. 84323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return openAssetFile(uri, "r"); 84423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 84523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter); 84623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 84723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 84823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 84923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Interface to write a stream of data to a pipe. Use with 85023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * {@link ContentProvider#openPipeHelper}. 85123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 85223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public interface PipeDataWriter<T> { 85323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 85423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Called from a background thread to stream data out to a pipe. 85523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Note that the pipe is blocking, so this thread can block on 85623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * writes for an arbitrary amount of time if the client is slow 85723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * at reading. 85823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 85923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param output The pipe where data should be written. This will be 86023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * closed for you upon returning from this function. 86123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param uri The URI whose data is to be written. 86223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param mimeType The desired type of data to be written. 86323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param opts Options supplied by caller. 86423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param args Your own custom arguments. 86523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 86623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, 86723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn Bundle opts, T args); 86823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 86923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 87023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 87123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * A helper function for implementing {@link #openTypedAssetFile}, for 87223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * creating a data pipe and background thread allowing you to stream 87323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * generated data back to the client. This function returns a new 87423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * ParcelFileDescriptor that should be returned to the caller (the caller 87523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * is responsible for closing it). 87623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * 87723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param uri The URI whose data is to be written. 87823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param mimeType The desired type of data to be written. 87923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param opts Options supplied by caller. 88023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param args Your own custom arguments. 88123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @param func Interface implementing the function that will actually 88223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * stream the data. 88323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * @return Returns a new ParcelFileDescriptor holding the read side of 88423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * the pipe. This should be returned to the caller for reading; the caller 88523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * is responsible for closing it when done. 88623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 88723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType, 88823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn final Bundle opts, final T args, final PipeDataWriter<T> func) 88923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn throws FileNotFoundException { 89023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn try { 89123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 89223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 89323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { 89423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn @Override 89523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn protected Object doInBackground(Object... params) { 89623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn func.writeDataToPipe(fds[1], uri, mimeType, opts, args); 89723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn try { 89823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn fds[1].close(); 89923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } catch (IOException e) { 90023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn Log.w(TAG, "Failure closing pipe", e); 90123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 90223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return null; 90323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 90423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn }; 9055d9d03a0234faa3cffd11502f973057045cafe82Dianne Hackborn task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null); 90623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 90723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn return fds[0]; 90823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } catch (IOException e) { 90923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn throw new FileNotFoundException("failure making pipe"); 91023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 91123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 91223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 91323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns true if this instance is a temporary content provider. 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if this instance is a temporary content provider 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean isTemporary() { 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the Binder object for this provider. 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the Binder object for this provider 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IContentProvider getIContentProvider() { 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTransport; 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * After being instantiated, this is called to tell the content provider 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * about itself. 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context The context this provider is running in 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param info Registered information about this content provider 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void attachInfo(Context context, ProviderInfo info) { 93923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /* 94023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * We may be using AsyncTask from binder threads. Make it init here 94123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * so its static handler is on the main thread. 94223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 94323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn AsyncTask.init(); 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Only allow it to be set once, so after the content service gives 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this to us clients can't change it. 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext == null) { 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 9512af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn mMyUid = Process.myUid(); 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (info != null) { 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setReadPermission(info.readPermission); 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setWritePermission(info.writePermission); 9552af632f87d487deaa5b2eb71341cfc4f0c0d1173Dianne Hackborn setPathPermissions(info.pathPermissions); 956b424b633bb3664bed924d2ea89036290a57eb2bdDianne Hackborn mExported = info.exported; 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentProvider.this.onCreate(); 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 961ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 962ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 96317876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * Override this to handle requests to perform a batch of operations, or the 96417876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * default implementation will iterate over the operations and call 96517876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * {@link ContentProviderOperation#apply} on each of them. 96617876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * If all calls to {@link ContentProviderOperation#apply} succeed 96717876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * then a {@link ContentProviderResult} array with as many 96817876aa586cc9acfb3e5b909c14b9e73537a1a8dDan Egnor * elements as there were operations will be returned. If any of the calls 9696fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * fail, it is up to the implementation how many of the others take effect. 9706fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * This method can be called from multiple threads, as described in 9717aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 9727aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * and Threads</a>. 9736fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * 974ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param operations the operations to apply 975ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return the results of the applications 9766fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * @throws OperationApplicationException thrown if any operation fails. 9776fcc0f073d8583cf1f485b9548cde41336a422beDan Egnor * @see ContentProviderOperation#apply 978ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 97903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 980ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throws OperationApplicationException { 98103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana final int numOperations = operations.size(); 98203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 98303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana for (int i = 0; i < numOperations; i++) { 98403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana results[i] = operations.get(i).apply(this, results, i); 985ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 986ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return results; 987ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 9881877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick 9891877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick /** 9902c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * Call a provider-defined method. This can be used to implement 991534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick * interfaces that are cheaper and/or unnatural for a table-like 992534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick * model. 9931877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick * 994534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick * @param method method name to call. Opaque to framework, but should not be null. 995534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick * @param arg provider-defined String argument. May be null. 996534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick * @param extras provider-defined Bundle argument. May be null. 997534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick * @return provider-defined return value. May be null. Null is also 998534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick * the default for providers which don't implement any call methods. 9991877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick */ 1000534c84c1ce19ae20ded249315c3c0558577eca6cBrad Fitzpatrick public Bundle call(String method, String arg, Bundle extras) { 10011877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick return null; 10021877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick } 10030c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori 10040c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori /** 10052c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * Implement this to shut down the ContentProvider instance. You can then 10062c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * invoke this method in unit tests. 10072c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * 10080c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori * <p> 10092c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * Android normally handles ContentProvider startup and shutdown 10102c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * automatically. You do not need to start up or shut down a 10112c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * ContentProvider. When you invoke a test method on a ContentProvider, 10122c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * however, a ContentProvider instance is started and keeps running after 10132c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * the test finishes, even if a succeeding test instantiates another 10142c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * ContentProvider. A conflict develops because the two instances are 10152c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * usually running against the same underlying data source (for example, an 10162c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * sqlite database). 10172c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * </p> 10180c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori * <p> 10192c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * Implementing shutDown() avoids this conflict by providing a way to 10202c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * terminate the ContentProvider. This method can also prevent memory leaks 10212c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * from multiple instantiations of the ContentProvider, and it can ensure 10222c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * unit test isolation by allowing you to completely clean up the test 10232c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * fixture before moving on to the next test. 10242c96a0c7acddb5f2e8027e9ffac73f82c297c4b9Manuel Roman * </p> 10250c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori */ 10260c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori public void shutdown() { 10270c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " + 10280c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori "connections are gracefully shutdown"); 10290c9e14aa4aa1370e01872dc05238f822f2dd552cVasu Nori } 10301877d0158b529663b8315482e7346a7bcaa96166Brad Fitzpatrick} 1031