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.Manifest.permission.INTERACT_ACROSS_USERS; 20 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; 21 import static android.os.Process.SYSTEM_UID; 22 import static android.os.Process.myUserHandle; 23 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; 24 25 import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION; 26 import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION; 27 import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_FRAMEWORK_PERMISSION; 28 29 import android.Manifest; 30 import android.annotation.NonNull; 31 import android.annotation.Nullable; 32 import android.annotation.SystemApi; 33 import android.annotation.TestApi; 34 import android.app.AppOpsManager; 35 import android.compat.annotation.UnsupportedAppUsage; 36 import android.content.pm.PackageManager; 37 import android.content.pm.PathPermission; 38 import android.content.pm.ProviderInfo; 39 import android.content.res.AssetFileDescriptor; 40 import android.content.res.Configuration; 41 import android.database.Cursor; 42 import android.database.MatrixCursor; 43 import android.database.SQLException; 44 import android.multiuser.Flags; 45 import android.net.Uri; 46 import android.os.AsyncTask; 47 import android.os.Binder; 48 import android.os.Build; 49 import android.os.Bundle; 50 import android.os.CancellationSignal; 51 import android.os.ICancellationSignal; 52 import android.os.ParcelFileDescriptor; 53 import android.os.ParcelableException; 54 import android.os.Process; 55 import android.os.RemoteCallback; 56 import android.os.RemoteException; 57 import android.os.Trace; 58 import android.os.UserHandle; 59 import android.os.UserManager; 60 import android.os.storage.StorageManager; 61 import android.permission.PermissionCheckerManager; 62 import android.provider.MediaStore; 63 import android.text.TextUtils; 64 import android.util.ArraySet; 65 import android.util.Log; 66 import android.util.SparseBooleanArray; 67 68 import com.android.internal.annotations.VisibleForTesting; 69 import com.android.internal.util.FrameworkStatsLog; 70 71 import java.io.File; 72 import java.io.FileDescriptor; 73 import java.io.FileNotFoundException; 74 import java.io.IOException; 75 import java.io.PrintWriter; 76 import java.util.ArrayList; 77 import java.util.Arrays; 78 import java.util.Objects; 79 80 /** 81 * Content providers are one of the primary building blocks of Android applications, providing 82 * content to applications. They encapsulate data and provide it to applications through the single 83 * {@link ContentResolver} interface. A content provider is only required if you need to share 84 * data between multiple applications. For example, the contacts data is used by multiple 85 * applications and must be stored in a content provider. If you don't need to share data amongst 86 * multiple applications you can use a database directly via 87 * {@link android.database.sqlite.SQLiteDatabase}. 88 * 89 * <p>When a request is made via 90 * a {@link ContentResolver} the system inspects the authority of the given URI and passes the 91 * request to the content provider registered with the authority. The content provider can interpret 92 * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing 93 * URIs.</p> 94 * 95 * <p>The primary methods that need to be implemented are: 96 * <ul> 97 * <li>{@link #onCreate} which is called to initialize the provider</li> 98 * <li>{@link #query} which returns data to the caller</li> 99 * <li>{@link #insert} which inserts new data into the content provider</li> 100 * <li>{@link #update} which updates existing data in the content provider</li> 101 * <li>{@link #delete} which deletes data from the content provider</li> 102 * <li>{@link #getType} which returns the MIME type of data in the content provider</li> 103 * </ul></p> 104 * 105 * <p class="caution">Data access methods (such as {@link #insert} and 106 * {@link #update}) may be called from many threads at once, and must be thread-safe. 107 * Other methods (such as {@link #onCreate}) are only called from the application 108 * main thread, and must avoid performing lengthy operations. See the method 109 * descriptions for their expected thread behavior.</p> 110 * 111 * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate 112 * ContentProvider instance, so subclasses don't have to worry about the details of 113 * cross-process calls.</p> 114 * 115 * <div class="special reference"> 116 * <h3>Developer Guides</h3> 117 * <p>For more information about using content providers, read the 118 * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> 119 * developer guide.</p> 120 * </div> 121 */ 122 @android.ravenwood.annotation.RavenwoodKeepPartialClass 123 public abstract class ContentProvider implements ContentInterface, ComponentCallbacks2 { 124 125 private static final String TAG = "ContentProvider"; 126 127 /* 128 * Note: if you add methods to ContentProvider, you must add similar methods to 129 * MockContentProvider. 130 */ 131 132 @UnsupportedAppUsage 133 private Context mContext = null; 134 private int mMyUid; 135 136 // Since most Providers have only one authority, we keep both a String and a String[] to improve 137 // performance. 138 @UnsupportedAppUsage 139 private String mAuthority; 140 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 141 private String[] mAuthorities; 142 @UnsupportedAppUsage 143 private String mReadPermission; 144 @UnsupportedAppUsage 145 private String mWritePermission; 146 @UnsupportedAppUsage 147 private PathPermission[] mPathPermissions; 148 private boolean mExported; 149 private boolean mNoPerms; 150 private boolean mSingleUser; 151 private boolean mSystemUserOnly; 152 private SparseBooleanArray mUsersRedirectedToOwnerForMedia = new SparseBooleanArray(); 153 154 private ThreadLocal<AttributionSource> mCallingAttributionSource; 155 156 /** 157 * @hide 158 */ isAuthorityRedirectedForCloneProfile(String authority)159 public static boolean isAuthorityRedirectedForCloneProfile(String authority) { 160 // For now, only MediaProvider gets redirected. 161 return MediaStore.AUTHORITY.equals(authority); 162 } 163 164 private Transport mTransport = new Transport(); 165 166 /** 167 * Construct a ContentProvider instance. Content providers must be 168 * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared 169 * in the manifest</a>, accessed with {@link ContentResolver}, and created 170 * automatically by the system, so applications usually do not create 171 * ContentProvider instances directly. 172 * 173 * <p>At construction time, the object is uninitialized, and most fields and 174 * methods are unavailable. Subclasses should initialize themselves in 175 * {@link #onCreate}, not the constructor. 176 * 177 * <p>Content providers are created on the application main thread at 178 * application launch time. The constructor must not perform lengthy 179 * operations, or application startup will be delayed. 180 */ ContentProvider()181 public ContentProvider() { 182 } 183 184 /** 185 * Constructor just for mocking. 186 * 187 * @param context A Context object which should be some mock instance (like the 188 * instance of {@link android.test.mock.MockContext}). 189 * @param readPermission The read permission you want this instance should have in the 190 * test, which is available via {@link #getReadPermission()}. 191 * @param writePermission The write permission you want this instance should have 192 * in the test, which is available via {@link #getWritePermission()}. 193 * @param pathPermissions The PathPermissions you want this instance should have 194 * in the test, which is available via {@link #getPathPermissions()}. 195 * @hide 196 */ 197 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) ContentProvider( Context context, String readPermission, String writePermission, PathPermission[] pathPermissions)198 public ContentProvider( 199 Context context, 200 String readPermission, 201 String writePermission, 202 PathPermission[] pathPermissions) { 203 mContext = context; 204 mReadPermission = readPermission; 205 mWritePermission = writePermission; 206 mPathPermissions = pathPermissions; 207 } 208 209 /** 210 * Given an IContentProvider, try to coerce it back to the real 211 * ContentProvider object if it is running in the local process. This can 212 * be used if you know you are running in the same process as a provider, 213 * and want to get direct access to its implementation details. Most 214 * clients should not nor have a reason to use it. 215 * 216 * @param abstractInterface The ContentProvider interface that is to be 217 * coerced. 218 * @return If the IContentProvider is non-{@code null} and local, returns its actual 219 * ContentProvider instance. Otherwise returns {@code null}. 220 * @hide 221 */ 222 @UnsupportedAppUsage coerceToLocalContentProvider( IContentProvider abstractInterface)223 public static ContentProvider coerceToLocalContentProvider( 224 IContentProvider abstractInterface) { 225 if (abstractInterface instanceof Transport) { 226 return ((Transport)abstractInterface).getContentProvider(); 227 } 228 return null; 229 } 230 231 /** 232 * Binder object that deals with remoting. 233 * 234 * @hide 235 */ 236 class Transport extends ContentProviderNative { 237 volatile AppOpsManager mAppOpsManager = null; 238 volatile int mReadOp = AppOpsManager.OP_NONE; 239 volatile int mWriteOp = AppOpsManager.OP_NONE; 240 volatile ContentInterface mInterface = ContentProvider.this; 241 getContentProvider()242 ContentProvider getContentProvider() { 243 return ContentProvider.this; 244 } 245 246 @Override getProviderName()247 public String getProviderName() { 248 return getContentProvider().getClass().getName(); 249 } 250 251 @Override query(@onNull AttributionSource attributionSource, Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)252 public Cursor query(@NonNull AttributionSource attributionSource, Uri uri, 253 @Nullable String[] projection, @Nullable Bundle queryArgs, 254 @Nullable ICancellationSignal cancellationSignal) { 255 uri = validateIncomingUri(uri); 256 uri = maybeGetUriWithoutUserId(uri); 257 if (enforceReadPermission(attributionSource, uri) 258 != PermissionChecker.PERMISSION_GRANTED) { 259 // The caller has no access to the data, so return an empty cursor with 260 // the columns in the requested order. The caller may ask for an invalid 261 // column and we would not catch that but this is not a problem in practice. 262 // We do not call ContentProvider#query with a modified where clause since 263 // the implementation is not guaranteed to be backed by a SQL database, hence 264 // it may not handle properly the tautology where clause we would have created. 265 if (projection != null) { 266 return new MatrixCursor(projection, 0); 267 } 268 269 // Null projection means all columns but we have no idea which they are. 270 // However, the caller may be expecting to access them my index. Hence, 271 // we have to execute the query as if allowed to get a cursor with the 272 // columns. We then use the column names to return an empty cursor. 273 Cursor cursor; 274 final AttributionSource original = setCallingAttributionSource( 275 attributionSource); 276 try { 277 cursor = mInterface.query( 278 uri, projection, queryArgs, 279 CancellationSignal.fromTransport(cancellationSignal)); 280 } catch (RemoteException e) { 281 throw e.rethrowAsRuntimeException(); 282 } finally { 283 setCallingAttributionSource(original); 284 } 285 if (cursor == null) { 286 return null; 287 } 288 289 // Return an empty cursor for all columns. 290 return new MatrixCursor(cursor.getColumnNames(), 0); 291 } 292 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "query: ", uri.getAuthority()); 293 final AttributionSource original = setCallingAttributionSource( 294 attributionSource); 295 try { 296 return mInterface.query( 297 uri, projection, queryArgs, 298 CancellationSignal.fromTransport(cancellationSignal)); 299 } catch (RemoteException e) { 300 throw e.rethrowAsRuntimeException(); 301 } finally { 302 setCallingAttributionSource(original); 303 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 304 } 305 } 306 307 @Override getType(AttributionSource attributionSource, Uri uri)308 public String getType(AttributionSource attributionSource, Uri uri) { 309 uri = validateIncomingUri(uri); 310 uri = maybeGetUriWithoutUserId(uri); 311 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getType: ", uri.getAuthority()); 312 final AttributionSource original = setCallingAttributionSource( 313 attributionSource); 314 try { 315 if (checkGetTypePermission(attributionSource, uri) 316 == PermissionChecker.PERMISSION_GRANTED) { 317 String type; 318 if (checkPermission(Manifest.permission.GET_ANY_PROVIDER_TYPE, 319 attributionSource) == PermissionChecker.PERMISSION_GRANTED) { 320 /* 321 For calling packages having the special permission for any type, 322 the calling identity should be cleared before calling getType. 323 */ 324 final CallingIdentity origId = getContentProvider().clearCallingIdentity(); 325 try { 326 type = mInterface.getType(uri); 327 } finally { 328 getContentProvider().restoreCallingIdentity(origId); 329 } 330 } else { 331 type = mInterface.getType(uri); 332 } 333 334 if (type != null) { 335 logGetTypeData(Binder.getCallingUid(), uri, type, true); 336 } 337 return type; 338 } else { 339 final int callingUid = Binder.getCallingUid(); 340 final CallingIdentity origId = getContentProvider().clearCallingIdentity(); 341 try { 342 final String type = getTypeAnonymous(uri); 343 if (type != null) { 344 logGetTypeData(callingUid, uri, type, false); 345 } 346 return type; 347 } finally { 348 getContentProvider().restoreCallingIdentity(origId); 349 } 350 } 351 } catch (RemoteException e) { 352 throw e.rethrowAsRuntimeException(); 353 } finally { 354 setCallingAttributionSource(original); 355 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 356 } 357 } 358 359 // Utility function to log the getTypeData calls logGetTypeData(int callingUid, Uri uri, String type, boolean permissionCheckPassed)360 private void logGetTypeData(int callingUid, Uri uri, String type, 361 boolean permissionCheckPassed) { 362 final int enumFrameworkPermission = 363 GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_FRAMEWORK_PERMISSION; 364 final int enumCheckUriPermission = 365 GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION; 366 if (permissionCheckPassed) { 367 try { 368 // Just for logging for mediaProvider cases 369 final ProviderInfo cpi = mContext.getPackageManager() 370 .resolveContentProvider(uri.getAuthority(), 371 PackageManager.ComponentInfoFlags.of( 372 PackageManager.GET_META_DATA)); 373 final int callingUserId = UserHandle.getUserId(callingUid); 374 final Uri userUri = (mSingleUser 375 && !UserHandle.isSameUser(mMyUid, callingUid)) 376 ? maybeAddUserId(uri, callingUserId) : uri; 377 if (cpi.forceUriPermissions 378 && mInterface.checkUriPermission(uri, 379 callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION) 380 != PermissionChecker.PERMISSION_GRANTED 381 && getContext().checkUriPermission(userUri, Binder.getCallingPid(), 382 callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION) 383 != PackageManager.PERMISSION_GRANTED 384 && !deniedAccessSystemUserOnlyProvider(callingUserId, 385 mSystemUserOnly)) { 386 FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION, 387 enumCheckUriPermission, 388 callingUid, uri.getAuthority(), type); 389 } 390 } catch (Exception e) { 391 //does nothing 392 } 393 } else { 394 FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION, 395 enumFrameworkPermission, 396 callingUid, uri.getAuthority(), type); 397 } 398 } 399 400 @Override getTypeAsync(AttributionSource attributionSource, Uri uri, RemoteCallback callback)401 public void getTypeAsync(AttributionSource attributionSource, 402 Uri uri, RemoteCallback callback) { 403 final Bundle result = new Bundle(); 404 try { 405 result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, 406 getType(attributionSource, uri)); 407 } catch (Exception e) { 408 result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR, 409 new ParcelableException(e)); 410 } 411 callback.sendResult(result); 412 } 413 414 @Override getTypeAnonymousAsync(Uri uri, RemoteCallback callback)415 public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback) { 416 // getCallingPackage() isn't available in getTypeAnonymous(), as the javadoc states. 417 uri = validateIncomingUri(uri); 418 uri = maybeGetUriWithoutUserId(uri); 419 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getTypeAnonymous: ", uri.getAuthority()); 420 final Bundle result = new Bundle(); 421 try { 422 result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri)); 423 } catch (Exception e) { 424 result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR, 425 new ParcelableException(e)); 426 } finally { 427 callback.sendResult(result); 428 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 429 } 430 } 431 432 @Override insert(@onNull AttributionSource attributionSource, Uri uri, ContentValues initialValues, Bundle extras)433 public Uri insert(@NonNull AttributionSource attributionSource, Uri uri, 434 ContentValues initialValues, Bundle extras) { 435 uri = validateIncomingUri(uri); 436 int userId = getUserIdFromUri(uri); 437 uri = maybeGetUriWithoutUserId(uri); 438 if (enforceWritePermission(attributionSource, uri) 439 != PermissionChecker.PERMISSION_GRANTED) { 440 final AttributionSource original = setCallingAttributionSource( 441 attributionSource); 442 try { 443 return rejectInsert(uri, initialValues); 444 } finally { 445 setCallingAttributionSource(original); 446 } 447 } 448 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "insert: ", uri.getAuthority()); 449 final AttributionSource original = setCallingAttributionSource( 450 attributionSource); 451 try { 452 return maybeAddUserId(mInterface.insert(uri, initialValues, extras), userId); 453 } catch (RemoteException e) { 454 throw e.rethrowAsRuntimeException(); 455 } finally { 456 setCallingAttributionSource(original); 457 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 458 } 459 } 460 461 @Override bulkInsert(@onNull AttributionSource attributionSource, Uri uri, ContentValues[] initialValues)462 public int bulkInsert(@NonNull AttributionSource attributionSource, Uri uri, 463 ContentValues[] initialValues) { 464 uri = validateIncomingUri(uri); 465 uri = maybeGetUriWithoutUserId(uri); 466 if (enforceWritePermission(attributionSource, uri) 467 != PermissionChecker.PERMISSION_GRANTED) { 468 return 0; 469 } 470 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "bulkInsert: ", uri.getAuthority()); 471 final AttributionSource original = setCallingAttributionSource( 472 attributionSource); 473 try { 474 return mInterface.bulkInsert(uri, initialValues); 475 } catch (RemoteException e) { 476 throw e.rethrowAsRuntimeException(); 477 } finally { 478 setCallingAttributionSource(original); 479 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 480 } 481 } 482 483 @Override applyBatch(@onNull AttributionSource attributionSource, String authority, ArrayList<ContentProviderOperation> operations)484 public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource, 485 String authority, ArrayList<ContentProviderOperation> operations) 486 throws OperationApplicationException { 487 validateIncomingAuthority(authority); 488 int numOperations = operations.size(); 489 final int[] userIds = new int[numOperations]; 490 final ArraySet<String> readPermissions = new ArraySet<String>(); 491 final ArraySet<String> writePermissions = new ArraySet<String>(); 492 for (int i = 0; i < numOperations; i++) { 493 ContentProviderOperation operation = operations.get(i); 494 Uri uri = operation.getUri(); 495 userIds[i] = getUserIdFromUri(uri); 496 uri = validateIncomingUri(uri); 497 uri = maybeGetUriWithoutUserId(uri); 498 // Rebuild operation if we changed the Uri above 499 if (!Objects.equals(operation.getUri(), uri)) { 500 operation = new ContentProviderOperation(operation, uri); 501 operations.set(i, operation); 502 } 503 final AttributionSource accessAttributionSource = 504 attributionSource; 505 if (operation.isReadOperation() && !readPermissions.contains(uri.toString())) { 506 if (enforceReadPermission(accessAttributionSource, uri) 507 != PermissionChecker.PERMISSION_GRANTED) { 508 throw new OperationApplicationException("App op not allowed", 0); 509 } 510 readPermissions.add(uri.toString()); 511 } 512 if (operation.isWriteOperation() && !writePermissions.contains(uri.toString())) { 513 if (enforceWritePermission(accessAttributionSource, uri) 514 != PermissionChecker.PERMISSION_GRANTED) { 515 throw new OperationApplicationException("App op not allowed", 0); 516 } 517 writePermissions.add(uri.toString()); 518 } 519 } 520 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "applyBatch: ", authority); 521 final AttributionSource original = setCallingAttributionSource( 522 attributionSource); 523 try { 524 ContentProviderResult[] results = mInterface.applyBatch(authority, 525 operations); 526 if (results != null) { 527 for (int i = 0; i < results.length ; i++) { 528 if (userIds[i] != UserHandle.USER_CURRENT) { 529 // Adding the userId to the uri. 530 results[i] = new ContentProviderResult(results[i], userIds[i]); 531 } 532 } 533 } 534 return results; 535 } catch (RemoteException e) { 536 throw e.rethrowAsRuntimeException(); 537 } finally { 538 setCallingAttributionSource(original); 539 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 540 } 541 } 542 543 @Override delete(@onNull AttributionSource attributionSource, Uri uri, Bundle extras)544 public int delete(@NonNull AttributionSource attributionSource, Uri uri, 545 Bundle extras) { 546 uri = validateIncomingUri(uri); 547 uri = maybeGetUriWithoutUserId(uri); 548 if (enforceWritePermission(attributionSource, uri) 549 != PermissionChecker.PERMISSION_GRANTED) { 550 return 0; 551 } 552 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "delete: ", uri.getAuthority()); 553 final AttributionSource original = setCallingAttributionSource( 554 attributionSource); 555 try { 556 return mInterface.delete(uri, extras); 557 } catch (RemoteException e) { 558 throw e.rethrowAsRuntimeException(); 559 } finally { 560 setCallingAttributionSource(original); 561 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 562 } 563 } 564 565 @Override update(@onNull AttributionSource attributionSource, Uri uri, ContentValues values, Bundle extras)566 public int update(@NonNull AttributionSource attributionSource, Uri uri, 567 ContentValues values, Bundle extras) { 568 uri = validateIncomingUri(uri); 569 uri = maybeGetUriWithoutUserId(uri); 570 if (enforceWritePermission(attributionSource, uri) 571 != PermissionChecker.PERMISSION_GRANTED) { 572 return 0; 573 } 574 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "update: ", uri.getAuthority()); 575 final AttributionSource original = setCallingAttributionSource( 576 attributionSource); 577 try { 578 return mInterface.update(uri, values, extras); 579 } catch (RemoteException e) { 580 throw e.rethrowAsRuntimeException(); 581 } finally { 582 setCallingAttributionSource(original); 583 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 584 } 585 } 586 587 @Override openFile(@onNull AttributionSource attributionSource, Uri uri, String mode, ICancellationSignal cancellationSignal)588 public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource, 589 Uri uri, String mode, ICancellationSignal cancellationSignal) 590 throws FileNotFoundException { 591 uri = validateIncomingUri(uri); 592 uri = maybeGetUriWithoutUserId(uri); 593 enforceFilePermission(attributionSource, uri, mode); 594 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openFile: ", uri.getAuthority()); 595 final AttributionSource original = setCallingAttributionSource( 596 attributionSource); 597 try { 598 return mInterface.openFile( 599 uri, mode, CancellationSignal.fromTransport(cancellationSignal)); 600 } catch (RemoteException e) { 601 throw e.rethrowAsRuntimeException(); 602 } finally { 603 setCallingAttributionSource(original); 604 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 605 } 606 } 607 608 @Override openAssetFile(@onNull AttributionSource attributionSource, Uri uri, String mode, ICancellationSignal cancellationSignal)609 public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource, 610 Uri uri, String mode, ICancellationSignal cancellationSignal) 611 throws FileNotFoundException { 612 uri = validateIncomingUri(uri); 613 uri = maybeGetUriWithoutUserId(uri); 614 enforceFilePermission(attributionSource, uri, mode); 615 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openAssetFile: ", uri.getAuthority()); 616 final AttributionSource original = setCallingAttributionSource( 617 attributionSource); 618 try { 619 return mInterface.openAssetFile( 620 uri, mode, CancellationSignal.fromTransport(cancellationSignal)); 621 } catch (RemoteException e) { 622 throw e.rethrowAsRuntimeException(); 623 } finally { 624 setCallingAttributionSource(original); 625 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 626 } 627 } 628 629 @Override call(@onNull AttributionSource attributionSource, String authority, String method, @Nullable String arg, @Nullable Bundle extras)630 public Bundle call(@NonNull AttributionSource attributionSource, String authority, 631 String method, @Nullable String arg, @Nullable Bundle extras) { 632 validateIncomingAuthority(authority); 633 Bundle.setDefusable(extras, true); 634 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "call: ", authority); 635 final AttributionSource original = setCallingAttributionSource( 636 attributionSource); 637 try { 638 return mInterface.call(authority, method, arg, extras); 639 } catch (RemoteException e) { 640 throw e.rethrowAsRuntimeException(); 641 } finally { 642 setCallingAttributionSource(original); 643 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 644 } 645 } 646 647 @Override getStreamTypes(AttributionSource attributionSource, Uri uri, String mimeTypeFilter)648 public String[] getStreamTypes(AttributionSource attributionSource, 649 Uri uri, String mimeTypeFilter) { 650 uri = validateIncomingUri(uri); 651 uri = maybeGetUriWithoutUserId(uri); 652 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getStreamTypes: ", uri.getAuthority()); 653 final AttributionSource original = setCallingAttributionSource( 654 attributionSource); 655 try { 656 return mInterface.getStreamTypes(uri, mimeTypeFilter); 657 } catch (RemoteException e) { 658 throw e.rethrowAsRuntimeException(); 659 } finally { 660 setCallingAttributionSource(original); 661 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 662 } 663 } 664 665 @Override openTypedAssetFile( @onNull AttributionSource attributionSource, Uri uri, String mimeType, Bundle opts, ICancellationSignal cancellationSignal)666 public AssetFileDescriptor openTypedAssetFile( 667 @NonNull AttributionSource attributionSource, Uri uri, String mimeType, 668 Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException { 669 Bundle.setDefusable(opts, true); 670 uri = validateIncomingUri(uri); 671 uri = maybeGetUriWithoutUserId(uri); 672 enforceFilePermission(attributionSource, uri, "r"); 673 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openTypedAssetFile: ", uri.getAuthority()); 674 final AttributionSource original = setCallingAttributionSource( 675 attributionSource); 676 try { 677 return mInterface.openTypedAssetFile( 678 uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal)); 679 } catch (RemoteException e) { 680 throw e.rethrowAsRuntimeException(); 681 } finally { 682 setCallingAttributionSource(original); 683 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 684 } 685 } 686 687 @Override createCancellationSignal()688 public ICancellationSignal createCancellationSignal() { 689 return CancellationSignal.createTransport(); 690 } 691 692 @Override canonicalize(@onNull AttributionSource attributionSource, Uri uri)693 public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri uri) { 694 uri = validateIncomingUri(uri); 695 int userId = getUserIdFromUri(uri); 696 uri = getUriWithoutUserId(uri); 697 if (enforceReadPermission(attributionSource, uri) 698 != PermissionChecker.PERMISSION_GRANTED) { 699 return null; 700 } 701 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "canonicalize: ", uri.getAuthority()); 702 final AttributionSource original = setCallingAttributionSource( 703 attributionSource); 704 try { 705 return maybeAddUserId(mInterface.canonicalize(uri), userId); 706 } catch (RemoteException e) { 707 throw e.rethrowAsRuntimeException(); 708 } finally { 709 setCallingAttributionSource(original); 710 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 711 } 712 } 713 714 @Override canonicalizeAsync(@onNull AttributionSource attributionSource, Uri uri, RemoteCallback callback)715 public void canonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri, 716 RemoteCallback callback) { 717 final Bundle result = new Bundle(); 718 try { 719 result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, 720 canonicalize(attributionSource, uri)); 721 } catch (Exception e) { 722 result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR, 723 new ParcelableException(e)); 724 } 725 callback.sendResult(result); 726 } 727 728 @Override uncanonicalize(@onNull AttributionSource attributionSource, Uri uri)729 public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri uri) { 730 uri = validateIncomingUri(uri); 731 int userId = getUserIdFromUri(uri); 732 uri = getUriWithoutUserId(uri); 733 if (enforceReadPermission(attributionSource, uri) 734 != PermissionChecker.PERMISSION_GRANTED) { 735 return null; 736 } 737 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "uncanonicalize: ", uri.getAuthority()); 738 final AttributionSource original = setCallingAttributionSource( 739 attributionSource); 740 try { 741 return maybeAddUserId(mInterface.uncanonicalize(uri), userId); 742 } catch (RemoteException e) { 743 throw e.rethrowAsRuntimeException(); 744 } finally { 745 setCallingAttributionSource(original); 746 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 747 } 748 } 749 750 @Override uncanonicalizeAsync(@onNull AttributionSource attributionSource, Uri uri, RemoteCallback callback)751 public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource, Uri uri, 752 RemoteCallback callback) { 753 final Bundle result = new Bundle(); 754 try { 755 result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, 756 uncanonicalize(attributionSource, uri)); 757 } catch (Exception e) { 758 result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR, 759 new ParcelableException(e)); 760 } 761 callback.sendResult(result); 762 } 763 764 @Override refresh(@onNull AttributionSource attributionSource, Uri uri, Bundle extras, ICancellationSignal cancellationSignal)765 public boolean refresh(@NonNull AttributionSource attributionSource, Uri uri, 766 Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException { 767 uri = validateIncomingUri(uri); 768 uri = getUriWithoutUserId(uri); 769 if (enforceReadPermission(attributionSource, uri) 770 != PermissionChecker.PERMISSION_GRANTED) { 771 return false; 772 } 773 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "refresh: ", uri.getAuthority()); 774 final AttributionSource original = setCallingAttributionSource( 775 attributionSource); 776 try { 777 return mInterface.refresh(uri, extras, 778 CancellationSignal.fromTransport(cancellationSignal)); 779 } finally { 780 setCallingAttributionSource(original); 781 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 782 } 783 } 784 785 @Override checkUriPermission(@onNull AttributionSource attributionSource, Uri uri, int uid, int modeFlags)786 public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri, 787 int uid, int modeFlags) { 788 uri = validateIncomingUri(uri); 789 uri = maybeGetUriWithoutUserId(uri); 790 traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "checkUriPermission: ", uri.getAuthority()); 791 final AttributionSource original = setCallingAttributionSource( 792 attributionSource); 793 try { 794 return mInterface.checkUriPermission(uri, uid, modeFlags); 795 } catch (RemoteException e) { 796 throw e.rethrowAsRuntimeException(); 797 } finally { 798 setCallingAttributionSource(original); 799 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); 800 } 801 } 802 803 @PermissionCheckerManager.PermissionResult enforceFilePermission(@onNull AttributionSource attributionSource, Uri uri, String mode)804 private void enforceFilePermission(@NonNull AttributionSource attributionSource, 805 Uri uri, String mode) 806 throws FileNotFoundException, SecurityException { 807 if (mode != null && mode.indexOf('w') != -1) { 808 if (enforceWritePermission(attributionSource, uri) 809 != PermissionChecker.PERMISSION_GRANTED) { 810 throw new FileNotFoundException("App op not allowed"); 811 } 812 } else { 813 if (enforceReadPermission(attributionSource, uri) 814 != PermissionChecker.PERMISSION_GRANTED) { 815 throw new FileNotFoundException("App op not allowed"); 816 } 817 } 818 } 819 820 @PermissionCheckerManager.PermissionResult enforceReadPermission(@onNull AttributionSource attributionSource, Uri uri)821 private int enforceReadPermission(@NonNull AttributionSource attributionSource, Uri uri) 822 throws SecurityException { 823 final int result = enforceReadPermissionInner(uri, attributionSource); 824 if (result != PermissionChecker.PERMISSION_GRANTED) { 825 return result; 826 } 827 // Only check the read op if it differs from the one for the permission 828 // we already checked above to avoid double attribution for every access. 829 if (mTransport.mReadOp != AppOpsManager.OP_NONE 830 && mTransport.mReadOp != AppOpsManager.permissionToOpCode(mReadPermission)) { 831 return PermissionChecker.checkOpForDataDelivery(getContext(), 832 AppOpsManager.opToPublicName(mTransport.mReadOp), 833 attributionSource, /*message*/ null); 834 } 835 return PermissionChecker.PERMISSION_GRANTED; 836 } 837 838 @PermissionCheckerManager.PermissionResult enforceWritePermission(@onNull AttributionSource attributionSource, Uri uri)839 private int enforceWritePermission(@NonNull AttributionSource attributionSource, Uri uri) 840 throws SecurityException { 841 final int result = enforceWritePermissionInner(uri, attributionSource); 842 if (result != PermissionChecker.PERMISSION_GRANTED) { 843 return result; 844 } 845 // Only check the write op if it differs from the one for the permission 846 // we already checked above to avoid double attribution for every access. 847 if (mTransport.mWriteOp != AppOpsManager.OP_NONE 848 && mTransport.mWriteOp != AppOpsManager.permissionToOpCode(mWritePermission)) { 849 return PermissionChecker.checkOpForDataDelivery(getContext(), 850 AppOpsManager.opToPublicName(mTransport.mWriteOp), 851 attributionSource, /*message*/ null); 852 } 853 return PermissionChecker.PERMISSION_GRANTED; 854 } 855 856 @PermissionCheckerManager.PermissionResult checkGetTypePermission(@onNull AttributionSource attributionSource, Uri uri)857 private int checkGetTypePermission(@NonNull AttributionSource attributionSource, 858 Uri uri) { 859 final int callingUid = Binder.getCallingUid(); 860 if (UserHandle.getAppId(callingUid) == SYSTEM_UID 861 || checkPermission(Manifest.permission.GET_ANY_PROVIDER_TYPE, attributionSource) 862 == PermissionChecker.PERMISSION_GRANTED) { 863 // Allowing System Uid and apps with permission to get any type, to access all types 864 return PermissionChecker.PERMISSION_GRANTED; 865 } 866 try { 867 return enforceReadPermission(attributionSource, uri); 868 } catch (SecurityException e) { 869 return PermissionChecker.PERMISSION_HARD_DENIED; 870 } 871 } 872 } 873 checkUser(int pid, int uid, Context context)874 boolean checkUser(int pid, int uid, Context context) { 875 final int callingUserId = UserHandle.getUserId(uid); 876 877 if (deniedAccessSystemUserOnlyProvider(callingUserId, mSystemUserOnly)) { 878 return false; 879 } 880 881 if (callingUserId == context.getUserId() || mSingleUser) { 882 return true; 883 } 884 if (context.checkPermission(INTERACT_ACROSS_USERS, pid, uid) 885 == PackageManager.PERMISSION_GRANTED 886 || context.checkPermission(INTERACT_ACROSS_USERS_FULL, pid, uid) 887 == PackageManager.PERMISSION_GRANTED) { 888 return true; 889 } 890 891 // Provider user-id will be determined from User Space of the calling app. 892 return isContentRedirectionAllowedForUser(callingUserId); 893 } 894 895 /** 896 * Verify that content redirection is allowed or not. 897 * We check: 898 * 1. Type of Authority 899 * 2. UserProperties allow content sharing 900 * 901 * @param incomingUserId - Provider's user-id to be passed should be based upon: 902 * 1. If client is a cloned app running in user 10, it should be that (10) 903 * 2. If client is accessing content by hinting user space of content, 904 * like sysUi (residing in user 0) accessing 'content://11@media/external' 905 * then it should be 11. 906 */ isContentRedirectionAllowedForUser(int incomingUserId)907 private boolean isContentRedirectionAllowedForUser(int incomingUserId) { 908 if (MediaStore.AUTHORITY.equals(mAuthority)) { 909 int incomingUserIdIndex = mUsersRedirectedToOwnerForMedia.indexOfKey(incomingUserId); 910 if (incomingUserIdIndex >= 0) { 911 return mUsersRedirectedToOwnerForMedia.valueAt(incomingUserIdIndex); 912 } 913 914 // Haven't seen this user yet, look it up 915 UserManager um = mContext.getSystemService(UserManager.class); 916 if (um != null && um.getUserProperties(UserHandle.of(incomingUserId)) 917 .isMediaSharedWithParent()) { 918 UserHandle parent = um.getProfileParent(UserHandle.of(incomingUserId)); 919 if (parent != null && parent.equals(myUserHandle())) { 920 mUsersRedirectedToOwnerForMedia.put(incomingUserId, true); 921 return true; 922 } 923 } 924 925 mUsersRedirectedToOwnerForMedia.put(incomingUserId, false); 926 return false; 927 } 928 return false; 929 } 930 931 /** 932 * Verify that calling app holds both the given permission and any app-op 933 * associated with that permission. 934 */ 935 @PermissionCheckerManager.PermissionResult checkPermission(String permission, @NonNull AttributionSource attributionSource)936 private int checkPermission(String permission, 937 @NonNull AttributionSource attributionSource) { 938 if (Binder.getCallingPid() == Process.myPid()) { 939 return PermissionChecker.PERMISSION_GRANTED; 940 } 941 return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(getContext(), 942 permission, -1, new AttributionSource(getContext().getAttributionSource(), 943 attributionSource), /*message*/ null); 944 } 945 946 /** {@hide} */ 947 @PermissionCheckerManager.PermissionResult enforceReadPermissionInner(Uri uri, @NonNull AttributionSource attributionSource)948 protected int enforceReadPermissionInner(Uri uri, 949 @NonNull AttributionSource attributionSource) throws SecurityException { 950 final Context context = getContext(); 951 final int pid = Binder.getCallingPid(); 952 final int uid = Binder.getCallingUid(); 953 String missingPerm = null; 954 int strongestResult = PermissionChecker.PERMISSION_GRANTED; 955 956 if (UserHandle.isSameApp(uid, mMyUid)) { 957 return PermissionChecker.PERMISSION_GRANTED; 958 } 959 960 if (mExported && checkUser(pid, uid, context)) { 961 final String componentPerm = getReadPermission(); 962 if (componentPerm != null) { 963 final int result = checkPermission(componentPerm, attributionSource); 964 if (result == PermissionChecker.PERMISSION_GRANTED) { 965 return PermissionChecker.PERMISSION_GRANTED; 966 } else { 967 missingPerm = componentPerm; 968 strongestResult = Math.max(strongestResult, result); 969 } 970 } 971 972 // track if unprotected read is allowed; any denied 973 // <path-permission> below removes this ability 974 boolean allowDefaultRead = (componentPerm == null); 975 976 final PathPermission[] pps = getPathPermissions(); 977 if (pps != null) { 978 final String path = uri.getPath(); 979 for (PathPermission pp : pps) { 980 final String pathPerm = pp.getReadPermission(); 981 if (pathPerm != null && pp.match(path)) { 982 final int result = checkPermission(pathPerm, attributionSource); 983 if (result == PermissionChecker.PERMISSION_GRANTED) { 984 return PermissionChecker.PERMISSION_GRANTED; 985 } else { 986 // any denied <path-permission> means we lose 987 // default <provider> access. 988 allowDefaultRead = false; 989 missingPerm = pathPerm; 990 strongestResult = Math.max(strongestResult, result); 991 } 992 } 993 } 994 } 995 996 // if we passed <path-permission> checks above, and no default 997 // <provider> permission, then allow access. 998 if (allowDefaultRead) return PermissionChecker.PERMISSION_GRANTED; 999 } 1000 1001 // last chance, check against any uri grants 1002 final int callingUserId = UserHandle.getUserId(uid); 1003 if (deniedAccessSystemUserOnlyProvider(callingUserId, mSystemUserOnly)) { 1004 return PermissionChecker.PERMISSION_HARD_DENIED; 1005 } 1006 final Uri userUri = (mSingleUser && !UserHandle.isSameUser(mMyUid, uid)) 1007 ? maybeAddUserId(uri, callingUserId) : uri; 1008 if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) 1009 == PackageManager.PERMISSION_GRANTED) { 1010 return PermissionChecker.PERMISSION_GRANTED; 1011 } 1012 1013 // If the worst denial we found above was ignored, then pass that 1014 // ignored through; otherwise we assume it should be a real error below. 1015 if (strongestResult == PermissionChecker.PERMISSION_SOFT_DENIED) { 1016 return PermissionChecker.PERMISSION_SOFT_DENIED; 1017 } 1018 1019 final String suffix; 1020 if (android.Manifest.permission.MANAGE_DOCUMENTS.equals(mReadPermission)) { 1021 suffix = " requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs"; 1022 } else if (mExported) { 1023 suffix = " requires " + missingPerm + ", or grantUriPermission()"; 1024 } else { 1025 suffix = " requires the provider be exported, or grantUriPermission()"; 1026 } 1027 throw new SecurityException("Permission Denial: reading " 1028 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid 1029 + ", uid=" + uid + suffix); 1030 } 1031 1032 /** {@hide} */ 1033 @PermissionCheckerManager.PermissionResult enforceWritePermissionInner(Uri uri, @NonNull AttributionSource attributionSource)1034 protected int enforceWritePermissionInner(Uri uri, 1035 @NonNull AttributionSource attributionSource) throws SecurityException { 1036 final Context context = getContext(); 1037 final int pid = Binder.getCallingPid(); 1038 final int uid = Binder.getCallingUid(); 1039 String missingPerm = null; 1040 int strongestResult = PermissionChecker.PERMISSION_GRANTED; 1041 1042 if (UserHandle.isSameApp(uid, mMyUid)) { 1043 return PermissionChecker.PERMISSION_GRANTED; 1044 } 1045 1046 if (mExported && checkUser(pid, uid, context)) { 1047 final String componentPerm = getWritePermission(); 1048 if (componentPerm != null) { 1049 final int mode = checkPermission(componentPerm, attributionSource); 1050 if (mode == PermissionChecker.PERMISSION_GRANTED) { 1051 return PermissionChecker.PERMISSION_GRANTED; 1052 } else { 1053 missingPerm = componentPerm; 1054 strongestResult = Math.max(strongestResult, mode); 1055 } 1056 } 1057 1058 // track if unprotected write is allowed; any denied 1059 // <path-permission> below removes this ability 1060 boolean allowDefaultWrite = (componentPerm == null); 1061 1062 final PathPermission[] pps = getPathPermissions(); 1063 if (pps != null) { 1064 final String path = uri.getPath(); 1065 for (PathPermission pp : pps) { 1066 final String pathPerm = pp.getWritePermission(); 1067 if (pathPerm != null && pp.match(path)) { 1068 final int mode = checkPermission(pathPerm, attributionSource); 1069 if (mode == PermissionChecker.PERMISSION_GRANTED) { 1070 return PermissionChecker.PERMISSION_GRANTED; 1071 } else { 1072 // any denied <path-permission> means we lose 1073 // default <provider> access. 1074 allowDefaultWrite = false; 1075 missingPerm = pathPerm; 1076 strongestResult = Math.max(strongestResult, mode); 1077 } 1078 } 1079 } 1080 } 1081 1082 // if we passed <path-permission> checks above, and no default 1083 // <provider> permission, then allow access. 1084 if (allowDefaultWrite) return PermissionChecker.PERMISSION_GRANTED; 1085 } 1086 1087 // last chance, check against any uri grants 1088 if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 1089 == PackageManager.PERMISSION_GRANTED) { 1090 return PermissionChecker.PERMISSION_GRANTED; 1091 } 1092 1093 // If the worst denial we found above was ignored, then pass that 1094 // ignored through; otherwise we assume it should be a real error below. 1095 if (strongestResult == PermissionChecker.PERMISSION_SOFT_DENIED) { 1096 return PermissionChecker.PERMISSION_SOFT_DENIED; 1097 } 1098 1099 final String failReason = mExported 1100 ? " requires " + missingPerm + ", or grantUriPermission()" 1101 : " requires the provider be exported, or grantUriPermission()"; 1102 throw new SecurityException("Permission Denial: writing " 1103 + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid 1104 + ", uid=" + uid + failReason); 1105 } 1106 1107 /** 1108 * Retrieves the Context this provider is running in. Only available once 1109 * {@link #onCreate} has been called -- this will return {@code null} in the 1110 * constructor. 1111 */ getContext()1112 public final @Nullable Context getContext() { 1113 return mContext; 1114 } 1115 1116 /** 1117 * Retrieves a Non-Nullable Context this provider is running in, this is intended to be called 1118 * after {@link #onCreate}. When called before context was created, an IllegalStateException 1119 * will be thrown. 1120 * <p> 1121 * Note A provider must be declared in the manifest and created automatically by the system, 1122 * and context is only available after {@link #onCreate} is called. 1123 */ 1124 @NonNull requireContext()1125 public final Context requireContext() { 1126 final Context ctx = getContext(); 1127 if (ctx == null) { 1128 throw new IllegalStateException("Cannot find context from the provider."); 1129 } 1130 return ctx; 1131 } 1132 1133 /** 1134 * Set the calling package/feature, returning the current value (or {@code null}) 1135 * which can be used later to restore the previous state. 1136 */ setCallingAttributionSource( @ullable AttributionSource attributionSource)1137 private @Nullable AttributionSource setCallingAttributionSource( 1138 @Nullable AttributionSource attributionSource) { 1139 final AttributionSource original = mCallingAttributionSource.get(); 1140 mCallingAttributionSource.set(attributionSource); 1141 onCallingPackageChanged(); 1142 return original; 1143 } 1144 1145 /** 1146 * Return the package name of the caller that initiated the request being 1147 * processed on the current thread. The returned package will have been 1148 * verified to belong to the calling UID. Returns {@code null} if not 1149 * currently processing a request. 1150 * <p> 1151 * This will always return {@code null} when processing 1152 * {@link #getTypeAnonymous(Uri)} requests 1153 * 1154 * For {@link #getType(Uri)} requests, this will be only available for cases, where 1155 * the caller can be identified. See {@link #getTypeAnonymous(Uri)} 1156 * 1157 * @see Binder#getCallingUid() 1158 * @see Context#grantUriPermission(String, Uri, int) 1159 * @throws SecurityException if the calling package doesn't belong to the 1160 * calling UID. 1161 */ getCallingPackage()1162 public final @Nullable String getCallingPackage() { 1163 final AttributionSource callingAttributionSource = getCallingAttributionSource(); 1164 return (callingAttributionSource != null) 1165 ? callingAttributionSource.getPackageName() : null; 1166 } 1167 1168 /** 1169 * Gets the attribution source of the calling app. If you want to attribute 1170 * the data access to the calling app you can create an attribution context 1171 * via {@link android.content.Context#createContext(ContextParams)} and passing 1172 * this identity to {@link ContextParams.Builder#setNextAttributionSource( 1173 * AttributionSource)}. 1174 * 1175 * @return The identity of the caller for permission purposes. 1176 * 1177 * @see ContextParams.Builder#setNextAttributionSource(AttributionSource) 1178 * @see AttributionSource 1179 */ getCallingAttributionSource()1180 public final @Nullable AttributionSource getCallingAttributionSource() { 1181 final AttributionSource attributionSource = mCallingAttributionSource.get(); 1182 if (attributionSource != null) { 1183 mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), 1184 attributionSource.getPackageName()); 1185 } 1186 return attributionSource; 1187 } 1188 1189 /** 1190 * Return the attribution tag of the caller that initiated the request being 1191 * processed on the current thread. Returns {@code null} if not currently processing 1192 * a request of the request is for the default attribution. 1193 * <p> 1194 * This will always return {@code null} when processing 1195 * {@link #getTypeAnonymous(Uri)} requests 1196 * 1197 * For {@link #getType(Uri)} requests, this will be only available for cases, where 1198 * the caller can be identified. See {@link #getTypeAnonymous(Uri)} 1199 * 1200 * @see #getCallingPackage 1201 */ getCallingAttributionTag()1202 public final @Nullable String getCallingAttributionTag() { 1203 final AttributionSource attributionSource = mCallingAttributionSource.get(); 1204 if (attributionSource != null) { 1205 return attributionSource.getAttributionTag(); 1206 } 1207 return null; 1208 } 1209 1210 /** 1211 * @removed 1212 */ 1213 @Deprecated getCallingFeatureId()1214 public final @Nullable String getCallingFeatureId() { 1215 return getCallingAttributionTag(); 1216 } 1217 1218 /** 1219 * Return the package name of the caller that initiated the request being 1220 * processed on the current thread. The returned package will have 1221 * <em>not</em> been verified to belong to the calling UID. Returns 1222 * {@code null} if not currently processing a request. 1223 * <p> 1224 * This will always return {@code null} when processing 1225 * {@link #getTypeAnonymous(Uri)} requests 1226 * 1227 * For {@link #getType(Uri)} requests, this will be only available for cases, where 1228 * the caller can be identified. See {@link #getTypeAnonymous(Uri)} 1229 * 1230 * @see Binder#getCallingUid() 1231 * @see Context#grantUriPermission(String, Uri, int) 1232 */ getCallingPackageUnchecked()1233 public final @Nullable String getCallingPackageUnchecked() { 1234 final AttributionSource attributionSource = mCallingAttributionSource.get(); 1235 if (attributionSource != null) { 1236 return attributionSource.getPackageName(); 1237 } 1238 return null; 1239 } 1240 1241 /** 1242 * Called whenever the value of {@link #getCallingPackage()} changes, giving 1243 * the provider an opportunity to invalidate any security related caching it 1244 * may be performing. 1245 * <p> 1246 * This typically happens when a {@link ContentProvider} makes a nested call 1247 * back into itself when already processing a call from a remote process. 1248 */ onCallingPackageChanged()1249 public void onCallingPackageChanged() { 1250 } 1251 1252 /** 1253 * Opaque token representing the identity of an incoming IPC. 1254 */ 1255 public final class CallingIdentity { 1256 /** {@hide} */ 1257 public final long binderToken; 1258 /** {@hide} */ 1259 public final @Nullable AttributionSource callingAttributionSource; 1260 1261 /** {@hide} */ CallingIdentity(long binderToken, @Nullable AttributionSource attributionSource)1262 public CallingIdentity(long binderToken, @Nullable AttributionSource attributionSource) { 1263 this.binderToken = binderToken; 1264 this.callingAttributionSource = attributionSource; 1265 } 1266 } 1267 1268 /** 1269 * Reset the identity of the incoming IPC on the current thread. 1270 * <p> 1271 * Internally this calls {@link Binder#clearCallingIdentity()} and also 1272 * clears any value stored in {@link #getCallingPackage()}. 1273 * 1274 * @return Returns an opaque token that can be used to restore the original 1275 * calling identity by passing it to 1276 * {@link #restoreCallingIdentity}. 1277 */ 1278 @SuppressWarnings("ResultOfClearIdentityCallNotStoredInVariable") clearCallingIdentity()1279 public final @NonNull CallingIdentity clearCallingIdentity() { 1280 return new CallingIdentity(Binder.clearCallingIdentity(), 1281 setCallingAttributionSource(null)); 1282 } 1283 1284 /** 1285 * Restore the identity of the incoming IPC on the current thread back to a 1286 * previously identity that was returned by {@link #clearCallingIdentity}. 1287 * <p> 1288 * Internally this calls {@link Binder#restoreCallingIdentity(long)} and 1289 * also restores any value stored in {@link #getCallingPackage()}. 1290 */ restoreCallingIdentity(@onNull CallingIdentity identity)1291 public final void restoreCallingIdentity(@NonNull CallingIdentity identity) { 1292 Binder.restoreCallingIdentity(identity.binderToken); 1293 mCallingAttributionSource.set(identity.callingAttributionSource); 1294 } 1295 1296 /** 1297 * Change the authorities of the ContentProvider. 1298 * This is normally set for you from its manifest information when the provider is first 1299 * created. 1300 * @hide 1301 * @param authorities the semi-colon separated authorities of the ContentProvider. 1302 */ setAuthorities(String authorities)1303 protected final void setAuthorities(String authorities) { 1304 if (authorities != null) { 1305 if (authorities.indexOf(';') == -1) { 1306 mAuthority = authorities; 1307 mAuthorities = null; 1308 } else { 1309 mAuthority = null; 1310 mAuthorities = authorities.split(";"); 1311 } 1312 } 1313 } 1314 1315 /** @hide */ matchesOurAuthorities(String authority)1316 protected final boolean matchesOurAuthorities(String authority) { 1317 if (mAuthority != null) { 1318 return mAuthority.equals(authority); 1319 } 1320 if (mAuthorities != null) { 1321 int length = mAuthorities.length; 1322 for (int i = 0; i < length; i++) { 1323 if (mAuthorities[i].equals(authority)) return true; 1324 } 1325 } 1326 return false; 1327 } 1328 1329 1330 /** 1331 * Change the permission required to read data from the content 1332 * provider. This is normally set for you from its manifest information 1333 * when the provider is first created. 1334 * 1335 * @param permission Name of the permission required for read-only access. 1336 */ setReadPermission(@ullable String permission)1337 protected final void setReadPermission(@Nullable String permission) { 1338 mReadPermission = permission; 1339 } 1340 1341 /** 1342 * Return the name of the permission required for read-only access to 1343 * this content provider. This method can be called from multiple 1344 * threads, as described in 1345 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1346 * and Threads</a>. 1347 */ getReadPermission()1348 public final @Nullable String getReadPermission() { 1349 return mReadPermission; 1350 } 1351 1352 /** 1353 * Change the permission required to read and write data in the content 1354 * provider. This is normally set for you from its manifest information 1355 * when the provider is first created. 1356 * 1357 * @param permission Name of the permission required for read/write access. 1358 */ setWritePermission(@ullable String permission)1359 protected final void setWritePermission(@Nullable String permission) { 1360 mWritePermission = permission; 1361 } 1362 1363 /** 1364 * Return the name of the permission required for read/write access to 1365 * this content provider. This method can be called from multiple 1366 * threads, as described in 1367 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1368 * and Threads</a>. 1369 */ getWritePermission()1370 public final @Nullable String getWritePermission() { 1371 return mWritePermission; 1372 } 1373 1374 /** 1375 * Change the path-based permission required to read and/or write data in 1376 * the content provider. This is normally set for you from its manifest 1377 * information when the provider is first created. 1378 * 1379 * @param permissions Array of path permission descriptions. 1380 */ setPathPermissions(@ullable PathPermission[] permissions)1381 protected final void setPathPermissions(@Nullable PathPermission[] permissions) { 1382 mPathPermissions = permissions; 1383 } 1384 1385 /** 1386 * Return the path-based permissions required for read and/or write access to 1387 * this content provider. This method can be called from multiple 1388 * threads, as described in 1389 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1390 * and Threads</a>. 1391 */ getPathPermissions()1392 public final @Nullable PathPermission[] getPathPermissions() { 1393 return mPathPermissions; 1394 } 1395 1396 /** @hide */ 1397 @UnsupportedAppUsage setAppOps(int readOp, int writeOp)1398 public final void setAppOps(int readOp, int writeOp) { 1399 if (!mNoPerms) { 1400 mTransport.mReadOp = readOp; 1401 mTransport.mWriteOp = writeOp; 1402 } 1403 } 1404 1405 /** @hide */ getAppOpsManager()1406 public AppOpsManager getAppOpsManager() { 1407 return mTransport.mAppOpsManager; 1408 } 1409 1410 /** @hide */ setTransportLoggingEnabled(boolean enabled)1411 public final void setTransportLoggingEnabled(boolean enabled) { 1412 if (mTransport == null) { 1413 return; 1414 } 1415 if (enabled) { 1416 mTransport.mInterface = new LoggingContentInterface(getClass().getSimpleName(), this); 1417 } else { 1418 mTransport.mInterface = this; 1419 } 1420 } 1421 1422 /** 1423 * Implement this to initialize your content provider on startup. 1424 * This method is called for all registered content providers on the 1425 * application main thread at application launch time. It must not perform 1426 * lengthy operations, or application startup will be delayed. 1427 * 1428 * <p>You should defer nontrivial initialization (such as opening, 1429 * upgrading, and scanning databases) until the content provider is used 1430 * (via {@link #query}, {@link #insert}, etc). Deferred initialization 1431 * keeps application startup fast, avoids unnecessary work if the provider 1432 * turns out not to be needed, and stops database errors (such as a full 1433 * disk) from halting application launch. 1434 * 1435 * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper} 1436 * is a helpful utility class that makes it easy to manage databases, 1437 * and will automatically defer opening until first use. If you do use 1438 * SQLiteOpenHelper, make sure to avoid calling 1439 * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or 1440 * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 1441 * from this method. (Instead, override 1442 * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the 1443 * database when it is first opened.) 1444 * 1445 * @return true if the provider was successfully loaded, false otherwise 1446 */ onCreate()1447 public abstract boolean onCreate(); 1448 1449 /** 1450 * {@inheritDoc} 1451 * This method is always called on the application main thread, and must 1452 * not perform lengthy operations. 1453 * 1454 * <p>The default content provider implementation does nothing. 1455 * Override this method to take appropriate action. 1456 * (Content providers do not usually care about things like screen 1457 * orientation, but may want to know about locale changes.) 1458 */ 1459 @Override onConfigurationChanged(Configuration newConfig)1460 public void onConfigurationChanged(Configuration newConfig) { 1461 } 1462 1463 /** 1464 * {@inheritDoc} 1465 * This method is always called on the application main thread, and must 1466 * not perform lengthy operations. 1467 * 1468 * <p>The default content provider implementation does nothing. 1469 * Subclasses may override this method to take appropriate action. 1470 */ 1471 @Override onLowMemory()1472 public void onLowMemory() { 1473 } 1474 1475 @Override onTrimMemory(int level)1476 public void onTrimMemory(int level) { 1477 } 1478 1479 /** 1480 * Implement this to handle query requests from clients. 1481 * 1482 * <p>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher should override 1483 * {@link #query(Uri, String[], Bundle, CancellationSignal)} and provide a stub 1484 * implementation of this method. 1485 * 1486 * <p>This method can be called from multiple threads, as described in 1487 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1488 * and Threads</a>. 1489 * <p> 1490 * Example client call:<p> 1491 * <pre>// Request a specific record. 1492 * Cursor managedCursor = managedQuery( 1493 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), 1494 projection, // Which columns to return. 1495 null, // WHERE clause. 1496 null, // WHERE clause value substitution 1497 People.NAME + " ASC"); // Sort order.</pre> 1498 * Example implementation:<p> 1499 * <pre>// SQLiteQueryBuilder is a helper class that creates the 1500 // proper SQL syntax for us. 1501 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 1502 1503 // Guard against SQL injection attacks 1504 qBuilder.setStrict(true); 1505 qBuilder.setProjectionMap(MAP_OF_QUERYABLE_COLUMNS); 1506 qBuilder.setStrictColumns(true); 1507 qBuilder.setStrictGrammar(true); 1508 1509 // Set the table we're querying. 1510 qBuilder.setTables(DATABASE_TABLE_NAME); 1511 1512 // If the query ends in a specific record number, we're 1513 // being asked for a specific record, so set the 1514 // WHERE clause in our query. 1515 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 1516 qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 1517 } 1518 1519 // Make the query. 1520 Cursor c = qBuilder.query(mDb, 1521 projection, 1522 selection, 1523 selectionArgs, 1524 groupBy, 1525 having, 1526 sortOrder); 1527 c.setNotificationUri(getContext().getContentResolver(), uri); 1528 return c;</pre> 1529 * 1530 * @param uri The URI to query. This will be the full URI sent by the client; 1531 * if the client is requesting a specific record, the URI will end in a record number 1532 * that the implementation should parse and add to a WHERE or HAVING clause, specifying 1533 * that _id value. 1534 * @param projection The list of columns to put into the cursor. If 1535 * {@code null} all columns are included. 1536 * @param selection A selection criteria to apply when filtering rows. 1537 * If {@code null} then all rows are included. 1538 * @param selectionArgs You may include ?s in selection, which will be replaced by 1539 * the values from selectionArgs, in order that they appear in the selection. 1540 * The values will be bound as Strings. 1541 * @param sortOrder How the rows in the cursor should be sorted. 1542 * If {@code null} then the provider is free to define the sort order. 1543 * @return a Cursor or {@code null}. 1544 */ query(@onNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder)1545 public abstract @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection, 1546 @Nullable String selection, @Nullable String[] selectionArgs, 1547 @Nullable String sortOrder); 1548 1549 /** 1550 * Implement this to handle query requests from clients with support for cancellation. 1551 * 1552 * <p>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher should override 1553 * {@link #query(Uri, String[], Bundle, CancellationSignal)} instead of this method. 1554 * 1555 * <p>This method can be called from multiple threads, as described in 1556 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1557 * and Threads</a>. 1558 * <p> 1559 * Example client call:<p> 1560 * <pre>// Request a specific record. 1561 * Cursor managedCursor = managedQuery( 1562 ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), 1563 projection, // Which columns to return. 1564 null, // WHERE clause. 1565 null, // WHERE clause value substitution 1566 People.NAME + " ASC"); // Sort order.</pre> 1567 * Example implementation:<p> 1568 * <pre>// SQLiteQueryBuilder is a helper class that creates the 1569 // proper SQL syntax for us. 1570 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 1571 1572 // Guard against SQL injection attacks 1573 qBuilder.setStrict(true); 1574 qBuilder.setProjectionMap(MAP_OF_QUERYABLE_COLUMNS); 1575 qBuilder.setStrictColumns(true); 1576 qBuilder.setStrictGrammar(true); 1577 1578 // Set the table we're querying. 1579 qBuilder.setTables(DATABASE_TABLE_NAME); 1580 1581 // If the query ends in a specific record number, we're 1582 // being asked for a specific record, so set the 1583 // WHERE clause in our query. 1584 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 1585 qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 1586 } 1587 1588 // Make the query. 1589 Cursor c = qBuilder.query(mDb, 1590 projection, 1591 selection, 1592 selectionArgs, 1593 groupBy, 1594 having, 1595 sortOrder); 1596 c.setNotificationUri(getContext().getContentResolver(), uri); 1597 return c;</pre> 1598 * <p> 1599 * If you implement this method then you must also implement the version of 1600 * {@link #query(Uri, String[], String, String[], String)} that does not take a cancellation 1601 * signal to ensure correct operation on older versions of the Android Framework in 1602 * which the cancellation signal overload was not available. 1603 * 1604 * @param uri The URI to query. This will be the full URI sent by the client; 1605 * if the client is requesting a specific record, the URI will end in a record number 1606 * that the implementation should parse and add to a WHERE or HAVING clause, specifying 1607 * that _id value. 1608 * @param projection The list of columns to put into the cursor. If 1609 * {@code null} all columns are included. 1610 * @param selection A selection criteria to apply when filtering rows. 1611 * If {@code null} then all rows are included. 1612 * @param selectionArgs You may include ?s in selection, which will be replaced by 1613 * the values from selectionArgs, in order that they appear in the selection. 1614 * The values will be bound as Strings. 1615 * @param sortOrder How the rows in the cursor should be sorted. 1616 * If {@code null} then the provider is free to define the sort order. 1617 * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if none. 1618 * If the operation is canceled, then {@link android.os.OperationCanceledException} will be thrown 1619 * when the query is executed. 1620 * @return a Cursor or {@code null}. 1621 */ query(@onNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal)1622 public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection, 1623 @Nullable String selection, @Nullable String[] selectionArgs, 1624 @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) { 1625 return query(uri, projection, selection, selectionArgs, sortOrder); 1626 } 1627 1628 /** 1629 * Implement this to handle query requests where the arguments are packed into a {@link Bundle}. 1630 * Arguments may include traditional SQL style query arguments. When present these 1631 * should be handled according to the contract established in 1632 * {@link #query(Uri, String[], String, String[], String, CancellationSignal)}. 1633 * 1634 * <p>Traditional SQL arguments can be found in the bundle using the following keys: 1635 * <li>{@link android.content.ContentResolver#QUERY_ARG_SQL_SELECTION} 1636 * <li>{@link android.content.ContentResolver#QUERY_ARG_SQL_SELECTION_ARGS} 1637 * <li>{@link android.content.ContentResolver#QUERY_ARG_SQL_SORT_ORDER} 1638 * 1639 * <p>This method can be called from multiple threads, as described in 1640 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1641 * and Threads</a>. 1642 * 1643 * <p> 1644 * Example client call:<p> 1645 * <pre>// Request 20 records starting at row index 30. 1646 Bundle queryArgs = new Bundle(); 1647 queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 30); 1648 queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 20); 1649 1650 Cursor cursor = getContentResolver().query( 1651 contentUri, // Content Uri is specific to individual content providers. 1652 projection, // String[] describing which columns to return. 1653 queryArgs, // Query arguments. 1654 null); // Cancellation signal.</pre> 1655 * 1656 * Example implementation:<p> 1657 * <pre> 1658 1659 int recordsetSize = 0x1000; // Actual value is implementation specific. 1660 queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY; // ensure queryArgs is non-null 1661 1662 int offset = queryArgs.getInt(ContentResolver.QUERY_ARG_OFFSET, 0); 1663 int limit = queryArgs.getInt(ContentResolver.QUERY_ARG_LIMIT, Integer.MIN_VALUE); 1664 1665 MatrixCursor c = new MatrixCursor(PROJECTION, limit); 1666 1667 // Calculate the number of items to include in the cursor. 1668 int numItems = MathUtils.constrain(recordsetSize - offset, 0, limit); 1669 1670 // Build the paged result set.... 1671 for (int i = offset; i < offset + numItems; i++) { 1672 // populate row from your data. 1673 } 1674 1675 Bundle extras = new Bundle(); 1676 c.setExtras(extras); 1677 1678 // Any QUERY_ARG_* key may be included if honored. 1679 // In an actual implementation, include only keys that are both present in queryArgs 1680 // and reflected in the Cursor output. For example, if QUERY_ARG_OFFSET were included 1681 // in queryArgs, but was ignored because it contained an invalid value (like –273), 1682 // then QUERY_ARG_OFFSET should be omitted. 1683 extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, new String[] { 1684 ContentResolver.QUERY_ARG_OFFSET, 1685 ContentResolver.QUERY_ARG_LIMIT 1686 }); 1687 1688 extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize); 1689 1690 cursor.setNotificationUri(getContext().getContentResolver(), uri); 1691 1692 return cursor;</pre> 1693 * <p> 1694 * See {@link #query(Uri, String[], String, String[], String, CancellationSignal)} 1695 * for implementation details. 1696 * 1697 * @param uri The URI to query. This will be the full URI sent by the client. 1698 * @param projection The list of columns to put into the cursor. 1699 * If {@code null} provide a default set of columns. 1700 * @param queryArgs A Bundle containing additional information necessary for 1701 * the operation. Arguments may include SQL style arguments, such 1702 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 1703 * the documentation for each individual provider will indicate 1704 * which arguments they support. 1705 * @param cancellationSignal A signal to cancel the operation in progress, 1706 * or {@code null}. 1707 * @return a Cursor or {@code null}. 1708 */ 1709 @Override query(@onNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)1710 public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection, 1711 @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { 1712 queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY; 1713 1714 // if client doesn't supply an SQL sort order argument, attempt to build one from 1715 // QUERY_ARG_SORT* arguments. 1716 String sortClause = queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER); 1717 if (sortClause == null && queryArgs.containsKey(ContentResolver.QUERY_ARG_SORT_COLUMNS)) { 1718 sortClause = ContentResolver.createSqlSortClause(queryArgs); 1719 } 1720 1721 return query( 1722 uri, 1723 projection, 1724 queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SELECTION), 1725 queryArgs.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS), 1726 sortClause, 1727 cancellationSignal); 1728 } 1729 1730 /** 1731 * Implement this to handle requests for the MIME type of the data at the 1732 * given URI. The returned MIME type should start with 1733 * <code>vnd.android.cursor.item</code> for a single record, 1734 * or <code>vnd.android.cursor.dir/</code> for multiple items. 1735 * This method can be called from multiple threads, as described in 1736 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1737 * and Threads</a>. 1738 * 1739 * <p>Note that by default there are no permissions needed for an application to 1740 * access this information; if your content provider requires read and/or 1741 * write permissions, or is not exported, all applications can still call 1742 * this method regardless of their access permissions. </p> 1743 * 1744 * <p>If your mime type reveals details that should be protected, 1745 * then you should protect this method by implementing {@link #getTypeAnonymous}. 1746 * Implementing {@link #getTypeAnonymous} ensures your {@link #getType} can be 1747 * only accessed by caller's having associated readPermission for the URI. </p> 1748 * 1749 * @param uri the URI to query. 1750 * @return a MIME type string, or {@code null} if there is no type. 1751 */ 1752 @Override getType(@onNull Uri uri)1753 public abstract @Nullable String getType(@NonNull Uri uri); 1754 1755 /** 1756 * Implement this to handle requests for MIME type of URIs, that does not need to 1757 * reveal any internal information which should be protected by any permission. 1758 * 1759 * <p>If your mime type reveals details that should be protected, then you should protect those 1760 * by implementing those in {@link #getType}, and in this function, only return types of 1761 * URIs which can be obtained by anyone without any access. 1762 * 1763 * Implementing ths function will make sure {@link #getType} is protected by readPermission. 1764 * This function by default works as the {@link #getType}</p> 1765 * 1766 * @param uri the URI to query. 1767 * @return a MIME type string, or {@code null} if type needs to be protected. 1768 */ getTypeAnonymous(@onNull Uri uri)1769 public @Nullable String getTypeAnonymous(@NonNull Uri uri) { 1770 return getType(uri); 1771 } 1772 1773 /** 1774 * Implement this to support canonicalization of URIs that refer to your 1775 * content provider. A canonical URI is one that can be transported across 1776 * devices, backup/restore, and other contexts, and still be able to refer 1777 * to the same data item. Typically this is implemented by adding query 1778 * params to the URI allowing the content provider to verify that an incoming 1779 * canonical URI references the same data as it was originally intended for and, 1780 * if it doesn't, to find that data (if it exists) in the current environment. 1781 * 1782 * <p>For example, if the content provider holds people and a normal URI in it 1783 * is created with a row index into that people database, the cananical representation 1784 * may have an additional query param at the end which specifies the name of the 1785 * person it is intended for. Later calls into the provider with that URI will look 1786 * up the row of that URI's base index and, if it doesn't match or its entry's 1787 * name doesn't match the name in the query param, perform a query on its database 1788 * to find the correct row to operate on.</p> 1789 * 1790 * <p>If you implement support for canonical URIs, <b>all</b> incoming calls with 1791 * URIs (including this one) must perform this verification and recovery of any 1792 * canonical URIs they receive. In addition, you must also implement 1793 * {@link #uncanonicalize} to strip the canonicalization of any of these URIs.</p> 1794 * 1795 * <p>The default implementation of this method returns null, indicating that 1796 * canonical URIs are not supported.</p> 1797 * 1798 * @param url The Uri to canonicalize. 1799 * 1800 * @return Return the canonical representation of <var>url</var>, or null if 1801 * canonicalization of that Uri is not supported. 1802 */ 1803 @Override canonicalize(@onNull Uri url)1804 public @Nullable Uri canonicalize(@NonNull Uri url) { 1805 return null; 1806 } 1807 1808 /** 1809 * Remove canonicalization from canonical URIs previously returned by 1810 * {@link #canonicalize}. For example, if your implementation is to add 1811 * a query param to canonicalize a URI, this method can simply trip any 1812 * query params on the URI. The default implementation always returns the 1813 * same <var>url</var> that was passed in. 1814 * 1815 * @param url The Uri to remove any canonicalization from. 1816 * 1817 * @return Return the non-canonical representation of <var>url</var>, return 1818 * the <var>url</var> as-is if there is nothing to do, or return null if 1819 * the data identified by the canonical representation can not be found in 1820 * the current environment. 1821 */ 1822 @Override uncanonicalize(@onNull Uri url)1823 public @Nullable Uri uncanonicalize(@NonNull Uri url) { 1824 return url; 1825 } 1826 1827 /** 1828 * Implement this to support refresh of content identified by {@code uri}. 1829 * By default, this method returns false; providers who wish to implement 1830 * this should return true to signal the client that the provider has tried 1831 * refreshing with its own implementation. 1832 * <p> 1833 * This allows clients to request an explicit refresh of content identified 1834 * by {@code uri}. 1835 * <p> 1836 * Client code should only invoke this method when there is a strong 1837 * indication (such as a user initiated pull to refresh gesture) that the 1838 * content is stale. 1839 * <p> 1840 * Remember to send 1841 * {@link ContentResolver#notifyChange(Uri, android.database.ContentObserver)} 1842 * notifications when content changes. 1843 * 1844 * @param uri The Uri identifying the data to refresh. 1845 * @param extras Additional options from the client. The definitions of 1846 * these are specific to the content provider being called. 1847 * @param cancellationSignal A signal to cancel the operation in progress, 1848 * or {@code null} if none. For example, if you called refresh on 1849 * a particular uri, you should call 1850 * {@link CancellationSignal#throwIfCanceled()} to check whether 1851 * the client has canceled the refresh request. 1852 * @return true if the provider actually tried refreshing. 1853 */ 1854 @Override refresh(Uri uri, @Nullable Bundle extras, @Nullable CancellationSignal cancellationSignal)1855 public boolean refresh(Uri uri, @Nullable Bundle extras, 1856 @Nullable CancellationSignal cancellationSignal) { 1857 return false; 1858 } 1859 1860 /** 1861 * Perform a detailed internal check on a {@link Uri} to determine if a UID 1862 * is able to access it with specific mode flags. 1863 * <p> 1864 * This method is typically used when the provider implements more dynamic 1865 * access controls that cannot be expressed with {@code <path-permission>} 1866 * style static rules. 1867 * <p> 1868 * Because validation of these dynamic access controls has significant 1869 * system health impact, this feature is only available to providers that 1870 * are built into the system. 1871 * 1872 * @param uri the {@link Uri} to perform an access check on. 1873 * @param uid the UID to check the permission for. 1874 * @param modeFlags the access flags to use for the access check, such as 1875 * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}. 1876 * @return {@link PackageManager#PERMISSION_GRANTED} if access is allowed, 1877 * otherwise {@link PackageManager#PERMISSION_DENIED}. 1878 * @hide 1879 */ 1880 @Override 1881 @SystemApi checkUriPermission(@onNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)1882 public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) { 1883 return PackageManager.PERMISSION_DENIED; 1884 } 1885 1886 /** 1887 * @hide 1888 * Implementation when a caller has performed an insert on the content 1889 * provider, but that call has been rejected for the operation given 1890 * to {@link #setAppOps(int, int)}. The default implementation simply 1891 * returns a URI that is the base URI with a 0 path element appended. 1892 */ rejectInsert(Uri uri, ContentValues values)1893 public Uri rejectInsert(Uri uri, ContentValues values) { 1894 // If not allowed, we need to return some reasonable URI. Maybe the 1895 // content provider should be responsible for this, but for now we 1896 // will just return the base URI with a '0' tagged on to it. 1897 // You shouldn't be able to read if you can't write, anyway, so it 1898 // shouldn't matter much what is returned. 1899 return uri.buildUpon().appendPath("0").build(); 1900 } 1901 1902 /** 1903 * Implement this to handle requests to insert a new row. As a courtesy, 1904 * call 1905 * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) 1906 * notifyChange()} after inserting. This method can be called from multiple 1907 * threads, as described in <a href=" 1908 * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1909 * and Threads</a>. 1910 * 1911 * @param uri The content:// URI of the insertion request. 1912 * @param values A set of column_name/value pairs to add to the database. 1913 * @return The URI for the newly inserted item. 1914 */ insert(@onNull Uri uri, @Nullable ContentValues values)1915 public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values); 1916 1917 /** 1918 * Implement this to handle requests to insert a new row. As a courtesy, 1919 * call 1920 * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) 1921 * notifyChange()} after inserting. This method can be called from multiple 1922 * threads, as described in <a href=" 1923 * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1924 * and Threads</a>. 1925 * 1926 * @param uri The content:// URI of the insertion request. 1927 * @param values A set of column_name/value pairs to add to the database. 1928 * @param extras A Bundle containing additional information necessary for 1929 * the operation. Arguments may include SQL style arguments, such 1930 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 1931 * the documentation for each individual provider will indicate 1932 * which arguments they support. 1933 * @return The URI for the newly inserted item. 1934 * @throws IllegalArgumentException if the provider doesn't support one of 1935 * the requested Bundle arguments. 1936 */ 1937 @Override insert(@onNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)1938 public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values, 1939 @Nullable Bundle extras) { 1940 return insert(uri, values); 1941 } 1942 1943 /** 1944 * Override this to handle requests to insert a set of new rows, or the 1945 * default implementation will iterate over the values and call 1946 * {@link #insert} on each of them. 1947 * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} 1948 * after inserting. 1949 * This method can be called from multiple threads, as described in 1950 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1951 * and Threads</a>. 1952 * 1953 * @param uri The content:// URI of the insertion request. 1954 * @param values An array of sets of column_name/value pairs to add to the database. 1955 * This must not be {@code null}. 1956 * @return The number of values that were inserted. 1957 */ 1958 @Override bulkInsert(@onNull Uri uri, @NonNull ContentValues[] values)1959 public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { 1960 int numValues = values.length; 1961 for (int i = 0; i < numValues; i++) { 1962 insert(uri, values[i]); 1963 } 1964 return numValues; 1965 } 1966 1967 /** 1968 * Implement this to handle requests to delete one or more rows. The 1969 * implementation should apply the selection clause when performing 1970 * deletion, allowing the operation to affect multiple rows in a directory. 1971 * As a courtesy, call 1972 * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) 1973 * notifyChange()} after deleting. This method can be called from multiple 1974 * threads, as described in <a href=" 1975 * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 1976 * and Threads</a>. 1977 * <p> 1978 * The implementation is responsible for parsing out a row ID at the end of 1979 * the URI, if a specific row is being deleted. That is, the client would 1980 * pass in <code>content://contacts/people/22</code> and the implementation 1981 * is responsible for parsing the record number (22) when creating a SQL 1982 * statement. 1983 * 1984 * @param uri The full URI to query, including a row ID (if a specific 1985 * record is requested). 1986 * @param selection An optional restriction to apply to rows when deleting. 1987 * @return The number of rows affected. 1988 * @throws SQLException 1989 */ delete(@onNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs)1990 public abstract int delete(@NonNull Uri uri, @Nullable String selection, 1991 @Nullable String[] selectionArgs); 1992 1993 /** 1994 * Implement this to handle requests to delete one or more rows. The 1995 * implementation should apply the selection clause when performing 1996 * deletion, allowing the operation to affect multiple rows in a directory. 1997 * As a courtesy, call 1998 * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) 1999 * notifyChange()} after deleting. This method can be called from multiple 2000 * threads, as described in <a href=" 2001 * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2002 * and Threads</a>. 2003 * <p> 2004 * The implementation is responsible for parsing out a row ID at the end of 2005 * the URI, if a specific row is being deleted. That is, the client would 2006 * pass in <code>content://contacts/people/22</code> and the implementation 2007 * is responsible for parsing the record number (22) when creating a SQL 2008 * statement. 2009 * 2010 * @param uri The full URI to query, including a row ID (if a specific 2011 * record is requested). 2012 * @param extras A Bundle containing additional information necessary for 2013 * the operation. Arguments may include SQL style arguments, such 2014 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 2015 * the documentation for each individual provider will indicate 2016 * which arguments they support. 2017 * @throws IllegalArgumentException if the provider doesn't support one of 2018 * the requested Bundle arguments. 2019 * @throws SQLException 2020 */ 2021 @Override delete(@onNull Uri uri, @Nullable Bundle extras)2022 public int delete(@NonNull Uri uri, @Nullable Bundle extras) { 2023 extras = (extras != null) ? extras : Bundle.EMPTY; 2024 return delete(uri, 2025 extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION), 2026 extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS)); 2027 } 2028 2029 /** 2030 * Implement this to handle requests to update one or more rows. The 2031 * implementation should update all rows matching the selection to set the 2032 * columns according to the provided values map. As a courtesy, call 2033 * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) 2034 * notifyChange()} after updating. This method can be called from multiple 2035 * threads, as described in <a href=" 2036 * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2037 * and Threads</a>. 2038 * 2039 * @param uri The URI to query. This can potentially have a record ID if 2040 * this is an update request for a specific record. 2041 * @param values A set of column_name/value pairs to update in the database. 2042 * @param selection An optional filter to match rows to update. 2043 * @return the number of rows affected. 2044 */ update(@onNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs)2045 public abstract int update(@NonNull Uri uri, @Nullable ContentValues values, 2046 @Nullable String selection, @Nullable String[] selectionArgs); 2047 2048 /** 2049 * Implement this to handle requests to update one or more rows. The 2050 * implementation should update all rows matching the selection to set the 2051 * columns according to the provided values map. As a courtesy, call 2052 * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) 2053 * notifyChange()} after updating. This method can be called from multiple 2054 * threads, as described in <a href=" 2055 * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2056 * and Threads</a>. 2057 * 2058 * @param uri The URI to query. This can potentially have a record ID if 2059 * this is an update request for a specific record. 2060 * @param values A set of column_name/value pairs to update in the database. 2061 * @param extras A Bundle containing additional information necessary for 2062 * the operation. Arguments may include SQL style arguments, such 2063 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 2064 * the documentation for each individual provider will indicate 2065 * which arguments they support. 2066 * @return the number of rows affected. 2067 * @throws IllegalArgumentException if the provider doesn't support one of 2068 * the requested Bundle arguments. 2069 */ 2070 @Override update(@onNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)2071 public int update(@NonNull Uri uri, @Nullable ContentValues values, 2072 @Nullable Bundle extras) { 2073 extras = (extras != null) ? extras : Bundle.EMPTY; 2074 return update(uri, values, 2075 extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION), 2076 extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS)); 2077 } 2078 2079 /** 2080 * Override this to handle requests to open a file blob. 2081 * The default implementation always throws {@link FileNotFoundException}. 2082 * This method can be called from multiple threads, as described in 2083 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2084 * and Threads</a>. 2085 * 2086 * <p>This method returns a ParcelFileDescriptor, which is returned directly 2087 * to the caller. This way large data (such as images and documents) can be 2088 * returned without copying the content. 2089 * 2090 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is 2091 * their responsibility to close it when done. That is, the implementation 2092 * of this method should create a new ParcelFileDescriptor for each call. 2093 * <p> 2094 * If opened with the exclusive "r" or "w" modes, the returned 2095 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming 2096 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that 2097 * supports seeking. 2098 * <p> 2099 * If you need to detect when the returned ParcelFileDescriptor has been 2100 * closed, or if the remote process has crashed or encountered some other 2101 * error, you can use {@link ParcelFileDescriptor#open(File, int, 2102 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)}, 2103 * {@link ParcelFileDescriptor#createReliablePipe()}, or 2104 * {@link ParcelFileDescriptor#createReliableSocketPair()}. 2105 * <p> 2106 * If you need to return a large file that isn't backed by a real file on 2107 * disk, such as a file on a network share or cloud storage service, 2108 * consider using 2109 * {@link StorageManager#openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback, android.os.Handler)} 2110 * which will let you to stream the content on-demand. 2111 * 2112 * <p class="note">For use in Intents, you will want to implement {@link #getType} 2113 * to return the appropriate MIME type for the data returned here with 2114 * the same URI. This will allow intent resolution to automatically determine the data MIME 2115 * type and select the appropriate matching targets as part of its operation.</p> 2116 * 2117 * <p class="note">For better interoperability with other applications, it is recommended 2118 * that for any URIs that can be opened, you also support queries on them 2119 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 2120 * You may also want to support other common columns if you have additional meta-data 2121 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 2122 * in {@link android.provider.MediaStore.MediaColumns}.</p> 2123 * 2124 * @param uri The URI whose file is to be opened. 2125 * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" 2126 * or "rwt". Please note the exact implementation of these may differ for each 2127 * Provider implementation - for example, "w" may or may not truncate. 2128 * 2129 * @return Returns a new ParcelFileDescriptor which you can use to access 2130 * the file. 2131 * 2132 * @throws FileNotFoundException Throws FileNotFoundException if there is 2133 * no file associated with the given URI or the mode is invalid. 2134 * @throws SecurityException Throws SecurityException if the caller does 2135 * not have permission to access the file. 2136 * 2137 * @see #openAssetFile(Uri, String) 2138 * @see #openFileHelper(Uri, String) 2139 * @see #getType(android.net.Uri) 2140 * @see ParcelFileDescriptor#parseMode(String) 2141 */ openFile(@onNull Uri uri, @NonNull String mode)2142 public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) 2143 throws FileNotFoundException { 2144 throw new FileNotFoundException("No files supported by provider at " 2145 + uri); 2146 } 2147 2148 /** 2149 * Override this to handle requests to open a file blob. 2150 * The default implementation always throws {@link FileNotFoundException}. 2151 * This method can be called from multiple threads, as described in 2152 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2153 * and Threads</a>. 2154 * 2155 * <p>This method returns a ParcelFileDescriptor, which is returned directly 2156 * to the caller. This way large data (such as images and documents) can be 2157 * returned without copying the content. 2158 * 2159 * <p>The returned ParcelFileDescriptor is owned by the caller, so it is 2160 * their responsibility to close it when done. That is, the implementation 2161 * of this method should create a new ParcelFileDescriptor for each call. 2162 * <p> 2163 * If opened with the exclusive "r" or "w" modes, the returned 2164 * ParcelFileDescriptor can be a pipe or socket pair to enable streaming 2165 * of data. Opening with the "rw" or "rwt" modes implies a file on disk that 2166 * supports seeking. 2167 * <p> 2168 * If you need to detect when the returned ParcelFileDescriptor has been 2169 * closed, or if the remote process has crashed or encountered some other 2170 * error, you can use {@link ParcelFileDescriptor#open(File, int, 2171 * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)}, 2172 * {@link ParcelFileDescriptor#createReliablePipe()}, or 2173 * {@link ParcelFileDescriptor#createReliableSocketPair()}. 2174 * 2175 * <p class="note">For use in Intents, you will want to implement {@link #getType} 2176 * to return the appropriate MIME type for the data returned here with 2177 * the same URI. This will allow intent resolution to automatically determine the data MIME 2178 * type and select the appropriate matching targets as part of its operation.</p> 2179 * 2180 * <p class="note">For better interoperability with other applications, it is recommended 2181 * that for any URIs that can be opened, you also support queries on them 2182 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 2183 * You may also want to support other common columns if you have additional meta-data 2184 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 2185 * in {@link android.provider.MediaStore.MediaColumns}.</p> 2186 * 2187 * @param uri The URI whose file is to be opened. 2188 * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" 2189 * or "rwt". Please note the exact implementation of these may differ for each 2190 * Provider implementation - for example, "w" may or may not truncate. 2191 * @param signal A signal to cancel the operation in progress, or 2192 * {@code null} if none. For example, if you are downloading a 2193 * file from the network to service a "rw" mode request, you 2194 * should periodically call 2195 * {@link CancellationSignal#throwIfCanceled()} to check whether 2196 * the client has canceled the request and abort the download. 2197 * 2198 * @return Returns a new ParcelFileDescriptor which you can use to access 2199 * the file. 2200 * 2201 * @throws FileNotFoundException Throws FileNotFoundException if there is 2202 * no file associated with the given URI or the mode is invalid. 2203 * @throws SecurityException Throws SecurityException if the caller does 2204 * not have permission to access the file. 2205 * 2206 * @see #openAssetFile(Uri, String) 2207 * @see #openFileHelper(Uri, String) 2208 * @see #getType(android.net.Uri) 2209 * @see ParcelFileDescriptor#parseMode(String) 2210 */ 2211 @Override openFile(@onNull Uri uri, @NonNull String mode, @Nullable CancellationSignal signal)2212 public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode, 2213 @Nullable CancellationSignal signal) throws FileNotFoundException { 2214 return openFile(uri, mode); 2215 } 2216 2217 /** 2218 * This is like {@link #openFile}, but can be implemented by providers 2219 * that need to be able to return sub-sections of files, often assets 2220 * inside of their .apk. 2221 * This method can be called from multiple threads, as described in 2222 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2223 * and Threads</a>. 2224 * 2225 * <p>If you implement this, your clients must be able to deal with such 2226 * file slices, either directly with 2227 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 2228 * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 2229 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 2230 * methods. 2231 * <p> 2232 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 2233 * streaming of data. 2234 * 2235 * <p class="note">If you are implementing this to return a full file, you 2236 * should create the AssetFileDescriptor with 2237 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 2238 * applications that cannot handle sub-sections of files.</p> 2239 * 2240 * <p class="note">For use in Intents, you will want to implement {@link #getType} 2241 * to return the appropriate MIME type for the data returned here with 2242 * the same URI. This will allow intent resolution to automatically determine the data MIME 2243 * type and select the appropriate matching targets as part of its operation.</p> 2244 * 2245 * <p class="note">For better interoperability with other applications, it is recommended 2246 * that for any URIs that can be opened, you also support queries on them 2247 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> 2248 * 2249 * @param uri The URI whose file is to be opened. 2250 * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" 2251 * or "rwt". Please note the exact implementation of these may differ for each 2252 * Provider implementation - for example, "w" may or may not truncate. 2253 * 2254 * @return Returns a new AssetFileDescriptor which you can use to access 2255 * the file. 2256 * 2257 * @throws FileNotFoundException Throws FileNotFoundException if there is 2258 * no file associated with the given URI or the mode is invalid. 2259 * @throws SecurityException Throws SecurityException if the caller does 2260 * not have permission to access the file. 2261 * 2262 * @see #openFile(Uri, String) 2263 * @see #openFileHelper(Uri, String) 2264 * @see #getType(android.net.Uri) 2265 */ openAssetFile(@onNull Uri uri, @NonNull String mode)2266 public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode) 2267 throws FileNotFoundException { 2268 ParcelFileDescriptor fd = openFile(uri, mode); 2269 return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null; 2270 } 2271 2272 /** 2273 * This is like {@link #openFile}, but can be implemented by providers 2274 * that need to be able to return sub-sections of files, often assets 2275 * inside of their .apk. 2276 * This method can be called from multiple threads, as described in 2277 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2278 * and Threads</a>. 2279 * 2280 * <p>If you implement this, your clients must be able to deal with such 2281 * file slices, either directly with 2282 * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level 2283 * {@link ContentResolver#openInputStream ContentResolver.openInputStream} 2284 * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} 2285 * methods. 2286 * <p> 2287 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 2288 * streaming of data. 2289 * 2290 * <p class="note">If you are implementing this to return a full file, you 2291 * should create the AssetFileDescriptor with 2292 * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with 2293 * applications that cannot handle sub-sections of files.</p> 2294 * 2295 * <p class="note">For use in Intents, you will want to implement {@link #getType} 2296 * to return the appropriate MIME type for the data returned here with 2297 * the same URI. This will allow intent resolution to automatically determine the data MIME 2298 * type and select the appropriate matching targets as part of its operation.</p> 2299 * 2300 * <p class="note">For better interoperability with other applications, it is recommended 2301 * that for any URIs that can be opened, you also support queries on them 2302 * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p> 2303 * 2304 * @param uri The URI whose file is to be opened. 2305 * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" 2306 * or "rwt". Please note the exact implementation of these may differ for each 2307 * Provider implementation - for example, "w" may or may not truncate. 2308 * @param signal A signal to cancel the operation in progress, or 2309 * {@code null} if none. For example, if you are downloading a 2310 * file from the network to service a "rw" mode request, you 2311 * should periodically call 2312 * {@link CancellationSignal#throwIfCanceled()} to check whether 2313 * the client has canceled the request and abort the download. 2314 * 2315 * @return Returns a new AssetFileDescriptor which you can use to access 2316 * the file. 2317 * 2318 * @throws FileNotFoundException Throws FileNotFoundException if there is 2319 * no file associated with the given URI or the mode is invalid. 2320 * @throws SecurityException Throws SecurityException if the caller does 2321 * not have permission to access the file. 2322 * 2323 * @see #openFile(Uri, String) 2324 * @see #openFileHelper(Uri, String) 2325 * @see #getType(android.net.Uri) 2326 */ 2327 @Override openAssetFile(@onNull Uri uri, @NonNull String mode, @Nullable CancellationSignal signal)2328 public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode, 2329 @Nullable CancellationSignal signal) throws FileNotFoundException { 2330 return openAssetFile(uri, mode); 2331 } 2332 2333 /** 2334 * Convenience for subclasses that wish to implement {@link #openFile} 2335 * by looking up a column named "_data" at the given URI. 2336 * 2337 * @param uri The URI to be opened. 2338 * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" 2339 * or "rwt". Please note the exact implementation of these may differ for each 2340 * Provider implementation - for example, "w" may or may not truncate. 2341 * 2342 * @return Returns a new ParcelFileDescriptor that can be used by the 2343 * client to access the file. 2344 */ openFileHelper(@onNull Uri uri, @NonNull String mode)2345 protected final @NonNull ParcelFileDescriptor openFileHelper(@NonNull Uri uri, 2346 @NonNull String mode) throws FileNotFoundException { 2347 Cursor c = query(uri, new String[]{"_data"}, null, null, null); 2348 int count = (c != null) ? c.getCount() : 0; 2349 if (count != 1) { 2350 // If there is not exactly one result, throw an appropriate 2351 // exception. 2352 if (c != null) { 2353 c.close(); 2354 } 2355 if (count == 0) { 2356 throw new FileNotFoundException("No entry for " + uri); 2357 } 2358 throw new FileNotFoundException("Multiple items at " + uri); 2359 } 2360 2361 c.moveToFirst(); 2362 int i = c.getColumnIndex("_data"); 2363 String path = (i >= 0 ? c.getString(i) : null); 2364 c.close(); 2365 if (path == null) { 2366 throw new FileNotFoundException("Column _data not found."); 2367 } 2368 2369 int modeBits = ParcelFileDescriptor.parseMode(mode); 2370 return ParcelFileDescriptor.open(new File(path), modeBits); 2371 } 2372 2373 /** 2374 * Called by a client to determine the types of data streams that this 2375 * content provider supports for the given URI. The default implementation 2376 * returns {@code null}, meaning no types. If your content provider stores data 2377 * of a particular type, return that MIME type if it matches the given 2378 * mimeTypeFilter. If it can perform type conversions, return an array 2379 * of all supported MIME types that match mimeTypeFilter. 2380 * 2381 * @param uri The data in the content provider being queried. 2382 * @param mimeTypeFilter The type of data the client desires. May be 2383 * a pattern, such as */* to retrieve all possible data types. 2384 * @return Returns {@code null} if there are no possible data streams for the 2385 * given mimeTypeFilter. Otherwise returns an array of all available 2386 * concrete MIME types. 2387 * 2388 * @see #getType(Uri) 2389 * @see #openTypedAssetFile(Uri, String, Bundle) 2390 * @see ClipDescription#compareMimeTypes(String, String) 2391 */ 2392 @Override getStreamTypes(@onNull Uri uri, @NonNull String mimeTypeFilter)2393 public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) { 2394 return null; 2395 } 2396 2397 /** 2398 * Called by a client to open a read-only stream containing data of a 2399 * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 2400 * except the file can only be read-only and the content provider may 2401 * perform data conversions to generate data of the desired type. 2402 * 2403 * <p>The default implementation compares the given mimeType against the 2404 * result of {@link #getType(Uri)} and, if they match, simply calls 2405 * {@link #openAssetFile(Uri, String)}. 2406 * 2407 * <p>See {@link ClipData} for examples of the use and implementation 2408 * of this method. 2409 * <p> 2410 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 2411 * streaming of data. 2412 * 2413 * <p class="note">For better interoperability with other applications, it is recommended 2414 * that for any URIs that can be opened, you also support queries on them 2415 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 2416 * You may also want to support other common columns if you have additional meta-data 2417 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 2418 * in {@link android.provider.MediaStore.MediaColumns}.</p> 2419 * 2420 * @param uri The data in the content provider being queried. 2421 * @param mimeTypeFilter The type of data the client desires. May be 2422 * a pattern, such as */*, if the caller does not have specific type 2423 * requirements; in this case the content provider will pick its best 2424 * type matching the pattern. 2425 * @param opts Additional options from the client. The definitions of 2426 * these are specific to the content provider being called. 2427 * 2428 * @return Returns a new AssetFileDescriptor from which the client can 2429 * read data of the desired type. 2430 * 2431 * @throws FileNotFoundException Throws FileNotFoundException if there is 2432 * no file associated with the given URI or the mode is invalid. 2433 * @throws SecurityException Throws SecurityException if the caller does 2434 * not have permission to access the data. 2435 * @throws IllegalArgumentException Throws IllegalArgumentException if the 2436 * content provider does not support the requested MIME type. 2437 * 2438 * @see #getStreamTypes(Uri, String) 2439 * @see #openAssetFile(Uri, String) 2440 * @see ClipDescription#compareMimeTypes(String, String) 2441 */ openTypedAssetFile(@onNull Uri uri, @NonNull String mimeTypeFilter, @Nullable Bundle opts)2442 public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri, 2443 @NonNull String mimeTypeFilter, @Nullable Bundle opts) throws FileNotFoundException { 2444 if ("*/*".equals(mimeTypeFilter)) { 2445 // If they can take anything, the untyped open call is good enough. 2446 return openAssetFile(uri, "r"); 2447 } 2448 String baseType = getType(uri); 2449 if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) { 2450 // Use old untyped open call if this provider has a type for this 2451 // URI and it matches the request. 2452 return openAssetFile(uri, "r"); 2453 } 2454 throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter); 2455 } 2456 2457 2458 /** 2459 * Called by a client to open a read-only stream containing data of a 2460 * particular MIME type. This is like {@link #openAssetFile(Uri, String)}, 2461 * except the file can only be read-only and the content provider may 2462 * perform data conversions to generate data of the desired type. 2463 * 2464 * <p>The default implementation compares the given mimeType against the 2465 * result of {@link #getType(Uri)} and, if they match, simply calls 2466 * {@link #openAssetFile(Uri, String)}. 2467 * 2468 * <p>See {@link ClipData} for examples of the use and implementation 2469 * of this method. 2470 * <p> 2471 * The returned AssetFileDescriptor can be a pipe or socket pair to enable 2472 * streaming of data. 2473 * 2474 * <p class="note">For better interoperability with other applications, it is recommended 2475 * that for any URIs that can be opened, you also support queries on them 2476 * containing at least the columns specified by {@link android.provider.OpenableColumns}. 2477 * You may also want to support other common columns if you have additional meta-data 2478 * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED} 2479 * in {@link android.provider.MediaStore.MediaColumns}.</p> 2480 * 2481 * @param uri The data in the content provider being queried. 2482 * @param mimeTypeFilter The type of data the client desires. May be 2483 * a pattern, such as */*, if the caller does not have specific type 2484 * requirements; in this case the content provider will pick its best 2485 * type matching the pattern. 2486 * @param opts Additional options from the client. The definitions of 2487 * these are specific to the content provider being called. 2488 * @param signal A signal to cancel the operation in progress, or 2489 * {@code null} if none. For example, if you are downloading a 2490 * file from the network to service a "rw" mode request, you 2491 * should periodically call 2492 * {@link CancellationSignal#throwIfCanceled()} to check whether 2493 * the client has canceled the request and abort the download. 2494 * 2495 * @return Returns a new AssetFileDescriptor from which the client can 2496 * read data of the desired type. 2497 * 2498 * @throws FileNotFoundException Throws FileNotFoundException if there is 2499 * no file associated with the given URI or the mode is invalid. 2500 * @throws SecurityException Throws SecurityException if the caller does 2501 * not have permission to access the data. 2502 * @throws IllegalArgumentException Throws IllegalArgumentException if the 2503 * content provider does not support the requested MIME type. 2504 * 2505 * @see #getStreamTypes(Uri, String) 2506 * @see #openAssetFile(Uri, String) 2507 * @see ClipDescription#compareMimeTypes(String, String) 2508 */ 2509 @Override openTypedAssetFile(@onNull Uri uri, @NonNull String mimeTypeFilter, @Nullable Bundle opts, @Nullable CancellationSignal signal)2510 public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri, 2511 @NonNull String mimeTypeFilter, @Nullable Bundle opts, 2512 @Nullable CancellationSignal signal) throws FileNotFoundException { 2513 return openTypedAssetFile(uri, mimeTypeFilter, opts); 2514 } 2515 2516 /** 2517 * Interface to write a stream of data to a pipe. Use with 2518 * {@link ContentProvider#openPipeHelper}. 2519 */ 2520 public interface PipeDataWriter<T> { 2521 /** 2522 * Called from a background thread to stream data out to a pipe. 2523 * Note that the pipe is blocking, so this thread can block on 2524 * writes for an arbitrary amount of time if the client is slow 2525 * at reading. 2526 * 2527 * @param output The pipe where data should be written. This will be 2528 * closed for you upon returning from this function. 2529 * @param uri The URI whose data is to be written. 2530 * @param mimeType The desired type of data to be written. 2531 * @param opts Options supplied by caller. 2532 * @param args Your own custom arguments. 2533 */ writeDataToPipe(@onNull ParcelFileDescriptor output, @NonNull Uri uri, @NonNull String mimeType, @Nullable Bundle opts, @Nullable T args)2534 public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri, 2535 @NonNull String mimeType, @Nullable Bundle opts, @Nullable T args); 2536 } 2537 2538 /** 2539 * A helper function for implementing {@link #openTypedAssetFile}, for 2540 * creating a data pipe and background thread allowing you to stream 2541 * generated data back to the client. This function returns a new 2542 * ParcelFileDescriptor that should be returned to the caller (the caller 2543 * is responsible for closing it). 2544 * 2545 * @param uri The URI whose data is to be written. 2546 * @param mimeType The desired type of data to be written. 2547 * @param opts Options supplied by caller. 2548 * @param args Your own custom arguments. 2549 * @param func Interface implementing the function that will actually 2550 * stream the data. 2551 * @return Returns a new ParcelFileDescriptor holding the read side of 2552 * the pipe. This should be returned to the caller for reading; the caller 2553 * is responsible for closing it when done. 2554 */ openPipeHelper(final @NonNull Uri uri, final @NonNull String mimeType, final @Nullable Bundle opts, final @Nullable T args, final @NonNull PipeDataWriter<T> func)2555 public @NonNull <T> ParcelFileDescriptor openPipeHelper(final @NonNull Uri uri, 2556 final @NonNull String mimeType, final @Nullable Bundle opts, final @Nullable T args, 2557 final @NonNull PipeDataWriter<T> func) throws FileNotFoundException { 2558 try { 2559 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 2560 2561 AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { 2562 @Override 2563 protected Object doInBackground(Object... params) { 2564 func.writeDataToPipe(fds[1], uri, mimeType, opts, args); 2565 try { 2566 fds[1].close(); 2567 } catch (IOException e) { 2568 Log.w(TAG, "Failure closing pipe", e); 2569 } 2570 return null; 2571 } 2572 }; 2573 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null); 2574 2575 return fds[0]; 2576 } catch (IOException e) { 2577 throw new FileNotFoundException("failure making pipe"); 2578 } 2579 } 2580 2581 /** 2582 * Returns true if this instance is a temporary content provider. 2583 * @return true if this instance is a temporary content provider 2584 */ isTemporary()2585 protected boolean isTemporary() { 2586 return false; 2587 } 2588 2589 /** 2590 * Returns the Binder object for this provider. 2591 * 2592 * @return the Binder object for this provider 2593 * @hide 2594 */ 2595 @UnsupportedAppUsage getIContentProvider()2596 public IContentProvider getIContentProvider() { 2597 return mTransport; 2598 } 2599 2600 /** 2601 * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use 2602 * when directly instantiating the provider for testing. 2603 * @hide 2604 */ 2605 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) attachInfoForTesting(Context context, ProviderInfo info)2606 public void attachInfoForTesting(Context context, ProviderInfo info) { 2607 attachInfo(context, info, true); 2608 } 2609 2610 /** 2611 * After being instantiated, this is called to tell the content provider 2612 * about itself. 2613 * 2614 * @param context The context this provider is running in 2615 * @param info Registered information about this content provider 2616 */ attachInfo(Context context, ProviderInfo info)2617 public void attachInfo(Context context, ProviderInfo info) { 2618 attachInfo(context, info, false); 2619 } 2620 attachInfo(Context context, ProviderInfo info, boolean testing)2621 private void attachInfo(Context context, ProviderInfo info, boolean testing) { 2622 mNoPerms = testing; 2623 mCallingAttributionSource = new ThreadLocal<>(); 2624 2625 /* 2626 * Only allow it to be set once, so after the content service gives 2627 * this to us clients can't change it. 2628 */ 2629 if (mContext == null) { 2630 mContext = context; 2631 if (context != null && mTransport != null) { 2632 mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService( 2633 Context.APP_OPS_SERVICE); 2634 } 2635 mMyUid = Process.myUid(); 2636 if (info != null) { 2637 setReadPermission(info.readPermission); 2638 setWritePermission(info.writePermission); 2639 setPathPermissions(info.pathPermissions); 2640 mExported = info.exported; 2641 mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0; 2642 mSystemUserOnly = (info.flags & ProviderInfo.FLAG_SYSTEM_USER_ONLY) != 0; 2643 setAuthorities(info.authority); 2644 } 2645 if (Build.IS_DEBUGGABLE) { 2646 setTransportLoggingEnabled(Log.isLoggable(getClass().getSimpleName(), 2647 Log.VERBOSE)); 2648 } 2649 ContentProvider.this.onCreate(); 2650 } 2651 } 2652 2653 /** 2654 * Override this to handle requests to perform a batch of operations, or the 2655 * default implementation will iterate over the operations and call 2656 * {@link ContentProviderOperation#apply} on each of them. 2657 * If all calls to {@link ContentProviderOperation#apply} succeed 2658 * then a {@link ContentProviderResult} array with as many 2659 * elements as there were operations will be returned. If any of the calls 2660 * fail, it is up to the implementation how many of the others take effect. 2661 * This method can be called from multiple threads, as described in 2662 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes 2663 * and Threads</a>. 2664 * 2665 * @param operations the operations to apply 2666 * @return the results of the applications 2667 * @throws OperationApplicationException thrown if any operation fails. 2668 * @see ContentProviderOperation#apply 2669 */ 2670 @Override applyBatch(@onNull String authority, @NonNull ArrayList<ContentProviderOperation> operations)2671 public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority, 2672 @NonNull ArrayList<ContentProviderOperation> operations) 2673 throws OperationApplicationException { 2674 return applyBatch(operations); 2675 } 2676 applyBatch( @onNull ArrayList<ContentProviderOperation> operations)2677 public @NonNull ContentProviderResult[] applyBatch( 2678 @NonNull ArrayList<ContentProviderOperation> operations) 2679 throws OperationApplicationException { 2680 final int numOperations = operations.size(); 2681 final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 2682 for (int i = 0; i < numOperations; i++) { 2683 results[i] = operations.get(i).apply(this, results, i); 2684 } 2685 return results; 2686 } 2687 2688 /** 2689 * Call a provider-defined method. This can be used to implement 2690 * interfaces that are cheaper and/or unnatural for a table-like 2691 * model. 2692 * 2693 * <p class="note"><strong>WARNING:</strong> The framework does no permission checking 2694 * on this entry into the content provider besides the basic ability for the application 2695 * to get access to the provider at all. For example, it has no idea whether the call 2696 * being executed may read or write data in the provider, so can't enforce those 2697 * individual permissions. Any implementation of this method <strong>must</strong> 2698 * do its own permission checks on incoming calls to make sure they are allowed.</p> 2699 * 2700 * @param method method name to call. Opaque to framework, but should not be {@code null}. 2701 * @param arg provider-defined String argument. May be {@code null}. 2702 * @param extras provider-defined Bundle argument. May be {@code null}. 2703 * @return provider-defined return value. May be {@code null}, which is also 2704 * the default for providers which don't implement any call methods. 2705 */ 2706 @Override call(@onNull String authority, @NonNull String method, @Nullable String arg, @Nullable Bundle extras)2707 public @Nullable Bundle call(@NonNull String authority, @NonNull String method, 2708 @Nullable String arg, @Nullable Bundle extras) { 2709 return call(method, arg, extras); 2710 } 2711 call(@onNull String method, @Nullable String arg, @Nullable Bundle extras)2712 public @Nullable Bundle call(@NonNull String method, @Nullable String arg, 2713 @Nullable Bundle extras) { 2714 return null; 2715 } 2716 2717 /** 2718 * Implement this to shut down the ContentProvider instance. You can then 2719 * invoke this method in unit tests. 2720 * 2721 * <p> 2722 * Android normally handles ContentProvider startup and shutdown 2723 * automatically. You do not need to start up or shut down a 2724 * ContentProvider. When you invoke a test method on a ContentProvider, 2725 * however, a ContentProvider instance is started and keeps running after 2726 * the test finishes, even if a succeeding test instantiates another 2727 * ContentProvider. A conflict develops because the two instances are 2728 * usually running against the same underlying data source (for example, an 2729 * sqlite database). 2730 * </p> 2731 * <p> 2732 * Implementing shutDown() avoids this conflict by providing a way to 2733 * terminate the ContentProvider. This method can also prevent memory leaks 2734 * from multiple instantiations of the ContentProvider, and it can ensure 2735 * unit test isolation by allowing you to completely clean up the test 2736 * fixture before moving on to the next test. 2737 * </p> 2738 */ shutdown()2739 public void shutdown() { 2740 Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " + 2741 "connections are gracefully shutdown"); 2742 } 2743 2744 /** 2745 * Print the Provider's state into the given stream. This gets invoked if 2746 * you run "adb shell dumpsys activity provider <provider_component_name>". 2747 * 2748 * @param fd The raw file descriptor that the dump is being sent to. 2749 * @param writer The PrintWriter to which you should dump your state. This will be 2750 * closed for you after you return. 2751 * @param args additional arguments to the dump request. 2752 */ dump(FileDescriptor fd, PrintWriter writer, String[] args)2753 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 2754 writer.println("nothing to dump"); 2755 } 2756 validateIncomingAuthority(String authority)2757 private void validateIncomingAuthority(String authority) throws SecurityException { 2758 if (!matchesOurAuthorities(getAuthorityWithoutUserId(authority))) { 2759 String message = "The authority " + authority + " does not match the one of the " 2760 + "contentProvider: "; 2761 if (mAuthority != null) { 2762 message += mAuthority; 2763 } else { 2764 message += Arrays.toString(mAuthorities); 2765 } 2766 throw new SecurityException(message); 2767 } 2768 } 2769 2770 /** @hide */ 2771 @VisibleForTesting validateIncomingUri(Uri uri)2772 public Uri validateIncomingUri(Uri uri) throws SecurityException { 2773 String auth = uri.getAuthority(); 2774 if (!mSingleUser) { 2775 int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT); 2776 if (deniedAccessSystemUserOnlyProvider(mContext.getUserId(), 2777 mSystemUserOnly)) { 2778 throw new SecurityException("Trying to query a SYSTEM user only content" 2779 + " provider from user:" + mContext.getUserId()); 2780 } 2781 if (userId != UserHandle.USER_CURRENT 2782 // getUserIdFromAuthority can return USER_NULL when can't cast the userId to 2783 // an int, which can cause high volume of binder calls. 2784 && (!android.multiuser.Flags.fixGetUserPropertyCache() 2785 || userId != UserHandle.USER_NULL) 2786 && userId != mContext.getUserId() 2787 // Since userId specified in content uri, the provider userId would be 2788 // determined from it. 2789 && !isContentRedirectionAllowedForUser(userId)) { 2790 throw new SecurityException("trying to query a ContentProvider in user " 2791 + mContext.getUserId() + " with a uri belonging to user " + userId); 2792 } 2793 } 2794 validateIncomingAuthority(auth); 2795 2796 // Normalize the path by removing any empty path segments, which can be 2797 // a source of security issues. 2798 final String encodedPath = uri.getEncodedPath(); 2799 if (encodedPath != null && encodedPath.indexOf("//") != -1) { 2800 final Uri normalized = uri.buildUpon() 2801 .encodedPath(encodedPath.replaceAll("//+", "/")).build(); 2802 Log.w(TAG, "Normalized " + uri + " to " + normalized 2803 + " to avoid possible security issues"); 2804 return normalized; 2805 } else { 2806 return uri; 2807 } 2808 } 2809 2810 /** @hide */ 2811 @android.ravenwood.annotation.RavenwoodKeep maybeGetUriWithoutUserId(Uri uri)2812 private Uri maybeGetUriWithoutUserId(Uri uri) { 2813 if (mSingleUser) { 2814 return uri; 2815 } 2816 return getUriWithoutUserId(uri); 2817 } 2818 2819 /** @hide */ 2820 @android.ravenwood.annotation.RavenwoodKeep getUserIdFromAuthority(String auth, int defaultUserId)2821 public static int getUserIdFromAuthority(String auth, int defaultUserId) { 2822 if (auth == null) return defaultUserId; 2823 int end = auth.lastIndexOf('@'); 2824 if (end == -1) return defaultUserId; 2825 String userIdString = auth.substring(0, end); 2826 try { 2827 return Integer.parseInt(userIdString); 2828 } catch (NumberFormatException e) { 2829 Log.w(TAG, "Error parsing userId.", e); 2830 return UserHandle.USER_NULL; 2831 } 2832 } 2833 2834 /** @hide */ 2835 @android.ravenwood.annotation.RavenwoodKeep getUserIdFromAuthority(String auth)2836 public static int getUserIdFromAuthority(String auth) { 2837 return getUserIdFromAuthority(auth, UserHandle.USER_CURRENT); 2838 } 2839 2840 /** @hide */ 2841 @android.ravenwood.annotation.RavenwoodKeep getUserIdFromUri(Uri uri, int defaultUserId)2842 public static int getUserIdFromUri(Uri uri, int defaultUserId) { 2843 if (uri == null) return defaultUserId; 2844 return getUserIdFromAuthority(uri.getAuthority(), defaultUserId); 2845 } 2846 2847 /** @hide */ 2848 @android.ravenwood.annotation.RavenwoodKeep getUserIdFromUri(Uri uri)2849 public static int getUserIdFromUri(Uri uri) { 2850 return getUserIdFromUri(uri, UserHandle.USER_CURRENT); 2851 } 2852 2853 /** 2854 * Returns the user associated with the given URI. 2855 * 2856 * @hide 2857 */ 2858 @TestApi 2859 @android.ravenwood.annotation.RavenwoodKeep getUserHandleFromUri(@onNull Uri uri)2860 public @NonNull static UserHandle getUserHandleFromUri(@NonNull Uri uri) { 2861 return UserHandle.of(getUserIdFromUri(uri, Process.myUserHandle().getIdentifier())); 2862 } 2863 2864 /** 2865 * Removes userId part from authority string. Expects format: 2866 * userId@some.authority 2867 * If there is no userId in the authority, it symply returns the argument 2868 * @hide 2869 */ 2870 @android.ravenwood.annotation.RavenwoodKeep getAuthorityWithoutUserId(String auth)2871 public static String getAuthorityWithoutUserId(String auth) { 2872 if (auth == null) return null; 2873 int end = auth.lastIndexOf('@'); 2874 return auth.substring(end+1); 2875 } 2876 2877 /** @hide */ 2878 @android.ravenwood.annotation.RavenwoodKeep getUriWithoutUserId(Uri uri)2879 public static Uri getUriWithoutUserId(Uri uri) { 2880 if (uri == null) return null; 2881 Uri.Builder builder = uri.buildUpon(); 2882 builder.authority(getAuthorityWithoutUserId(uri.getAuthority())); 2883 return builder.build(); 2884 } 2885 2886 /** @hide */ 2887 @android.ravenwood.annotation.RavenwoodKeep uriHasUserId(Uri uri)2888 public static boolean uriHasUserId(Uri uri) { 2889 if (uri == null) return false; 2890 return !TextUtils.isEmpty(uri.getUserInfo()); 2891 } 2892 2893 /** 2894 * Returns the given content URI explicitly associated with the given {@link UserHandle}. 2895 * 2896 * @param contentUri The content URI to be associated with a user handle. 2897 * @param userHandle The user handle with which to associate the URI. 2898 * 2899 * @throws IllegalArgumentException if 2900 * <ul> 2901 * <li>the given URI is not content URI (a content URI has {@link Uri#getScheme} equal to 2902 * {@link ContentResolver.SCHEME_CONTENT}) or</li> 2903 * <li>the given URI is already explicitly associated with a {@link UserHandle}, which is 2904 * different than the given one.</li> 2905 * </ul> 2906 * 2907 * @hide 2908 */ 2909 @NonNull 2910 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 2911 @android.ravenwood.annotation.RavenwoodKeep createContentUriForUser( @onNull Uri contentUri, @NonNull UserHandle userHandle)2912 public static Uri createContentUriForUser( 2913 @NonNull Uri contentUri, @NonNull UserHandle userHandle) { 2914 if (!ContentResolver.SCHEME_CONTENT.equals(contentUri.getScheme())) { 2915 throw new IllegalArgumentException(String.format( 2916 "Given URI [%s] is not a content URI: ", contentUri)); 2917 } 2918 2919 int userId = userHandle.getIdentifier(); 2920 if (uriHasUserId(contentUri)) { 2921 if (String.valueOf(userId).equals(contentUri.getUserInfo())) { 2922 return contentUri; 2923 } 2924 throw new IllegalArgumentException(String.format( 2925 "Given URI [%s] already has a user ID, different from given user handle [%s]", 2926 contentUri, 2927 userId)); 2928 } 2929 2930 Uri.Builder builder = contentUri.buildUpon(); 2931 builder.encodedAuthority( 2932 "" + userHandle.getIdentifier() + "@" + contentUri.getEncodedAuthority()); 2933 return builder.build(); 2934 } 2935 2936 /** @hide */ 2937 @UnsupportedAppUsage 2938 @android.ravenwood.annotation.RavenwoodKeep maybeAddUserId(Uri uri, int userId)2939 public static Uri maybeAddUserId(Uri uri, int userId) { 2940 if (uri == null) return null; 2941 if (userId != UserHandle.USER_CURRENT 2942 && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { 2943 if (!uriHasUserId(uri)) { 2944 //We don't add the user Id if there's already one 2945 Uri.Builder builder = uri.buildUpon(); 2946 builder.encodedAuthority("" + userId + "@" + uri.getEncodedAuthority()); 2947 return builder.build(); 2948 } 2949 } 2950 return uri; 2951 } 2952 traceBegin(long traceTag, String methodName, String subInfo)2953 private static void traceBegin(long traceTag, String methodName, String subInfo) { 2954 if (Trace.isTagEnabled(traceTag)) { 2955 Trace.traceBegin(traceTag, methodName + subInfo); 2956 } 2957 } 2958 /** 2959 * Return true if access to content provider is denied because it's a SYSTEM user only 2960 * provider and the calling user is not the SYSTEM user. 2961 * 2962 * @param callingUserId UserId of the caller accessing the content provider. 2963 * @param systemUserOnly true when the content provider is only available for the SYSTEM user. 2964 */ deniedAccessSystemUserOnlyProvider(int callingUserId, boolean systemUserOnly)2965 private static boolean deniedAccessSystemUserOnlyProvider(int callingUserId, 2966 boolean systemUserOnly) { 2967 return Flags.enableSystemUserOnlyForServicesAndProviders() 2968 && (callingUserId != UserHandle.USER_SYSTEM && systemUserOnly); 2969 } 2970 } 2971