summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2019-11-15 12:45:15 -0700
committerJeff Sharkey <jsharkey@android.com>2019-11-15 13:46:31 -0700
commite9fe152f317bbce0bce63b657468867f0fc1f4a4 (patch)
treeec405d03c37c9795b18bfa87b5e91ca7ae6f940d
parentb500cb85ff779bd564f68d0a293bbf6b74f05b7b (diff)
Extend insert/update/delete to provide extras.
A few releases ago we added ContentResolver.QUERY_ARG_* constants to query() as a new best-practice that will help wean us off raw SQL arguments. (For example, a provider could add their own custom arguments like QUERY_ARG_INCLUDE_PENDING to cause the query to reveal pending items that would otherwise be hidden.) This change expands update() and delete() to accept those arguments. This change also expand insert() to accept extras too, as part of preparing to support an upcoming MediaProvider feature that will let apps place new media "adjacent" to an existing media item. (Sending that adjacent item through extras is cleaner than trying to send it through escaped query parameters.) Bug: 131643582 Test: atest CtsContentTestCases Change-Id: I436296155b9b5f371b4cbe661feaf42070285fcc
-rw-r--r--api/current.txt9
-rw-r--r--cmds/content/src/com/android/commands/content/Content.java8
-rw-r--r--core/java/android/content/ContentInterface.java13
-rw-r--r--core/java/android/content/ContentProvider.java193
-rw-r--r--core/java/android/content/ContentProviderClient.java35
-rw-r--r--core/java/android/content/ContentProviderNative.java45
-rw-r--r--core/java/android/content/ContentResolver.java109
-rw-r--r--core/java/android/content/IContentProvider.java20
-rw-r--r--core/java/android/content/LoggingContentInterface.java23
-rw-r--r--test-mock/src/android/test/mock/MockContentProvider.java13
-rw-r--r--test-mock/src/android/test/mock/MockIContentProvider.java6
11 files changed, 321 insertions, 153 deletions
diff --git a/api/current.txt b/api/current.txt
index 667f5d2f1d60..b0e2acbf6219 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9475,6 +9475,7 @@ package android.content {
method @Nullable public android.net.Uri canonicalize(@NonNull android.net.Uri);
method @NonNull public final android.content.ContentProvider.CallingIdentity clearCallingIdentity();
method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]);
+ method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle);
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
method @Nullable public final String getCallingFeatureId();
method @Nullable public final String getCallingPackage();
@@ -9485,6 +9486,7 @@ package android.content {
method @Nullable public abstract String getType(@NonNull android.net.Uri);
method @Nullable public final String getWritePermission();
method @Nullable public abstract android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues);
+ method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
method protected boolean isTemporary();
method public void onConfigurationChanged(android.content.res.Configuration);
method public abstract boolean onCreate();
@@ -9510,6 +9512,7 @@ package android.content {
method public void shutdown();
method @Nullable public android.net.Uri uncanonicalize(@NonNull android.net.Uri);
method public abstract int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
+ method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
}
public final class ContentProvider.CallingIdentity {
@@ -9528,10 +9531,12 @@ package android.content {
method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
method public void close();
method public int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
+ method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle) throws android.os.RemoteException;
method @Nullable public android.content.ContentProvider getLocalContentProvider();
method @Nullable public String[] getStreamTypes(@NonNull android.net.Uri, @NonNull String) throws android.os.RemoteException;
method @Nullable public String getType(@NonNull android.net.Uri) throws android.os.RemoteException;
method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues) throws android.os.RemoteException;
+ method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle) throws android.os.RemoteException;
method @Nullable public android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException, android.os.RemoteException;
method @Nullable public android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method @Nullable public android.os.ParcelFileDescriptor openFile(@NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException, android.os.RemoteException;
@@ -9546,6 +9551,7 @@ package android.content {
method @Deprecated public boolean release();
method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
+ method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle) throws android.os.RemoteException;
}
public class ContentProviderOperation implements android.os.Parcelable {
@@ -9633,6 +9639,7 @@ package android.content {
method public static void cancelSync(android.content.SyncRequest);
method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri);
method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable String, @Nullable String[]);
+ method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.os.Bundle);
method @Deprecated public static android.content.SyncInfo getCurrentSync();
method public static java.util.List<android.content.SyncInfo> getCurrentSyncs();
method public static int getIsSyncable(android.accounts.Account, String);
@@ -9646,6 +9653,7 @@ package android.content {
method @Nullable public final String getType(@NonNull android.net.Uri);
method @NonNull public final android.content.ContentResolver.MimeTypeInfo getTypeInfo(@NonNull String);
method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues);
+ method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
method public static boolean isSyncActive(android.accounts.Account, String);
method public static boolean isSyncPending(android.accounts.Account, String);
method @NonNull public android.graphics.Bitmap loadThumbnail(@NonNull android.net.Uri, @NonNull android.util.Size, @Nullable android.os.CancellationSignal) throws java.io.IOException;
@@ -9683,6 +9691,7 @@ package android.content {
method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri);
method public final void unregisterContentObserver(@NonNull android.database.ContentObserver);
method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
+ method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
method public static void validateSyncExtrasBundle(android.os.Bundle);
method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider);
method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient);
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 7e278e964ab5..59544a971e5f 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(), null, mUri, mContentValues);
+ provider.insert(resolveCallingPackage(), null, mUri, mContentValues, null);
}
}
@@ -522,7 +522,8 @@ public class Content {
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.delete(resolveCallingPackage(), null, mUri, mWhere, null);
+ provider.delete(resolveCallingPackage(), null, mUri,
+ ContentResolver.createSqlQueryBundle(mWhere, null));
}
}
@@ -679,7 +680,8 @@ public class Content {
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.update(resolveCallingPackage(), null, mUri, mContentValues, mWhere, null);
+ provider.update(resolveCallingPackage(), null, mUri, mContentValues,
+ ContentResolver.createSqlQueryBundle(mWhere, null));
}
}
diff --git a/core/java/android/content/ContentInterface.java b/core/java/android/content/ContentInterface.java
index 197de9711296..5988dd3914f1 100644
--- a/core/java/android/content/ContentInterface.java
+++ b/core/java/android/content/ContentInterface.java
@@ -53,23 +53,22 @@ public interface ContentInterface {
public @Nullable Uri uncanonicalize(@NonNull Uri uri) throws RemoteException;
- public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
+ public boolean refresh(@NonNull Uri uri, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) throws RemoteException;
public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
throws RemoteException;
- public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
- throws RemoteException;
+ public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues,
+ @Nullable Bundle extras) 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 delete(@NonNull Uri uri, @Nullable Bundle extras) throws RemoteException;
- public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
- @Nullable String[] selectionArgs) throws RemoteException;
+ public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)
+ throws RemoteException;
public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 17f1a07d6e01..2240823ebe92 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -299,7 +299,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
@Override
public Uri insert(String callingPkg, @Nullable String featureId, Uri uri,
- ContentValues initialValues) {
+ ContentValues initialValues, Bundle extras) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = maybeGetUriWithoutUserId(uri);
@@ -317,7 +317,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return maybeAddUserId(mInterface.insert(uri, initialValues), userId);
+ return maybeAddUserId(mInterface.insert(uri, initialValues, extras), userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -403,8 +403,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
@Override
- public int delete(String callingPkg, @Nullable String featureId, Uri uri, String selection,
- String[] selectionArgs) {
+ public int delete(String callingPkg, @Nullable String featureId, Uri uri, Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, featureId, uri, null)
@@ -415,7 +414,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return mInterface.delete(uri, selection, selectionArgs);
+ return mInterface.delete(uri, extras);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -426,7 +425,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
@Override
public int update(String callingPkg, @Nullable String featureId, Uri uri,
- ContentValues values, String selection, String[] selectionArgs) {
+ ContentValues values, Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, featureId, uri, null)
@@ -437,7 +436,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return mInterface.update(uri, values, selection, selectionArgs);
+ return mInterface.update(uri, values, extras);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -593,7 +592,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
@Override
- public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle args,
+ public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle extras,
ICancellationSignal cancellationSignal) throws RemoteException {
uri = validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
@@ -605,7 +604,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return mInterface.refresh(uri, args,
+ return mInterface.refresh(uri, extras,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
setCallingPackage(original);
@@ -1494,29 +1493,34 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
/**
- * Implement this to support refresh of content identified by {@code uri}. By default, this
- * method returns false; providers who wish to implement this should return true to signal the
- * client that the provider has tried refreshing with its own implementation.
+ * Implement this to support refresh of content identified by {@code uri}.
+ * By default, this method returns false; providers who wish to implement
+ * this should return true to signal the client that the provider has tried
+ * refreshing with its own implementation.
* <p>
- * This allows clients to request an explicit refresh of content identified by {@code uri}.
+ * This allows clients to request an explicit refresh of content identified
+ * by {@code uri}.
* <p>
- * Client code should only invoke this method when there is a strong indication (such as a user
- * initiated pull to refresh gesture) that the content is stale.
+ * Client code should only invoke this method when there is a strong
+ * indication (such as a user initiated pull to refresh gesture) that the
+ * content is stale.
* <p>
- * Remember to send {@link ContentResolver#notifyChange(Uri, android.database.ContentObserver)}
+ * Remember to send
+ * {@link ContentResolver#notifyChange(Uri, android.database.ContentObserver)}
* notifications when content changes.
*
* @param uri The Uri identifying the data to refresh.
- * @param args Additional options from the client. The definitions of these are specific to the
- * content provider being called.
- * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if
- * none. For example, if you called refresh on a particular uri, you should call
- * {@link CancellationSignal#throwIfCanceled()} to check whether the client has
- * canceled the refresh request.
+ * @param extras Additional options from the client. The definitions of
+ * these are specific to the content provider being called.
+ * @param cancellationSignal A signal to cancel the operation in progress,
+ * or {@code null} if none. For example, if you called refresh on
+ * a particular uri, you should call
+ * {@link CancellationSignal#throwIfCanceled()} to check whether
+ * the client has canceled the refresh request.
* @return true if the provider actually tried refreshing.
*/
@Override
- public boolean refresh(Uri uri, @Nullable Bundle args,
+ public boolean refresh(Uri uri, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) {
return false;
}
@@ -1545,20 +1549,42 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
/**
- * Implement this to handle requests to insert a new row.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after inserting.
- * This method can be called from multiple threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * Implement this to handle requests to insert a new row. As a courtesy,
+ * call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after inserting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
+ *
* @param uri The content:// URI of the insertion request.
* @param values A set of column_name/value pairs to add to the database.
* @return The URI for the newly inserted item.
*/
- @Override
public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
/**
+ * Implement this to handle requests to insert a new row. As a courtesy,
+ * call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after inserting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * and Threads</a>.
+ *
+ * @param uri The content:// URI of the insertion request.
+ * @param values A set of column_name/value pairs to add to the database.
+ * @param extras A Bundle containing all additional information necessary
+ * for the insert.
+ * @return The URI for the newly inserted item.
+ */
+ @Override
+ public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values,
+ @Nullable Bundle extras) {
+ return insert(uri, values);
+ }
+
+ /**
* Override this to handle requests to insert a set of new rows, or the
* default implementation will iterate over the values and call
* {@link #insert} on each of them.
@@ -1583,50 +1609,111 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
/**
- * Implement this to handle requests to delete one or more rows.
- * The implementation should apply the selection clause when performing
+ * Implement this to handle requests to delete one or more rows. The
+ * implementation should apply the selection clause when performing
* deletion, allowing the operation to affect multiple rows in a directory.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after deleting.
- * This method can be called from multiple threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after deleting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
- *
- * <p>The implementation is responsible for parsing out a row ID at the end
- * of the URI, if a specific row is being deleted. That is, the client would
- * pass in <code>content://contacts/people/22</code> and the implementation is
- * responsible for parsing the record number (22) when creating a SQL statement.
- *
- * @param uri The full URI to query, including a row ID (if a specific record is requested).
+ * <p>
+ * The implementation is responsible for parsing out a row ID at the end of
+ * the URI, if a specific row is being deleted. That is, the client would
+ * pass in <code>content://contacts/people/22</code> and the implementation
+ * is responsible for parsing the record number (22) when creating a SQL
+ * statement.
+ *
+ * @param uri The full URI to query, including a row ID (if a specific
+ * record is requested).
* @param selection An optional restriction to apply to rows when deleting.
* @return The number of rows affected.
* @throws SQLException
*/
- @Override
public abstract int delete(@NonNull Uri uri, @Nullable String selection,
@Nullable String[] selectionArgs);
/**
- * Implement this to handle requests to update one or more rows.
- * The implementation should update all rows matching the selection
- * to set the columns according to the provided values map.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after updating.
- * This method can be called from multiple threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * Implement this to handle requests to delete one or more rows. The
+ * implementation should apply the selection clause when performing
+ * deletion, allowing the operation to affect multiple rows in a directory.
+ * As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after deleting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * and Threads</a>.
+ * <p>
+ * The implementation is responsible for parsing out a row ID at the end of
+ * the URI, if a specific row is being deleted. That is, the client would
+ * pass in <code>content://contacts/people/22</code> and the implementation
+ * is responsible for parsing the record number (22) when creating a SQL
+ * statement.
+ *
+ * @param uri The full URI to query, including a row ID (if a specific
+ * record is requested).
+ * @param extras A Bundle containing all additional information necessary
+ * for the delete. Values in the Bundle may include SQL style
+ * arguments.
+ * @return The number of rows affected.
+ * @throws SQLException
+ */
+ @Override
+ public int delete(@NonNull Uri uri, @Nullable Bundle extras) {
+ extras = (extras != null) ? extras : Bundle.EMPTY;
+ return delete(uri,
+ extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION),
+ extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS));
+ }
+
+ /**
+ * Implement this to handle requests to update one or more rows. The
+ * implementation should update all rows matching the selection to set the
+ * columns according to the provided values map. As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after updating. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
*
- * @param uri The URI to query. This can potentially have a record ID if this
- * is an update request for a specific record.
+ * @param uri The URI to query. This can potentially have a record ID if
+ * this is an update request for a specific record.
* @param values A set of column_name/value pairs to update in the database.
* @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);
/**
+ * Implement this to handle requests to update one or more rows. The
+ * implementation should update all rows matching the selection to set the
+ * columns according to the provided values map. As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after updating. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * and Threads</a>.
+ *
+ * @param uri The URI to query. This can potentially have a record ID if
+ * this is an update request for a specific record.
+ * @param values A set of column_name/value pairs to update in the database.
+ * @param extras A Bundle containing all additional information necessary
+ * for the update. Values in the Bundle may include SQL style
+ * arguments.
+ * @return the number of rows affected.
+ */
+ @Override
+ public int update(@NonNull Uri uri, @Nullable ContentValues values,
+ @Nullable Bundle extras) {
+ extras = (extras != null) ? extras : Bundle.EMPTY;
+ return update(uri, values,
+ extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION),
+ extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS));
+ }
+
+ /**
* Override this to handle requests to open a file blob.
* The default implementation always throws {@link FileNotFoundException}.
* This method can be called from multiple threads, as described in
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index d2632e78c00c..bb65aa013f72 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -286,7 +286,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
/** See {@link ContentProvider#refresh} */
@Override
- public boolean refresh(Uri url, @Nullable Bundle args,
+ public boolean refresh(Uri url, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -298,7 +298,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return mContentProvider.refresh(mPackageName, mFeatureId, url, args,
+ return mContentProvider.refresh(mPackageName, mFeatureId, url, extras,
remoteCancellationSignal);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -331,14 +331,20 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
}
/** See {@link ContentProvider#insert ContentProvider.insert} */
- @Override
public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
throws RemoteException {
+ return insert(url, initialValues, null);
+ }
+
+ /** See {@link ContentProvider#insert ContentProvider.insert} */
+ @Override
+ public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues,
+ @Nullable Bundle extras) throws RemoteException {
Preconditions.checkNotNull(url, "url");
beforeRemote();
try {
- return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues);
+ return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -370,15 +376,19 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
}
/** See {@link ContentProvider#delete ContentProvider.delete} */
- @Override
public int delete(@NonNull Uri url, @Nullable String selection,
@Nullable String[] selectionArgs) throws RemoteException {
+ return delete(url, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+ }
+
+ /** See {@link ContentProvider#delete ContentProvider.delete} */
+ @Override
+ public int delete(@NonNull Uri url, @Nullable Bundle extras) throws RemoteException {
Preconditions.checkNotNull(url, "url");
beforeRemote();
try {
- return mContentProvider.delete(mPackageName, mFeatureId, url, selection,
- selectionArgs);
+ return mContentProvider.delete(mPackageName, mFeatureId, url, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -390,15 +400,20 @@ public class ContentProviderClient implements ContentInterface, 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 {
+ return update(url, values, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+ }
+
+ /** See {@link ContentProvider#update ContentProvider.update} */
+ @Override
+ public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable Bundle extras)
+ throws RemoteException {
Preconditions.checkNotNull(url, "url");
beforeRemote();
try {
- return mContentProvider.update(mPackageName, mFeatureId, url, values, selection,
- selectionArgs);
+ return mContentProvider.update(mPackageName, mFeatureId, url, values, 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 f082690e2ceb..dfa71f88fa0a 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -153,8 +153,9 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
+ Bundle extras = data.readBundle();
- Uri out = insert(callingPkg, featureId, url, values);
+ Uri out = insert(callingPkg, featureId, url, values, extras);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -199,10 +200,9 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
String callingPkg = data.readString();
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
+ Bundle extras = data.readBundle();
- int count = delete(callingPkg, featureId, url, selection, selectionArgs);
+ int count = delete(callingPkg, featureId, url, extras);
reply.writeNoException();
reply.writeInt(count);
@@ -216,11 +216,9 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
+ Bundle extras = data.readBundle();
- int count = update(callingPkg, featureId, url, values, selection,
- selectionArgs);
+ int count = update(callingPkg, featureId, url, values, extras);
reply.writeNoException();
reply.writeInt(count);
@@ -283,10 +281,10 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
String authority = data.readString();
String method = data.readString();
String stringArg = data.readString();
- Bundle args = data.readBundle();
+ Bundle extras = data.readBundle();
Bundle responseBundle = call(callingPkg, featureId, authority, method,
- stringArg, args);
+ stringArg, extras);
reply.writeNoException();
reply.writeBundle(responseBundle);
@@ -370,11 +368,11 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
String callingPkg = data.readString();
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
- Bundle args = data.readBundle();
+ Bundle extras = data.readBundle();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- boolean out = refresh(callingPkg, featureId, url, args, signal);
+ boolean out = refresh(callingPkg, featureId, url, extras, signal);
reply.writeNoException();
reply.writeInt(out ? 0 : -1);
return true;
@@ -498,7 +496,7 @@ final class ContentProviderProxy implements IContentProvider
@Override
public Uri insert(String callingPkg, @Nullable String featureId, Uri url,
- ContentValues values) throws RemoteException
+ ContentValues values, Bundle extras) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -509,6 +507,7 @@ final class ContentProviderProxy implements IContentProvider
data.writeString(featureId);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
@@ -573,8 +572,8 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
- public int delete(String callingPkg, @Nullable String featureId, Uri url, String selection,
- String[] selectionArgs) throws RemoteException {
+ public int delete(String callingPkg, @Nullable String featureId, Uri url, Bundle extras)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
@@ -583,8 +582,7 @@ final class ContentProviderProxy implements IContentProvider
data.writeString(callingPkg);
data.writeString(featureId);
url.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
@@ -599,7 +597,7 @@ final class ContentProviderProxy implements IContentProvider
@Override
public int update(String callingPkg, @Nullable String featureId, Uri url,
- ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
+ ContentValues values, Bundle extras) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
@@ -609,8 +607,7 @@ final class ContentProviderProxy implements IContentProvider
data.writeString(featureId);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
@@ -682,7 +679,7 @@ final class ContentProviderProxy implements IContentProvider
@Override
public Bundle call(String callingPkg, @Nullable String featureId, String authority,
- String method, String request, Bundle args) throws RemoteException {
+ String method, String request, Bundle extras) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
@@ -693,7 +690,7 @@ final class ContentProviderProxy implements IContentProvider
data.writeString(authority);
data.writeString(method);
data.writeString(request);
- data.writeBundle(args);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
@@ -824,7 +821,7 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
- public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
+ public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle extras,
ICancellationSignal signal) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -834,7 +831,7 @@ final class ContentProviderProxy implements IContentProvider
data.writeString(callingPkg);
data.writeString(featureId);
url.writeToParcel(data, 0);
- data.writeBundle(args);
+ data.writeBundle(extras);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
mRemote.transact(IContentProvider.REFRESH_TRANSACTION, data, reply, 0);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index a93c6d25c38f..d4280f8992c2 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1181,28 +1181,31 @@ public abstract class ContentResolver implements ContentInterface {
}
/**
- * This allows clients to request an explicit refresh of content identified by {@code uri}.
+ * This allows clients to request an explicit refresh of content identified
+ * by {@code uri}.
* <p>
- * Client code should only invoke this method when there is a strong indication (such as a user
- * initiated pull to refresh gesture) that the content is stale.
+ * Client code should only invoke this method when there is a strong
+ * indication (such as a user initiated pull to refresh gesture) that the
+ * content is stale.
* <p>
*
* @param url The Uri identifying the data to refresh.
- * @param args Additional options from the client. The definitions of these are specific to the
- * content provider being called.
- * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if
- * none. For example, if you called refresh on a particular uri, you should call
- * {@link CancellationSignal#throwIfCanceled()} to check whether the client has
- * canceled the refresh request.
+ * @param extras Additional options from the client. The definitions of
+ * these are specific to the content provider being called.
+ * @param cancellationSignal A signal to cancel the operation in progress,
+ * or {@code null} if none. For example, if you called refresh on
+ * a particular uri, you should call
+ * {@link CancellationSignal#throwIfCanceled()} to check whether
+ * the client has canceled the refresh request.
* @return true if the provider actually tried refreshing.
*/
@Override
- public final boolean refresh(@NonNull Uri url, @Nullable Bundle args,
+ public final boolean refresh(@NonNull Uri url, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(url, "url");
try {
- if (mWrapped != null) return mWrapped.refresh(url, args, cancellationSignal);
+ if (mWrapped != null) return mWrapped.refresh(url, extras, cancellationSignal);
} catch (RemoteException e) {
return false;
}
@@ -1219,7 +1222,7 @@ public abstract class ContentResolver implements ContentInterface {
remoteCancellationSignal = provider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return provider.refresh(mPackageName, mFeatureId, url, args,
+ return provider.refresh(mPackageName, mFeatureId, url, extras,
remoteCancellationSignal);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -1910,13 +1913,30 @@ public abstract class ContentResolver implements ContentInterface {
* @return the URL of the newly created row. May return <code>null</code> if the underlying
* content provider returns <code>null</code>, or if it crashes.
*/
- @Override
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
@Nullable ContentValues values) {
+ return insert(url, values, null);
+ }
+
+ /**
+ * Inserts a row into a table at the given URL.
+ *
+ * If the content provider supports transactions the insertion will be atomic.
+ *
+ * @param url The URL of the table to insert into.
+ * @param values The initial values for the newly inserted row. The key is the column name for
+ * the field. Passing an empty ContentValues will create an empty row.
+ * @param extras A Bundle containing all additional information necessary for the insert.
+ * @return the URL of the newly created row. May return <code>null</code> if the underlying
+ * content provider returns <code>null</code>, or if it crashes.
+ */
+ @Override
+ public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
+ @Nullable ContentValues values, @Nullable Bundle extras) {
Preconditions.checkNotNull(url, "url");
try {
- if (mWrapped != null) return mWrapped.insert(url, values);
+ if (mWrapped != null) return mWrapped.insert(url, values, extras);
} catch (RemoteException e) {
return null;
}
@@ -1927,7 +1947,7 @@ public abstract class ContentResolver implements ContentInterface {
}
try {
long startTime = SystemClock.uptimeMillis();
- Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values);
+ Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
return createdRow;
@@ -2031,13 +2051,27 @@ public abstract class ContentResolver implements ContentInterface {
(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) {
+ return delete(url, createSqlQueryBundle(where, selectionArgs));
+ }
+
+ /**
+ * Deletes row(s) specified by a content URI.
+ *
+ * If the content provider supports transactions, the deletion will be atomic.
+ *
+ * @param url The URL of the row to delete.
+ * @param extras A Bundle containing all additional information necessary for the delete.
+ * Values in the Bundle may include SQL style arguments.
+ * @return The number of rows deleted.
+ */
+ @Override
+ public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) {
Preconditions.checkNotNull(url, "url");
try {
- if (mWrapped != null) return mWrapped.delete(url, where, selectionArgs);
+ if (mWrapped != null) return mWrapped.delete(url, extras);
} catch (RemoteException e) {
return 0;
}
@@ -2048,10 +2082,9 @@ public abstract class ContentResolver implements ContentInterface {
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, where,
- selectionArgs);
+ int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
- maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
+ maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
return rowsDeleted;
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -2075,14 +2108,32 @@ public abstract class ContentResolver implements ContentInterface {
* @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) {
+ return update(uri, values, createSqlQueryBundle(where, selectionArgs));
+ }
+
+ /**
+ * Update row(s) in a content URI.
+ *
+ * If the content provider supports transactions the update will be atomic.
+ *
+ * @param uri The URI to modify.
+ * @param values The new field values. The key is the column name for the field.
+ A null value will remove an existing field value.
+ * @param extras A Bundle containing all additional information necessary for the update.
+ * Values in the Bundle may include SQL style arguments.
+ * @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 Bundle extras) {
Preconditions.checkNotNull(uri, "uri");
try {
- if (mWrapped != null) return mWrapped.update(uri, values, where, selectionArgs);
+ if (mWrapped != null) return mWrapped.update(uri, values, extras);
} catch (RemoteException e) {
return 0;
}
@@ -2093,10 +2144,9 @@ public abstract class ContentResolver implements ContentInterface {
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, where,
- selectionArgs);
+ int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
- maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
+ maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
return rowsUpdated;
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -3643,6 +3693,15 @@ public abstract class ContentResolver implements ContentInterface {
*/
public static @Nullable Bundle createSqlQueryBundle(
@Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ return createSqlQueryBundle(selection, selectionArgs, null);
+ }
+
+ /**
+ * @hide
+ */
+ public static @Nullable Bundle createSqlQueryBundle(
+ @Nullable String selection,
@Nullable String[] selectionArgs,
@Nullable String sortOrder) {
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index d2c97c4ebdd3..1fb29586e15b 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -48,10 +48,10 @@ public interface IContentProvider extends IInterface {
+ "instead")
public default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
throws RemoteException {
- return insert(callingPkg, null, url, initialValues);
+ return insert(callingPkg, null, url, initialValues, null);
}
- public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues)
- throws RemoteException;
+ public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues,
+ Bundle extras) throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])"
@@ -68,20 +68,22 @@ public interface IContentProvider extends IInterface {
+ ".String[])} instead")
public default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
throws RemoteException {
- return delete(callingPkg, null, url, selection, selectionArgs);
+ return delete(callingPkg, null, url,
+ ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
- public int delete(String callingPkg, String featureId, Uri url, String selection,
- String[] selectionArgs) throws RemoteException;
+ public int delete(String callingPkg, String featureId, Uri url, Bundle extras)
+ throws RemoteException;
@Deprecated
@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);
+ return update(callingPkg, null, url, values,
+ ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
public int update(String callingPkg, String featureId, Uri url, ContentValues values,
- String selection, String[] selectionArgs) throws RemoteException;
+ Bundle extras) throws RemoteException;
public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
String mode, ICancellationSignal signal, IBinder callerToken)
@@ -119,7 +121,7 @@ public interface IContentProvider extends IInterface {
throws RemoteException;
public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
- @Nullable Bundle args, ICancellationSignal cancellationSignal) throws RemoteException;
+ @Nullable Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException;
// Data interchange.
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
diff --git a/core/java/android/content/LoggingContentInterface.java b/core/java/android/content/LoggingContentInterface.java
index 1df1c4faf2fe..3bd083268d45 100644
--- a/core/java/android/content/LoggingContentInterface.java
+++ b/core/java/android/content/LoggingContentInterface.java
@@ -178,11 +178,11 @@ public class LoggingContentInterface implements ContentInterface {
}
@Override
- public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
- throws RemoteException {
- try (Logger l = new Logger("insert", uri, initialValues)) {
+ public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues,
+ @Nullable Bundle extras) throws RemoteException {
+ try (Logger l = new Logger("insert", uri, initialValues, extras)) {
try {
- return l.setResult(delegate.insert(uri, initialValues));
+ return l.setResult(delegate.insert(uri, initialValues, extras));
} catch (Exception res) {
l.setResult(res);
throw res;
@@ -204,11 +204,10 @@ public class LoggingContentInterface implements ContentInterface {
}
@Override
- public int delete(@NonNull Uri uri, @Nullable String selection,
- @Nullable String[] selectionArgs) throws RemoteException {
- try (Logger l = new Logger("delete", uri, selection, selectionArgs)) {
+ public int delete(@NonNull Uri uri, @Nullable Bundle extras) throws RemoteException {
+ try (Logger l = new Logger("delete", uri, extras)) {
try {
- return l.setResult(delegate.delete(uri, selection, selectionArgs));
+ return l.setResult(delegate.delete(uri, extras));
} catch (Exception res) {
l.setResult(res);
throw res;
@@ -217,11 +216,11 @@ public class LoggingContentInterface implements ContentInterface {
}
@Override
- public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
- @Nullable String[] selectionArgs) throws RemoteException {
- try (Logger l = new Logger("update", uri, values, selection, selectionArgs)) {
+ public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)
+ throws RemoteException {
+ try (Logger l = new Logger("update", uri, values, extras)) {
try {
- return l.setResult(delegate.update(uri, values, selection, selectionArgs));
+ return l.setResult(delegate.update(uri, values, extras));
} catch (Exception res) {
l.setResult(res);
throw res;
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index 9d3e12050193..85e5916a63df 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -71,8 +71,8 @@ public class MockContentProvider extends ContentProvider {
@Override
public int delete(String callingPackage, @Nullable String featureId, Uri url,
- String selection, String[] selectionArgs) throws RemoteException {
- return MockContentProvider.this.delete(url, selection, selectionArgs);
+ Bundle extras) throws RemoteException {
+ return MockContentProvider.this.delete(url, extras);
}
@Override
@@ -82,8 +82,8 @@ public class MockContentProvider extends ContentProvider {
@Override
public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
- ContentValues initialValues) throws RemoteException {
- return MockContentProvider.this.insert(url, initialValues);
+ ContentValues initialValues, Bundle extras) throws RemoteException {
+ return MockContentProvider.this.insert(url, initialValues, extras);
}
@Override
@@ -109,9 +109,8 @@ public class MockContentProvider extends ContentProvider {
@Override
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);
+ ContentValues values, Bundle extras) throws RemoteException {
+ return MockContentProvider.this.update(url, values, extras);
}
@Override
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index e512b52643f3..464abfb1a514 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -51,7 +51,7 @@ public class MockIContentProvider implements IContentProvider {
@Override
@SuppressWarnings("unused")
public int delete(String callingPackage, @Nullable String featureId, Uri url,
- String selection, String[] selectionArgs) throws RemoteException {
+ Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -63,7 +63,7 @@ public class MockIContentProvider implements IContentProvider {
@Override
@SuppressWarnings("unused")
public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
- ContentValues initialValues) throws RemoteException {
+ ContentValues initialValues, Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -99,7 +99,7 @@ public class MockIContentProvider implements IContentProvider {
@Override
public int update(String callingPackage, @Nullable String featureId, Uri url,
- ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
+ ContentValues values, Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}