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