Extract common methods into ContentInterface.

Existing APIs that accept a ContentResolver are too restrictive when
the caller has their own ContentProviderClient already bound and
configured, so we're in the market for a solution to open those
existing APIs to accept a wider range of inputs.

The solution we've come up with is to introduce a super-interface
which contains the common ContentProvider APIs, and then make
ContentProvider, ContentResolver, and ContentProviderClient all
implement that interface for consistency.

After this change lands, we can then safely relax existing APIs to
accept this new ContentInterface, offering a clean path to solving
the problem outlined above.

Bug: 117635768
Test: atest android.content.cts
Test: atest android.provider.cts
Change-Id: Ic5ae08107f7dd3dd23dcaec2df40c16543e0d86e
Exempted-From-Owner-Approval: keep tests working
This commit is contained in:
Jeff Sharkey
2018-12-07 12:00:45 -07:00
parent dfeea60477
commit 633a13e2fa
15 changed files with 324 additions and 73 deletions

View File

@@ -9227,11 +9227,31 @@ package android.content {
field public static final android.os.Parcelable.Creator<android.content.ComponentName> CREATOR;
}
public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
public abstract interface ContentInterface {
method public abstract android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
method public abstract int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException;
method public abstract android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
method public abstract android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException;
method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
method public abstract java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException;
method public abstract java.lang.String getType(android.net.Uri) throws android.os.RemoteException;
method public abstract android.net.Uri insert(android.net.Uri, android.content.ContentValues) throws android.os.RemoteException;
method public abstract android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public abstract android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public abstract android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public abstract boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public abstract android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
}
public abstract class ContentProvider implements android.content.ComponentCallbacks2 android.content.ContentInterface {
ctor public ContentProvider();
method public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
method public void attachInfo(android.content.Context, android.content.pm.ProviderInfo);
method public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
method public android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle);
method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
method public android.net.Uri canonicalize(android.net.Uri);
method public final android.content.ContentProvider.CallingIdentity clearCallingIdentity();
@@ -9278,10 +9298,12 @@ package android.content {
method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
}
public class ContentProviderClient implements java.lang.AutoCloseable {
public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
method public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
method public int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException;
method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
method public android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
method public final android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException;
method public void close();
method public static void closeQuietly(android.content.ContentProviderClient);
@@ -9294,6 +9316,7 @@ package android.content {
method public android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public final android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException, android.os.RemoteException;
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
@@ -9358,7 +9381,7 @@ package android.content {
method public void setKeepUpdated(boolean);
}
public abstract class ContentResolver {
public abstract class ContentResolver implements android.content.ContentInterface {
ctor public ContentResolver(android.content.Context);
method public final android.content.ContentProviderClient acquireContentProviderClient(android.net.Uri);
method public final android.content.ContentProviderClient acquireContentProviderClient(java.lang.String);
@@ -9369,6 +9392,7 @@ package android.content {
method public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
method public final int bulkInsert(android.net.Uri, android.content.ContentValues[]);
method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle);
method public final android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle);
method public deprecated void cancelSync(android.net.Uri);
method public static void cancelSync(android.accounts.Account, java.lang.String);
method public static void cancelSync(android.content.SyncRequest);
@@ -9392,13 +9416,16 @@ package android.content {
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final java.io.InputStream openInputStream(android.net.Uri) throws java.io.FileNotFoundException;
method public final java.io.OutputStream openOutputStream(android.net.Uri) throws java.io.FileNotFoundException;
method public final java.io.OutputStream openOutputStream(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);

View File

@@ -299,7 +299,7 @@ package android.bluetooth {
package android.content {
public abstract class ContentResolver {
public abstract class ContentResolver implements android.content.ContentInterface {
method public static java.lang.String[] getSyncAdapterPackagesForAuthorityAsUser(java.lang.String, int);
}

View File

@@ -557,7 +557,7 @@ public class Content {
@Override
public void onExecute(IContentProvider provider) throws Exception {
Bundle result = provider.call(null, mMethod, mArg, mExtras);
Bundle result = provider.call(null, mUri.getAuthority(), mMethod, mArg, mExtras);
if (result != null) {
result.size(); // unpack
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import java.io.FileNotFoundException;
import java.util.ArrayList;
/**
* Interface representing calls that can be made to {@link ContentProvider}
* instances.
* <p>
* These methods have been extracted into a general interface so that APIs can
* be flexible in accepting either a {@link ContentProvider}, a
* {@link ContentResolver}, or a {@link ContentProviderClient}.
*/
public interface ContentInterface {
public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
throws RemoteException;
public @Nullable String getType(@NonNull Uri uri) throws RemoteException;
public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter)
throws RemoteException;
public @Nullable Uri canonicalize(@NonNull Uri uri) throws RemoteException;
public @Nullable Uri uncanonicalize(@NonNull Uri uri) throws RemoteException;
public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
@Nullable CancellationSignal cancellationSignal) throws RemoteException;
public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
throws RemoteException;
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] initialValues)
throws RemoteException;
public int delete(@NonNull Uri uri, @Nullable String selection,
@Nullable String[] selectionArgs) throws RemoteException;
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
@Nullable String[] selectionArgs) throws RemoteException;
public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
@NonNull String mimeTypeFilter, @Nullable Bundle opts,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
@NonNull ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException;
public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException;
}

View File

@@ -105,7 +105,7 @@ import java.util.Objects;
* developer guide.</p>
* </div>
*/
public abstract class ContentProvider implements ComponentCallbacks2 {
public abstract class ContentProvider implements ContentInterface, ComponentCallbacks2 {
private static final String TAG = "ContentProvider";
@@ -324,7 +324,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
@Override
public ContentProviderResult[] applyBatch(String callingPkg,
public ContentProviderResult[] applyBatch(String callingPkg, String authority,
ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
int numOperations = operations.size();
@@ -356,7 +356,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
final String original = setCallingPackage(callingPkg);
try {
ContentProviderResult[] results = ContentProvider.this.applyBatch(operations);
ContentProviderResult[] results = ContentProvider.this.applyBatch(authority,
operations);
if (results != null) {
for (int i = 0; i < results.length ; i++) {
if (userIds[i] != UserHandle.USER_CURRENT) {
@@ -444,13 +445,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
@Override
public Bundle call(
String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras) {
public Bundle call(String callingPkg, String authority, String method, @Nullable String arg,
@Nullable Bundle extras) {
Bundle.setDefusable(extras, true);
Trace.traceBegin(TRACE_TAG_DATABASE, "call");
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.call(method, arg, extras);
return ContentProvider.this.call(authority, method, arg, extras);
} finally {
setCallingPackage(original);
Trace.traceEnd(TRACE_TAG_DATABASE);
@@ -1255,6 +1256,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* or {@code null}.
* @return a Cursor or {@code null}.
*/
@Override
public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) {
queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
@@ -1293,6 +1295,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @param uri the URI to query.
* @return a MIME type string, or {@code null} if there is no type.
*/
@Override
public abstract @Nullable String getType(@NonNull Uri uri);
/**
@@ -1325,6 +1328,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @return Return the canonical representation of <var>url</var>, or null if
* canonicalization of that Uri is not supported.
*/
@Override
public @Nullable Uri canonicalize(@NonNull Uri url) {
return null;
}
@@ -1343,6 +1347,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* the data identified by the canonical representation can not be found in
* the current environment.
*/
@Override
public @Nullable Uri uncanonicalize(@NonNull Uri url) {
return url;
}
@@ -1369,6 +1374,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* canceled the refresh request.
* @return true if the provider actually tried refreshing.
*/
@Override
public boolean refresh(Uri uri, @Nullable Bundle args,
@Nullable CancellationSignal cancellationSignal) {
return false;
@@ -1403,6 +1409,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* This must not be {@code null}.
* @return The URI for the newly inserted item.
*/
@Override
public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
/**
@@ -1420,6 +1427,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* This must not be {@code null}.
* @return The number of values that were inserted.
*/
@Override
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
int numValues = values.length;
for (int i = 0; i < numValues; i++) {
@@ -1448,6 +1456,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @return The number of rows affected.
* @throws SQLException
*/
@Override
public abstract int delete(@NonNull Uri uri, @Nullable String selection,
@Nullable String[] selectionArgs);
@@ -1468,6 +1477,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @param selection An optional filter to match rows to update.
* @return the number of rows affected.
*/
@Override
public abstract int update(@NonNull Uri uri, @Nullable ContentValues values,
@Nullable String selection, @Nullable String[] selectionArgs);
@@ -1604,6 +1614,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #getType(android.net.Uri)
* @see ParcelFileDescriptor#parseMode(String)
*/
@Override
public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws FileNotFoundException {
return openFile(uri, mode);
@@ -1723,6 +1734,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openFileHelper(Uri, String)
* @see #getType(android.net.Uri)
*/
@Override
public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws FileNotFoundException {
return openAssetFile(uri, mode);
@@ -1789,6 +1801,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openTypedAssetFile(Uri, String, Bundle)
* @see ClipDescription#compareMimeTypes(String, String)
*/
@Override
public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) {
return null;
}
@@ -1905,6 +1918,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openAssetFile(Uri, String)
* @see ClipDescription#compareMimeTypes(String, String)
*/
@Override
public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
@NonNull String mimeTypeFilter, @Nullable Bundle opts,
@Nullable CancellationSignal signal) throws FileNotFoundException {
@@ -2059,6 +2073,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @throws OperationApplicationException thrown if any operation fails.
* @see ContentProviderOperation#apply
*/
@Override
public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
@NonNull ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
return applyBatch(operations);
}
public @NonNull ContentProviderResult[] applyBatch(
@NonNull ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
@@ -2088,6 +2109,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @return provider-defined return value. May be {@code null}, which is also
* the default for providers which don't implement any call methods.
*/
@Override
public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
@Nullable String arg, @Nullable Bundle extras) {
return call(method, arg, extras);
}
public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
@Nullable Bundle extras) {
return null;
@@ -2133,6 +2160,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
writer.println("nothing to dump");
}
private void validateIncomingAuthority(String authority) throws SecurityException {
if (!matchesOurAuthorities(getAuthorityWithoutUserId(authority))) {
String message = "The authority " + authority + " does not match the one of the "
+ "contentProvider: ";
if (mAuthority != null) {
message += mAuthority;
} else {
message += Arrays.toString(mAuthorities);
}
throw new SecurityException(message);
}
}
/** @hide */
@VisibleForTesting
public Uri validateIncomingUri(Uri uri) throws SecurityException {
@@ -2144,16 +2184,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
+ mContext.getUserId() + " with a uri belonging to user " + userId);
}
}
if (!matchesOurAuthorities(getAuthorityWithoutUserId(auth))) {
String message = "The authority of the uri " + uri + " does not match the one of the "
+ "contentProvider: ";
if (mAuthority != null) {
message += mAuthority;
} else {
message += Arrays.toString(mAuthorities);
}
throw new SecurityException(message);
}
validateIncomingAuthority(auth);
// Normalize the path by removing any empty path segments, which can be
// a source of security issues.

View File

@@ -65,7 +65,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* on the ContentProviderClient those calls are made from until you are finished
* with the data they have returned.
*/
public class ContentProviderClient implements AutoCloseable {
public class ContentProviderClient implements ContentInterface, AutoCloseable {
private static final String TAG = "ContentProviderClient";
@GuardedBy("ContentProviderClient.class")
@@ -76,6 +76,7 @@ public class ContentProviderClient implements AutoCloseable {
private final IContentProvider mContentProvider;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final String mPackageName;
private final String mAuthority;
private final boolean mStable;
private final AtomicBoolean mClosed = new AtomicBoolean();
@@ -86,12 +87,20 @@ public class ContentProviderClient implements AutoCloseable {
/** {@hide} */
@VisibleForTesting
public ContentProviderClient(
ContentResolver contentResolver, IContentProvider contentProvider, boolean stable) {
public ContentProviderClient(ContentResolver contentResolver, IContentProvider contentProvider,
boolean stable) {
// Only used for testing, so use a fake authority
this(contentResolver, contentProvider, "unknown", stable);
}
/** {@hide} */
public ContentProviderClient(ContentResolver contentResolver, IContentProvider contentProvider,
String authority, boolean stable) {
mContentResolver = contentResolver;
mContentProvider = contentProvider;
mPackageName = contentResolver.mPackageName;
mAuthority = authority;
mStable = stable;
mCloseGuard.open("close");
@@ -153,6 +162,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#query ContentProvider.query} */
@Override
public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
throws RemoteException {
@@ -183,6 +193,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#getType ContentProvider.getType} */
@Override
public @Nullable String getType(@NonNull Uri url) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -200,6 +211,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
@Override
public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter)
throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -219,6 +231,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#canonicalize} */
@Override
public final @Nullable Uri canonicalize(@NonNull Uri url) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -236,6 +249,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#uncanonicalize} */
@Override
public final @Nullable Uri uncanonicalize(@NonNull Uri url) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -253,6 +267,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#refresh} */
@Override
public boolean refresh(Uri url, @Nullable Bundle args,
@Nullable CancellationSignal cancellationSignal) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -277,6 +292,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#insert ContentProvider.insert} */
@Override
public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -295,6 +311,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
@Override
public int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] initialValues)
throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -314,6 +331,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#delete ContentProvider.delete} */
@Override
public int delete(@NonNull Uri url, @Nullable String selection,
@Nullable String[] selectionArgs) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -332,6 +350,7 @@ public class ContentProviderClient implements AutoCloseable {
}
/** See {@link ContentProvider#update ContentProvider.update} */
@Override
public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable String selection,
@Nullable String[] selectionArgs) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -368,6 +387,7 @@ public class ContentProviderClient implements AutoCloseable {
* you use the {@link ContentResolver#openFileDescriptor
* ContentResolver.openFileDescriptor} API instead.
*/
@Override
public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Preconditions.checkNotNull(url, "url");
@@ -411,6 +431,7 @@ public class ContentProviderClient implements AutoCloseable {
* you use the {@link ContentResolver#openAssetFileDescriptor
* ContentResolver.openAssetFileDescriptor} API instead.
*/
@Override
public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Preconditions.checkNotNull(url, "url");
@@ -446,8 +467,15 @@ public class ContentProviderClient implements AutoCloseable {
public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
@NonNull String mimeType, @Nullable Bundle opts, @Nullable CancellationSignal signal)
throws RemoteException, FileNotFoundException {
return openTypedAssetFile(uri, mimeType, opts, signal);
}
@Override
public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
@NonNull String mimeTypeFilter, @Nullable Bundle opts,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Preconditions.checkNotNull(uri, "uri");
Preconditions.checkNotNull(mimeType, "mimeType");
Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
beforeRemote();
try {
@@ -458,7 +486,7 @@ public class ContentProviderClient implements AutoCloseable {
signal.setRemote(remoteSignal);
}
return mContentProvider.openTypedAssetFile(
mPackageName, uri, mimeType, opts, remoteSignal);
mPackageName, uri, mimeTypeFilter, opts, remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -472,12 +500,20 @@ public class ContentProviderClient implements AutoCloseable {
/** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
public @NonNull ContentProviderResult[] applyBatch(
@NonNull ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
throws RemoteException, OperationApplicationException {
return applyBatch(mAuthority, operations);
}
/** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
@Override
public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
@NonNull ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
Preconditions.checkNotNull(operations, "operations");
beforeRemote();
try {
return mContentProvider.applyBatch(mPackageName, operations);
return mContentProvider.applyBatch(mPackageName, authority, operations);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -491,11 +527,19 @@ public class ContentProviderClient implements AutoCloseable {
/** See {@link ContentProvider#call(String, String, Bundle)} */
public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
@Nullable Bundle extras) throws RemoteException {
return call(mAuthority, method, arg, extras);
}
/** See {@link ContentProvider#call(String, String, Bundle)} */
@Override
public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException {
Preconditions.checkNotNull(authority, "authority");
Preconditions.checkNotNull(method, "method");
beforeRemote();
try {
return mContentProvider.call(mPackageName, method, arg, extras);
return mContentProvider.call(mPackageName, authority, method, arg, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);

View File

@@ -174,13 +174,15 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
String authority = data.readString();
final int numOperations = data.readInt();
final ArrayList<ContentProviderOperation> operations =
new ArrayList<>(numOperations);
for (int i = 0; i < numOperations; i++) {
operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
}
final ContentProviderResult[] results = applyBatch(callingPkg, operations);
final ContentProviderResult[] results = applyBatch(callingPkg, authority,
operations);
reply.writeNoException();
reply.writeTypedArray(results, 0);
return true;
@@ -267,11 +269,12 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
String authority = data.readString();
String method = data.readString();
String stringArg = data.readString();
Bundle args = data.readBundle();
Bundle responseBundle = call(callingPkg, method, stringArg, args);
Bundle responseBundle = call(callingPkg, authority, method, stringArg, args);
reply.writeNoException();
reply.writeBundle(responseBundle);
@@ -507,7 +510,7 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
public ContentProviderResult[] applyBatch(String callingPkg,
public ContentProviderResult[] applyBatch(String callingPkg, String authority,
ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
Parcel data = Parcel.obtain();
@@ -515,6 +518,7 @@ final class ContentProviderProxy implements IContentProvider
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
data.writeString(authority);
data.writeInt(operations.size());
for (ContentProviderOperation operation : operations) {
operation.writeToParcel(data, 0);
@@ -636,14 +640,15 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
public Bundle call(String callingPkg, String method, String request, Bundle args)
throws RemoteException {
public Bundle call(String callingPkg, 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(authority);
data.writeString(method);
data.writeString(request);
data.writeBundle(args);

View File

@@ -52,7 +52,6 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.text.TextUtils;
@@ -88,7 +87,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
* developer guide.</p>
*/
public abstract class ContentResolver {
public abstract class ContentResolver implements ContentInterface {
/**
* Enables logic that supports deprecation of {@code _data} columns,
* typically by replacing values with fake paths that the OS then offers to
@@ -655,6 +654,7 @@ public abstract class ContentResolver {
* using the content:// scheme.
* @return A MIME type for the content, or null if the URL is invalid or the type is unknown
*/
@Override
public final @Nullable String getType(@NonNull Uri url) {
Preconditions.checkNotNull(url, "url");
@@ -708,6 +708,7 @@ public abstract class ContentResolver {
* data streams that match the given mimeTypeFilter. If there are none,
* null is returned.
*/
@Override
public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
Preconditions.checkNotNull(url, "url");
Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
@@ -835,6 +836,7 @@ public abstract class ContentResolver {
* @return A Cursor object, which is positioned before the first entry, or null
* @see Cursor
*/
@Override
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable CancellationSignal cancellationSignal) {
@@ -935,6 +937,7 @@ public abstract class ContentResolver {
*
* @see #uncanonicalize
*/
@Override
public final @Nullable Uri canonicalize(@NonNull Uri url) {
Preconditions.checkNotNull(url, "url");
IContentProvider provider = acquireProvider(url);
@@ -971,6 +974,7 @@ public abstract class ContentResolver {
*
* @see #canonicalize
*/
@Override
public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
Preconditions.checkNotNull(url, "url");
IContentProvider provider = acquireProvider(url);
@@ -1005,6 +1009,7 @@ public abstract class ContentResolver {
* canceled the refresh request.
* @return true if the provider actually tried refreshing.
*/
@Override
public final boolean refresh(@NonNull Uri url, @Nullable Bundle args,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(url, "url");
@@ -1116,6 +1121,12 @@ public abstract class ContentResolver {
}
}
@Override
public final @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws FileNotFoundException {
return openFileDescriptor(uri, mode, signal);
}
/**
* Open a raw file descriptor to access data under a URI. This
* is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
@@ -1221,6 +1232,12 @@ public abstract class ContentResolver {
throw new FileNotFoundException("Not a whole file");
}
@Override
public final @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws FileNotFoundException {
return openAssetFileDescriptor(uri, mode, signal);
}
/**
* Open a raw file descriptor to access data under a URI. This
* interacts with the underlying {@link ContentProvider#openAssetFile}
@@ -1425,6 +1442,13 @@ public abstract class ContentResolver {
}
}
@Override
public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
@NonNull String mimeTypeFilter, @Nullable Bundle opts,
@Nullable CancellationSignal signal) throws FileNotFoundException {
return openTypedAssetFileDescriptor(uri, mimeTypeFilter, opts, signal);
}
/**
* Open a raw file descriptor to access (potentially type transformed)
* data from a "content:" URI. This interacts with the underlying
@@ -1634,6 +1658,7 @@ public abstract class ContentResolver {
* the field. Passing an empty ContentValues will create an empty row.
* @return the URL of the newly created row.
*/
@Override
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
@Nullable ContentValues values) {
Preconditions.checkNotNull(url, "url");
@@ -1672,6 +1697,7 @@ public abstract class ContentResolver {
* @throws RemoteException thrown if a RemoteException is encountered while attempting
* to communicate with a remote provider.
*/
@Override
public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
@NonNull ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
@@ -1698,6 +1724,7 @@ public abstract class ContentResolver {
* the field. Passing null will create an empty row.
* @return the number of newly created rows.
*/
@Override
public final int bulkInsert(@RequiresPermission.Write @NonNull Uri url,
@NonNull ContentValues[] values) {
Preconditions.checkNotNull(url, "url");
@@ -1731,6 +1758,7 @@ public abstract class ContentResolver {
(excluding the WHERE itself).
* @return The number of rows deleted.
*/
@Override
public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where,
@Nullable String[] selectionArgs) {
Preconditions.checkNotNull(url, "url");
@@ -1766,6 +1794,7 @@ public abstract class ContentResolver {
* @return the number of rows updated.
* @throws NullPointerException if uri or values are null
*/
@Override
public final int update(@RequiresPermission.Write @NonNull Uri uri,
@Nullable ContentValues values, @Nullable String where,
@Nullable String[] selectionArgs) {
@@ -1805,14 +1834,20 @@ public abstract class ContentResolver {
*/
public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
@Nullable String arg, @Nullable Bundle extras) {
Preconditions.checkNotNull(uri, "uri");
return call(uri.getAuthority(), method, arg, extras);
}
@Override
public final @Nullable Bundle call(@NonNull String authority, @NonNull String method,
@Nullable String arg, @Nullable Bundle extras) {
Preconditions.checkNotNull(authority, "authority");
Preconditions.checkNotNull(method, "method");
IContentProvider provider = acquireProvider(uri);
IContentProvider provider = acquireProvider(authority);
if (provider == null) {
throw new IllegalArgumentException("Unknown URI " + uri);
throw new IllegalArgumentException("Unknown authority " + authority);
}
try {
final Bundle res = provider.call(mPackageName, method, arg, extras);
final Bundle res = provider.call(mPackageName, authority, method, arg, extras);
Bundle.setDefusable(res, true);
return res;
} catch (RemoteException e) {
@@ -1918,7 +1953,7 @@ public abstract class ContentResolver {
Preconditions.checkNotNull(uri, "uri");
IContentProvider provider = acquireProvider(uri);
if (provider != null) {
return new ContentProviderClient(this, provider, true);
return new ContentProviderClient(this, provider, uri.getAuthority(), true);
}
return null;
}
@@ -1939,7 +1974,7 @@ public abstract class ContentResolver {
Preconditions.checkNotNull(name, "name");
IContentProvider provider = acquireProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, true);
return new ContentProviderClient(this, provider, name, true);
}
return null;
@@ -1966,7 +2001,7 @@ public abstract class ContentResolver {
Preconditions.checkNotNull(uri, "uri");
IContentProvider provider = acquireUnstableProvider(uri);
if (provider != null) {
return new ContentProviderClient(this, provider, false);
return new ContentProviderClient(this, provider, uri.getAuthority(), false);
}
return null;
@@ -1993,7 +2028,7 @@ public abstract class ContentResolver {
Preconditions.checkNotNull(name, "name");
IContentProvider provider = acquireUnstableProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, false);
return new ContentProviderClient(this, provider, name, false);
}
return null;

View File

@@ -60,13 +60,28 @@ public interface IContentProvider extends IInterface {
public AssetFileDescriptor openAssetFile(
String callingPkg, Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException;
public ContentProviderResult[] applyBatch(String callingPkg,
@Deprecated
public default ContentProviderResult[] applyBatch(String callingPkg,
ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException;
throws RemoteException, OperationApplicationException {
return applyBatch(callingPkg, "unknown", operations);
}
public ContentProviderResult[] applyBatch(String callingPkg, String authority,
ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException;
@Deprecated
@UnsupportedAppUsage
public Bundle call(
String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras)
throws RemoteException;
public default Bundle call(String callingPkg, String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException {
return call(callingPkg, "unknown", method, arg, extras);
}
public Bundle call(String callingPkg, String authority, String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException;
public ICancellationSignal createCancellationSignal() throws RemoteException;
public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException;

View File

@@ -2055,7 +2055,8 @@ public final class Settings {
arg.putBoolean(CALL_METHOD_MAKE_DEFAULT_KEY, true);
}
IContentProvider cp = mProviderHolder.getProvider(cr);
cp.call(cr.getPackageName(), mCallSetCommand, name, arg);
cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
mCallSetCommand, name, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
return false;
@@ -2128,12 +2129,14 @@ public final class Settings {
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
mCallGetCommand, name, args);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
mCallGetCommand, name, args);
}
if (b != null) {
String value = b.getString(Settings.NameValueTable.VALUE);
@@ -5123,7 +5126,8 @@ public final class Settings {
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
cp.call(resolver.getPackageName(), CALL_METHOD_RESET_SECURE, null, arg);
cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
CALL_METHOD_RESET_SECURE, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
}
@@ -13158,7 +13162,8 @@ public final class Settings {
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
cp.call(resolver.getPackageName(), CALL_METHOD_RESET_GLOBAL, null, arg);
cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
CALL_METHOD_RESET_GLOBAL, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
}
@@ -13953,7 +13958,8 @@ public final class Settings {
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, RESET_MODE_PACKAGE_DEFAULTS);
IContentProvider cp = sProviderHolder.getProvider(resolver);
cp.call(resolver.getPackageName(), CALL_METHOD_RESET_CONFIG, null, arg);
cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
CALL_METHOD_RESET_CONFIG, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset to defaults for " + CONTENT_URI, e);
}

View File

@@ -363,7 +363,8 @@ public class TileUtils {
return null;
}
try {
return provider.call(context.getPackageName(), method, uriString, null);
return provider.call(context.getPackageName(), uri.getAuthority(),
method, uriString, null);
} catch (RemoteException e) {
return null;
}

View File

@@ -309,8 +309,8 @@ final public class SettingsService extends Binder {
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
Bundle result =
provider.call(resolveCallingPackage(), callListCommand, null, arg);
Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
callListCommand, null, arg);
lines.addAll(result.getStringArrayList(SettingsProvider.RESULT_SETTINGS_LIST));
Collections.sort(lines);
} catch (RemoteException e) {
@@ -334,7 +334,8 @@ final public class SettingsService extends Binder {
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
Bundle b = provider.call(resolveCallingPackage(), callGetCommand, key, arg);
Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
callGetCommand, key, arg);
if (b != null) {
result = b.getPairValue();
}
@@ -371,7 +372,8 @@ final public class SettingsService extends Binder {
if (makeDefault) {
arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
}
provider.call(resolveCallingPackage(), callPutCommand, key, arg);
provider.call(resolveCallingPackage(), Settings.AUTHORITY,
callPutCommand, key, arg);
} catch (RemoteException e) {
throw new RuntimeException("Failed in IPC", e);
}
@@ -394,8 +396,8 @@ final public class SettingsService extends Binder {
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
Bundle result =
provider.call(resolveCallingPackage(), callDeleteCommand, key, arg);
Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
callDeleteCommand, key, arg);
return result.getInt(SettingsProvider.RESULT_ROWS_DELETED);
} catch (RemoteException e) {
throw new RuntimeException("Failed in IPC", e);
@@ -421,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, callResetCommand, null, arg);
provider.call(packageName, Settings.AUTHORITY, callResetCommand, null, arg);
} catch (RemoteException e) {
throw new RuntimeException("Failed in IPC", e);
}

View File

@@ -106,8 +106,8 @@ public class PinnedSliceStateTest extends UiServiceTestCase {
mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
TestableLooper.get(this).processAllMessages();
verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null),
argThat(b -> {
verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN),
eq(null), argThat(b -> {
assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
return true;
}));

View File

@@ -54,10 +54,10 @@ public class MockContentProvider extends ContentProvider {
*/
private class InversionIContentProvider implements IContentProvider {
@Override
public ContentProviderResult[] applyBatch(String callingPackage,
public ContentProviderResult[] applyBatch(String callingPackage, String authority,
ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
return MockContentProvider.this.applyBatch(operations);
return MockContentProvider.this.applyBatch(authority, operations);
}
@Override
@@ -112,9 +112,9 @@ public class MockContentProvider extends ContentProvider {
}
@Override
public Bundle call(String callingPackage, String method, String request, Bundle args)
throws RemoteException {
return MockContentProvider.this.call(method, request, args);
public Bundle call(String callingPackage, String authority, String method, String request,
Bundle args) throws RemoteException {
return MockContentProvider.this.call(authority, method, request, args);
}
@Override

View File

@@ -80,7 +80,7 @@ public class MockIContentProvider implements IContentProvider {
}
@Override
public ContentProviderResult[] applyBatch(String callingPackage,
public ContentProviderResult[] applyBatch(String callingPackage, String authority,
ArrayList<ContentProviderOperation> operations) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -103,8 +103,8 @@ public class MockIContentProvider implements IContentProvider {
}
@Override
public Bundle call(String callingPackage, String method, String request, Bundle args)
throws RemoteException {
public Bundle call(String callingPackage, String authority, String method, String request,
Bundle args) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}