ContentProvider.java revision 3390018c6b45acffa6edf97a4174ca49f1e8c76d
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 * @see ParcelFileDescriptor#parseMode(String) 1082 */ 1083 public ParcelFileDescriptor openFile(Uri uri, String mode) 1084 throws FileNotFoundException { 1085 throw new FileNotFoundException("No files supported by provider at " 1086 + uri); 1087 } 1088 1089 /** 1090 * Override this to handle requests to open a file blob. 1091 * The default implementation always throws {@link FileNotFoundException}. 1092 * This method can be called from multiple threads, as described in 1093 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1094 * and Threads</a>. 1095 * 1096 * <p>This method returns a ParcelFileDescriptor, which is returned directly 1097 * to the caller. This way large data (such as images and documents) can be 1098 * returned without copying the content. 1099 * 1100 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is 1101 * their responsibility to close it when done. That is, the implementation 1102 * of this method should create a new ParcelFileDescriptor for each call. 1103 * <p> 1104 * If opened with the exclusive "r" or "w" modes, the returned 1105 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming 1106 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that 1107 * supports seeking. 1108 * <p> 1109 * If you need to detect when the returned ParcelFileDescriptor has been 1110 * closed, or if the remote process has crashed or encountered some other 1111 * error, you can use {@link ParcelFileDescriptor#open(File, int, 1112 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)}, 1113 * {@link ParcelFileDescriptor#createReliablePipe()}, or 1114 * {@link ParcelFileDescriptor#createReliableSocketPair()}. 1115 * 1116 * <p class="note">For use in Intents, you will want to implement {@link #getType} 1117 * to return the appropriate MIME type for the data returned here with 1118 * the same URI. This will allow intent resolution to automatically determine the data MIME 1119 * type and select the appropriate matching targets as part of its operation.</p> 1120 * 1121 * <p class="note">For better interoperability with other applications, it is recommended 1122 * that for any URIs that can be opened, you also support queries on them 1123 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 1124 * You may also want to support other common columns if you have additional meta-data 1125 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 1126 * in {@link android.provider.MediaStore.MediaColumns}.</p> 1127 * 1128 * @param uri The URI whose file is to be opened. 1129 * @param mode Access mode for the file. May be "r" for read-only access, 1130 * "w" for write-only access, "rw" for read and write access, or 1131 * "rwt" for read and write access that truncates any existing 1132 * file. 1133 * @param signal A signal to cancel the operation in progress, or 1134 * {@code null} if none. For example, if you are downloading a 1135 * file from the network to service a "rw" mode request, you 1136 * should periodically call 1137 * {@link CancellationSignal#throwIfCanceled()} to check whether 1138 * the client has canceled the request and abort the download. 1139 * 1140 * @return Returns a new ParcelFileDescriptor which you can use to access 1141 * the file. 1142 * 1143 * @throws FileNotFoundException Throws FileNotFoundException if there is 1144 * no file associated with the given URI or the mode is invalid. 1145 * @throws SecurityException Throws SecurityException if the caller does 1146 * not have permission to access the file. 1147 * 1148 * @see #openAssetFile(Uri, String) 1149 * @see #openFileHelper(Uri, String) 1150 * @see #getType(android.net.Uri) 1151 * @see ParcelFileDescriptor#parseMode(String) 1152 */ 1153 public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) 1154 throws FileNotFoundException { 1155 return openFile(uri, mode); 1156 } 1157 1158 /** 1159 * This is like {@link #openFile}, but can be implemented by providers 1160 * that need to be able to return sub-sections of files, often assets 1161 * inside of their .apk. 1162 * This method can be called from multiple threads, as described in 1163 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1164 * and Threads</a>. 1165 * 1166 * <p>If you implement this, your clients must be able to deal with such 1167 * file slices, either directly with 1168 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 1169 * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 1170 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 1171 * methods. 1172 * <p> 1173 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1174 * streaming of data. 1175 * 1176 * <p class="note">If you are implementing this to return a full file, you 1177 * should create the AssetFileDescriptor with 1178 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 1179 * applications that cannot handle sub-sections of files.</p> 1180 * 1181 * <p class="note">For use in Intents, you will want to implement {@link #getType} 1182 * to return the appropriate MIME type for the data returned here with 1183 * the same URI. This will allow intent resolution to automatically determine the data MIME 1184 * type and select the appropriate matching targets as part of its operation.</p> 1185 * 1186 * <p class="note">For better interoperability with other applications, it is recommended 1187 * that for any URIs that can be opened, you also support queries on them 1188 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> 1189 * 1190 * @param uri The URI whose file is to be opened. 1191 * @param mode Access mode for the file. May be "r" for read-only access, 1192 * "w" for write-only access (erasing whatever data is currently in 1193 * the file), "wa" for write-only access to append to any existing data, 1194 * "rw" for read and write access on any existing data, and "rwt" for read 1195 * and write access that truncates any existing file. 1196 * 1197 * @return Returns a new AssetFileDescriptor which you can use to access 1198 * the file. 1199 * 1200 * @throws FileNotFoundException Throws FileNotFoundException if there is 1201 * no file associated with the given URI or the mode is invalid. 1202 * @throws SecurityException Throws SecurityException if the caller does 1203 * not have permission to access the file. 1204 * 1205 * @see #openFile(Uri, String) 1206 * @see #openFileHelper(Uri, String) 1207 * @see #getType(android.net.Uri) 1208 */ 1209 public AssetFileDescriptor openAssetFile(Uri uri, String mode) 1210 throws FileNotFoundException { 1211 ParcelFileDescriptor fd = openFile(uri, mode); 1212 return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null; 1213 } 1214 1215 /** 1216 * This is like {@link #openFile}, but can be implemented by providers 1217 * that need to be able to return sub-sections of files, often assets 1218 * inside of their .apk. 1219 * This method can be called from multiple threads, as described in 1220 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1221 * and Threads</a>. 1222 * 1223 * <p>If you implement this, your clients must be able to deal with such 1224 * file slices, either directly with 1225 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 1226 * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 1227 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 1228 * methods. 1229 * <p> 1230 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1231 * streaming of data. 1232 * 1233 * <p class="note">If you are implementing this to return a full file, you 1234 * should create the AssetFileDescriptor with 1235 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 1236 * applications that cannot handle sub-sections of files.</p> 1237 * 1238 * <p class="note">For use in Intents, you will want to implement {@link #getType} 1239 * to return the appropriate MIME type for the data returned here with 1240 * the same URI. This will allow intent resolution to automatically determine the data MIME 1241 * type and select the appropriate matching targets as part of its operation.</p> 1242 * 1243 * <p class="note">For better interoperability with other applications, it is recommended 1244 * that for any URIs that can be opened, you also support queries on them 1245 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> 1246 * 1247 * @param uri The URI whose file is to be opened. 1248 * @param mode Access mode for the file. May be "r" for read-only access, 1249 * "w" for write-only access (erasing whatever data is currently in 1250 * the file), "wa" for write-only access to append to any existing data, 1251 * "rw" for read and write access on any existing data, and "rwt" for read 1252 * and write access that truncates any existing file. 1253 * @param signal A signal to cancel the operation in progress, or 1254 * {@code null} if none. For example, if you are downloading a 1255 * file from the network to service a "rw" mode request, you 1256 * should periodically call 1257 * {@link CancellationSignal#throwIfCanceled()} to check whether 1258 * the client has canceled the request and abort the download. 1259 * 1260 * @return Returns a new AssetFileDescriptor which you can use to access 1261 * the file. 1262 * 1263 * @throws FileNotFoundException Throws FileNotFoundException if there is 1264 * no file associated with the given URI or the mode is invalid. 1265 * @throws SecurityException Throws SecurityException if the caller does 1266 * not have permission to access the file. 1267 * 1268 * @see #openFile(Uri, String) 1269 * @see #openFileHelper(Uri, String) 1270 * @see #getType(android.net.Uri) 1271 */ 1272 public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal) 1273 throws FileNotFoundException { 1274 return openAssetFile(uri, mode); 1275 } 1276 1277 /** 1278 * Convenience for subclasses that wish to implement {@link #openFile} 1279 * by looking up a column named "_data" at the given URI. 1280 * 1281 * @param uri The URI to be opened. 1282 * @param mode The file mode. May be "r" for read-only access, 1283 * "w" for write-only access (erasing whatever data is currently in 1284 * the file), "wa" for write-only access to append to any existing data, 1285 * "rw" for read and write access on any existing data, and "rwt" for read 1286 * and write access that truncates any existing file. 1287 * 1288 * @return Returns a new ParcelFileDescriptor that can be used by the 1289 * client to access the file. 1290 */ 1291 protected final ParcelFileDescriptor openFileHelper(Uri uri, 1292 String mode) throws FileNotFoundException { 1293 Cursor c = query(uri, new String[]{"_data"}, null, null, null); 1294 int count = (c != null) ? c.getCount() : 0; 1295 if (count != 1) { 1296 // If there is not exactly one result, throw an appropriate 1297 // exception. 1298 if (c != null) { 1299 c.close(); 1300 } 1301 if (count == 0) { 1302 throw new FileNotFoundException("No entry for " + uri); 1303 } 1304 throw new FileNotFoundException("Multiple items at " + uri); 1305 } 1306 1307 c.moveToFirst(); 1308 int i = c.getColumnIndex("_data"); 1309 String path = (i >= 0 ? c.getString(i) : null); 1310 c.close(); 1311 if (path == null) { 1312 throw new FileNotFoundException("Column _data not found."); 1313 } 1314 1315 int modeBits = ParcelFileDescriptor.parseMode(mode); 1316 return ParcelFileDescriptor.open(new File(path), modeBits); 1317 } 1318 1319 /** 1320 * Called by a client to determine the types of data streams that this 1321 * content provider supports for the given URI. The default implementation 1322 * returns {@code null}, meaning no types. If your content provider stores data 1323 * of a particular type, return that MIME type if it matches the given 1324 * mimeTypeFilter. If it can perform type conversions, return an array 1325 * of all supported MIME types that match mimeTypeFilter. 1326 * 1327 * @param uri The data in the content provider being queried. 1328 * @param mimeTypeFilter The type of data the client desires. May be 1329 * a pattern, such as */* to retrieve all possible data types. 1330 * @return Returns {@code null} if there are no possible data streams for the 1331 * given mimeTypeFilter. Otherwise returns an array of all available 1332 * concrete MIME types. 1333 * 1334 * @see #getType(Uri) 1335 * @see #openTypedAssetFile(Uri, String, Bundle) 1336 * @see ClipDescription#compareMimeTypes(String, String) 1337 */ 1338 public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { 1339 return null; 1340 } 1341 1342 /** 1343 * Called by a client to open a read-only stream containing data of a 1344 * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 1345 * except the file can only be read-only and the content provider may 1346 * perform data conversions to generate data of the desired type. 1347 * 1348 * <p>The default implementation compares the given mimeType against the 1349 * result of {@link #getType(Uri)} and, if they match, simply calls 1350 * {@link #openAssetFile(Uri, String)}. 1351 * 1352 * <p>See {@link ClipData} for examples of the use and implementation 1353 * of this method. 1354 * <p> 1355 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1356 * streaming of data. 1357 * 1358 * <p class="note">For better interoperability with other applications, it is recommended 1359 * that for any URIs that can be opened, you also support queries on them 1360 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 1361 * You may also want to support other common columns if you have additional meta-data 1362 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 1363 * in {@link android.provider.MediaStore.MediaColumns}.</p> 1364 * 1365 * @param uri The data in the content provider being queried. 1366 * @param mimeTypeFilter The type of data the client desires. May be 1367 * a pattern, such as */*, if the caller does not have specific type 1368 * requirements; in this case the content provider will pick its best 1369 * type matching the pattern. 1370 * @param opts Additional options from the client. The definitions of 1371 * these are specific to the content provider being called. 1372 * 1373 * @return Returns a new AssetFileDescriptor from which the client can 1374 * read data of the desired type. 1375 * 1376 * @throws FileNotFoundException Throws FileNotFoundException if there is 1377 * no file associated with the given URI or the mode is invalid. 1378 * @throws SecurityException Throws SecurityException if the caller does 1379 * not have permission to access the data. 1380 * @throws IllegalArgumentException Throws IllegalArgumentException if the 1381 * content provider does not support the requested MIME type. 1382 * 1383 * @see #getStreamTypes(Uri, String) 1384 * @see #openAssetFile(Uri, String) 1385 * @see ClipDescription#compareMimeTypes(String, String) 1386 */ 1387 public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts) 1388 throws FileNotFoundException { 1389 if ("*/*".equals(mimeTypeFilter)) { 1390 // If they can take anything, the untyped open call is good enough. 1391 return openAssetFile(uri, "r"); 1392 } 1393 String baseType = getType(uri); 1394 if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) { 1395 // Use old untyped open call if this provider has a type for this 1396 // URI and it matches the request. 1397 return openAssetFile(uri, "r"); 1398 } 1399 throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter); 1400 } 1401 1402 1403 /** 1404 * Called by a client to open a read-only stream containing data of a 1405 * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 1406 * except the file can only be read-only and the content provider may 1407 * perform data conversions to generate data of the desired type. 1408 * 1409 * <p>The default implementation compares the given mimeType against the 1410 * result of {@link #getType(Uri)} and, if they match, simply calls 1411 * {@link #openAssetFile(Uri, String)}. 1412 * 1413 * <p>See {@link ClipData} for examples of the use and implementation 1414 * of this method. 1415 * <p> 1416 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 1417 * streaming of data. 1418 * 1419 * <p class="note">For better interoperability with other applications, it is recommended 1420 * that for any URIs that can be opened, you also support queries on them 1421 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 1422 * You may also want to support other common columns if you have additional meta-data 1423 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 1424 * in {@link android.provider.MediaStore.MediaColumns}.</p> 1425 * 1426 * @param uri The data in the content provider being queried. 1427 * @param mimeTypeFilter The type of data the client desires. May be 1428 * a pattern, such as */*, if the caller does not have specific type 1429 * requirements; in this case the content provider will pick its best 1430 * type matching the pattern. 1431 * @param opts Additional options from the client. The definitions of 1432 * these are specific to the content provider being called. 1433 * @param signal A signal to cancel the operation in progress, or 1434 * {@code null} if none. For example, if you are downloading a 1435 * file from the network to service a "rw" mode request, you 1436 * should periodically call 1437 * {@link CancellationSignal#throwIfCanceled()} to check whether 1438 * the client has canceled the request and abort the download. 1439 * 1440 * @return Returns a new AssetFileDescriptor from which the client can 1441 * read data of the desired type. 1442 * 1443 * @throws FileNotFoundException Throws FileNotFoundException if there is 1444 * no file associated with the given URI or the mode is invalid. 1445 * @throws SecurityException Throws SecurityException if the caller does 1446 * not have permission to access the data. 1447 * @throws IllegalArgumentException Throws IllegalArgumentException if the 1448 * content provider does not support the requested MIME type. 1449 * 1450 * @see #getStreamTypes(Uri, String) 1451 * @see #openAssetFile(Uri, String) 1452 * @see ClipDescription#compareMimeTypes(String, String) 1453 */ 1454 public AssetFileDescriptor openTypedAssetFile( 1455 Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal) 1456 throws FileNotFoundException { 1457 return openTypedAssetFile(uri, mimeTypeFilter, opts); 1458 } 1459 1460 /** 1461 * Interface to write a stream of data to a pipe. Use with 1462 * {@link ContentProvider#openPipeHelper}. 1463 */ 1464 public interface PipeDataWriter<T> { 1465 /** 1466 * Called from a background thread to stream data out to a pipe. 1467 * Note that the pipe is blocking, so this thread can block on 1468 * writes for an arbitrary amount of time if the client is slow 1469 * at reading. 1470 * 1471 * @param output The pipe where data should be written. This will be 1472 * closed for you upon returning from this function. 1473 * @param uri The URI whose data is to be written. 1474 * @param mimeType The desired type of data to be written. 1475 * @param opts Options supplied by caller. 1476 * @param args Your own custom arguments. 1477 */ 1478 public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, 1479 Bundle opts, T args); 1480 } 1481 1482 /** 1483 * A helper function for implementing {@link #openTypedAssetFile}, for 1484 * creating a data pipe and background thread allowing you to stream 1485 * generated data back to the client. This function returns a new 1486 * ParcelFileDescriptor that should be returned to the caller (the caller 1487 * is responsible for closing it). 1488 * 1489 * @param uri The URI whose data is to be written. 1490 * @param mimeType The desired type of data to be written. 1491 * @param opts Options supplied by caller. 1492 * @param args Your own custom arguments. 1493 * @param func Interface implementing the function that will actually 1494 * stream the data. 1495 * @return Returns a new ParcelFileDescriptor holding the read side of 1496 * the pipe. This should be returned to the caller for reading; the caller 1497 * is responsible for closing it when done. 1498 */ 1499 public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType, 1500 final Bundle opts, final T args, final PipeDataWriter<T> func) 1501 throws FileNotFoundException { 1502 try { 1503 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 1504 1505 AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { 1506 @Override 1507 protected Object doInBackground(Object... params) { 1508 func.writeDataToPipe(fds[1], uri, mimeType, opts, args); 1509 try { 1510 fds[1].close(); 1511 } catch (IOException e) { 1512 Log.w(TAG, "Failure closing pipe", e); 1513 } 1514 return null; 1515 } 1516 }; 1517 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null); 1518 1519 return fds[0]; 1520 } catch (IOException e) { 1521 throw new FileNotFoundException("failure making pipe"); 1522 } 1523 } 1524 1525 /** 1526 * Returns true if this instance is a temporary content provider. 1527 * @return true if this instance is a temporary content provider 1528 */ 1529 protected boolean isTemporary() { 1530 return false; 1531 } 1532 1533 /** 1534 * Returns the Binder object for this provider. 1535 * 1536 * @return the Binder object for this provider 1537 * @hide 1538 */ 1539 public IContentProvider getIContentProvider() { 1540 return mTransport; 1541 } 1542 1543 /** 1544 * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use 1545 * when directly instantiating the provider for testing. 1546 * @hide 1547 */ 1548 public void attachInfoForTesting(Context context, ProviderInfo info) { 1549 attachInfo(context, info, true); 1550 } 1551 1552 /** 1553 * After being instantiated, this is called to tell the content provider 1554 * about itself. 1555 * 1556 * @param context The context this provider is running in 1557 * @param info Registered information about this content provider 1558 */ 1559 public void attachInfo(Context context, ProviderInfo info) { 1560 attachInfo(context, info, false); 1561 } 1562 1563 private void attachInfo(Context context, ProviderInfo info, boolean testing) { 1564 /* 1565 * We may be using AsyncTask from binder threads. Make it init here 1566 * so its static handler is on the main thread. 1567 */ 1568 AsyncTask.init(); 1569 1570 mNoPerms = testing; 1571 1572 /* 1573 * Only allow it to be set once, so after the content service gives 1574 * this to us clients can't change it. 1575 */ 1576 if (mContext == null) { 1577 mContext = context; 1578 if (context != null) { 1579 mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService( 1580 Context.APP_OPS_SERVICE); 1581 } 1582 mMyUid = Process.myUid(); 1583 if (info != null) { 1584 setReadPermission(info.readPermission); 1585 setWritePermission(info.writePermission); 1586 setPathPermissions(info.pathPermissions); 1587 mExported = info.exported; 1588 } 1589 ContentProvider.this.onCreate(); 1590 } 1591 } 1592 1593 /** 1594 * Override this to handle requests to perform a batch of operations, or the 1595 * default implementation will iterate over the operations and call 1596 * {@link ContentProviderOperation#apply} on each of them. 1597 * If all calls to {@link ContentProviderOperation#apply} succeed 1598 * then a {@link ContentProviderResult} array with as many 1599 * elements as there were operations will be returned. If any of the calls 1600 * fail, it is up to the implementation how many of the others take effect. 1601 * This method can be called from multiple threads, as described in 1602 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1603 * and Threads</a>. 1604 * 1605 * @param operations the operations to apply 1606 * @return the results of the applications 1607 * @throws OperationApplicationException thrown if any operation fails. 1608 * @see ContentProviderOperation#apply 1609 */ 1610 public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1611 throws OperationApplicationException { 1612 final int numOperations = operations.size(); 1613 final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 1614 for (int i = 0; i < numOperations; i++) { 1615 results[i] = operations.get(i).apply(this, results, i); 1616 } 1617 return results; 1618 } 1619 1620 /** 1621 * Call a provider-defined method. This can be used to implement 1622 * interfaces that are cheaper and/or unnatural for a table-like 1623 * model. 1624 * 1625 * <p class="note"><strong>WARNING:</strong> The framework does no permission checking 1626 * on this entry into the content provider besides the basic ability for the application 1627 * to get access to the provider at all. For example, it has no idea whether the call 1628 * being executed may read or write data in the provider, so can't enforce those 1629 * individual permissions. Any implementation of this method <strong>must</strong> 1630 * do its own permission checks on incoming calls to make sure they are allowed.</p> 1631 * 1632 * @param method method name to call. Opaque to framework, but should not be {@code null}. 1633 * @param arg provider-defined String argument. May be {@code null}. 1634 * @param extras provider-defined Bundle argument. May be {@code null}. 1635 * @return provider-defined return value. May be {@code null}, which is also 1636 * the default for providers which don't implement any call methods. 1637 */ 1638 public Bundle call(String method, String arg, Bundle extras) { 1639 return null; 1640 } 1641 1642 /** 1643 * Implement this to shut down the ContentProvider instance. You can then 1644 * invoke this method in unit tests. 1645 * 1646 * <p> 1647 * Android normally handles ContentProvider startup and shutdown 1648 * automatically. You do not need to start up or shut down a 1649 * ContentProvider. When you invoke a test method on a ContentProvider, 1650 * however, a ContentProvider instance is started and keeps running after 1651 * the test finishes, even if a succeeding test instantiates another 1652 * ContentProvider. A conflict develops because the two instances are 1653 * usually running against the same underlying data source (for example, an 1654 * sqlite database). 1655 * </p> 1656 * <p> 1657 * Implementing shutDown() avoids this conflict by providing a way to 1658 * terminate the ContentProvider. This method can also prevent memory leaks 1659 * from multiple instantiations of the ContentProvider, and it can ensure 1660 * unit test isolation by allowing you to completely clean up the test 1661 * fixture before moving on to the next test. 1662 * </p> 1663 */ 1664 public void shutdown() { 1665 Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " + 1666 "connections are gracefully shutdown"); 1667 } 1668 1669 /** 1670 * Print the Provider's state into the given stream. This gets invoked if 1671 * you run "adb shell dumpsys activity provider <provider_component_name>". 1672 * 1673 * @param fd The raw file descriptor that the dump is being sent to. 1674 * @param writer The PrintWriter to which you should dump your state. This will be 1675 * closed for you after you return. 1676 * @param args additional arguments to the dump request. 1677 */ 1678 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1679 writer.println("nothing to dump"); 1680 } 1681} 1682