Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fa31f69 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

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
parent 847e6761
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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";
+2 −0
Original line number Diff line number Diff line
@@ -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 {
+99 −3
Original line number Diff line number Diff line
@@ -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";