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