@@ -97,6 +97,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
9797
9898 private Context mContext = null ;
9999 private int mMyUid ;
100+
101+ // Since most Providers have only one authority, we keep both a String and a String[] to improve
102+ // performance.
103+ private String mAuthority ;
104+ private String [] mAuthorities ;
100105 private String mReadPermission ;
101106 private String mWritePermission ;
102107 private PathPermission [] mPathPermissions ;
@@ -193,7 +198,7 @@ public String getProviderName() {
193198 public Cursor query (String callingPkg , Uri uri , String [] projection ,
194199 String selection , String [] selectionArgs , String sortOrder ,
195200 ICancellationSignal cancellationSignal ) {
196- getAndEnforceUserId (uri );
201+ validateIncomingUri (uri );
197202 uri = getUriWithoutUserId (uri );
198203 if (enforceReadPermission (callingPkg , uri ) != AppOpsManager .MODE_ALLOWED ) {
199204 return rejectQuery (uri , projection , selection , selectionArgs , sortOrder ,
@@ -211,14 +216,15 @@ public Cursor query(String callingPkg, Uri uri, String[] projection,
211216
212217 @ Override
213218 public String getType (Uri uri ) {
214- getAndEnforceUserId (uri );
219+ validateIncomingUri (uri );
215220 uri = getUriWithoutUserId (uri );
216221 return ContentProvider .this .getType (uri );
217222 }
218223
219224 @ Override
220225 public Uri insert (String callingPkg , Uri uri , ContentValues initialValues ) {
221- int userId = getAndEnforceUserId (uri );
226+ validateIncomingUri (uri );
227+ int userId = getUserIdFromUri (uri );
222228 uri = getUriWithoutUserId (uri );
223229 if (enforceWritePermission (callingPkg , uri ) != AppOpsManager .MODE_ALLOWED ) {
224230 return rejectInsert (uri , initialValues );
@@ -233,7 +239,7 @@ public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
233239
234240 @ Override
235241 public int bulkInsert (String callingPkg , Uri uri , ContentValues [] initialValues ) {
236- getAndEnforceUserId (uri );
242+ validateIncomingUri (uri );
237243 uri = getUriWithoutUserId (uri );
238244 if (enforceWritePermission (callingPkg , uri ) != AppOpsManager .MODE_ALLOWED ) {
239245 return 0 ;
@@ -254,20 +260,22 @@ public ContentProviderResult[] applyBatch(String callingPkg,
254260 final int [] userIds = new int [numOperations ];
255261 for (int i = 0 ; i < numOperations ; i ++) {
256262 ContentProviderOperation operation = operations .get (i );
257- userIds [i ] = getAndEnforceUserId (operation .getUri ());
263+ Uri uri = operation .getUri ();
264+ validateIncomingUri (uri );
265+ userIds [i ] = getUserIdFromUri (uri );
258266 if (userIds [i ] != UserHandle .USER_CURRENT ) {
259267 // Removing the user id from the uri.
260268 operation = new ContentProviderOperation (operation , true );
261269 operations .set (i , operation );
262270 }
263271 if (operation .isReadOperation ()) {
264- if (enforceReadPermission (callingPkg , operation . getUri () )
272+ if (enforceReadPermission (callingPkg , uri )
265273 != AppOpsManager .MODE_ALLOWED ) {
266274 throw new OperationApplicationException ("App op not allowed" , 0 );
267275 }
268276 }
269277 if (operation .isWriteOperation ()) {
270- if (enforceWritePermission (callingPkg , operation . getUri () )
278+ if (enforceWritePermission (callingPkg , uri )
271279 != AppOpsManager .MODE_ALLOWED ) {
272280 throw new OperationApplicationException ("App op not allowed" , 0 );
273281 }
@@ -290,7 +298,7 @@ public ContentProviderResult[] applyBatch(String callingPkg,
290298
291299 @ Override
292300 public int delete (String callingPkg , Uri uri , String selection , String [] selectionArgs ) {
293- getAndEnforceUserId (uri );
301+ validateIncomingUri (uri );
294302 uri = getUriWithoutUserId (uri );
295303 if (enforceWritePermission (callingPkg , uri ) != AppOpsManager .MODE_ALLOWED ) {
296304 return 0 ;
@@ -306,7 +314,7 @@ public int delete(String callingPkg, Uri uri, String selection, String[] selecti
306314 @ Override
307315 public int update (String callingPkg , Uri uri , ContentValues values , String selection ,
308316 String [] selectionArgs ) {
309- getAndEnforceUserId (uri );
317+ validateIncomingUri (uri );
310318 uri = getUriWithoutUserId (uri );
311319 if (enforceWritePermission (callingPkg , uri ) != AppOpsManager .MODE_ALLOWED ) {
312320 return 0 ;
@@ -323,7 +331,7 @@ public int update(String callingPkg, Uri uri, ContentValues values, String selec
323331 public ParcelFileDescriptor openFile (
324332 String callingPkg , Uri uri , String mode , ICancellationSignal cancellationSignal )
325333 throws FileNotFoundException {
326- getAndEnforceUserId (uri );
334+ validateIncomingUri (uri );
327335 uri = getUriWithoutUserId (uri );
328336 enforceFilePermission (callingPkg , uri , mode );
329337 final String original = setCallingPackage (callingPkg );
@@ -339,7 +347,7 @@ public ParcelFileDescriptor openFile(
339347 public AssetFileDescriptor openAssetFile (
340348 String callingPkg , Uri uri , String mode , ICancellationSignal cancellationSignal )
341349 throws FileNotFoundException {
342- getAndEnforceUserId (uri );
350+ validateIncomingUri (uri );
343351 uri = getUriWithoutUserId (uri );
344352 enforceFilePermission (callingPkg , uri , mode );
345353 final String original = setCallingPackage (callingPkg );
@@ -363,15 +371,15 @@ public Bundle call(String callingPkg, String method, String arg, Bundle extras)
363371
364372 @ Override
365373 public String [] getStreamTypes (Uri uri , String mimeTypeFilter ) {
366- getAndEnforceUserId (uri );
374+ validateIncomingUri (uri );
367375 uri = getUriWithoutUserId (uri );
368376 return ContentProvider .this .getStreamTypes (uri , mimeTypeFilter );
369377 }
370378
371379 @ Override
372380 public AssetFileDescriptor openTypedAssetFile (String callingPkg , Uri uri , String mimeType ,
373381 Bundle opts , ICancellationSignal cancellationSignal ) throws FileNotFoundException {
374- getAndEnforceUserId (uri );
382+ validateIncomingUri (uri );
375383 uri = getUriWithoutUserId (uri );
376384 enforceFilePermission (callingPkg , uri , "r" );
377385 final String original = setCallingPackage (callingPkg );
@@ -390,7 +398,8 @@ public ICancellationSignal createCancellationSignal() {
390398
391399 @ Override
392400 public Uri canonicalize (String callingPkg , Uri uri ) {
393- int userId = getAndEnforceUserId (uri );
401+ validateIncomingUri (uri );
402+ int userId = getUserIdFromUri (uri );
394403 uri = getUriWithoutUserId (uri );
395404 if (enforceReadPermission (callingPkg , uri ) != AppOpsManager .MODE_ALLOWED ) {
396405 return null ;
@@ -405,7 +414,8 @@ public Uri canonicalize(String callingPkg, Uri uri) {
405414
406415 @ Override
407416 public Uri uncanonicalize (String callingPkg , Uri uri ) {
408- int userId = getAndEnforceUserId (uri );
417+ validateIncomingUri (uri );
418+ int userId = getUserIdFromUri (uri );
409419 uri = getUriWithoutUserId (uri );
410420 if (enforceReadPermission (callingPkg , uri ) != AppOpsManager .MODE_ALLOWED ) {
411421 return null ;
@@ -619,6 +629,36 @@ public final String getCallingPackage() {
619629 return pkg ;
620630 }
621631
632+ /**
633+ * Change the authorities of the ContentProvider.
634+ * This is normally set for you from its manifest information when the provider is first
635+ * created.
636+ * @hide
637+ * @param authorities the semi-colon separated authorities of the ContentProvider.
638+ */
639+ protected final void setAuthorities (String authorities ) {
640+ if (authorities .indexOf (';' ) == -1 ) {
641+ mAuthority = authorities ;
642+ mAuthorities = null ;
643+ } else {
644+ mAuthority = null ;
645+ mAuthorities = authorities .split (";" );
646+ }
647+ }
648+
649+ /** @hide */
650+ protected final boolean matchesOurAuthorities (String authority ) {
651+ if (mAuthority != null ) {
652+ return mAuthority .equals (authority );
653+ }
654+ int length = mAuthorities .length ;
655+ for (int i = 0 ; i < length ; i ++) {
656+ if (mAuthorities [i ].equals (authority )) return true ;
657+ }
658+ return false ;
659+ }
660+
661+
622662 /**
623663 * Change the permission required to read data from the content
624664 * provider. This is normally set for you from its manifest information
@@ -1634,6 +1674,7 @@ private void attachInfo(Context context, ProviderInfo info, boolean testing) {
16341674 setWritePermission (info .writePermission );
16351675 setPathPermissions (info .pathPermissions );
16361676 mExported = info .exported ;
1677+ setAuthorities (info .authority );
16371678 }
16381679 ContentProvider .this .onCreate ();
16391680 }
@@ -1727,14 +1768,25 @@ public void shutdown() {
17271768 public void dump (FileDescriptor fd , PrintWriter writer , String [] args ) {
17281769 writer .println ("nothing to dump" );
17291770 }
1771+
17301772 /** @hide */
1731- private int getAndEnforceUserId (Uri uri ) {
1732- int userId = getUserIdFromUri (uri , UserHandle .USER_CURRENT );
1773+ private void validateIncomingUri (Uri uri ) throws SecurityException {
1774+ String auth = uri .getAuthority ();
1775+ int userId = getUserIdFromAuthority (auth , UserHandle .USER_CURRENT );
17331776 if (userId != UserHandle .USER_CURRENT && userId != mContext .getUserId ()) {
17341777 throw new SecurityException ("trying to query a ContentProvider in user "
1735- + mContext .getUserId () + "with a uri belonging to user " + userId );
1778+ + mContext .getUserId () + " with a uri belonging to user " + userId );
1779+ }
1780+ if (!matchesOurAuthorities (getAuthorityWithoutUserId (auth ))) {
1781+ String message = "The authority of the uri " + uri + " does not match the one of the "
1782+ + "contentProvider: " ;
1783+ if (mAuthority != null ) {
1784+ message += mAuthority ;
1785+ } else {
1786+ message += mAuthorities ;
1787+ }
1788+ throw new SecurityException (message );
17361789 }
1737- return userId ;
17381790 }
17391791
17401792 /** @hide */
0 commit comments