Merge "Import translations. DO NOT MERGE ANYWHERE" into sc-mainline-prod
diff --git a/.gitignore b/.gitignore
index be6b71b..74b2e0b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
 # Intellij
 **/.idea/
 *.iml
+local.properties
+# Gradle
+**/.gradle/
diff --git a/apex/framework/java/android/provider/CloudMediaProviderContract.java b/apex/framework/java/android/provider/CloudMediaProviderContract.java
index 840f009..6cb68e9 100644
--- a/apex/framework/java/android/provider/CloudMediaProviderContract.java
+++ b/apex/framework/java/android/provider/CloudMediaProviderContract.java
@@ -16,7 +16,6 @@
 
 package android.provider;
 
-import android.annotation.SystemApi;
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Intent;
@@ -115,6 +114,36 @@
         public static final String MIME_TYPE = "mime_type";
 
         /**
+         * Mime-type extension representing special format for a media item.
+         *
+         * Photo Picker requires special format tagging for media items.
+         * This is essential as media items can have various formats like
+         * Motion Photos, GIFs etc, which are not identifiable by
+         * {@link #MIME_TYPE}.
+         * <p>
+         * Type: INTEGER
+         */
+        public static final String STANDARD_MIME_TYPE_EXTENSION = "standard_mime_type_extension";
+
+        /**
+         * Constant for the {@link #STANDARD_MIME_TYPE_EXTENSION} column indicating
+         * that the media item doesn't have any special format associated with it.
+         */
+        public static final int STANDARD_MIME_TYPE_EXTENSION_NONE = 0;
+
+        /**
+         * Constant for the {@link #STANDARD_MIME_TYPE_EXTENSION} column indicating
+         * that the media item is a GIF.
+         */
+        public static final int STANDARD_MIME_TYPE_EXTENSION_GIF = 1;
+
+        /**
+         * Constant for the {@link #STANDARD_MIME_TYPE_EXTENSION} column indicating
+         * that the media item is a Motion Photo.
+         */
+        public static final int STANDARD_MIME_TYPE_EXTENSION_MOTION_PHOTO = 2;
+
+        /**
          * Size of a media file, in bytes.
          * <p>
          * Type: LONG
diff --git a/apex/framework/java/android/provider/MediaStore.java b/apex/framework/java/android/provider/MediaStore.java
index 39df119..36df668 100644
--- a/apex/framework/java/android/provider/MediaStore.java
+++ b/apex/framework/java/android/provider/MediaStore.java
@@ -2062,7 +2062,7 @@
              * Photo Picker requires special format tagging for media files.
              * This is essential as {@link Images} collection can include
              * images of various formats like Motion Photos, GIFs etc, which
-             * is not identifiable by {@link #MIME_TYPE}
+             * is not identifiable by {@link #MIME_TYPE}.
              *
              * @hide
              */
@@ -2072,29 +2072,30 @@
             /**
              * Constant for the {@link #_SPECIAL_FORMAT} column indicating
              * that the file doesn't have any special format associated with it.
-             * TODO(b/199522401): Expose these as public API for cloud providers.
              *
              * @hide
              */
-            public static final int _SPECIAL_FORMAT_NONE = 0;
+            public static final int _SPECIAL_FORMAT_NONE =
+                    CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE;
 
             /**
              * Constant for the {@link #_SPECIAL_FORMAT} column indicating
              * that the file is a GIF file.
-             * TODO(b/199522401): Expose these as public API for cloud providers.
              *
              * @hide
              */
-            public static final int _SPECIAL_FORMAT_GIF = 1;
+            public static final int _SPECIAL_FORMAT_GIF =
+                    CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION_GIF;
 
             /**
              * Constant for the {@link #_SPECIAL_FORMAT} column indicating
              * that the file is a Motion Photo.
-             * TODO(b/199522401): Expose these as public API for cloud providers.
              *
              * @hide
              */
-            public static final int _SPECIAL_FORMAT_MOTION_PHOTO = 2;
+            public static final int _SPECIAL_FORMAT_MOTION_PHOTO =
+                    CloudMediaProviderContract.MediaColumns.
+                            STANDARD_MIME_TYPE_EXTENSION_MOTION_PHOTO;
         }
     }
 
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 0981b5b..8760947 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -3661,8 +3661,8 @@
                 // gallery is not allowed to create non-default top level directory.
                 final boolean createNonDefaultTopLevelDir = primary != null &&
                         !FileUtils.buildPath(volumePath, primary).exists();
-                validPath = !createNonDefaultTopLevelDir &&
-                        canAccessMediaFile(res.getAbsolutePath(), /*allowLegacy*/ false);
+                validPath = !createNonDefaultTopLevelDir && canAccessMediaFile(
+                        res.getAbsolutePath(), /*excludeNonSystemGallery*/ true);
             }
 
             // Nothing left to check; caller can't use this path
@@ -7039,8 +7039,8 @@
 
         // 2. Check if the calling package is a special app which has global access
         if (isCallingPackageManager() ||
-                (canAccessMediaFile(srcPath, /* allowLegacy */ false) &&
-                        (canAccessMediaFile(destPath, /* allowLegacy */ false)))) {
+                (canAccessMediaFile(srcPath, /* excludeNonSystemGallery */ true) &&
+                        (canAccessMediaFile(destPath, /* excludeNonSystemGallery */ true)))) {
             return true;
         }
 
@@ -8117,8 +8117,8 @@
         return MimeUtils.resolveMediaType(mimeType);
     }
 
