ContentProvider.java revision 558459fe85f56f29a6ed6a4d0adb4a0bd6665884
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content;
18
19import android.content.pm.PackageManager;
20import android.content.pm.PathPermission;
21import android.content.pm.ProviderInfo;
22import android.content.res.AssetFileDescriptor;
23import android.content.res.Configuration;
24import android.database.Cursor;
25import android.database.SQLException;
26import android.net.Uri;
27import android.os.AsyncTask;
28import android.os.Binder;
29import android.os.Bundle;
30import android.os.ParcelFileDescriptor;
31import android.os.Process;
32import android.util.Log;
33
34import java.io.File;
35import java.io.FileNotFoundException;
36import java.io.IOException;
37import java.util.ArrayList;
38
39/**
40 * Content providers are one of the primary building blocks of Android applications, providing
41 * content to applications. They encapsulate data and provide it to applications through the single
42 * {@link ContentResolver} interface. A content provider is only required if you need to share
43 * data between multiple applications. For example, the contacts data is used by multiple
44 * applications and must be stored in a content provider. If you don't need to share data amongst
45 * multiple applications you can use a database directly via
46 * {@link android.database.sqlite.SQLiteDatabase}.
47 *
48 * <p>When a request is made via
49 * a {@link ContentResolver} the system inspects the authority of the given URI and passes the
50 * request to the content provider registered with the authority. The content provider can interpret
51 * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing
52 * URIs.</p>
53 *
54 * <p>The primary methods that need to be implemented are:
55 * <ul>
56 *   <li>{@link #onCreate} which is called to initialize the provider</li>
57 *   <li>{@link #query} which returns data to the caller</li>
58 *   <li>{@link #insert} which inserts new data into the content provider</li>
59 *   <li>{@link #update} which updates existing data in the content provider</li>
60 *   <li>{@link #delete} which deletes data from the content provider</li>
61 *   <li>{@link #getType} which returns the MIME type of data in the content provider</li>
62 * </ul></p>
63 *
64 * <p class="caution">Data access methods (such as {@link #insert} and
65 * {@link #update}) may be called from many threads at once, and must be thread-safe.
66 * Other methods (such as {@link #onCreate}) are only called from the application
67 * main thread, and must avoid performing lengthy operations.  See the method
68 * descriptions for their expected thread behavior.</p>
69 *
70 * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate
71 * ContentProvider instance, so subclasses don't have to worry about the details of
72 * cross-process calls.</p>
73 *
74 * <div class="special reference">
75 * <h3>Developer Guides</h3>
76 * <p>For more information about using content providers, read the
77 * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
78 * developer guide.</p>
79 */
80public abstract class ContentProvider implements ComponentCallbacks2 {
81    private static final String TAG = "ContentProvider";
82
83    /*
84     * Note: if you add methods to ContentProvider, you must add similar methods to
85     *       MockContentProvider.
86     */
87
88    private Context mContext = null;
89    private int mMyUid;
90    private String mReadPermission;
91    private String mWritePermission;
92    private PathPermission[] mPathPermissions;
93    private boolean mExported;
94
95    private Transport mTransport = new Transport();
96
97    /**
98     * Construct a ContentProvider instance.  Content providers must be
99     * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared
100     * in the manifest</a>, accessed with {@link ContentResolver}, and created
101     * automatically by the system, so applications usually do not create
102     * ContentProvider instances directly.
103     *
104     * <p>At construction time, the object is uninitialized, and most fields and
105     * methods are unavailable.  Subclasses should initialize themselves in
106     * {@link #onCreate}, not the constructor.
107     *
108     * <p>Content providers are created on the application main thread at
109     * application launch time.  The constructor must not perform lengthy
110     * operations, or application startup will be delayed.
111     */
112    public ContentProvider() {
113    }
114
115    /**
116     * Constructor just for mocking.
117     *
118     * @param context A Context object which should be some mock instance (like the
119     * instance of {@link android.test.mock.MockContext}).
120     * @param readPermission The read permision you want this instance should have in the
121     * test, which is available via {@link #getReadPermission()}.
122     * @param writePermission The write permission you want this instance should have
123     * in the test, which is available via {@link #getWritePermission()}.
124     * @param pathPermissions The PathPermissions you want this instance should have
125     * in the test, which is available via {@link #getPathPermissions()}.
126     * @hide
127     */
128    public ContentProvider(
129            Context context,
130            String readPermission,
131            String writePermission,
132            PathPermission[] pathPermissions) {
133        mContext = context;
134        mReadPermission = readPermission;
135        mWritePermission = writePermission;
136        mPathPermissions = pathPermissions;
137    }
138
139    /**
140     * Given an IContentProvider, try to coerce it back to the real
141     * ContentProvider object if it is running in the local process.  This can
142     * be used if you know you are running in the same process as a provider,
143     * and want to get direct access to its implementation details.  Most
144     * clients should not nor have a reason to use it.
145     *
146     * @param abstractInterface The ContentProvider interface that is to be
147     *              coerced.
148     * @return If the IContentProvider is non-null and local, returns its actual
149     * ContentProvider instance.  Otherwise returns null.
150     * @hide
151     */
152    public static ContentProvider coerceToLocalContentProvider(
153            IContentProvider abstractInterface) {
154        if (abstractInterface instanceof Transport) {
155            return ((Transport)abstractInterface).getContentProvider();
156        }
157        return null;
158    }
159
160    /**
161     * Binder object that deals with remoting.
162     *
163     * @hide
164     */
165    class Transport extends ContentProviderNative {
166        ContentProvider getContentProvider() {
167            return ContentProvider.this;
168        }
169
170        @Override
171        public String getProviderName() {
172            return getContentProvider().getClass().getName();
173        }
174
175        public Cursor query(Uri uri, String[] projection,
176                String selection, String[] selectionArgs, String sortOrder) {
177            enforceReadPermission(uri);
178            return ContentProvider.this.query(uri, projection, selection,
179                    selectionArgs, sortOrder);
180        }
181
182        public String getType(Uri uri) {
183            return ContentProvider.this.getType(uri);
184        }
185
186
187        public Uri insert(Uri uri, ContentValues initialValues) {
188            enforceWritePermission(uri);
189            return ContentProvider.this.insert(uri, initialValues);
190        }
191
192        public int bulkInsert(Uri uri, ContentValues[] initialValues) {
193            enforceWritePermission(uri);
194            return ContentProvider.this.bulkInsert(uri, initialValues);
195        }
196
197        public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
198                throws OperationApplicationException {
199            for (ContentProviderOperation operation : operations) {
200                if (operation.isReadOperation()) {
201                    enforceReadPermission(operation.getUri());
202                }
203
204                if (operation.isWriteOperation()) {
205                    enforceWritePermission(operation.getUri());
206                }
207            }
208            return ContentProvider.this.applyBatch(operations);
209        }
210
211        public int delete(Uri uri, String selection, String[] selectionArgs) {
212            enforceWritePermission(uri);
213            return ContentProvider.this.delete(uri, selection, selectionArgs);
214        }
215
216        public int update(Uri uri, ContentValues values, String selection,
217                String[] selectionArgs) {
218            enforceWritePermission(uri);
219            return ContentProvider.this.update(uri, values, selection, selectionArgs);
220        }
221
222        public ParcelFileDescriptor openFile(Uri uri, String mode)
223                throws FileNotFoundException {
224            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
225            else enforceReadPermission(uri);
226            return ContentProvider.this.openFile(uri, mode);
227        }
228
229        public AssetFileDescriptor openAssetFile(Uri uri, String mode)
230                throws FileNotFoundException {
231            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
232            else enforceReadPermission(uri);
233            return ContentProvider.this.openAssetFile(uri, mode);
234        }
235
236        public Bundle call(String method, String arg, Bundle extras) {
237            return ContentProvider.this.call(method, arg, extras);
238        }
239
240        @Override
241        public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
242            return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
243        }
244
245        @Override
246        public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeType, Bundle opts)
247                throws FileNotFoundException {
248            enforceReadPermission(uri);
249            return ContentProvider.this.openTypedAssetFile(uri, mimeType, opts);
250        }
251
252        private void enforceReadPermission(Uri uri) {
253            final int uid = Binder.getCallingUid();
254            if (uid == mMyUid) {
255                return;
256            }
257
258            final Context context = getContext();
259            final String rperm = getReadPermission();
260            final int pid = Binder.getCallingPid();
261            if (mExported && (rperm == null
262                    || context.checkPermission(rperm, pid, uid)
263                    == PackageManager.PERMISSION_GRANTED)) {
264                return;
265            }
266
267            PathPermission[] pps = getPathPermissions();
268            if (pps != null) {
269                final String path = uri.getPath();
270                int i = pps.length;
271                while (i > 0) {
272                    i--;
273                    final PathPermission pp = pps[i];
274                    final String pprperm = pp.getReadPermission();
275                    if (pprperm != null && pp.match(path)) {
276                        if (context.checkPermission(pprperm, pid, uid)
277                                == PackageManager.PERMISSION_GRANTED) {
278                            return;
279                        }
280                    }
281                }
282            }
283
284            if (context.checkUriPermission(uri, pid, uid,
285                    Intent.FLAG_GRANT_READ_URI_PERMISSION)
286                    == PackageManager.PERMISSION_GRANTED) {
287                return;
288            }
289
290            String msg = "Permission Denial: reading "
291                    + ContentProvider.this.getClass().getName()
292                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
293                    + ", uid=" + Binder.getCallingUid()
294                    + " requires " + rperm;
295            throw new SecurityException(msg);
296        }
297
298        private boolean hasWritePermission(Uri uri) {
299            final int uid = Binder.getCallingUid();
300            if (uid == mMyUid) {
301                return true;
302            }
303
304            final Context context = getContext();
305            final String wperm = getWritePermission();
306            final int pid = Binder.getCallingPid();
307            if (mExported && (wperm == null
308                    || context.checkPermission(wperm, pid, uid)
309                    == PackageManager.PERMISSION_GRANTED)) {
310                return true;
311            }
312
313            PathPermission[] pps = getPathPermissions();
314            if (pps != null) {
315                final String path = uri.getPath();
316                int i = pps.length;
317                while (i > 0) {
318                    i--;
319                    final PathPermission pp = pps[i];
320                    final String ppwperm = pp.getWritePermission();
321                    if (ppwperm != null && pp.match(path)) {
322                        if (context.checkPermission(ppwperm, pid, uid)
323                                == PackageManager.PERMISSION_GRANTED) {
324                            return true;
325                        }
326                    }
327                }
328            }
329
330            if (context.checkUriPermission(uri, pid, uid,
331                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
332                    == PackageManager.PERMISSION_GRANTED) {
333                return true;
334            }
335
336            return false;
337        }
338
339        private void enforceWritePermission(Uri uri) {
340            if (hasWritePermission(uri)) {
341                return;
342            }
343
344            String msg = "Permission Denial: writing "
345                    + ContentProvider.this.getClass().getName()
346                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
347                    + ", uid=" + Binder.getCallingUid()
348                    + " requires " + getWritePermission();
349            throw new SecurityException(msg);
350        }
351    }
352
353
354    /**
355     * Retrieves the Context this provider is running in.  Only available once
356     * {@link #onCreate} has been called -- this will return null in the
357     * constructor.
358     */
359    public final Context getContext() {
360        return mContext;
361    }
362
363    /**
364     * Change the permission required to read data from the content
365     * provider.  This is normally set for you from its manifest information
366     * when the provider is first created.
367     *
368     * @param permission Name of the permission required for read-only access.
369     */
370    protected final void setReadPermission(String permission) {
371        mReadPermission = permission;
372    }
373
374    /**
375     * Return the name of the permission required for read-only access to
376     * this content provider.  This method can be called from multiple
377     * threads, as described in
378     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
379     * and Threads</a>.
380     */
381    public final String getReadPermission() {
382        return mReadPermission;
383    }
384
385    /**
386     * Change the permission required to read and write data in the content
387     * provider.  This is normally set for you from its manifest information
388     * when the provider is first created.
389     *
390     * @param permission Name of the permission required for read/write access.
391     */
392    protected final void setWritePermission(String permission) {
393        mWritePermission = permission;
394    }
395
396    /**
397     * Return the name of the permission required for read/write access to
398     * this content provider.  This method can be called from multiple
399     * threads, as described in
400     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
401     * and Threads</a>.
402     */
403    public final String getWritePermission() {
404        return mWritePermission;
405    }
406
407    /**
408     * Change the path-based permission required to read and/or write data in
409     * the content provider.  This is normally set for you from its manifest
410     * information when the provider is first created.
411     *
412     * @param permissions Array of path permission descriptions.
413     */
414    protected final void setPathPermissions(PathPermission[] permissions) {
415        mPathPermissions = permissions;
416    }
417
418    /**
419     * Return the path-based permissions required for read and/or write access to
420     * this content provider.  This method can be called from multiple
421     * threads, as described in
422     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
423     * and Threads</a>.
424     */
425    public final PathPermission[] getPathPermissions() {
426        return mPathPermissions;
427    }
428
429    /**
430     * Implement this to initialize your content provider on startup.
431     * This method is called for all registered content providers on the
432     * application main thread at application launch time.  It must not perform
433     * lengthy operations, or application startup will be delayed.
434     *
435     * <p>You should defer nontrivial initialization (such as opening,
436     * upgrading, and scanning databases) until the content provider is used
437     * (via {@link #query}, {@link #insert}, etc).  Deferred initialization
438     * keeps application startup fast, avoids unnecessary work if the provider
439     * turns out not to be needed, and stops database errors (such as a full
440     * disk) from halting application launch.
441     *
442     * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper}
443     * is a helpful utility class that makes it easy to manage databases,
444     * and will automatically defer opening until first use.  If you do use
445     * SQLiteOpenHelper, make sure to avoid calling
446     * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or
447     * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase}
448     * from this method.  (Instead, override
449     * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the
450     * database when it is first opened.)
451     *
452     * @return true if the provider was successfully loaded, false otherwise
453     */
454    public abstract boolean onCreate();
455
456    /**
457     * {@inheritDoc}
458     * This method is always called on the application main thread, and must
459     * not perform lengthy operations.
460     *
461     * <p>The default content provider implementation does nothing.
462     * Override this method to take appropriate action.
463     * (Content providers do not usually care about things like screen
464     * orientation, but may want to know about locale changes.)
465     */
466    public void onConfigurationChanged(Configuration newConfig) {
467    }
468
469    /**
470     * {@inheritDoc}
471     * This method is always called on the application main thread, and must
472     * not perform lengthy operations.
473     *
474     * <p>The default content provider implementation does nothing.
475     * Subclasses may override this method to take appropriate action.
476     */
477    public void onLowMemory() {
478    }
479
480    public void onTrimMemory(int level) {
481    }
482
483    /**
484     * Implement this to handle query requests from clients.
485     * This method can be called from multiple threads, as described in
486     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
487     * and Threads</a>.
488     * <p>
489     * Example client call:<p>
490     * <pre>// Request a specific record.
491     * Cursor managedCursor = managedQuery(
492                ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
493                projection,    // Which columns to return.
494                null,          // WHERE clause.
495                null,          // WHERE clause value substitution
496                People.NAME + " ASC");   // Sort order.</pre>
497     * Example implementation:<p>
498     * <pre>// SQLiteQueryBuilder is a helper class that creates the
499        // proper SQL syntax for us.
500        SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
501
502        // Set the table we're querying.
503        qBuilder.setTables(DATABASE_TABLE_NAME);
504
505        // If the query ends in a specific record number, we're
506        // being asked for a specific record, so set the
507        // WHERE clause in our query.
508        if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
509            qBuilder.appendWhere("_id=" + uri.getPathLeafId());
510        }
511
512        // Make the query.
513        Cursor c = qBuilder.query(mDb,
514                projection,
515                selection,
516                selectionArgs,
517                groupBy,
518                having,
519                sortOrder);
520        c.setNotificationUri(getContext().getContentResolver(), uri);
521        return c;</pre>
522     *
523     * @param uri The URI to query. This will be the full URI sent by the client;
524     *      if the client is requesting a specific record, the URI will end in a record number
525     *      that the implementation should parse and add to a WHERE or HAVING clause, specifying
526     *      that _id value.
527     * @param projection The list of columns to put into the cursor. If
528     *      null all columns are included.
529     * @param selection A selection criteria to apply when filtering rows.
530     *      If null then all rows are included.
531     * @param selectionArgs You may include ?s in selection, which will be replaced by
532     *      the values from selectionArgs, in order that they appear in the selection.
533     *      The values will be bound as Strings.
534     * @param sortOrder How the rows in the cursor should be sorted.
535     *      If null then the provider is free to define the sort order.
536     * @return a Cursor or null.
537     */
538    public abstract Cursor query(Uri uri, String[] projection,
539            String selection, String[] selectionArgs, String sortOrder);
540
541    /**
542     * Implement this to handle requests for the MIME type of the data at the
543     * given URI.  The returned MIME type should start with
544     * <code>vnd.android.cursor.item</code> for a single record,
545     * or <code>vnd.android.cursor.dir/</code> for multiple items.
546     * This method can be called from multiple threads, as described in
547     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
548     * and Threads</a>.
549     *
550     * <p>Note that there are no permissions needed for an application to
551     * access this information; if your content provider requires read and/or
552     * write permissions, or is not exported, all applications can still call
553     * this method regardless of their access permissions.  This allows them
554     * to retrieve the MIME type for a URI when dispatching intents.
555     *
556     * @param uri the URI to query.
557     * @return a MIME type string, or null if there is no type.
558     */
559    public abstract String getType(Uri uri);
560
561    /**
562     * Implement this to handle requests to insert a new row.
563     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
564     * after inserting.
565     * This method can be called from multiple threads, as described in
566     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
567     * and Threads</a>.
568     * @param uri The content:// URI of the insertion request.
569     * @param values A set of column_name/value pairs to add to the database.
570     * @return The URI for the newly inserted item.
571     */
572    public abstract Uri insert(Uri uri, ContentValues values);
573
574    /**
575     * Override this to handle requests to insert a set of new rows, or the
576     * default implementation will iterate over the values and call
577     * {@link #insert} on each of them.
578     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
579     * after inserting.
580     * This method can be called from multiple threads, as described in
581     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
582     * and Threads</a>.
583     *
584     * @param uri The content:// URI of the insertion request.
585     * @param values An array of sets of column_name/value pairs to add to the database.
586     * @return The number of values that were inserted.
587     */
588    public int bulkInsert(Uri uri, ContentValues[] values) {
589        int numValues = values.length;
590        for (int i = 0; i < numValues; i++) {
591            insert(uri, values[i]);
592        }
593        return numValues;
594    }
595
596    /**
597     * Implement this to handle requests to delete one or more rows.
598     * The implementation should apply the selection clause when performing
599     * deletion, allowing the operation to affect multiple rows in a directory.
600     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
601     * after deleting.
602     * This method can be called from multiple threads, as described in
603     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
604     * and Threads</a>.
605     *
606     * <p>The implementation is responsible for parsing out a row ID at the end
607     * of the URI, if a specific row is being deleted. That is, the client would
608     * pass in <code>content://contacts/people/22</code> and the implementation is
609     * responsible for parsing the record number (22) when creating a SQL statement.
610     *
611     * @param uri The full URI to query, including a row ID (if a specific record is requested).
612     * @param selection An optional restriction to apply to rows when deleting.
613     * @return The number of rows affected.
614     * @throws SQLException
615     */
616    public abstract int delete(Uri uri, String selection, String[] selectionArgs);
617
618    /**
619     * Implement this to handle requests to update one or more rows.
620     * The implementation should update all rows matching the selection
621     * to set the columns according to the provided values map.
622     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
623     * after updating.
624     * This method can be called from multiple threads, as described in
625     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
626     * and Threads</a>.
627     *
628     * @param uri The URI to query. This can potentially have a record ID if this
629     * is an update request for a specific record.
630     * @param values A Bundle mapping from column names to new column values (NULL is a
631     *               valid value).
632     * @param selection An optional filter to match rows to update.
633     * @return the number of rows affected.
634     */
635    public abstract int update(Uri uri, ContentValues values, String selection,
636            String[] selectionArgs);
637
638    /**
639     * Override this to handle requests to open a file blob.
640     * The default implementation always throws {@link FileNotFoundException}.
641     * This method can be called from multiple threads, as described in
642     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
643     * and Threads</a>.
644     *
645     * <p>This method returns a ParcelFileDescriptor, which is returned directly
646     * to the caller.  This way large data (such as images and documents) can be
647     * returned without copying the content.
648     *
649     * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
650     * their responsibility to close it when done.  That is, the implementation
651     * of this method should create a new ParcelFileDescriptor for each call.
652     *
653     * @param uri The URI whose file is to be opened.
654     * @param mode Access mode for the file.  May be "r" for read-only access,
655     * "rw" for read and write access, or "rwt" for read and write access
656     * that truncates any existing file.
657     *
658     * @return Returns a new ParcelFileDescriptor which you can use to access
659     * the file.
660     *
661     * @throws FileNotFoundException Throws FileNotFoundException if there is
662     * no file associated with the given URI or the mode is invalid.
663     * @throws SecurityException Throws SecurityException if the caller does
664     * not have permission to access the file.
665     *
666     * @see #openAssetFile(Uri, String)
667     * @see #openFileHelper(Uri, String)
668     */
669    public ParcelFileDescriptor openFile(Uri uri, String mode)
670            throws FileNotFoundException {
671        throw new FileNotFoundException("No files supported by provider at "
672                + uri);
673    }
674
675    /**
676     * This is like {@link #openFile}, but can be implemented by providers
677     * that need to be able to return sub-sections of files, often assets
678     * inside of their .apk.
679     * This method can be called from multiple threads, as described in
680     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
681     * and Threads</a>.
682     *
683     * <p>If you implement this, your clients must be able to deal with such
684     * file slices, either directly with
685     * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
686     * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
687     * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
688     * methods.
689     *
690     * <p class="note">If you are implementing this to return a full file, you
691     * should create the AssetFileDescriptor with
692     * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
693     * applications that can not handle sub-sections of files.</p>
694     *
695     * @param uri The URI whose file is to be opened.
696     * @param mode Access mode for the file.  May be "r" for read-only access,
697     * "w" for write-only access (erasing whatever data is currently in
698     * the file), "wa" for write-only access to append to any existing data,
699     * "rw" for read and write access on any existing data, and "rwt" for read
700     * and write access that truncates any existing file.
701     *
702     * @return Returns a new AssetFileDescriptor which you can use to access
703     * the file.
704     *
705     * @throws FileNotFoundException Throws FileNotFoundException if there is
706     * no file associated with the given URI or the mode is invalid.
707     * @throws SecurityException Throws SecurityException if the caller does
708     * not have permission to access the file.
709     *
710     * @see #openFile(Uri, String)
711     * @see #openFileHelper(Uri, String)
712     */
713    public AssetFileDescriptor openAssetFile(Uri uri, String mode)
714            throws FileNotFoundException {
715        ParcelFileDescriptor fd = openFile(uri, mode);
716        return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
717    }
718
719    /**
720     * Convenience for subclasses that wish to implement {@link #openFile}
721     * by looking up a column named "_data" at the given URI.
722     *
723     * @param uri The URI to be opened.
724     * @param mode The file mode.  May be "r" for read-only access,
725     * "w" for write-only access (erasing whatever data is currently in
726     * the file), "wa" for write-only access to append to any existing data,
727     * "rw" for read and write access on any existing data, and "rwt" for read
728     * and write access that truncates any existing file.
729     *
730     * @return Returns a new ParcelFileDescriptor that can be used by the
731     * client to access the file.
732     */
733    protected final ParcelFileDescriptor openFileHelper(Uri uri,
734            String mode) throws FileNotFoundException {
735        Cursor c = query(uri, new String[]{"_data"}, null, null, null);
736        int count = (c != null) ? c.getCount() : 0;
737        if (count != 1) {
738            // If there is not exactly one result, throw an appropriate
739            // exception.
740            if (c != null) {
741                c.close();
742            }
743            if (count == 0) {
744                throw new FileNotFoundException("No entry for " + uri);
745            }
746            throw new FileNotFoundException("Multiple items at " + uri);
747        }
748
749        c.moveToFirst();
750        int i = c.getColumnIndex("_data");
751        String path = (i >= 0 ? c.getString(i) : null);
752        c.close();
753        if (path == null) {
754            throw new FileNotFoundException("Column _data not found.");
755        }
756
757        int modeBits = ContentResolver.modeToMode(uri, mode);
758        return ParcelFileDescriptor.open(new File(path), modeBits);
759    }
760
761    /**
762     * Called by a client to determine the types of data streams that this
763     * content provider supports for the given URI.  The default implementation
764     * returns null, meaning no types.  If your content provider stores data
765     * of a particular type, return that MIME type if it matches the given
766     * mimeTypeFilter.  If it can perform type conversions, return an array
767     * of all supported MIME types that match mimeTypeFilter.
768     *
769     * @param uri The data in the content provider being queried.
770     * @param mimeTypeFilter The type of data the client desires.  May be
771     * a pattern, such as *\/* to retrieve all possible data types.
772     * @return Returns null if there are no possible data streams for the
773     * given mimeTypeFilter.  Otherwise returns an array of all available
774     * concrete MIME types.
775     *
776     * @see #getType(Uri)
777     * @see #openTypedAssetFile(Uri, String, Bundle)
778     * @see ClipDescription#compareMimeTypes(String, String)
779     */
780    public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
781        return null;
782    }
783
784    /**
785     * Called by a client to open a read-only stream containing data of a
786     * particular MIME type.  This is like {@link #openAssetFile(Uri, String)},
787     * except the file can only be read-only and the content provider may
788     * perform data conversions to generate data of the desired type.
789     *
790     * <p>The default implementation compares the given mimeType against the
791     * result of {@link #getType(Uri)} and, if the match, simple calls
792     * {@link #openAssetFile(Uri, String)}.
793     *
794     * <p>See {@link ClipData} for examples of the use and implementation
795     * of this method.
796     *
797     * @param uri The data in the content provider being queried.
798     * @param mimeTypeFilter The type of data the client desires.  May be
799     * a pattern, such as *\/*, if the caller does not have specific type
800     * requirements; in this case the content provider will pick its best
801     * type matching the pattern.
802     * @param opts Additional options from the client.  The definitions of
803     * these are specific to the content provider being called.
804     *
805     * @return Returns a new AssetFileDescriptor from which the client can
806     * read data of the desired type.
807     *
808     * @throws FileNotFoundException Throws FileNotFoundException if there is
809     * no file associated with the given URI or the mode is invalid.
810     * @throws SecurityException Throws SecurityException if the caller does
811     * not have permission to access the data.
812     * @throws IllegalArgumentException Throws IllegalArgumentException if the
813     * content provider does not support the requested MIME type.
814     *
815     * @see #getStreamTypes(Uri, String)
816     * @see #openAssetFile(Uri, String)
817     * @see ClipDescription#compareMimeTypes(String, String)
818     */
819    public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
820            throws FileNotFoundException {
821        if ("*/*".equals(mimeTypeFilter)) {
822            // If they can take anything, the untyped open call is good enough.
823            return openAssetFile(uri, "r");
824        }
825        String baseType = getType(uri);
826        if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) {
827            // Use old untyped open call if this provider has a type for this
828            // URI and it matches the request.
829            return openAssetFile(uri, "r");
830        }
831        throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter);
832    }
833
834    /**
835     * Interface to write a stream of data to a pipe.  Use with
836     * {@link ContentProvider#openPipeHelper}.
837     */
838    public interface PipeDataWriter<T> {
839        /**
840         * Called from a background thread to stream data out to a pipe.
841         * Note that the pipe is blocking, so this thread can block on
842         * writes for an arbitrary amount of time if the client is slow
843         * at reading.
844         *
845         * @param output The pipe where data should be written.  This will be
846         * closed for you upon returning from this function.
847         * @param uri The URI whose data is to be written.
848         * @param mimeType The desired type of data to be written.
849         * @param opts Options supplied by caller.
850         * @param args Your own custom arguments.
851         */
852        public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
853                Bundle opts, T args);
854    }
855
856    /**
857     * A helper function for implementing {@link #openTypedAssetFile}, for
858     * creating a data pipe and background thread allowing you to stream
859     * generated data back to the client.  This function returns a new
860     * ParcelFileDescriptor that should be returned to the caller (the caller
861     * is responsible for closing it).
862     *
863     * @param uri The URI whose data is to be written.
864     * @param mimeType The desired type of data to be written.
865     * @param opts Options supplied by caller.
866     * @param args Your own custom arguments.
867     * @param func Interface implementing the function that will actually
868     * stream the data.
869     * @return Returns a new ParcelFileDescriptor holding the read side of
870     * the pipe.  This should be returned to the caller for reading; the caller
871     * is responsible for closing it when done.
872     */
873    public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType,
874            final Bundle opts, final T args, final PipeDataWriter<T> func)
875            throws FileNotFoundException {
876        try {
877            final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
878
879            AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
880                @Override
881                protected Object doInBackground(Object... params) {
882                    func.writeDataToPipe(fds[1], uri, mimeType, opts, args);
883                    try {
884                        fds[1].close();
885                    } catch (IOException e) {
886                        Log.w(TAG, "Failure closing pipe", e);
887                    }
888                    return null;
889                }
890            };
891            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null);
892
893            return fds[0];
894        } catch (IOException e) {
895            throw new FileNotFoundException("failure making pipe");
896        }
897    }
898
899    /**
900     * Returns true if this instance is a temporary content provider.
901     * @return true if this instance is a temporary content provider
902     */
903    protected boolean isTemporary() {
904        return false;
905    }
906
907    /**
908     * Returns the Binder object for this provider.
909     *
910     * @return the Binder object for this provider
911     * @hide
912     */
913    public IContentProvider getIContentProvider() {
914        return mTransport;
915    }
916
917    /**
918     * After being instantiated, this is called to tell the content provider
919     * about itself.
920     *
921     * @param context The context this provider is running in
922     * @param info Registered information about this content provider
923     */
924    public void attachInfo(Context context, ProviderInfo info) {
925        /*
926         * We may be using AsyncTask from binder threads.  Make it init here
927         * so its static handler is on the main thread.
928         */
929        AsyncTask.init();
930
931        /*
932         * Only allow it to be set once, so after the content service gives
933         * this to us clients can't change it.
934         */
935        if (mContext == null) {
936            mContext = context;
937            mMyUid = Process.myUid();
938            if (info != null) {
939                setReadPermission(info.readPermission);
940                setWritePermission(info.writePermission);
941                setPathPermissions(info.pathPermissions);
942                mExported = info.exported;
943            }
944            ContentProvider.this.onCreate();
945        }
946    }
947
948    /**
949     * Override this to handle requests to perform a batch of operations, or the
950     * default implementation will iterate over the operations and call
951     * {@link ContentProviderOperation#apply} on each of them.
952     * If all calls to {@link ContentProviderOperation#apply} succeed
953     * then a {@link ContentProviderResult} array with as many
954     * elements as there were operations will be returned.  If any of the calls
955     * fail, it is up to the implementation how many of the others take effect.
956     * This method can be called from multiple threads, as described in
957     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
958     * and Threads</a>.
959     *
960     * @param operations the operations to apply
961     * @return the results of the applications
962     * @throws OperationApplicationException thrown if any operation fails.
963     * @see ContentProviderOperation#apply
964     */
965    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
966            throws OperationApplicationException {
967        final int numOperations = operations.size();
968        final ContentProviderResult[] results = new ContentProviderResult[numOperations];
969        for (int i = 0; i < numOperations; i++) {
970            results[i] = operations.get(i).apply(this, results, i);
971        }
972        return results;
973    }
974
975    /**
976     * Call a provider-defined method.  This can be used to implement
977     * interfaces that are cheaper and/or unnatural for a table-like
978     * model.
979     *
980     * @param method method name to call.  Opaque to framework, but should not be null.
981     * @param arg provider-defined String argument.  May be null.
982     * @param extras provider-defined Bundle argument.  May be null.
983     * @return provider-defined return value.  May be null.  Null is also
984     *   the default for providers which don't implement any call methods.
985     */
986    public Bundle call(String method, String arg, Bundle extras) {
987        return null;
988    }
989
990    /**
991     * Implement this to shut down the ContentProvider instance. You can then
992     * invoke this method in unit tests.
993     *
994     * <p>
995     * Android normally handles ContentProvider startup and shutdown
996     * automatically. You do not need to start up or shut down a
997     * ContentProvider. When you invoke a test method on a ContentProvider,
998     * however, a ContentProvider instance is started and keeps running after
999     * the test finishes, even if a succeeding test instantiates another
1000     * ContentProvider. A conflict develops because the two instances are
1001     * usually running against the same underlying data source (for example, an
1002     * sqlite database).
1003     * </p>
1004     * <p>
1005     * Implementing shutDown() avoids this conflict by providing a way to
1006     * terminate the ContentProvider. This method can also prevent memory leaks
1007     * from multiple instantiations of the ContentProvider, and it can ensure
1008     * unit test isolation by allowing you to completely clean up the test
1009     * fixture before moving on to the next test.
1010     * </p>
1011     */
1012    public void shutdown() {
1013        Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " +
1014                "connections are gracefully shutdown");
1015    }
1016}
1017