ContentProvider.java revision 961321fe4ed4431a6362d729d9e4ea26bdecde61
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.content; 18 19import static android.content.pm.PackageManager.PERMISSION_GRANTED; 20 21import android.app.AppOpsManager; 22import android.content.pm.PackageManager; 23import android.content.pm.PathPermission; 24import android.content.pm.ProviderInfo; 25import android.content.res.AssetFileDescriptor; 26import android.content.res.Configuration; 27import android.database.Cursor; 28import android.database.SQLException; 29import android.net.Uri; 30import android.os.AsyncTask; 31import android.os.Binder; 32import android.os.Bundle; 33import android.os.CancellationSignal; 34import android.os.ICancellationSignal; 35import android.os.OperationCanceledException; 36import android.os.ParcelFileDescriptor; 37import android.os.Process; 38import android.os.RemoteException; 39import android.os.UserHandle; 40import android.util.Log; 41 42import java.io.File; 43import java.io.FileDescriptor; 44import java.io.FileNotFoundException; 45import java.io.IOException; 46import java.io.PrintWriter; 47import java.util.ArrayList; 48 49/** 50 * Content providers are one of the primary building blocks of Android applications, providing 51 * content to applications. They encapsulate data and provide it to applications through the single 52 * {@link ContentResolver} interface. A content provider is only required if you need to share 53 * data between multiple applications. For example, the contacts data is used by multiple 54 * applications and must be stored in a content provider. If you don't need to share data amongst 55 * multiple applications you can use a database directly via 56 * {@link android.database.sqlite.SQLiteDatabase}. 57 * 58 * <p>When a request is made via 59 * a {@link ContentResolver} the system inspects the authority of the given URI and passes the 60 * request to the content provider registered with the authority. The content provider can interpret 61 * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing 62 * URIs.</p> 63 * 64 * <p>The primary methods that need to be implemented are: 65 * <ul> 66 * <li>{@link #onCreate} which is called to initialize the provider</li> 67 * <li>{@link #query} which returns data to the caller</li> 68 * <li>{@link #insert} which inserts new data into the content provider</li> 69 * <li>{@link #update} which updates existing data in the content provider</li> 70 * <li>{@link #delete} which deletes data from the content provider</li> 71 * <li>{@link #getType} which returns the MIME type of data in the content provider</li> 72 * </ul></p> 73 * 74 * <p class="caution">Data access methods (such as {@link #insert} and 75 * {@link #update}) may be called from many threads at once, and must be thread-safe. 76 * Other methods (such as {@link #onCreate}) are only called from the application 77 * main thread, and must avoid performing lengthy operations. See the method 78 * descriptions for their expected thread behavior.</p> 79 * 80 * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate 81 * ContentProvider instance, so subclasses don't have to worry about the details of 82 * cross-process calls.</p> 83 * 84 * <div class="special reference"> 85 * <h3>Developer Guides</h3> 86 * <p>For more information about using content providers, read the 87 * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> 88 * developer guide.</p> 89 */ 90public abstract class ContentProvider implements ComponentCallbacks2 { 91 private static final String TAG = "ContentProvider"; 92 93 /* 94 * Note: if you add methods to ContentProvider, you must add similar methods to 95 * MockContentProvider. 96 */ 97 98 private Context mContext = null; 99 private int mMyUid; 100 private String mReadPermission; 101 private String mWritePermission; 102 private PathPermission[] mPathPermissions; 103 private boolean mExported; 104 105 private Transport mTransport = new Transport(); 106 107 /** 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 */ 122 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 149 /** 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. 158 * @return If the IContentProvider is non-{@code null} and local, returns its actual 159 * ContentProvider instance. Otherwise returns {@code null}. 160 * @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 { 176 AppOpsManager mAppOpsManager = null; 177 int mReadOp = AppOpsManager.OP_NONE; 178 int mWriteOp = AppOpsManager.OP_NONE; 179 180 ContentProvider getContentProvider() { 181 return ContentProvider.this; 182 } 183 184 @Override 185 public String getProviderName() { 186 return getContentProvider().getClass().getName(); 187 } 188 189 @Override 190 public Cursor query(String callingPkg, Uri uri, String[] projection, 191 String selection, String[] selectionArgs, String sortOrder, 192 ICancellationSignal cancellationSignal) { 193 if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 194 return rejectQuery(uri, projection, selection, selectionArgs, sortOrder, 195 CancellationSignal.fromTransport(cancellationSignal)); 196 } 197 return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder, 198 CancellationSignal.fromTransport(cancellationSignal)); 199 } 200 201 @Override 202 public String getType(Uri uri) { 203 return ContentProvider.this.getType(uri); 204 } 205 206 @Override 207 public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) { 208 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 209 return rejectInsert(uri, initialValues); 210 } 211 return ContentProvider.this.insert(uri, initialValues); 212 } 213 214 @Override 215 public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) { 216 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 217 return 0; 218 } 219 return ContentProvider.this.bulkInsert(uri, initialValues); 220 } 221 222 @Override 223 public ContentProviderResult[] applyBatch(String callingPkg, 224 ArrayList<ContentProviderOperation> operations) 225 throws OperationApplicationException { 226 for (ContentProviderOperation operation : operations) { 227 if (operation.isReadOperation()) { 228 if (enforceReadPermission(callingPkg, operation.getUri()) 229 != AppOpsManager.MODE_ALLOWED) { 230 throw new OperationApplicationException("App op not allowed", 0); 231 } 232 } 233 234 if (operation.isWriteOperation()) { 235 if (enforceWritePermission(callingPkg, operation.getUri()) 236 != AppOpsManager.MODE_ALLOWED) { 237 throw new OperationApplicationException("App op not allowed", 0); 238 } 239 } 240 } 241 return ContentProvider.this.applyBatch(operations); 242 } 243 244 @Override 245 public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) { 246 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 247 return 0; 248 } 249 return ContentProvider.this.delete(uri, selection, selectionArgs); 250 } 251 252 @Override 253 public int update(String callingPkg, Uri uri, ContentValues values, String selection, 254 String[] selectionArgs) { 255 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 256 return 0; 257 } 258 return ContentProvider.this.update(uri, values, selection, selectionArgs); 259 } 260 261 @Override 262 public ParcelFileDescriptor openFile(String callingPkg, Uri uri, String mode) 263 throws FileNotFoundException { 264 enforceFilePermission(callingPkg, uri, mode); 265 return ContentProvider.this.openFile(uri, mode); 266 } 267 268 @Override 269 public AssetFileDescriptor openAssetFile(String callingPkg, Uri uri, String mode) 270 throws FileNotFoundException { 271 enforceFilePermission(callingPkg, uri, mode); 272 return ContentProvider.this.openAssetFile(uri, mode); 273 } 274 275 @Override 276 public Bundle call(String callingPkg, String method, String arg, Bundle extras) { 277 return ContentProvider.this.callFromPackage(callingPkg, method, arg, extras); 278 } 279 280 @Override 281 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { 282 return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter); 283 } 284 285 @Override 286 public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType, 287 Bundle opts) throws FileNotFoundException { 288 enforceFilePermission(callingPkg, uri, "r"); 289 return ContentProvider.this.openTypedAssetFile(uri, mimeType, opts); 290 } 291 292 @Override 293 public ICancellationSignal createCancellationSignal() throws RemoteException { 294 return CancellationSignal.createTransport(); 295 } 296 297 private void enforceFilePermission(String callingPkg, Uri uri, String mode) 298 throws FileNotFoundException, SecurityException { 299 if (mode != null && mode.startsWith("rw")) { 300 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 301 throw new FileNotFoundException("App op not allowed"); 302 } 303 } else { 304 if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 305 throw new FileNotFoundException("App op not allowed"); 306 } 307 } 308 } 309 310 private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException { 311 enforceReadPermissionInner(uri); 312 if (mReadOp != AppOpsManager.OP_NONE) { 313 return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg); 314 } 315 return AppOpsManager.MODE_ALLOWED; 316 } 317 318 private void enforceReadPermissionInner(Uri uri) throws SecurityException { 319 final Context context = getContext(); 320 final int pid = Binder.getCallingPid(); 321 final int uid = Binder.getCallingUid(); 322 String missingPerm = null; 323 324 if (UserHandle.isSameApp(uid, mMyUid)) { 325 return; 326 } 327 328 if (mExported) { 329 final String componentPerm = getReadPermission(); 330 if (componentPerm != null) { 331 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) { 332 return; 333 } else { 334 missingPerm = componentPerm; 335 } 336 } 337 338 // track if unprotected read is allowed; any denied 339 // <path-permission> below removes this ability 340 boolean allowDefaultRead = (componentPerm == null); 341 342 final PathPermission[] pps = getPathPermissions(); 343 if (pps != null) { 344 final String path = uri.getPath(); 345 for (PathPermission pp : pps) { 346 final String pathPerm = pp.getReadPermission(); 347 if (pathPerm != null && pp.match(path)) { 348 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) { 349 return; 350 } else { 351 // any denied <path-permission> means we lose 352 // default <provider> access. 353 allowDefaultRead = false; 354 missingPerm = pathPerm; 355 } 356 } 357 } 358 } 359 360 // if we passed <path-permission> checks above, and no default 361 // <provider> permission, then allow access. 362 if (allowDefaultRead) return; 363 } 364 365 // last chance, check against any uri grants 366 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) 367 == PERMISSION_GRANTED) { 368 return; 369 } 370 371 final String failReason = mExported 372 ? " requires " + missingPerm + ", or grantUriPermission()" 373 : " requires the provider be exported, or grantUriPermission()"; 374 throw new SecurityException("Permission Denial: reading " 375 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid 376 + ", uid=" + uid + failReason); 377 } 378 379 private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException { 380 enforceWritePermissionInner(uri); 381 if (mWriteOp != AppOpsManager.OP_NONE) { 382 return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg); 383 } 384 return AppOpsManager.MODE_ALLOWED; 385 } 386 387 private void enforceWritePermissionInner(Uri uri) throws SecurityException { 388 final Context context = getContext(); 389 final int pid = Binder.getCallingPid(); 390 final int uid = Binder.getCallingUid(); 391 String missingPerm = null; 392 393 if (UserHandle.isSameApp(uid, mMyUid)) { 394 return; 395 } 396 397 if (mExported) { 398 final String componentPerm = getWritePermission(); 399 if (componentPerm != null) { 400 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) { 401 return; 402 } else { 403 missingPerm = componentPerm; 404 } 405 } 406 407 // track if unprotected write is allowed; any denied 408 // <path-permission> below removes this ability 409 boolean allowDefaultWrite = (componentPerm == null); 410 411 final PathPermission[] pps = getPathPermissions(); 412 if (pps != null) { 413 final String path = uri.getPath(); 414 for (PathPermission pp : pps) { 415 final String pathPerm = pp.getWritePermission(); 416 if (pathPerm != null && pp.match(path)) { 417 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) { 418 return; 419 } else { 420 // any denied <path-permission> means we lose 421 // default <provider> access. 422 allowDefaultWrite = false; 423 missingPerm = pathPerm; 424 } 425 } 426 } 427 } 428 429 // if we passed <path-permission> checks above, and no default 430 // <provider> permission, then allow access. 431 if (allowDefaultWrite) return; 432 } 433 434 // last chance, check against any uri grants 435 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 436 == PERMISSION_GRANTED) { 437 return; 438 } 439 440 final String failReason = mExported 441 ? " requires " + missingPerm + ", or grantUriPermission()" 442 : " requires the provider be exported, or grantUriPermission()"; 443 throw new SecurityException("Permission Denial: writing " 444 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid 445 + ", uid=" + uid + failReason); 446 } 447 } 448 449 /** 450 * Retrieves the Context this provider is running in. Only available once 451 * {@link #onCreate} has been called -- this will return {@code null} in the 452 * constructor. 453 */ 454 public final Context getContext() { 455 return mContext; 456 } 457 458 /** 459 * Change the permission required to read data from the content 460 * provider. This is normally set for you from its manifest information 461 * when the provider is first created. 462 * 463 * @param permission Name of the permission required for read-only access. 464 */ 465 protected final void setReadPermission(String permission) { 466 mReadPermission = permission; 467 } 468 469 /** 470 * Return the name of the permission required for read-only access to 471 * this content provider. This method can be called from multiple 472 * threads, as described in 473 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 474 * and Threads</a>. 475 */ 476 public final String getReadPermission() { 477 return mReadPermission; 478 } 479 480 /** 481 * Change the permission required to read and write data in the content 482 * provider. This is normally set for you from its manifest information 483 * when the provider is first created. 484 * 485 * @param permission Name of the permission required for read/write access. 486 */ 487 protected final void setWritePermission(String permission) { 488 mWritePermission = permission; 489 } 490 491 /** 492 * Return the name of the permission required for read/write access to 493 * this content provider. This method can be called from multiple 494 * threads, as described in 495 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 496 * and Threads</a>. 497 */ 498 public final String getWritePermission() { 499 return mWritePermission; 500 } 501 502 /** 503 * Change the path-based permission required to read and/or write data in 504 * the content provider. This is normally set for you from its manifest 505 * information when the provider is first created. 506 * 507 * @param permissions Array of path permission descriptions. 508 */ 509 protected final void setPathPermissions(PathPermission[] permissions) { 510 mPathPermissions = permissions; 511 } 512 513 /** 514 * Return the path-based permissions required for read and/or write access to 515 * this content provider. This method can be called from multiple 516 * threads, as described in 517 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 518 * and Threads</a>. 519 */ 520 public final PathPermission[] getPathPermissions() { 521 return mPathPermissions; 522 } 523 524 /** @hide */ 525 public final void setAppOps(int readOp, int writeOp) { 526 mTransport.mAppOpsManager = (AppOpsManager)mContext.getSystemService( 527 Context.APP_OPS_SERVICE); 528 mTransport.mReadOp = readOp; 529 mTransport.mWriteOp = writeOp; 530 } 531 532 /** @hide */ 533 public AppOpsManager getAppOpsManager() { 534 return mTransport.mAppOpsManager; 535 } 536 537 /** 538 * Implement this to initialize your content provider on startup. 539 * This method is called for all registered content providers on the 540 * application main thread at application launch time. It must not perform 541 * lengthy operations, or application startup will be delayed. 542 * 543 * <p>You should defer nontrivial initialization (such as opening, 544 * upgrading, and scanning databases) until the content provider is used 545 * (via {@link #query}, {@link #insert}, etc). Deferred initialization 546 * keeps application startup fast, avoids unnecessary work if the provider 547 * turns out not to be needed, and stops database errors (such as a full 548 * disk) from halting application launch. 549 * 550 * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper} 551 * is a helpful utility class that makes it easy to manage databases, 552 * and will automatically defer opening until first use. If you do use 553 * SQLiteOpenHelper, make sure to avoid calling 554 * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or 555 * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 556 * from this method. (Instead, override 557 * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the 558 * database when it is first opened.) 559 * 560 * @return true if the provider was successfully loaded, false otherwise 561 */ 562 public abstract boolean onCreate(); 563 564 /** 565 * {@inheritDoc} 566 * This method is always called on the application main thread, and must 567 * not perform lengthy operations. 568 * 569 * <p>The default content provider implementation does nothing. 570 * Override this method to take appropriate action. 571 * (Content providers do not usually care about things like screen 572 * orientation, but may want to know about locale changes.) 573 */ 574 public void onConfigurationChanged(Configuration newConfig) { 575 } 576 577 /** 578 * {@inheritDoc} 579 * This method is always called on the application main thread, and must 580 * not perform lengthy operations. 581 * 582 * <p>The default content provider implementation does nothing. 583 * Subclasses may override this method to take appropriate action. 584 */ 585 public void onLowMemory() { 586 } 587 588 public void onTrimMemory(int level) { 589 } 590 591 /** 592 * @hide 593 * Implementation when a caller has performed a query on the content 594 * provider, but that call has been rejected for the operation given 595 * to {@link #setAppOps(int, int)}. The default implementation 596 * rewrites the <var>selection</var> argument to include a condition 597 * that is never true (so will always result in an empty cursor) 598 * and calls through to {@link #query(android.net.Uri, String[], String, String[], 599 * String, android.os.CancellationSignal)} with that. 600 */ 601 public Cursor rejectQuery(Uri uri, String[] projection, 602 String selection, String[] selectionArgs, String sortOrder, 603 CancellationSignal cancellationSignal) { 604 // The read is not allowed... to fake it out, we replace the given 605 // selection statement with a dummy one that will always be false. 606 // This way we will get a cursor back that has the correct structure 607 // but contains no rows. 608 if (selection == null) { 609 selection = "'A' = 'B'"; 610 } else { 611 selection = "'A' = 'B' AND (" + selection + ")"; 612 } 613 return query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); 614 } 615 616 /** 617 * Implement this to handle query requests from clients. 618 * This method can be called from multiple threads, as described in 619 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 620 * and Threads</a>. 621 * <p> 622 * Example client call:<p> 623 * <pre>// Request a specific record. 624 * Cursor managedCursor = managedQuery( 625 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), 626 projection, // Which columns to return. 627 null, // WHERE clause. 628 null, // WHERE clause value substitution 629 People.NAME + " ASC"); // Sort order.</pre> 630 * Example implementation:<p> 631 * <pre>// SQLiteQueryBuilder is a helper class that creates the 632 // proper SQL syntax for us. 633 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 634 635 // Set the table we're querying. 636 qBuilder.setTables(DATABASE_TABLE_NAME); 637 638 // If the query ends in a specific record number, we're 639 // being asked for a specific record, so set the 640 // WHERE clause in our query. 641 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 642 qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 643 } 644 645 // Make the query. 646 Cursor c = qBuilder.query(mDb, 647 projection, 648 selection, 649 selectionArgs, 650 groupBy, 651 having, 652 sortOrder); 653 c.setNotificationUri(getContext().getContentResolver(), uri); 654 return c;</pre> 655 * 656 * @param uri The URI to query. This will be the full URI sent by the client; 657 * if the client is requesting a specific record, the URI will end in a record number 658 * that the implementation should parse and add to a WHERE or HAVING clause, specifying 659 * that _id value. 660 * @param projection The list of columns to put into the cursor. If 661 * {@code null} all columns are included. 662 * @param selection A selection criteria to apply when filtering rows. 663 * If {@code null} then all rows are included. 664 * @param selectionArgs You may include ?s in selection, which will be replaced by 665 * the values from selectionArgs, in order that they appear in the selection. 666 * The values will be bound as Strings. 667 * @param sortOrder How the rows in the cursor should be sorted. 668 * If {@code null} then the provider is free to define the sort order. 669 * @return a Cursor or {@code null}. 670 */ 671 public abstract Cursor query(Uri uri, String[] projection, 672 String selection, String[] selectionArgs, String sortOrder); 673 674 /** 675 * Implement this to handle query requests from clients with support for cancellation. 676 * This method can be called from multiple threads, as described in 677 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 678 * and Threads</a>. 679 * <p> 680 * Example client call:<p> 681 * <pre>// Request a specific record. 682 * Cursor managedCursor = managedQuery( 683 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), 684 projection, // Which columns to return. 685 null, // WHERE clause. 686 null, // WHERE clause value substitution 687 People.NAME + " ASC"); // Sort order.</pre> 688 * Example implementation:<p> 689 * <pre>// SQLiteQueryBuilder is a helper class that creates the 690 // proper SQL syntax for us. 691 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 692 693 // Set the table we're querying. 694 qBuilder.setTables(DATABASE_TABLE_NAME); 695 696 // If the query ends in a specific record number, we're 697 // being asked for a specific record, so set the 698 // WHERE clause in our query. 699 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 700 qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 701 } 702 703 // Make the query. 704 Cursor c = qBuilder.query(mDb, 705 projection, 706 selection, 707 selectionArgs, 708 groupBy, 709 having, 710 sortOrder); 711 c.setNotificationUri(getContext().getContentResolver(), uri); 712 return c;</pre> 713 * <p> 714 * If you implement this method then you must also implement the version of 715 * {@link #query(Uri, String[], String, String[], String)} that does not take a cancellation 716 * signal to ensure correct operation on older versions of the Android Framework in 717 * which the cancellation signal overload was not available. 718 * 719 * @param uri The URI to query. This will be the full URI sent by the client; 720 * if the client is requesting a specific record, the URI will end in a record number 721 * that the implementation should parse and add to a WHERE or HAVING clause, specifying 722 * that _id value. 723 * @param projection The list of columns to put into the cursor. If 724 * {@code null} all columns are included. 725 * @param selection A selection criteria to apply when filtering rows. 726 * If {@code null} then all rows are included. 727 * @param selectionArgs You may include ?s in selection, which will be replaced by 728 * the values from selectionArgs, in order that they appear in the selection. 729 * The values will be bound as Strings. 730 * @param sortOrder How the rows in the cursor should be sorted. 731 * If {@code null} then the provider is free to define the sort order. 732 * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if none. 733 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 734 * when the query is executed. 735 * @return a Cursor or {@code null}. 736 */ 737 public Cursor query(Uri uri, String[] projection, 738 String selection, String[] selectionArgs, String sortOrder, 739 CancellationSignal cancellationSignal) { 740 return query(uri, projection, selection, selectionArgs, sortOrder); 741 } 742 743 /** 744 * Implement this to handle requests for the MIME type of the data at the 745 * given URI. The returned MIME type should start with 746 * <code>vnd.android.cursor.item</code> for a single record, 747 * or <code>vnd.android.cursor.dir/</code> for multiple items. 748 * This method can be called from multiple threads, as described in 749 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 750 * and Threads</a>. 751 * 752 * <p>Note that there are no permissions needed for an application to 753 * access this information; if your content provider requires read and/or 754 * write permissions, or is not exported, all applications can still call 755 * this method regardless of their access permissions. This allows them 756 * to retrieve the MIME type for a URI when dispatching intents. 757 * 758 * @param uri the URI to query. 759 * @return a MIME type string, or {@code null} if there is no type. 760 */ 761 public abstract String getType(Uri uri); 762 763 /** 764 * @hide 765 * Implementation when a caller has performed an insert on the content 766 * provider, but that call has been rejected for the operation given 767 * to {@link #setAppOps(int, int)}. The default implementation simply 768 * returns a dummy URI that is the base URI with a 0 path element 769 * appended. 770 */ 771 public Uri rejectInsert(Uri uri, ContentValues values) { 772 // If not allowed, we need to return some reasonable URI. Maybe the 773 // content provider should be responsible for this, but for now we 774 // will just return the base URI with a dummy '0' tagged on to it. 775 // You shouldn't be able to read if you can't write, anyway, so it 776 // shouldn't matter much what is returned. 777 return uri.buildUpon().appendPath("0").build(); 778 } 779 780 /** 781 * Implement this to handle requests to insert a new row. 782 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 783 * after inserting. 784 * This method can be called from multiple threads, as described in 785 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 786 * and Threads</a>. 787 * @param uri The content:// URI of the insertion request. This must not be {@code null}. 788 * @param values A set of column_name/value pairs to add to the database. 789 * This must not be {@code null}. 790 * @return The URI for the newly inserted item. 791 */ 792 public abstract Uri insert(Uri uri, ContentValues values); 793 794 /** 795 * Override this to handle requests to insert a set of new rows, or the 796 * default implementation will iterate over the values and call 797 * {@link #insert} on each of them. 798 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 799 * after inserting. 800 * This method can be called from multiple threads, as described in 801 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 802 * and Threads</a>. 803 * 804 * @param uri The content:// URI of the insertion request. 805 * @param values An array of sets of column_name/value pairs to add to the database. 806 * This must not be {@code null}. 807 * @return The number of values that were inserted. 808 */ 809 public int bulkInsert(Uri uri, ContentValues[] values) { 810 int numValues = values.length; 811 for (int i = 0; i < numValues; i++) { 812 insert(uri, values[i]); 813 } 814 return numValues; 815 } 816 817 /** 818 * Implement this to handle requests to delete one or more rows. 819 * The implementation should apply the selection clause when performing 820 * deletion, allowing the operation to affect multiple rows in a directory. 821 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()} 822 * after deleting. 823 * This method can be called from multiple threads, as described in 824 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 825 * and Threads</a>. 826 * 827 * <p>The implementation is responsible for parsing out a row ID at the end 828 * of the URI, if a specific row is being deleted. That is, the client would 829 * pass in <code>content://contacts/people/22</code> and the implementation is 830 * responsible for parsing the record number (22) when creating a SQL statement. 831 * 832 * @param uri The full URI to query, including a row ID (if a specific record is requested). 833 * @param selection An optional restriction to apply to rows when deleting. 834 * @return The number of rows affected. 835 * @throws SQLException 836 */ 837 public abstract int delete(Uri uri, String selection, String[] selectionArgs); 838 839 /** 840 * Implement this to handle requests to update one or more rows. 841 * The implementation should update all rows matching the selection 842 * to set the columns according to the provided values map. 843 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 844 * after updating. 845 * This method can be called from multiple threads, as described in 846 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 847 * and Threads</a>. 848 * 849 * @param uri The URI to query. This can potentially have a record ID if this 850 * is an update request for a specific record. 851 * @param values A set of column_name/value pairs to update in the database. 852 * This must not be {@code null}. 853 * @param selection An optional filter to match rows to update. 854 * @return the number of rows affected. 855 */ 856 public abstract int update(Uri uri, ContentValues values, String selection, 857 String[] selectionArgs); 858 859 /** 860 * Override this to handle requests to open a file blob. 861 * The default implementation always throws {@link FileNotFoundException}. 862 * This method can be called from multiple threads, as described in 863 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 864 * and Threads</a>. 865 * 866 * <p>This method returns a ParcelFileDescriptor, which is returned directly 867 * to the caller. This way large data (such as images and documents) can be 868 * returned without copying the content. 869 * 870 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is 871 * their responsibility to close it when done. That is, the implementation 872 * of this method should create a new ParcelFileDescriptor for each call. 873 * 874 * @param uri The URI whose file is to be opened. 875 * @param mode Access mode for the file. May be "r" for read-only access, 876 * "rw" for read and write access, or "rwt" for read and write access 877 * that truncates any existing file. 878 * 879 * @return Returns a new ParcelFileDescriptor which you can use to access 880 * the file. 881 * 882 * @throws FileNotFoundException Throws FileNotFoundException if there is 883 * no file associated with the given URI or the mode is invalid. 884 * @throws SecurityException Throws SecurityException if the caller does 885 * not have permission to access the file. 886 * 887 * @see #openAssetFile(Uri, String) 888 * @see #openFileHelper(Uri, String) 889 */ 890 public ParcelFileDescriptor openFile(Uri uri, String mode) 891 throws FileNotFoundException { 892 throw new FileNotFoundException("No files supported by provider at " 893 + uri); 894 } 895 896 /** 897 * This is like {@link #openFile}, but can be implemented by providers 898 * that need to be able to return sub-sections of files, often assets 899 * inside of their .apk. 900 * This method can be called from multiple threads, as described in 901 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 902 * and Threads</a>. 903 * 904 * <p>If you implement this, your clients must be able to deal with such 905 * file slices, either directly with 906 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 907 * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 908 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 909 * methods. 910 * 911 * <p class="note">If you are implementing this to return a full file, you 912 * should create the AssetFileDescriptor with 913 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 914 * applications that can not handle sub-sections of files.</p> 915 * 916 * @param uri The URI whose file is to be opened. 917 * @param mode Access mode for the file. May be "r" for read-only access, 918 * "w" for write-only access (erasing whatever data is currently in 919 * the file), "wa" for write-only access to append to any existing data, 920 * "rw" for read and write access on any existing data, and "rwt" for read 921 * and write access that truncates any existing file. 922 * 923 * @return Returns a new AssetFileDescriptor which you can use to access 924 * the file. 925 * 926 * @throws FileNotFoundException Throws FileNotFoundException if there is 927 * no file associated with the given URI or the mode is invalid. 928 * @throws SecurityException Throws SecurityException if the caller does 929 * not have permission to access the file. 930 * 931 * @see #openFile(Uri, String) 932 * @see #openFileHelper(Uri, String) 933 */ 934 public AssetFileDescriptor openAssetFile(Uri uri, String mode) 935 throws FileNotFoundException { 936 ParcelFileDescriptor fd = openFile(uri, mode); 937 return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null; 938 } 939 940 /** 941 * Convenience for subclasses that wish to implement {@link #openFile} 942 * by looking up a column named "_data" at the given URI. 943 * 944 * @param uri The URI to be opened. 945 * @param mode The file mode. May be "r" for read-only access, 946 * "w" for write-only access (erasing whatever data is currently in 947 * the file), "wa" for write-only access to append to any existing data, 948 * "rw" for read and write access on any existing data, and "rwt" for read 949 * and write access that truncates any existing file. 950 * 951 * @return Returns a new ParcelFileDescriptor that can be used by the 952 * client to access the file. 953 */ 954 protected final ParcelFileDescriptor openFileHelper(Uri uri, 955 String mode) throws FileNotFoundException { 956 Cursor c = query(uri, new String[]{"_data"}, null, null, null); 957 int count = (c != null) ? c.getCount() : 0; 958 if (count != 1) { 959 // If there is not exactly one result, throw an appropriate 960 // exception. 961 if (c != null) { 962 c.close(); 963 } 964 if (count == 0) { 965 throw new FileNotFoundException("No entry for " + uri); 966 } 967 throw new FileNotFoundException("Multiple items at " + uri); 968 } 969 970 c.moveToFirst(); 971 int i = c.getColumnIndex("_data"); 972 String path = (i >= 0 ? c.getString(i) : null); 973 c.close(); 974 if (path == null) { 975 throw new FileNotFoundException("Column _data not found."); 976 } 977 978 int modeBits = ContentResolver.modeToMode(uri, mode); 979 return ParcelFileDescriptor.open(new File(path), modeBits); 980 } 981 982 /** 983 * Called by a client to determine the types of data streams that this 984 * content provider supports for the given URI. The default implementation 985 * returns {@code null}, meaning no types. If your content provider stores data 986 * of a particular type, return that MIME type if it matches the given 987 * mimeTypeFilter. If it can perform type conversions, return an array 988 * of all supported MIME types that match mimeTypeFilter. 989 * 990 * @param uri The data in the content provider being queried. 991 * @param mimeTypeFilter The type of data the client desires. May be 992 * a pattern, such as *\/* to retrieve all possible data types. 993 * @return Returns {@code null} if there are no possible data streams for the 994 * given mimeTypeFilter. Otherwise returns an array of all available 995 * concrete MIME types. 996 * 997 * @see #getType(Uri) 998 * @see #openTypedAssetFile(Uri, String, Bundle) 999 * @see ClipDescription#compareMimeTypes(String, String) 1000 */ 1001 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { 1002 return null; 1003 } 1004 1005 /** 1006 * Called by a client to open a read-only stream containing data of a 1007 * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 1008 * except the file can only be read-only and the content provider may 1009 * perform data conversions to generate data of the desired type. 1010 * 1011 * <p>The default implementation compares the given mimeType against the 1012 * result of {@link #getType(Uri)} and, if the match, simple calls 1013 * {@link #openAssetFile(Uri, String)}. 1014 * 1015 * <p>See {@link ClipData} for examples of the use and implementation 1016 * of this method. 1017 * 1018 * @param uri The data in the content provider being queried. 1019 * @param mimeTypeFilter The type of data the client desires. May be 1020 * a pattern, such as *\/*, if the caller does not have specific type 1021 * requirements; in this case the content provider will pick its best 1022 * type matching the pattern. 1023 * @param opts Additional options from the client. The definitions of 1024 * these are specific to the content provider being called. 1025 * 1026 * @return Returns a new AssetFileDescriptor from which the client can 1027 * read data of the desired type. 1028 * 1029 * @throws FileNotFoundException Throws FileNotFoundException if there is 1030 * no file associated with the given URI or the mode is invalid. 1031 * @throws SecurityException Throws SecurityException if the caller does 1032 * not have permission to access the data. 1033 * @throws IllegalArgumentException Throws IllegalArgumentException if the 1034 * content provider does not support the requested MIME type. 1035 * 1036 * @see #getStreamTypes(Uri, String) 1037 * @see #openAssetFile(Uri, String) 1038 * @see ClipDescription#compareMimeTypes(String, String) 1039 */ 1040 public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts) 1041 throws FileNotFoundException { 1042 if ("*/*".equals(mimeTypeFilter)) { 1043 // If they can take anything, the untyped open call is good enough. 1044 return openAssetFile(uri, "r"); 1045 } 1046 String baseType = getType(uri); 1047 if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) { 1048 // Use old untyped open call if this provider has a type for this 1049 // URI and it matches the request. 1050 return openAssetFile(uri, "r"); 1051 } 1052 throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter); 1053 } 1054 1055 /** 1056 * Interface to write a stream of data to a pipe. Use with 1057 * {@link ContentProvider#openPipeHelper}. 1058 */ 1059 public interface PipeDataWriter<T> { 1060 /** 1061 * Called from a background thread to stream data out to a pipe. 1062 * Note that the pipe is blocking, so this thread can block on 1063 * writes for an arbitrary amount of time if the client is slow 1064 * at reading. 1065 * 1066 * @param output The pipe where data should be written. This will be 1067 * closed for you upon returning from this function. 1068 * @param uri The URI whose data is to be written. 1069 * @param mimeType The desired type of data to be written. 1070 * @param opts Options supplied by caller. 1071 * @param args Your own custom arguments. 1072 */ 1073 public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, 1074 Bundle opts, T args); 1075 } 1076 1077 /** 1078 * A helper function for implementing {@link #openTypedAssetFile}, for 1079 * creating a data pipe and background thread allowing you to stream 1080 * generated data back to the client. This function returns a new 1081 * ParcelFileDescriptor that should be returned to the caller (the caller 1082 * is responsible for closing it). 1083 * 1084 * @param uri The URI whose data is to be written. 1085 * @param mimeType The desired type of data to be written. 1086 * @param opts Options supplied by caller. 1087 * @param args Your own custom arguments. 1088 * @param func Interface implementing the function that will actually 1089 * stream the data. 1090 * @return Returns a new ParcelFileDescriptor holding the read side of 1091 * the pipe. This should be returned to the caller for reading; the caller 1092 * is responsible for closing it when done. 1093 */ 1094 public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType, 1095 final Bundle opts, final T args, final PipeDataWriter<T> func) 1096 throws FileNotFoundException { 1097 try { 1098 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 1099 1100 AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { 1101 @Override 1102 protected Object doInBackground(Object... params) { 1103 func.writeDataToPipe(fds[1], uri, mimeType, opts, args); 1104 try { 1105 fds[1].close(); 1106 } catch (IOException e) { 1107 Log.w(TAG, "Failure closing pipe", e); 1108 } 1109 return null; 1110 } 1111 }; 1112 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null); 1113 1114 return fds[0]; 1115 } catch (IOException e) { 1116 throw new FileNotFoundException("failure making pipe"); 1117 } 1118 } 1119 1120 /** 1121 * Returns true if this instance is a temporary content provider. 1122 * @return true if this instance is a temporary content provider 1123 */ 1124 protected boolean isTemporary() { 1125 return false; 1126 } 1127 1128 /** 1129 * Returns the Binder object for this provider. 1130 * 1131 * @return the Binder object for this provider 1132 * @hide 1133 */ 1134 public IContentProvider getIContentProvider() { 1135 return mTransport; 1136 } 1137 1138 /** 1139 * After being instantiated, this is called to tell the content provider 1140 * about itself. 1141 * 1142 * @param context The context this provider is running in 1143 * @param info Registered information about this content provider 1144 */ 1145 public void attachInfo(Context context, ProviderInfo info) { 1146 /* 1147 * We may be using AsyncTask from binder threads. Make it init here 1148 * so its static handler is on the main thread. 1149 */ 1150 AsyncTask.init(); 1151 1152 /* 1153 * Only allow it to be set once, so after the content service gives 1154 * this to us clients can't change it. 1155 */ 1156 if (mContext == null) { 1157 mContext = context; 1158 mMyUid = Process.myUid(); 1159 if (info != null) { 1160 setReadPermission(info.readPermission); 1161 setWritePermission(info.writePermission); 1162 setPathPermissions(info.pathPermissions); 1163 mExported = info.exported; 1164 } 1165 ContentProvider.this.onCreate(); 1166 } 1167 } 1168 1169 /** 1170 * Override this to handle requests to perform a batch of operations, or the 1171 * default implementation will iterate over the operations and call 1172 * {@link ContentProviderOperation#apply} on each of them. 1173 * If all calls to {@link ContentProviderOperation#apply} succeed 1174 * then a {@link ContentProviderResult} array with as many 1175 * elements as there were operations will be returned. If any of the calls 1176 * fail, it is up to the implementation how many of the others take effect. 1177 * This method can be called from multiple threads, as described in 1178 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1179 * and Threads</a>. 1180 * 1181 * @param operations the operations to apply 1182 * @return the results of the applications 1183 * @throws OperationApplicationException thrown if any operation fails. 1184 * @see ContentProviderOperation#apply 1185 */ 1186 public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1187 throws OperationApplicationException { 1188 final int numOperations = operations.size(); 1189 final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 1190 for (int i = 0; i < numOperations; i++) { 1191 results[i] = operations.get(i).apply(this, results, i); 1192 } 1193 return results; 1194 } 1195 1196 /** 1197 * @hide 1198 * Front-end to {@link #call(String, String, android.os.Bundle)} that provides the name 1199 * of the calling package. 1200 */ 1201 public Bundle callFromPackage(String callingPackag, String method, String arg, Bundle extras) { 1202 return call(method, arg, extras); 1203 } 1204 1205 /** 1206 * Call a provider-defined method. This can be used to implement 1207 * interfaces that are cheaper and/or unnatural for a table-like 1208 * model. 1209 * 1210 * @param method method name to call. Opaque to framework, but should not be {@code null}. 1211 * @param arg provider-defined String argument. May be {@code null}. 1212 * @param extras provider-defined Bundle argument. May be {@code null}. 1213 * @return provider-defined return value. May be {@code null}, which is also 1214 * the default for providers which don't implement any call methods. 1215 */ 1216 public Bundle call(String method, String arg, Bundle extras) { 1217 return null; 1218 } 1219 1220 /** 1221 * Implement this to shut down the ContentProvider instance. You can then 1222 * invoke this method in unit tests. 1223 * 1224 * <p> 1225 * Android normally handles ContentProvider startup and shutdown 1226 * automatically. You do not need to start up or shut down a 1227 * ContentProvider. When you invoke a test method on a ContentProvider, 1228 * however, a ContentProvider instance is started and keeps running after 1229 * the test finishes, even if a succeeding test instantiates another 1230 * ContentProvider. A conflict develops because the two instances are 1231 * usually running against the same underlying data source (for example, an 1232 * sqlite database). 1233 * </p> 1234 * <p> 1235 * Implementing shutDown() avoids this conflict by providing a way to 1236 * terminate the ContentProvider. This method can also prevent memory leaks 1237 * from multiple instantiations of the ContentProvider, and it can ensure 1238 * unit test isolation by allowing you to completely clean up the test 1239 * fixture before moving on to the next test. 1240 * </p> 1241 */ 1242 public void shutdown() { 1243 Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " + 1244 "connections are gracefully shutdown"); 1245 } 1246 1247 /** 1248 * Print the Provider's state into the given stream. This gets invoked if 1249 * you run "adb shell dumpsys activity provider <provider_component_name>". 1250 * 1251 * @param fd The raw file descriptor that the dump is being sent to. 1252 * @param writer The PrintWriter to which you should dump your state. This will be 1253 * closed for you after you return. 1254 * @param args additional arguments to the dump request. 1255 */ 1256 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1257 writer.println("nothing to dump"); 1258 } 1259} 1260