Introduce QUERY_ARG_MATCH_* values for filtering.
The existing strategy of methods like setIncludePending() doesn't scale well for callers to use multiple matching strategies. For example, callers are interested in these matching strategies: MATCH_EXCLUDE: Ensure that any matches are excluded. MATCH_INCLUDE: Ensure that any matches are included. MATCH_ONLY: Return only exact matches. The reason why we have this menu of options is because the underlying fields have different default behavior. For example, "trashed" items are naturally excluded by default, but "favorite" items are naturally included by default. Callers only interesting in listing "trashed" items or "favorite" items shouldn't need to perform their own inefficient Cursor diffing logic, so we give them these flexible arguments. Adjust MediaProvider internals to apply these matcher values to all update() and delete() calls, in addition to query(). Bug: 143432502 Test: atest --test-mapping packages/providers/MediaProvider Change-Id: I0d4bc063b8ea5ac2a602fab43a62c2de7724ba34
This commit is contained in:
@@ -38591,15 +38591,13 @@ package android.provider {
|
||||
ctor public MediaStore();
|
||||
method @Nullable public static android.net.Uri getDocumentUri(@NonNull android.content.Context, @NonNull android.net.Uri);
|
||||
method @NonNull public static java.util.Set<java.lang.String> getExternalVolumeNames(@NonNull android.content.Context);
|
||||
method public static boolean getIncludePending(@NonNull android.net.Uri);
|
||||
method public static android.net.Uri getMediaScannerUri();
|
||||
method @Nullable public static android.net.Uri getMediaUri(@NonNull android.content.Context, @NonNull android.net.Uri);
|
||||
method public static boolean getRequireOriginal(@NonNull android.net.Uri);
|
||||
method @NonNull public static String getVersion(@NonNull android.content.Context);
|
||||
method @NonNull public static String getVersion(@NonNull android.content.Context, @NonNull String);
|
||||
method @NonNull public static String getVolumeName(@NonNull android.net.Uri);
|
||||
method @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
|
||||
method @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
|
||||
method @Deprecated @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
|
||||
method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri);
|
||||
method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
|
||||
method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
|
||||
@@ -38635,9 +38633,16 @@ package android.provider {
|
||||
field public static final String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH = "android.media.action.TEXT_OPEN_FROM_SEARCH";
|
||||
field public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
|
||||
field public static final String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
|
||||
field public static final int MATCH_DEFAULT = 0; // 0x0
|
||||
field public static final int MATCH_EXCLUDE = 2; // 0x2
|
||||
field public static final int MATCH_INCLUDE = 1; // 0x1
|
||||
field public static final int MATCH_ONLY = 3; // 0x3
|
||||
field public static final String MEDIA_IGNORE_FILENAME = ".nomedia";
|
||||
field public static final String MEDIA_SCANNER_VOLUME = "volume";
|
||||
field public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service";
|
||||
field public static final String QUERY_ARG_MATCH_FAVORITE = "android:query-arg-match-favorite";
|
||||
field public static final String QUERY_ARG_MATCH_PENDING = "android:query-arg-match-pending";
|
||||
field public static final String QUERY_ARG_MATCH_TRASHED = "android:query-arg-match-trashed";
|
||||
field public static final String UNKNOWN_STRING = "<unknown>";
|
||||
field public static final String VOLUME_EXTERNAL = "external";
|
||||
field public static final String VOLUME_EXTERNAL_PRIMARY = "external_primary";
|
||||
|
||||
@@ -438,7 +438,9 @@ package android.provider {
|
||||
public final class MediaStore {
|
||||
method @Deprecated @NonNull public static android.net.Uri createPending(@NonNull android.content.Context, @NonNull android.provider.MediaStore.PendingParams);
|
||||
method @Deprecated @NonNull public static java.util.Set<java.lang.String> getAllVolumeNames(@NonNull android.content.Context);
|
||||
method @Deprecated public static boolean getIncludePending(@NonNull android.net.Uri);
|
||||
method @Deprecated @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri);
|
||||
method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
|
||||
}
|
||||
|
||||
public static interface MediaStore.Audio.AudioColumns extends android.provider.MediaStore.MediaColumns {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.BytesLong;
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.CurrentTimeSecondsLong;
|
||||
import android.annotation.DurationMillisLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -78,6 +79,8 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -205,8 +208,10 @@ public final class MediaStore {
|
||||
public static final String PARAM_DELETE_DATA = "deletedata";
|
||||
|
||||
/** {@hide} */
|
||||
@Deprecated
|
||||
public static final String PARAM_INCLUDE_PENDING = "includePending";
|
||||
/** {@hide} */
|
||||
@Deprecated
|
||||
public static final String PARAM_INCLUDE_TRASHED = "includeTrashed";
|
||||
/** {@hide} */
|
||||
public static final String PARAM_PROGRESS = "progress";
|
||||
@@ -558,6 +563,84 @@ public final class MediaStore {
|
||||
*/
|
||||
public static final String UNKNOWN_STRING = "<unknown>";
|
||||
|
||||
/**
|
||||
* Specify how {@link MediaColumns#IS_PENDING} items should be filtered when
|
||||
* performing a {@link MediaStore} operation.
|
||||
* <p>
|
||||
* This key can be placed in a {@link Bundle} of extras and passed to
|
||||
* {@link ContentResolver#query}, {@link ContentResolver#update}, or
|
||||
* {@link ContentResolver#delete}.
|
||||
* <p>
|
||||
* By default, pending items are filtered away from operations.
|
||||
*/
|
||||
@Match
|
||||
public static final String QUERY_ARG_MATCH_PENDING = "android:query-arg-match-pending";
|
||||
|
||||
/**
|
||||
* Specify how {@link MediaColumns#IS_TRASHED} items should be filtered when
|
||||
* performing a {@link MediaStore} operation.
|
||||
* <p>
|
||||
* This key can be placed in a {@link Bundle} of extras and passed to
|
||||
* {@link ContentResolver#query}, {@link ContentResolver#update}, or
|
||||
* {@link ContentResolver#delete}.
|
||||
* <p>
|
||||
* By default, trashed items are filtered away from operations.
|
||||
*/
|
||||
@Match
|
||||
public static final String QUERY_ARG_MATCH_TRASHED = "android:query-arg-match-trashed";
|
||||
|
||||
/**
|
||||
* Specify how {@link MediaColumns#IS_FAVORITE} items should be filtered
|
||||
* when performing a {@link MediaStore} operation.
|
||||
* <p>
|
||||
* This key can be placed in a {@link Bundle} of extras and passed to
|
||||
* {@link ContentResolver#query}, {@link ContentResolver#update}, or
|
||||
* {@link ContentResolver#delete}.
|
||||
* <p>
|
||||
* By default, favorite items are <em>not</em> filtered away from
|
||||
* operations.
|
||||
*/
|
||||
@Match
|
||||
public static final String QUERY_ARG_MATCH_FAVORITE = "android:query-arg-match-favorite";
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = true, prefix = { "MATCH_" }, value = {
|
||||
MATCH_DEFAULT,
|
||||
MATCH_INCLUDE,
|
||||
MATCH_EXCLUDE,
|
||||
MATCH_ONLY,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Match {}
|
||||
|
||||
/**
|
||||
* Value indicating that the default matching behavior should be used, as
|
||||
* defined by the key documentation.
|
||||
*/
|
||||
public static final int MATCH_DEFAULT = 0;
|
||||
|
||||
/**
|
||||
* Value indicating that operations should include items matching the
|
||||
* criteria defined by this key.
|
||||
* <p>
|
||||
* Note that items <em>not</em> matching the criteria <em>may</em> also be
|
||||
* included depending on the default behavior documented by the key. If you
|
||||
* want to operate exclusively on matching items, use {@link #MATCH_ONLY}.
|
||||
*/
|
||||
public static final int MATCH_INCLUDE = 1;
|
||||
|
||||
/**
|
||||
* Value indicating that operations should exclude items matching the
|
||||
* criteria defined by this key.
|
||||
*/
|
||||
public static final int MATCH_EXCLUDE = 2;
|
||||
|
||||
/**
|
||||
* Value indicating that operations should only operate on items explicitly
|
||||
* matching the criteria defined by this key.
|
||||
*/
|
||||
public static final int MATCH_ONLY = 3;
|
||||
|
||||
/**
|
||||
* Update the given {@link Uri} to also include any pending media items from
|
||||
* calls such as
|
||||
@@ -566,12 +649,16 @@ public final class MediaStore {
|
||||
*
|
||||
* @see MediaColumns#IS_PENDING
|
||||
* @see MediaStore#getIncludePending(Uri)
|
||||
* @deprecated consider migrating to {@link #QUERY_ARG_MATCH_PENDING} which
|
||||
* is more expressive.
|
||||
*/
|
||||
@Deprecated
|
||||
public static @NonNull Uri setIncludePending(@NonNull Uri uri) {
|
||||
return setIncludePending(uri.buildUpon()).build();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Deprecated
|
||||
public static @NonNull Uri.Builder setIncludePending(@NonNull Uri.Builder uriBuilder) {
|
||||
return uriBuilder.appendQueryParameter(PARAM_INCLUDE_PENDING, "1");
|
||||
}
|
||||
@@ -582,7 +669,11 @@ public final class MediaStore {
|
||||
*
|
||||
* @see MediaColumns#IS_PENDING
|
||||
* @see MediaStore#setIncludePending(Uri)
|
||||
* @deprecated consider migrating to {@link #QUERY_ARG_MATCH_PENDING} which
|
||||
* is more expressive.
|
||||
* @removed
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean getIncludePending(@NonNull Uri uri) {
|
||||
return parseBoolean(uri.getQueryParameter(MediaStore.PARAM_INCLUDE_PENDING));
|
||||
}
|
||||
@@ -597,7 +688,11 @@ public final class MediaStore {
|
||||
* @see MediaStore#setIncludeTrashed(Uri)
|
||||
* @see MediaStore#trash(Context, Uri)
|
||||
* @see MediaStore#untrash(Context, Uri)
|
||||
* @deprecated consider migrating to {@link #QUERY_ARG_MATCH_TRASHED} which
|
||||
* is more expressive.
|
||||
* @removed
|
||||
*/
|
||||
@Deprecated
|
||||
public static @NonNull Uri setIncludeTrashed(@NonNull Uri uri) {
|
||||
return uri.buildUpon().appendQueryParameter(PARAM_INCLUDE_TRASHED, "1").build();
|
||||
}
|
||||
@@ -1000,7 +1095,7 @@ public final class MediaStore {
|
||||
* the field to {@code 0}, or until they expire as defined by
|
||||
* {@link #DATE_EXPIRES}.
|
||||
*
|
||||
* @see MediaStore#setIncludePending(Uri)
|
||||
* @see MediaStore#QUERY_ARG_MATCH_PENDING
|
||||
*/
|
||||
@Column(Cursor.FIELD_TYPE_INTEGER)
|
||||
public static final String IS_PENDING = "is_pending";
|
||||
@@ -1011,8 +1106,7 @@ public final class MediaStore {
|
||||
* Trashed items are retained until they expire as defined by
|
||||
* {@link #DATE_EXPIRES}.
|
||||
*
|
||||
* @see MediaColumns#IS_TRASHED
|
||||
* @see MediaStore#setIncludeTrashed(Uri)
|
||||
* @see MediaStore#QUERY_ARG_MATCH_TRASHED
|
||||
* @see MediaStore#trash(Context, Uri)
|
||||
* @see MediaStore#untrash(Context, Uri)
|
||||
*/
|
||||
@@ -1186,6 +1280,8 @@ public final class MediaStore {
|
||||
/**
|
||||
* Flag indicating if the media item has been marked as being a
|
||||
* "favorite" by the user.
|
||||
*
|
||||
* @see MediaStore#QUERY_ARG_MATCH_FAVORITE
|
||||
*/
|
||||
@Column(Cursor.FIELD_TYPE_INTEGER)
|
||||
public static final String IS_FAVORITE = "is_favorite";
|
||||
|
||||
Reference in New Issue
Block a user