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