-    private boolean canAccessMediaFile(String filePath, boolean allowLegacy) {
-        if (!allowLegacy && isCallingPackageRequestingLegacy()) {
+    private boolean canAccessMediaFile(String filePath, boolean excludeNonSystemGallery) {
+        if (excludeNonSystemGallery && !isCallingPackageSystemGallery()) {
             return false;
         }
         switch (getFileMediaType(filePath)) {
@@ -8160,7 +8160,7 @@
 
         // Apps with write access to images and/or videos can bypass our restrictions if all of the
         // the files they're accessing are of the compatible media type.
-        if (canAccessMediaFile(filePath, /*allowLegacy*/ true)) {
+        if (canAccessMediaFile(filePath, /*excludeNonSystemGallery*/ false)) {
             return true;
         }
 
diff --git a/src/com/android/providers/media/PickerUriResolver.java b/src/com/android/providers/media/PickerUriResolver.java
index 6f5c83b..2473877 100644
--- a/src/com/android/providers/media/PickerUriResolver.java
+++ b/src/com/android/providers/media/PickerUriResolver.java
@@ -94,12 +94,15 @@
         checkUriPermission(uri, callingPid, callingUid);
 
         final ContentResolver resolver = getContentResolverForUserId(uri);
-        final long token = Binder.clearCallingIdentity();
-        try {
-            if (PickerDbFacade.isPickerDbEnabled()) {
+        if (PickerDbFacade.isPickerDbEnabled()) {
+            if (canHandleUriInUser(uri)) {
                 return openPickerFile(uri);
             }
+            return resolver.openFile(uri, mode, signal);
+        }
 
+        final long token = Binder.clearCallingIdentity();
+        try {
             uri = getRedactedFileUriFromPickerUri(uri, resolver);
             return resolver.openFile(uri, "r", signal);
         } finally {
@@ -113,13 +116,16 @@
         checkUriPermission(uri, callingPid, callingUid);
 
         final ContentResolver resolver = getContentResolverForUserId(uri);
-        final long token = Binder.clearCallingIdentity();
-        try {
-            if (PickerDbFacade.isPickerDbEnabled()) {
+        if (PickerDbFacade.isPickerDbEnabled()) {
+            if (canHandleUriInUser(uri)) {
                 return new AssetFileDescriptor(openPickerFile(uri), 0,
                         AssetFileDescriptor.UNKNOWN_LENGTH);
             }
+            return resolver.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
+        }
 
+        final long token = Binder.clearCallingIdentity();
+        try {
             uri = getRedactedFileUriFromPickerUri(uri, resolver);
             return resolver.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
         } finally {
@@ -139,7 +145,34 @@
         }
     }
 
+    // TODO(b/191362529): Restrict projection values when we start querying picker db.
+    // Add PickerColumns and add checks for projection.
+    private Cursor queryInternal(Uri uri, String[] projection, Bundle queryArgs,
+            CancellationSignal signal) throws FileNotFoundException {
+        final ContentResolver resolver = getContentResolverForUserId(uri);
+
+        if (PickerDbFacade.isPickerDbEnabled()) {
+            if (canHandleUriInUser(uri)) {
+                return queryPickerUri(uri);
+            }
+            return resolver.query(uri, /* projection */ null, /* queryArgs */ null,
+                    /* cancellationSignal */ null);
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            // Support query similar to as we support for redacted mediastore file uris.
+            return resolver.query(getRedactedFileUriFromPickerUri(uri, resolver), projection,
+                    queryArgs, signal);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     public String getType(@NonNull Uri uri) {
+        // There's no permission check because ContentProviders allow anyone to check the mimetype
+        // of a URI
+
         try (Cursor cursor = queryInternal(uri, new String[]{MediaStore.MediaColumns.MIME_TYPE},
                         /* queryArgs */ null, /* signal */ null)) {
             if (cursor != null && cursor.getCount() == 1 && cursor.moveToFirst()) {
@@ -178,25 +211,6 @@
                 + CloudMediaProviderContract.URI_PATH_ALBUM);
     }
 
-    private Cursor queryInternal(Uri uri, String[] projection, Bundle queryArgs,
-            CancellationSignal signal) throws FileNotFoundException {
-        final ContentResolver resolver = getContentResolverForUserId(uri);
-        final long token = Binder.clearCallingIdentity();
-        try {
-            if (PickerDbFacade.isPickerDbEnabled()) {
-                return queryPickerUri(uri);
-            }
-
-            // Support query similar to as we support for redacted mediastore file uris.
-            // TODO(b/191362529): Restrict projection values when we start querying picker db. Add
-            // PickerColumns and add checks for projection.
-            return resolver.query(getRedactedFileUriFromPickerUri(uri, resolver), projection,
-                    queryArgs, signal);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
     private ParcelFileDescriptor openPickerFile(Uri uri) throws FileNotFoundException {
         final File file = getPickerFileFromUri(uri);
         if (file == null) {
@@ -245,7 +259,6 @@
             throw new IllegalArgumentException("Unexpected picker provider URI: " + uri);
         }
 
-
         // segments.get(0) == 'picker'
         final String userId = segments.get(1);
         final String host = segments.get(2);
@@ -295,23 +308,32 @@
     }
 
     @VisibleForTesting
-    static UserId getUserId(Uri uri) {
-        // content://media/picker/<user-id>/<media-id>
-        final int user = Integer.parseInt(uri.getPathSegments().get(1));
-        return UserId.of(UserHandle.of(user));
+    static int getUserId(Uri uri) {
+        // content://media/picker/<user-id>/<media-id>/...
+        return Integer.parseInt(uri.getPathSegments().get(1));
     }
 
     private void checkUriPermission(Uri uri, int pid, int uid) {
-        if (mContext.checkUriPermission(uri, pid, uid,
+        if (!isSelf(uid) && mContext.checkUriPermission(uri, pid, uid,
                 Intent.FLAG_GRANT_READ_URI_PERMISSION) != PERMISSION_GRANTED) {
             throw new SecurityException("Calling uid ( " + uid + " ) does not have permission to " +
                     "access picker uri: " + uri);
         }
     }
 
+    private boolean isSelf(int uid) {
+        return UserHandle.getAppId(android.os.Process.myUid()) == UserHandle.getAppId(uid);
+    }
+
+    private boolean canHandleUriInUser(Uri uri) {
+        // If MPs user_id matches the URIs user_id, we can handle this URI in this MP user,
+        // otherwise, we'd have to re-route to MP matching URI user_id
+        return getUserId(uri) == MediaStore.MY_USER_ID;
+    }
+
     @VisibleForTesting
     ContentResolver getContentResolverForUserId(Uri uri) throws FileNotFoundException {
-        final UserId userId = getUserId(uri);
+        final UserId userId = UserId.of(UserHandle.of(getUserId(uri)));
         try {
             return userId.getContentResolver(mContext);
         } catch (NameNotFoundException e) {
diff --git a/src/com/android/providers/media/photopicker/data/ExternalDbFacade.java b/src/com/android/providers/media/photopicker/data/ExternalDbFacade.java
index e9af9c1..729e4a3 100644
--- a/src/com/android/providers/media/photopicker/data/ExternalDbFacade.java
+++ b/src/com/android/providers/media/photopicker/data/ExternalDbFacade.java
@@ -66,6 +66,8 @@
                 CloudMediaProviderContract.MediaColumns.GENERATION_MODIFIED,
         MediaColumns.SIZE + " AS " + CloudMediaProviderContract.MediaColumns.SIZE_BYTES,
         MediaColumns.MIME_TYPE + " AS " + CloudMediaProviderContract.MediaColumns.MIME_TYPE,
+        FileColumns._SPECIAL_FORMAT + " AS " +
+                CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION,
         MediaColumns.DURATION + " AS " + CloudMediaProviderContract.MediaColumns.DURATION_MS,
         MediaColumns.IS_FAVORITE + " AS " + CloudMediaProviderContract.MediaColumns.IS_FAVORITE
     };
@@ -108,10 +110,9 @@
     private static final String WHERE_MIME_TYPE = MediaStore.MediaColumns.MIME_TYPE
             + " LIKE ?";
 
-    // TODO(b/196071169): Include media that contains Environment#DIRECTORY_SCREENSHOTS in its
-    // relative_path.
-    public static final String RELATIVE_PATH_SCREENSHOTS = Environment.DIRECTORY_PICTURES + "/"
-            + Environment.DIRECTORY_SCREENSHOTS + "/%";
+    public static final String RELATIVE_PATH_SCREENSHOTS =
+            "%/" + Environment.DIRECTORY_SCREENSHOTS + "/%";
+
     public static final String RELATIVE_PATH_CAMERA = Environment.DIRECTORY_DCIM + "/Camera/%";
 
     private final DatabaseHelper mDatabaseHelper;
diff --git a/src/com/android/providers/media/photopicker/data/PickerDatabaseHelper.java b/src/com/android/providers/media/photopicker/data/PickerDatabaseHelper.java
index 5553d2f..98fece2 100644
--- a/src/com/android/providers/media/photopicker/data/PickerDatabaseHelper.java
+++ b/src/com/android/providers/media/photopicker/data/PickerDatabaseHelper.java
@@ -34,7 +34,7 @@
     @VisibleForTesting
     static final String PICKER_DATABASE_NAME = "picker.db";
 
-    private static final int VERSION_T = 2;
+    private static final int VERSION_T = 3;
     private static final int VERSION_LATEST = VERSION_T;
 
     final Context mContext;
@@ -113,7 +113,9 @@
                 + "generation_modified INTEGER NOT NULL CHECK(generation_modified >= 0),"
                 + "size_bytes INTEGER NOT NULL CHECK(size_bytes > 0),"
                 + "duration_ms INTEGER CHECK(duration_ms >= 0),"
-                + "mime_type TEXT NOT NULL,is_favorite INTEGER,"
+                + "mime_type TEXT NOT NULL,"
+                + "standard_mime_type_extension INTEGER,"
+                + "is_favorite INTEGER,"
                 + "CHECK(local_id IS NOT NULL OR cloud_id IS NOT NULL),"
                 + "UNIQUE(local_id, is_visible))");
     }
diff --git a/src/com/android/providers/media/photopicker/data/PickerDbFacade.java b/src/com/android/providers/media/photopicker/data/PickerDbFacade.java
index d801d8c..9ddf955 100644
--- a/src/com/android/providers/media/photopicker/data/PickerDbFacade.java
+++ b/src/com/android/providers/media/photopicker/data/PickerDbFacade.java
@@ -98,6 +98,8 @@
     @VisibleForTesting
     public static final String KEY_MIME_TYPE = "mime_type";
     @VisibleForTesting
+    public static final String KEY_STANDARD_MIME_TYPE_EXTENSION = "standard_mime_type_extension";
+    @VisibleForTesting
     public static final String KEY_IS_FAVORITE = "is_favorite";
 
     @VisibleForTesting
@@ -122,6 +124,9 @@
             CloudMediaProviderContract.MediaColumns.DURATION_MS);
     private static final String PROJECTION_MIME_TYPE = String.format("%s AS %s", KEY_MIME_TYPE,
             CloudMediaProviderContract.MediaColumns.MIME_TYPE);
+    private static final String PROJECTION_STANDARD_MIME_TYPE_EXTENSION = String.format("%s AS %s",
+            KEY_STANDARD_MIME_TYPE_EXTENSION,
+            CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION);
 
     private static final String WHERE_ID = KEY_ID + " = ?";
     private static final String WHERE_LOCAL_ID = KEY_LOCAL_ID + " = ?";
@@ -642,7 +647,8 @@
             PROJECTION_GENERATION_MODIFIED,
             PROJECTION_SIZE,
             PROJECTION_DURATION,
-            PROJECTION_MIME_TYPE
+            PROJECTION_MIME_TYPE,
+            PROJECTION_STANDARD_MIME_TYPE_EXTENSION
         };
     }
 
@@ -713,6 +719,14 @@
                 case CloudMediaProviderContract.MediaColumns.MIME_TYPE:
                     values.put(KEY_MIME_TYPE, cursor.getString(index));
                     break;
+                case CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION:
+                    int standardMimeTypeExtension = cursor.getInt(index);
+                    if (isValidStandardMimeTypeExtension(standardMimeTypeExtension)) {
+                        values.put(KEY_STANDARD_MIME_TYPE_EXTENSION, standardMimeTypeExtension);
+                    } else {
+                        throw new IllegalArgumentException("Invalid standard mime type extension");
+                    }
+                    break;
                 case CloudMediaProviderContract.MediaColumns.DURATION_MS:
                     values.put(KEY_DURATION_MS, cursor.getLong(index));
                     break;
@@ -727,6 +741,16 @@
         return values;
     }
 
+    private static boolean isValidStandardMimeTypeExtension(int standardMimeTypeExtension) {
+        return (standardMimeTypeExtension ==
+                CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE) ||
+                (standardMimeTypeExtension ==
+                        CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION_GIF) ||
+                (standardMimeTypeExtension ==
+                        CloudMediaProviderContract.MediaColumns.
+                                STANDARD_MIME_TYPE_EXTENSION_MOTION_PHOTO);
+    }
+
     private static String[] buildSelectionArgs(SQLiteQueryBuilder qb, QueryFilter query) {
         List<String> selectArgs = new ArrayList<>();
 
diff --git a/src/com/android/providers/media/photopicker/data/model/Item.java b/src/com/android/providers/media/photopicker/data/model/Item.java
index f90def4..0939c4b 100644
--- a/src/com/android/providers/media/photopicker/data/model/Item.java
+++ b/src/com/android/providers/media/photopicker/data/model/Item.java
@@ -51,8 +51,8 @@
         public static String DURATION = CloudMediaProviderContract.MediaColumns.DURATION_MS;
         public static String SIZE = CloudMediaProviderContract.MediaColumns.SIZE_BYTES;
         public static String AUTHORITY = CloudMediaProviderContract.MediaColumns.AUTHORITY;
-        // TODO(b/204837343): Replace by CloudMediaProviderContract constant
-        public static String SPECIAL_FORMAT = MediaStore.Files.FileColumns._SPECIAL_FORMAT;
+        public static String SPECIAL_FORMAT =
+                CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION;
 
         public static final String[] ALL_COLUMNS = {
                 ID,
diff --git a/tests/src/com/android/providers/media/PickerProviderMediaGenerator.java b/tests/src/com/android/providers/media/PickerProviderMediaGenerator.java
index 909f28c..9707473 100644
--- a/tests/src/com/android/providers/media/PickerProviderMediaGenerator.java
+++ b/tests/src/com/android/providers/media/PickerProviderMediaGenerator.java
@@ -45,6 +45,7 @@
         MediaColumns.ID,
         MediaColumns.MEDIA_STORE_URI,
         MediaColumns.MIME_TYPE,
+        MediaColumns.STANDARD_MIME_TYPE_EXTENSION,
         MediaColumns.DATE_TAKEN_MS,
         MediaColumns.GENERATION_MODIFIED,
         MediaColumns.SIZE_BYTES,
@@ -114,10 +115,11 @@
         }
 
         public void addMedia(String localId, String cloudId, String albumId, String mimeType,
-                long sizeBytes, boolean isFavorite) {
+                int standardMimeTypeExtension, long sizeBytes, boolean isFavorite) {
             mDeletedMedia.remove(createPlaceholderMedia(localId, cloudId));
             mMedia.add(0,
-                    createTestMedia(localId, cloudId, albumId, mimeType, sizeBytes, isFavorite));
+                    createTestMedia(localId, cloudId, albumId, mimeType, standardMimeTypeExtension,
+                            sizeBytes, isFavorite));
         }
 
         public void deleteMedia(String localId, String cloudId) {
@@ -162,10 +164,11 @@
         }
 
         private TestMedia createTestMedia(String localId, String cloudId, String albumId,
-                String mimeType, long sizeBytes, boolean isFavorite) {
+                String mimeType, int standardMimeTypeExtension, long sizeBytes,
+                boolean isFavorite) {
             // Increase generation
-            return new TestMedia(localId, cloudId, albumId, mimeType, sizeBytes, /* durationMs */ 0,
-                    ++mGeneration, isFavorite);
+            return new TestMedia(localId, cloudId, albumId, mimeType, standardMimeTypeExtension,
+                    sizeBytes, /* durationMs */ 0, ++mGeneration, isFavorite);
         }
 
         private static TestMedia createPlaceholderMedia(String localId, String cloudId) {
@@ -211,6 +214,7 @@
         public final String cloudId;
         public final String albumId;
         public final String mimeType;
+        public final int standardMimeTypeExtension;
         public final long sizeBytes;
         public final long dateTakenMs;
         public final long durationMs;
@@ -218,16 +222,20 @@
         public final boolean isFavorite;
 
         public TestMedia(String localId, String cloudId, long generation) {
-            this(localId, cloudId, /* albumId */ null, "image/jpeg", /* sizeBytes */ 4096,
-                    /* durationMs */ 0, generation, /* isFavorite */ false);
+            this(localId, cloudId, /* albumId */ null, "image/jpeg",
+                    /* standardMimeTypeExtension */ MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE,
+                    /* sizeBytes */ 4096, /* durationMs */ 0, generation,
+                    /* isFavorite */ false);
         }
 
         public TestMedia(String localId, String cloudId, String albumId, String mimeType,
-                long sizeBytes, long durationMs, long generation, boolean isFavorite) {
+                int standardMimeTypeExtension, long sizeBytes, long durationMs, long generation,
+                boolean isFavorite) {
             this.localId = localId;
             this.cloudId = cloudId;
             this.albumId = albumId;
             this.mimeType = mimeType;
+            this.standardMimeTypeExtension = standardMimeTypeExtension;
             this.sizeBytes = sizeBytes;
             this.dateTakenMs = System.currentTimeMillis();
             this.durationMs = durationMs;
@@ -245,6 +253,7 @@
                 getId(),
                 localId == null ? null : "content://media/external/files/" + localId,
                 mimeType,
+                String.valueOf(standardMimeTypeExtension),
                 String.valueOf(dateTakenMs),
                 String.valueOf(generation),
                 String.valueOf(sizeBytes),
diff --git a/tests/src/com/android/providers/media/PickerUriResolverTest.java b/tests/src/com/android/providers/media/PickerUriResolverTest.java
index 1c68ab9..863525f 100644
--- a/tests/src/com/android/providers/media/PickerUriResolverTest.java
+++ b/tests/src/com/android/providers/media/PickerUriResolverTest.java
@@ -277,7 +277,7 @@
     public void testPickerUriResolver_userValid() throws Exception {
         updateReadUriPermission(sTestPickerUri, /* grant */ true);
 
-        testGetUserId(sTestPickerUri, UserHandle.of(TEST_USER));
+        assertThat(PickerUriResolver.getUserId(sTestPickerUri)).isEqualTo(TEST_USER);
         testOpenFile(sTestPickerUri);
         testOpenTypedAssetFile(sTestPickerUri);
         testQuery(sTestPickerUri);
@@ -327,11 +327,6 @@
         return Uri.parse("content://media/picker/" + user + "/" + id);
     }
 
-    private void testGetUserId(Uri uri, UserHandle userHandle) {
-        assertThat(PickerUriResolver.getUserId(uri).toString()).isEqualTo(
-                UserId.of(userHandle).toString());
-    }
-
     private void testOpenFile(Uri uri) throws Exception {
         ParcelFileDescriptor pfd = sTestPickerUriResolver.openFile(uri, "r", /* signal */ null,
                 /* callingPid */ -1, /* callingUid */ -1);
diff --git a/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java b/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java
index a0e69fc..04509c3 100644
--- a/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java
+++ b/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java
@@ -20,9 +20,6 @@
 import static com.android.providers.media.PickerProviderMediaGenerator.ALBUM_COLUMN_TYPE_FAVORITES;
 import static com.android.providers.media.PickerProviderMediaGenerator.ALBUM_COLUMN_TYPE_LOCAL;
 import static com.android.providers.media.PickerProviderMediaGenerator.MediaGenerator;
-import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.BOOLEAN_DEFAULT;
-import static com.android.providers.media.photopicker.data.PickerDbFacade.KEY_CLOUD_ID;
-import static com.android.providers.media.photopicker.data.PickerDbFacade.KEY_LOCAL_ID;
 import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.LONG_DEFAULT;
 import static com.android.providers.media.photopicker.data.PickerDbFacade.QueryFilterBuilder.STRING_DEFAULT;
 import static com.google.common.truth.Truth.assertThat;
@@ -32,7 +29,6 @@
 import android.content.Intent;
 import android.database.Cursor;
 import android.os.Bundle;
-import android.os.SystemClock;
 import android.provider.CloudMediaProviderContract.AlbumColumns;
 import android.provider.CloudMediaProviderContract.MediaColumns;
 import android.provider.MediaStore;
@@ -44,7 +40,6 @@
 import com.android.providers.media.PickerProviderMediaGenerator;
 import com.android.providers.media.photopicker.data.PickerDbFacade;
 import com.android.providers.media.photopicker.data.model.Category;
-import com.android.providers.media.photopicker.data.model.Item;
 import com.android.providers.media.util.BackgroundThread;
 
 import java.util.List;
@@ -155,13 +150,14 @@
         mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ true);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ true);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle defaultQueryArgs = buildDefaultQueryArgs();
 
@@ -186,13 +182,14 @@
         mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ true);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ true);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle defaultQueryArgs = buildDefaultQueryArgs();
 
@@ -216,13 +213,14 @@
         mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ true);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ true);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle defaultQueryArgs = buildDefaultQueryArgs();
 
@@ -246,13 +244,14 @@
         mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ true);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ true);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle defaultQueryArgs = buildDefaultQueryArgs();
 
@@ -274,9 +273,9 @@
         mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle queryArgs = buildQueryArgs(IMAGE_MIME_TYPE, SIZE_BYTES_DEFAULT);
 
@@ -293,9 +292,10 @@
         mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle queryArgs = buildQueryArgs(IMAGE_MIME_TYPE, SIZE_BYTES - 1);
 
@@ -312,11 +312,13 @@
         mController.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, /* albumId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle queryArgs = buildQueryArgs(VIDEO_MIME_TYPE, SIZE_BYTES - 1);
 
@@ -336,13 +338,13 @@
         mCloudPrimaryMediaGenerator.createAlbum(ALBUM_ID_2);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, ALBUM_ID_1, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, ALBUM_ID_2, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, /* albumId */ null, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ true);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, /* albumdId */ null, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ true);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ true);
 
         final Bundle defaultQueryArgs = buildDefaultQueryArgs();
 
@@ -401,13 +403,13 @@
         mCloudPrimaryMediaGenerator.createAlbum(ALBUM_ID_2);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, ALBUM_ID_1, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, ALBUM_ID_2, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, ALBUM_ID_1, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, ALBUM_ID_2, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle mimeTypeQueryArgs = buildQueryArgs(IMAGE_MIME_TYPE, SIZE_BYTES_DEFAULT);
 
@@ -446,13 +448,15 @@
         mCloudPrimaryMediaGenerator.createAlbum(ALBUM_ID_2);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, ALBUM_ID_1, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, ALBUM_ID_2, VIDEO_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ false);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, ALBUM_ID_1, VIDEO_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, ALBUM_ID_2, IMAGE_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle sizeQueryArgs = buildQueryArgs(MIME_TYPE_DEFAULT, SIZE_BYTES - 1);
 
@@ -491,13 +495,15 @@
         mCloudPrimaryMediaGenerator.createAlbum(ALBUM_ID_2);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1, ALBUM_ID_1, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_1, ALBUM_ID_2, VIDEO_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ false);
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_2, ALBUM_ID_1, VIDEO_MIME_TYPE,
-                SIZE_BYTES - 1, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES - 1,
+                /* isFavorite */ false);
         addMedia(mCloudPrimaryMediaGenerator, CLOUD_ONLY_2, ALBUM_ID_2, VIDEO_MIME_TYPE,
-                SIZE_BYTES, /* isFavorite */ false);
+                MediaColumns.STANDARD_MIME_TYPE_EXTENSION_NONE, SIZE_BYTES, /* isFavorite */ false);
 
         final Bundle mimeTypeAndSizeQueryArgs = buildQueryArgs(VIDEO_MIME_TYPE, SIZE_BYTES -1);
 
