From: Philip P. Moltmann Date: Fri, 27 Sep 2019 15:44:12 +0000 (-0700) Subject: Note with featureId from ContentProvider X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=128b70364ee9ea9bd588908d8002ffa610d3794e;p=android-x86%2Fframeworks-base.git Note with featureId from ContentProvider This takes the Context#getFeatureId from the calling context and pipes it all way through to the noteOp calls done by the content provider. Bug: 136595429 Test: atest CtsAppOpsTestCases (new test added to capture this case) TelecomUnitTests:CallLogManagerTest ContentProviderClientTest TelecomUnitTests:MissedCallNotifierImplTest TelecomUnitTests:BasicCallTests MediaInserterTest PreferencesHelperTest RankingHelperTest PinnedSliceStateTest FrameworksCoreTests:ContentResolverTest Change-Id: I53b1035626229c920b353509a5bece157b52fb51 --- diff --git a/api/current.txt b/api/current.txt index 57bbd7765678..bec1bc8f1762 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9467,6 +9467,7 @@ package android.content { method @NonNull public final android.content.ContentProvider.CallingIdentity clearCallingIdentity(); method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]); method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]); + method @Nullable public final String getCallingFeatureId(); method @Nullable public final String getCallingPackage(); method @Nullable public final android.content.Context getContext(); method @Nullable public final android.content.pm.PathPermission[] getPathPermissions(); diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java index 55dbc17dba5d..7e278e964ab5 100644 --- a/cmds/content/src/com/android/commands/content/Content.java +++ b/cmds/content/src/com/android/commands/content/Content.java @@ -508,7 +508,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { - provider.insert(resolveCallingPackage(), mUri, mContentValues); + provider.insert(resolveCallingPackage(), null, mUri, mContentValues); } } @@ -522,7 +522,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { - provider.delete(resolveCallingPackage(), mUri, mWhere, null); + provider.delete(resolveCallingPackage(), null, mUri, mWhere, null); } } @@ -557,7 +557,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { - Bundle result = provider.call(null, mUri.getAuthority(), mMethod, mArg, mExtras); + Bundle result = provider.call(null, null, mUri.getAuthority(), mMethod, mArg, mExtras); if (result != null) { result.size(); // unpack } @@ -584,7 +584,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { - try (ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null, null)) { + try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "r", null, null)) { FileUtils.copy(fd.getFileDescriptor(), FileDescriptor.out); } } @@ -597,7 +597,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { - try (ParcelFileDescriptor fd = provider.openFile(null, mUri, "w", null, null)) { + try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "w", null, null)) { FileUtils.copy(FileDescriptor.in, fd.getFileDescriptor()); } } @@ -616,7 +616,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { - Cursor cursor = provider.query(resolveCallingPackage(), mUri, mProjection, + Cursor cursor = provider.query(resolveCallingPackage(), null, mUri, mProjection, ContentResolver.createSqlQueryBundle(mWhere, null, mSortOrder), null); if (cursor == null) { System.out.println("No result found."); @@ -679,7 +679,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { - provider.update(resolveCallingPackage(), mUri, mContentValues, mWhere, null); + provider.update(resolveCallingPackage(), null, mUri, mContentValues, mWhere, null); } } diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java index 455e4bbc0b76..b23bf5da5c8d 100644 --- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java +++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java @@ -67,7 +67,7 @@ public class ShellUiAutomatorBridge extends UiAutomatorBridge { throw new IllegalStateException("Could not find provider: " + providerName); } provider = holder.provider; - cursor = provider.query(null, Settings.Secure.CONTENT_URI, + cursor = provider.query(null, null, Settings.Secure.CONTENT_URI, new String[] { Settings.Secure.VALUE }, diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 7de87938c1f6..17f1a07d6e01 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -53,6 +53,7 @@ import android.os.UserHandle; import android.os.storage.StorageManager; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; @@ -136,7 +137,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall private boolean mNoPerms; private boolean mSingleUser; - private ThreadLocal mCallingPackage; + private ThreadLocal> mCallingPackage; private Transport mTransport = new Transport(); @@ -226,11 +227,13 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection, - @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) { + public Cursor query(String callingPkg, @Nullable String featureId, Uri uri, + @Nullable String[] projection, @Nullable Bundle queryArgs, + @Nullable ICancellationSignal cancellationSignal) { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { + if (enforceReadPermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { // The caller has no access to the data, so return an empty cursor with // the columns in the requested order. The caller may ask for an invalid // column and we would not catch that but this is not a problem in practice. @@ -246,7 +249,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall // we have to execute the query as if allowed to get a cursor with the // columns. We then use the column names to return an empty cursor. Cursor cursor; - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { cursor = mInterface.query( uri, projection, queryArgs, @@ -264,7 +268,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall return new MatrixCursor(cursor.getColumnNames(), 0); } Trace.traceBegin(TRACE_TAG_DATABASE, "query"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.query( uri, projection, queryArgs, @@ -293,12 +298,15 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) { + public Uri insert(String callingPkg, @Nullable String featureId, Uri uri, + ContentValues initialValues) { uri = validateIncomingUri(uri); int userId = getUserIdFromUri(uri); uri = maybeGetUriWithoutUserId(uri); - if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { - final String original = setCallingPackage(callingPkg); + if (enforceWritePermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return rejectInsert(uri, initialValues); } finally { @@ -306,7 +314,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } } Trace.traceBegin(TRACE_TAG_DATABASE, "insert"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return maybeAddUserId(mInterface.insert(uri, initialValues), userId); } catch (RemoteException e) { @@ -318,14 +327,17 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) { + public int bulkInsert(String callingPkg, @Nullable String featureId, Uri uri, + ContentValues[] initialValues) { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { + if (enforceWritePermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { return 0; } Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.bulkInsert(uri, initialValues); } catch (RemoteException e) { @@ -337,8 +349,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public ContentProviderResult[] applyBatch(String callingPkg, String authority, - ArrayList operations) + public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId, + String authority, ArrayList operations) throws OperationApplicationException { validateIncomingAuthority(authority); int numOperations = operations.size(); @@ -355,20 +367,21 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall operations.set(i, operation); } if (operation.isReadOperation()) { - if (enforceReadPermission(callingPkg, uri, null) + if (enforceReadPermission(callingPkg, featureId, uri, null) != AppOpsManager.MODE_ALLOWED) { throw new OperationApplicationException("App op not allowed", 0); } } if (operation.isWriteOperation()) { - if (enforceWritePermission(callingPkg, uri, null) + if (enforceWritePermission(callingPkg, featureId, uri, null) != AppOpsManager.MODE_ALLOWED) { throw new OperationApplicationException("App op not allowed", 0); } } } Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { ContentProviderResult[] results = mInterface.applyBatch(authority, operations); @@ -390,14 +403,17 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) { + public int delete(String callingPkg, @Nullable String featureId, Uri uri, String selection, + String[] selectionArgs) { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { + if (enforceWritePermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { return 0; } Trace.traceBegin(TRACE_TAG_DATABASE, "delete"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.delete(uri, selection, selectionArgs); } catch (RemoteException e) { @@ -409,15 +425,17 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public int update(String callingPkg, Uri uri, ContentValues values, String selection, - String[] selectionArgs) { + public int update(String callingPkg, @Nullable String featureId, Uri uri, + ContentValues values, String selection, String[] selectionArgs) { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { + if (enforceWritePermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { return 0; } Trace.traceBegin(TRACE_TAG_DATABASE, "update"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.update(uri, values, selection, selectionArgs); } catch (RemoteException e) { @@ -429,14 +447,15 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public ParcelFileDescriptor openFile( - String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal, - IBinder callerToken) throws FileNotFoundException { + public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, + Uri uri, String mode, ICancellationSignal cancellationSignal, IBinder callerToken) + throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - enforceFilePermission(callingPkg, uri, mode, callerToken); + enforceFilePermission(callingPkg, featureId, uri, mode, callerToken); Trace.traceBegin(TRACE_TAG_DATABASE, "openFile"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.openFile( uri, mode, CancellationSignal.fromTransport(cancellationSignal)); @@ -449,14 +468,15 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public AssetFileDescriptor openAssetFile( - String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal) + public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId, + Uri uri, String mode, ICancellationSignal cancellationSignal) throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - enforceFilePermission(callingPkg, uri, mode, null); + enforceFilePermission(callingPkg, featureId, uri, mode, null); Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.openAssetFile( uri, mode, CancellationSignal.fromTransport(cancellationSignal)); @@ -469,12 +489,13 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public Bundle call(String callingPkg, String authority, String method, @Nullable String arg, - @Nullable Bundle extras) { + public Bundle call(String callingPkg, @Nullable String featureId, String authority, + String method, @Nullable String arg, @Nullable Bundle extras) { validateIncomingAuthority(authority); Bundle.setDefusable(extras, true); Trace.traceBegin(TRACE_TAG_DATABASE, "call"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.call(authority, method, arg, extras); } catch (RemoteException e) { @@ -501,14 +522,16 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType, - Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException { + public AssetFileDescriptor openTypedAssetFile(String callingPkg, + @Nullable String featureId, Uri uri, String mimeType, Bundle opts, + ICancellationSignal cancellationSignal) throws FileNotFoundException { Bundle.setDefusable(opts, true); uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - enforceFilePermission(callingPkg, uri, "r", null); + enforceFilePermission(callingPkg, featureId, uri, "r", null); Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.openTypedAssetFile( uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal)); @@ -526,15 +549,17 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public Uri canonicalize(String callingPkg, Uri uri) { + public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) { uri = validateIncomingUri(uri); int userId = getUserIdFromUri(uri); uri = getUriWithoutUserId(uri); - if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { + if (enforceReadPermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { return null; } Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return maybeAddUserId(mInterface.canonicalize(uri), userId); } catch (RemoteException e) { @@ -546,15 +571,17 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public Uri uncanonicalize(String callingPkg, Uri uri) { + public Uri uncanonicalize(String callingPkg, String featureId, Uri uri) { uri = validateIncomingUri(uri); int userId = getUserIdFromUri(uri); uri = getUriWithoutUserId(uri); - if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { + if (enforceReadPermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { return null; } Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return maybeAddUserId(mInterface.uncanonicalize(uri), userId); } catch (RemoteException e) { @@ -566,15 +593,17 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public boolean refresh(String callingPkg, Uri uri, Bundle args, + public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle args, ICancellationSignal cancellationSignal) throws RemoteException { uri = validateIncomingUri(uri); uri = getUriWithoutUserId(uri); - if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { + if (enforceReadPermission(callingPkg, featureId, uri, null) + != AppOpsManager.MODE_ALLOWED) { return false; } Trace.traceBegin(TRACE_TAG_DATABASE, "refresh"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.refresh(uri, args, CancellationSignal.fromTransport(cancellationSignal)); @@ -585,11 +614,13 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } @Override - public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) { + public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, + int uid, int modeFlags) { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission"); - final String original = setCallingPackage(callingPkg); + final Pair original = setCallingPackage( + new Pair<>(callingPkg, featureId)); try { return mInterface.checkUriPermission(uri, uid, modeFlags); } catch (RemoteException e) { @@ -600,44 +631,47 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } } - private void enforceFilePermission(String callingPkg, Uri uri, String mode, - IBinder callerToken) throws FileNotFoundException, SecurityException { + private void enforceFilePermission(String callingPkg, @Nullable String featureId, Uri uri, + String mode, IBinder callerToken) throws FileNotFoundException, SecurityException { if (mode != null && mode.indexOf('w') != -1) { - if (enforceWritePermission(callingPkg, uri, callerToken) + if (enforceWritePermission(callingPkg, featureId, uri, callerToken) != AppOpsManager.MODE_ALLOWED) { throw new FileNotFoundException("App op not allowed"); } } else { - if (enforceReadPermission(callingPkg, uri, callerToken) + if (enforceReadPermission(callingPkg, featureId, uri, callerToken) != AppOpsManager.MODE_ALLOWED) { throw new FileNotFoundException("App op not allowed"); } } } - private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken) + private int enforceReadPermission(String callingPkg, @Nullable String featureId, Uri uri, + IBinder callerToken) throws SecurityException { - final int mode = enforceReadPermissionInner(uri, callingPkg, callerToken); + final int mode = enforceReadPermissionInner(uri, callingPkg, featureId, callerToken); if (mode != MODE_ALLOWED) { return mode; } - return noteProxyOp(callingPkg, mReadOp); + return noteProxyOp(callingPkg, featureId, mReadOp); } - private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken) + private int enforceWritePermission(String callingPkg, String featureId, Uri uri, + IBinder callerToken) throws SecurityException { - final int mode = enforceWritePermissionInner(uri, callingPkg, callerToken); + final int mode = enforceWritePermissionInner(uri, callingPkg, featureId, callerToken); if (mode != MODE_ALLOWED) { return mode; } - return noteProxyOp(callingPkg, mWriteOp); + return noteProxyOp(callingPkg, featureId, mWriteOp); } - private int noteProxyOp(String callingPkg, int op) { + private int noteProxyOp(String callingPkg, String featureId, int op) { if (op != AppOpsManager.OP_NONE) { - int mode = mAppOpsManager.noteProxyOp(op, callingPkg); + int mode = mAppOpsManager.noteProxyOp(op, callingPkg, Binder.getCallingUid(), + featureId, null); return mode == MODE_DEFAULT ? MODE_IGNORED : mode; } @@ -659,18 +693,19 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * associated with that permission. */ private int checkPermissionAndAppOp(String permission, String callingPkg, - IBinder callerToken) { + @Nullable String featureId, IBinder callerToken) { if (getContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid(), callerToken) != PERMISSION_GRANTED) { return MODE_ERRORED; } - return mTransport.noteProxyOp(callingPkg, AppOpsManager.permissionToOpCode(permission)); + return mTransport.noteProxyOp(callingPkg, featureId, + AppOpsManager.permissionToOpCode(permission)); } /** {@hide} */ - protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) - throws SecurityException { + protected int enforceReadPermissionInner(Uri uri, String callingPkg, + @Nullable String featureId, IBinder callerToken) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); @@ -684,7 +719,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall if (mExported && checkUser(pid, uid, context)) { final String componentPerm = getReadPermission(); if (componentPerm != null) { - final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken); + final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, featureId, + callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { @@ -703,7 +739,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall for (PathPermission pp : pps) { final String pathPerm = pp.getReadPermission(); if (pathPerm != null && pp.match(path)) { - final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken); + final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, featureId, + callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { @@ -751,8 +788,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } /** {@hide} */ - protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) - throws SecurityException { + protected int enforceWritePermissionInner(Uri uri, String callingPkg, + @Nullable String featureId, IBinder callerToken) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); @@ -766,7 +803,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall if (mExported && checkUser(pid, uid, context)) { final String componentPerm = getWritePermission(); if (componentPerm != null) { - final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken); + final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, featureId, + callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { @@ -785,7 +823,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall for (PathPermission pp : pps) { final String pathPerm = pp.getWritePermission(); if (pathPerm != null && pp.match(path)) { - final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken); + final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, featureId, + callerToken); if (mode == MODE_ALLOWED) { return MODE_ALLOWED; } else { @@ -851,11 +890,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } /** - * Set the calling package, returning the current value (or {@code null}) + * Set the calling package/feature, returning the current value (or {@code null}) * which can be used later to restore the previous state. */ - private String setCallingPackage(String callingPackage) { - final String original = mCallingPackage.get(); + private Pair setCallingPackage(Pair callingPackage) { + final Pair original = mCallingPackage.get(); mCallingPackage.set(callingPackage); onCallingPackageChanged(); return original; @@ -876,16 +915,42 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall * calling UID. */ public final @Nullable String getCallingPackage() { - final String pkg = mCallingPackage.get(); + final Pair pkg = mCallingPackage.get(); if (pkg != null) { - mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg); + mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg.first); + return pkg.first; } - return pkg; + + return null; + } + + /** + * Return the feature in the package of the caller that initiated the request being + * processed on the current thread. Returns {@code null} if not currently processing + * a request of the request is for the default feature. + *

