ContentProvider.java revision bd3b902567b09379e1b62c60b3319ad82102efad
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.PathPermission; 23import android.content.pm.ProviderInfo; 24import android.content.res.AssetFileDescriptor; 25import android.content.res.Configuration; 26import android.database.Cursor; 27import android.database.SQLException; 28import android.net.Uri; 29import android.os.AsyncTask; 30import android.os.Binder; 31import android.os.Bundle; 32import android.os.CancellationSignal; 33import android.os.ICancellationSignal; 34import android.os.OperationCanceledException; 35import android.os.ParcelFileDescriptor; 36import android.os.Process; 37import android.os.RemoteException; 38import android.os.UserHandle; 39import android.util.Log; 40 41import java.io.File; 42import java.io.FileDescriptor; 43import java.io.FileNotFoundException; 44import java.io.IOException; 45import java.io.PrintWriter; 46import java.util.ArrayList; 47 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 * 57 * <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> 65 * <li>{@link #onCreate} which is called to initialize the provider</li> 66 * <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 * 73 * <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> 82 * 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> 88 */ 89public abstract class ContentProvider implements ComponentCallbacks2 { 90 private static final String TAG = "ContentProvider"; 91 92 /* 93 * Note: if you add methods to ContentProvider, you must add similar methods to 94 * MockContentProvider. 95 */ 96 97 private Context mContext = null; 98 private int mMyUid; 99 private String mReadPermission; 100 private String mWritePermission; 101 private PathPermission[] mPathPermissions; 102 private boolean mExported; 103 private boolean mNoPerms; 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( 263 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal) 264 throws FileNotFoundException { 265 enforceFilePermission(callingPkg, uri, mode); 266 return ContentProvider.this.openFile( 267 uri, mode, CancellationSignal.fromTransport(cancellationSignal)); 268 } 269 270 @Override 271 public AssetFileDescriptor openAssetFile( 272 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal) 273 throws FileNotFoundException { 274 enforceFilePermission(callingPkg, uri, mode); 275 return ContentProvider.this.openAssetFile( 276 uri, mode, CancellationSignal.fromTransport(cancellationSignal)); 277 } 278 279 @Override 280 public Bundle call(String callingPkg, String method, String arg, Bundle extras) { 281 return ContentProvider.this.callFromPackage(callingPkg, method, arg, extras); 282 } 283 284 @Override 285 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { 286 return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter); 287 } 288 289 @Override 290 public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType, 291 Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException { 292 enforceFilePermission(callingPkg, uri, "r"); 293 return ContentProvider.this.openTypedAssetFile( 294 uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal)); 295 } 296 297 @Override 298 public ICancellationSignal createCancellationSignal() throws RemoteException { 299 return CancellationSignal.createTransport(); 300 } 301 302 private void enforceFilePermission(String callingPkg, Uri uri, String mode) 303 throws FileNotFoundException, SecurityException { 304 if (mode != null && mode.indexOf('w') != -1) { 305 if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 306 throw new FileNotFoundException("App op not allowed"); 307 } 308 } else { 309 if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { 310 throw new FileNotFoundException("App op not allowed"); 311 } 312 } 313 } 314 315 private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException { 316 enforceReadPermissionInner(uri); 317 if (mReadOp != AppOpsManager.OP_NONE) { 318 return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg); 319 } 320 return AppOpsManager.MODE_ALLOWED; 321 } 322 323 private void enforceReadPermissionInner(Uri uri) throws SecurityException { 324 final Context context = getContext(); 325 final int pid = Binder.getCallingPid(); 326 final int uid = Binder.getCallingUid(); 327 String missingPerm = null; 328 329 if (UserHandle.isSameApp(uid, mMyUid)) { 330 return; 331 } 332 333 if (mExported) { 334 final String componentPerm = getReadPermission(); 335 if (componentPerm != null) { 336 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) { 337 return; 338 } else { 339 missingPerm = componentPerm; 340 } 341 } 342 343 // track if unprotected read is allowed; any denied 344 // <path-permission> below removes this ability 345 boolean allowDefaultRead = (componentPerm == null); 346 347 final PathPermission[] pps = getPathPermissions(); 348 if (pps != null) { 349 final String path = uri.getPath(); 350 for (PathPermission pp : pps) { 351 final String pathPerm = pp.getReadPermission(); 352 if (pathPerm != null && pp.match(path)) { 353 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) { 354 return; 355 } else { 356 // any denied <path-permission> means we lose 357 // default <provider> access. 358 allowDefaultRead = false; 359 missingPerm = pathPerm; 360 } 361 } 362 } 363 } 364 365 // if we passed <path-permission> checks above, and no default 366 // <provider> permission, then allow access. 367 if (allowDefaultRead) return; 368 } 369 370 // last chance, check against any uri grants 371 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) 372 == PERMISSION_GRANTED) { 373 return; 374 } 375 376 final String failReason = mExported 377 ? " requires " + missingPerm + ", or grantUriPermission()" 378 : " requires the provider be exported, or grantUriPermission()"; 379 throw new SecurityException("Permission Denial: reading " 380 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid 381 + ", uid=" + uid + failReason); 382 } 383 384 private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException { 385 enforceWritePermissionInner(uri); 386 if (mWriteOp != AppOpsManager.OP_NONE) { 387 return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg); 388 } 389 return AppOpsManager.MODE_ALLOWED; 390 } 391 392 private void enforceWritePermissionInner(Uri uri) throws SecurityException { 393 final Context context = getContext(); 394 final int pid = Binder.getCallingPid(); 395 final int uid = Binder.getCallingUid(); 396 String missingPerm = null; 397 398 if (UserHandle.isSameApp(uid, mMyUid)) { 399 return; 400 } 401 402 if (mExported) { 403 final String componentPerm = getWritePermission(); 404 if (componentPerm != null) { 405 if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) { 406 return; 407 } else { 408 missingPerm = componentPerm; 409 } 410 } 411 412 // track if unprotected write is allowed; any denied 413 // <path-permission> below removes this ability 414 boolean allowDefaultWrite = (componentPerm == null); 415 416 final PathPermission[] pps = getPathPermissions(); 417 if (pps != null) { 418 final String path = uri.getPath(); 419 for (PathPermission pp : pps) { 420 final String pathPerm = pp.getWritePermission(); 421 if (pathPerm != null && pp.match(path)) { 422 if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) { 423 return; 424 } else { 425 // any denied <path-permission> means we lose 426 // default <provider> access. 427 allowDefaultWrite = false; 428 missingPerm = pathPerm; 429 } 430 } 431 } 432 } 433 434 // if we passed <path-permission> checks above, and no default 435 // <provider> permission, then allow access. 436 if (allowDefaultWrite) return; 437 } 438 439 // last chance, check against any uri grants 440 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 441 == PERMISSION_GRANTED) { 442 return; 443 } 444 445 final String failReason = mExported 446 ? " requires " + missingPerm + ", or grantUriPermission()" 447 : " requires the provider be exported, or grantUriPermission()"; 448 throw new SecurityException("Permission Denial: writing " 449 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid 450 + ", uid=" + uid + failReason); 451 } 452 } 453 454 /** 455 * Retrieves the Context this provider is running in. Only available once 456 * {@link #onCreate} has been called -- this will return {@code null} in the 457 * constructor. 458 */ 459 public final Context getContext() { 460 return mContext; 461 } 462 463 /** 464 * Change the permission required to read data from the content 465 * provider. This is normally set for you from its manifest information 466 * when the provider is first created. 467 * 468 * @param permission Name of the permission required for read-only access. 469 */ 470 protected final void setReadPermission(String permission) { 471 mReadPermission = permission; 472 } 473 474 /** 475 * Return the name of the permission required for read-only access to 476 * this content provider. This method can be called from multiple 477 * threads, as described in 478 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 479 * and Threads</a>. 480 */ 481 public final String getReadPermission() { 482 return mReadPermission; 483 } 484 485 /** 486 * Change the permission required to read and write data in the content 487 * provider. This is normally set for you from its manifest information 488 * when the provider is first created. 489 * 490 * @param permission Name of the permission required for read/write access. 491 */ 492 protected final void setWritePermission(String permission) { 493 mWritePermission = permission; 494 } 495 496 /** 497 * Return the name of the permission required for read/write access to 498 * this content provider. This method can be called from multiple 499 * threads, as described in 500 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 501 * and Threads</a>. 502 */ 503 public final String getWritePermission() { 504 return mWritePermission; 505 } 506 507 /** 508 * Change the path-based permission required to read and/or write data in 509 * the content provider. This is normally set for you from its manifest 510 * information when the provider is first created. 511 * 512 * @param permissions Array of path permission descriptions. 513 */ 514 protected final void setPathPermissions(PathPermission[] permissions) { 515 mPathPermissions = permissions; 516 } 517 518 /** 519 * Return the path-based permissions required for read and/or write access to 520 * this content provider. This method can be called from multiple 521 * threads, as described in 522 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 523 * and Threads</a>. 524 */ 525 public final PathPermission[] getPathPermissions() { 526 return mPathPermissions; 527 } 528 529 /** @hide */ 530 public final void setAppOps(int readOp, int writeOp) { 531 if (!mNoPerms) { 532 mTransport.mAppOpsManager = (AppOpsManager)mContext.getSystemService( 533 Context.APP_OPS_SERVICE); 534 mTransport.mReadOp = readOp; 535 mTransport.mWriteOp = writeOp; 536 } 537 } 538 539 /** @hide */ 540 public AppOpsManager getAppOpsManager() { 541 return mTransport.mAppOpsManager; 542 } 543 544 /** 545 * Implement this to initialize your content provider on startup. 546 * This method is called for all registered content providers on the 547 * application main thread at application launch time. It must not perform 548 * lengthy operations, or application startup will be delayed. 549 * 550 * <p>You should defer nontrivial initialization (such as opening, 551 * upgrading, and scanning databases) until the content provider is used 552 * (via {@link #query}, {@link #insert}, etc). Deferred initialization 553 * keeps application startup fast, avoids unnecessary work if the provider 554 * turns out not to be needed, and stops database errors (such as a full 555 * disk) from halting application launch. 556 * 557 * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper} 558 * is a helpful utility class that makes it easy to manage databases, 559 * and will automatically defer opening until first use. If you do use 560 * SQLiteOpenHelper, make sure to avoid calling 561 * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or 562 * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 563 * from this method. (Instead, override 564 * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the 565 * database when it is first opened.) 566 * 567 * @return true if the provider was successfully loaded, false otherwise 568 */ 569 public abstract boolean onCreate(); 570 571 /** 572 * {@inheritDoc} 573 * This method is always called on the application main thread, and must 574 * not perform lengthy operations. 575 * 576 * <p>The default content provider implementation does nothing. 577 * Override this method to take appropriate action. 578 * (Content providers do not usually care about things like screen 579 * orientation, but may want to know about locale changes.) 580 */ 581 public void onConfigurationChanged(Configuration newConfig) { 582 } 583 584 /** 585 * {@inheritDoc} 586 * This method is always called on the application main thread, and must 587 * not perform lengthy operations. 588 * 589 * <p>The default content provider implementation does nothing. 590 * Subclasses may override this method to take appropriate action. 591 */ 592 public void onLowMemory() { 593 } 594 595 public void onTrimMemory(int level) { 596 } 597 598 /** 599 * @hide 600 * Implementation when a caller has performed a query on the content 601 * provider, but that call has been rejected for the operation given 602 * to {@link #setAppOps(int, int)}. The default implementation 603 * rewrites the <var>selection</var> argument to include a condition 604 * that is never true (so will always result in an empty cursor) 605 * and calls through to {@link #query(android.net.Uri, String[], String, String[], 606 * String, android.os.CancellationSignal)} with that. 607 */ 608 public Cursor rejectQuery(Uri uri, String[] projection, 609 String selection, String[] selectionArgs, String sortOrder, 610 CancellationSignal cancellationSignal) { 611 // The read is not allowed... to fake it out, we replace the given 612 // selection statement with a dummy one that will always be false. 613 // This way we will get a cursor back that has the correct structure 614 // but contains no rows. 615 if (selection == null || selection.isEmpty()) { 616 selection = "'A' = 'B'"; 617 } else { 618 selection = "'A' = 'B' AND (" + selection + ")"; 619 } 620 return query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); 621 } 622 623 /** 624 * Implement this to handle query requests from clients. 625 * This method can be called from multiple threads, as described in 626 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 627 * and Threads</a>. 628 * <p> 629 * Example client call:<p> 630 * <pre>// Request a specific record. 631 * Cursor managedCursor = managedQuery( 632 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), 633 projection, // Which columns to return. 634 null, // WHERE clause. 635 null, // WHERE clause value substitution 636 People.NAME + " ASC"); // Sort order.</pre> 637 * Example implementation:<p> 638 * <pre>// SQLiteQueryBuilder is a helper class that creates the 639 // proper SQL syntax for us. 640 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 641 642 // Set the table we're querying. 643 qBuilder.setTables(DATABASE_TABLE_NAME); 644 645 // If the query ends in a specific record number, we're 646 // being asked for a specific record, so set the 647 // WHERE clause in our query. 648 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 649 qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 650 } 651 652 // Make the query. 653 Cursor c = qBuilder.query(mDb, 654 projection, 655 selection, 656 selectionArgs, 657 groupBy, 658 having, 659 sortOrder); 660 c.setNotificationUri(getContext().getContentResolver(), uri); 661 return c;</pre> 662 * 663 * @param uri The URI to query. This will be the full URI sent by the client; 664 * if the client is requesting a specific record, the URI will end in a record number 665 * that the implementation should parse and add to a WHERE or HAVING clause, specifying 666 * that _id value. 667 * @param projection The list of columns to put into the cursor. If 668 * {@code null} all columns are included. 669 * @param selection A selection criteria to apply when filtering rows. 670 * If {@code null} then all rows are included. 671 * @param selectionArgs You may include ?s in selection, which will be replaced by 672 * the values from selectionArgs, in order that they appear in the selection. 673 * The values will be bound as Strings. 674 * @param sortOrder How the rows in the cursor should be sorted. 675 * If {@code null} then the provider is free to define the sort order. 676 * @return a Cursor or {@code null}. 677 */ 678 public abstract Cursor query(Uri uri, String[] projection, 679 String selection, String[] selectionArgs, String sortOrder); 680 681 /** 682 * Implement this to handle query requests from clients with support for cancellation. 683 * This method can be called from multiple threads, as described in 684 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 685 * and Threads</a>. 686 * <p> 687 * Example client call:<p> 688 * <pre>// Request a specific record. 689 * Cursor managedCursor = managedQuery( 690 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), 691 projection, // Which columns to return. 692 null, // WHERE clause. 693 null, // WHERE clause value substitution 694 People.NAME + " ASC"); // Sort order.</pre> 695 * Example implementation:<p> 696 * <pre>// SQLiteQueryBuilder is a helper class that creates the 697 // proper SQL syntax for us. 698 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 699 700 // Set the table we're querying. 701 qBuilder.setTables(DATABASE_TABLE_NAME); 702 703 // If the query ends in a specific record number, we're 704 // being asked for a specific record, so set the 705 // WHERE clause in our query. 706 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 707 qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 708 } 709 710 // Make the query. 711 Cursor c = qBuilder.query(mDb, 712 projection, 713 selection, 714 selectionArgs, 715 groupBy, 716 having, 717 sortOrder); 718 c.setNotificationUri(getContext().getContentResolver(), uri); 719 return c;</pre> 720 * <p> 721 * If you implement this method then you must also implement the version of 722 * {@link #query(Uri, String[], String, String[], String)} that does not take a cancellation 723 * signal to ensure correct operation on older versions of the Android Framework in 724 * which the cancellation signal overload was not available. 725 * 726 * @param uri The URI to query. This will be the full URI sent by the client; 727 * if the client is requesting a specific record, the URI will end in a record number 728 * that the implementation should parse and add to a WHERE or HAVING clause, specifying 729 * that _id value. 730 * @param projection The list of columns to put into the cursor. If 731 * {@code null} all columns are included. 732 * @param selection A selection criteria to apply when filtering rows. 733 * If {@code null} then all rows are included. 734 * @param selectionArgs You may include ?s in selection, which will be replaced by 735 * the values from selectionArgs, in order that they appear in the selection. 736 * The values will be bound as Strings. 737 * @param sortOrder How the rows in the cursor should be sorted. 738 * If {@code null} then the provider is free to define the sort order. 739 * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if none. 740 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 741 * when the query is executed. 742 * @return a Cursor or {@code null}. 743 */ 744 public Cursor query(Uri uri, String[] projection, 745 String selection, String[] selectionArgs, String sortOrder, 746 CancellationSignal cancellationSignal) { 747 return query(uri, projection, selection, selectionArgs, sortOrder); 748 } 749 750 /** 751 * Implement this to handle requests for the MIME type of the data at the 752 * given URI. The returned MIME type should start with 753 * <code>vnd.android.cursor.item</code> for a single record, 754 * or <code>vnd.android.cursor.dir/</code> for multiple items. 755 * This method can be called from multiple threads, as described in 756 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 757 * and Threads</a>. 758 * 759 * <p>Note that there are no permissions needed for an application to 760 * access this information; if your content provider requires read and/or 761 * write permissions, or is not exported, all applications can still call 762 * this method regardless of their access permissions. This allows them 763 * to retrieve the MIME type for a URI when dispatching intents. 764 * 765 * @param uri the URI to query. 766 * @return a MIME type string, or {@code null} if there is no type. 767 */ 768 public abstract String getType(Uri uri); 769 770 /** 771 * @hide 772 * Implementation when a caller has performed an insert on the content 773 * provider, but that call has been rejected for the operation given 774 * to {@link #setAppOps(int, int)}. The default implementation simply 775 * returns a dummy URI that is the base URI with a 0 path element 776 * appended. 777 */ 778 public Uri rejectInsert(Uri uri, ContentValues values) { 779 // If not allowed, we need to return some reasonable URI. Maybe the 780 // content provider should be responsible for this, but for now we 781 // will just return the base URI with a dummy '0' tagged on to it. 782 // You shouldn't be able to read if you can't write, anyway, so it 783 // shouldn't matter much what is returned. 784 return uri.buildUpon().appendPath("0").build(); 785 } 786 787 /** 788 * Implement this to handle requests to insert a new row. 789 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 790 * after inserting. 791 * This method can be called from multiple threads, as described in 792 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 793 * and Threads</a>. 794 * @param uri The content:// URI of the insertion request. This must not be {@code null}. 795 * @param values A set of column_name/value pairs to add to the database. 796 * This must not be {@code null}. 797 * @return The URI for the newly inserted item. 798 */ 799 public abstract Uri insert(Uri uri, ContentValues values); 800 801 /** 802 * Override this to handle requests to insert a set of new rows, or the 803 * default implementation will iterate over the values and call 804 * {@link #insert} on each of them. 805 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 806 * after inserting. 807 * This method can be called from multiple threads, as described in 808 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 809 * and Threads</a>. 810 * 811 * @param uri The content:// URI of the insertion request. 812 * @param values An array of sets of column_name/value pairs to add to the database. 813 * This must not be {@code null}. 814 * @return The number of values that were inserted. 815 */ 816 public int bulkInsert(Uri uri, ContentValues[] values) { 817 int numValues = values.length; 818 for (int i = 0; i < numValues; i++) { 819 insert(uri, values[i]); 820 } 821 return numValues; 822 } 823 824 /** 825 * Implement this to handle requests to delete one or more rows. 826 * The implementation should apply the selection clause when performing 827 * deletion, allowing the operation to affect multiple rows in a directory. 828 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()} 829 * after deleting. 830 * This method can be called from multiple threads, as described in 831 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 832 * and Threads</a>. 833 * 834 * <p>The implementation is responsible for parsing out a row ID at the end 835 * of the URI, if a specific row is being deleted. That is, the client would 836 * pass in <code>content://contacts/people/22</code> and the implementation is 837 * responsible for parsing the record number (22) when creating a SQL statement. 838 * 839 * @param uri The full URI to query, including a row ID (if a specific record is requested). 840 * @param selection An optional restriction to apply to rows when deleting. 841 * @return The number of rows affected. 842 * @throws SQLException 843 */ 844 public abstract int delete(Uri uri, String selection, String[] selectionArgs); 845 846 /** 847 * Implement this to handle requests to update one or more rows. 848 * The implementation should update all rows matching the selection 849 * to set the columns according to the provided values map. 850 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 851 * after updating. 852 * This method can be called from multiple threads, as described in 853 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 854 * and Threads</a>. 855 * 856 * @param uri The URI to query. This can potentially have a record ID if this 857 * is an update request for a specific record. 858 * @param values A set of column_name/value pairs to update in the database. 859 * This must not be {@code null}. 860 * @param selection An optional filter to match rows to update. 861 * @return the number of rows affected. 862 */ 863 public abstract int update(Uri uri, ContentValues values, String selection, 864 String[] selectionArgs); 865 866 /** 867 * Override this to handle requests to open a file blob. 868 * The default implementation always throws {@link FileNotFoundException}. 869 * This method can be called from multiple threads, as described in 870 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 871 * and Threads</a>. 872 * 873 * <p>This method returns a ParcelFileDescriptor, which is returned directly 874 * to the caller. This way large data (such as images and documents) can be 875 * returned without copying the content. 876 * 877 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is 878 * their responsibility to close it when done. That is, the implementation 879 * of this method should create a new ParcelFileDescriptor for each call. 880 * <p> 881 * If opened with the exclusive "r" or "w" modes, the returned 882 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming 883 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that 884 * supports seeking. 885 * <p> 886 * If you need to detect when the returned ParcelFileDescriptor has been 887 * closed, or if the remote process has crashed or encountered some other 888 * error, you can use {@link ParcelFileDescriptor#open(File, int, 889 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)}, 890 * {@link ParcelFileDescriptor#createReliablePipe()}, or 891 * {@link ParcelFileDescriptor#createReliableSocketPair()}. 892 * 893 * <p class="note">For use in Intents, you will want to implement {@link #getType} 894 * to return the appropriate MIME type for the data returned here with 895 * the same URI. This will allow intent resolution to automatically determine the data MIME 896 * type and select the appropriate matching targets as part of its operation.</p> 897 * 898 * <p class="note">For better interoperability with other applications, it is recommended 899 * that for any URIs that can be opened, you also support queries on them 900 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 901 * You may also want to support other common columns if you have additional meta-data 902 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 903 * in {@link android.provider.MediaStore.MediaColumns}.</p> 904 * 905 * @param uri The URI whose file is to be opened. 906 * @param mode Access mode for the file. May be "r" for read-only access, 907 * "rw" for read and write access, or "rwt" for read and write access 908 * that truncates any existing file. 909 * 910 * @return Returns a new ParcelFileDescriptor which you can use to access 911 * the file. 912 * 913 * @throws FileNotFoundException Throws FileNotFoundException if there is 914 * no file associated with the given URI or the mode is invalid. 915 * @throws SecurityException Throws SecurityException if the caller does 916 * not have permission to access the file. 917 * 918 * @see #openAssetFile(Uri, String) 919 * @see #openFileHelper(Uri, String) 920 * @see #getType(android.net.Uri) 921 */ 922 public ParcelFileDescriptor openFile(Uri uri, String mode) 923 throws FileNotFoundException { 924 throw new FileNotFoundException("No files supported by provider at " 925 + uri); 926 } 927 928 /** 929 * Override this to handle requests to open a file blob. 930 * The default implementation always throws {@link FileNotFoundException}. 931 * This method can be called from multiple threads, as described in 932 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 933 * and Threads</a>. 934 * 935 * <p>This method returns a ParcelFileDescriptor, which is returned directly 936 * to the caller. This way large data (such as images and documents) can be 937 * returned without copying the content. 938 * 939 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is 940 * their responsibility to close it when done. That is, the implementation 941 * of this method should create a new ParcelFileDescriptor for each call. 942 * <p> 943 * If opened with the exclusive "r" or "w" modes, the returned 944 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming 945 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that 946 * supports seeking. 947 * <p> 948 * If you need to detect when the returned ParcelFileDescriptor has been 949 * closed, or if the remote process has crashed or encountered some other 950 * error, you can use {@link ParcelFileDescriptor#open(File, int, 951 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)}, 952 * {@link ParcelFileDescriptor#createReliablePipe()}, or 953 * {@link ParcelFileDescriptor#createReliableSocketPair()}. 954 * 955 * <p class="note">For use in Intents, you will want to implement {@link #getType} 956 * to return the appropriate MIME type for the data returned here with 957 * the same URI. This will allow intent resolution to automatically determine the data MIME 958 * type and select the appropriate matching targets as part of its operation.</p> 959 * 960 * <p class="note">For better interoperability with other applications, it is recommended 961 * that for any URIs that can be opened, you also support queries on them 962 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 963 * You may also want to support other common columns if you have additional meta-data 964 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 965 * in {@link android.provider.MediaStore.MediaColumns}.</p> 966 * 967 * @param uri The URI whose file is to be opened. 968 * @param mode Access mode for the file. May be "r" for read-only access, 969 * "w" for write-only access, "rw" for read and write access, or 970 * "rwt" for read and write access that truncates any existing 971 * file. 972 * @param signal A signal to cancel the operation in progress, or 973 * {@code null} if none. For example, if you are downloading a 974 * file from the network to service a "rw" mode request, you 975 * should periodically call 976 * {@link CancellationSignal#throwIfCanceled()} to check whether 977 * the client has canceled the request and abort the download. 978 * 979 * @return Returns a new ParcelFileDescriptor which you can use to access 980 * the file. 981 * 982 * @throws FileNotFoundException Throws FileNotFoundException if there is 983 * no file associated with the given URI or the mode is invalid. 984 * @throws SecurityException Throws SecurityException if the caller does 985 * not have permission to access the file. 986 * 987 * @see #openAssetFile(Uri, String) 988 * @see #openFileHelper(Uri, String) 989 * @see #getType(android.net.Uri) 990 */ 991 public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) 992 throws FileNotFoundException { 993 return openFile(uri, mode); 994 } 995 996 /** 997 * This is like {@link #openFile}, but can be implemented by providers 998 * that need to be able to return sub-sections of files, often assets 999 * inside of their .apk. 1000 * This method can be called from multiple threads, as described in 1001 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1002 * and Threads</a>. 1003 * 1004 * <p>If you implement this, your clients must be able to deal with such 1005 * file slices, either directly with 1006 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 1007 * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 1008 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 1009 * methods. 1010 * <p> 1011 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1012 * streaming of data. 1013 * 1014 * <p class="note">If you are implementing this to return a full file, you 1015 * should create the AssetFileDescriptor with 1016 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 1017 * applications that cannot handle sub-sections of files.</p> 1018 * 1019 * <p class="note">For use in Intents, you will want to implement {@link #getType} 1020 * to return the appropriate MIME type for the data returned here with 1021 * the same URI. This will allow intent resolution to automatically determine the data MIME 1022 * type and select the appropriate matching targets as part of its operation.</p> 1023 * 1024 * <p class="note">For better interoperability with other applications, it is recommended 1025 * that for any URIs that can be opened, you also support queries on them 1026 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> 1027 * 1028 * @param uri The URI whose file is to be opened. 1029 * @param mode Access mode for the file. May be "r" for read-only access, 1030 * "w" for write-only access (erasing whatever data is currently in 1031 * the file), "wa" for write-only access to append to any existing data, 1032 * "rw" for read and write access on any existing data, and "rwt" for read 1033 * and write access that truncates any existing file. 1034 * 1035 * @return Returns a new AssetFileDescriptor which you can use to access 1036 * the file. 1037 * 1038 * @throws FileNotFoundException Throws FileNotFoundException if there is 1039 * no file associated with the given URI or the mode is invalid. 1040 * @throws SecurityException Throws SecurityException if the caller does 1041 * not have permission to access the file. 1042 * 1043 * @see #openFile(Uri, String) 1044 * @see #openFileHelper(Uri, String) 1045 * @see #getType(android.net.Uri) 1046 */ 1047 public AssetFileDescriptor openAssetFile(Uri uri, String mode) 1048 throws FileNotFoundException { 1049 ParcelFileDescriptor fd = openFile(uri, mode); 1050 return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null; 1051 } 1052 1053 /** 1054 * This is like {@link #openFile}, but can be implemented by providers 1055 * that need to be able to return sub-sections of files, often assets 1056 * inside of their .apk. 1057 * This method can be called from multiple threads, as described in 1058 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1059 * and Threads</a>. 1060 * 1061 * <p>If you implement this, your clients must be able to deal with such 1062 * file slices, either directly with 1063 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 1064 * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 1065 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 1066 * methods. 1067 * <p> 1068 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1069 * streaming of data. 1070 * 1071 * <p class="note">If you are implementing this to return a full file, you 1072 * should create the AssetFileDescriptor with 1073 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 1074 * applications that cannot handle sub-sections of files.</p> 1075 * 1076 * <p class="note">For use in Intents, you will want to implement {@link #getType} 1077 * to return the appropriate MIME type for the data returned here with 1078 * the same URI. This will allow intent resolution to automatically determine the data MIME 1079 * type and select the appropriate matching targets as part of its operation.</p> 1080 * 1081 * <p class="note">For better interoperability with other applications, it is recommended 1082 * that for any URIs that can be opened, you also support queries on them 1083 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> 1084 * 1085 * @param uri The URI whose file is to be opened. 1086 * @param mode Access mode for the file. May be "r" for read-only access, 1087 * "w" for write-only access (erasing whatever data is currently in 1088 * the file), "wa" for write-only access to append to any existing data, 1089 * "rw" for read and write access on any existing data, and "rwt" for read 1090 * and write access that truncates any existing file. 1091 * @param signal A signal to cancel the operation in progress, or 1092 * {@code null} if none. For example, if you are downloading a 1093 * file from the network to service a "rw" mode request, you 1094 * should periodically call 1095 * {@link CancellationSignal#throwIfCanceled()} to check whether 1096 * the client has canceled the request and abort the download. 1097 * 1098 * @return Returns a new AssetFileDescriptor which you can use to access 1099 * the file. 1100 * 1101 * @throws FileNotFoundException Throws FileNotFoundException if there is 1102 * no file associated with the given URI or the mode is invalid. 1103 * @throws SecurityException Throws SecurityException if the caller does 1104 * not have permission to access the file. 1105 * 1106 * @see #openFile(Uri, String) 1107 * @see #openFileHelper(Uri, String) 1108 * @see #getType(android.net.Uri) 1109 */ 1110 public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal) 1111 throws FileNotFoundException { 1112 return openAssetFile(uri, mode); 1113 } 1114 1115 /** 1116 * Convenience for subclasses that wish to implement {@link #openFile} 1117 * by looking up a column named "_data" at the given URI. 1118 * 1119 * @param uri The URI to be opened. 1120 * @param mode The file mode. May be "r" for read-only access, 1121 * "w" for write-only access (erasing whatever data is currently in 1122 * the file), "wa" for write-only access to append to any existing data, 1123 * "rw" for read and write access on any existing data, and "rwt" for read 1124 * and write access that truncates any existing file. 1125 * 1126 * @return Returns a new ParcelFileDescriptor that can be used by the 1127 * client to access the file. 1128 */ 1129 protected final ParcelFileDescriptor openFileHelper(Uri uri, 1130 String mode) throws FileNotFoundException { 1131 Cursor c = query(uri, new String[]{"_data"}, null, null, null); 1132 int count = (c != null) ? c.getCount() : 0; 1133 if (count != 1) { 1134 // If there is not exactly one result, throw an appropriate 1135 // exception. 1136 if (c != null) { 1137 c.close(); 1138 } 1139 if (count == 0) { 1140 throw new FileNotFoundException("No entry for " + uri); 1141 } 1142 throw new FileNotFoundException("Multiple items at " + uri); 1143 } 1144 1145 c.moveToFirst(); 1146 int i = c.getColumnIndex("_data"); 1147 String path = (i >= 0 ? c.getString(i) : null); 1148 c.close(); 1149 if (path == null) { 1150 throw new FileNotFoundException("Column _data not found."); 1151 } 1152 1153 int modeBits = ContentResolver.modeToMode(uri, mode); 1154 return ParcelFileDescriptor.open(new File(path), modeBits); 1155 } 1156 1157 /** 1158 * Called by a client to determine the types of data streams that this 1159 * content provider supports for the given URI. The default implementation 1160 * returns {@code null}, meaning no types. If your content provider stores data 1161 * of a particular type, return that MIME type if it matches the given 1162 * mimeTypeFilter. If it can perform type conversions, return an array 1163 * of all supported MIME types that match mimeTypeFilter. 1164 * 1165 * @param uri The data in the content provider being queried. 1166 * @param mimeTypeFilter The type of data the client desires. May be 1167 * a pattern, such as *\/* to retrieve all possible data types. 1168 * @return Returns {@code null} if there are no possible data streams for the 1169 * given mimeTypeFilter. Otherwise returns an array of all available 1170 * concrete MIME types. 1171 * 1172 * @see #getType(Uri) 1173 * @see #openTypedAssetFile(Uri, String, Bundle) 1174 * @see ClipDescription#compareMimeTypes(String, String) 1175 */ 1176 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { 1177 return null; 1178 } 1179 1180 /** 1181 * Called by a client to open a read-only stream containing data of a 1182 * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 1183 * except the file can only be read-only and the content provider may 1184 * perform data conversions to generate data of the desired type. 1185 * 1186 * <p>The default implementation compares the given mimeType against the 1187 * result of {@link #getType(Uri)} and, if they match, simply calls 1188 * {@link #openAssetFile(Uri, String)}. 1189 * 1190 * <p>See {@link ClipData} for examples of the use and implementation 1191 * of this method. 1192 * <p> 1193 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1194 * streaming of data. 1195 * 1196 * <p class="note">For better interoperability with other applications, it is recommended 1197 * that for any URIs that can be opened, you also support queries on them 1198 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 1199 * You may also want to support other common columns if you have additional meta-data 1200 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 1201 * in {@link android.provider.MediaStore.MediaColumns}.</p> 1202 * 1203 * @param uri The data in the content provider being queried. 1204 * @param mimeTypeFilter The type of data the client desires. May be 1205 * a pattern, such as *\/*, if the caller does not have specific type 1206 * requirements; in this case the content provider will pick its best 1207 * type matching the pattern. 1208 * @param opts Additional options from the client. The definitions of 1209 * these are specific to the content provider being called. 1210 * 1211 * @return Returns a new AssetFileDescriptor from which the client can 1212 * read data of the desired type. 1213 * 1214 * @throws FileNotFoundException Throws FileNotFoundException if there is 1215 * no file associated with the given URI or the mode is invalid. 1216 * @throws SecurityException Throws SecurityException if the caller does 1217 * not have permission to access the data. 1218 * @throws IllegalArgumentException Throws IllegalArgumentException if the 1219 * content provider does not support the requested MIME type. 1220 * 1221 * @see #getStreamTypes(Uri, String) 1222 * @see #openAssetFile(Uri, String) 1223 * @see ClipDescription#compareMimeTypes(String, String) 1224 */ 1225 public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts) 1226 throws FileNotFoundException { 1227 if ("*/*".equals(mimeTypeFilter)) { 1228 // If they can take anything, the untyped open call is good enough. 1229 return openAssetFile(uri, "r"); 1230 } 1231 String baseType = getType(uri); 1232 if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) { 1233 // Use old untyped open call if this provider has a type for this 1234 // URI and it matches the request. 1235 return openAssetFile(uri, "r"); 1236 } 1237 throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter); 1238 } 1239 1240 1241 /** 1242 * Called by a client to open a read-only stream containing data of a 1243 * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 1244 * except the file can only be read-only and the content provider may 1245 * perform data conversions to generate data of the desired type. 1246 * 1247 * <p>The default implementation compares the given mimeType against the 1248 * result of {@link #getType(Uri)} and, if they match, simply calls 1249 * {@link #openAssetFile(Uri, String)}. 1250 * 1251 * <p>See {@link ClipData} for examples of the use and implementation 1252 * of this method. 1253 * <p> 1254 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1255 * streaming of data. 1256 * 1257 * <p class="note">For better interoperability with other applications, it is recommended 1258 * that for any URIs that can be opened, you also support queries on them 1259 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 1260 * You may also want to support other common columns if you have additional meta-data 1261 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 1262 * in {@link android.provider.MediaStore.MediaColumns}.</p> 1263 * 1264 * @param uri The data in the content provider being queried. 1265 * @param mimeTypeFilter The type of data the client desires. May be 1266 * a pattern, such as *\/*, if the caller does not have specific type 1267 * requirements; in this case the content provider will pick its best 1268 * type matching the pattern. 1269 * @param opts Additional options from the client. The definitions of 1270 * these are specific to the content provider being called. 1271 * @param signal A signal to cancel the operation in progress, or 1272 * {@code null} if none. For example, if you are downloading a 1273 * file from the network to service a "rw" mode request, you 1274 * should periodically call 1275 * {@link CancellationSignal#throwIfCanceled()} to check whether 1276 * the client has canceled the request and abort the download. 1277 * 1278 * @return Returns a new AssetFileDescriptor from which the client can 1279 * read data of the desired type. 1280 * 1281 * @throws FileNotFoundException Throws FileNotFoundException if there is 1282 * no file associated with the given URI or the mode is invalid. 1283 * @throws SecurityException Throws SecurityException if the caller does 1284 * not have permission to access the data. 1285 * @throws IllegalArgumentException Throws IllegalArgumentException if the 1286 * content provider does not support the requested MIME type. 1287 * 1288 * @see #getStreamTypes(Uri, String) 1289 * @see #openAssetFile(Uri, String) 1290 * @see ClipDescription#compareMimeTypes(String, String) 1291 */ 1292 public AssetFileDescriptor openTypedAssetFile( 1293 Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal) 1294 throws FileNotFoundException { 1295 return openTypedAssetFile(uri, mimeTypeFilter, opts); 1296 } 1297 1298 /** 1299 * Interface to write a stream of data to a pipe. Use with 1300 * {@link ContentProvider#openPipeHelper}. 1301 */ 1302 public interface PipeDataWriter<T> { 1303 /** 1304 * Called from a background thread to stream data out to a pipe. 1305 * Note that the pipe is blocking, so this thread can block on 1306 * writes for an arbitrary amount of time if the client is slow 1307 * at reading. 1308 * 1309 * @param output The pipe where data should be written. This will be 1310 * closed for you upon returning from this function. 1311 * @param uri The URI whose data is to be written. 1312 * @param mimeType The desired type of data to be written. 1313 * @param opts Options supplied by caller. 1314 * @param args Your own custom arguments. 1315 */ 1316 public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, 1317 Bundle opts, T args); 1318 } 1319 1320 /** 1321 * A helper function for implementing {@link #openTypedAssetFile}, for 1322 * creating a data pipe and background thread allowing you to stream 1323 * generated data back to the client. This function returns a new 1324 * ParcelFileDescriptor that should be returned to the caller (the caller 1325 * is responsible for closing it). 1326 * 1327 * @param uri The URI whose data is to be written. 1328 * @param mimeType The desired type of data to be written. 1329 * @param opts Options supplied by caller. 1330 * @param args Your own custom arguments. 1331 * @param func Interface implementing the function that will actually 1332 * stream the data. 1333 * @return Returns a new ParcelFileDescriptor holding the read side of 1334 * the pipe. This should be returned to the caller for reading; the caller 1335 * is responsible for closing it when done. 1336 */ 1337 public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType, 1338 final Bundle opts, final T args, final PipeDataWriter<T> func) 1339 throws FileNotFoundException { 1340 try { 1341 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 1342 1343 AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { 1344 @Override 1345 protected Object doInBackground(Object... params) { 1346 func.writeDataToPipe(fds[1], uri, mimeType, opts, args); 1347 try { 1348 fds[1].close(); 1349 } catch (IOException e) { 1350 Log.w(TAG, "Failure closing pipe", e); 1351 } 1352 return null; 1353 } 1354 }; 1355 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null); 1356 1357 return fds[0]; 1358 } catch (IOException e) { 1359 throw new FileNotFoundException("failure making pipe"); 1360 } 1361 } 1362 1363 /** 1364 * Returns true if this instance is a temporary content provider. 1365 * @return true if this instance is a temporary content provider 1366 */ 1367 protected boolean isTemporary() { 1368 return false; 1369 } 1370 1371 /** 1372 * Returns the Binder object for this provider. 1373 * 1374 * @return the Binder object for this provider 1375 * @hide 1376 */ 1377 public IContentProvider getIContentProvider() { 1378 return mTransport; 1379 } 1380 1381 /** 1382 * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use 1383 * when directly instantiating the provider for testing. 1384 * @hide 1385 */ 1386 public void attachInfoForTesting(Context context, ProviderInfo info) { 1387 attachInfo(context, info, true); 1388 } 1389 1390 /** 1391 * After being instantiated, this is called to tell the content provider 1392 * about itself. 1393 * 1394 * @param context The context this provider is running in 1395 * @param info Registered information about this content provider 1396 */ 1397 public void attachInfo(Context context, ProviderInfo info) { 1398 attachInfo(context, info, false); 1399 } 1400 1401 private void attachInfo(Context context, ProviderInfo info, boolean testing) { 1402 /* 1403 * We may be using AsyncTask from binder threads. Make it init here 1404 * so its static handler is on the main thread. 1405 */ 1406 AsyncTask.init(); 1407 1408 mNoPerms = testing; 1409 1410 /* 1411 * Only allow it to be set once, so after the content service gives 1412 * this to us clients can't change it. 1413 */ 1414 if (mContext == null) { 1415 mContext = context; 1416 mMyUid = Process.myUid(); 1417 if (info != null) { 1418 setReadPermission(info.readPermission); 1419 setWritePermission(info.writePermission); 1420 setPathPermissions(info.pathPermissions); 1421 mExported = info.exported; 1422 } 1423 ContentProvider.this.onCreate(); 1424 } 1425 } 1426 1427 /** 1428 * Override this to handle requests to perform a batch of operations, or the 1429 * default implementation will iterate over the operations and call 1430 * {@link ContentProviderOperation#apply} on each of them. 1431 * If all calls to {@link ContentProviderOperation#apply} succeed 1432 * then a {@link ContentProviderResult} array with as many 1433 * elements as there were operations will be returned. If any of the calls 1434 * fail, it is up to the implementation how many of the others take effect. 1435 * This method can be called from multiple threads, as described in 1436 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1437 * and Threads</a>. 1438 * 1439 * @param operations the operations to apply 1440 * @return the results of the applications 1441 * @throws OperationApplicationException thrown if any operation fails. 1442 * @see ContentProviderOperation#apply 1443 */ 1444 public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1445 throws OperationApplicationException { 1446 final int numOperations = operations.size(); 1447 final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 1448 for (int i = 0; i < numOperations; i++) { 1449 results[i] = operations.get(i).apply(this, results, i); 1450 } 1451 return results; 1452 } 1453 1454 /** 1455 * @hide 1456 * Front-end to {@link #call(String, String, android.os.Bundle)} that provides the name 1457 * of the calling package. 1458 */ 1459 public Bundle callFromPackage(String callingPackag, String method, String arg, Bundle extras) { 1460 return call(method, arg, extras); 1461 } 1462 1463 /** 1464 * Call a provider-defined method. This can be used to implement 1465 * interfaces that are cheaper and/or unnatural for a table-like 1466 * model. 1467 * 1468 * <p class="note"><strong>WARNING:</strong> The framework does no permission checking 1469 * on this entry into the content provider besides the basic ability for the application 1470 * to get access to the provider at all. For example, it has no idea whether the call 1471 * being executed may read or write data in the provider, so can't enforce those 1472 * individual permissions. Any implementation of this method <strong>must</strong> 1473 * do its own permission checks on incoming calls to make sure they are allowed.</p> 1474 * 1475 * @param method method name to call. Opaque to framework, but should not be {@code null}. 1476 * @param arg provider-defined String argument. May be {@code null}. 1477 * @param extras provider-defined Bundle argument. May be {@code null}. 1478 * @return provider-defined return value. May be {@code null}, which is also 1479 * the default for providers which don't implement any call methods. 1480 */ 1481 public Bundle call(String method, String arg, Bundle extras) { 1482 return null; 1483 } 1484 1485 /** 1486 * Implement this to shut down the ContentProvider instance. You can then 1487 * invoke this method in unit tests. 1488 * 1489 * <p> 1490 * Android normally handles ContentProvider startup and shutdown 1491 * automatically. You do not need to start up or shut down a 1492 * ContentProvider. When you invoke a test method on a ContentProvider, 1493 * however, a ContentProvider instance is started and keeps running after 1494 * the test finishes, even if a succeeding test instantiates another 1495 * ContentProvider. A conflict develops because the two instances are 1496 * usually running against the same underlying data source (for example, an 1497 * sqlite database). 1498 * </p> 1499 * <p> 1500 * Implementing shutDown() avoids this conflict by providing a way to 1501 * terminate the ContentProvider. This method can also prevent memory leaks 1502 * from multiple instantiations of the ContentProvider, and it can ensure 1503 * unit test isolation by allowing you to completely clean up the test 1504 * fixture before moving on to the next test. 1505 * </p> 1506 */ 1507 public void shutdown() { 1508 Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " + 1509 "connections are gracefully shutdown"); 1510 } 1511 1512 /** 1513 * Print the Provider's state into the given stream. This gets invoked if 1514 * you run "adb shell dumpsys activity provider <provider_component_name>". 1515 * 1516 * @param fd The raw file descriptor that the dump is being sent to. 1517 * @param writer The PrintWriter to which you should dump your state. This will be 1518 * closed for you after you return. 1519 * @param args additional arguments to the dump request. 1520 */ 1521 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1522 writer.println("nothing to dump"); 1523 } 1524} 1525