@@ -588,8 +594,10 @@
     }
 
     private static void addMedia(MediaGenerator generator, Pair<String, String> media,
-            String albumId, String mimeType, long sizeBytes, boolean isFavorite) {
-        generator.addMedia(media.first, media.second, albumId, mimeType, sizeBytes, isFavorite);
+            String albumId, String mimeType, int standardMimeTypeExtension, long sizeBytes,
+            boolean isFavorite) {
+        generator.addMedia(media.first, media.second, albumId, mimeType,
+                standardMimeTypeExtension, sizeBytes, isFavorite);
     }
 
     private static void deleteMedia(MediaGenerator generator, Pair<String, String> media) {
diff --git a/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java b/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java
index 02ab1d0..ae2c433 100644
--- a/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java
+++ b/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java
@@ -419,8 +419,10 @@
     }
 
     private static void addMedia(MediaGenerator generator, Pair<String, String> media,
-            String albumId, String mimeType, long sizeBytes, boolean isFavorite) {
-        generator.addMedia(media.first, media.second, albumId, mimeType, sizeBytes, isFavorite);
+            String albumId, String mimeType, int standardMimeTypeExtension, long sizeBytes,
+            boolean isFavorite) {
+        generator.addMedia(media.first, media.second, albumId, mimeType, standardMimeTypeExtension,
+                sizeBytes, isFavorite);
     }
 
     private static void deleteMedia(MediaGenerator generator, Pair<String, String> media) {
diff --git a/tests/src/com/android/providers/media/photopicker/data/PickerDatabaseHelperTest.java b/tests/src/com/android/providers/media/photopicker/data/PickerDatabaseHelperTest.java
index 77d7ef6..554de5b 100644
--- a/tests/src/com/android/providers/media/photopicker/data/PickerDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/media/photopicker/data/PickerDatabaseHelperTest.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
+import android.provider.CloudMediaProviderContract;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -48,6 +49,7 @@
     private static final String KEY_SIZE_BYTES = "size_bytes";
     private static final String KEY_DURATION_MS = "duration_ms";
     private static final String KEY_MIME_TYPE = "mime_type";
+    private static final String KEY_STANDARD_MIME_TYPE_EXTENSION = "standard_mime_type_extension";
 
     private static final long LOCAL_ID = 50;
     private static final long SIZE_BYTES = 7000;
@@ -55,6 +57,8 @@
     private static final long GENERATION_MODIFIED = 1L;
     private static final String CLOUD_ID = "asdfghjkl;";
     private static final String MIME_TYPE = "video/mp4";
+    private static final int STANDARD_MIME_TYPE_EXTENSION =
+            CloudMediaProviderContract.MediaColumns.STANDARD_MIME_TYPE_EXTENSION_GIF;
     private static final long DURATION_MS = 0;
 
     private static Context sIsolatedContext;
@@ -75,7 +79,8 @@
             KEY_GENERATION_MODIFIED,
             KEY_SIZE_BYTES,
             KEY_DURATION_MS,
-            KEY_MIME_TYPE
+            KEY_MIME_TYPE,
+            KEY_STANDARD_MIME_TYPE_EXTENSION
         };
 
         try (PickerDatabaseHelper helper = new PickerDatabaseHelperT(sIsolatedContext)) {
@@ -99,6 +104,7 @@
                     assertThat(cr.getLong(5)).isEqualTo(SIZE_BYTES);
                     assertThat(cr.getLong(6)).isEqualTo(DURATION_MS);
                     assertThat(cr.getString(7)).isEqualTo(MIME_TYPE);
+                    assertThat(cr.getInt(8)).isEqualTo(STANDARD_MIME_TYPE_EXTENSION);
                 }
             }
         }
