blob: 24c396a903ed10e6a1c786ac56f768c1b7a97ade [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
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700105 private final ThreadLocal<String> mCallingPackage = new ThreadLocal<String>();
106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 private Transport mTransport = new Transport();
108
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700109 /**
110 * Construct a ContentProvider instance. Content providers must be
111 * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared
112 * in the manifest</a>, accessed with {@link ContentResolver}, and created
113 * automatically by the system, so applications usually do not create
114 * ContentProvider instances directly.
115 *
116 * <p>At construction time, the object is uninitialized, and most fields and
117 * methods are unavailable. Subclasses should initialize themselves in
118 * {@link #onCreate}, not the constructor.
119 *
120 * <p>Content providers are created on the application main thread at
121 * application launch time. The constructor must not perform lengthy
122 * operations, or application startup will be delayed.
123 */
Daisuke Miyakawa8280c2b2009-10-22 08:36:42 +0900124 public ContentProvider() {
125 }
126
127 /**
128 * Constructor just for mocking.
129 *
130 * @param context A Context object which should be some mock instance (like the
131 * instance of {@link android.test.mock.MockContext}).
132 * @param readPermission The read permision you want this instance should have in the
133 * test, which is available via {@link #getReadPermission()}.
134 * @param writePermission The write permission you want this instance should have
135 * in the test, which is available via {@link #getWritePermission()}.
136 * @param pathPermissions The PathPermissions you want this instance should have
137 * in the test, which is available via {@link #getPathPermissions()}.
138 * @hide
139 */
140 public ContentProvider(
141 Context context,
142 String readPermission,
143 String writePermission,
144 PathPermission[] pathPermissions) {
145 mContext = context;
146 mReadPermission = readPermission;
147 mWritePermission = writePermission;
148 mPathPermissions = pathPermissions;
149 }
150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 /**
152 * Given an IContentProvider, try to coerce it back to the real
153 * ContentProvider object if it is running in the local process. This can
154 * be used if you know you are running in the same process as a provider,
155 * and want to get direct access to its implementation details. Most
156 * clients should not nor have a reason to use it.
157 *
158 * @param abstractInterface The ContentProvider interface that is to be
159 * coerced.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800160 * @return If the IContentProvider is non-{@code null} and local, returns its actual
161 * ContentProvider instance. Otherwise returns {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 * @hide
163 */
164 public static ContentProvider coerceToLocalContentProvider(
165 IContentProvider abstractInterface) {
166 if (abstractInterface instanceof Transport) {
167 return ((Transport)abstractInterface).getContentProvider();
168 }
169 return null;
170 }
171
172 /**
173 * Binder object that deals with remoting.
174 *
175 * @hide
176 */
177 class Transport extends ContentProviderNative {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800178 AppOpsManager mAppOpsManager = null;
Dianne Hackborn961321f2013-02-05 17:22:41 -0800179 int mReadOp = AppOpsManager.OP_NONE;
180 int mWriteOp = AppOpsManager.OP_NONE;
Dianne Hackborn35654b62013-01-14 17:38:02 -0800181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 ContentProvider getContentProvider() {
183 return ContentProvider.this;
184 }
185
Jeff Brownd2183652011-10-09 12:39:53 -0700186 @Override
187 public String getProviderName() {
188 return getContentProvider().getClass().getName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 }
190
Jeff Brown75ea64f2012-01-25 19:37:13 -0800191 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800192 public Cursor query(String callingPkg, Uri uri, String[] projection,
Jeff Brown75ea64f2012-01-25 19:37:13 -0800193 String selection, String[] selectionArgs, String sortOrder,
Jeff Brown4c1241d2012-02-02 17:05:00 -0800194 ICancellationSignal cancellationSignal) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800195 if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800196 return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
197 CancellationSignal.fromTransport(cancellationSignal));
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800198 }
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700199 mCallingPackage.set(callingPkg);
200 try {
201 return ContentProvider.this.query(
202 uri, projection, selection, selectionArgs, sortOrder,
203 CancellationSignal.fromTransport(cancellationSignal));
204 } finally {
205 mCallingPackage.set(null);
206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 }
208
Jeff Brown75ea64f2012-01-25 19:37:13 -0800209 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 public String getType(Uri uri) {
211 return ContentProvider.this.getType(uri);
212 }
213
Jeff Brown75ea64f2012-01-25 19:37:13 -0800214 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800215 public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800216 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800217 return rejectInsert(uri, initialValues);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800218 }
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700219 mCallingPackage.set(callingPkg);
220 try {
221 return ContentProvider.this.insert(uri, initialValues);
222 } finally {
223 mCallingPackage.set(null);
224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 }
226
Jeff Brown75ea64f2012-01-25 19:37:13 -0800227 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800228 public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
229 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
230 return 0;
231 }
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700232 mCallingPackage.set(callingPkg);
233 try {
234 return ContentProvider.this.bulkInsert(uri, initialValues);
235 } finally {
236 mCallingPackage.set(null);
237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 }
239
Jeff Brown75ea64f2012-01-25 19:37:13 -0800240 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800241 public ContentProviderResult[] applyBatch(String callingPkg,
242 ArrayList<ContentProviderOperation> operations)
Fred Quintana89437372009-05-15 15:10:40 -0700243 throws OperationApplicationException {
244 for (ContentProviderOperation operation : operations) {
245 if (operation.isReadOperation()) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800246 if (enforceReadPermission(callingPkg, operation.getUri())
247 != AppOpsManager.MODE_ALLOWED) {
248 throw new OperationApplicationException("App op not allowed", 0);
249 }
Fred Quintana89437372009-05-15 15:10:40 -0700250 }
251
252 if (operation.isWriteOperation()) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800253 if (enforceWritePermission(callingPkg, operation.getUri())
254 != AppOpsManager.MODE_ALLOWED) {
255 throw new OperationApplicationException("App op not allowed", 0);
256 }
Fred Quintana89437372009-05-15 15:10:40 -0700257 }
258 }
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700259 mCallingPackage.set(callingPkg);
260 try {
261 return ContentProvider.this.applyBatch(operations);
262 } finally {
263 mCallingPackage.set(null);
264 }
Fred Quintana6a8d5332009-05-07 17:35:38 -0700265 }
266
Jeff Brown75ea64f2012-01-25 19:37:13 -0800267 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800268 public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
269 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
270 return 0;
271 }
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700272 mCallingPackage.set(callingPkg);
273 try {
274 return ContentProvider.this.delete(uri, selection, selectionArgs);
275 } finally {
276 mCallingPackage.set(null);
277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 }
279
Jeff Brown75ea64f2012-01-25 19:37:13 -0800280 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800281 public int update(String callingPkg, Uri uri, ContentValues values, String selection,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 String[] selectionArgs) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800283 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
284 return 0;
285 }
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700286 mCallingPackage.set(callingPkg);
287 try {
288 return ContentProvider.this.update(uri, values, selection, selectionArgs);
289 } finally {
290 mCallingPackage.set(null);
291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 }
293
Jeff Brown75ea64f2012-01-25 19:37:13 -0800294 @Override
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700295 public ParcelFileDescriptor openFile(
296 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 throws FileNotFoundException {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800298 enforceFilePermission(callingPkg, uri, mode);
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700299 mCallingPackage.set(callingPkg);
300 try {
301 return ContentProvider.this.openFile(
302 uri, mode, CancellationSignal.fromTransport(cancellationSignal));
303 } finally {
304 mCallingPackage.set(null);
305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 }
307
Jeff Brown75ea64f2012-01-25 19:37:13 -0800308 @Override
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700309 public AssetFileDescriptor openAssetFile(
310 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 throws FileNotFoundException {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800312 enforceFilePermission(callingPkg, uri, mode);
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700313 mCallingPackage.set(callingPkg);
314 try {
315 return ContentProvider.this.openAssetFile(
316 uri, mode, CancellationSignal.fromTransport(cancellationSignal));
317 } finally {
318 mCallingPackage.set(null);
319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 }
321
Jeff Brown75ea64f2012-01-25 19:37:13 -0800322 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800323 public Bundle call(String callingPkg, String method, String arg, Bundle extras) {
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700324 mCallingPackage.set(callingPkg);
325 try {
326 return ContentProvider.this.call(method, arg, extras);
327 } finally {
328 mCallingPackage.set(null);
329 }
Brad Fitzpatrick1877d012010-03-04 17:48:13 -0800330 }
331
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700332 @Override
333 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
334 return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
335 }
336
337 @Override
Dianne Hackborn35654b62013-01-14 17:38:02 -0800338 public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700339 Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800340 enforceFilePermission(callingPkg, uri, "r");
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700341 mCallingPackage.set(callingPkg);
342 try {
343 return ContentProvider.this.openTypedAssetFile(
344 uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
345 } finally {
346 mCallingPackage.set(null);
347 }
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700348 }
349
Jeff Brown75ea64f2012-01-25 19:37:13 -0800350 @Override
Jeff Brown4c1241d2012-02-02 17:05:00 -0800351 public ICancellationSignal createCancellationSignal() throws RemoteException {
352 return CancellationSignal.createTransport();
Jeff Brown75ea64f2012-01-25 19:37:13 -0800353 }
354
Dianne Hackborn35654b62013-01-14 17:38:02 -0800355 private void enforceFilePermission(String callingPkg, Uri uri, String mode)
356 throws FileNotFoundException, SecurityException {
Jeff Sharkeyba761972013-02-28 15:57:36 -0800357 if (mode != null && mode.indexOf('w') != -1) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800358 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
359 throw new FileNotFoundException("App op not allowed");
360 }
361 } else {
362 if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
363 throw new FileNotFoundException("App op not allowed");
364 }
365 }
366 }
367
368 private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException {
369 enforceReadPermissionInner(uri);
Dianne Hackborn961321f2013-02-05 17:22:41 -0800370 if (mReadOp != AppOpsManager.OP_NONE) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800371 return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg);
372 }
373 return AppOpsManager.MODE_ALLOWED;
374 }
375
376 private void enforceReadPermissionInner(Uri uri) throws SecurityException {
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700377 final Context context = getContext();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 final int pid = Binder.getCallingPid();
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700379 final int uid = Binder.getCallingUid();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700380 String missingPerm = null;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700381
Dianne Hackborn0d8af782012-08-17 16:51:54 -0700382 if (UserHandle.isSameApp(uid, mMyUid)) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700383 return;
384 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700385
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700386 if (mExported) {
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700387 final String componentPerm = getReadPermission();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700388 if (componentPerm != null) {
389 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
390 return;
391 } else {
392 missingPerm = componentPerm;
393 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700394 }
395
396 // track if unprotected read is allowed; any denied
397 // <path-permission> below removes this ability
398 boolean allowDefaultRead = (componentPerm == null);
399
400 final PathPermission[] pps = getPathPermissions();
401 if (pps != null) {
402 final String path = uri.getPath();
403 for (PathPermission pp : pps) {
404 final String pathPerm = pp.getReadPermission();
405 if (pathPerm != null && pp.match(path)) {
406 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700407 return;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700408 } else {
409 // any denied <path-permission> means we lose
410 // default <provider> access.
411 allowDefaultRead = false;
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700412 missingPerm = pathPerm;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700413 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700414 }
415 }
416 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700417
418 // if we passed <path-permission> checks above, and no default
419 // <provider> permission, then allow access.
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700420 if (allowDefaultRead) return;
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700421 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700422
423 // last chance, check against any uri grants
424 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
425 == PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 return;
427 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700428
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700429 final String failReason = mExported
430 ? " requires " + missingPerm + ", or grantUriPermission()"
431 : " requires the provider be exported, or grantUriPermission()";
432 throw new SecurityException("Permission Denial: reading "
433 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
434 + ", uid=" + uid + failReason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 }
436
Dianne Hackborn35654b62013-01-14 17:38:02 -0800437 private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
438 enforceWritePermissionInner(uri);
Dianne Hackborn961321f2013-02-05 17:22:41 -0800439 if (mWriteOp != AppOpsManager.OP_NONE) {
Dianne Hackborn35654b62013-01-14 17:38:02 -0800440 return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg);
441 }
442 return AppOpsManager.MODE_ALLOWED;
443 }
444
445 private void enforceWritePermissionInner(Uri uri) throws SecurityException {
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700446 final Context context = getContext();
447 final int pid = Binder.getCallingPid();
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700448 final int uid = Binder.getCallingUid();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700449 String missingPerm = null;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700450
Dianne Hackborn0d8af782012-08-17 16:51:54 -0700451 if (UserHandle.isSameApp(uid, mMyUid)) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700452 return;
453 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700454
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700455 if (mExported) {
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700456 final String componentPerm = getWritePermission();
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700457 if (componentPerm != null) {
458 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
459 return;
460 } else {
461 missingPerm = componentPerm;
462 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700463 }
464
465 // track if unprotected write is allowed; any denied
466 // <path-permission> below removes this ability
467 boolean allowDefaultWrite = (componentPerm == null);
468
469 final PathPermission[] pps = getPathPermissions();
470 if (pps != null) {
471 final String path = uri.getPath();
472 for (PathPermission pp : pps) {
473 final String pathPerm = pp.getWritePermission();
474 if (pathPerm != null && pp.match(path)) {
475 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700476 return;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700477 } else {
478 // any denied <path-permission> means we lose
479 // default <provider> access.
480 allowDefaultWrite = false;
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700481 missingPerm = pathPerm;
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700482 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700483 }
484 }
485 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700486
487 // if we passed <path-permission> checks above, and no default
488 // <provider> permission, then allow access.
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700489 if (allowDefaultWrite) return;
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700490 }
Jeff Sharkey110a6b62012-03-12 11:12:41 -0700491
492 // last chance, check against any uri grants
493 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
494 == PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 return;
496 }
Jeff Sharkeye5d49332012-03-13 12:13:17 -0700497
498 final String failReason = mExported
499 ? " requires " + missingPerm + ", or grantUriPermission()"
500 : " requires the provider be exported, or grantUriPermission()";
501 throw new SecurityException("Permission Denial: writing "
502 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
503 + ", uid=" + uid + failReason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 }
505 }
506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700508 * Retrieves the Context this provider is running in. Only available once
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800509 * {@link #onCreate} has been called -- this will return {@code null} in the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 * constructor.
511 */
512 public final Context getContext() {
513 return mContext;
514 }
515
516 /**
Jeff Sharkey911d7f42013-09-05 18:11:45 -0700517 * Return the package name of the caller that initiated the request being
518 * processed on the current thread. The returned package will have been
519 * verified to belong to the calling UID. Returns {@code null} if not
520 * currently processing a request.
521 * <p>
522 * This will always return {@code null} when processing
523 * {@link #getType(Uri)} or {@link #getStreamTypes(Uri, String)} requests.
524 *
525 * @see Binder#getCallingUid()
526 * @see Context#grantUriPermission(String, Uri, int)
527 * @throws SecurityException if the calling package doesn't belong to the
528 * calling UID.
529 */
530 public final String getCallingPackage() {
531 final String pkg = mCallingPackage.get();
532 if (pkg != null) {
533 mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
534 }
535 return pkg;
536 }
537
538 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 * Change the permission required to read data from the content
540 * provider. This is normally set for you from its manifest information
541 * when the provider is first created.
542 *
543 * @param permission Name of the permission required for read-only access.
544 */
545 protected final void setReadPermission(String permission) {
546 mReadPermission = permission;
547 }
548
549 /**
550 * Return the name of the permission required for read-only access to
551 * this content provider. This method can be called from multiple
552 * threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800553 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
554 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 */
556 public final String getReadPermission() {
557 return mReadPermission;
558 }
559
560 /**
561 * Change the permission required to read and write data in the content
562 * provider. This is normally set for you from its manifest information
563 * when the provider is first created.
564 *
565 * @param permission Name of the permission required for read/write access.
566 */
567 protected final void setWritePermission(String permission) {
568 mWritePermission = permission;
569 }
570
571 /**
572 * Return the name of the permission required for read/write access to
573 * this content provider. This method can be called from multiple
574 * threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800575 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
576 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 */
578 public final String getWritePermission() {
579 return mWritePermission;
580 }
581
582 /**
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700583 * Change the path-based permission required to read and/or write data in
584 * the content provider. This is normally set for you from its manifest
585 * information when the provider is first created.
586 *
587 * @param permissions Array of path permission descriptions.
588 */
589 protected final void setPathPermissions(PathPermission[] permissions) {
590 mPathPermissions = permissions;
591 }
592
593 /**
594 * Return the path-based permissions required for read and/or write access to
595 * this content provider. This method can be called from multiple
596 * threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800597 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
598 * and Threads</a>.
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700599 */
600 public final PathPermission[] getPathPermissions() {
601 return mPathPermissions;
602 }
603
Dianne Hackborn35654b62013-01-14 17:38:02 -0800604 /** @hide */
605 public final void setAppOps(int readOp, int writeOp) {
Dianne Hackborn7e6f9762013-02-26 13:35:11 -0800606 if (!mNoPerms) {
Dianne Hackborn7e6f9762013-02-26 13:35:11 -0800607 mTransport.mReadOp = readOp;
608 mTransport.mWriteOp = writeOp;
609 }
Dianne Hackborn35654b62013-01-14 17:38:02 -0800610 }
611
Dianne Hackborn961321f2013-02-05 17:22:41 -0800612 /** @hide */
613 public AppOpsManager getAppOpsManager() {
614 return mTransport.mAppOpsManager;
615 }
616
Dianne Hackborn2af632f2009-07-08 14:56:37 -0700617 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700618 * Implement this to initialize your content provider on startup.
619 * This method is called for all registered content providers on the
620 * application main thread at application launch time. It must not perform
621 * lengthy operations, or application startup will be delayed.
622 *
623 * <p>You should defer nontrivial initialization (such as opening,
624 * upgrading, and scanning databases) until the content provider is used
625 * (via {@link #query}, {@link #insert}, etc). Deferred initialization
626 * keeps application startup fast, avoids unnecessary work if the provider
627 * turns out not to be needed, and stops database errors (such as a full
628 * disk) from halting application launch.
629 *
Dan Egnor17876aa2010-07-28 12:28:04 -0700630 * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper}
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700631 * is a helpful utility class that makes it easy to manage databases,
632 * and will automatically defer opening until first use. If you do use
633 * SQLiteOpenHelper, make sure to avoid calling
634 * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or
635 * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase}
636 * from this method. (Instead, override
637 * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the
638 * database when it is first opened.)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 *
640 * @return true if the provider was successfully loaded, false otherwise
641 */
642 public abstract boolean onCreate();
643
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700644 /**
645 * {@inheritDoc}
646 * This method is always called on the application main thread, and must
647 * not perform lengthy operations.
648 *
649 * <p>The default content provider implementation does nothing.
650 * Override this method to take appropriate action.
651 * (Content providers do not usually care about things like screen
652 * orientation, but may want to know about locale changes.)
653 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 public void onConfigurationChanged(Configuration newConfig) {
655 }
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700656
657 /**
658 * {@inheritDoc}
659 * This method is always called on the application main thread, and must
660 * not perform lengthy operations.
661 *
662 * <p>The default content provider implementation does nothing.
663 * Subclasses may override this method to take appropriate action.
664 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 public void onLowMemory() {
666 }
667
Dianne Hackbornc68c9132011-07-29 01:25:18 -0700668 public void onTrimMemory(int level) {
669 }
670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 /**
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800672 * @hide
673 * Implementation when a caller has performed a query on the content
674 * provider, but that call has been rejected for the operation given
675 * to {@link #setAppOps(int, int)}. The default implementation
676 * rewrites the <var>selection</var> argument to include a condition
677 * that is never true (so will always result in an empty cursor)
678 * and calls through to {@link #query(android.net.Uri, String[], String, String[],
679 * String, android.os.CancellationSignal)} with that.
680 */
681 public Cursor rejectQuery(Uri uri, String[] projection,
682 String selection, String[] selectionArgs, String sortOrder,
683 CancellationSignal cancellationSignal) {
684 // The read is not allowed... to fake it out, we replace the given
685 // selection statement with a dummy one that will always be false.
686 // This way we will get a cursor back that has the correct structure
687 // but contains no rows.
Dianne Hackborn9fa39bd2013-03-22 18:42:14 -0700688 if (selection == null || selection.isEmpty()) {
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800689 selection = "'A' = 'B'";
690 } else {
691 selection = "'A' = 'B' AND (" + selection + ")";
692 }
693 return query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);
694 }
695
696 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700697 * Implement this to handle query requests from clients.
698 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800699 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
700 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 * <p>
702 * Example client call:<p>
703 * <pre>// Request a specific record.
704 * Cursor managedCursor = managedQuery(
Alan Jones81a476f2009-05-21 12:32:17 +1000705 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 projection, // Which columns to return.
707 null, // WHERE clause.
Alan Jones81a476f2009-05-21 12:32:17 +1000708 null, // WHERE clause value substitution
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709 People.NAME + " ASC"); // Sort order.</pre>
710 * Example implementation:<p>
711 * <pre>// SQLiteQueryBuilder is a helper class that creates the
712 // proper SQL syntax for us.
713 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
714
715 // Set the table we're querying.
716 qBuilder.setTables(DATABASE_TABLE_NAME);
717
718 // If the query ends in a specific record number, we're
719 // being asked for a specific record, so set the
720 // WHERE clause in our query.
721 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
722 qBuilder.appendWhere("_id=" + uri.getPathLeafId());
723 }
724
725 // Make the query.
726 Cursor c = qBuilder.query(mDb,
727 projection,
728 selection,
729 selectionArgs,
730 groupBy,
731 having,
732 sortOrder);
733 c.setNotificationUri(getContext().getContentResolver(), uri);
734 return c;</pre>
735 *
736 * @param uri The URI to query. This will be the full URI sent by the client;
Alan Jones81a476f2009-05-21 12:32:17 +1000737 * if the client is requesting a specific record, the URI will end in a record number
738 * that the implementation should parse and add to a WHERE or HAVING clause, specifying
739 * that _id value.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 * @param projection The list of columns to put into the cursor. If
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800741 * {@code null} all columns are included.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 * @param selection A selection criteria to apply when filtering rows.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800743 * If {@code null} then all rows are included.
Alan Jones81a476f2009-05-21 12:32:17 +1000744 * @param selectionArgs You may include ?s in selection, which will be replaced by
745 * the values from selectionArgs, in order that they appear in the selection.
746 * The values will be bound as Strings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 * @param sortOrder How the rows in the cursor should be sorted.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800748 * If {@code null} then the provider is free to define the sort order.
749 * @return a Cursor or {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 */
751 public abstract Cursor query(Uri uri, String[] projection,
752 String selection, String[] selectionArgs, String sortOrder);
753
Fred Quintana5bba6322009-10-05 14:21:12 -0700754 /**
Jeff Brown4c1241d2012-02-02 17:05:00 -0800755 * Implement this to handle query requests from clients with support for cancellation.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800756 * This method can be called from multiple threads, as described in
757 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
758 * and Threads</a>.
759 * <p>
760 * Example client call:<p>
761 * <pre>// Request a specific record.
762 * Cursor managedCursor = managedQuery(
763 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
764 projection, // Which columns to return.
765 null, // WHERE clause.
766 null, // WHERE clause value substitution
767 People.NAME + " ASC"); // Sort order.</pre>
768 * Example implementation:<p>
769 * <pre>// SQLiteQueryBuilder is a helper class that creates the
770 // proper SQL syntax for us.
771 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
772
773 // Set the table we're querying.
774 qBuilder.setTables(DATABASE_TABLE_NAME);
775
776 // If the query ends in a specific record number, we're
777 // being asked for a specific record, so set the
778 // WHERE clause in our query.
779 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
780 qBuilder.appendWhere("_id=" + uri.getPathLeafId());
781 }
782
783 // Make the query.
784 Cursor c = qBuilder.query(mDb,
785 projection,
786 selection,
787 selectionArgs,
788 groupBy,
789 having,
790 sortOrder);
791 c.setNotificationUri(getContext().getContentResolver(), uri);
792 return c;</pre>
793 * <p>
794 * If you implement this method then you must also implement the version of
Jeff Brown4c1241d2012-02-02 17:05:00 -0800795 * {@link #query(Uri, String[], String, String[], String)} that does not take a cancellation
796 * signal to ensure correct operation on older versions of the Android Framework in
797 * which the cancellation signal overload was not available.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800798 *
799 * @param uri The URI to query. This will be the full URI sent by the client;
800 * if the client is requesting a specific record, the URI will end in a record number
801 * that the implementation should parse and add to a WHERE or HAVING clause, specifying
802 * that _id value.
803 * @param projection The list of columns to put into the cursor. If
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800804 * {@code null} all columns are included.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800805 * @param selection A selection criteria to apply when filtering rows.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800806 * If {@code null} then all rows are included.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800807 * @param selectionArgs You may include ?s in selection, which will be replaced by
808 * the values from selectionArgs, in order that they appear in the selection.
809 * The values will be bound as Strings.
810 * @param sortOrder How the rows in the cursor should be sorted.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800811 * If {@code null} then the provider is free to define the sort order.
812 * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if none.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800813 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
814 * when the query is executed.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800815 * @return a Cursor or {@code null}.
Jeff Brown75ea64f2012-01-25 19:37:13 -0800816 */
817 public Cursor query(Uri uri, String[] projection,
818 String selection, String[] selectionArgs, String sortOrder,
Jeff Brown4c1241d2012-02-02 17:05:00 -0800819 CancellationSignal cancellationSignal) {
Jeff Brown75ea64f2012-01-25 19:37:13 -0800820 return query(uri, projection, selection, selectionArgs, sortOrder);
821 }
822
823 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700824 * Implement this to handle requests for the MIME type of the data at the
825 * given URI. The returned MIME type should start with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 * <code>vnd.android.cursor.item</code> for a single record,
827 * or <code>vnd.android.cursor.dir/</code> for multiple items.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700828 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800829 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
830 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 *
Dianne Hackborncca1f0e2010-09-26 18:34:53 -0700832 * <p>Note that there are no permissions needed for an application to
833 * access this information; if your content provider requires read and/or
834 * write permissions, or is not exported, all applications can still call
835 * this method regardless of their access permissions. This allows them
836 * to retrieve the MIME type for a URI when dispatching intents.
837 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 * @param uri the URI to query.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800839 * @return a MIME type string, or {@code null} if there is no type.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 */
841 public abstract String getType(Uri uri);
842
843 /**
Dianne Hackbornd7960d12013-01-29 18:55:48 -0800844 * @hide
845 * Implementation when a caller has performed an insert on the content
846 * provider, but that call has been rejected for the operation given
847 * to {@link #setAppOps(int, int)}. The default implementation simply
848 * returns a dummy URI that is the base URI with a 0 path element
849 * appended.
850 */
851 public Uri rejectInsert(Uri uri, ContentValues values) {
852 // If not allowed, we need to return some reasonable URI. Maybe the
853 // content provider should be responsible for this, but for now we
854 // will just return the base URI with a dummy '0' tagged on to it.
855 // You shouldn't be able to read if you can't write, anyway, so it
856 // shouldn't matter much what is returned.
857 return uri.buildUpon().appendPath("0").build();
858 }
859
860 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700861 * Implement this to handle requests to insert a new row.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
863 * after inserting.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700864 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800865 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
866 * and Threads</a>.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800867 * @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 -0800868 * @param values A set of column_name/value pairs to add to the database.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800869 * This must not be {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 * @return The URI for the newly inserted item.
871 */
872 public abstract Uri insert(Uri uri, ContentValues values);
873
874 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700875 * Override this to handle requests to insert a set of new rows, or the
876 * default implementation will iterate over the values and call
877 * {@link #insert} on each of them.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
879 * after inserting.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700880 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800881 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
882 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 *
884 * @param uri The content:// URI of the insertion request.
885 * @param values An array of sets of column_name/value pairs to add to the database.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800886 * This must not be {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 * @return The number of values that were inserted.
888 */
889 public int bulkInsert(Uri uri, ContentValues[] values) {
890 int numValues = values.length;
891 for (int i = 0; i < numValues; i++) {
892 insert(uri, values[i]);
893 }
894 return numValues;
895 }
896
897 /**
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700898 * Implement this to handle requests to delete one or more rows.
899 * The implementation should apply the selection clause when performing
900 * deletion, allowing the operation to affect multiple rows in a directory.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
902 * after deleting.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700903 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800904 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
905 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 *
907 * <p>The implementation is responsible for parsing out a row ID at the end
908 * of the URI, if a specific row is being deleted. That is, the client would
909 * pass in <code>content://contacts/people/22</code> and the implementation is
910 * responsible for parsing the record number (22) when creating a SQL statement.
911 *
912 * @param uri The full URI to query, including a row ID (if a specific record is requested).
913 * @param selection An optional restriction to apply to rows when deleting.
914 * @return The number of rows affected.
915 * @throws SQLException
916 */
917 public abstract int delete(Uri uri, String selection, String[] selectionArgs);
918
919 /**
Dan Egnor17876aa2010-07-28 12:28:04 -0700920 * Implement this to handle requests to update one or more rows.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700921 * The implementation should update all rows matching the selection
922 * to set the columns according to the provided values map.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
924 * after updating.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700925 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800926 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
927 * and Threads</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 *
929 * @param uri The URI to query. This can potentially have a record ID if this
930 * is an update request for a specific record.
Christopher Tate2bc6eb82013-01-03 12:04:08 -0800931 * @param values A set of column_name/value pairs to update in the database.
932 * This must not be {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 * @param selection An optional filter to match rows to update.
934 * @return the number of rows affected.
935 */
936 public abstract int update(Uri uri, ContentValues values, String selection,
937 String[] selectionArgs);
938
939 /**
Dan Egnor17876aa2010-07-28 12:28:04 -0700940 * Override this to handle requests to open a file blob.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700941 * The default implementation always throws {@link FileNotFoundException}.
942 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -0800943 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
944 * and Threads</a>.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700945 *
Dan Egnor17876aa2010-07-28 12:28:04 -0700946 * <p>This method returns a ParcelFileDescriptor, which is returned directly
947 * to the caller. This way large data (such as images and documents) can be
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700948 * returned without copying the content.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 *
950 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
951 * their responsibility to close it when done. That is, the implementation
952 * of this method should create a new ParcelFileDescriptor for each call.
Jeff Sharkeybd3b9022013-08-20 15:20:04 -0700953 * <p>
954 * If opened with the exclusive "r" or "w" modes, the returned
955 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming
956 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that
957 * supports seeking.
958 * <p>
959 * If you need to detect when the returned ParcelFileDescriptor has been
960 * closed, or if the remote process has crashed or encountered some other
961 * error, you can use {@link ParcelFileDescriptor#open(File, int,
962 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)},
963 * {@link ParcelFileDescriptor#createReliablePipe()}, or
964 * {@link ParcelFileDescriptor#createReliableSocketPair()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 *
Dianne Hackborna53ee352013-02-20 12:47:02 -0800966 * <p class="note">For use in Intents, you will want to implement {@link #getType}
967 * to return the appropriate MIME type for the data returned here with
968 * the same URI. This will allow intent resolution to automatically determine the data MIME
969 * type and select the appropriate matching targets as part of its operation.</p>
970 *
971 * <p class="note">For better interoperability with other applications, it is recommended
972 * that for any URIs that can be opened, you also support queries on them
973 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
974 * You may also want to support other common columns if you have additional meta-data
975 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
976 * in {@link android.provider.MediaStore.MediaColumns}.</p>
977 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 * @param uri The URI whose file is to be opened.
979 * @param mode Access mode for the file. May be "r" for read-only access,
980 * "rw" for read and write access, or "rwt" for read and write access
981 * that truncates any existing file.
982 *
983 * @return Returns a new ParcelFileDescriptor which you can use to access
984 * the file.
985 *
986 * @throws FileNotFoundException Throws FileNotFoundException if there is
987 * no file associated with the given URI or the mode is invalid.
988 * @throws SecurityException Throws SecurityException if the caller does
989 * not have permission to access the file.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700990 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 * @see #openAssetFile(Uri, String)
992 * @see #openFileHelper(Uri, String)
Dianne Hackborna53ee352013-02-20 12:47:02 -0800993 * @see #getType(android.net.Uri)
Dan Egnor6fcc0f0732010-07-27 16:32:17 -0700994 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 public ParcelFileDescriptor openFile(Uri uri, String mode)
996 throws FileNotFoundException {
997 throw new FileNotFoundException("No files supported by provider at "
998 + uri);
999 }
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 /**
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001002 * Override this to handle requests to open a file blob.
1003 * The default implementation always throws {@link FileNotFoundException}.
1004 * This method can be called from multiple threads, as described in
1005 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1006 * and Threads</a>.
1007 *
1008 * <p>This method returns a ParcelFileDescriptor, which is returned directly
1009 * to the caller. This way large data (such as images and documents) can be
1010 * returned without copying the content.
1011 *
1012 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
1013 * their responsibility to close it when done. That is, the implementation
1014 * of this method should create a new ParcelFileDescriptor for each call.
1015 * <p>
1016 * If opened with the exclusive "r" or "w" modes, the returned
1017 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming
1018 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that
1019 * supports seeking.
1020 * <p>
1021 * If you need to detect when the returned ParcelFileDescriptor has been
1022 * closed, or if the remote process has crashed or encountered some other
1023 * error, you can use {@link ParcelFileDescriptor#open(File, int,
1024 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)},
1025 * {@link ParcelFileDescriptor#createReliablePipe()}, or
1026 * {@link ParcelFileDescriptor#createReliableSocketPair()}.
1027 *
1028 * <p class="note">For use in Intents, you will want to implement {@link #getType}
1029 * to return the appropriate MIME type for the data returned here with
1030 * the same URI. This will allow intent resolution to automatically determine the data MIME
1031 * type and select the appropriate matching targets as part of its operation.</p>
1032 *
1033 * <p class="note">For better interoperability with other applications, it is recommended
1034 * that for any URIs that can be opened, you also support queries on them
1035 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1036 * You may also want to support other common columns if you have additional meta-data
1037 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1038 * in {@link android.provider.MediaStore.MediaColumns}.</p>
1039 *
1040 * @param uri The URI whose file is to be opened.
1041 * @param mode Access mode for the file. May be "r" for read-only access,
1042 * "w" for write-only access, "rw" for read and write access, or
1043 * "rwt" for read and write access that truncates any existing
1044 * file.
1045 * @param signal A signal to cancel the operation in progress, or
1046 * {@code null} if none. For example, if you are downloading a
1047 * file from the network to service a "rw" mode request, you
1048 * should periodically call
1049 * {@link CancellationSignal#throwIfCanceled()} to check whether
1050 * the client has canceled the request and abort the download.
1051 *
1052 * @return Returns a new ParcelFileDescriptor which you can use to access
1053 * the file.
1054 *
1055 * @throws FileNotFoundException Throws FileNotFoundException if there is
1056 * no file associated with the given URI or the mode is invalid.
1057 * @throws SecurityException Throws SecurityException if the caller does
1058 * not have permission to access the file.
1059 *
1060 * @see #openAssetFile(Uri, String)
1061 * @see #openFileHelper(Uri, String)
1062 * @see #getType(android.net.Uri)
1063 */
1064 public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
1065 throws FileNotFoundException {
1066 return openFile(uri, mode);
1067 }
1068
1069 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 * This is like {@link #openFile}, but can be implemented by providers
1071 * that need to be able to return sub-sections of files, often assets
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001072 * inside of their .apk.
1073 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -08001074 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1075 * and Threads</a>.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001076 *
1077 * <p>If you implement this, your clients must be able to deal with such
Dan Egnor17876aa2010-07-28 12:28:04 -07001078 * file slices, either directly with
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001079 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
1081 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
1082 * methods.
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001083 * <p>
1084 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1085 * streaming of data.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001086 *
1087 * <p class="note">If you are implementing this to return a full file, you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 * should create the AssetFileDescriptor with
1089 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001090 * applications that cannot handle sub-sections of files.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 *
Dianne Hackborna53ee352013-02-20 12:47:02 -08001092 * <p class="note">For use in Intents, you will want to implement {@link #getType}
1093 * to return the appropriate MIME type for the data returned here with
1094 * the same URI. This will allow intent resolution to automatically determine the data MIME
1095 * type and select the appropriate matching targets as part of its operation.</p>
1096 *
1097 * <p class="note">For better interoperability with other applications, it is recommended
1098 * that for any URIs that can be opened, you also support queries on them
1099 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
1100 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 * @param uri The URI whose file is to be opened.
1102 * @param mode Access mode for the file. May be "r" for read-only access,
1103 * "w" for write-only access (erasing whatever data is currently in
1104 * the file), "wa" for write-only access to append to any existing data,
1105 * "rw" for read and write access on any existing data, and "rwt" for read
1106 * and write access that truncates any existing file.
1107 *
1108 * @return Returns a new AssetFileDescriptor which you can use to access
1109 * the file.
1110 *
1111 * @throws FileNotFoundException Throws FileNotFoundException if there is
1112 * no file associated with the given URI or the mode is invalid.
1113 * @throws SecurityException Throws SecurityException if the caller does
1114 * not have permission to access the file.
1115 *
1116 * @see #openFile(Uri, String)
1117 * @see #openFileHelper(Uri, String)
Dianne Hackborna53ee352013-02-20 12:47:02 -08001118 * @see #getType(android.net.Uri)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 */
1120 public AssetFileDescriptor openAssetFile(Uri uri, String mode)
1121 throws FileNotFoundException {
1122 ParcelFileDescriptor fd = openFile(uri, mode);
1123 return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
1124 }
1125
1126 /**
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001127 * This is like {@link #openFile}, but can be implemented by providers
1128 * that need to be able to return sub-sections of files, often assets
1129 * inside of their .apk.
1130 * This method can be called from multiple threads, as described in
1131 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1132 * and Threads</a>.
1133 *
1134 * <p>If you implement this, your clients must be able to deal with such
1135 * file slices, either directly with
1136 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
1137 * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
1138 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
1139 * methods.
1140 * <p>
1141 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1142 * streaming of data.
1143 *
1144 * <p class="note">If you are implementing this to return a full file, you
1145 * should create the AssetFileDescriptor with
1146 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
1147 * applications that cannot handle sub-sections of files.</p>
1148 *
1149 * <p class="note">For use in Intents, you will want to implement {@link #getType}
1150 * to return the appropriate MIME type for the data returned here with
1151 * the same URI. This will allow intent resolution to automatically determine the data MIME
1152 * type and select the appropriate matching targets as part of its operation.</p>
1153 *
1154 * <p class="note">For better interoperability with other applications, it is recommended
1155 * that for any URIs that can be opened, you also support queries on them
1156 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
1157 *
1158 * @param uri The URI whose file is to be opened.
1159 * @param mode Access mode for the file. May be "r" for read-only access,
1160 * "w" for write-only access (erasing whatever data is currently in
1161 * the file), "wa" for write-only access to append to any existing data,
1162 * "rw" for read and write access on any existing data, and "rwt" for read
1163 * and write access that truncates any existing file.
1164 * @param signal A signal to cancel the operation in progress, or
1165 * {@code null} if none. For example, if you are downloading a
1166 * file from the network to service a "rw" mode request, you
1167 * should periodically call
1168 * {@link CancellationSignal#throwIfCanceled()} to check whether
1169 * the client has canceled the request and abort the download.
1170 *
1171 * @return Returns a new AssetFileDescriptor which you can use to access
1172 * the file.
1173 *
1174 * @throws FileNotFoundException Throws FileNotFoundException if there is
1175 * no file associated with the given URI or the mode is invalid.
1176 * @throws SecurityException Throws SecurityException if the caller does
1177 * not have permission to access the file.
1178 *
1179 * @see #openFile(Uri, String)
1180 * @see #openFileHelper(Uri, String)
1181 * @see #getType(android.net.Uri)
1182 */
1183 public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal)
1184 throws FileNotFoundException {
1185 return openAssetFile(uri, mode);
1186 }
1187
1188 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 * Convenience for subclasses that wish to implement {@link #openFile}
1190 * by looking up a column named "_data" at the given URI.
1191 *
1192 * @param uri The URI to be opened.
1193 * @param mode The file mode. May be "r" for read-only access,
1194 * "w" for write-only access (erasing whatever data is currently in
1195 * the file), "wa" for write-only access to append to any existing data,
1196 * "rw" for read and write access on any existing data, and "rwt" for read
1197 * and write access that truncates any existing file.
1198 *
1199 * @return Returns a new ParcelFileDescriptor that can be used by the
1200 * client to access the file.
1201 */
1202 protected final ParcelFileDescriptor openFileHelper(Uri uri,
1203 String mode) throws FileNotFoundException {
1204 Cursor c = query(uri, new String[]{"_data"}, null, null, null);
1205 int count = (c != null) ? c.getCount() : 0;
1206 if (count != 1) {
1207 // If there is not exactly one result, throw an appropriate
1208 // exception.
1209 if (c != null) {
1210 c.close();
1211 }
1212 if (count == 0) {
1213 throw new FileNotFoundException("No entry for " + uri);
1214 }
1215 throw new FileNotFoundException("Multiple items at " + uri);
1216 }
1217
1218 c.moveToFirst();
1219 int i = c.getColumnIndex("_data");
1220 String path = (i >= 0 ? c.getString(i) : null);
1221 c.close();
1222 if (path == null) {
1223 throw new FileNotFoundException("Column _data not found.");
1224 }
1225
1226 int modeBits = ContentResolver.modeToMode(uri, mode);
1227 return ParcelFileDescriptor.open(new File(path), modeBits);
1228 }
1229
1230 /**
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001231 * Called by a client to determine the types of data streams that this
1232 * content provider supports for the given URI. The default implementation
Christopher Tate2bc6eb82013-01-03 12:04:08 -08001233 * returns {@code null}, meaning no types. If your content provider stores data
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001234 * of a particular type, return that MIME type if it matches the given
1235 * mimeTypeFilter. If it can perform type conversions, return an array
1236 * of all supported MIME types that match mimeTypeFilter.
1237 *
1238 * @param uri The data in the content provider being queried.
1239 * @param mimeTypeFilter The type of data the client desires. May be
1240 * a pattern, such as *\/* to retrieve all possible data types.
Christopher Tate2bc6eb82013-01-03 12:04:08 -08001241 * @return Returns {@code null} if there are no possible data streams for the
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001242 * given mimeTypeFilter. Otherwise returns an array of all available
1243 * concrete MIME types.
1244 *
1245 * @see #getType(Uri)
1246 * @see #openTypedAssetFile(Uri, String, Bundle)
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001247 * @see ClipDescription#compareMimeTypes(String, String)
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001248 */
1249 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
1250 return null;
1251 }
1252
1253 /**
1254 * Called by a client to open a read-only stream containing data of a
1255 * particular MIME type. This is like {@link #openAssetFile(Uri, String)},
1256 * except the file can only be read-only and the content provider may
1257 * perform data conversions to generate data of the desired type.
1258 *
1259 * <p>The default implementation compares the given mimeType against the
Dianne Hackborna53ee352013-02-20 12:47:02 -08001260 * result of {@link #getType(Uri)} and, if they match, simply calls
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001261 * {@link #openAssetFile(Uri, String)}.
1262 *
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001263 * <p>See {@link ClipData} for examples of the use and implementation
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001264 * of this method.
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001265 * <p>
1266 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1267 * streaming of data.
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001268 *
Dianne Hackborna53ee352013-02-20 12:47:02 -08001269 * <p class="note">For better interoperability with other applications, it is recommended
1270 * that for any URIs that can be opened, you also support queries on them
1271 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1272 * You may also want to support other common columns if you have additional meta-data
1273 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1274 * in {@link android.provider.MediaStore.MediaColumns}.</p>
1275 *
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001276 * @param uri The data in the content provider being queried.
1277 * @param mimeTypeFilter The type of data the client desires. May be
1278 * a pattern, such as *\/*, if the caller does not have specific type
1279 * requirements; in this case the content provider will pick its best
1280 * type matching the pattern.
1281 * @param opts Additional options from the client. The definitions of
1282 * these are specific to the content provider being called.
1283 *
1284 * @return Returns a new AssetFileDescriptor from which the client can
1285 * read data of the desired type.
1286 *
1287 * @throws FileNotFoundException Throws FileNotFoundException if there is
1288 * no file associated with the given URI or the mode is invalid.
1289 * @throws SecurityException Throws SecurityException if the caller does
1290 * not have permission to access the data.
1291 * @throws IllegalArgumentException Throws IllegalArgumentException if the
1292 * content provider does not support the requested MIME type.
1293 *
1294 * @see #getStreamTypes(Uri, String)
1295 * @see #openAssetFile(Uri, String)
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001296 * @see ClipDescription#compareMimeTypes(String, String)
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001297 */
1298 public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
1299 throws FileNotFoundException {
Dianne Hackborn02dfd262010-08-13 12:34:58 -07001300 if ("*/*".equals(mimeTypeFilter)) {
1301 // If they can take anything, the untyped open call is good enough.
1302 return openAssetFile(uri, "r");
1303 }
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001304 String baseType = getType(uri);
Dianne Hackborn1040dc42010-08-26 22:11:06 -07001305 if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) {
Dianne Hackborn02dfd262010-08-13 12:34:58 -07001306 // Use old untyped open call if this provider has a type for this
1307 // URI and it matches the request.
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001308 return openAssetFile(uri, "r");
1309 }
1310 throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter);
1311 }
1312
Jeff Sharkeybd3b9022013-08-20 15:20:04 -07001313
1314 /**
1315 * Called by a client to open a read-only stream containing data of a
1316 * particular MIME type. This is like {@link #openAssetFile(Uri, String)},
1317 * except the file can only be read-only and the content provider may
1318 * perform data conversions to generate data of the desired type.
1319 *
1320 * <p>The default implementation compares the given mimeType against the
1321 * result of {@link #getType(Uri)} and, if they match, simply calls
1322 * {@link #openAssetFile(Uri, String)}.
1323 *
1324 * <p>See {@link ClipData} for examples of the use and implementation
1325 * of this method.
1326 * <p>
1327 * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1328 * streaming of data.
1329 *
1330 * <p class="note">For better interoperability with other applications, it is recommended
1331 * that for any URIs that can be opened, you also support queries on them
1332 * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1333 * You may also want to support other common columns if you have additional meta-data
1334 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1335 * in {@link android.provider.MediaStore.MediaColumns}.</p>
1336 *
1337 * @param uri The data in the content provider being queried.
1338 * @param mimeTypeFilter The type of data the client desires. May be
1339 * a pattern, such as *\/*, if the caller does not have specific type
1340 * requirements; in this case the content provider will pick its best
1341 * type matching the pattern.
1342 * @param opts Additional options from the client. The definitions of
1343 * these are specific to the content provider being called.
1344 * @param signal A signal to cancel the operation in progress, or
1345 * {@code null} if none. For example, if you are downloading a
1346 * file from the network to service a "rw" mode request, you
1347 * should periodically call
1348 * {@link CancellationSignal#throwIfCanceled()} to check whether
1349 * the client has canceled the request and abort the download.
1350 *
1351 * @return Returns a new AssetFileDescriptor from which the client can
1352 * read data of the desired type.
1353 *
1354 * @throws FileNotFoundException Throws FileNotFoundException if there is
1355 * no file associated with the given URI or the mode is invalid.
1356 * @throws SecurityException Throws SecurityException if the caller does
1357 * not have permission to access the data.
1358 * @throws IllegalArgumentException Throws IllegalArgumentException if the
1359 * content provider does not support the requested MIME type.
1360 *
1361 * @see #getStreamTypes(Uri, String)
1362 * @see #openAssetFile(Uri, String)
1363 * @see ClipDescription#compareMimeTypes(String, String)
1364 */
1365 public AssetFileDescriptor openTypedAssetFile(
1366 Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
1367 throws FileNotFoundException {
1368 return openTypedAssetFile(uri, mimeTypeFilter, opts);
1369 }
1370
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001371 /**
1372 * Interface to write a stream of data to a pipe. Use with
1373 * {@link ContentProvider#openPipeHelper}.
1374 */
1375 public interface PipeDataWriter<T> {
1376 /**
1377 * Called from a background thread to stream data out to a pipe.
1378 * Note that the pipe is blocking, so this thread can block on
1379 * writes for an arbitrary amount of time if the client is slow
1380 * at reading.
1381 *
1382 * @param output The pipe where data should be written. This will be
1383 * closed for you upon returning from this function.
1384 * @param uri The URI whose data is to be written.
1385 * @param mimeType The desired type of data to be written.
1386 * @param opts Options supplied by caller.
1387 * @param args Your own custom arguments.
1388 */
1389 public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
1390 Bundle opts, T args);
1391 }
1392
1393 /**
1394 * A helper function for implementing {@link #openTypedAssetFile}, for
1395 * creating a data pipe and background thread allowing you to stream
1396 * generated data back to the client. This function returns a new
1397 * ParcelFileDescriptor that should be returned to the caller (the caller
1398 * is responsible for closing it).
1399 *
1400 * @param uri The URI whose data is to be written.
1401 * @param mimeType The desired type of data to be written.
1402 * @param opts Options supplied by caller.
1403 * @param args Your own custom arguments.
1404 * @param func Interface implementing the function that will actually
1405 * stream the data.
1406 * @return Returns a new ParcelFileDescriptor holding the read side of
1407 * the pipe. This should be returned to the caller for reading; the caller
1408 * is responsible for closing it when done.
1409 */
1410 public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType,
1411 final Bundle opts, final T args, final PipeDataWriter<T> func)
1412 throws FileNotFoundException {
1413 try {
1414 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
1415
1416 AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
1417 @Override
1418 protected Object doInBackground(Object... params) {
1419 func.writeDataToPipe(fds[1], uri, mimeType, opts, args);
1420 try {
1421 fds[1].close();
1422 } catch (IOException e) {
1423 Log.w(TAG, "Failure closing pipe", e);
1424 }
1425 return null;
1426 }
1427 };
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08001428 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null);
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001429
1430 return fds[0];
1431 } catch (IOException e) {
1432 throw new FileNotFoundException("failure making pipe");
1433 }
1434 }
1435
1436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 * Returns true if this instance is a temporary content provider.
1438 * @return true if this instance is a temporary content provider
1439 */
1440 protected boolean isTemporary() {
1441 return false;
1442 }
1443
1444 /**
1445 * Returns the Binder object for this provider.
1446 *
1447 * @return the Binder object for this provider
1448 * @hide
1449 */
1450 public IContentProvider getIContentProvider() {
1451 return mTransport;
1452 }
1453
1454 /**
Dianne Hackborn334d9ae2013-02-26 15:02:06 -08001455 * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use
1456 * when directly instantiating the provider for testing.
1457 * @hide
1458 */
1459 public void attachInfoForTesting(Context context, ProviderInfo info) {
1460 attachInfo(context, info, true);
1461 }
1462
1463 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 * After being instantiated, this is called to tell the content provider
1465 * about itself.
1466 *
1467 * @param context The context this provider is running in
1468 * @param info Registered information about this content provider
1469 */
1470 public void attachInfo(Context context, ProviderInfo info) {
Dianne Hackborn334d9ae2013-02-26 15:02:06 -08001471 attachInfo(context, info, false);
1472 }
1473
1474 private void attachInfo(Context context, ProviderInfo info, boolean testing) {
Dianne Hackborn23fdaf62010-08-06 12:16:55 -07001475 /*
1476 * We may be using AsyncTask from binder threads. Make it init here
1477 * so its static handler is on the main thread.
1478 */
1479 AsyncTask.init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480
Dianne Hackborn334d9ae2013-02-26 15:02:06 -08001481 mNoPerms = testing;
1482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 /*
1484 * Only allow it to be set once, so after the content service gives
1485 * this to us clients can't change it.
1486 */
1487 if (mContext == null) {
1488 mContext = context;
Jeff Sharkey911d7f42013-09-05 18:11:45 -07001489 mTransport.mAppOpsManager = (AppOpsManager) mContext.getSystemService(
1490 Context.APP_OPS_SERVICE);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07001491 mMyUid = Process.myUid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 if (info != null) {
1493 setReadPermission(info.readPermission);
1494 setWritePermission(info.writePermission);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07001495 setPathPermissions(info.pathPermissions);
Dianne Hackbornb424b632010-08-18 15:59:05 -07001496 mExported = info.exported;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 }
1498 ContentProvider.this.onCreate();
1499 }
1500 }
Fred Quintanace31b232009-05-04 16:01:15 -07001501
1502 /**
Dan Egnor17876aa2010-07-28 12:28:04 -07001503 * Override this to handle requests to perform a batch of operations, or the
1504 * default implementation will iterate over the operations and call
1505 * {@link ContentProviderOperation#apply} on each of them.
1506 * If all calls to {@link ContentProviderOperation#apply} succeed
1507 * then a {@link ContentProviderResult} array with as many
1508 * elements as there were operations will be returned. If any of the calls
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001509 * fail, it is up to the implementation how many of the others take effect.
1510 * This method can be called from multiple threads, as described in
Scott Main7aee61f2011-02-08 11:25:01 -08001511 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1512 * and Threads</a>.
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001513 *
Fred Quintanace31b232009-05-04 16:01:15 -07001514 * @param operations the operations to apply
1515 * @return the results of the applications
Dan Egnor6fcc0f0732010-07-27 16:32:17 -07001516 * @throws OperationApplicationException thrown if any operation fails.
1517 * @see ContentProviderOperation#apply
Fred Quintanace31b232009-05-04 16:01:15 -07001518 */
Fred Quintana03d94902009-05-22 14:23:31 -07001519 public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
Fred Quintanace31b232009-05-04 16:01:15 -07001520 throws OperationApplicationException {
Fred Quintana03d94902009-05-22 14:23:31 -07001521 final int numOperations = operations.size();
1522 final ContentProviderResult[] results = new ContentProviderResult[numOperations];
1523 for (int i = 0; i < numOperations; i++) {
1524 results[i] = operations.get(i).apply(this, results, i);
Fred Quintanace31b232009-05-04 16:01:15 -07001525 }
1526 return results;
1527 }
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001528
1529 /**
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001530 * Call a provider-defined method. This can be used to implement
Brad Fitzpatrick534c84c2011-01-12 14:06:30 -08001531 * interfaces that are cheaper and/or unnatural for a table-like
1532 * model.
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001533 *
Dianne Hackborn5d122d92013-03-12 18:37:07 -07001534 * <p class="note"><strong>WARNING:</strong> The framework does no permission checking
1535 * on this entry into the content provider besides the basic ability for the application
1536 * to get access to the provider at all. For example, it has no idea whether the call
1537 * being executed may read or write data in the provider, so can't enforce those
1538 * individual permissions. Any implementation of this method <strong>must</strong>
1539 * do its own permission checks on incoming calls to make sure they are allowed.</p>
1540 *
Christopher Tate2bc6eb82013-01-03 12:04:08 -08001541 * @param method method name to call. Opaque to framework, but should not be {@code null}.
1542 * @param arg provider-defined String argument. May be {@code null}.
1543 * @param extras provider-defined Bundle argument. May be {@code null}.
1544 * @return provider-defined return value. May be {@code null}, which is also
Brad Fitzpatrick534c84c2011-01-12 14:06:30 -08001545 * the default for providers which don't implement any call methods.
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001546 */
Brad Fitzpatrick534c84c2011-01-12 14:06:30 -08001547 public Bundle call(String method, String arg, Bundle extras) {
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001548 return null;
1549 }
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001550
1551 /**
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001552 * Implement this to shut down the ContentProvider instance. You can then
1553 * invoke this method in unit tests.
1554 *
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001555 * <p>
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001556 * Android normally handles ContentProvider startup and shutdown
1557 * automatically. You do not need to start up or shut down a
1558 * ContentProvider. When you invoke a test method on a ContentProvider,
1559 * however, a ContentProvider instance is started and keeps running after
1560 * the test finishes, even if a succeeding test instantiates another
1561 * ContentProvider. A conflict develops because the two instances are
1562 * usually running against the same underlying data source (for example, an
1563 * sqlite database).
1564 * </p>
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001565 * <p>
Manuel Roman2c96a0c2010-08-05 16:39:49 -07001566 * Implementing shutDown() avoids this conflict by providing a way to
1567 * terminate the ContentProvider. This method can also prevent memory leaks
1568 * from multiple instantiations of the ContentProvider, and it can ensure
1569 * unit test isolation by allowing you to completely clean up the test
1570 * fixture before moving on to the next test.
1571 * </p>
Vasu Nori0c9e14a2010-08-04 13:31:48 -07001572 */
1573 public void shutdown() {
1574 Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " +
1575 "connections are gracefully shutdown");
1576 }
Marco Nelissen18cb2872011-11-15 11:19:53 -08001577
1578 /**
1579 * Print the Provider's state into the given stream. This gets invoked if
Jeff Sharkey5554b702012-04-11 18:30:51 -07001580 * you run "adb shell dumpsys activity provider &lt;provider_component_name&gt;".
Marco Nelissen18cb2872011-11-15 11:19:53 -08001581 *
Marco Nelissen18cb2872011-11-15 11:19:53 -08001582 * @param fd The raw file descriptor that the dump is being sent to.
1583 * @param writer The PrintWriter to which you should dump your state. This will be
1584 * closed for you after you return.
1585 * @param args additional arguments to the dump request.
Marco Nelissen18cb2872011-11-15 11:19:53 -08001586 */
1587 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1588 writer.println("nothing to dump");
1589 }
Brad Fitzpatrick1877d012010-03-04 17:48:13 -08001590}