Merge "Move MediaStore.java inside APEX boundary."
diff --git a/Android.bp b/Android.bp
index bf901ec..eef9f80 100644
--- a/Android.bp
+++ b/Android.bp
@@ -265,6 +265,7 @@
         ":framework-sdkext-sources",
         ":framework-statsd-sources",
         ":updatable-media-srcs",
+        ":framework-mediaprovider-sources",
         ":framework-wifi-updatable-sources",
     ]
 }
@@ -380,6 +381,7 @@
         "ext",
         "unsupportedappusage",
         "updatable_media_stubs",
+        "framework_mediaprovider_stubs",
     ],
 
     jarjar_rules: ":framework-jarjar-rules",
@@ -468,6 +470,7 @@
     static_libs: [
         "framework-minus-apex",
         "updatable_media_stubs",
+        "framework_mediaprovider_stubs",
         "framework-appsearch", // TODO(b/146218515): should be framework-appsearch-stubs
         "framework-sdkext-stubs-systemapi",
         // TODO(b/146167933): Use framework-statsd-stubs instead.
@@ -583,11 +586,14 @@
 filegroup {
     name: "framework-annotations",
     srcs: [
-        "core/java/android/annotation/NonNull.java",
-        "core/java/android/annotation/Nullable.java",
         "core/java/android/annotation/IntDef.java",
         "core/java/android/annotation/IntRange.java",
+        "core/java/android/annotation/NonNull.java",
+        "core/java/android/annotation/Nullable.java",
+        "core/java/android/annotation/RequiresPermission.java",
+        "core/java/android/annotation/SdkConstant.java",
         "core/java/android/annotation/SystemApi.java",
+        "core/java/android/annotation/TestApi.java",
         "core/java/android/annotation/UnsupportedAppUsage.java",
         "core/java/com/android/internal/annotations/GuardedBy.java",
         "core/java/com/android/internal/annotations/VisibleForTesting.java",
@@ -1648,20 +1654,23 @@
 filegroup {
     name: "framework-media-annotation-srcs",
     srcs: [
+        ":framework-annotations",
         "core/java/android/annotation/CallbackExecutor.java",
         "core/java/android/annotation/CallSuper.java",
         "core/java/android/annotation/DrawableRes.java",
-        "core/java/android/annotation/IntDef.java",
         "core/java/android/annotation/LongDef.java",
-        "core/java/android/annotation/NonNull.java",
-        "core/java/android/annotation/Nullable.java",
-        "core/java/android/annotation/RequiresPermission.java",
-        "core/java/android/annotation/SdkConstant.java",
         "core/java/android/annotation/StringDef.java",
-        "core/java/android/annotation/SystemApi.java",
-        "core/java/android/annotation/TestApi.java",
-        "core/java/android/annotation/UnsupportedAppUsage.java",
-        "core/java/com/android/internal/annotations/GuardedBy.java",
+    ],
+}
+
+filegroup {
+    name: "framework-mediaprovider-annotation-sources",
+    srcs: [
+        ":framework-annotations",
+        "core/java/android/annotation/BytesLong.java",
+        "core/java/android/annotation/CurrentTimeMillisLong.java",
+        "core/java/android/annotation/CurrentTimeSecondsLong.java",
+        "core/java/android/annotation/DurationMillisLong.java",
     ],
 }
 
diff --git a/api/current.txt b/api/current.txt
index fe97b29..31857a2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39063,6 +39063,8 @@
     field public static final String GENRE = "genre";
     field public static final String HEIGHT = "height";
     field public static final String INSTANCE_ID = "instance_id";
+    field public static final String IS_DOWNLOAD = "is_download";
+    field public static final String IS_DRM = "is_drm";
     field public static final String IS_FAVORITE = "is_favorite";
     field public static final String IS_PENDING = "is_pending";
     field public static final String IS_TRASHED = "is_trashed";
diff --git a/api/system-current.txt b/api/system-current.txt
index 4964d2b..8a147bb 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7295,8 +7295,12 @@
   }
 
   public final class MediaStore {
+    method @NonNull public static android.net.Uri rewriteToLegacy(@NonNull android.net.Uri);
     method @NonNull public static android.net.Uri scanFile(@NonNull android.content.ContentResolver, @NonNull java.io.File);
     method public static void scanVolume(@NonNull android.content.ContentResolver, @NonNull String);
+    method public static void waitForIdle(@NonNull android.content.ContentResolver);
+    field public static final String AUTHORITY_LEGACY = "media_legacy";
+    field @NonNull public static final android.net.Uri AUTHORITY_LEGACY_URI;
   }
 
   public abstract class SearchIndexableData {
diff --git a/core/java/android/provider/Column.java b/core/java/android/provider/Column.java
deleted file mode 100644
index 1364fb8..0000000
--- a/core/java/android/provider/Column.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 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.provider;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Denotes that a field is a {@link ContentProvider} column. It can be used as a
- * key for {@link ContentValues} when inserting or updating data, or as a
- * projection when querying.
- *
- * @hide
- */
-@Documented
-@Retention(RUNTIME)
-@Target({FIELD})
-public @interface Column {
-    /**
-     * The {@link Cursor#getType(int)} of the data stored in this column.
-     */
-    int value();
-
-    /**
-     * This column is read-only and cannot be defined during insert or updates.
-     */
-    boolean readOnly() default false;
-}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
deleted file mode 100644
index 63204d3..0000000
--- a/core/java/android/provider/MediaStore.java
+++ /dev/null
@@ -1,3832 +0,0 @@
-/*
- * Copyright (C) 2007 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.provider;
-
-import android.annotation.BytesLong;
-import android.annotation.CurrentTimeMillisLong;
-import android.annotation.CurrentTimeSecondsLong;
-import android.annotation.DurationMillisLong;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.content.ClipData;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.UriPermission;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageDecoder;
-import android.graphics.PostProcessor;
-import android.media.ExifInterface;
-import android.media.MediaFormat;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.Environment;
-import android.os.OperationCanceledException;
-import android.os.RemoteException;
-import android.os.storage.StorageManager;
-import android.os.storage.StorageVolume;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.Size;
-
-import libcore.util.HexEncoding;
-
-import java.io.File;
-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;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-/**
- * The contract between the media provider and applications. Contains
- * definitions for the supported URIs and columns.
- * <p>
- * The media provider provides an indexed collection of common media types, such
- * as {@link Audio}, {@link Video}, and {@link Images}, from any attached
- * storage devices. Each collection is organized based on the primary MIME type
- * of the underlying content; for example, {@code image/*} content is indexed
- * under {@link Images}. The {@link Files} collection provides a broad view
- * across all collections, and does not filter by MIME type.
- */
-public final class MediaStore {
-    private final static String TAG = "MediaStore";
-
-    /** The authority for the media provider */
-    public static final String AUTHORITY = "media";
-    /** A content:// style uri to the authority for the media provider */
-    public static final @NonNull Uri AUTHORITY_URI =
-            Uri.parse("content://" + AUTHORITY);
-
-    /** @hide */
-    public static final String AUTHORITY_LEGACY = "media_legacy";
-    /** @hide */
-    public static final @NonNull Uri AUTHORITY_LEGACY_URI =
-            Uri.parse("content://" + AUTHORITY_LEGACY);
-
-    /**
-     * Synthetic volume name that provides a view of all content across the
-     * "internal" storage of the device.
-     * <p>
-     * This synthetic volume provides a merged view of all media distributed
-     * with the device, such as built-in ringtones and wallpapers.
-     * <p>
-     * Because this is a synthetic volume, you can't insert new content into
-     * this volume.
-     */
-    public static final String VOLUME_INTERNAL = "internal";
-
-    /**
-     * Synthetic volume name that provides a view of all content across the
-     * "external" storage of the device.
-     * <p>
-     * This synthetic volume provides a merged view of all media across all
-     * currently attached external storage devices.
-     * <p>
-     * Because this is a synthetic volume, you can't insert new content into
-     * this volume. Instead, you can insert content into a specific storage
-     * volume obtained from {@link #getExternalVolumeNames(Context)}.
-     */
-    public static final String VOLUME_EXTERNAL = "external";
-
-    /**
-     * Specific volume name that represents the primary external storage device
-     * at {@link Environment#getExternalStorageDirectory()}.
-     * <p>
-     * This volume may not always be available, such as when the user has
-     * ejected the device. You can find a list of all specific volume names
-     * using {@link #getExternalVolumeNames(Context)}.
-     */
-    public static final String VOLUME_EXTERNAL_PRIMARY = "external_primary";
-
-    /** {@hide} */
-    public static final String WAIT_FOR_IDLE_CALL = "wait_for_idle";
-    /** {@hide} */
-    public static final String SCAN_FILE_CALL = "scan_file";
-    /** {@hide} */
-    public static final String SCAN_VOLUME_CALL = "scan_volume";
-    /** {@hide} */
-    public static final String CREATE_WRITE_REQUEST_CALL = "create_write_request";
-    /** {@hide} */
-    public static final String CREATE_TRASH_REQUEST_CALL = "create_trash_request";
-    /** {@hide} */
-    public static final String CREATE_FAVORITE_REQUEST_CALL = "create_favorite_request";
-    /** {@hide} */
-    public static final String CREATE_DELETE_REQUEST_CALL = "create_delete_request";
-
-
-    /** {@hide} */
-    public static final String GET_VERSION_CALL = "get_version";
-
-    /** {@hide} */
-    public static final String GET_DOCUMENT_URI_CALL = "get_document_uri";
-    /** {@hide} */
-    public static final String GET_MEDIA_URI_CALL = "get_media_uri";
-
-    /** {@hide} */
-    public static final String EXTRA_URI = "uri";
-    /** {@hide} */
-    public static final String EXTRA_URI_PERMISSIONS = "uriPermissions";
-
-    /** {@hide} */
-    public static final String EXTRA_CLIP_DATA = "clip_data";
-    /** {@hide} */
-    public static final String EXTRA_CONTENT_VALUES = "content_values";
-    /** {@hide} */
-    public static final String EXTRA_RESULT = "result";
-
-    /**
-     * This is for internal use by the media scanner only.
-     * Name of the (optional) Uri parameter that determines whether to skip deleting
-     * the file pointed to by the _data column, when deleting the database entry.
-     * The only appropriate value for this parameter is "false", in which case the
-     * delete will be skipped. Note especially that setting this to true, or omitting
-     * the parameter altogether, will perform the default action, which is different
-     * for different types of media.
-     * @hide
-     */
-    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";
-    /** {@hide} */
-    public static final String PARAM_REQUIRE_ORIGINAL = "requireOriginal";
-    /** {@hide} */
-    public static final String PARAM_LIMIT = "limit";
-
-    /**
-     * Activity Action: Launch a music player.
-     * The activity should be able to play, browse, or manipulate music files stored on the device.
-     *
-     * @deprecated Use {@link android.content.Intent#CATEGORY_APP_MUSIC} instead.
-     */
-    @Deprecated
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
-
-    /**
-     * Activity Action: Perform a search for media.
-     * Contains at least the {@link android.app.SearchManager#QUERY} extra.
-     * May also contain any combination of the following extras:
-     * EXTRA_MEDIA_ARTIST, EXTRA_MEDIA_ALBUM, EXTRA_MEDIA_TITLE, EXTRA_MEDIA_FOCUS
-     *
-     * @see android.provider.MediaStore#EXTRA_MEDIA_ARTIST
-     * @see android.provider.MediaStore#EXTRA_MEDIA_ALBUM
-     * @see android.provider.MediaStore#EXTRA_MEDIA_TITLE
-     * @see android.provider.MediaStore#EXTRA_MEDIA_FOCUS
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
-
-    /**
-     * An intent to perform a search for music media and automatically play content from the
-     * result when possible. This can be fired, for example, by the result of a voice recognition
-     * command to listen to music.
-     * <p>This intent always includes the {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS}
-     * and {@link android.app.SearchManager#QUERY} extras. The
-     * {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS} extra determines the search mode, and
-     * the value of the {@link android.app.SearchManager#QUERY} extra depends on the search mode.
-     * For more information about the search modes for this intent, see
-     * <a href="{@docRoot}guide/components/intents-common.html#PlaySearch">Play music based
-     * on a search query</a> in <a href="{@docRoot}guide/components/intents-common.html">Common
-     * Intents</a>.</p>
-     *
-     * <p>This intent makes the most sense for apps that can support large-scale search of music,
-     * such as services connected to an online database of music which can be streamed and played
-     * on the device.</p>
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
-            "android.media.action.MEDIA_PLAY_FROM_SEARCH";
-
-    /**
-     * An intent to perform a search for readable media and automatically play content from the
-     * result when possible. This can be fired, for example, by the result of a voice recognition
-     * command to read a book or magazine.
-     * <p>
-     * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
-     * contain any type of unstructured text search, like the name of a book or magazine, an author
-     * a genre, a publisher, or any combination of these.
-     * <p>
-     * Because this intent includes an open-ended unstructured search string, it makes the most
-     * sense for apps that can support large-scale search of text media, such as services connected
-     * to an online database of books and/or magazines which can be read on the device.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH =
-            "android.media.action.TEXT_OPEN_FROM_SEARCH";
-
-    /**
-     * An intent to perform a search for video media and automatically play content from the
-     * result when possible. This can be fired, for example, by the result of a voice recognition
-     * command to play movies.
-     * <p>
-     * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
-     * contain any type of unstructured video search, like the name of a movie, one or more actors,
-     * a genre, or any combination of these.
-     * <p>
-     * Because this intent includes an open-ended unstructured search string, it makes the most
-     * sense for apps that can support large-scale search of video, such as services connected to an
-     * online database of videos which can be streamed and played on the device.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH =
-            "android.media.action.VIDEO_PLAY_FROM_SEARCH";
-
-    /**
-     * The name of the Intent-extra used to define the artist
-     */
-    public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
-    /**
-     * The name of the Intent-extra used to define the album
-     */
-    public static final String EXTRA_MEDIA_ALBUM = "android.intent.extra.album";
-    /**
-     * The name of the Intent-extra used to define the song title
-     */
-    public static final String EXTRA_MEDIA_TITLE = "android.intent.extra.title";
-    /**
-     * The name of the Intent-extra used to define the genre.
-     */
-    public static final String EXTRA_MEDIA_GENRE = "android.intent.extra.genre";
-    /**
-     * The name of the Intent-extra used to define the playlist.
-     */
-    public static final String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist";
-    /**
-     * The name of the Intent-extra used to define the radio channel.
-     */
-    public static final String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel";
-    /**
-     * The name of the Intent-extra used to define the search focus. The search focus
-     * indicates whether the search should be for things related to the artist, album
-     * or song that is identified by the other extras.
-     */
-    public static final String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus";
-
-    /**
-     * The name of the Intent-extra used to control the orientation of a ViewImage or a MovieView.
-     * This is an int property that overrides the activity's requestedOrientation.
-     * @see android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED
-     */
-    public static final String EXTRA_SCREEN_ORIENTATION = "android.intent.extra.screenOrientation";
-
-    /**
-     * The name of an Intent-extra used to control the UI of a ViewImage.
-     * This is a boolean property that overrides the activity's default fullscreen state.
-     */
-    public static final String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen";
-
-    /**
-     * The name of an Intent-extra used to control the UI of a ViewImage.
-     * This is a boolean property that specifies whether or not to show action icons.
-     */
-    public static final String EXTRA_SHOW_ACTION_ICONS = "android.intent.extra.showActionIcons";
-
-    /**
-     * The name of the Intent-extra used to control the onCompletion behavior of a MovieView.
-     * This is a boolean property that specifies whether or not to finish the MovieView activity
-     * when the movie completes playing. The default value is true, which means to automatically
-     * exit the movie player activity when the movie completes playing.
-     */
-    public static final String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion";
-
-    /**
-     * The name of the Intent action used to launch a camera in still image mode.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
-
-    /**
-     * Name under which an activity handling {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
-     * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE} publishes the service name for its prewarm
-     * service.
-     * <p>
-     * This meta-data should reference the fully qualified class name of the prewarm service
-     * extending {@code CameraPrewarmService}.
-     * <p>
-     * The prewarm service will get bound and receive a prewarm signal
-     * {@code CameraPrewarmService#onPrewarm()} when a camera launch intent fire might be imminent.
-     * An application implementing a prewarm service should do the absolute minimum amount of work
-     * to initialize the camera in order to reduce startup time in likely case that shortly after a
-     * camera launch intent would be sent.
-     */
-    public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE =
-            "android.media.still_image_camera_preview_service";
-
-    /**
-     * The name of the Intent action used to launch a camera in still image mode
-     * for use when the device is secured (e.g. with a pin, password, pattern,
-     * or face unlock). Applications responding to this intent must not expose
-     * any personal content like existing photos or videos on the device. The
-     * applications should be careful not to share any photo or video with other
-     * applications or internet. The activity should use {@link
-     * Activity#setShowWhenLocked} to display
-     * on top of the lock screen while secured. There is no activity stack when
-     * this flag is used, so launching more than one activity is strongly
-     * discouraged.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
-            "android.media.action.STILL_IMAGE_CAMERA_SECURE";
-
-    /**
-     * The name of the Intent action used to launch a camera in video mode.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
-
-    /**
-     * Standard Intent action that can be sent to have the camera application
-     * capture an image and return it.
-     * <p>
-     * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written.
-     * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap
-     * object in the extra field. This is useful for applications that only need a small image.
-     * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
-     * value of EXTRA_OUTPUT.
-     * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through
-     * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
-     * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
-     * If you don't set a ClipData, it will be copied there for you when calling
-     * {@link Context#startActivity(Intent)}.
-     *
-     * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
-     * and declares as using the {@link android.Manifest.permission#CAMERA} permission which
-     * is not granted, then attempting to use this action will result in a {@link
-     * java.lang.SecurityException}.
-     *
-     *  @see #EXTRA_OUTPUT
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
-
-    /**
-     * Intent action that can be sent to have the camera application capture an image and return
-     * it when the device is secured (e.g. with a pin, password, pattern, or face unlock).
-     * Applications responding to this intent must not expose any personal content like existing
-     * photos or videos on the device. The applications should be careful not to share any photo
-     * or video with other applications or Internet. The activity should use {@link
-     * Activity#setShowWhenLocked} to display on top of the
-     * lock screen while secured. There is no activity stack when this flag is used, so
-     * launching more than one activity is strongly discouraged.
-     * <p>
-     * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written.
-     * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap
-     * object in the extra field. This is useful for applications that only need a small image.
-     * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
-     * value of EXTRA_OUTPUT.
-     * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through
-     * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
-     * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
-     * If you don't set a ClipData, it will be copied there for you when calling
-     * {@link Context#startActivity(Intent)}.
-     *
-     * @see #ACTION_IMAGE_CAPTURE
-     * @see #EXTRA_OUTPUT
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_IMAGE_CAPTURE_SECURE =
-            "android.media.action.IMAGE_CAPTURE_SECURE";
-
-    /**
-     * Standard Intent action that can be sent to have the camera application
-     * capture a video and return it.
-     * <p>
-     * The caller may pass in an extra EXTRA_VIDEO_QUALITY to control the video quality.
-     * <p>
-     * The caller may pass in an extra EXTRA_OUTPUT to control
-     * where the video is written. If EXTRA_OUTPUT is not present the video will be
-     * written to the standard location for videos, and the Uri of that location will be
-     * returned in the data field of the Uri.
-     * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through
-     * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
-     * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
-     * If you don't set a ClipData, it will be copied there for you when calling
-     * {@link Context#startActivity(Intent)}.
-     *
-     * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
-     * and declares as using the {@link android.Manifest.permission#CAMERA} permission which
-     * is not granted, then atempting to use this action will result in a {@link
-     * java.lang.SecurityException}.
-     *
-     * @see #EXTRA_OUTPUT
-     * @see #EXTRA_VIDEO_QUALITY
-     * @see #EXTRA_SIZE_LIMIT
-     * @see #EXTRA_DURATION_LIMIT
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public final static String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
-
-    /**
-     * Standard action that can be sent to review the given media file.
-     * <p>
-     * The launched application is expected to provide a large-scale view of the
-     * given media file, while allowing the user to quickly access other
-     * recently captured media files.
-     * <p>
-     * Input: {@link Intent#getData} is URI of the primary media item to
-     * initially display.
-     *
-     * @see #ACTION_REVIEW_SECURE
-     * @see #EXTRA_BRIGHTNESS
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public final static String ACTION_REVIEW = "android.provider.action.REVIEW";
-
-    /**
-     * Standard action that can be sent to review the given media file when the
-     * device is secured (e.g. with a pin, password, pattern, or face unlock).
-     * The applications should be careful not to share any media with other
-     * applications or Internet. The activity should use
-     * {@link Activity#setShowWhenLocked} to display on top of the lock screen
-     * while secured. There is no activity stack when this flag is used, so
-     * launching more than one activity is strongly discouraged.
-     * <p>
-     * The launched application is expected to provide a large-scale view of the
-     * given primary media file, while only allowing the user to quickly access
-     * other media from an explicit secondary list.
-     * <p>
-     * Input: {@link Intent#getData} is URI of the primary media item to
-     * initially display. {@link Intent#getClipData} is the limited list of
-     * secondary media items that the user is allowed to review. If
-     * {@link Intent#getClipData} is undefined, then no other media access
-     * should be allowed.
-     *
-     * @see #EXTRA_BRIGHTNESS
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public final static String ACTION_REVIEW_SECURE = "android.provider.action.REVIEW_SECURE";
-
-    /**
-     * When defined, the launched application is requested to set the given
-     * brightness value via
-     * {@link android.view.WindowManager.LayoutParams#screenBrightness} to help
-     * ensure a smooth transition when launching {@link #ACTION_REVIEW} or
-     * {@link #ACTION_REVIEW_SECURE} intents.
-     */
-    public final static String EXTRA_BRIGHTNESS = "android.provider.extra.BRIGHTNESS";
-
-    /**
-     * The name of the Intent-extra used to control the quality of a recorded video. This is an
-     * integer property. Currently value 0 means low quality, suitable for MMS messages, and
-     * value 1 means high quality. In the future other quality levels may be added.
-     */
-    public final static String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
-
-    /**
-     * Specify the maximum allowed size.
-     */
-    public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit";
-
-    /**
-     * Specify the maximum allowed recording duration in seconds.
-     */
-    public final static String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
-
-    /**
-     * The name of the Intent-extra used to indicate a content resolver Uri to be used to
-     * store the requested image or video.
-     */
-    public final static String EXTRA_OUTPUT = "output";
-
-    /**
-      * The string that is used when a media attribute is not known. For example,
-      * if an audio file does not have any meta data, the artist and album columns
-      * will be set to this value.
-      */
-    public static final String UNKNOWN_STRING = "<unknown>";
-
-    /**
-     * Specify a {@link Uri} that is "related" to the current operation being
-     * performed.
-     * <p>
-     * This is typically used to allow an operation that may normally be
-     * rejected, such as making a copy of a pre-existing image located under a
-     * {@link MediaColumns#RELATIVE_PATH} where new images are not allowed.
-     * <p>
-     * It's strongly recommended that when making a copy of pre-existing content
-     * that you define the "original document ID" GUID as defined by the <em>XMP
-     * Media Management</em> standard.
-     * <p>
-     * This key can be placed in a {@link Bundle} of extras and passed to
-     * {@link ContentResolver#insert}.
-     */
-    public static final String QUERY_ARG_RELATED_URI = "android:query-arg-related-uri";
-
-    /**
-     * 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.
-     *
-     * @see MediaColumns#IS_TRASHED
-     * @see MediaStore#QUERY_ARG_MATCH_TRASHED
-     * @see MediaStore#createTrashRequest
-     */
-    @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.
-     *
-     * @see MediaColumns#IS_FAVORITE
-     * @see MediaStore#QUERY_ARG_MATCH_FAVORITE
-     * @see MediaStore#createFavoriteRequest
-     */
-    @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
-     * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
-     * By default no pending items are returned.
-     *
-     * @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");
-    }
-
-    /**
-     * Return if any pending media items should be included in calls such as
-     * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
-     *
-     * @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));
-    }
-
-    /**
-     * Update the given {@link Uri} to also include any trashed media items from
-     * calls such as
-     * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
-     * By default no trashed items are returned.
-     *
-     * @see MediaColumns#IS_TRASHED
-     * @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();
-    }
-
-    /**
-     * Update the given {@link Uri} to indicate that the caller requires the
-     * original file contents when calling
-     * {@link ContentResolver#openFileDescriptor(Uri, String)}.
-     * <p>
-     * This can be useful when the caller wants to ensure they're backing up the
-     * exact bytes of the underlying media, without any Exif redaction being
-     * performed.
-     * <p>
-     * If the original file contents cannot be provided, a
-     * {@link UnsupportedOperationException} will be thrown when the returned
-     * {@link Uri} is used, such as when the caller doesn't hold
-     * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION}.
-     *
-     * @see MediaStore#getRequireOriginal(Uri)
-     */
-    public static @NonNull Uri setRequireOriginal(@NonNull Uri uri) {
-        return uri.buildUpon().appendQueryParameter(PARAM_REQUIRE_ORIGINAL, "1").build();
-    }
-
-    /**
-     * Return if the caller requires the original file contents when calling
-     * {@link ContentResolver#openFileDescriptor(Uri, String)}.
-     *
-     * @see MediaStore#setRequireOriginal(Uri)
-     */
-    public static boolean getRequireOriginal(@NonNull Uri uri) {
-        return parseBoolean(uri.getQueryParameter(MediaStore.PARAM_REQUIRE_ORIGINAL));
-    }
-
-    /**
-     * Mark the given item as being "trashed", meaning it should be deleted at
-     * some point in the future. This is a more gentle operation than simply
-     * calling {@link ContentResolver#delete(Uri, String, String[])}, which
-     * would take effect immediately.
-     * <p>
-     * This method preserves trashed items for at least 48 hours before erasing
-     * them, giving the user a chance to untrash the item.
-     *
-     * @see MediaColumns#IS_TRASHED
-     * @see MediaStore#setIncludeTrashed(Uri)
-     * @see MediaStore#trash(Context, Uri)
-     * @see MediaStore#untrash(Context, Uri)
-     * @removed
-     */
-    @Deprecated
-    public static void trash(@NonNull Context context, @NonNull Uri uri) {
-        trash(context, uri, 48 * DateUtils.HOUR_IN_MILLIS);
-    }
-
-    /**
-     * Mark the given item as being "trashed", meaning it should be deleted at
-     * some point in the future. This is a more gentle operation than simply
-     * calling {@link ContentResolver#delete(Uri, String, String[])}, which
-     * would take effect immediately.
-     * <p>
-     * This method preserves trashed items for at least the given timeout before
-     * erasing them, giving the user a chance to untrash the item.
-     *
-     * @see MediaColumns#IS_TRASHED
-     * @see MediaStore#setIncludeTrashed(Uri)
-     * @see MediaStore#trash(Context, Uri)
-     * @see MediaStore#untrash(Context, Uri)
-     * @removed
-     */
-    @Deprecated
-    public static void trash(@NonNull Context context, @NonNull Uri uri,
-            @DurationMillisLong long timeoutMillis) {
-        if (timeoutMillis < 0) {
-            throw new IllegalArgumentException();
-        }
-
-        final ContentValues values = new ContentValues();
-        values.put(MediaColumns.IS_TRASHED, 1);
-        values.put(MediaColumns.DATE_EXPIRES,
-                (System.currentTimeMillis() + timeoutMillis) / 1000);
-        context.getContentResolver().update(uri, values, null, null);
-    }
-
-    /**
-     * Mark the given item as being "untrashed", meaning it should no longer be
-     * deleted as previously requested through {@link #trash(Context, Uri)}.
-     *
-     * @see MediaColumns#IS_TRASHED
-     * @see MediaStore#setIncludeTrashed(Uri)
-     * @see MediaStore#trash(Context, Uri)
-     * @see MediaStore#untrash(Context, Uri)
-     * @removed
-     */
-    @Deprecated
-    public static void untrash(@NonNull Context context, @NonNull Uri uri) {
-        final ContentValues values = new ContentValues();
-        values.put(MediaColumns.IS_TRASHED, 0);
-        values.putNull(MediaColumns.DATE_EXPIRES);
-        context.getContentResolver().update(uri, values, null, null);
-    }
-
-    /**
-     * Rewrite the given {@link Uri} to point at
-     * {@link MediaStore#AUTHORITY_LEGACY}.
-     *
-     * @hide
-     */
-    public static @NonNull Uri rewriteToLegacy(@NonNull Uri uri) {
-        return uri.buildUpon().authority(MediaStore.AUTHORITY_LEGACY).build();
-    }
-
-    private static @NonNull PendingIntent createRequest(@NonNull ContentResolver resolver,
-            @NonNull String method, @NonNull Collection<Uri> uris, @Nullable ContentValues values) {
-        Objects.requireNonNull(resolver);
-        Objects.requireNonNull(uris);
-
-        final Iterator<Uri> it = uris.iterator();
-        final ClipData clipData = ClipData.newRawUri(null, it.next());
-        while (it.hasNext()) {
-            clipData.addItem(new ClipData.Item(it.next()));
-        }
-
-        final Bundle extras = new Bundle();
-        extras.putParcelable(EXTRA_CLIP_DATA, clipData);
-        extras.putParcelable(EXTRA_CONTENT_VALUES, values);
-        return resolver.call(AUTHORITY, method, null, extras).getParcelable(EXTRA_RESULT);
-    }
-
-    /**
-     * Create a {@link PendingIntent} that will prompt the user to grant your
-     * app write access for the requested media items.
-     * <p>
-     * This call only generates the request for a prompt; to display the prompt,
-     * call {@link Activity#startIntentSenderForResult} with
-     * {@link PendingIntent#getIntentSender()}. You can then determine if the
-     * user granted your request by testing for {@link Activity#RESULT_OK} in
-     * {@link Activity#onActivityResult}.
-     * <p>
-     * Permissions granted through this mechanism are tied to the lifecycle of
-     * the {@link Activity} that requests them. If you need to retain
-     * longer-term access for background actions, you can place items into a
-     * {@link ClipData} or {@link Intent} which can then be passed to
-     * {@link Context#startService} or
-     * {@link android.app.job.JobInfo.Builder#setClipData}. Be sure to include
-     * any relevant access modes you want to retain, such as
-     * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
-     * <p>
-     * The displayed prompt will reflect all the media items you're requesting,
-     * including those for which you already hold write access. If you want to
-     * determine if you already hold write access before requesting access, use
-     * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
-     * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
-     * <p>
-     * For security and performance reasons this method does not support
-     * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} or
-     * {@link Intent#FLAG_GRANT_PREFIX_URI_PERMISSION}.
-     *
-     * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
-     *            Typically this value is {@link Context#getContentResolver()},
-     *            but if you need more explicit lifecycle controls, you can
-     *            obtain a {@link ContentProviderClient} and wrap it using
-     *            {@link ContentResolver#wrap(ContentProviderClient)}.
-     * @param uris The set of media items to include in this request. Each item
-     *            must be hosted by {@link MediaStore#AUTHORITY} and must
-     *            reference a specific media item by {@link BaseColumns#_ID}.
-     */
-    public static @NonNull PendingIntent createWriteRequest(@NonNull ContentResolver resolver,
-            @NonNull Collection<Uri> uris) {
-        return createRequest(resolver, CREATE_WRITE_REQUEST_CALL, uris, null);
-    }
-
-    /**
-     * Create a {@link PendingIntent} that will prompt the user to trash the
-     * requested media items. When the user approves this request,
-     * {@link MediaColumns#IS_TRASHED} is set on these items.
-     * <p>
-     * This call only generates the request for a prompt; to display the prompt,
-     * call {@link Activity#startIntentSenderForResult} with
-     * {@link PendingIntent#getIntentSender()}. You can then determine if the
-     * user granted your request by testing for {@link Activity#RESULT_OK} in
-     * {@link Activity#onActivityResult}.
-     * <p>
-     * The displayed prompt will reflect all the media items you're requesting,
-     * including those for which you already hold write access. If you want to
-     * determine if you already hold write access before requesting access, use
-     * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
-     * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
-     *
-     * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
-     *            Typically this value is {@link Context#getContentResolver()},
-     *            but if you need more explicit lifecycle controls, you can
-     *            obtain a {@link ContentProviderClient} and wrap it using
-     *            {@link ContentResolver#wrap(ContentProviderClient)}.
-     * @param uris The set of media items to include in this request. Each item
-     *            must be hosted by {@link MediaStore#AUTHORITY} and must
-     *            reference a specific media item by {@link BaseColumns#_ID}.
-     * @param value The {@link MediaColumns#IS_TRASHED} value to apply.
-     * @see MediaColumns#IS_TRASHED
-     * @see MediaStore#QUERY_ARG_MATCH_TRASHED
-     */
-    public static @NonNull PendingIntent createTrashRequest(@NonNull ContentResolver resolver,
-            @NonNull Collection<Uri> uris, boolean value) {
-        final ContentValues values = new ContentValues();
-        if (value) {
-            values.put(MediaColumns.IS_TRASHED, 1);
-            values.put(MediaColumns.DATE_EXPIRES,
-                    (System.currentTimeMillis() + DateUtils.WEEK_IN_MILLIS) / 1000);
-        } else {
-            values.put(MediaColumns.IS_TRASHED, 0);
-            values.putNull(MediaColumns.DATE_EXPIRES);
-        }
-        return createRequest(resolver, CREATE_TRASH_REQUEST_CALL, uris, values);
-    }
-
-    /**
-     * Create a {@link PendingIntent} that will prompt the user to favorite the
-     * requested media items. When the user approves this request,
-     * {@link MediaColumns#IS_FAVORITE} is set on these items.
-     * <p>
-     * This call only generates the request for a prompt; to display the prompt,
-     * call {@link Activity#startIntentSenderForResult} with
-     * {@link PendingIntent#getIntentSender()}. You can then determine if the
-     * user granted your request by testing for {@link Activity#RESULT_OK} in
-     * {@link Activity#onActivityResult}.
-     * <p>
-     * The displayed prompt will reflect all the media items you're requesting,
-     * including those for which you already hold write access. If you want to
-     * determine if you already hold write access before requesting access, use
-     * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
-     * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
-     *
-     * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
-     *            Typically this value is {@link Context#getContentResolver()},
-     *            but if you need more explicit lifecycle controls, you can
-     *            obtain a {@link ContentProviderClient} and wrap it using
-     *            {@link ContentResolver#wrap(ContentProviderClient)}.
-     * @param uris The set of media items to include in this request. Each item
-     *            must be hosted by {@link MediaStore#AUTHORITY} and must
-     *            reference a specific media item by {@link BaseColumns#_ID}.
-     * @param value The {@link MediaColumns#IS_FAVORITE} value to apply.
-     * @see MediaColumns#IS_FAVORITE
-     * @see MediaStore#QUERY_ARG_MATCH_FAVORITE
-     */
-    public static @NonNull PendingIntent createFavoriteRequest(@NonNull ContentResolver resolver,
-            @NonNull Collection<Uri> uris, boolean value) {
-        final ContentValues values = new ContentValues();
-        if (value) {
-            values.put(MediaColumns.IS_FAVORITE, 1);
-        } else {
-            values.put(MediaColumns.IS_FAVORITE, 0);
-        }
-        return createRequest(resolver, CREATE_FAVORITE_REQUEST_CALL, uris, values);
-    }
-
-    /**
-     * Create a {@link PendingIntent} that will prompt the user to permanently
-     * delete the requested media items. When the user approves this request,
-     * {@link ContentResolver#delete} will be called on these items.
-     * <p>
-     * This call only generates the request for a prompt; to display the prompt,
-     * call {@link Activity#startIntentSenderForResult} with
-     * {@link PendingIntent#getIntentSender()}. You can then determine if the
-     * user granted your request by testing for {@link Activity#RESULT_OK} in
-     * {@link Activity#onActivityResult}.
-     * <p>
-     * The displayed prompt will reflect all the media items you're requesting,
-     * including those for which you already hold write access. If you want to
-     * determine if you already hold write access before requesting access, use
-     * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
-     * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
-     *
-     * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
-     *            Typically this value is {@link Context#getContentResolver()},
-     *            but if you need more explicit lifecycle controls, you can
-     *            obtain a {@link ContentProviderClient} and wrap it using
-     *            {@link ContentResolver#wrap(ContentProviderClient)}.
-     * @param uris The set of media items to include in this request. Each item
-     *            must be hosted by {@link MediaStore#AUTHORITY} and must
-     *            reference a specific media item by {@link BaseColumns#_ID}.
-     */
-    public static @NonNull PendingIntent createDeleteRequest(@NonNull ContentResolver resolver,
-            @NonNull Collection<Uri> uris) {
-        return createRequest(resolver, CREATE_DELETE_REQUEST_CALL, uris, null);
-    }
-
-    /**
-     * Common media metadata columns.
-     */
-    public interface MediaColumns extends BaseColumns {
-        /**
-         * Absolute filesystem path to the media item on disk.
-         * <p>
-         * Note that apps may not have filesystem permissions to directly access
-         * this path. Instead of trying to open this path directly, apps should
-         * use {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
-         * access.
-         *
-         * @deprecated Apps may not have filesystem permissions to directly
-         *             access this path. Instead of trying to open this path
-         *             directly, apps should use
-         *             {@link ContentResolver#openFileDescriptor(Uri, String)}
-         *             to gain access.
-         */
-        @Deprecated
-        @Column(Cursor.FIELD_TYPE_STRING)
-        public static final String DATA = "_data";
-
-        /**
-         * Indexed value of {@link File#length()} extracted from this media
-         * item.
-         */
-        @BytesLong
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String SIZE = "_size";
-
-        /**
-         * The display name of the media item.
-         * <p>
-         * For example, an item stored at
-         * {@code /storage/0000-0000/DCIM/Vacation/IMG1024.JPG} would have a
-         * display name of {@code IMG1024.JPG}.
-         */
-        @Column(Cursor.FIELD_TYPE_STRING)
-        public static final String DISPLAY_NAME = "_display_name";
-
-        /**
-         * The time the media item was first added.
-         */
-        @CurrentTimeSecondsLong
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String DATE_ADDED = "date_added";
-
-        /**
-         * Indexed value of {@link File#lastModified()} extracted from this
-         * media item.
-         */
-        @CurrentTimeSecondsLong
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String DATE_MODIFIED = "date_modified";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DATE} or
-         * {@link ExifInterface#TAG_DATETIME_ORIGINAL} extracted from this media
-         * item.
-         * <p>
-         * Note that images must define both
-         * {@link ExifInterface#TAG_DATETIME_ORIGINAL} and
-         * {@code ExifInterface#TAG_OFFSET_TIME_ORIGINAL} to reliably determine
-         * this value in relation to the epoch.
-         */
-        @CurrentTimeMillisLong
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String DATE_TAKEN = "datetaken";
-
-        /**
-         * The MIME type of the media item.
-         * <p>
-         * This is typically defined based on the file extension of the media
-         * item. However, it may be the value of the {@code format} attribute
-         * defined by the <em>Dublin Core Media Initiative</em> standard,
-         * extracted from any XMP metadata contained within this media item.
-         * <p class="note">
-         * Note: the {@code format} attribute may be ignored if the top-level
-         * MIME type disagrees with the file extension. For example, it's
-         * reasonable for an {@code image/jpeg} file to declare a {@code format}
-         * of {@code image/vnd.google.panorama360+jpg}, but declaring a
-         * {@code format} of {@code audio/ogg} would be ignored.
-         * <p>
-         * This is a read-only column that is automatically computed.
-         */
-        @Column(Cursor.FIELD_TYPE_STRING)
-        public static final String MIME_TYPE = "mime_type";
-
-        /**
-         * Non-zero if the media file is drm-protected
-         * @hide
-         */
-        @UnsupportedAppUsage
-        @Deprecated
-        @Column(Cursor.FIELD_TYPE_INTEGER)
-        public static final String IS_DRM = "is_drm";
-
-        /**
-         * Flag indicating if a media item is pending, and still being inserted
-         * by its owner. While this flag is set, only the owner of the item can
-         * open the underlying file; requests from other apps will be rejected.
-         * <p>
-         * Pending items are retained either until they are published by setting
-         * the field to {@code 0}, or until they expire as defined by
-         * {@link #DATE_EXPIRES}.
-         *
-         * @see MediaStore#QUERY_ARG_MATCH_PENDING
-         */
-        @Column(Cursor.FIELD_TYPE_INTEGER)
-        public static final String IS_PENDING = "is_pending";
-
-        /**
-         * Flag indicating if a media item is trashed.
-         * <p>
-         * Trashed items are retained until they expire as defined by
-         * {@link #DATE_EXPIRES}.
-         *
-         * @see MediaColumns#IS_TRASHED
-         * @see MediaStore#QUERY_ARG_MATCH_TRASHED
-         * @see MediaStore#createTrashRequest
-         */
-        @Column(Cursor.FIELD_TYPE_INTEGER)
-        public static final String IS_TRASHED = "is_trashed";
-
-        /**
-         * The time the media item should be considered expired. Typically only
-         * meaningful in the context of {@link #IS_PENDING} or
-         * {@link #IS_TRASHED}.
-         */
-        @CurrentTimeSecondsLong
-        @Column(Cursor.FIELD_TYPE_INTEGER)
-        public static final String DATE_EXPIRES = "date_expires";
-
-        /**
-         * Indexed value of
-         * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_WIDTH},
-         * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_WIDTH} or
-         * {@link ExifInterface#TAG_IMAGE_WIDTH} extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String WIDTH = "width";
-
-        /**
-         * Indexed value of
-         * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_HEIGHT},
-         * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_HEIGHT} or
-         * {@link ExifInterface#TAG_IMAGE_LENGTH} extracted from this media
-         * item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String HEIGHT = "height";
-
-        /**
-         * Calculated value that combines {@link #WIDTH} and {@link #HEIGHT}
-         * into a user-presentable string.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String RESOLUTION = "resolution";
-
-        /**
-         * Package name that contributed this media. The value may be
-         * {@code NULL} if ownership cannot be reliably determined.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String OWNER_PACKAGE_NAME = "owner_package_name";
-
-        /**
-         * Volume name of the specific storage device where this media item is
-         * persisted. The value is typically one of the volume names returned
-         * from {@link MediaStore#getExternalVolumeNames(Context)}.
-         * <p>
-         * This is a read-only column that is automatically computed.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String VOLUME_NAME = "volume_name";
-
-        /**
-         * Relative path of this media item within the storage device where it
-         * is persisted. For example, an item stored at
-         * {@code /storage/0000-0000/DCIM/Vacation/IMG1024.JPG} would have a
-         * path of {@code DCIM/Vacation/}.
-         * <p>
-         * This value should only be used for organizational purposes, and you
-         * should not attempt to construct or access a raw filesystem path using
-         * this value. If you need to open a media item, use an API like
-         * {@link ContentResolver#openFileDescriptor(Uri, String)}.
-         * <p>
-         * When this value is set to {@code NULL} during an
-         * {@link ContentResolver#insert} operation, the newly created item will
-         * be placed in a relevant default location based on the type of media
-         * being inserted. For example, a {@code image/jpeg} item will be placed
-         * under {@link Environment#DIRECTORY_PICTURES}.
-         * <p>
-         * You can modify this column during an {@link ContentResolver#update}
-         * call, which will move the underlying file on disk.
-         * <p>
-         * In both cases above, content must be placed under a top-level
-         * directory that is relevant to the media type. For example, attempting
-         * to place a {@code audio/mpeg} file under
-         * {@link Environment#DIRECTORY_PICTURES} will be rejected.
-         */
-        @Column(Cursor.FIELD_TYPE_STRING)
-        public static final String RELATIVE_PATH = "relative_path";
-
-        /**
-         * The primary bucket ID of this media item. This can be useful to
-         * present the user a first-level clustering of related media items.
-         * This is a read-only column that is automatically computed.
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String BUCKET_ID = "bucket_id";
-
-        /**
-         * The primary bucket display name of this media item. This can be
-         * useful to present the user a first-level clustering of related
-         * media items. This is a read-only column that is automatically
-         * computed.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
-
-        /**
-         * The group ID of this media item. This can be useful to present
-         * the user a grouping of related media items, such a burst of
-         * images, or a {@code JPG} and {@code DNG} version of the same
-         * image.
-         * <p>
-         * This is a read-only column that is automatically computed based
-         * on the first portion of the filename. For example,
-         * {@code IMG1024.BURST001.JPG} and {@code IMG1024.BURST002.JPG}
-         * will have the same {@link #GROUP_ID} because the first portion of
-         * their filenames is identical.
-         *
-         * @removed
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        @Deprecated
-        public static final String GROUP_ID = "group_id";
-
-        /**
-         * The "document ID" GUID as defined by the <em>XMP Media
-         * Management</em> standard, extracted from any XMP metadata contained
-         * within this media item. The value is {@code null} when no metadata
-         * was found.
-         * <p>
-         * Each "document ID" is created once for each new resource. Different
-         * renditions of that resource are expected to have different IDs.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String DOCUMENT_ID = "document_id";
-
-        /**
-         * The "instance ID" GUID as defined by the <em>XMP Media
-         * Management</em> standard, extracted from any XMP metadata contained
-         * within this media item. The value is {@code null} when no metadata
-         * was found.
-         * <p>
-         * This "instance ID" changes with each save operation of a specific
-         * "document ID".
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String INSTANCE_ID = "instance_id";
-
-        /**
-         * The "original document ID" GUID as defined by the <em>XMP Media
-         * Management</em> standard, extracted from any XMP metadata contained
-         * within this media item.
-         * <p>
-         * This "original document ID" links a resource to its original source.
-         * For example, when you save a PSD document as a JPEG, then convert the
-         * JPEG to GIF format, the "original document ID" of both the JPEG and
-         * GIF files is the "document ID" of the original PSD file.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
-
-        /**
-         * Indexed value of
-         * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_ROTATION},
-         * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_ROTATION}, or
-         * {@link ExifInterface#TAG_ORIENTATION} extracted from this media item.
-         * <p>
-         * For consistency the indexed value is expressed in degrees, such as 0,
-         * 90, 180, or 270.
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String ORIENTATION = "orientation";
-
-        /**
-         * Flag indicating if the media item has been marked as being a
-         * "favorite" by the user.
-         *
-         * @see MediaColumns#IS_FAVORITE
-         * @see MediaStore#QUERY_ARG_MATCH_FAVORITE
-         * @see MediaStore#createFavoriteRequest
-         */
-        @Column(Cursor.FIELD_TYPE_INTEGER)
-        public static final String IS_FAVORITE = "is_favorite";
-
-        // =======================================
-        // ==== MediaMetadataRetriever values ====
-        // =======================================
-
-        /**
-         * Indexed value of
-         * {@link MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER} extracted
-         * from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String CD_TRACK_NUMBER = "cd_track_number";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ALBUM}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String ALBUM = "album";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ARTIST}
-         * or {@link ExifInterface#TAG_ARTIST} extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String ARTIST = "artist";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_AUTHOR}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String AUTHOR = "author";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_COMPOSER}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String COMPOSER = "composer";
-
-        // METADATA_KEY_DATE is DATE_TAKEN
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_GENRE}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String GENRE = "genre";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_TITLE}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String TITLE = "title";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_YEAR}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String YEAR = "year";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DURATION}
-         * extracted from this media item.
-         */
-        @DurationMillisLong
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String DURATION = "duration";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_NUM_TRACKS}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String NUM_TRACKS = "num_tracks";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_WRITER}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String WRITER = "writer";
-
-        // METADATA_KEY_MIMETYPE is MIME_TYPE
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String ALBUM_ARTIST = "album_artist";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String DISC_NUMBER = "disc_number";
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_COMPILATION}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-        public static final String COMPILATION = "compilation";
-
-        // HAS_AUDIO is ignored
-        // HAS_VIDEO is ignored
-        // VIDEO_WIDTH is WIDTH
-        // VIDEO_HEIGHT is HEIGHT
-
-        /**
-         * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_BITRATE}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-        public static final String BITRATE = "bitrate";
-
-        // TIMED_TEXT_LANGUAGES is ignored
-        // IS_DRM is ignored
-        // LOCATION is LATITUDE and LONGITUDE
-        // VIDEO_ROTATION is ORIENTATION
-
-        /**
-         * Indexed value of
-         * {@link MediaMetadataRetriever#METADATA_KEY_CAPTURE_FRAMERATE}
-         * extracted from this media item.
-         */
-        @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
-        public static final String CAPTURE_FRAMERATE = "capture_framerate";
-
-        // HAS_IMAGE is ignored
-        // IMAGE_COUNT is ignored
-        // IMAGE_PRIMARY is ignored
-        // IMAGE_WIDTH is WIDTH
-        // IMAGE_HEIGHT is HEIGHT
-        // IMAGE_ROTATION is ORIENTATION
-        // VIDEO_FRAME_COUNT is ignored
-        // EXIF_OFFSET is ignored
-        // EXIF_LENGTH is ignored
-        // COLOR_STANDARD is ignored
-        // COLOR_TRANSFER is ignored
-        // COLOR_RANGE is ignored
-        // SAMPLERATE is ignored
-        // BITS_PER_SAMPLE is ignored
-    }
-
-    /**
-     * Media provider table containing an index of all files in the media storage,
-     * including non-media files.  This should be used by applications that work with
-     * non-media file types (text, HTML, PDF, etc) as well as applications that need to
-     * work with multiple media file types in a single query.
-     */
-    public static final class Files {
-        /** @hide */
-        public static final String TABLE = "files";
-
-        /** @hide */
-        public static final Uri EXTERNAL_CONTENT_URI = getContentUri(VOLUME_EXTERNAL);
-
-        /**
-         * Get the content:// style URI for the files table on the
-         * given volume.
-         *
-         * @param volumeName the name of the volume to get the URI for
-         * @return the URI to the files table on the given volume
-         */
-        public static Uri getContentUri(String volumeName) {
-            return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("file").build();
-        }
-
-        /**
-         * Get the content:// style URI for a single row in the files table on the
-         * given volume.
-         *
-         * @param volumeName the name of the volume to get the URI for
-         * @param rowId the file to get the URI for
-         * @return the URI to the files table on the given volume
-         */
-        public static final Uri getContentUri(String volumeName,
-                long rowId) {
-            return ContentUris.withAppendedId(getContentUri(volumeName), rowId);
-        }
-
-        /** {@hide} */
-        @UnsupportedAppUsage
-        public static Uri getMtpObjectsUri(@NonNull String volumeName) {
-            return MediaStore.Files.getContentUri(volumeName);
-        }
-
-        /** {@hide} */
-        @UnsupportedAppUsage
-        public static final Uri getMtpObjectsUri(@NonNull String volumeName, long fileId) {
-            return MediaStore.Files.getContentUri(volumeName, fileId);
-        }
-
-        /** {@hide} */
-        @UnsupportedAppUsage
-        public static final Uri getMtpReferencesUri(@NonNull String volumeName, long fileId) {
-            return MediaStore.Files.getContentUri(volumeName, fileId);
-        }
-
-        /**
-         * Used to trigger special logic for directories.
-         * @hide
-         */
-        public static final Uri getDirectoryUri(String volumeName) {
-            return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("dir").build();
-        }
-
-        /** @hide */
-        public static final Uri getContentUriForPath(String path) {
-            return getContentUri(getVolumeName(new File(path)));
-        }
-
-        /**
-         * File metadata columns.
-         */
-        public interface FileColumns extends MediaColumns {
-            /**
-             * The MTP storage ID of the file
-             * @hide
-             */
-            @UnsupportedAppUsage
-            @Deprecated
-            // @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String STORAGE_ID = "storage_id";
-
-            /**
-             * The MTP format code of the file
-             * @hide
-             */
-            @UnsupportedAppUsage
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String FORMAT = "format";
-
-            /**
-             * The index of the parent directory of the file
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String PARENT = "parent";
-
-            /**
-             * The MIME type of the media item.
-             * <p>
-             * This is typically defined based on the file extension of the media
-             * item. However, it may be the value of the {@code format} attribute
-             * defined by the <em>Dublin Core Media Initiative</em> standard,
-             * extracted from any XMP metadata contained within this media item.
-             * <p class="note">
-             * Note: the {@code format} attribute may be ignored if the top-level
-             * MIME type disagrees with the file extension. For example, it's
-             * reasonable for an {@code image/jpeg} file to declare a {@code format}
-             * of {@code image/vnd.google.panorama360+jpg}, but declaring a
-             * {@code format} of {@code audio/ogg} would be ignored.
-             * <p>
-             * This is a read-only column that is automatically computed.
-             */
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String MIME_TYPE = "mime_type";
-
-            /** @removed promoted to parent interface */
-            public static final String TITLE = "title";
-
-            /**
-             * The media type (audio, video, image or playlist)
-             * of the file, or 0 for not a media file
-             */
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String MEDIA_TYPE = "media_type";
-
-            /**
-             * Constant for the {@link #MEDIA_TYPE} column indicating that file
-             * is not an audio, image, video, playlist, or subtitles file.
-             */
-            public static final int MEDIA_TYPE_NONE = 0;
-
-            /**
-             * Constant for the {@link #MEDIA_TYPE} column indicating that file
-             * is an image file.
-             */
-            public static final int MEDIA_TYPE_IMAGE = 1;
-
-            /**
-             * Constant for the {@link #MEDIA_TYPE} column indicating that file
-             * is an audio file.
-             */
-            public static final int MEDIA_TYPE_AUDIO = 2;
-
-            /**
-             * Constant for the {@link #MEDIA_TYPE} column indicating that file
-             * is a video file.
-             */
-            public static final int MEDIA_TYPE_VIDEO = 3;
-
-            /**
-             * Constant for the {@link #MEDIA_TYPE} column indicating that file
-             * is a playlist file.
-             */
-            public static final int MEDIA_TYPE_PLAYLIST = 4;
-
-            /**
-             * Constant for the {@link #MEDIA_TYPE} column indicating that file
-             * is a subtitles or lyrics file.
-             */
-            public static final int MEDIA_TYPE_SUBTITLE = 5;
-
-            /**
-             * Column indicating if the file is part of Downloads collection.
-             * @hide
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String IS_DOWNLOAD = "is_download";
-        }
-    }
-
-    /** @hide */
-    public static class ThumbnailConstants {
-        public static final int MINI_KIND = 1;
-        public static final int FULL_SCREEN_KIND = 2;
-        public static final int MICRO_KIND = 3;
-
-        public static final Size MINI_SIZE = new Size(512, 384);
-        public static final Size FULL_SCREEN_SIZE = new Size(1024, 786);
-        public static final Size MICRO_SIZE = new Size(96, 96);
-
-        public static @NonNull Size getKindSize(int kind) {
-            if (kind == ThumbnailConstants.MICRO_KIND) {
-                return ThumbnailConstants.MICRO_SIZE;
-            } else if (kind == ThumbnailConstants.FULL_SCREEN_KIND) {
-                return ThumbnailConstants.FULL_SCREEN_SIZE;
-            } else if (kind == ThumbnailConstants.MINI_KIND) {
-                return ThumbnailConstants.MINI_SIZE;
-            } else {
-                throw new IllegalArgumentException("Unsupported kind: " + kind);
-            }
-        }
-    }
-
-    /**
-     * Download metadata columns.
-     */
-    public interface DownloadColumns extends MediaColumns {
-        /**
-         * Uri indicating where the item has been downloaded from.
-         */
-        @Column(Cursor.FIELD_TYPE_STRING)
-        String DOWNLOAD_URI = "download_uri";
-
-        /**
-         * Uri indicating HTTP referer of {@link #DOWNLOAD_URI}.
-         */
-        @Column(Cursor.FIELD_TYPE_STRING)
-        String REFERER_URI = "referer_uri";
-
-        /**
-         * The description of the download.
-         *
-         * @removed
-         */
-        @Deprecated
-        @Column(Cursor.FIELD_TYPE_STRING)
-        String DESCRIPTION = "description";
-    }
-
-    /**
-     * Collection of downloaded items.
-     */
-    public static final class Downloads implements DownloadColumns {
-        private Downloads() {}
-
-        /**
-         * The content:// style URI for the internal storage.
-         */
-        @NonNull
-        public static final Uri INTERNAL_CONTENT_URI =
-                getContentUri("internal");
-
-        /**
-         * The content:// style URI for the "primary" external storage
-         * volume.
-         */
-        @NonNull
-        public static final Uri EXTERNAL_CONTENT_URI =
-                getContentUri("external");
-
-        /**
-         * The MIME type for this table.
-         */
-        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/download";
-
-        /**
-         * Regex that matches paths that needs to be considered part of downloads collection.
-         * @hide
-         */
-        public static final Pattern PATTERN_DOWNLOADS_FILE = Pattern.compile(
-                "(?i)^/storage/[^/]+/(?:[0-9]+/)?(?:Android/sandbox/[^/]+/)?Download/.+");
-        private static final Pattern PATTERN_DOWNLOADS_DIRECTORY = Pattern.compile(
-                "(?i)^/storage/[^/]+/(?:[0-9]+/)?(?:Android/sandbox/[^/]+/)?Download/?");
-
-        /**
-         * Get the content:// style URI for the downloads table on the
-         * given volume.
-         *
-         * @param volumeName the name of the volume to get the URI for
-         * @return the URI to the image media table on the given volume
-         */
-        public static @NonNull Uri getContentUri(@NonNull String volumeName) {
-            return AUTHORITY_URI.buildUpon().appendPath(volumeName)
-                    .appendPath("downloads").build();
-        }
-
-        /**
-         * Get the content:// style URI for a single row in the downloads table
-         * on the given volume.
-         *
-         * @param volumeName the name of the volume to get the URI for
-         * @param id the download to get the URI for
-         * @return the URI to the downloads table on the given volume
-         */
-        public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
-            return ContentUris.withAppendedId(getContentUri(volumeName), id);
-        }
-
-        /** @hide */
-        public static @NonNull Uri getContentUriForPath(@NonNull String path) {
-            return getContentUri(getVolumeName(new File(path)));
-        }
-
-        /** @hide */
-        public static boolean isDownload(@NonNull String path) {
-            return PATTERN_DOWNLOADS_FILE.matcher(path).matches();
-        }
-
-        /** @hide */
-        public static boolean isDownloadDir(@NonNull String path) {
-            return PATTERN_DOWNLOADS_DIRECTORY.matcher(path).matches();
-        }
-    }
-
-    /**
-     * @deprecated since this method doesn't have a {@link Context}, we can't
-     *             find the actual {@link StorageVolume} for the given path, so
-     *             only a vague guess is returned. Callers should use
-     *             {@link StorageManager#getStorageVolume(File)} instead.
-     * @hide
-     */
-    @Deprecated
-    public static @NonNull String getVolumeName(@NonNull File path) {
-        // Ideally we'd find the relevant StorageVolume, but we don't have a
-        // Context to obtain it from, so the best we can do is assume
-        if (path.getAbsolutePath()
-                .startsWith(Environment.getStorageDirectory().getAbsolutePath())) {
-            return MediaStore.VOLUME_EXTERNAL;
-        } else {
-            return MediaStore.VOLUME_INTERNAL;
-        }
-    }
-
-    /**
-     * This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended
-     * to be accessed elsewhere.
-     */
-    @Deprecated
-    private static class InternalThumbnails implements BaseColumns {
-        /**
-         * Currently outstanding thumbnail requests that can be cancelled.
-         */
-        // @GuardedBy("sPending")
-        private static ArrayMap<Uri, CancellationSignal> sPending = new ArrayMap<>();
-
-        /**
-         * Make a blocking request to obtain the given thumbnail, generating it
-         * if needed.
-         *
-         * @see #cancelThumbnail(ContentResolver, Uri)
-         */
-        @Deprecated
-        static @Nullable Bitmap getThumbnail(@NonNull ContentResolver cr, @NonNull Uri uri,
-                int kind, @Nullable BitmapFactory.Options opts) {
-            final Size size = ThumbnailConstants.getKindSize(kind);
-
-            CancellationSignal signal = null;
-            synchronized (sPending) {
-                signal = sPending.get(uri);
-                if (signal == null) {
-                    signal = new CancellationSignal();
-                    sPending.put(uri, signal);
-                }
-            }
-
-            try {
-                return cr.loadThumbnail(uri, size, signal);
-            } catch (IOException e) {
-                Log.w(TAG, "Failed to obtain thumbnail for " + uri, e);
-                return null;
-            } finally {
-                synchronized (sPending) {
-                    sPending.remove(uri);
-                }
-            }
-        }
-
-        /**
-         * This method cancels the thumbnail request so clients waiting for
-         * {@link #getThumbnail} will be interrupted and return immediately.
-         * Only the original process which made the request can cancel their own
-         * requests.
-         */
-        @Deprecated
-        static void cancelThumbnail(@NonNull ContentResolver cr, @NonNull Uri uri) {
-            synchronized (sPending) {
-                final CancellationSignal signal = sPending.get(uri);
-                if (signal != null) {
-                    signal.cancel();
-                }
-            }
-        }
-    }
-
-    /**
-     * Collection of all media with MIME type of {@code image/*}.
-     */
-    public static final class Images {
-        /**
-         * Image metadata columns.
-         */
-        public interface ImageColumns extends MediaColumns {
-            /**
-             * The picasa id of the image
-             *
-             * @deprecated this value was only relevant for images hosted on
-             *             Picasa, which are no longer supported.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String PICASA_ID = "picasa_id";
-
-            /**
-             * Whether the video should be published as public or private
-             */
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String IS_PRIVATE = "isprivate";
-
-            /**
-             * The latitude where the image was captured.
-             *
-             * @deprecated location details are no longer indexed for privacy
-             *             reasons, and this value is now always {@code null}.
-             *             You can still manually obtain location metadata using
-             *             {@link ExifInterface#getLatLong(float[])}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
-            public static final String LATITUDE = "latitude";
-
-            /**
-             * The longitude where the image was captured.
-             *
-             * @deprecated location details are no longer indexed for privacy
-             *             reasons, and this value is now always {@code null}.
-             *             You can still manually obtain location metadata using
-             *             {@link ExifInterface#getLatLong(float[])}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
-            public static final String LONGITUDE = "longitude";
-
-            /** @removed promoted to parent interface */
-            public static final String DATE_TAKEN = "datetaken";
-            /** @removed promoted to parent interface */
-            public static final String ORIENTATION = "orientation";
-
-            /**
-             * The mini thumb id.
-             *
-             * @deprecated all thumbnails should be obtained via
-             *             {@link MediaStore.Images.Thumbnails#getThumbnail}, as this
-             *             value is no longer supported.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
-
-            /** @removed promoted to parent interface */
-            public static final String BUCKET_ID = "bucket_id";
-            /** @removed promoted to parent interface */
-            public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
-            /** @removed promoted to parent interface */
-            public static final String GROUP_ID = "group_id";
-
-            /**
-             * Indexed value of {@link ExifInterface#TAG_IMAGE_DESCRIPTION}
-             * extracted from this media item.
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String DESCRIPTION = "description";
-
-            /**
-             * Indexed value of {@link ExifInterface#TAG_EXPOSURE_TIME}
-             * extracted from this media item.
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String EXPOSURE_TIME = "exposure_time";
-
-            /**
-             * Indexed value of {@link ExifInterface#TAG_F_NUMBER}
-             * extracted from this media item.
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String F_NUMBER = "f_number";
-
-            /**
-             * Indexed value of {@link ExifInterface#TAG_ISO_SPEED_RATINGS}
-             * extracted from this media item.
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String ISO = "iso";
-        }
-
-        public static final class Media implements ImageColumns {
-            /**
-             * @deprecated all queries should be performed through
-             *             {@link ContentResolver} directly, which offers modern
-             *             features like {@link CancellationSignal}.
-             */
-            @Deprecated
-            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
-                return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
-            }
-
-            /**
-             * @deprecated all queries should be performed through
-             *             {@link ContentResolver} directly, which offers modern
-             *             features like {@link CancellationSignal}.
-             */
-            @Deprecated
-            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
-                    String where, String orderBy) {
-                return cr.query(uri, projection, where,
-                                             null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
-            }
-
-            /**
-             * @deprecated all queries should be performed through
-             *             {@link ContentResolver} directly, which offers modern
-             *             features like {@link CancellationSignal}.
-             */
-            @Deprecated
-            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
-                    String selection, String [] selectionArgs, String orderBy) {
-                return cr.query(uri, projection, selection,
-                        selectionArgs, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
-            }
-
-            /**
-             * Retrieves an image for the given url as a {@link Bitmap}.
-             *
-             * @param cr The content resolver to use
-             * @param url The url of the image
-             * @deprecated loading of images should be performed through
-             *             {@link ImageDecoder#createSource(ContentResolver, Uri)},
-             *             which offers modern features like
-             *             {@link PostProcessor}.
-             */
-            @Deprecated
-            public static final Bitmap getBitmap(ContentResolver cr, Uri url)
-                    throws FileNotFoundException, IOException {
-                InputStream input = cr.openInputStream(url);
-                Bitmap bitmap = BitmapFactory.decodeStream(input);
-                input.close();
-                return bitmap;
-            }
-
-            /**
-             * Insert an image and create a thumbnail for it.
-             *
-             * @param cr The content resolver to use
-             * @param imagePath The path to the image to insert
-             * @param name The name of the image
-             * @param description The description of the image
-             * @return The URL to the newly created image
-             * @deprecated inserting of images should be performed using
-             *             {@link MediaColumns#IS_PENDING}, which offers richer
-             *             control over lifecycle.
-             */
-            @Deprecated
-            public static final String insertImage(ContentResolver cr, String imagePath,
-                    String name, String description) throws FileNotFoundException {
-                final Bitmap source;
-                try {
-                    source = ImageDecoder
-                            .decodeBitmap(ImageDecoder.createSource(new File(imagePath)));
-                } catch (IOException e) {
-                    throw new FileNotFoundException(e.getMessage());
-                }
-                return insertImage(cr, source, name, description);
-            }
-
-            /**
-             * Insert an image and create a thumbnail for it.
-             *
-             * @param cr The content resolver to use
-             * @param source The stream to use for the image
-             * @param title The name of the image
-             * @param description The description of the image
-             * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
-             *              for any reason.
-             * @deprecated inserting of images should be performed using
-             *             {@link MediaColumns#IS_PENDING}, which offers richer
-             *             control over lifecycle.
-             */
-            @Deprecated
-            public static final String insertImage(ContentResolver cr, Bitmap source, String title,
-                    String description) {
-                if (TextUtils.isEmpty(title)) title = "Image";
-
-                final long now = System.currentTimeMillis();
-                final ContentValues values = new ContentValues();
-                values.put(MediaColumns.DISPLAY_NAME, title);
-                values.put(MediaColumns.MIME_TYPE, "image/jpeg");
-                values.put(MediaColumns.DATE_ADDED, now / 1000);
-                values.put(MediaColumns.DATE_MODIFIED, now / 1000);
-                values.put(MediaColumns.DATE_EXPIRES, (now + DateUtils.DAY_IN_MILLIS) / 1000);
-                values.put(MediaColumns.IS_PENDING, 1);
-
-                final Uri uri = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
-                try {
-                    try (OutputStream out = cr.openOutputStream(uri)) {
-                        source.compress(Bitmap.CompressFormat.JPEG, 90, out);
-                    }
-
-                    // Everything went well above, publish it!
-                    values.clear();
-                    values.put(MediaColumns.IS_PENDING, 0);
-                    values.putNull(MediaColumns.DATE_EXPIRES);
-                    cr.update(uri, values, null, null);
-                    return uri.toString();
-                } catch (Exception e) {
-                    Log.w(TAG, "Failed to insert image", e);
-                    cr.delete(uri, null, null);
-                    return null;
-                }
-            }
-
-            /**
-             * Get the content:// style URI for the image media table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the image media table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("images")
-                        .appendPath("media").build();
-            }
-
-            /**
-             * Get the content:// style URI for a single row in the images table
-             * on the given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @param id the image to get the URI for
-             * @return the URI to the images table on the given volume
-             */
-            public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
-                return ContentUris.withAppendedId(getContentUri(volumeName), id);
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The MIME type of of this directory of
-             * images.  Note that each entry in this directory will have a standard
-             * image MIME type as appropriate -- for example, image/jpeg.
-             */
-            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image";
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = ImageColumns.BUCKET_DISPLAY_NAME;
-        }
-
-        /**
-         * This class provides utility methods to obtain thumbnails for various
-         * {@link Images} items.
-         *
-         * @deprecated Callers should migrate to using
-         *             {@link ContentResolver#loadThumbnail}, since it offers
-         *             richer control over requested thumbnail sizes and
-         *             cancellation behavior.
-         */
-        @Deprecated
-        public static class Thumbnails implements BaseColumns {
-            /**
-             * @deprecated all queries should be performed through
-             *             {@link ContentResolver} directly, which offers modern
-             *             features like {@link CancellationSignal}.
-             */
-            @Deprecated
-            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
-                return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
-            }
-
-            /**
-             * @deprecated all queries should be performed through
-             *             {@link ContentResolver} directly, which offers modern
-             *             features like {@link CancellationSignal}.
-             */
-            @Deprecated
-            public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind,
-                    String[] projection) {
-                return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER);
-            }
-
-            /**
-             * @deprecated all queries should be performed through
-             *             {@link ContentResolver} directly, which offers modern
-             *             features like {@link CancellationSignal}.
-             */
-            @Deprecated
-            public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind,
-                    String[] projection) {
-                return cr.query(EXTERNAL_CONTENT_URI, projection,
-                        IMAGE_ID + " = " + origId + " AND " + KIND + " = " +
-                        kind, null, null);
-            }
-
-            /**
-             * Cancel any outstanding {@link #getThumbnail} requests, causing
-             * them to return by throwing a {@link OperationCanceledException}.
-             * <p>
-             * This method has no effect on
-             * {@link ContentResolver#loadThumbnail} calls, since they provide
-             * their own {@link CancellationSignal}.
-             *
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static void cancelThumbnailRequest(ContentResolver cr, long origId) {
-                final Uri uri = ContentUris.withAppendedId(
-                        Images.Media.EXTERNAL_CONTENT_URI, origId);
-                InternalThumbnails.cancelThumbnail(cr, uri);
-            }
-
-            /**
-             * Return thumbnail representing a specific image item. If a
-             * thumbnail doesn't exist, this method will block until it's
-             * generated. Callers are responsible for their own in-memory
-             * caching of returned values.
-             *
-             * As of {@link android.os.Build.VERSION_CODES#Q}, this output
-             * of the thumbnail has correct rotation, don't need to rotate
-             * it again.
-             *
-             * @param imageId the image item to obtain a thumbnail for.
-             * @param kind optimal thumbnail size desired.
-             * @return decoded thumbnail, or {@code null} if problem was
-             *         encountered.
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static Bitmap getThumbnail(ContentResolver cr, long imageId, int kind,
-                    BitmapFactory.Options options) {
-                final Uri uri = ContentUris.withAppendedId(
-                        Images.Media.EXTERNAL_CONTENT_URI, imageId);
-                return InternalThumbnails.getThumbnail(cr, uri, kind, options);
-            }
-
-            /**
-             * Cancel any outstanding {@link #getThumbnail} requests, causing
-             * them to return by throwing a {@link OperationCanceledException}.
-             * <p>
-             * This method has no effect on
-             * {@link ContentResolver#loadThumbnail} calls, since they provide
-             * their own {@link CancellationSignal}.
-             *
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static void cancelThumbnailRequest(ContentResolver cr, long origId,
-                    long groupId) {
-                cancelThumbnailRequest(cr, origId);
-            }
-
-            /**
-             * Return thumbnail representing a specific image item. If a
-             * thumbnail doesn't exist, this method will block until it's
-             * generated. Callers are responsible for their own in-memory
-             * caching of returned values.
-             *
-             * As of {@link android.os.Build.VERSION_CODES#Q}, this output
-             * of the thumbnail has correct rotation, don't need to rotate
-             * it again.
-             *
-             * @param imageId the image item to obtain a thumbnail for.
-             * @param kind optimal thumbnail size desired.
-             * @return decoded thumbnail, or {@code null} if problem was
-             *         encountered.
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static Bitmap getThumbnail(ContentResolver cr, long imageId, long groupId,
-                    int kind, BitmapFactory.Options options) {
-                return getThumbnail(cr, imageId, kind, options);
-            }
-
-            /**
-             * Get the content:// style URI for the image media table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the image media table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("images")
-                        .appendPath("thumbnails").build();
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = "image_id ASC";
-
-            /**
-             * Path to the thumbnail file on disk.
-             * <p>
-             * Note that apps may not have filesystem permissions to directly
-             * access this path. Instead of trying to open this path directly,
-             * apps should use
-             * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
-             * access.
-             *
-             * As of {@link android.os.Build.VERSION_CODES#Q}, this thumbnail
-             * has correct rotation, don't need to rotate it again.
-             *
-             * @deprecated Apps may not have filesystem permissions to directly
-             *             access this path. Instead of trying to open this path
-             *             directly, apps should use
-             *             {@link ContentResolver#loadThumbnail}
-             *             to gain access.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String DATA = "_data";
-
-            /**
-             * The original image for the thumbnal
-             */
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String IMAGE_ID = "image_id";
-
-            /**
-             * The kind of the thumbnail
-             */
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String KIND = "kind";
-
-            public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
-            public static final int FULL_SCREEN_KIND = ThumbnailConstants.FULL_SCREEN_KIND;
-            public static final int MICRO_KIND = ThumbnailConstants.MICRO_KIND;
-
-            /**
-             * Return the typical {@link Size} (in pixels) used internally when
-             * the given thumbnail kind is requested.
-             */
-            public static @NonNull Size getKindSize(int kind) {
-                return ThumbnailConstants.getKindSize(kind);
-            }
-
-            /**
-             * The blob raw data of thumbnail
-             *
-             * @deprecated this column never existed internally, and could never
-             *             have returned valid data.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_BLOB)
-            public static final String THUMB_DATA = "thumb_data";
-
-            /**
-             * The width of the thumbnal
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String WIDTH = "width";
-
-            /**
-             * The height of the thumbnail
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String HEIGHT = "height";
-        }
-    }
-
-    /**
-     * Collection of all media with MIME type of {@code audio/*}.
-     */
-    public static final class Audio {
-        /**
-         * Audio metadata columns.
-         */
-        public interface AudioColumns extends MediaColumns {
-
-            /**
-             * A non human readable key calculated from the TITLE, used for
-             * searching, sorting and grouping
-             *
-             * @see Audio#keyFor(String)
-             * @deprecated These keys are generated using
-             *             {@link java.util.Locale#ROOT}, which means they don't
-             *             reflect locale-specific sorting preferences. To apply
-             *             locale-specific sorting preferences, use
-             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-             *             {@code COLLATE LOCALIZED}, or
-             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String TITLE_KEY = "title_key";
-
-            /** @removed promoted to parent interface */
-            public static final String DURATION = "duration";
-
-            /**
-             * The position within the audio item at which playback should be
-             * resumed.
-             */
-            @DurationMillisLong
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String BOOKMARK = "bookmark";
-
-            /**
-             * The id of the artist who created the audio file, if any
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String ARTIST_ID = "artist_id";
-
-            /** @removed promoted to parent interface */
-            public static final String ARTIST = "artist";
-
-            /**
-             * The artist credited for the album that contains the audio file
-             * @hide
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ALBUM_ARTIST = "album_artist";
-
-            /**
-             * A non human readable key calculated from the ARTIST, used for
-             * searching, sorting and grouping
-             *
-             * @see Audio#keyFor(String)
-             * @deprecated These keys are generated using
-             *             {@link java.util.Locale#ROOT}, which means they don't
-             *             reflect locale-specific sorting preferences. To apply
-             *             locale-specific sorting preferences, use
-             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-             *             {@code COLLATE LOCALIZED}, or
-             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ARTIST_KEY = "artist_key";
-
-            /** @removed promoted to parent interface */
-            public static final String COMPOSER = "composer";
-
-            /**
-             * The id of the album the audio file is from, if any
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String ALBUM_ID = "album_id";
-
-            /** @removed promoted to parent interface */
-            public static final String ALBUM = "album";
-
-            /**
-             * A non human readable key calculated from the ALBUM, used for
-             * searching, sorting and grouping
-             *
-             * @see Audio#keyFor(String)
-             * @deprecated These keys are generated using
-             *             {@link java.util.Locale#ROOT}, which means they don't
-             *             reflect locale-specific sorting preferences. To apply
-             *             locale-specific sorting preferences, use
-             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-             *             {@code COLLATE LOCALIZED}, or
-             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ALBUM_KEY = "album_key";
-
-            /**
-             * The track number of this song on the album, if any.
-             * This number encodes both the track number and the
-             * disc number. For multi-disc sets, this number will
-             * be 1xxx for tracks on the first disc, 2xxx for tracks
-             * on the second disc, etc.
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String TRACK = "track";
-
-            /**
-             * The year the audio file was recorded, if any
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String YEAR = "year";
-
-            /**
-             * Non-zero if the audio file is music
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String IS_MUSIC = "is_music";
-
-            /**
-             * Non-zero if the audio file is a podcast
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String IS_PODCAST = "is_podcast";
-
-            /**
-             * Non-zero if the audio file may be a ringtone
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String IS_RINGTONE = "is_ringtone";
-
-            /**
-             * Non-zero if the audio file may be an alarm
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String IS_ALARM = "is_alarm";
-
-            /**
-             * Non-zero if the audio file may be a notification sound
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String IS_NOTIFICATION = "is_notification";
-
-            /**
-             * Non-zero if the audio file is an audiobook
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String IS_AUDIOBOOK = "is_audiobook";
-
-            /**
-             * The id of the genre the audio file is from, if any
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String GENRE_ID = "genre_id";
-
-            /**
-             * The genre of the audio file, if any.
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String GENRE = "genre";
-
-            /**
-             * A non human readable key calculated from the GENRE, used for
-             * searching, sorting and grouping
-             *
-             * @see Audio#keyFor(String)
-             * @deprecated These keys are generated using
-             *             {@link java.util.Locale#ROOT}, which means they don't
-             *             reflect locale-specific sorting preferences. To apply
-             *             locale-specific sorting preferences, use
-             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-             *             {@code COLLATE LOCALIZED}, or
-             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String GENRE_KEY = "genre_key";
-
-            /**
-             * The resource URI of a localized title, if any.
-             * <p>
-             * Conforms to this pattern:
-             * <ul>
-             * <li>Scheme: {@link ContentResolver#SCHEME_ANDROID_RESOURCE}
-             * <li>Authority: Package Name of ringtone title provider
-             * <li>First Path Segment: Type of resource (must be "string")
-             * <li>Second Path Segment: Resource ID of title
-             * </ul>
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String TITLE_RESOURCE_URI = "title_resource_uri";
-        }
-
-        private static final Pattern PATTERN_TRIM_BEFORE = Pattern.compile(
-                "(?i)(^(the|an|a) |,\\s*(the|an|a)$|[^\\w\\s]|^\\s+|\\s+$)");
-        private static final Pattern PATTERN_TRIM_AFTER = Pattern.compile(
-                "(^(00)+|(00)+$)");
-
-        /**
-         * Converts a user-visible string into a "key" that can be used for
-         * grouping, sorting, and searching.
-         *
-         * @return Opaque token that should not be parsed or displayed to users.
-         * @deprecated These keys are generated using
-         *             {@link java.util.Locale#ROOT}, which means they don't
-         *             reflect locale-specific sorting preferences. To apply
-         *             locale-specific sorting preferences, use
-         *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-         *             {@code COLLATE LOCALIZED}, or
-         *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-         */
-        @Deprecated
-        public static @Nullable String keyFor(@Nullable String name) {
-            if (TextUtils.isEmpty(name)) return null;
-
-            if (UNKNOWN_STRING.equals(name)) {
-                return "01";
-            }
-
-            final boolean sortFirst = name.startsWith("\001");
-
-            name = PATTERN_TRIM_BEFORE.matcher(name).replaceAll("");
-            if (TextUtils.isEmpty(name)) return null;
-
-            final Collator c = Collator.getInstance(Locale.ROOT);
-            c.setStrength(Collator.PRIMARY);
-            name = HexEncoding.encodeToString(c.getCollationKey(name).toByteArray(), false);
-
-            name = PATTERN_TRIM_AFTER.matcher(name).replaceAll("");
-            if (sortFirst) {
-                name = "01" + name;
-            }
-            return name;
-        }
-
-        public static final class Media implements AudioColumns {
-            /**
-             * Get the content:// style URI for the audio media table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the audio media table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
-                        .appendPath("media").build();
-            }
-
-            /**
-             * Get the content:// style URI for a single row in the audio table
-             * on the given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @param id the audio to get the URI for
-             * @return the URI to the audio table on the given volume
-             */
-            public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
-                return ContentUris.withAppendedId(getContentUri(volumeName), id);
-            }
-
-            /**
-             * Get the content:// style URI for the given audio media file.
-             *
-             * @deprecated Apps may not have filesystem permissions to directly
-             *             access this path.
-             */
-            @Deprecated
-            public static @Nullable Uri getContentUriForPath(@NonNull String path) {
-                return getContentUri(getVolumeName(new File(path)));
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The MIME type for this table.
-             */
-            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/audio";
-
-            /**
-             * The MIME type for an audio track.
-             */
-            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/audio";
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = TITLE_KEY;
-
-            /**
-             * Activity Action: Start SoundRecorder application.
-             * <p>Input: nothing.
-             * <p>Output: An uri to the recorded sound stored in the Media Library
-             * if the recording was successful.
-             * May also contain the extra EXTRA_MAX_BYTES.
-             * @see #EXTRA_MAX_BYTES
-             */
-            @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-            public static final String RECORD_SOUND_ACTION =
-                    "android.provider.MediaStore.RECORD_SOUND";
-
-            /**
-             * The name of the Intent-extra used to define a maximum file size for
-             * a recording made by the SoundRecorder application.
-             *
-             * @see #RECORD_SOUND_ACTION
-             */
-             public static final String EXTRA_MAX_BYTES =
-                    "android.provider.MediaStore.extra.MAX_BYTES";
-        }
-
-        /**
-         * Audio genre metadata columns.
-         */
-        public interface GenresColumns {
-            /**
-             * The name of the genre
-             */
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String NAME = "name";
-        }
-
-        /**
-         * Contains all genres for audio files
-         */
-        public static final class Genres implements BaseColumns, GenresColumns {
-            /**
-             * Get the content:// style URI for the audio genres table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the audio genres table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
-                        .appendPath("genres").build();
-            }
-
-            /**
-             * Get the content:// style URI for querying the genres of an audio file.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @param audioId the ID of the audio file for which to retrieve the genres
-             * @return the URI to for querying the genres for the audio file
-             * with the given the volume and audioID
-             */
-            public static Uri getContentUriForAudioId(String volumeName, int audioId) {
-                return ContentUris.withAppendedId(Audio.Media.getContentUri(volumeName), audioId)
-                        .buildUpon().appendPath("genres").build();
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The MIME type for this table.
-             */
-            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/genre";
-
-            /**
-             * The MIME type for entries in this table.
-             */
-            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/genre";
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = NAME;
-
-            /**
-             * Sub-directory of each genre containing all members.
-             */
-            public static final class Members implements AudioColumns {
-
-                public static final Uri getContentUri(String volumeName, long genreId) {
-                    return ContentUris
-                            .withAppendedId(Audio.Genres.getContentUri(volumeName), genreId)
-                            .buildUpon().appendPath("members").build();
-                }
-
-                /**
-                 * A subdirectory of each genre containing all member audio files.
-                 */
-                public static final String CONTENT_DIRECTORY = "members";
-
-                /**
-                 * The default sort order for this table
-                 */
-                public static final String DEFAULT_SORT_ORDER = TITLE_KEY;
-
-                /**
-                 * The ID of the audio file
-                 */
-                @Column(Cursor.FIELD_TYPE_INTEGER)
-                public static final String AUDIO_ID = "audio_id";
-
-                /**
-                 * The ID of the genre
-                 */
-                @Column(Cursor.FIELD_TYPE_INTEGER)
-                public static final String GENRE_ID = "genre_id";
-            }
-        }
-
-        /**
-         * Audio playlist metadata columns.
-         */
-        public interface PlaylistsColumns {
-            /**
-             * The name of the playlist
-             */
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String NAME = "name";
-
-            /**
-             * Path to the playlist file on disk.
-             * <p>
-             * Note that apps may not have filesystem permissions to directly
-             * access this path. Instead of trying to open this path directly,
-             * apps should use
-             * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
-             * access.
-             *
-             * @deprecated Apps may not have filesystem permissions to directly
-             *             access this path. Instead of trying to open this path
-             *             directly, apps should use
-             *             {@link ContentResolver#openFileDescriptor(Uri, String)}
-             *             to gain access.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String DATA = "_data";
-
-            /**
-             * The time the media item was first added.
-             */
-            @CurrentTimeSecondsLong
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String DATE_ADDED = "date_added";
-
-            /**
-             * The time the media item was last modified.
-             */
-            @CurrentTimeSecondsLong
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String DATE_MODIFIED = "date_modified";
-        }
-
-        /**
-         * Contains playlists for audio files
-         */
-        public static final class Playlists implements BaseColumns,
-                PlaylistsColumns {
-            /**
-             * Get the content:// style URI for the audio playlists table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the audio playlists table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
-                        .appendPath("playlists").build();
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The MIME type for this table.
-             */
-            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/playlist";
-
-            /**
-             * The MIME type for entries in this table.
-             */
-            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/playlist";
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = NAME;
-
-            /**
-             * Sub-directory of each playlist containing all members.
-             */
-            public static final class Members implements AudioColumns {
-                public static final Uri getContentUri(String volumeName, long playlistId) {
-                    return ContentUris
-                            .withAppendedId(Audio.Playlists.getContentUri(volumeName), playlistId)
-                            .buildUpon().appendPath("members").build();
-                }
-
-                /**
-                 * Convenience method to move a playlist item to a new location
-                 * @param res The content resolver to use
-                 * @param playlistId The numeric id of the playlist
-                 * @param from The position of the item to move
-                 * @param to The position to move the item to
-                 * @return true on success
-                 */
-                public static final boolean moveItem(ContentResolver res,
-                        long playlistId, int from, int to) {
-                    Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external",
-                            playlistId)
-                            .buildUpon()
-                            .appendEncodedPath(String.valueOf(from))
-                            .appendQueryParameter("move", "true")
-                            .build();
-                    ContentValues values = new ContentValues();
-                    values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, to);
-                    return res.update(uri, values, null, null) != 0;
-                }
-
-                /**
-                 * The ID within the playlist.
-                 */
-                @Column(Cursor.FIELD_TYPE_INTEGER)
-                public static final String _ID = "_id";
-
-                /**
-                 * A subdirectory of each playlist containing all member audio
-                 * files.
-                 */
-                public static final String CONTENT_DIRECTORY = "members";
-
-                /**
-                 * The ID of the audio file
-                 */
-                @Column(Cursor.FIELD_TYPE_INTEGER)
-                public static final String AUDIO_ID = "audio_id";
-
-                /**
-                 * The ID of the playlist
-                 */
-                @Column(Cursor.FIELD_TYPE_INTEGER)
-                public static final String PLAYLIST_ID = "playlist_id";
-
-                /**
-                 * The order of the songs in the playlist
-                 */
-                @Column(Cursor.FIELD_TYPE_INTEGER)
-                public static final String PLAY_ORDER = "play_order";
-
-                /**
-                 * The default sort order for this table
-                 */
-                public static final String DEFAULT_SORT_ORDER = PLAY_ORDER;
-            }
-        }
-
-        /**
-         * Audio artist metadata columns.
-         */
-        public interface ArtistColumns {
-            /**
-             * The artist who created the audio file, if any
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ARTIST = "artist";
-
-            /**
-             * A non human readable key calculated from the ARTIST, used for
-             * searching, sorting and grouping
-             *
-             * @see Audio#keyFor(String)
-             * @deprecated These keys are generated using
-             *             {@link java.util.Locale#ROOT}, which means they don't
-             *             reflect locale-specific sorting preferences. To apply
-             *             locale-specific sorting preferences, use
-             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-             *             {@code COLLATE LOCALIZED}, or
-             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ARTIST_KEY = "artist_key";
-
-            /**
-             * The number of albums in the database for this artist
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String NUMBER_OF_ALBUMS = "number_of_albums";
-
-            /**
-             * The number of albums in the database for this artist
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String NUMBER_OF_TRACKS = "number_of_tracks";
-        }
-
-        /**
-         * Contains artists for audio files
-         */
-        public static final class Artists implements BaseColumns, ArtistColumns {
-            /**
-             * Get the content:// style URI for the artists table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the audio artists table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
-                        .appendPath("artists").build();
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The MIME type for this table.
-             */
-            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/artists";
-
-            /**
-             * The MIME type for entries in this table.
-             */
-            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/artist";
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = ARTIST_KEY;
-
-            /**
-             * Sub-directory of each artist containing all albums on which
-             * a song by the artist appears.
-             */
-            public static final class Albums implements AlbumColumns {
-                public static final Uri getContentUri(String volumeName,long artistId) {
-                    return ContentUris
-                            .withAppendedId(Audio.Artists.getContentUri(volumeName), artistId)
-                            .buildUpon().appendPath("albums").build();
-                }
-            }
-        }
-
-        /**
-         * Audio album metadata columns.
-         */
-        public interface AlbumColumns {
-
-            /**
-             * The id for the album
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String ALBUM_ID = "album_id";
-
-            /**
-             * The album on which the audio file appears, if any
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ALBUM = "album";
-
-            /**
-             * The ID of the artist whose songs appear on this album.
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String ARTIST_ID = "artist_id";
-
-            /**
-             * The name of the artist whose songs appear on this album.
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ARTIST = "artist";
-
-            /**
-             * A non human readable key calculated from the ARTIST, used for
-             * searching, sorting and grouping
-             *
-             * @see Audio#keyFor(String)
-             * @deprecated These keys are generated using
-             *             {@link java.util.Locale#ROOT}, which means they don't
-             *             reflect locale-specific sorting preferences. To apply
-             *             locale-specific sorting preferences, use
-             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-             *             {@code COLLATE LOCALIZED}, or
-             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ARTIST_KEY = "artist_key";
-
-            /**
-             * The number of songs on this album
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String NUMBER_OF_SONGS = "numsongs";
-
-            /**
-             * This column is available when getting album info via artist,
-             * and indicates the number of songs on the album by the given
-             * artist.
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String NUMBER_OF_SONGS_FOR_ARTIST = "numsongs_by_artist";
-
-            /**
-             * The year in which the earliest songs
-             * on this album were released. This will often
-             * be the same as {@link #LAST_YEAR}, but for compilation albums
-             * they might differ.
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String FIRST_YEAR = "minyear";
-
-            /**
-             * The year in which the latest songs
-             * on this album were released. This will often
-             * be the same as {@link #FIRST_YEAR}, but for compilation albums
-             * they might differ.
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String LAST_YEAR = "maxyear";
-
-            /**
-             * A non human readable key calculated from the ALBUM, used for
-             * searching, sorting and grouping
-             *
-             * @see Audio#keyFor(String)
-             * @deprecated These keys are generated using
-             *             {@link java.util.Locale#ROOT}, which means they don't
-             *             reflect locale-specific sorting preferences. To apply
-             *             locale-specific sorting preferences, use
-             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
-             *             {@code COLLATE LOCALIZED}, or
-             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String ALBUM_KEY = "album_key";
-
-            /**
-             * Cached album art.
-             *
-             * @deprecated Apps may not have filesystem permissions to directly
-             *             access this path. Instead of trying to open this path
-             *             directly, apps should use
-             *             {@link ContentResolver#loadThumbnail}
-             *             to gain access.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String ALBUM_ART = "album_art";
-        }
-
-        /**
-         * Contains artists for audio files
-         */
-        public static final class Albums implements BaseColumns, AlbumColumns {
-            /**
-             * Get the content:// style URI for the albums table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the audio albums table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
-                        .appendPath("albums").build();
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The MIME type for this table.
-             */
-            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/albums";
-
-            /**
-             * The MIME type for entries in this table.
-             */
-            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/album";
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = ALBUM_KEY;
-        }
-
-        public static final class Radio {
-            /**
-             * The MIME type for entries in this table.
-             */
-            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/radio";
-
-            // Not instantiable.
-            private Radio() { }
-        }
-
-        /**
-         * This class provides utility methods to obtain thumbnails for various
-         * {@link Audio} items.
-         *
-         * @deprecated Callers should migrate to using
-         *             {@link ContentResolver#loadThumbnail}, since it offers
-         *             richer control over requested thumbnail sizes and
-         *             cancellation behavior.
-         * @hide
-         */
-        @Deprecated
-        public static class Thumbnails implements BaseColumns {
-            /**
-             * Path to the thumbnail file on disk.
-             * <p>
-             * Note that apps may not have filesystem permissions to directly
-             * access this path. Instead of trying to open this path directly,
-             * apps should use
-             * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
-             * access.
-             *
-             * @deprecated Apps may not have filesystem permissions to directly
-             *             access this path. Instead of trying to open this path
-             *             directly, apps should use
-             *             {@link ContentResolver#loadThumbnail}
-             *             to gain access.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String DATA = "_data";
-
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String ALBUM_ID = "album_id";
-        }
-    }
-
-    /**
-     * Collection of all media with MIME type of {@code video/*}.
-     */
-    public static final class Video {
-
-        /**
-         * The default sort order for this table.
-         */
-        public static final String DEFAULT_SORT_ORDER = MediaColumns.DISPLAY_NAME;
-
-        /**
-         * @deprecated all queries should be performed through
-         *             {@link ContentResolver} directly, which offers modern
-         *             features like {@link CancellationSignal}.
-         */
-        @Deprecated
-        public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
-            return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
-        }
-
-        /**
-         * Video metadata columns.
-         */
-        public interface VideoColumns extends MediaColumns {
-            /** @removed promoted to parent interface */
-            public static final String DURATION = "duration";
-            /** @removed promoted to parent interface */
-            public static final String ARTIST = "artist";
-            /** @removed promoted to parent interface */
-            public static final String ALBUM = "album";
-            /** @removed promoted to parent interface */
-            public static final String RESOLUTION = "resolution";
-
-            /**
-             * The description of the video recording
-             */
-            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
-            public static final String DESCRIPTION = "description";
-
-            /**
-             * Whether the video should be published as public or private
-             */
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String IS_PRIVATE = "isprivate";
-
-            /**
-             * The user-added tags associated with a video
-             */
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String TAGS = "tags";
-
-            /**
-             * The YouTube category of the video
-             */
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String CATEGORY = "category";
-
-            /**
-             * The language of the video
-             */
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String LANGUAGE = "language";
-
-            /**
-             * The latitude where the video was captured.
-             *
-             * @deprecated location details are no longer indexed for privacy
-             *             reasons, and this value is now always {@code null}.
-             *             You can still manually obtain location metadata using
-             *             {@link ExifInterface#getLatLong(float[])}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
-            public static final String LATITUDE = "latitude";
-
-            /**
-             * The longitude where the video was captured.
-             *
-             * @deprecated location details are no longer indexed for privacy
-             *             reasons, and this value is now always {@code null}.
-             *             You can still manually obtain location metadata using
-             *             {@link ExifInterface#getLatLong(float[])}.
-             */
-            @Deprecated
-            @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
-            public static final String LONGITUDE = "longitude";
-
-            /** @removed promoted to parent interface */
-            public static final String DATE_TAKEN = "datetaken";
-
-            /**
-             * The mini thumb id.
-             *
-             * @deprecated all thumbnails should be obtained via
-             *             {@link MediaStore.Images.Thumbnails#getThumbnail}, as this
-             *             value is no longer supported.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
-
-            /** @removed promoted to parent interface */
-            public static final String BUCKET_ID = "bucket_id";
-            /** @removed promoted to parent interface */
-            public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
-            /** @removed promoted to parent interface */
-            public static final String GROUP_ID = "group_id";
-
-            /**
-             * The position within the video item at which playback should be
-             * resumed.
-             */
-            @DurationMillisLong
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String BOOKMARK = "bookmark";
-
-            /**
-             * The color standard of this media file, if available.
-             *
-             * @see MediaFormat#COLOR_STANDARD_BT709
-             * @see MediaFormat#COLOR_STANDARD_BT601_PAL
-             * @see MediaFormat#COLOR_STANDARD_BT601_NTSC
-             * @see MediaFormat#COLOR_STANDARD_BT2020
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String COLOR_STANDARD = "color_standard";
-
-            /**
-             * The color transfer of this media file, if available.
-             *
-             * @see MediaFormat#COLOR_TRANSFER_LINEAR
-             * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO
-             * @see MediaFormat#COLOR_TRANSFER_ST2084
-             * @see MediaFormat#COLOR_TRANSFER_HLG
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String COLOR_TRANSFER = "color_transfer";
-
-            /**
-             * The color range of this media file, if available.
-             *
-             * @see MediaFormat#COLOR_RANGE_LIMITED
-             * @see MediaFormat#COLOR_RANGE_FULL
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String COLOR_RANGE = "color_range";
-        }
-
-        public static final class Media implements VideoColumns {
-            /**
-             * Get the content:// style URI for the video media table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the video media table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("video")
-                        .appendPath("media").build();
-            }
-
-            /**
-             * Get the content:// style URI for a single row in the videos table
-             * on the given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @param id the video to get the URI for
-             * @return the URI to the videos table on the given volume
-             */
-            public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
-                return ContentUris.withAppendedId(getContentUri(volumeName), id);
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The MIME type for this table.
-             */
-            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/video";
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = TITLE;
-        }
-
-        /**
-         * This class provides utility methods to obtain thumbnails for various
-         * {@link Video} items.
-         *
-         * @deprecated Callers should migrate to using
-         *             {@link ContentResolver#loadThumbnail}, since it offers
-         *             richer control over requested thumbnail sizes and
-         *             cancellation behavior.
-         */
-        @Deprecated
-        public static class Thumbnails implements BaseColumns {
-            /**
-             * Cancel any outstanding {@link #getThumbnail} requests, causing
-             * them to return by throwing a {@link OperationCanceledException}.
-             * <p>
-             * This method has no effect on
-             * {@link ContentResolver#loadThumbnail} calls, since they provide
-             * their own {@link CancellationSignal}.
-             *
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static void cancelThumbnailRequest(ContentResolver cr, long origId) {
-                final Uri uri = ContentUris.withAppendedId(
-                        Video.Media.EXTERNAL_CONTENT_URI, origId);
-                InternalThumbnails.cancelThumbnail(cr, uri);
-            }
-
-            /**
-             * Return thumbnail representing a specific video item. If a
-             * thumbnail doesn't exist, this method will block until it's
-             * generated. Callers are responsible for their own in-memory
-             * caching of returned values.
-             *
-             * @param videoId the video item to obtain a thumbnail for.
-             * @param kind optimal thumbnail size desired.
-             * @return decoded thumbnail, or {@code null} if problem was
-             *         encountered.
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static Bitmap getThumbnail(ContentResolver cr, long videoId, int kind,
-                    BitmapFactory.Options options) {
-                final Uri uri = ContentUris.withAppendedId(
-                        Video.Media.EXTERNAL_CONTENT_URI, videoId);
-                return InternalThumbnails.getThumbnail(cr, uri, kind, options);
-            }
-
-            /**
-             * Cancel any outstanding {@link #getThumbnail} requests, causing
-             * them to return by throwing a {@link OperationCanceledException}.
-             * <p>
-             * This method has no effect on
-             * {@link ContentResolver#loadThumbnail} calls, since they provide
-             * their own {@link CancellationSignal}.
-             *
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static void cancelThumbnailRequest(ContentResolver cr, long videoId,
-                    long groupId) {
-                cancelThumbnailRequest(cr, videoId);
-            }
-
-            /**
-             * Return thumbnail representing a specific video item. If a
-             * thumbnail doesn't exist, this method will block until it's
-             * generated. Callers are responsible for their own in-memory
-             * caching of returned values.
-             *
-             * @param videoId the video item to obtain a thumbnail for.
-             * @param kind optimal thumbnail size desired.
-             * @return decoded thumbnail, or {@code null} if problem was
-             *         encountered.
-             * @deprecated Callers should migrate to using
-             *             {@link ContentResolver#loadThumbnail}, since it
-             *             offers richer control over requested thumbnail sizes
-             *             and cancellation behavior.
-             */
-            @Deprecated
-            public static Bitmap getThumbnail(ContentResolver cr, long videoId, long groupId,
-                    int kind, BitmapFactory.Options options) {
-                return getThumbnail(cr, videoId, kind, options);
-            }
-
-            /**
-             * Get the content:// style URI for the image media table on the
-             * given volume.
-             *
-             * @param volumeName the name of the volume to get the URI for
-             * @return the URI to the image media table on the given volume
-             */
-            public static Uri getContentUri(String volumeName) {
-                return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("video")
-                        .appendPath("thumbnails").build();
-            }
-
-            /**
-             * The content:// style URI for the internal storage.
-             */
-            public static final Uri INTERNAL_CONTENT_URI =
-                    getContentUri("internal");
-
-            /**
-             * The content:// style URI for the "primary" external storage
-             * volume.
-             */
-            public static final Uri EXTERNAL_CONTENT_URI =
-                    getContentUri("external");
-
-            /**
-             * The default sort order for this table
-             */
-            public static final String DEFAULT_SORT_ORDER = "video_id ASC";
-
-            /**
-             * Path to the thumbnail file on disk.
-             *
-             * @deprecated Apps may not have filesystem permissions to directly
-             *             access this path. Instead of trying to open this path
-             *             directly, apps should use
-             *             {@link ContentResolver#openFileDescriptor(Uri, String)}
-             *             to gain access.
-             */
-            @Deprecated
-            @Column(Cursor.FIELD_TYPE_STRING)
-            public static final String DATA = "_data";
-
-            /**
-             * The original image for the thumbnal
-             */
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String VIDEO_ID = "video_id";
-
-            /**
-             * The kind of the thumbnail
-             */
-            @Column(Cursor.FIELD_TYPE_INTEGER)
-            public static final String KIND = "kind";
-
-            public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
-            public static final int FULL_SCREEN_KIND = ThumbnailConstants.FULL_SCREEN_KIND;
-            public static final int MICRO_KIND = ThumbnailConstants.MICRO_KIND;
-
-            /**
-             * Return the typical {@link Size} (in pixels) used internally when
-             * the given thumbnail kind is requested.
-             */
-            public static @NonNull Size getKindSize(int kind) {
-                return ThumbnailConstants.getKindSize(kind);
-            }
-
-            /**
-             * The width of the thumbnal
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String WIDTH = "width";
-
-            /**
-             * The height of the thumbnail
-             */
-            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
-            public static final String HEIGHT = "height";
-        }
-    }
-
-    /** @removed */
-    @Deprecated
-    public static @NonNull Set<String> getAllVolumeNames(@NonNull Context context) {
-        return getExternalVolumeNames(context);
-    }
-
-    /**
-     * Return list of all specific volume names that make up
-     * {@link #VOLUME_EXTERNAL}. This includes a unique volume name for each
-     * shared storage device that is currently attached, which typically
-     * includes {@link MediaStore#VOLUME_EXTERNAL_PRIMARY}.
-     * <p>
-     * Each specific volume name can be passed to APIs like
-     * {@link MediaStore.Images.Media#getContentUri(String)} to interact with
-     * media on that storage device.
-     */
-    public static @NonNull Set<String> getExternalVolumeNames(@NonNull Context context) {
-        final StorageManager sm = context.getSystemService(StorageManager.class);
-        final Set<String> res = new ArraySet<>();
-        for (StorageVolume sv : sm.getStorageVolumes()) {
-            switch (sv.getState()) {
-                case Environment.MEDIA_MOUNTED:
-                case Environment.MEDIA_MOUNTED_READ_ONLY: {
-                    final String volumeName = sv.getMediaStoreVolumeName();
-                    if (volumeName != null) {
-                        res.add(volumeName);
-                    }
-                    break;
-                }
-            }
-        }
-        return res;
-    }
-
-    /**
-     * Return list of all recent volume names that have been part of
-     * {@link #VOLUME_EXTERNAL}.
-     * <p>
-     * These volume names are not currently mounted, but they're likely to
-     * reappear in the future, so apps are encouraged to preserve any indexed
-     * metadata related to these volumes to optimize user experiences.
-     * <p>
-     * Each specific volume name can be passed to APIs like
-     * {@link MediaStore.Images.Media#getContentUri(String)} to interact with
-     * media on that storage device.
-     */
-    public static @NonNull Set<String> getRecentExternalVolumeNames(@NonNull Context context) {
-        final StorageManager sm = context.getSystemService(StorageManager.class);
-        final Set<String> res = new ArraySet<>();
-        for (StorageVolume sv : sm.getRecentStorageVolumes()) {
-            final String volumeName = sv.getMediaStoreVolumeName();
-            if (volumeName != null) {
-                res.add(volumeName);
-            }
-        }
-        return res;
-    }
-
-    /**
-     * Return the volume name that the given {@link Uri} references.
-     */
-    public static @NonNull String getVolumeName(@NonNull Uri uri) {
-        final List<String> segments = uri.getPathSegments();
-        switch (uri.getAuthority()) {
-            case AUTHORITY:
-            case AUTHORITY_LEGACY: {
-                if (segments != null && segments.size() > 0) {
-                    return segments.get(0);
-                }
-            }
-        }
-        throw new IllegalArgumentException("Missing volume name: " + uri);
-    }
-
-    /** {@hide} */
-    public static @NonNull String checkArgumentVolumeName(@NonNull String volumeName) {
-        if (TextUtils.isEmpty(volumeName)) {
-            throw new IllegalArgumentException();
-        }
-
-        if (VOLUME_INTERNAL.equals(volumeName)) {
-            return volumeName;
-        } else if (VOLUME_EXTERNAL.equals(volumeName)) {
-            return volumeName;
-        } else if (VOLUME_EXTERNAL_PRIMARY.equals(volumeName)) {
-            return volumeName;
-        }
-
-        // When not one of the well-known values above, it must be a hex UUID
-        for (int i = 0; i < volumeName.length(); i++) {
-            final char c = volumeName.charAt(i);
-            if (('a' <= c && c <= 'f') || ('0' <= c && c <= '9') || (c == '-')) {
-                continue;
-            } else {
-                throw new IllegalArgumentException("Invalid volume name: " + volumeName);
-            }
-        }
-        return volumeName;
-    }
-
-    private static boolean parseBoolean(@Nullable String value) {
-        if (value == null) return false;
-        if ("1".equals(value)) return true;
-        if ("true".equalsIgnoreCase(value)) return true;
-        return false;
-    }
-
-    /**
-     * Uri for querying the state of the media scanner.
-     */
-    public static Uri getMediaScannerUri() {
-        return AUTHORITY_URI.buildUpon().appendPath("none").appendPath("media_scanner").build();
-    }
-
-    /**
-     * Name of current volume being scanned by the media scanner.
-     */
-    public static final String MEDIA_SCANNER_VOLUME = "volume";
-
-    /**
-     * Name of the file signaling the media scanner to ignore media in the containing directory
-     * and its subdirectories. Developers should use this to avoid application graphics showing
-     * up in the Gallery and likewise prevent application sounds and music from showing up in
-     * the Music app.
-     */
-    public static final String MEDIA_IGNORE_FILENAME = ".nomedia";
-
-    /**
-     * Return an opaque version string describing the {@link MediaStore} state.
-     * <p>
-     * Applications that import data from {@link MediaStore} into their own
-     * caches can use this to detect that {@link MediaStore} has undergone
-     * substantial changes, and that data should be rescanned.
-     * <p>
-     * No other assumptions should be made about the meaning of the version.
-     * <p>
-     * This method returns the version for
-     * {@link MediaStore#VOLUME_EXTERNAL_PRIMARY}; to obtain a version for a
-     * different volume, use {@link #getVersion(Context, String)}.
-     */
-    public static @NonNull String getVersion(@NonNull Context context) {
-        return getVersion(context, VOLUME_EXTERNAL_PRIMARY);
-    }
-
-    /**
-     * Return an opaque version string describing the {@link MediaStore} state.
-     * <p>
-     * Applications that import data from {@link MediaStore} into their own
-     * caches can use this to detect that {@link MediaStore} has undergone
-     * substantial changes, and that data should be rescanned.
-     * <p>
-     * No other assumptions should be made about the meaning of the version.
-     *
-     * @param volumeName specific volume to obtain an opaque version string for.
-     *            Must be one of the values returned from
-     *            {@link #getExternalVolumeNames(Context)}.
-     */
-    public static @NonNull String getVersion(@NonNull Context context, @NonNull String volumeName) {
-        final ContentResolver resolver = context.getContentResolver();
-        try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
-            final Bundle in = new Bundle();
-            in.putString(Intent.EXTRA_TEXT, volumeName);
-            final Bundle out = client.call(GET_VERSION_CALL, null, in);
-            return out.getString(Intent.EXTRA_TEXT);
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Return a {@link DocumentsProvider} Uri that is an equivalent to the given
-     * {@link MediaStore} Uri.
-     * <p>
-     * This allows apps with Storage Access Framework permissions to convert
-     * between {@link MediaStore} and {@link DocumentsProvider} Uris that refer
-     * to the same underlying item. Note that this method doesn't grant any new
-     * permissions; callers must already hold permissions obtained with
-     * {@link Intent#ACTION_OPEN_DOCUMENT} or related APIs.
-     *
-     * @param mediaUri The {@link MediaStore} Uri to convert.
-     * @return An equivalent {@link DocumentsProvider} Uri. Returns {@code null}
-     *         if no equivalent was found.
-     * @see #getMediaUri(Context, Uri)
-     */
-    public static @Nullable Uri getDocumentUri(@NonNull Context context, @NonNull Uri mediaUri) {
-        final ContentResolver resolver = context.getContentResolver();
-        final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
-
-        try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
-            final Bundle in = new Bundle();
-            in.putParcelable(EXTRA_URI, mediaUri);
-            in.putParcelableArrayList(EXTRA_URI_PERMISSIONS, new ArrayList<>(uriPermissions));
-            final Bundle out = client.call(GET_DOCUMENT_URI_CALL, null, in);
-            return out.getParcelable(EXTRA_URI);
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Return a {@link MediaStore} Uri that is an equivalent to the given
-     * {@link DocumentsProvider} Uri.
-     * <p>
-     * This allows apps with Storage Access Framework permissions to convert
-     * between {@link MediaStore} and {@link DocumentsProvider} Uris that refer
-     * to the same underlying item. Note that this method doesn't grant any new
-     * permissions; callers must already hold permissions obtained with
-     * {@link Intent#ACTION_OPEN_DOCUMENT} or related APIs.
-     *
-     * @param documentUri The {@link DocumentsProvider} Uri to convert.
-     * @return An equivalent {@link MediaStore} Uri. Returns {@code null} if no
-     *         equivalent was found.
-     * @see #getDocumentUri(Context, Uri)
-     */
-    public static @Nullable Uri getMediaUri(@NonNull Context context, @NonNull Uri documentUri) {
-        final ContentResolver resolver = context.getContentResolver();
-        final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
-
-        try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
-            final Bundle in = new Bundle();
-            in.putParcelable(EXTRA_URI, documentUri);
-            in.putParcelableArrayList(EXTRA_URI_PERMISSIONS, new ArrayList<>(uriPermissions));
-            final Bundle out = client.call(GET_MEDIA_URI_CALL, null, in);
-            return out.getParcelable(EXTRA_URI);
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }
-    }
-
-    /** @hide */
-    @TestApi
-    public static void waitForIdle(@NonNull ContentResolver resolver) {
-        resolver.call(AUTHORITY, WAIT_FOR_IDLE_CALL, null, null);
-    }
-
-    /**
-     * Perform a blocking scan of the given {@link File}, returning the
-     * {@link Uri} of the scanned file.
-     *
-     * @hide
-     */
-    @SystemApi
-    @TestApi
-    @SuppressLint("StreamFiles")
-    public static @NonNull Uri scanFile(@NonNull ContentResolver resolver, @NonNull File file) {
-        final Bundle out = resolver.call(AUTHORITY, SCAN_FILE_CALL, file.getAbsolutePath(), null);
-        return out.getParcelable(Intent.EXTRA_STREAM);
-    }
-
-    /**
-     * Perform a blocking scan of the given storage volume.
-     *
-     * @hide
-     */
-    @SystemApi
-    @TestApi
-    public static void scanVolume(@NonNull ContentResolver resolver, @NonNull String volumeName) {
-        resolver.call(AUTHORITY, SCAN_VOLUME_CALL, volumeName, null);
-    }
-}
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index a46ad6d..738965e 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -37,6 +37,7 @@
   "/apex/com.android.conscrypt/javalib/conscrypt.jar",
   "/apex/com.android.ipsec/javalib/ike.jar",
   "/apex/com.android.media/javalib/updatable-media.jar",
+  "/apex/com.android.mediaprovider/javalib/framework-mediaprovider.jar",
   "/apex/com.android.os.statsd/javalib/framework-statsd.jar",
   "/apex/com.android.sdkext/javalib/framework-sdkext.jar",
   "/apex/com.android.telephony/javalib/telephony-common.jar",
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 7b2922ba..1e19786 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -102,6 +102,9 @@
             DocumentsContract.EXTERNAL_STORAGE_PRIMARY_EMULATED_ROOT_ID;
     private static final String ROOT_ID_HOME = "home";
 
+    private static final String GET_DOCUMENT_URI_CALL = "get_document_uri";
+    private static final String GET_MEDIA_URI_CALL = "get_media_uri";
+
     private StorageManager mStorageManager;
     private UserManager mUserManager;
 
@@ -665,7 +668,7 @@
                     }
                     break;
                 }
-                case MediaStore.GET_DOCUMENT_URI_CALL: {
+                case GET_DOCUMENT_URI_CALL: {
                     // All callers must go through MediaProvider
                     getContext().enforceCallingPermission(
                             android.Manifest.permission.WRITE_MEDIA_STORAGE, TAG);
@@ -684,7 +687,7 @@
                         throw new IllegalStateException("File in " + path + " is not found.", e);
                     }
                 }
-                case MediaStore.GET_MEDIA_URI_CALL: {
+                case GET_MEDIA_URI_CALL: {
                     // All callers must go through MediaProvider
                     getContext().enforceCallingPermission(
                             android.Manifest.permission.WRITE_MEDIA_STORAGE, TAG);