@@ -313,6 +319,7 @@
         values.put(KEY_GENERATION_MODIFIED, GENERATION_MODIFIED);
         values.put(KEY_DURATION_MS, DURATION_MS);
         values.put(KEY_MIME_TYPE, MIME_TYPE);
+        values.put(KEY_STANDARD_MIME_TYPE_EXTENSION, STANDARD_MIME_TYPE_EXTENSION);
         values.put(KEY_SIZE_BYTES, SIZE_BYTES);
 
         return values;
diff --git a/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java b/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java
index fc4025f..61cf600 100644
--- a/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java
+++ b/tests/src/com/android/providers/media/photopicker/data/PickerDbFacadeTest.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.database.MatrixCursor;
+import android.provider.CloudMediaProviderContract;
 import android.provider.CloudMediaProviderContract.AlbumColumns;
 import android.provider.CloudMediaProviderContract.MediaColumns;
 
@@ -46,6 +47,8 @@
     private static final String CLOUD_ID = "asdfghjkl;";
     private static final String VIDEO_MIME_TYPE = "video/mp4";
     private static final String IMAGE_MIME_TYPE = "image/jpeg";
+    private static final int STANDARD_MIME_TYPE_EXTENSION =
+            MediaColumns.STANDARD_MIME_TYPE_EXTENSION_GIF;
 
     private static final String LOCAL_PROVIDER = "com.local.provider";
     private static final String CLOUD_PROVIDER = "com.cloud.provider";