+ * This will always return {@code null} when processing + * {@link #getType(Uri)} or {@link #getStreamTypes(Uri, String)} requests. + * + * @see #getCallingPackage + */ + public final @Nullable String getCallingFeatureId() { + final Pair pkg = mCallingPackage.get(); + if (pkg != null) { + return pkg.second; + } + + return null; } /** {@hide} */ public final @Nullable String getCallingPackageUnchecked() { - return mCallingPackage.get(); + final Pair pkg = mCallingPackage.get(); + if (pkg != null) { + return pkg.first; + } + + return null; } /** {@hide} */ @@ -899,10 +964,10 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall /** {@hide} */ public final long binderToken; /** {@hide} */ - public final String callingPackage; + public final Pair callingPackage; /** {@hide} */ - public CallingIdentity(long binderToken, String callingPackage) { + public CallingIdentity(long binderToken, Pair callingPackage) { this.binderToken = binderToken; this.callingPackage = callingPackage; } diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java index 8a4330ec0ede..d2632e78c00c 100644 --- a/core/java/android/content/ContentProviderClient.java +++ b/core/java/android/content/ContentProviderClient.java @@ -80,6 +80,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { private final IContentProvider mContentProvider; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final String mPackageName; + private final @Nullable String mFeatureId; private final String mAuthority; private final boolean mStable; @@ -103,6 +104,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { mContentResolver = contentResolver; mContentProvider = contentProvider; mPackageName = contentResolver.mPackageName; + mFeatureId = contentResolver.mFeatureId; mAuthority = authority; mStable = stable; @@ -193,7 +195,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { cancellationSignal.setRemote(remoteCancellationSignal); } final Cursor cursor = mContentProvider.query( - mPackageName, uri, projection, queryArgs, remoteCancellationSignal); + mPackageName, mFeatureId, uri, projection, queryArgs, remoteCancellationSignal); if (cursor == null) { return null; } @@ -253,7 +255,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.canonicalize(mPackageName, url); + return mContentProvider.canonicalize(mPackageName, mFeatureId, url); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -271,7 +273,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.uncanonicalize(mPackageName, url); + return mContentProvider.uncanonicalize(mPackageName, mFeatureId, url); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -296,7 +298,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { remoteCancellationSignal = mContentProvider.createCancellationSignal(); cancellationSignal.setRemote(remoteCancellationSignal); } - return mContentProvider.refresh(mPackageName, url, args, remoteCancellationSignal); + return mContentProvider.refresh(mPackageName, mFeatureId, url, args, + remoteCancellationSignal); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -315,7 +318,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.checkUriPermission(mPackageName, uri, uid, modeFlags); + return mContentProvider.checkUriPermission(mPackageName, mFeatureId, uri, uid, + modeFlags); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -334,7 +338,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.insert(mPackageName, url, initialValues); + return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -354,7 +358,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.bulkInsert(mPackageName, url, initialValues); + return mContentProvider.bulkInsert(mPackageName, mFeatureId, url, initialValues); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -373,7 +377,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.delete(mPackageName, url, selection, selectionArgs); + return mContentProvider.delete(mPackageName, mFeatureId, url, selection, + selectionArgs); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -392,7 +397,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.update(mPackageName, url, values, selection, selectionArgs); + return mContentProvider.update(mPackageName, mFeatureId, url, values, selection, + selectionArgs); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -436,7 +442,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { remoteSignal = mContentProvider.createCancellationSignal(); signal.setRemote(remoteSignal); } - return mContentProvider.openFile(mPackageName, url, mode, remoteSignal, null); + return mContentProvider.openFile(mPackageName, mFeatureId, url, mode, remoteSignal, + null); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -480,7 +487,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { remoteSignal = mContentProvider.createCancellationSignal(); signal.setRemote(remoteSignal); } - return mContentProvider.openAssetFile(mPackageName, url, mode, remoteSignal); + return mContentProvider.openAssetFile(mPackageName, mFeatureId, url, mode, + remoteSignal); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -521,7 +529,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { signal.setRemote(remoteSignal); } return mContentProvider.openTypedAssetFile( - mPackageName, uri, mimeTypeFilter, opts, remoteSignal); + mPackageName, mFeatureId, uri, mimeTypeFilter, opts, remoteSignal); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -548,7 +556,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.applyBatch(mPackageName, authority, operations); + return mContentProvider.applyBatch(mPackageName, mFeatureId, authority, operations); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -574,7 +582,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { beforeRemote(); try { - return mContentProvider.call(mPackageName, authority, method, arg, extras); + return mContentProvider.call(mPackageName, mFeatureId, authority, method, arg, extras); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index cd735d4b10a3..f082690e2ceb 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -83,6 +83,7 @@ abstract public class ContentProviderNative extends Binder implements IContentPr data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String callingFeatureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); // String[] projection @@ -101,7 +102,8 @@ abstract public class ContentProviderNative extends Binder implements IContentPr ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface( data.readStrongBinder()); - Cursor cursor = query(callingPkg, url, projection, queryArgs, cancellationSignal); + Cursor cursor = query(callingPkg, callingFeatureId, url, projection, queryArgs, + cancellationSignal); if (cursor != null) { CursorToBulkCursorAdaptor adaptor = null; @@ -148,10 +150,11 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); ContentValues values = ContentValues.CREATOR.createFromParcel(data); - Uri out = insert(callingPkg, url, values); + Uri out = insert(callingPkg, featureId, url, values); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; @@ -161,10 +164,11 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); ContentValues[] values = data.createTypedArray(ContentValues.CREATOR); - int count = bulkInsert(callingPkg, url, values); + int count = bulkInsert(callingPkg, featureId, url, values); reply.writeNoException(); reply.writeInt(count); return true; @@ -174,6 +178,7 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); String authority = data.readString(); final int numOperations = data.readInt(); final ArrayList operations = @@ -181,8 +186,8 @@ abstract public class ContentProviderNative extends Binder implements IContentPr for (int i = 0; i < numOperations; i++) { operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data)); } - final ContentProviderResult[] results = applyBatch(callingPkg, authority, - operations); + final ContentProviderResult[] results = applyBatch(callingPkg, featureId, + authority, operations); reply.writeNoException(); reply.writeTypedArray(results, 0); return true; @@ -192,11 +197,12 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String selection = data.readString(); String[] selectionArgs = data.readStringArray(); - int count = delete(callingPkg, url, selection, selectionArgs); + int count = delete(callingPkg, featureId, url, selection, selectionArgs); reply.writeNoException(); reply.writeInt(count); @@ -207,12 +213,14 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); ContentValues values = ContentValues.CREATOR.createFromParcel(data); String selection = data.readString(); String[] selectionArgs = data.readStringArray(); - int count = update(callingPkg, url, values, selection, selectionArgs); + int count = update(callingPkg, featureId, url, values, selection, + selectionArgs); reply.writeNoException(); reply.writeInt(count); @@ -223,6 +231,7 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String mode = data.readString(); ICancellationSignal signal = ICancellationSignal.Stub.asInterface( @@ -230,7 +239,7 @@ abstract public class ContentProviderNative extends Binder implements IContentPr IBinder callerToken = data.readStrongBinder(); ParcelFileDescriptor fd; - fd = openFile(callingPkg, url, mode, signal, callerToken); + fd = openFile(callingPkg, featureId, url, mode, signal, callerToken); reply.writeNoException(); if (fd != null) { reply.writeInt(1); @@ -246,13 +255,14 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String mode = data.readString(); ICancellationSignal signal = ICancellationSignal.Stub.asInterface( data.readStrongBinder()); AssetFileDescriptor fd; - fd = openAssetFile(callingPkg, url, mode, signal); + fd = openAssetFile(callingPkg, featureId, url, mode, signal); reply.writeNoException(); if (fd != null) { reply.writeInt(1); @@ -269,12 +279,14 @@ abstract public class ContentProviderNative extends Binder implements IContentPr data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); String authority = data.readString(); String method = data.readString(); String stringArg = data.readString(); Bundle args = data.readBundle(); - Bundle responseBundle = call(callingPkg, authority, method, stringArg, args); + Bundle responseBundle = call(callingPkg, featureId, authority, method, + stringArg, args); reply.writeNoException(); reply.writeBundle(responseBundle); @@ -297,6 +309,7 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String mimeType = data.readString(); Bundle opts = data.readBundle(); @@ -304,7 +317,7 @@ abstract public class ContentProviderNative extends Binder implements IContentPr data.readStrongBinder()); AssetFileDescriptor fd; - fd = openTypedAssetFile(callingPkg, url, mimeType, opts, signal); + fd = openTypedAssetFile(callingPkg, featureId, url, mimeType, opts, signal); reply.writeNoException(); if (fd != null) { reply.writeInt(1); @@ -330,9 +343,10 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); - Uri out = canonicalize(callingPkg, url); + Uri out = canonicalize(callingPkg, featureId, url); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; @@ -342,9 +356,10 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); - Uri out = uncanonicalize(callingPkg, url); + Uri out = uncanonicalize(callingPkg, featureId, url); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; @@ -353,12 +368,13 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case REFRESH_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); Bundle args = data.readBundle(); ICancellationSignal signal = ICancellationSignal.Stub.asInterface( data.readStrongBinder()); - boolean out = refresh(callingPkg, url, args, signal); + boolean out = refresh(callingPkg, featureId, url, args, signal); reply.writeNoException(); reply.writeInt(out ? 0 : -1); return true; @@ -367,11 +383,12 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case CHECK_URI_PERMISSION_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); + String featureId = data.readString(); Uri uri = Uri.CREATOR.createFromParcel(data); int uid = data.readInt(); int modeFlags = data.readInt(); - int out = checkUriPermission(callingPkg, uri, uid, modeFlags); + int out = checkUriPermission(callingPkg, featureId, uri, uid, modeFlags); reply.writeNoException(); reply.writeInt(out); return true; @@ -407,8 +424,9 @@ final class ContentProviderProxy implements IContentProvider } @Override - public Cursor query(String callingPkg, Uri url, @Nullable String[] projection, - @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) + public Cursor query(String callingPkg, @Nullable String featureId, Uri url, + @Nullable String[] projection, @Nullable Bundle queryArgs, + @Nullable ICancellationSignal cancellationSignal) throws RemoteException { BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); Parcel data = Parcel.obtain(); @@ -417,6 +435,7 @@ final class ContentProviderProxy implements IContentProvider data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); int length = 0; if (projection != null) { @@ -478,7 +497,8 @@ final class ContentProviderProxy implements IContentProvider } @Override - public Uri insert(String callingPkg, Uri url, ContentValues values) throws RemoteException + public Uri insert(String callingPkg, @Nullable String featureId, Uri url, + ContentValues values) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -486,6 +506,7 @@ final class ContentProviderProxy implements IContentProvider data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); values.writeToParcel(data, 0); @@ -501,13 +522,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public int bulkInsert(String callingPkg, Uri url, ContentValues[] values) throws RemoteException { + public int bulkInsert(String callingPkg, @Nullable String featureId, Uri url, + ContentValues[] values) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); data.writeTypedArray(values, 0); @@ -523,14 +546,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public ContentProviderResult[] applyBatch(String callingPkg, String authority, - ArrayList operations) - throws RemoteException, OperationApplicationException { + public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId, + String authority, ArrayList operations) + throws RemoteException, OperationApplicationException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); data.writeString(authority); data.writeInt(operations.size()); for (ContentProviderOperation operation : operations) { @@ -549,14 +573,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs) - throws RemoteException { + public int delete(String callingPkg, @Nullable String featureId, Uri url, String selection, + String[] selectionArgs) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); data.writeString(selection); data.writeStringArray(selectionArgs); @@ -573,14 +598,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public int update(String callingPkg, Uri url, ContentValues values, String selection, - String[] selectionArgs) throws RemoteException { + public int update(String callingPkg, @Nullable String featureId, Uri url, + ContentValues values, String selection, String[] selectionArgs) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); values.writeToParcel(data, 0); data.writeString(selection); @@ -598,8 +624,8 @@ final class ContentProviderProxy implements IContentProvider } @Override - public ParcelFileDescriptor openFile( - String callingPkg, Uri url, String mode, ICancellationSignal signal, IBinder token) + public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url, + String mode, ICancellationSignal signal, IBinder token) throws RemoteException, FileNotFoundException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -607,6 +633,7 @@ final class ContentProviderProxy implements IContentProvider data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); data.writeString(mode); data.writeStrongBinder(signal != null ? signal.asBinder() : null); @@ -626,8 +653,8 @@ final class ContentProviderProxy implements IContentProvider } @Override - public AssetFileDescriptor openAssetFile( - String callingPkg, Uri url, String mode, ICancellationSignal signal) + public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId, + Uri url, String mode, ICancellationSignal signal) throws RemoteException, FileNotFoundException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -635,6 +662,7 @@ final class ContentProviderProxy implements IContentProvider data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); data.writeString(mode); data.writeStrongBinder(signal != null ? signal.asBinder() : null); @@ -653,14 +681,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public Bundle call(String callingPkg, String authority, String method, String request, - Bundle args) throws RemoteException { + public Bundle call(String callingPkg, @Nullable String featureId, String authority, + String method, String request, Bundle args) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); data.writeString(authority); data.writeString(method); data.writeString(request); @@ -700,14 +729,16 @@ final class ContentProviderProxy implements IContentProvider } @Override - public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri url, String mimeType, - Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException { + public AssetFileDescriptor openTypedAssetFile(String callingPkg, @Nullable String featureId, + Uri url, String mimeType, Bundle opts, ICancellationSignal signal) + throws RemoteException, FileNotFoundException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); data.writeString(mimeType); data.writeBundle(opts); @@ -747,14 +778,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public Uri canonicalize(String callingPkg, Uri url) throws RemoteException - { + public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri url) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0); @@ -769,13 +801,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public Uri uncanonicalize(String callingPkg, Uri url) throws RemoteException { + public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri url) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0); @@ -790,14 +824,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public boolean refresh(String callingPkg, Uri url, Bundle args, ICancellationSignal signal) - throws RemoteException { + public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args, + ICancellationSignal signal) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); data.writeBundle(args); data.writeStrongBinder(signal != null ? signal.asBinder() : null); @@ -814,14 +849,15 @@ final class ContentProviderProxy implements IContentProvider } @Override - public int checkUriPermission(String callingPkg, Uri url, int uid, int modeFlags) - throws RemoteException { + public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri url, int uid, + int modeFlags) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); + data.writeString(featureId); url.writeToParcel(data, 0); data.writeInt(uid); data.writeInt(modeFlags); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 7f9ea76c95d6..1031fe27e57a 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -649,6 +649,7 @@ public abstract class ContentResolver implements ContentInterface { public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) { mContext = context != null ? context : ActivityThread.currentApplication(); mPackageName = mContext.getOpPackageName(); + mFeatureId = mContext.getFeatureId(); mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; mWrapped = wrapped; } @@ -968,7 +969,7 @@ public abstract class ContentResolver implements ContentInterface { cancellationSignal.setRemote(remoteCancellationSignal); } try { - qCursor = unstableProvider.query(mPackageName, uri, projection, + qCursor = unstableProvider.query(mPackageName, mFeatureId, uri, projection, queryArgs, remoteCancellationSignal); } catch (DeadObjectException e) { // The remote process has died... but we only hold an unstable @@ -979,8 +980,8 @@ public abstract class ContentResolver implements ContentInterface { if (stableProvider == null) { return null; } - qCursor = stableProvider.query( - mPackageName, uri, projection, queryArgs, remoteCancellationSignal); + qCursor = stableProvider.query(mPackageName, mFeatureId, uri, projection, + queryArgs, remoteCancellationSignal); } if (qCursor == null) { return null; @@ -1070,7 +1071,7 @@ public abstract class ContentResolver implements ContentInterface { } try { - return provider.canonicalize(mPackageName, url); + return provider.canonicalize(mPackageName, mFeatureId, url); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. @@ -1114,7 +1115,7 @@ public abstract class ContentResolver implements ContentInterface { } try { - return provider.uncanonicalize(mPackageName, url); + return provider.uncanonicalize(mPackageName, mFeatureId, url); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. @@ -1163,7 +1164,8 @@ public abstract class ContentResolver implements ContentInterface { remoteCancellationSignal = provider.createCancellationSignal(); cancellationSignal.setRemote(remoteCancellationSignal); } - return provider.refresh(mPackageName, url, args, remoteCancellationSignal); + return provider.refresh(mPackageName, mFeatureId, url, args, + remoteCancellationSignal); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. @@ -1564,7 +1566,7 @@ public abstract class ContentResolver implements ContentInterface { try { fd = unstableProvider.openAssetFile( - mPackageName, uri, mode, remoteCancellationSignal); + mPackageName, mFeatureId, uri, mode, remoteCancellationSignal); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -1579,7 +1581,7 @@ public abstract class ContentResolver implements ContentInterface { throw new FileNotFoundException("No content provider: " + uri); } fd = stableProvider.openAssetFile( - mPackageName, uri, mode, remoteCancellationSignal); + mPackageName, mFeatureId, uri, mode, remoteCancellationSignal); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -1730,7 +1732,7 @@ public abstract class ContentResolver implements ContentInterface { try { fd = unstableProvider.openTypedAssetFile( - mPackageName, uri, mimeType, opts, remoteCancellationSignal); + mPackageName, mFeatureId, uri, mimeType, opts, remoteCancellationSignal); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -1745,7 +1747,7 @@ public abstract class ContentResolver implements ContentInterface { throw new FileNotFoundException("No content provider: " + uri); } fd = stableProvider.openTypedAssetFile( - mPackageName, uri, mimeType, opts, remoteCancellationSignal); + mPackageName, mFeatureId, uri, mimeType, opts, remoteCancellationSignal); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -1870,7 +1872,7 @@ public abstract class ContentResolver implements ContentInterface { } try { long startTime = SystemClock.uptimeMillis(); - Uri createdRow = provider.insert(mPackageName, url, values); + Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */); return createdRow; @@ -1951,7 +1953,7 @@ public abstract class ContentResolver implements ContentInterface { } try { long startTime = SystemClock.uptimeMillis(); - int rowsCreated = provider.bulkInsert(mPackageName, url, values); + int rowsCreated = provider.bulkInsert(mPackageName, mFeatureId, url, values); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */); return rowsCreated; @@ -1991,7 +1993,8 @@ public abstract class ContentResolver implements ContentInterface { } try { long startTime = SystemClock.uptimeMillis(); - int rowsDeleted = provider.delete(mPackageName, url, where, selectionArgs); + int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, where, + selectionArgs); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, url, "delete", where); return rowsDeleted; @@ -2035,7 +2038,8 @@ public abstract class ContentResolver implements ContentInterface { } try { long startTime = SystemClock.uptimeMillis(); - int rowsUpdated = provider.update(mPackageName, uri, values, where, selectionArgs); + int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, where, + selectionArgs); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, uri, "update", where); return rowsUpdated; @@ -2084,7 +2088,8 @@ public abstract class ContentResolver implements ContentInterface { throw new IllegalArgumentException("Unknown authority " + authority); } try { - final Bundle res = provider.call(mPackageName, authority, method, arg, extras); + final Bundle res = provider.call(mPackageName, mFeatureId, authority, method, arg, + extras); Bundle.setDefusable(res, true); return res; } catch (RemoteException e) { @@ -3436,6 +3441,11 @@ public abstract class ContentResolver implements ContentInterface { return mPackageName; } + /** @hide */ + public @Nullable String getFeatureId() { + return mFeatureId; + } + @UnsupportedAppUsage private static volatile IContentService sContentService; @UnsupportedAppUsage @@ -3443,6 +3453,7 @@ public abstract class ContentResolver implements ContentInterface { @UnsupportedAppUsage final String mPackageName; + final @Nullable String mFeatureId; final int mTargetSdkVersion; final ContentInterface mWrapped; diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java index fade0ab6bb5c..d2c97c4ebdd3 100644 --- a/core/java/android/content/IContentProvider.java +++ b/core/java/android/content/IContentProvider.java @@ -16,7 +16,6 @@ package android.content; -import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.content.res.AssetFileDescriptor; @@ -38,66 +37,96 @@ import java.util.ArrayList; * @hide */ public interface IContentProvider extends IInterface { - public Cursor query(String callingPkg, Uri url, @Nullable String[] projection, + public Cursor query(String callingPkg, @Nullable String featureId, Uri url, + @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) throws RemoteException; public String getType(Uri url) throws RemoteException; - @UnsupportedAppUsage - public Uri insert(String callingPkg, Uri url, ContentValues initialValues) - throws RemoteException; - @UnsupportedAppUsage - public int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues) - throws RemoteException; - @UnsupportedAppUsage - public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs) + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link " + + "ContentProviderClient#insert(android.net.Uri, android.content.ContentValues)} " + + "instead") + public default Uri insert(String callingPkg, Uri url, ContentValues initialValues) + throws RemoteException { + return insert(callingPkg, null, url, initialValues); + } + public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues) throws RemoteException; - @UnsupportedAppUsage - public int update(String callingPkg, Uri url, ContentValues values, String selection, + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link " + + "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])" + + "} instead") + public default int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues) + throws RemoteException { + return bulkInsert(callingPkg, null, url, initialValues); + } + public int bulkInsert(String callingPkg, String featureId, Uri url, + ContentValues[] initialValues) throws RemoteException; + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link " + + "ContentProviderClient#delete(android.net.Uri, java.lang.String, java.lang" + + ".String[])} instead") + public default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs) + throws RemoteException { + return delete(callingPkg, null, url, selection, selectionArgs); + } + public int delete(String callingPkg, String featureId, Uri url, String selection, String[] selectionArgs) throws RemoteException; - public ParcelFileDescriptor openFile( - String callingPkg, Uri url, String mode, ICancellationSignal signal, - IBinder callerToken) - throws RemoteException, FileNotFoundException; - public AssetFileDescriptor openAssetFile( - String callingPkg, Uri url, String mode, ICancellationSignal signal) - throws RemoteException, FileNotFoundException; - @Deprecated - public default ContentProviderResult[] applyBatch(String callingPkg, - ArrayList operations) - throws RemoteException, OperationApplicationException { - return applyBatch(callingPkg, "unknown", operations); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link " + + "ContentProviderClient#update(android.net.Uri, android.content.ContentValues, java" + + ".lang.String, java.lang.String[])} instead") + public default int update(String callingPkg, Uri url, ContentValues values, String selection, + String[] selectionArgs) throws RemoteException { + return update(callingPkg, null, url, values, selection, selectionArgs); } + public int update(String callingPkg, String featureId, Uri url, ContentValues values, + String selection, String[] selectionArgs) throws RemoteException; + + public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url, + String mode, ICancellationSignal signal, IBinder callerToken) + throws RemoteException, FileNotFoundException; - public ContentProviderResult[] applyBatch(String callingPkg, String authority, - ArrayList operations) + public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId, + Uri url, String mode, ICancellationSignal signal) + throws RemoteException, FileNotFoundException; + + public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId, + String authority, ArrayList operations) throws RemoteException, OperationApplicationException; @Deprecated - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link " + + "ContentProviderClient#call(java.lang.String, java.lang.String, android.os.Bundle)} " + + "instead") public default Bundle call(String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras) throws RemoteException { - return call(callingPkg, "unknown", method, arg, extras); + return call(callingPkg, null, "unknown", method, arg, extras); } - public Bundle call(String callingPkg, String authority, String method, - @Nullable String arg, @Nullable Bundle extras) throws RemoteException; + public Bundle call(String callingPkg, @Nullable String featureId, String authority, + String method, @Nullable String arg, @Nullable Bundle extras) throws RemoteException; - public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) - throws RemoteException; + public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid, + int modeFlags) throws RemoteException; public ICancellationSignal createCancellationSignal() throws RemoteException; - public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException; - public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException; + public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) + throws RemoteException; + + public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri) + throws RemoteException; - public boolean refresh(String callingPkg, Uri url, @Nullable Bundle args, - ICancellationSignal cancellationSignal) throws RemoteException; + public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, + @Nullable Bundle args, ICancellationSignal cancellationSignal) throws RemoteException; // Data interchange. public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException; - public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri url, String mimeType, - Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException; + + public AssetFileDescriptor openTypedAssetFile(String callingPkg, @Nullable String featureId, + Uri url, String mimeType, Bundle opts, ICancellationSignal signal) + throws RemoteException, FileNotFoundException; /* IPC constants */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java index 2143a0deb723..a80153d691f0 100644 --- a/core/java/android/provider/DocumentsProvider.java +++ b/core/java/android/provider/DocumentsProvider.java @@ -1081,7 +1081,8 @@ public abstract class DocumentsProvider extends ContentProvider { // signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for // MANAGE_DOCUMENTS or associated URI permission here instead final Uri rootUri = extras.getParcelable(DocumentsContract.EXTRA_URI); - enforceWritePermissionInner(rootUri, getCallingPackage(), null); + enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingFeatureId(), + null); final String rootId = DocumentsContract.getRootId(rootUri); ejectRoot(rootId); @@ -1102,7 +1103,8 @@ public abstract class DocumentsProvider extends ContentProvider { enforceTree(documentUri); if (METHOD_IS_CHILD_DOCUMENT.equals(method)) { - enforceReadPermissionInner(documentUri, getCallingPackage(), null); + enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); final Uri childUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI); final String childAuthority = childUri.getAuthority(); @@ -1114,7 +1116,8 @@ public abstract class DocumentsProvider extends ContentProvider { && isChildDocument(documentId, childId)); } else if (METHOD_CREATE_DOCUMENT.equals(method)) { - enforceWritePermissionInner(documentUri, getCallingPackage(), null); + enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE); final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME); @@ -1128,7 +1131,8 @@ public abstract class DocumentsProvider extends ContentProvider { out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri); } else if (METHOD_CREATE_WEB_LINK_INTENT.equals(method)) { - enforceWritePermissionInner(documentUri, getCallingPackage(), null); + enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); final Bundle options = extras.getBundle(DocumentsContract.EXTRA_OPTIONS); final IntentSender intentSender = createWebLinkIntent(documentId, options); @@ -1136,7 +1140,8 @@ public abstract class DocumentsProvider extends ContentProvider { out.putParcelable(DocumentsContract.EXTRA_RESULT, intentSender); } else if (METHOD_RENAME_DOCUMENT.equals(method)) { - enforceWritePermissionInner(documentUri, getCallingPackage(), null); + enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME); final String newDocumentId = renameDocument(documentId, displayName); @@ -1160,7 +1165,8 @@ public abstract class DocumentsProvider extends ContentProvider { } } else if (METHOD_DELETE_DOCUMENT.equals(method)) { - enforceWritePermissionInner(documentUri, getCallingPackage(), null); + enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); deleteDocument(documentId); // Document no longer exists, clean up any grants. @@ -1170,8 +1176,10 @@ public abstract class DocumentsProvider extends ContentProvider { final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI); final String targetId = DocumentsContract.getDocumentId(targetUri); - enforceReadPermissionInner(documentUri, getCallingPackage(), null); - enforceWritePermissionInner(targetUri, getCallingPackage(), null); + enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); + enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingFeatureId(), + null); final String newDocumentId = copyDocument(documentId, targetId); @@ -1194,9 +1202,12 @@ public abstract class DocumentsProvider extends ContentProvider { final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI); final String targetId = DocumentsContract.getDocumentId(targetUri); - enforceWritePermissionInner(documentUri, getCallingPackage(), null); - enforceReadPermissionInner(parentSourceUri, getCallingPackage(), null); - enforceWritePermissionInner(targetUri, getCallingPackage(), null); + enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); + enforceReadPermissionInner(parentSourceUri, getCallingPackage(), getCallingFeatureId(), + null); + enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingFeatureId(), + null); final String newDocumentId = moveDocument(documentId, parentSourceId, targetId); @@ -1217,8 +1228,10 @@ public abstract class DocumentsProvider extends ContentProvider { final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI); final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri); - enforceReadPermissionInner(parentSourceUri, getCallingPackage(), null); - enforceWritePermissionInner(documentUri, getCallingPackage(), null); + enforceReadPermissionInner(parentSourceUri, getCallingPackage(), getCallingFeatureId(), + null); + enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); removeDocument(documentId, parentSourceId); // It's responsibility of the provider to revoke any grants, as the document may be @@ -1227,7 +1240,8 @@ public abstract class DocumentsProvider extends ContentProvider { final boolean isTreeUri = isTreeUri(documentUri); if (isTreeUri) { - enforceReadPermissionInner(documentUri, getCallingPackage(), null); + enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(), + null); } else { getContext().enforceCallingPermission(Manifest.permission.MANAGE_DOCUMENTS, null); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b5580d4d589b..cce7c42000d8 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2306,8 +2306,8 @@ public final class Settings { arg.putBoolean(CALL_METHOD_MAKE_DEFAULT_KEY, true); } IContentProvider cp = mProviderHolder.getProvider(cr); - cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(), - mCallSetCommand, name, arg); + cp.call(cr.getPackageName(), cr.getFeatureId(), + mProviderHolder.mUri.getAuthority(), mCallSetCommand, name, arg); } catch (RemoteException e) { Log.w(TAG, "Can't set key " + name + " in " + mUri, e); return false; @@ -2380,14 +2380,15 @@ public final class Settings { if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { final long token = Binder.clearCallingIdentity(); try { - b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(), - mCallGetCommand, name, args); + b = cp.call(cr.getPackageName(), cr.getFeatureId(), + mProviderHolder.mUri.getAuthority(), mCallGetCommand, name, + args); } finally { Binder.restoreCallingIdentity(token); } } else { - b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(), - mCallGetCommand, name, args); + b = cp.call(cr.getPackageName(), cr.getFeatureId(), + mProviderHolder.mUri.getAuthority(), mCallGetCommand, name, args); } if (b != null) { String value = b.getString(Settings.NameValueTable.VALUE); @@ -2455,14 +2456,14 @@ public final class Settings { if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { final long token = Binder.clearCallingIdentity(); try { - c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, - null); + c = cp.query(cr.getPackageName(), cr.getFeatureId(), mUri, + SELECT_VALUE_PROJECTION, queryArgs, null); } finally { Binder.restoreCallingIdentity(token); } } else { - c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, - null); + c = cp.query(cr.getPackageName(), cr.getFeatureId(), mUri, + SELECT_VALUE_PROJECTION, queryArgs, null); } if (c == null) { Log.w(TAG, "Can't get key " + name + " from " + mUri); @@ -2557,8 +2558,8 @@ public final class Settings { } // Fetch all flags for the namespace at once for caching purposes - Bundle b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(), - mCallListCommand, null, args); + Bundle b = cp.call(cr.getPackageName(), cr.getFeatureId(), + mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args); if (b == null) { // Invalid response, return an empty map return keyValues; @@ -5132,8 +5133,8 @@ public final class Settings { } arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode); IContentProvider cp = sProviderHolder.getProvider(resolver); - cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(), - CALL_METHOD_RESET_SECURE, null, arg); + cp.call(resolver.getPackageName(), resolver.getFeatureId(), + sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_SECURE, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e); } @@ -12821,8 +12822,8 @@ public final class Settings { } arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode); IContentProvider cp = sProviderHolder.getProvider(resolver); - cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(), - CALL_METHOD_RESET_GLOBAL, null, arg); + cp.call(resolver.getPackageName(), resolver.getFeatureId(), + sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_GLOBAL, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e); } @@ -13758,8 +13759,8 @@ public final class Settings { arg.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix); } IContentProvider cp = sProviderHolder.getProvider(resolver); - cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(), - CALL_METHOD_RESET_CONFIG, null, arg); + cp.call(resolver.getPackageName(), resolver.getFeatureId(), + sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_CONFIG, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't reset to defaults for " + DeviceConfig.CONTENT_URI, e); } diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java index f14f2896d8f5..88967b54aa50 100644 --- a/core/tests/coretests/src/android/content/ContentResolverTest.java +++ b/core/tests/coretests/src/android/content/ContentResolverTest.java @@ -82,7 +82,8 @@ public class ContentResolverTest { final AssetFileDescriptor afd = new AssetFileDescriptor( new ParcelFileDescriptor(mImage.getFileDescriptor()), 0, mSize, null); - when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any())).thenReturn(afd); + when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any(), any())).thenReturn( + afd); } private static void assertImageAspectAndContents(Bitmap bitmap) { diff --git a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java index 1bd8ff6bdea3..5f640bee7ce9 100644 --- a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java +++ b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java @@ -93,12 +93,14 @@ public class TestDocumentsProvider extends DocumentsProvider { } @Override - protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) { + protected int enforceReadPermissionInner(Uri uri, String callingPkg, + @Nullable String callingFeatureId, IBinder callerToken) { return AppOpsManager.MODE_ALLOWED; } @Override - protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) { + protected int enforceWritePermissionInner(Uri uri, String callingPkg, + @Nullable String callingFeatureId, IBinder callerToken) { return AppOpsManager.MODE_ALLOWED; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java index 74bf1a20304a..de353bf58aec 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java @@ -42,6 +42,7 @@ import org.mockito.MockitoAnnotations; public class MediaInserterTest extends InstrumentationTestCase { + private static final String TEST_FEATURE_ID = "testFeature"; private MediaInserter mMediaInserter; private static final int TEST_BUFFER_SIZE = 10; private @Mock IContentProvider mMockProvider; @@ -86,7 +87,8 @@ public class MediaInserterTest extends InstrumentationTestCase { MockitoAnnotations.initMocks(this); final ContentProviderClient client = new ContentProviderClient( - getInstrumentation().getContext().getContentResolver(), mMockProvider, true); + getInstrumentation().getContext().createFeatureContext(TEST_FEATURE_ID) + .getContentResolver(), mMockProvider, true); mMediaInserter = new MediaInserter(client, TEST_BUFFER_SIZE); mPackageName = getInstrumentation().getContext().getPackageName(); mFilesCounter = 0; @@ -142,31 +144,36 @@ public class MediaInserterTest extends InstrumentationTestCase { fillBuffer(sVideoUri, TEST_BUFFER_SIZE - 2); fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1); - verify(mMockProvider, never()).bulkInsert(eq(mPackageName), any(), any()); + verify(mMockProvider, never()).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any()); } @SmallTest public void testInsertContentsEqualToBufferSize() throws Exception { - when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any())).thenReturn(1); fillBuffer(sFilesUri, TEST_BUFFER_SIZE); fillBuffer(sAudioUri, TEST_BUFFER_SIZE); fillBuffer(sVideoUri, TEST_BUFFER_SIZE); fillBuffer(sImagesUri, TEST_BUFFER_SIZE); - verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), any(), any()); + verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any()); } @SmallTest public void testInsertContentsMoreThanBufferSize() throws Exception { - when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any())).thenReturn(1); fillBuffer(sFilesUri, TEST_BUFFER_SIZE + 1); fillBuffer(sAudioUri, TEST_BUFFER_SIZE + 2); fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3); fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4); - verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), any(), any()); + verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any()); } @SmallTest @@ -176,7 +183,8 @@ public class MediaInserterTest extends InstrumentationTestCase { @SmallTest public void testFlushAllWithSomeContents() throws Exception { - when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any())).thenReturn(1); fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4); fillBuffer(sAudioUri, TEST_BUFFER_SIZE - 3); @@ -184,12 +192,14 @@ public class MediaInserterTest extends InstrumentationTestCase { fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1); mMediaInserter.flushAll(); - verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), any(), any()); + verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any()); } @SmallTest public void testInsertContentsAfterFlushAll() throws Exception { - when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any())).thenReturn(1); fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4); fillBuffer(sAudioUri, TEST_BUFFER_SIZE - 3); @@ -202,15 +212,20 @@ public class MediaInserterTest extends InstrumentationTestCase { fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3); fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4); - verify(mMockProvider, times(8)).bulkInsert(eq(mPackageName), any(), any()); + verify(mMockProvider, times(8)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(), + any()); } @SmallTest public void testInsertContentsWithDifferentSizePerContentType() throws Exception { - when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sFilesUri), any())).thenReturn(1); - when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sAudioUri), any())).thenReturn(1); - when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sVideoUri), any())).thenReturn(1); - when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sImagesUri), any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sFilesUri), + any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sAudioUri), + any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sVideoUri), + any())).thenReturn(1); + when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sImagesUri), + any())).thenReturn(1); for (int i = 0; i < TEST_BUFFER_SIZE; ++i) { fillBuffer(sFilesUri, 1); @@ -219,9 +234,13 @@ public class MediaInserterTest extends InstrumentationTestCase { fillBuffer(sImagesUri, 4); } - verify(mMockProvider, times(1)).bulkInsert(eq(mPackageName), eqUri(sFilesUri), any()); - verify(mMockProvider, times(2)).bulkInsert(eq(mPackageName), eqUri(sAudioUri), any()); - verify(mMockProvider, times(3)).bulkInsert(eq(mPackageName), eqUri(sVideoUri), any()); - verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eqUri(sImagesUri), any()); + verify(mMockProvider, times(1)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), + eqUri(sFilesUri), any()); + verify(mMockProvider, times(2)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), + eqUri(sAudioUri), any()); + verify(mMockProvider, times(3)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), + eqUri(sVideoUri), any()); + verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), + eqUri(sImagesUri), any()); } } diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 48d34ae7ba47..af96982f5426 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -129,17 +129,17 @@ public class ExternalStorageProvider extends FileSystemProvider { } @Override - protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) - throws SecurityException { + protected int enforceReadPermissionInner(Uri uri, String callingPkg, + @Nullable String featureId, IBinder callerToken) throws SecurityException { enforceShellRestrictions(); - return super.enforceReadPermissionInner(uri, callingPkg, callerToken); + return super.enforceReadPermissionInner(uri, callingPkg, featureId, callerToken); } @Override - protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) - throws SecurityException { + protected int enforceWritePermissionInner(Uri uri, String callingPkg, + @Nullable String featureId, IBinder callerToken) throws SecurityException { enforceShellRestrictions(); - return super.enforceWritePermissionInner(uri, callingPkg, callerToken); + return super.enforceWritePermissionInner(uri, callingPkg, featureId, callerToken); } public void updateVolumes() { diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java index c4df2e8860b4..b9daf7fcab4e 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java @@ -406,8 +406,8 @@ public class TileUtils { return null; } try { - return provider.call(context.getPackageName(), uri.getAuthority(), - method, uri.toString(), bundle); + return provider.call(context.getPackageName(), context.getFeatureId(), + uri.getAuthority(), method, uri.toString(), bundle); } catch (RemoteException e) { return null; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java index 8fb879d3606b..1e75fe70becd 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java @@ -248,7 +248,7 @@ public final class DeviceConfigService extends Binder { Bundle args = new Bundle(); args.putInt(Settings.CALL_METHOD_USER_KEY, ActivityManager.getService().getCurrentUser().id); - Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY, + Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY, Settings.CALL_METHOD_DELETE_CONFIG, compositeKey, args); success = (b != null && b.getInt(SettingsProvider.RESULT_ROWS_DELETED) == 1); } catch (RemoteException e) { @@ -264,7 +264,7 @@ public final class DeviceConfigService extends Binder { Bundle args = new Bundle(); args.putInt(Settings.CALL_METHOD_USER_KEY, ActivityManager.getService().getCurrentUser().id); - Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY, + Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY, Settings.CALL_METHOD_LIST_CONFIG, null, args); if (b != null) { Map flagsToValues = diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java index 36360a31a4b7..3b3ca5b02417 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java @@ -309,7 +309,7 @@ final public class SettingsService extends Binder { try { Bundle arg = new Bundle(); arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle); - Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY, + Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY, callListCommand, null, arg); lines.addAll(result.getStringArrayList(SettingsProvider.RESULT_SETTINGS_LIST)); Collections.sort(lines); @@ -334,7 +334,7 @@ final public class SettingsService extends Binder { try { Bundle arg = new Bundle(); arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle); - Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY, + Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY, callGetCommand, key, arg); if (b != null) { result = b.getPairValue(); @@ -372,7 +372,7 @@ final public class SettingsService extends Binder { if (makeDefault) { arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true); } - provider.call(resolveCallingPackage(), Settings.AUTHORITY, + provider.call(resolveCallingPackage(), null, Settings.AUTHORITY, callPutCommand, key, arg); } catch (RemoteException e) { throw new RuntimeException("Failed in IPC", e); @@ -396,7 +396,7 @@ final public class SettingsService extends Binder { try { Bundle arg = new Bundle(); arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle); - Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY, + Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY, callDeleteCommand, key, arg); return result.getInt(SettingsProvider.RESULT_ROWS_DELETED); } catch (RemoteException e) { @@ -423,7 +423,7 @@ final public class SettingsService extends Binder { } String packageName = mPackageName != null ? mPackageName : resolveCallingPackage(); arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle); - provider.call(packageName, Settings.AUTHORITY, callResetCommand, null, arg); + provider.call(packageName, null, Settings.AUTHORITY, callResetCommand, null, arg); } catch (RemoteException e) { throw new RuntimeException("Failed in IPC", e); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 11cfe12f6e67..5df45437ae34 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7758,7 +7758,7 @@ public class ActivityManagerService extends IActivityManager.Stub holder = getContentProviderExternalUnchecked(name, null, callingUid, "*checkContentProviderUriPermission*", userId); if (holder != null) { - return holder.provider.checkUriPermission(null, uri, callingUid, modeFlags); + return holder.provider.checkUriPermission(null, null, uri, callingUid, modeFlags); } } catch (RemoteException e) { Log.w(TAG, "Content provider dead retrieving " + uri, e); @@ -7923,7 +7923,7 @@ public class ActivityManagerService extends IActivityManager.Stub sCallerIdentity.set(new Identity( token, Binder.getCallingPid(), Binder.getCallingUid())); try { - pfd = cph.provider.openFile(null, uri, "r", null, token); + pfd = cph.provider.openFile(null, null, uri, "r", null, token); } catch (FileNotFoundException e) { // do nothing; pfd will be returned null } finally { diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index 1ad7b6e8d155..79af34d80686 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -191,7 +191,7 @@ public class NetworkScoreServiceTest { @After public void tearDown() throws Exception { mHandlerThread.quitSafely(); - LocalServices.removeServiceForTest(PackageManagerInternal.class); + LocalServices.removeServiceForTest(PermissionManagerServiceInternal.class); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 80439cf66387..a1322b9a9015 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -62,7 +62,6 @@ import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings.Secure; - import android.test.suitebuilder.annotation.SmallTest; import android.testing.TestableContentResolver; import android.util.ArrayMap; @@ -162,11 +161,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider); contentResolver.addProvider(TEST_AUTHORITY, testContentProvider); - when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))) + when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI))) .thenReturn(CANONICAL_SOUND_URI); - when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(CANONICAL_SOUND_URI); - when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(SOUND_URI); mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, @@ -465,7 +464,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // Testing that in restore we are given the canonical version loadStreamXml(baos, true, UserHandle.USER_SYSTEM); - verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI)); + verify(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)); } @Test @@ -475,11 +474,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { .appendQueryParameter("title", "Test") .appendQueryParameter("canonical", "1") .build(); - when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(canonicalBasedOnLocal); - when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(localUri); - when(mTestIContentProvider.uncanonicalize(any(), eq(canonicalBasedOnLocal))) + when(mTestIContentProvider.uncanonicalize(any(), any(), eq(canonicalBasedOnLocal))) .thenReturn(localUri); NotificationChannel channel = @@ -499,9 +498,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception { Thread.sleep(3000); - when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(null); - when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(null); NotificationChannel channel = @@ -526,7 +525,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception { // Not a local uncanonicalized uri, simulating that it fails to exist locally - when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))).thenReturn(null); + when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI))).thenReturn(null); String id = "id"; String backupWithUncanonicalizedSoundUri = "\n" + "\n" diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java index 2abd340e967a..8774b639b554 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java @@ -132,11 +132,11 @@ public class RankingHelperTest extends UiServiceTestCase { when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider); contentResolver.addProvider(TEST_AUTHORITY, testContentProvider); - when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))) + when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI))) .thenReturn(CANONICAL_SOUND_URI); - when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(CANONICAL_SOUND_URI); - when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI))) + when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI))) .thenReturn(SOUND_URI); mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java index 3b336eb7aec9..aceed86220c6 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java @@ -12,6 +12,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -109,8 +110,8 @@ public class PinnedSliceStateTest extends UiServiceTestCase { mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken); TestableLooper.get(this).processAllMessages(); - verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN), - eq(null), argThat(b -> { + verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(), + eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> { assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI)); return true; })); @@ -167,8 +168,8 @@ public class PinnedSliceStateTest extends UiServiceTestCase { // Throw exception when trying to pin doAnswer(invocation -> { throw new Exception("Pin failed"); - }).when(mIContentProvider).call( - anyString(), anyString(), anyString(), eq(null), any()); + }).when(mIContentProvider).call(anyString(), nullable(String.class), anyString(), + anyString(), eq(null), any()); TestableLooper.get(this).processAllMessages(); @@ -176,8 +177,8 @@ public class PinnedSliceStateTest extends UiServiceTestCase { mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken); TestableLooper.get(this).processAllMessages(); - verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN), - eq(null), argThat(b -> { + verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(), + eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> { assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI)); return true; })); diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java index 4d8c7d930bde..9d3e12050193 100644 --- a/test-mock/src/android/test/mock/MockContentProvider.java +++ b/test-mock/src/android/test/mock/MockContentProvider.java @@ -56,21 +56,22 @@ public class MockContentProvider extends ContentProvider { */ private class InversionIContentProvider implements IContentProvider { @Override - public ContentProviderResult[] applyBatch(String callingPackage, String authority, + public ContentProviderResult[] applyBatch(String callingPackage, + @Nullable String featureId, String authority, ArrayList operations) throws RemoteException, OperationApplicationException { return MockContentProvider.this.applyBatch(authority, operations); } @Override - public int bulkInsert(String callingPackage, Uri url, ContentValues[] initialValues) - throws RemoteException { + public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url, + ContentValues[] initialValues) throws RemoteException { return MockContentProvider.this.bulkInsert(url, initialValues); } @Override - public int delete(String callingPackage, Uri url, String selection, String[] selectionArgs) - throws RemoteException { + public int delete(String callingPackage, @Nullable String featureId, Uri url, + String selection, String[] selectionArgs) throws RemoteException { return MockContentProvider.this.delete(url, selection, selectionArgs); } @@ -80,42 +81,42 @@ public class MockContentProvider extends ContentProvider { } @Override - public Uri insert(String callingPackage, Uri url, ContentValues initialValues) - throws RemoteException { + public Uri insert(String callingPackage, @Nullable String featureId, Uri url, + ContentValues initialValues) throws RemoteException { return MockContentProvider.this.insert(url, initialValues); } @Override - public AssetFileDescriptor openAssetFile( - String callingPackage, Uri url, String mode, ICancellationSignal signal) + public AssetFileDescriptor openAssetFile(String callingPackage, + @Nullable String featureId, Uri url, String mode, ICancellationSignal signal) throws RemoteException, FileNotFoundException { return MockContentProvider.this.openAssetFile(url, mode); } @Override - public ParcelFileDescriptor openFile( - String callingPackage, Uri url, String mode, ICancellationSignal signal, - IBinder callerToken) throws RemoteException, FileNotFoundException { + public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId, + Uri url, String mode, ICancellationSignal signal, IBinder callerToken) + throws RemoteException, FileNotFoundException { return MockContentProvider.this.openFile(url, mode); } @Override - public Cursor query(String callingPackage, Uri url, @Nullable String[] projection, - @Nullable Bundle queryArgs, - @Nullable ICancellationSignal cancellationSignal) - throws RemoteException { + public Cursor query(String callingPackage, @Nullable String featureId, Uri url, + @Nullable String[] projection, @Nullable Bundle queryArgs, + @Nullable ICancellationSignal cancellationSignal) throws RemoteException { return MockContentProvider.this.query(url, projection, queryArgs, null); } @Override - public int update(String callingPackage, Uri url, ContentValues values, String selection, - String[] selectionArgs) throws RemoteException { + public int update(String callingPackage, @Nullable String featureId, Uri url, + ContentValues values, String selection, String[] selectionArgs) + throws RemoteException { return MockContentProvider.this.update(url, values, selection, selectionArgs); } @Override - public Bundle call(String callingPackage, String authority, String method, String request, - Bundle args) throws RemoteException { + public Bundle call(String callingPackage, @Nullable String featureId, String authority, + String method, String request, Bundle args) throws RemoteException { return MockContentProvider.this.call(authority, method, request, args); } @@ -130,9 +131,9 @@ public class MockContentProvider extends ContentProvider { } @Override - public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri url, - String mimeType, Bundle opts, ICancellationSignal signal) - throws RemoteException, FileNotFoundException { + public AssetFileDescriptor openTypedAssetFile(String callingPackage, + @Nullable String featureId, Uri url, String mimeType, Bundle opts, + ICancellationSignal signal) throws RemoteException, FileNotFoundException { return MockContentProvider.this.openTypedAssetFile(url, mimeType, opts); } @@ -142,23 +143,26 @@ public class MockContentProvider extends ContentProvider { } @Override - public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException { + public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) + throws RemoteException { return MockContentProvider.this.canonicalize(uri); } @Override - public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException { + public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri) + throws RemoteException { return MockContentProvider.this.uncanonicalize(uri); } @Override - public boolean refresh(String callingPkg, Uri url, Bundle args, - ICancellationSignal cancellationSignal) throws RemoteException { + public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, + Bundle args, ICancellationSignal cancellationSignal) throws RemoteException { return MockContentProvider.this.refresh(url, args); } @Override - public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) { + public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, + int uid, int modeFlags) { return MockContentProvider.this.checkUriPermission(uri, uid, modeFlags); } } diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java index b072d7440de4..e512b52643f3 100644 --- a/test-mock/src/android/test/mock/MockIContentProvider.java +++ b/test-mock/src/android/test/mock/MockIContentProvider.java @@ -16,14 +16,12 @@ package android.test.mock; -import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentValues; import android.content.EntityIterator; import android.content.IContentProvider; -import android.content.Intent; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.net.Uri; @@ -45,14 +43,15 @@ import java.util.ArrayList; */ public class MockIContentProvider implements IContentProvider { @Override - public int bulkInsert(String callingPackage, Uri url, ContentValues[] initialValues) { + public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url, + ContentValues[] initialValues) { throw new UnsupportedOperationException("unimplemented mock method"); } @Override @SuppressWarnings("unused") - public int delete(String callingPackage, Uri url, String selection, String[] selectionArgs) - throws RemoteException { + public int delete(String callingPackage, @Nullable String featureId, Uri url, + String selection, String[] selectionArgs) throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } @@ -63,33 +62,33 @@ public class MockIContentProvider implements IContentProvider { @Override @SuppressWarnings("unused") - public Uri insert(String callingPackage, Uri url, ContentValues initialValues) - throws RemoteException { + public Uri insert(String callingPackage, @Nullable String featureId, Uri url, + ContentValues initialValues) throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } @Override - public ParcelFileDescriptor openFile( - String callingPackage, Uri url, String mode, ICancellationSignal signal, - IBinder callerToken) { + public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId, + Uri url, String mode, ICancellationSignal signal, IBinder callerToken) { throw new UnsupportedOperationException("unimplemented mock method"); } @Override - public AssetFileDescriptor openAssetFile( - String callingPackage, Uri uri, String mode, ICancellationSignal signal) { + public AssetFileDescriptor openAssetFile(String callingPackage, @Nullable String featureId, + Uri uri, String mode, ICancellationSignal signal) { throw new UnsupportedOperationException("unimplemented mock method"); } @Override - public ContentProviderResult[] applyBatch(String callingPackage, String authority, - ArrayList operations) { + public ContentProviderResult[] applyBatch(String callingPackage, @Nullable String featureId, + String authority, ArrayList operations) { throw new UnsupportedOperationException("unimplemented mock method"); } @Override - public Cursor query(String callingPackage, Uri url, @Nullable String[] projection, - @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) { + public Cursor query(String callingPackage, @Nullable String featureId, Uri url, + @Nullable String[] projection, @Nullable Bundle queryArgs, + @Nullable ICancellationSignal cancellationSignal) { throw new UnsupportedOperationException("unimplemented mock method"); } @@ -99,14 +98,14 @@ public class MockIContentProvider implements IContentProvider { } @Override - public int update(String callingPackage, Uri url, ContentValues values, String selection, - String[] selectionArgs) throws RemoteException { + public int update(String callingPackage, @Nullable String featureId, Uri url, + ContentValues values, String selection, String[] selectionArgs) throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } @Override - public Bundle call(String callingPackage, String authority, String method, String request, - Bundle args) throws RemoteException { + public Bundle call(String callingPackage, @Nullable String featureId, String authority, + String method, String request, Bundle args) throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } @@ -121,8 +120,9 @@ public class MockIContentProvider implements IContentProvider { } @Override - public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri url, String mimeType, - Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException { + public AssetFileDescriptor openTypedAssetFile(String callingPackage, + @Nullable String featureId, Uri url, String mimeType, Bundle opts, + ICancellationSignal signal) throws RemoteException, FileNotFoundException { throw new UnsupportedOperationException("unimplemented mock method"); } @@ -132,24 +132,27 @@ public class MockIContentProvider implements IContentProvider { } @Override - public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException { + public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) + throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } @Override - public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException { + public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri) + throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } @Override - public boolean refresh(String callingPkg, Uri url, Bundle args, + public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args, ICancellationSignal cancellationSignal) throws RemoteException { throw new UnsupportedOperationException("unimplemented mock method"); } /** {@hide} */ @Override - public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) { + public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid, + int modeFlags) { throw new UnsupportedOperationException("unimplemented mock method call"); } }