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