@@ -488,10 +491,10 @@
     public void testQueryWithSizeFilter() throws Exception {
         Cursor cursor1 = getMediaCursor(LOCAL_ID, DATE_TAKEN_MS, GENERATION_MODIFIED,
                 /* mediaStoreUri */ null, /* sizeBytes */ 1, VIDEO_MIME_TYPE,
-                /* isFavorite */ false);
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
         Cursor cursor2 = getMediaCursor(CLOUD_ID, DATE_TAKEN_MS, GENERATION_MODIFIED,
                 /* mediaStoreUri */ null, /* sizeBytes */ 2, VIDEO_MIME_TYPE,
-                /* isFavorite */ false);
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
 
         assertThat(mFacade.addMedia(cursor1, LOCAL_PROVIDER)).isEqualTo(1);
         assertThat(mFacade.addMedia(cursor2, CLOUD_PROVIDER)).isEqualTo(1);
@@ -553,9 +556,11 @@
     @Test
     public void testQueryWithMimeTypeFilter() throws Exception {
         Cursor cursor1 = getMediaCursor(LOCAL_ID, DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, "video/webm", /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, "video/webm",
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
         Cursor cursor2 = getMediaCursor(CLOUD_ID, DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, "video/mp4", /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, "video/mp4",
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
 
         assertThat(mFacade.addMedia(cursor1, LOCAL_PROVIDER)).isEqualTo(1);
         assertThat(mFacade.addMedia(cursor2, CLOUD_PROVIDER)).isEqualTo(1);
@@ -617,9 +622,11 @@
     @Test
     public void testQueryWithSizeAndMimeTypeFilter() throws Exception {
         Cursor cursor1 = getMediaCursor(LOCAL_ID, DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, /* sizeBytes */ 2, "video/webm", /* isFavorite */ false);
+                /* mediaStoreUri */ null, /* sizeBytes */ 2, "video/webm",
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
         Cursor cursor2 = getMediaCursor(CLOUD_ID, DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, /* sizeBytes */ 1, "video/mp4", /* isFavorite */ false);
+                /* mediaStoreUri */ null, /* sizeBytes */ 1, "video/mp4",
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
 
         assertThat(mFacade.addMedia(cursor1, LOCAL_PROVIDER)).isEqualTo(1);
         assertThat(mFacade.addMedia(cursor2, CLOUD_PROVIDER)).isEqualTo(1);
@@ -685,13 +692,17 @@
     @Test
     public void testFavorites() throws Exception {
         Cursor localCursor1 = getMediaCursor(LOCAL_ID + "1", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ true);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ true);
         Cursor localCursor2 = getMediaCursor(LOCAL_ID + "2", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
         Cursor cloudCursor1 = getMediaCursor(CLOUD_ID + "1", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ true);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ true);
         Cursor cloudCursor2 = getMediaCursor(CLOUD_ID + "2", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
 
         assertThat(mFacade.addMedia(localCursor1, LOCAL_PROVIDER)).isEqualTo(1);
         assertThat(mFacade.addMedia(localCursor2, LOCAL_PROVIDER)).isEqualTo(1);
@@ -718,13 +729,17 @@
     @Test
     public void testGetFavoritesAlbumWithoutFilter() throws Exception {
         Cursor localCursor1 = getMediaCursor(LOCAL_ID + "1", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ true);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ true);
         Cursor localCursor2 = getMediaCursor(LOCAL_ID + "2", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
         Cursor cloudCursor1 = getMediaCursor(CLOUD_ID + "1", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE, /* isFavorite */ true);
+                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ true);
         Cursor cloudCursor2 = getMediaCursor(CLOUD_ID + "2", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
 
         assertThat(mFacade.addMedia(localCursor1, LOCAL_PROVIDER)).isEqualTo(1);
         assertThat(mFacade.addMedia(localCursor2, LOCAL_PROVIDER)).isEqualTo(1);
@@ -752,13 +767,17 @@
     @Test
     public void testGetFavoritesAlbumWithMimeTypeFilter() throws Exception {
         Cursor localCursor1 = getMediaCursor(LOCAL_ID + "1", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ true);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ true);
         Cursor localCursor2 = getMediaCursor(LOCAL_ID + "2", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
         Cursor cloudCursor1 = getMediaCursor(CLOUD_ID + "1", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE, /* isFavorite */ true);
+                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ true);
         Cursor cloudCursor2 = getMediaCursor(CLOUD_ID + "2", DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
 
         assertThat(mFacade.addMedia(localCursor1, LOCAL_PROVIDER)).isEqualTo(1);
         assertThat(mFacade.addMedia(localCursor2, LOCAL_PROVIDER)).isEqualTo(1);
@@ -815,9 +834,11 @@
     @Test
     public void testDataColumn() throws Exception {
         Cursor imageCursor = getMediaCursor(LOCAL_ID, DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, IMAGE_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
         Cursor videoCursor = getMediaCursor(LOCAL_ID + 1, DATE_TAKEN_MS, GENERATION_MODIFIED,
-                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ false);
+                /* mediaStoreUri */ null, SIZE_BYTES, VIDEO_MIME_TYPE,
+                STANDARD_MIME_TYPE_EXTENSION, /* isFavorite */ false);
 
         assertThat(mFacade.addMedia(imageCursor, LOCAL_PROVIDER)).isEqualTo(1);
         assertThat(mFacade.addMedia(videoCursor, LOCAL_PROVIDER)).isEqualTo(1);
@@ -845,7 +866,8 @@
     }
 
     private static Cursor getMediaCursor(String id, long dateTakenMs, long generationModified,
-            String mediaStoreUri, long sizeBytes, String mimeType, boolean isFavorite) {
+            String mediaStoreUri, long sizeBytes, String mimeType, int standardMimeTypeExtension,
+            boolean isFavorite) {
         String[] projectionKey = new String[] {
             MediaColumns.ID,
             MediaColumns.MEDIA_STORE_URI,
@@ -853,6 +875,7 @@
             MediaColumns.GENERATION_MODIFIED,
             MediaColumns.SIZE_BYTES,
             MediaColumns.MIME_TYPE,
+            MediaColumns.STANDARD_MIME_TYPE_EXTENSION,
             MediaColumns.DURATION_MS,
             MediaColumns.IS_FAVORITE
         };
@@ -864,6 +887,7 @@
             String.valueOf(generationModified),
             String.valueOf(sizeBytes),
             mimeType,
+            String.valueOf(standardMimeTypeExtension),
             String.valueOf(DURATION_MS),
             String.valueOf(isFavorite ? 1 : 0)
         };
@@ -875,13 +899,15 @@
 
     private static Cursor getLocalMediaCursor(String localId, long dateTakenMs) {
         return getMediaCursor(localId, dateTakenMs, GENERATION_MODIFIED, toMediaStoreUri(localId),
-                SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ false);
+                SIZE_BYTES, VIDEO_MIME_TYPE, STANDARD_MIME_TYPE_EXTENSION,
+                /* isFavorite */ false);
     }
 
     private static Cursor getCloudMediaCursor(String cloudId, String localId,
             long dateTakenMs) {
         return getMediaCursor(cloudId, dateTakenMs, GENERATION_MODIFIED, toMediaStoreUri(localId),
-                SIZE_BYTES, VIDEO_MIME_TYPE, /* isFavorite */ false);
+                SIZE_BYTES, VIDEO_MIME_TYPE, STANDARD_MIME_TYPE_EXTENSION,
+                /* isFavorite */ false);
     }
 
     private static String toMediaStoreUri(String localId) {
@@ -925,6 +951,8 @@
         assertMediaCursor(cursor, id, VIDEO_MIME_TYPE);
         assertThat(cursor.getString(cursor.getColumnIndex(MediaColumns.MIME_TYPE)))
                 .isEqualTo(VIDEO_MIME_TYPE);
+        assertThat(cursor.getInt(cursor.getColumnIndex(MediaColumns.STANDARD_MIME_TYPE_EXTENSION)))
+                .isEqualTo(STANDARD_MIME_TYPE_EXTENSION);
         assertThat(cursor.getLong(cursor.getColumnIndex(MediaColumns.DATE_TAKEN_MS)))
                 .isEqualTo(dateTakenMs);
         assertThat(cursor.getLong(cursor.getColumnIndex(MediaColumns.GENERATION_MODIFIED)))
diff --git a/tools/photopicker-gradle/app/src/main/java/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java b/tools/photopicker-gradle/app/src/main/java/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java
index 475c100..b6d2e8d 100644
--- a/tools/photopicker-gradle/app/src/main/java/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java
+++ b/tools/photopicker-gradle/app/src/main/java/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java
@@ -4,6 +4,7 @@
 import static android.provider.MediaStore.ACTION_PICK_IMAGES;
 import static android.provider.MediaStore.EXTRA_PICK_IMAGES_MAX;
 
+import android.annotation.SuppressLint;
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
 
@@ -139,6 +140,9 @@
         mMaxCountText.setEnabled(isChecked);
     }
 
+    // We mistakenly get lint warning about using getPickImagesMaxLimit. The API is
+    // actually available in SX.
+    @SuppressLint("NewApi")
     private void onLaunchButtonClicked(View view) {
         final Intent intent;
         if (mGetContentCheckBox.isChecked()) {
@@ -156,6 +160,8 @@
             if (mGetContentCheckBox.isChecked()) {
                 intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
             } else {
+                // We mistakenly get lint warning about using getPickImagesMaxLimit. The API is
+                // actually available in SX.
                 intent.putExtra(EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
             }
         }
@@ -182,6 +188,9 @@
         }
     }
 
+    // We mistakenly get lint warning about using getExtensionVersion on API level < 32. The API is
+    // actually available in R+.
+    @SuppressLint("NewApi")
     private boolean isPhotoPickerAvailable() {
         return SDK_INT >= Build.VERSION_CODES.R
             && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 2;
@@ -276,7 +285,7 @@
     private ImageView generateImageView(Uri uri, LinearLayout.LayoutParams params) {
         final ImageView image = new ImageView(this);
         image.setLayoutParams(params);
-        image.setScaleType(ImageView.ScaleType.CENTER_CROP);
+        image.setScaleType(ImageView.ScaleType.FIT_CENTER);
         image.setImageURI(uri);
         return image;
     }
diff --git a/tools/photopicker/src/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java b/tools/photopicker/src/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java
index 6835895..adae4eb 100644
--- a/tools/photopicker/src/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java
+++ b/tools/photopicker/src/com/android/providers/media/tools/photopicker/PhotoPickerToolActivity.java
@@ -253,7 +253,7 @@
     private ImageView generateImageView(Uri uri, LinearLayout.LayoutParams params) {
         final ImageView image = new ImageView(this);
         image.setLayoutParams(params);
-        image.setScaleType(ImageView.ScaleType.CENTER_CROP);
+        image.setScaleType(ImageView.ScaleType.FIT_CENTER);
         Glide.with(this)
                 .load(uri)
                 .thumbnail()