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