blob: b9121c7f51bb5747d8bdc7a9c2ca47ba5d7fb072 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Jeff Sharkey110a6b62012-03-12 11:12:41 -070019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20
Dianne Hackborn35654b62013-01-14 17:38:02 -080021import android.app.AppOpsManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070022import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.pm.ProviderInfo;
24import android.content.res.AssetFileDescriptor;
25import android.content.res.Configuration;
26import android.database.Cursor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.database.SQLException;
28import android.net.Uri;
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070029import android.os.AsyncTask;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.os.Binder;
Brad Fitzpatrick1877d012010-03-04 17:48:13 -080031import android.os.Bundle;
Jeff Browna7771df2012-05-07 20:06:46 -070032import android.os.CancellationSignal;
33import android.os.ICancellationSignal;
34import android.os.OperationCanceledException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.ParcelFileDescriptor;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070036import android.os.Process;
Jeff Brown75ea64f2012-01-25 19:37:13 -080037import android.os.RemoteException;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070038import android.os.UserHandle;
Vasu Nori0c9e14a2010-08-04 13:31:48 -070039import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
41import java.io.File;
Marco Nelissen18cb2872011-11-15 11:19:53 -080042import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import java.io.FileNotFoundException;
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070044import java.io.IOException;
Marco Nelissen18cb2872011-11-15 11:19:53 -080045import java.io.PrintWriter;
Fred Quintana03d94902009-05-22 14:23:31 -070046import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047
48/**
49 * Content providers are one of the primary building blocks of Android applications, providing
50 * content to applications. They encapsulate data and provide it to applications through the single
51 * {@link ContentResolver} interface. A content provider is only required if you need to share
52 * data between multiple applications. For example, the contacts data is used by multiple
53 * applications and must be stored in a content provider. If you don't need to share data amongst
54 * multiple applications you can use a database directly via
55 * {@link android.database.sqlite.SQLiteDatabase}.
56 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 * <p>When a request is made via
58 * a {@link ContentResolver} the system inspects the authority of the given URI and passes the
59 * request to the content provider registered with the authority. The content provider can interpret
60 * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing
61 * URIs.</p>
62 *
63 * <p>The primary methods that need to be implemented are:
64 * <ul>
Dan Egnor6fcc0f0732010-07-27 16:32:17 -070065 * <li>{@link #onCreate} which is called to initialize the provider</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066 * <li>{@link #query} which returns data to the caller</li>
67 * <li>{@link #insert} which inserts new data into the content provider</li>
68 * <li>{@link #update} which updates existing data in the content provider</li>
69 * <li>{@link #delete} which deletes data from the content provider</li>
70 * <li>{@link #getType} which returns the MIME type of data in the content provider</li>
71 * </ul></p>
72 *
Dan Egnor6fcc0f0732010-07-27 16:32:17 -070073 * <p class="caution">Data access methods (such as {@link #insert} and
74 * {@link #update}) may be called from many threads at once, and must be thread-safe.
75 * Other methods (such as {@link #onCreate}) are only called from the application
76 * main thread, and must avoid performing lengthy operations. See the method
77 * descriptions for their expected thread behavior.</p>
78 *
79 * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate
80 * ContentProvider instance, so subclasses don't have to worry about the details of
81 * cross-process calls.</p>
Joe Fernandez558459f2011-10-13 16:47:36 -070082 *
83 * <div class="special reference">
84 * <h3>Developer Guides</h3>
85 * <p>For more information about using content providers, read the
86 * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
87 * developer guide.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 */
Dianne Hackbornc68c9132011-07-29 01:25:18 -070089public abstract class ContentProvider implements ComponentCallbacks2 {
Vasu Nori0c9e14a2010-08-04 13:31:48 -070090 private static final String TAG = "ContentProvider";
91
Daisuke Miyakawa8280c2b2009-10-22 08:36:42 +090092 /*
93 * Note: if you add methods to ContentProvider, you must add similar methods to
94 * MockContentProvider.
95 */
96
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 private Context mContext = null;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070098 private int mMyUid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 private String mReadPermission;
100 private String mWritePermission;
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700101 private PathPermission[] mPathPermissions;
Dianne Hackbornb424b632010-08-18 15:59:05 -0700102 private boolean mExported;
Dianne Hackborn7e6f9762013-02-26 13:35:11 -0800103 private boolean mNoPerms;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104
105 private Transport mTransport = new Transport();
106
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700107 /**
108 * Construct a ContentProvider instance. Content providers must be
109 * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared
110 * in the manifest</a>, accessed with {@link ContentResolver}, and created
111 * automatically by the system, so applications usually do not create
112 * ContentProvider instances directly.
113 *
114 * <p>At construction time, the object is uninitialized, and most fields and
115 * methods are unavailable. Subclasses should initialize themselves in
116 * {@link #onCreate}, not the constructor.
117 *
118 * <p>Content providers are created on the application main thread at
119 * application launch time. The constructor must not perform lengthy
120 * operations, or application startup will be delayed.
121 */
Daisuke Miyakawa8280c2b2009-10-22 08:36:42 +0900122 public ContentProvider() {
123 }
124
125 /**
126 * Constructor just for mocking.
127 *
128 * @param context A Context object which should be some mock instance (like the
129 * instance of {@link android.test.mock.MockContext}).
130 * @param readPermission The read permision you want this instance should have in the
131 * test, which is available via {@link #getReadPermission()}.
132 * @param writePermission The write permission you want this instance should have
133 * in the test, which is available via {@link #getWritePermission()}.
134 * @param pathPermissions The PathPermissions you want this instance should have
135 * in the test, which is available via {@link #getPathPermissions()}.
136 * @hide
137 */
138 public ContentProvider(
139 Context context,
140 String readPermission,
141 String writePermission,
142 PathPermission[] pathPermissions) {
143 mContext = context;
144 mReadPermission = readPermission;
145 mWritePermission = writePermission;
146 mPathPermissions = pathPermissions;
147 }
148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 /**
150 * Given an IContentProvider, try to coerce it back to the real
151 * ContentProvider object if it is running in the local process. This can
152 * be used if you know you are running in the same process as a provider,
153 * and want to get direct access to its implementation details. Most
154 * clients should not nor have a reason to use it.
155 *
156 * @param abstractInterface The ContentProvider interface that is to be
157 * coerced.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800158 * @return If the IContentProvider is non-{@code null} and local, returns its actual
159 * ContentProvider instance. Otherwise returns {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 * @hide
161 */
162 public static ContentProvider coerceToLocalContentProvider(
163 IContentProvider abstractInterface) {
164 if (abstractInterface instanceof Transport) {
165 return ((Transport)abstractInterface).getContentProvider();
166 }
167 return null;
168 }
169
170 /**
171 * Binder object that deals with remoting.
172 *
173 * @hide
174 */
175 class Transport extends ContentProviderNative {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800176 AppOpsManager mAppOpsManager = null;
Dianne Hackborn961321f2013-02-05 17:22:41 -0800177 int mReadOp = AppOpsManager.OP_NONE;
178 int mWriteOp = AppOpsManager.OP_NONE;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 ContentProvider getContentProvider() {
181 return ContentProvider.this;
182 }
183
Jeff Brownd2183652011-10-09 12:39:53 -0700184 @Override
185 public String getProviderName() {
186 return getContentProvider().getClass().getName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 }
188
Jeff Brown75ea64f2012-01-25 19:37:13 -0800189 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800190 public Cursor query(String callingPkg, Uri uri, String[] projection,
Jeff Brown75ea64f2012-01-25 19:37:13 -0800191 String selection, String[] selectionArgs, String sortOrder,
Jeff Brown4c1241d2012-02-02 17:05:00 -0800192 ICancellationSignal cancellationSignal) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800193 if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800194 return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
195 CancellationSignal.fromTransport(cancellationSignal));
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800196 }
Jeff Brown75ea64f2012-01-25 19:37:13 -0800197 return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder,
Jeff Brown4c1241d2012-02-02 17:05:00 -0800198 CancellationSignal.fromTransport(cancellationSignal));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 }
200
Jeff Brown75ea64f2012-01-25 19:37:13 -0800201 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 public String getType(Uri uri) {
203 return ContentProvider.this.getType(uri);
204 }
205
Jeff Brown75ea64f2012-01-25 19:37:13 -0800206 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800207 public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800208 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800209 return rejectInsert(uri, initialValues);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 return ContentProvider.this.insert(uri, initialValues);
212 }
213
Jeff Brown75ea64f2012-01-25 19:37:13 -0800214 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800215 public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
216 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
217 return 0;
218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 return ContentProvider.this.bulkInsert(uri, initialValues);
220 }
221
Jeff Brown75ea64f2012-01-25 19:37:13 -0800222 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800223 public ContentProviderResult[] applyBatch(String callingPkg,
224 ArrayList<ContentProviderOperation> operations)
Fred Quintana89437372009-05-15 15:10:40 -0700225 throws OperationApplicationException {
226 for (ContentProviderOperation operation : operations) {
227 if (operation.isReadOperation()) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800228 if (enforceReadPermission(callingPkg, operation.getUri())
229 != AppOpsManager.MODE_ALLOWED) {
230 throw new OperationApplicationException("App op not allowed", 0);
231 }
Fred Quintana89437372009-05-15 15:10:40 -0700232 }
233
234 if (operation.isWriteOperation()) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800235 if (enforceWritePermission(callingPkg, operation.getUri())
236 != AppOpsManager.MODE_ALLOWED) {
237 throw new OperationApplicationException("App op not allowed", 0);
238 }
Fred Quintana89437372009-05-15 15:10:40 -0700239 }
240 }
241 return ContentProvider.this.applyBatch(operations);
Fred Quintana6a8d5332009-05-07 17:35:38 -0700242 }
243
Jeff Brown75ea64f2012-01-25 19:37:13 -0800244 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800245 public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
246 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
247 return 0;
248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 return ContentProvider.this.delete(uri, selection, selectionArgs);
250 }
251
Jeff Brown75ea64f2012-01-25 19:37:13 -0800252 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800253 public int update(String callingPkg, Uri uri, ContentValues values, String selection,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 String[] selectionArgs) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800255 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
256 return 0;
257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 return ContentProvider.this.update(uri, values, selection, selectionArgs);
259 }
260
Jeff Brown75ea64f2012-01-25 19:37:13 -0800261 @Override
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700262 public ParcelFileDescriptor openFile(
263 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 throws FileNotFoundException {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800265 enforceFilePermission(callingPkg, uri, mode);
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700266 return ContentProvider.this.openFile(
267 uri, mode, CancellationSignal.fromTransport(cancellationSignal));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 }
269
Jeff Brown75ea64f2012-01-25 19:37:13 -0800270 @Override
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700271 public AssetFileDescriptor openAssetFile(
272 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 throws FileNotFoundException {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800274 enforceFilePermission(callingPkg, uri, mode);
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700275 return ContentProvider.this.openAssetFile(
276 uri, mode, CancellationSignal.fromTransport(cancellationSignal));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 }
278
Jeff Brown75ea64f2012-01-25 19:37:13 -0800279 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800280 public Bundle call(String callingPkg, String method, String arg, Bundle extras) {
Dianne Hackborn961321f2013-02-05 17:22:41 -0800281 return ContentProvider.this.callFromPackage(callingPkg, method, arg, extras);
Brad Fitzpatrick1877d012010-03-04 17:48:13 -0800282 }
283
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700284 @Override
285 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
286 return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
287 }
288
289 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800290 public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700291 Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800292 enforceFilePermission(callingPkg, uri, "r");
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700293 return ContentProvider.this.openTypedAssetFile(
294 uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700295 }
296
Jeff Brown75ea64f2012-01-25 19:37:13 -0800297 @Override
Jeff Brown4c1241d2012-02-02 17:05:00 -0800298 public ICancellationSignal createCancellationSignal() throws RemoteException {
299 return CancellationSignal.createTransport();
Jeff Brown75ea64f2012-01-25 19:37:13 -0800300 }
301
Dianne Hackborn35654b62013-01-14 17:38:02 -0800302 private void enforceFilePermission(String callingPkg, Uri uri, String mode)
303 throws FileNotFoundException, SecurityException {
Jeff Sharkeyba761972013-02-28 15:57:36 -0800304 if (mode != null && mode.indexOf('w') != -1) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800305 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
306 throw new FileNotFoundException("App op not allowed");
307 }
308 } else {
309 if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
310 throw new FileNotFoundException("App op not allowed");
311 }
312 }
313 }
314
315 private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException {
316 enforceReadPermissionInner(uri);
Dianne Hackborn961321f2013-02-05 17:22:41 -0800317 if (mReadOp != AppOpsManager.OP_NONE) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800318 return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg);
319 }
320 return AppOpsManager.MODE_ALLOWED;
321 }
322
323 private void enforceReadPermissionInner(Uri uri) throws SecurityException {
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700324 final Context context = getContext();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 final int pid = Binder.getCallingPid();
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700326 final int uid = Binder.getCallingUid();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700327 String missingPerm = null;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700328
Dianne Hackborn0d8af782012-08-17 16:51:54 -0700329 if (UserHandle.isSameApp(uid, mMyUid)) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700330 return;
331 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700332
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700333 if (mExported) {
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700334 final String componentPerm = getReadPermission();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700335 if (componentPerm != null) {
336 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
337 return;
338 } else {
339 missingPerm = componentPerm;
340 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700341 }
342
343 // track if unprotected read is allowed; any denied
344 // <path-permission> below removes this ability
345 boolean allowDefaultRead = (componentPerm == null);
346
347 final PathPermission[] pps = getPathPermissions();
348 if (pps != null) {
349 final String path = uri.getPath();
350 for (PathPermission pp : pps) {
351 final String pathPerm = pp.getReadPermission();
352 if (pathPerm != null && pp.match(path)) {
353 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700354 return;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700355 } else {
356 // any denied <path-permission> means we lose
357 // default <provider> access.
358 allowDefaultRead = false;
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700359 missingPerm = pathPerm;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700360 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700361 }
362 }
363 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700364
365 // if we passed <path-permission> checks above, and no default
366 // <provider> permission, then allow access.
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700367 if (allowDefaultRead) return;
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700368 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700369
370 // last chance, check against any uri grants
371 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
372 == PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 return;
374 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700375
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700376 final String failReason = mExported
377 ? " requires " + missingPerm + ", or grantUriPermission()"
378 : " requires the provider be exported, or grantUriPermission()";
379 throw new SecurityException("Permission Denial: reading "
380 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
381 + ", uid=" + uid + failReason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 }
383
Dianne Hackborn35654b62013-01-14 17:38:02 -0800384 private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
385 enforceWritePermissionInner(uri);
Dianne Hackborn961321f2013-02-05 17:22:41 -0800386 if (mWriteOp != AppOpsManager.OP_NONE) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800387 return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg);
388 }
389 return AppOpsManager.MODE_ALLOWED;
390 }
391
392 private void enforceWritePermissionInner(Uri uri) throws SecurityException {
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700393 final Context context = getContext();
394 final int pid = Binder.getCallingPid();
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700395 final int uid = Binder.getCallingUid();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700396 String missingPerm = null;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700397
Dianne Hackborn0d8af782012-08-17 16:51:54 -0700398 if (UserHandle.isSameApp(uid, mMyUid)) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700399 return;
400 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700401
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700402 if (mExported) {
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700403 final String componentPerm = getWritePermission();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700404 if (componentPerm != null) {
405 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
406 return;
407 } else {
408 missingPerm = componentPerm;
409 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700410 }
411
412 // track if unprotected write is allowed; any denied
413 // <path-permission> below removes this ability
414 boolean allowDefaultWrite = (componentPerm == null);
415
416 final PathPermission[] pps = getPathPermissions();
417 if (pps != null) {
418 final String path = uri.getPath();
419 for (PathPermission pp : pps) {
420 final String pathPerm = pp.getWritePermission();
421 if (pathPerm != null && pp.match(path)) {
422 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700423 return;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700424 } else {
425 // any denied <path-permission> means we lose
426 // default <provider> access.
427 allowDefaultWrite = false;
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700428 missingPerm = pathPerm;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700429 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700430 }
431 }
432 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700433
434 // if we passed <path-permission> checks above, and no default
435 // <provider> permission, then allow access.
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700436 if (allowDefaultWrite) return;
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700437 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700438
439 // last chance, check against any uri grants
440 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
441 == PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 return;
443 }
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700444
445 final String failReason = mExported
446 ? " requires " + missingPerm + ", or grantUriPermission()"
447 : " requires the provider be exported, or grantUriPermission()";
448 throw new SecurityException("Permission Denial: writing "
449 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
450 + ", uid=" + uid + failReason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 }
452 }
453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700455 * Retrieves the Context this provider is running in. Only available once
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800456 * {@link #onCreate} has been called -- this will return {@code null} in the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 * constructor.
458 */
459 public final Context getContext() {
460 return mContext;
461 }
462
463 /**
464 * Change the permission required to read data from the content
465 * provider. This is normally set for you from its manifest information
466 * when the provider is first created.
467 *
468 * @param permission Name of the permission required for read-only access.
469 */
470 protected final void setReadPermission(String permission) {
471 mReadPermission = permission;
472 }
473
474 /**
475 * Return the name of the permission required for read-only access to
476 * this content provider. This method can be called from multiple
477 * threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800478 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
479 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 */
481 public final String getReadPermission() {
482 return mReadPermission;
483 }
484
485 /**
486 * Change the permission required to read and write data in the content
487 * provider. This is normally set for you from its manifest information
488 * when the provider is first created.
489 *
490 * @param permission Name of the permission required for read/write access.
491 */
492 protected final void setWritePermission(String permission) {
493 mWritePermission = permission;
494 }
495
496 /**
497 * Return the name of the permission required for read/write access to
498 * this content provider. This method can be called from multiple
499 * threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800500 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
501 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 */
503 public final String getWritePermission() {
504 return mWritePermission;
505 }
506
507 /**
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700508 * Change the path-based permission required to read and/or write data in
509 * the content provider. This is normally set for you from its manifest
510 * information when the provider is first created.
511 *
512 * @param permissions Array of path permission descriptions.
513 */
514 protected final void setPathPermissions(PathPermission[] permissions) {
515 mPathPermissions = permissions;
516 }
517
518 /**
519 * Return the path-based permissions required for read and/or write access to
520 * this content provider. This method can be called from multiple
521 * threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800522 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
523 * and Threads</a>.
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700524 */
525 public final PathPermission[] getPathPermissions() {
526 return mPathPermissions;
527 }
528
Dianne Hackborn35654b62013-01-14 17:38:02 -0800529 /** @hide */
530 public final void setAppOps(int readOp, int writeOp) {
Dianne Hackborn7e6f9762013-02-26 13:35:11 -0800531 if (!mNoPerms) {
532 mTransport.mAppOpsManager = (AppOpsManager)mContext.getSystemService(
533 Context.APP_OPS_SERVICE);
534 mTransport.mReadOp = readOp;
535 mTransport.mWriteOp = writeOp;
536 }
Dianne Hackborn35654b62013-01-14 17:38:02 -0800537 }
538
Dianne Hackborn961321f2013-02-05 17:22:41 -0800539 /** @hide */
540 public AppOpsManager getAppOpsManager() {
541 return mTransport.mAppOpsManager;
542 }
543
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700544 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700545 * Implement this to initialize your content provider on startup.
546 * This method is called for all registered content providers on the
547 * application main thread at application launch time. It must not perform
548 * lengthy operations, or application startup will be delayed.
549 *
550 * <p>You should defer nontrivial initialization (such as opening,
551 * upgrading, and scanning databases) until the content provider is used
552 * (via {@link #query}, {@link #insert}, etc). Deferred initialization
553 * keeps application startup fast, avoids unnecessary work if the provider
554 * turns out not to be needed, and stops database errors (such as a full
555 * disk) from halting application launch.
556 *
Dan Egnor17876aa2010-07-28 12:28:04 -0700557 * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper}
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700558 * is a helpful utility class that makes it easy to manage databases,
559 * and will automatically defer opening until first use. If you do use
560 * SQLiteOpenHelper, make sure to avoid calling
561 * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or
562 * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase}
563 * from this method. (Instead, override
564 * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the
565 * database when it is first opened.)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 *
567 * @return true if the provider was successfully loaded, false otherwise
568 */
569 public abstract boolean onCreate();
570
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700571 /**
572 * {@inheritDoc}
573 * This method is always called on the application main thread, and must
574 * not perform lengthy operations.
575 *
576 * <p>The default content provider implementation does nothing.
577 * Override this method to take appropriate action.
578 * (Content providers do not usually care about things like screen
579 * orientation, but may want to know about locale changes.)
580 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 public void onConfigurationChanged(Configuration newConfig) {
582 }
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700583
584 /**
585 * {@inheritDoc}
586 * This method is always called on the application main thread, and must
587 * not perform lengthy operations.
588 *
589 * <p>The default content provider implementation does nothing.
590 * Subclasses may override this method to take appropriate action.
591 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 public void onLowMemory() {
593 }
594
Dianne Hackbornc68c9132011-07-29 01:25:18 -0700595 public void onTrimMemory(int level) {
596 }
597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 /**
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800599 * @hide
600 * Implementation when a caller has performed a query on the content
601 * provider, but that call has been rejected for the operation given
602 * to {@link #setAppOps(int, int)}. The default implementation
603 * rewrites the <var>selection</var> argument to include a condition
604 * that is never true (so will always result in an empty cursor)
605 * and calls through to {@link #query(android.net.Uri, String[], String, String[],
606 * String, android.os.CancellationSignal)} with that.
607 */
608 public Cursor rejectQuery(Uri uri, String[] projection,
609 String selection, String[] selectionArgs, String sortOrder,
610 CancellationSignal cancellationSignal) {
611 // The read is not allowed... to fake it out, we replace the given
612 // selection statement with a dummy one that will always be false.
613 // This way we will get a cursor back that has the correct structure
614 // but contains no rows.
Dianne Hackborn9fa39bd2013-03-22 18:42:14 -0700615 if (selection == null || selection.isEmpty()) {
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800616 selection = "'A' = 'B'";
617 } else {
618 selection = "'A' = 'B' AND (" + selection + ")";
619 }
620 return query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);
621 }
622
623 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700624 * Implement this to handle query requests from clients.
625 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800626 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
627 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 * <p>
629 * Example client call:<p>
630 * <pre>// Request a specific record.
631 * Cursor managedCursor = managedQuery(
Alan Jones81a476f2009-05-21 12:32:17 +1000632 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 projection, // Which columns to return.
634 null, // WHERE clause.
Alan Jones81a476f2009-05-21 12:32:17 +1000635 null, // WHERE clause value substitution
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 People.NAME + " ASC"); // Sort order.</pre>
637 * Example implementation:<p>
638 * <pre>// SQLiteQueryBuilder is a helper class that creates the
639 // proper SQL syntax for us.
640 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
641
642 // Set the table we're querying.
643 qBuilder.setTables(DATABASE_TABLE_NAME);
644
645 // If the query ends in a specific record number, we're
646 // being asked for a specific record, so set the
647 // WHERE clause in our query.
648 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
649 qBuilder.appendWhere("_id=" + uri.getPathLeafId());
650 }
651
652 // Make the query.
653 Cursor c = qBuilder.query(mDb,
654 projection,
655 selection,
656 selectionArgs,
657 groupBy,
658 having,
659 sortOrder);
660 c.setNotificationUri(getContext().getContentResolver(), uri);
661 return c;</pre>
662 *
663 * @param uri The URI to query. This will be the full URI sent by the client;
Alan Jones81a476f2009-05-21 12:32:17 +1000664 * if the client is requesting a specific record, the URI will end in a record number
665 * that the implementation should parse and add to a WHERE or HAVING clause, specifying
666 * that _id value.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 * @param projection The list of columns to put into the cursor. If
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800668 * {@code null} all columns are included.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 * @param selection A selection criteria to apply when filtering rows.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800670 * If {@code null} then all rows are included.
Alan Jones81a476f2009-05-21 12:32:17 +1000671 * @param selectionArgs You may include ?s in selection, which will be replaced by
672 * the values from selectionArgs, in order that they appear in the selection.
673 * The values will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 * @param sortOrder How the rows in the cursor should be sorted.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800675 * If {@code null} then the provider is free to define the sort order.
676 * @return a Cursor or {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 */
678 public abstract Cursor query(Uri uri, String[] projection,
679 String selection, String[] selectionArgs, String sortOrder);
680
Fred Quintana5bba6322009-10-05 14:21:12 -0700681 /**
Jeff Brown4c1241d2012-02-02 17:05:00 -0800682 * Implement this to handle query requests from clients with support for cancellation.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800683 * This method can be called from multiple threads, as described in
684 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
685 * and Threads</a>.
686 * <p>
687 * Example client call:<p>
688 * <pre>// Request a specific record.
689 * Cursor managedCursor = managedQuery(
690 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
691 projection, // Which columns to return.
692 null, // WHERE clause.
693 null, // WHERE clause value substitution
694 People.NAME + " ASC"); // Sort order.</pre>
695 * Example implementation:<p>
696 * <pre>// SQLiteQueryBuilder is a helper class that creates the
697 // proper SQL syntax for us.
698 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
699
700 // Set the table we're querying.
701 qBuilder.setTables(DATABASE_TABLE_NAME);
702
703 // If the query ends in a specific record number, we're
704 // being asked for a specific record, so set the
705 // WHERE clause in our query.
706 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
707 qBuilder.appendWhere("_id=" + uri.getPathLeafId());
708 }
709
710 // Make the query.
711 Cursor c = qBuilder.query(mDb,
712 projection,
713 selection,
714 selectionArgs,
715 groupBy,
716 having,
717 sortOrder);
718 c.setNotificationUri(getContext().getContentResolver(), uri);
719 return c;</pre>
720 * <p>
721 * If you implement this method then you must also implement the version of
Jeff Brown4c1241d2012-02-02 17:05:00 -0800722 * {@link #query(Uri, String[], String, String[], String)} that does not take a cancellation
723 * signal to ensure correct operation on older versions of the Android Framework in
724 * which the cancellation signal overload was not available.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800725 *
726 * @param uri The URI to query. This will be the full URI sent by the client;
727 * if the client is requesting a specific record, the URI will end in a record number
728 * that the implementation should parse and add to a WHERE or HAVING clause, specifying
729 * that _id value.
730 * @param projection The list of columns to put into the cursor. If
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800731 * {@code null} all columns are included.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800732 * @param selection A selection criteria to apply when filtering rows.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800733 * If {@code null} then all rows are included.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800734 * @param selectionArgs You may include ?s in selection, which will be replaced by
735 * the values from selectionArgs, in order that they appear in the selection.
736 * The values will be bound as Strings.
737 * @param sortOrder How the rows in the cursor should be sorted.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800738 * If {@code null} then the provider is free to define the sort order.
739 * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800740 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
741 * when the query is executed.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800742 * @return a Cursor or {@code null}.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800743 */
744 public Cursor query(Uri uri, String[] projection,
745 String selection, String[] selectionArgs, String sortOrder,
Jeff Brown4c1241d2012-02-02 17:05:00 -0800746 CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -0800747 return query(uri, projection, selection, selectionArgs, sortOrder);
748 }
749
750 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700751 * Implement this to handle requests for the MIME type of the data at the
752 * given URI. The returned MIME type should start with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 * <code>vnd.android.cursor.item</code> for a single record,
754 * or <code>vnd.android.cursor.dir/</code> for multiple items.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700755 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800756 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
757 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 *
Dianne Hackborncca1f0e2010-09-26 18:34:53 -0700759 * <p>Note that there are no permissions needed for an application to
760 * access this information; if your content provider requires read and/or
761 * write permissions, or is not exported, all applications can still call
762 * this method regardless of their access permissions. This allows them
763 * to retrieve the MIME type for a URI when dispatching intents.
764 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 * @param uri the URI to query.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800766 * @return a MIME type string, or {@code null} if there is no type.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 */
768 public abstract String getType(Uri uri);
769
770 /**
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800771 * @hide
772 * Implementation when a caller has performed an insert on the content
773 * provider, but that call has been rejected for the operation given
774 * to {@link #setAppOps(int, int)}. The default implementation simply
775 * returns a dummy URI that is the base URI with a 0 path element
776 * appended.
777 */
778 public Uri rejectInsert(Uri uri, ContentValues values) {
779 // If not allowed, we need to return some reasonable URI. Maybe the
780 // content provider should be responsible for this, but for now we
781 // will just return the base URI with a dummy '0' tagged on to it.
782 // You shouldn't be able to read if you can't write, anyway, so it
783 // shouldn't matter much what is returned.
784 return uri.buildUpon().appendPath("0").build();
785 }
786
787 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700788 * Implement this to handle requests to insert a new row.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
790 * after inserting.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700791 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800792 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
793 * and Threads</a>.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800794 * @param uri The content:// URI of the insertion request. This must not be {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 * @param values A set of column_name/value pairs to add to the database.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800796 * This must not be {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 * @return The URI for the newly inserted item.
798 */
799 public abstract Uri insert(Uri uri, ContentValues values);
800
801 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700802 * Override this to handle requests to insert a set of new rows, or the
803 * default implementation will iterate over the values and call
804 * {@link #insert} on each of them.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
806 * after inserting.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700807 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800808 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
809 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 *
811 * @param uri The content:// URI of the insertion request.
812 * @param values An array of sets of column_name/value pairs to add to the database.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800813 * This must not be {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 * @return The number of values that were inserted.
815 */
816 public int bulkInsert(Uri uri, ContentValues[] values) {
817 int numValues = values.length;
818 for (int i = 0; i < numValues; i++) {
819 insert(uri, values[i]);
820 }
821 return numValues;
822 }
823
824 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700825 * Implement this to handle requests to delete one or more rows.
826 * The implementation should apply the selection clause when performing
827 * deletion, allowing the operation to affect multiple rows in a directory.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
829 * after deleting.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700830 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800831 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
832 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 *
834 * <p>The implementation is responsible for parsing out a row ID at the end
835 * of the URI, if a specific row is being deleted. That is, the client would
836 * pass in <code>content://contacts/people/22</code> and the implementation is
837 * responsible for parsing the record number (22) when creating a SQL statement.
838 *
839 * @param uri The full URI to query, including a row ID (if a specific record is requested).
840 * @param selection An optional restriction to apply to rows when deleting.
841 * @return The number of rows affected.
842 * @throws SQLException
843 */
844 public abstract int delete(Uri uri, String selection, String[] selectionArgs);
845
846 /**
Dan Egnor17876aa2010-07-28 12:28:04 -0700847 * Implement this to handle requests to update one or more rows.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700848 * The implementation should update all rows matching the selection
849 * to set the columns according to the provided values map.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
851 * after updating.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700852 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800853 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
854 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 *
856 * @param uri The URI to query. This can potentially have a record ID if this
857 * is an update request for a specific record.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800858 * @param values A set of column_name/value pairs to update in the database.
859 * This must not be {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 * @param selection An optional filter to match rows to update.
861 * @return the number of rows affected.
862 */
863 public abstract int update(Uri uri, ContentValues values, String selection,
864 String[] selectionArgs);
865
866 /**
Dan Egnor17876aa2010-07-28 12:28:04 -0700867 * Override this to handle requests to open a file blob.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700868 * The default implementation always throws {@link FileNotFoundException}.
869 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800870 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
871 * and Threads</a>.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700872 *
Dan Egnor17876aa2010-07-28 12:28:04 -0700873 * <p>This method returns a ParcelFileDescriptor, which is returned directly
874 * to the caller. This way large data (such as images and documents) can be
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700875 * returned without copying the content.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 *
877 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
878 * their responsibility to close it when done. That is, the implementation
879 * of this method should create a new ParcelFileDescriptor for each call.
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700880 * <p>
881 * If opened with the exclusive "r" or "w" modes, the returned
882 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming
883 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that
884 * supports seeking.
885 * <p>
886 * If you need to detect when the returned ParcelFileDescriptor has been
887 * closed, or if the remote process has crashed or encountered some other
888 * error, you can use {@link ParcelFileDescriptor#open(File, int,
889 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)},
890 * {@link ParcelFileDescriptor#createReliablePipe()}, or
891 * {@link ParcelFileDescriptor#createReliableSocketPair()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 *
Dianne Hackborna53ee352013-02-20 12:47:02 -0800893 * <p class="note">For use in Intents, you will want to implement {@link #getType}
894 * to return the appropriate MIME type for the data returned here with
895 * the same URI. This will allow intent resolution to automatically determine the data MIME
896 * type and select the appropriate matching targets as part of its operation.</p>
897 *
898 * <p class="note">For better interoperability with other applications, it is recommended
899 * that for any URIs that can be opened, you also support queries on them
900 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
901 * You may also want to support other common columns if you have additional meta-data
902 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
903 * in {@link android.provider.MediaStore.MediaColumns}.</p>
904 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 * @param uri The URI whose file is to be opened.
906 * @param mode Access mode for the file. May be "r" for read-only access,
907 * "rw" for read and write access, or "rwt" for read and write access
908 * that truncates any existing file.
909 *
910 * @return Returns a new ParcelFileDescriptor which you can use to access
911 * the file.
912 *
913 * @throws FileNotFoundException Throws FileNotFoundException if there is
914 * no file associated with the given URI or the mode is invalid.
915 * @throws SecurityException Throws SecurityException if the caller does
916 * not have permission to access the file.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700917 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 * @see #openAssetFile(Uri, String)
919 * @see #openFileHelper(Uri, String)
Dianne Hackborna53ee352013-02-20 12:47:02 -0800920 * @see #getType(android.net.Uri)
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700921 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 public ParcelFileDescriptor openFile(Uri uri, String mode)
923 throws FileNotFoundException {
924 throw new FileNotFoundException("No files supported by provider at "
925 + uri);
926 }
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 /**
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700929 * Override this to handle requests to open a file blob.
930 * The default implementation always throws {@link FileNotFoundException}.
931 * This method can be called from multiple threads, as described in
932 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
933 * and Threads</a>.
934 *
935 * <p>This method returns a ParcelFileDescriptor, which is returned directly
936 * to the caller. This way large data (such as images and documents) can be
937 * returned without copying the content.
938 *
939 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
940 * their responsibility to close it when done. That is, the implementation
941 * of this method should create a new ParcelFileDescriptor for each call.
942 * <p>
943 * If opened with the exclusive "r" or "w" modes, the returned
944 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming
945 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that
946 * supports seeking.
947 * <p>
948 * If you need to detect when the returned ParcelFileDescriptor has been
949 * closed, or if the remote process has crashed or encountered some other
950 * error, you can use {@link ParcelFileDescriptor#open(File, int,
951 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)},
952 * {@link ParcelFileDescriptor#createReliablePipe()}, or
953 * {@link ParcelFileDescriptor#createReliableSocketPair()}.
954 *
955 * <p class="note">For use in Intents, you will want to implement {@link #getType}
956 * to return the appropriate MIME type for the data returned here with
957 * the same URI. This will allow intent resolution to automatically determine the data MIME
958 * type and select the appropriate matching targets as part of its operation.</p>
959 *
960 * <p class="note">For better interoperability with other applications, it is recommended
961 * that for any URIs that can be opened, you also support queries on them
962 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
963 * You may also want to support other common columns if you have additional meta-data
964 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
965 * in {@link android.provider.MediaStore.MediaColumns}.</p>
966 *
967 * @param uri The URI whose file is to be opened.
968 * @param mode Access mode for the file. May be "r" for read-only access,
969 * "w" for write-only access, "rw" for read and write access, or
970 * "rwt" for read and write access that truncates any existing
971 * file.
972 * @param signal A signal to cancel the operation in progress, or
973 * {@code null} if none. For example, if you are downloading a
974 * file from the network to service a "rw" mode request, you
975 * should periodically call
976 * {@link CancellationSignal#throwIfCanceled()} to check whether
977 * the client has canceled the request and abort the download.
978 *
979 * @return Returns a new ParcelFileDescriptor which you can use to access
980 * the file.
981 *
982 * @throws FileNotFoundException Throws FileNotFoundException if there is
983 * no file associated with the given URI or the mode is invalid.
984 * @throws SecurityException Throws SecurityException if the caller does
985 * not have permission to access the file.
986 *
987 * @see #openAssetFile(Uri, String)
988 * @see #openFileHelper(Uri, String)
989 * @see #getType(android.net.Uri)
990 */
991 public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
992 throws FileNotFoundException {
993 return openFile(uri, mode);
994 }
995
996 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 * This is like {@link #openFile}, but can be implemented by providers
998 * that need to be able to return sub-sections of files, often assets
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700999 * inside of their .apk.
1000 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -08001001 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1002 * and Threads</a>.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001003 *
1004 * <p>If you implement this, your clients must be able to deal with such
Dan Egnor17876aa2010-07-28 12:28:04 -07001005 * file slices, either directly with
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001006 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
1008 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
1009 * methods.
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001010 * <p>
1011 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1012 * streaming of data.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001013 *
1014 * <p class="note">If you are implementing this to return a full file, you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 * should create the AssetFileDescriptor with
1016 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001017 * applications that cannot handle sub-sections of files.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 *
Dianne Hackborna53ee352013-02-20 12:47:02 -08001019 * <p class="note">For use in Intents, you will want to implement {@link #getType}
1020 * to return the appropriate MIME type for the data returned here with
1021 * the same URI. This will allow intent resolution to automatically determine the data MIME
1022 * type and select the appropriate matching targets as part of its operation.</p>
1023 *
1024 * <p class="note">For better interoperability with other applications, it is recommended
1025 * that for any URIs that can be opened, you also support queries on them
1026 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
1027 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 * @param uri The URI whose file is to be opened.
1029 * @param mode Access mode for the file. May be "r" for read-only access,
1030 * "w" for write-only access (erasing whatever data is currently in
1031 * the file), "wa" for write-only access to append to any existing data,
1032 * "rw" for read and write access on any existing data, and "rwt" for read
1033 * and write access that truncates any existing file.
1034 *
1035 * @return Returns a new AssetFileDescriptor which you can use to access
1036 * the file.
1037 *
1038 * @throws FileNotFoundException Throws FileNotFoundException if there is
1039 * no file associated with the given URI or the mode is invalid.
1040 * @throws SecurityException Throws SecurityException if the caller does
1041 * not have permission to access the file.
1042 *
1043 * @see #openFile(Uri, String)
1044 * @see #openFileHelper(Uri, String)
Dianne Hackborna53ee352013-02-20 12:47:02 -08001045 * @see #getType(android.net.Uri)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 */
1047 public AssetFileDescriptor openAssetFile(Uri uri, String mode)
1048 throws FileNotFoundException {
1049 ParcelFileDescriptor fd = openFile(uri, mode);
1050 return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
1051 }
1052
1053 /**
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001054 * This is like {@link #openFile}, but can be implemented by providers
1055 * that need to be able to return sub-sections of files, often assets
1056 * inside of their .apk.
1057 * This method can be called from multiple threads, as described in
1058 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1059 * and Threads</a>.
1060 *
1061 * <p>If you implement this, your clients must be able to deal with such
1062 * file slices, either directly with
1063 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
1064 * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
1065 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
1066 * methods.
1067 * <p>
1068 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1069 * streaming of data.
1070 *
1071 * <p class="note">If you are implementing this to return a full file, you
1072 * should create the AssetFileDescriptor with
1073 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
1074 * applications that cannot handle sub-sections of files.</p>
1075 *
1076 * <p class="note">For use in Intents, you will want to implement {@link #getType}
1077 * to return the appropriate MIME type for the data returned here with
1078 * the same URI. This will allow intent resolution to automatically determine the data MIME
1079 * type and select the appropriate matching targets as part of its operation.</p>
1080 *
1081 * <p class="note">For better interoperability with other applications, it is recommended
1082 * that for any URIs that can be opened, you also support queries on them
1083 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
1084 *
1085 * @param uri The URI whose file is to be opened.
1086 * @param mode Access mode for the file. May be "r" for read-only access,
1087 * "w" for write-only access (erasing whatever data is currently in
1088 * the file), "wa" for write-only access to append to any existing data,
1089 * "rw" for read and write access on any existing data, and "rwt" for read
1090 * and write access that truncates any existing file.
1091 * @param signal A signal to cancel the operation in progress, or
1092 * {@code null} if none. For example, if you are downloading a
1093 * file from the network to service a "rw" mode request, you
1094 * should periodically call
1095 * {@link CancellationSignal#throwIfCanceled()} to check whether
1096 * the client has canceled the request and abort the download.
1097 *
1098 * @return Returns a new AssetFileDescriptor which you can use to access
1099 * the file.
1100 *
1101 * @throws FileNotFoundException Throws FileNotFoundException if there is
1102 * no file associated with the given URI or the mode is invalid.
1103 * @throws SecurityException Throws SecurityException if the caller does
1104 * not have permission to access the file.
1105 *
1106 * @see #openFile(Uri, String)
1107 * @see #openFileHelper(Uri, String)
1108 * @see #getType(android.net.Uri)
1109 */
1110 public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal)
1111 throws FileNotFoundException {
1112 return openAssetFile(uri, mode);
1113 }
1114
1115 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 * Convenience for subclasses that wish to implement {@link #openFile}
1117 * by looking up a column named "_data" at the given URI.
1118 *
1119 * @param uri The URI to be opened.
1120 * @param mode The file mode. May be "r" for read-only access,
1121 * "w" for write-only access (erasing whatever data is currently in
1122 * the file), "wa" for write-only access to append to any existing data,
1123 * "rw" for read and write access on any existing data, and "rwt" for read
1124 * and write access that truncates any existing file.
1125 *
1126 * @return Returns a new ParcelFileDescriptor that can be used by the
1127 * client to access the file.
1128 */
1129 protected final ParcelFileDescriptor openFileHelper(Uri uri,
1130 String mode) throws FileNotFoundException {
1131 Cursor c = query(uri, new String[]{"_data"}, null, null, null);
1132 int count = (c != null) ? c.getCount() : 0;
1133 if (count != 1) {
1134 // If there is not exactly one result, throw an appropriate
1135 // exception.
1136 if (c != null) {
1137 c.close();
1138 }
1139 if (count == 0) {
1140 throw new FileNotFoundException("No entry for " + uri);
1141 }
1142 throw new FileNotFoundException("Multiple items at " + uri);
1143 }
1144
1145 c.moveToFirst();
1146 int i = c.getColumnIndex("_data");
1147 String path = (i >= 0 ? c.getString(i) : null);
1148 c.close();
1149 if (path == null) {
1150 throw new FileNotFoundException("Column _data not found.");
1151 }
1152
1153 int modeBits = ContentResolver.modeToMode(uri, mode);
1154 return ParcelFileDescriptor.open(new File(path), modeBits);
1155 }
1156
1157 /**
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001158 * Called by a client to determine the types of data streams that this
1159 * content provider supports for the given URI. The default implementation
Christopher Tate2bc6eb82013-01-03 12:04:08 -08001160 * returns {@code null}, meaning no types. If your content provider stores data
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001161 * of a particular type, return that MIME type if it matches the given
1162 * mimeTypeFilter. If it can perform type conversions, return an array
1163 * of all supported MIME types that match mimeTypeFilter.
1164 *
1165 * @param uri The data in the content provider being queried.
1166 * @param mimeTypeFilter The type of data the client desires. May be
1167 * a pattern, such as *\/* to retrieve all possible data types.
Christopher Tate2bc6eb82013-01-03 12:04:08 -08001168 * @return Returns {@code null} if there are no possible data streams for the
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001169 * given mimeTypeFilter. Otherwise returns an array of all available
1170 * concrete MIME types.
1171 *
1172 * @see #getType(Uri)
1173 * @see #openTypedAssetFile(Uri, String, Bundle)
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001174 * @see ClipDescription#compareMimeTypes(String, String)
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001175 */
1176 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
1177 return null;
1178 }
1179
1180 /**
1181 * Called by a client to open a read-only stream containing data of a
1182 * particular MIME type. This is like {@link #openAssetFile(Uri, String)},
1183 * except the file can only be read-only and the content provider may
1184 * perform data conversions to generate data of the desired type.
1185 *
1186 * <p>The default implementation compares the given mimeType against the
Dianne Hackborna53ee352013-02-20 12:47:02 -08001187 * result of {@link #getType(Uri)} and, if they match, simply calls
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001188 * {@link #openAssetFile(Uri, String)}.
1189 *
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001190 * <p>See {@link ClipData} for examples of the use and implementation
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001191 * of this method.
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001192 * <p>
1193 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1194 * streaming of data.
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001195 *
Dianne Hackborna53ee352013-02-20 12:47:02 -08001196 * <p class="note">For better interoperability with other applications, it is recommended
1197 * that for any URIs that can be opened, you also support queries on them
1198 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1199 * You may also want to support other common columns if you have additional meta-data
1200 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1201 * in {@link android.provider.MediaStore.MediaColumns}.</p>
1202 *
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001203 * @param uri The data in the content provider being queried.
1204 * @param mimeTypeFilter The type of data the client desires. May be
1205 * a pattern, such as *\/*, if the caller does not have specific type
1206 * requirements; in this case the content provider will pick its best
1207 * type matching the pattern.
1208 * @param opts Additional options from the client. The definitions of
1209 * these are specific to the content provider being called.
1210 *
1211 * @return Returns a new AssetFileDescriptor from which the client can
1212 * read data of the desired type.
1213 *
1214 * @throws FileNotFoundException Throws FileNotFoundException if there is
1215 * no file associated with the given URI or the mode is invalid.
1216 * @throws SecurityException Throws SecurityException if the caller does
1217 * not have permission to access the data.
1218 * @throws IllegalArgumentException Throws IllegalArgumentException if the
1219 * content provider does not support the requested MIME type.
1220 *
1221 * @see #getStreamTypes(Uri, String)
1222 * @see #openAssetFile(Uri, String)
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001223 * @see ClipDescription#compareMimeTypes(String, String)
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001224 */
1225 public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
1226 throws FileNotFoundException {
Dianne Hackborn02dfd262010-08-13 12:34:58 -07001227 if ("*/*".equals(mimeTypeFilter)) {
1228 // If they can take anything, the untyped open call is good enough.
1229 return openAssetFile(uri, "r");
1230 }
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001231 String baseType = getType(uri);
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001232 if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) {
Dianne Hackborn02dfd262010-08-13 12:34:58 -07001233 // Use old untyped open call if this provider has a type for this
1234 // URI and it matches the request.
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001235 return openAssetFile(uri, "r");
1236 }
1237 throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter);
1238 }
1239
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001240
1241 /**
1242 * Called by a client to open a read-only stream containing data of a
1243 * particular MIME type. This is like {@link #openAssetFile(Uri, String)},
1244 * except the file can only be read-only and the content provider may
1245 * perform data conversions to generate data of the desired type.
1246 *
1247 * <p>The default implementation compares the given mimeType against the
1248 * result of {@link #getType(Uri)} and, if they match, simply calls
1249 * {@link #openAssetFile(Uri, String)}.
1250 *
1251 * <p>See {@link ClipData} for examples of the use and implementation
1252 * of this method.
1253 * <p>
1254 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1255 * streaming of data.
1256 *
1257 * <p class="note">For better interoperability with other applications, it is recommended
1258 * that for any URIs that can be opened, you also support queries on them
1259 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1260 * You may also want to support other common columns if you have additional meta-data
1261 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1262 * in {@link android.provider.MediaStore.MediaColumns}.</p>
1263 *
1264 * @param uri The data in the content provider being queried.
1265 * @param mimeTypeFilter The type of data the client desires. May be
1266 * a pattern, such as *\/*, if the caller does not have specific type
1267 * requirements; in this case the content provider will pick its best
1268 * type matching the pattern.
1269 * @param opts Additional options from the client. The definitions of
1270 * these are specific to the content provider being called.
1271 * @param signal A signal to cancel the operation in progress, or
1272 * {@code null} if none. For example, if you are downloading a
1273 * file from the network to service a "rw" mode request, you
1274 * should periodically call
1275 * {@link CancellationSignal#throwIfCanceled()} to check whether
1276 * the client has canceled the request and abort the download.
1277 *
1278 * @return Returns a new AssetFileDescriptor from which the client can
1279 * read data of the desired type.
1280 *
1281 * @throws FileNotFoundException Throws FileNotFoundException if there is
1282 * no file associated with the given URI or the mode is invalid.
1283 * @throws SecurityException Throws SecurityException if the caller does
1284 * not have permission to access the data.
1285 * @throws IllegalArgumentException Throws IllegalArgumentException if the
1286 * content provider does not support the requested MIME type.
1287 *
1288 * @see #getStreamTypes(Uri, String)
1289 * @see #openAssetFile(Uri, String)
1290 * @see ClipDescription#compareMimeTypes(String, String)
1291 */
1292 public AssetFileDescriptor openTypedAssetFile(
1293 Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
1294 throws FileNotFoundException {
1295 return openTypedAssetFile(uri, mimeTypeFilter, opts);
1296 }
1297
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001298 /**
1299 * Interface to write a stream of data to a pipe. Use with
1300 * {@link ContentProvider#openPipeHelper}.
1301 */
1302 public interface PipeDataWriter<T> {
1303 /**
1304 * Called from a background thread to stream data out to a pipe.
1305 * Note that the pipe is blocking, so this thread can block on
1306 * writes for an arbitrary amount of time if the client is slow
1307 * at reading.
1308 *
1309 * @param output The pipe where data should be written. This will be
1310 * closed for you upon returning from this function.
1311 * @param uri The URI whose data is to be written.
1312 * @param mimeType The desired type of data to be written.
1313 * @param opts Options supplied by caller.
1314 * @param args Your own custom arguments.
1315 */
1316 public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
1317 Bundle opts, T args);
1318 }
1319
1320 /**
1321 * A helper function for implementing {@link #openTypedAssetFile}, for
1322 * creating a data pipe and background thread allowing you to stream
1323 * generated data back to the client. This function returns a new
1324 * ParcelFileDescriptor that should be returned to the caller (the caller
1325 * is responsible for closing it).
1326 *
1327 * @param uri The URI whose data is to be written.
1328 * @param mimeType The desired type of data to be written.
1329 * @param opts Options supplied by caller.
1330 * @param args Your own custom arguments.
1331 * @param func Interface implementing the function that will actually
1332 * stream the data.
1333 * @return Returns a new ParcelFileDescriptor holding the read side of
1334 * the pipe. This should be returned to the caller for reading; the caller
1335 * is responsible for closing it when done.
1336 */
1337 public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType,
1338 final Bundle opts, final T args, final PipeDataWriter<T> func)
1339 throws FileNotFoundException {
1340 try {
1341 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
1342
1343 AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
1344 @Override
1345 protected Object doInBackground(Object... params) {
1346 func.writeDataToPipe(fds[1], uri, mimeType, opts, args);
1347 try {
1348 fds[1].close();
1349 } catch (IOException e) {
1350 Log.w(TAG, "Failure closing pipe", e);
1351 }
1352 return null;
1353 }
1354 };
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08001355 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null);
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001356
1357 return fds[0];
1358 } catch (IOException e) {
1359 throw new FileNotFoundException("failure making pipe");
1360 }
1361 }
1362
1363 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 * Returns true if this instance is a temporary content provider.
1365 * @return true if this instance is a temporary content provider
1366 */
1367 protected boolean isTemporary() {
1368 return false;
1369 }
1370
1371 /**
1372 * Returns the Binder object for this provider.
1373 *
1374 * @return the Binder object for this provider
1375 * @hide
1376 */
1377 public IContentProvider getIContentProvider() {
1378 return mTransport;
1379 }
1380
1381 /**
Dianne Hackborn334d9ae2013-02-26 15:02:06 -08001382 * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use
1383 * when directly instantiating the provider for testing.
1384 * @hide
1385 */
1386 public void attachInfoForTesting(Context context, ProviderInfo info) {
1387 attachInfo(context, info, true);
1388 }
1389
1390 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 * After being instantiated, this is called to tell the content provider
1392 * about itself.
1393 *
1394 * @param context The context this provider is running in
1395 * @param info Registered information about this content provider
1396 */
1397 public void attachInfo(Context context, ProviderInfo info) {
Dianne Hackborn334d9ae2013-02-26 15:02:06 -08001398 attachInfo(context, info, false);
1399 }
1400
1401 private void attachInfo(Context context, ProviderInfo info, boolean testing) {
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001402 /*
1403 * We may be using AsyncTask from binder threads. Make it init here
1404 * so its static handler is on the main thread.
1405 */
1406 AsyncTask.init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407
Dianne Hackborn334d9ae2013-02-26 15:02:06 -08001408 mNoPerms = testing;
1409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 /*
1411 * Only allow it to be set once, so after the content service gives
1412 * this to us clients can't change it.
1413 */
1414 if (mContext == null) {
1415 mContext = context;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07001416 mMyUid = Process.myUid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 if (info != null) {
1418 setReadPermission(info.readPermission);
1419 setWritePermission(info.writePermission);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07001420 setPathPermissions(info.pathPermissions);
Dianne Hackbornb424b632010-08-18 15:59:05 -07001421 mExported = info.exported;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 }
1423 ContentProvider.this.onCreate();
1424 }
1425 }
Fred Quintanace31b232009-05-04 16:01:15 -07001426
1427 /**
Dan Egnor17876aa2010-07-28 12:28:04 -07001428 * Override this to handle requests to perform a batch of operations, or the
1429 * default implementation will iterate over the operations and call
1430 * {@link ContentProviderOperation#apply} on each of them.
1431 * If all calls to {@link ContentProviderOperation#apply} succeed
1432 * then a {@link ContentProviderResult} array with as many
1433 * elements as there were operations will be returned. If any of the calls
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001434 * fail, it is up to the implementation how many of the others take effect.
1435 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -08001436 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1437 * and Threads</a>.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001438 *
Fred Quintanace31b232009-05-04 16:01:15 -07001439 * @param operations the operations to apply
1440 * @return the results of the applications
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001441 * @throws OperationApplicationException thrown if any operation fails.
1442 * @see ContentProviderOperation#apply
Fred Quintanace31b232009-05-04 16:01:15 -07001443 */
Fred Quintana03d94902009-05-22 14:23:31 -07001444 public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
Fred Quintanace31b232009-05-04 16:01:15 -07001445 throws OperationApplicationException {
Fred Quintana03d94902009-05-22 14:23:31 -07001446 final int numOperations = operations.size();
1447 final ContentProviderResult[] results = new ContentProviderResult[numOperations];
1448 for (int i = 0; i < numOperations; i++) {
1449 results[i] = operations.get(i).apply(this, results, i);
Fred Quintanace31b232009-05-04 16:01:15 -07001450 }
1451 return results;
1452 }
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001453
1454 /**
Dianne Hackborn961321f2013-02-05 17:22:41 -08001455 * @hide
1456 * Front-end to {@link #call(String, String, android.os.Bundle)} that provides the name
1457 * of the calling package.
1458 */
1459 public Bundle callFromPackage(String callingPackag, String method, String arg, Bundle extras) {
1460 return call(method, arg, extras);
1461 }
1462
1463 /**
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001464 * Call a provider-defined method. This can be used to implement
Brad Fitzpatrick534c84c2011-01-12 14:06:30 -08001465 * interfaces that are cheaper and/or unnatural for a table-like
1466 * model.
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001467 *
Dianne Hackborn5d122d92013-03-12 18:37:07 -07001468 * <p class="note"><strong>WARNING:</strong> The framework does no permission checking
1469 * on this entry into the content provider besides the basic ability for the application
1470 * to get access to the provider at all. For example, it has no idea whether the call
1471 * being executed may read or write data in the provider, so can't enforce those
1472 * individual permissions. Any implementation of this method <strong>must</strong>
1473 * do its own permission checks on incoming calls to make sure they are allowed.</p>
1474 *
Christopher Tate2bc6eb82013-01-03 12:04:08 -08001475 * @param method method name to call. Opaque to framework, but should not be {@code null}.
1476 * @param arg provider-defined String argument. May be {@code null}.
1477 * @param extras provider-defined Bundle argument. May be {@code null}.
1478 * @return provider-defined return value. May be {@code null}, which is also
Brad Fitzpatrick534c84c2011-01-12 14:06:30 -08001479 * the default for providers which don't implement any call methods.
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001480 */
Brad Fitzpatrick534c84c2011-01-12 14:06:30 -08001481 public Bundle call(String method, String arg, Bundle extras) {
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001482 return null;
1483 }
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001484
1485 /**
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001486 * Implement this to shut down the ContentProvider instance. You can then
1487 * invoke this method in unit tests.
1488 *
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001489 * <p>
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001490 * Android normally handles ContentProvider startup and shutdown
1491 * automatically. You do not need to start up or shut down a
1492 * ContentProvider. When you invoke a test method on a ContentProvider,
1493 * however, a ContentProvider instance is started and keeps running after
1494 * the test finishes, even if a succeeding test instantiates another
1495 * ContentProvider. A conflict develops because the two instances are
1496 * usually running against the same underlying data source (for example, an
1497 * sqlite database).
1498 * </p>
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001499 * <p>
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001500 * Implementing shutDown() avoids this conflict by providing a way to
1501 * terminate the ContentProvider. This method can also prevent memory leaks
1502 * from multiple instantiations of the ContentProvider, and it can ensure
1503 * unit test isolation by allowing you to completely clean up the test
1504 * fixture before moving on to the next test.
1505 * </p>
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001506 */
1507 public void shutdown() {
1508 Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " +
1509 "connections are gracefully shutdown");
1510 }
Marco Nelissen18cb2872011-11-15 11:19:53 -08001511
1512 /**
1513 * Print the Provider's state into the given stream. This gets invoked if
Jeff Sharkey5554b702012-04-11 18:30:51 -07001514 * you run "adb shell dumpsys activity provider &lt;provider_component_name&gt;".
Marco Nelissen18cb2872011-11-15 11:19:53 -08001515 *
Marco Nelissen18cb2872011-11-15 11:19:53 -08001516 * @param fd The raw file descriptor that the dump is being sent to.
1517 * @param writer The PrintWriter to which you should dump your state. This will be
1518 * closed for you after you return.
1519 * @param args additional arguments to the dump request.
Marco Nelissen18cb2872011-11-15 11:19:53 -08001520 */
1521 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1522 writer.println("nothing to dump");
1523 }
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001524}