Optimize the UI of the PermissionDialog

- If there is no thumbnails or images, load the mime icon to
  instead
- Sort the thumbnails by the order (Images, Videos, Audios, Others)

Test: add the screenshots
Fix: 162564974
Bug: 161758014
Merged-In: Ifb5796488b1071ef1b389f4ffd6e87255580c0d0
Change-Id: Ifb5796488b1071ef1b389f4ffd6e87255580c0d0
(cherry picked from commit f923930f0e908f164a0d28319fe5d600ee20b1ca)
diff --git a/res/drawable/thumb_clip_gradient.xml b/res/drawable/thumb_clip_gradient.xml
new file mode 100644
index 0000000..d94b0c2
--- /dev/null
+++ b/res/drawable/thumb_clip_gradient.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shape="rectangle">
+    <solid android:color="@color/thumb_more_tint"/>
+    <corners android:radius="4dp" />
+</shape>
diff --git a/res/layout/permission_body.xml b/res/layout/permission_body.xml
index 6282c7c..0fb4ece 100644
--- a/res/layout/permission_body.xml
+++ b/res/layout/permission_body.xml
@@ -61,8 +61,13 @@
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:background="@drawable/thumb_clip"
-                android:scaleType="centerCrop"
-                android:tint="@color/thumb_more_tint" />
+                android:scaleType="centerCrop"/>
+            <View
+                android:id="@+id/thumb_more_gradient"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@drawable/thumb_clip_gradient"
+                android:visibility="gone"/>
             <TextView
                 android:id="@+id/thumb_more_text"
                 android:layout_width="match_parent"
diff --git a/src/com/android/providers/media/PermissionActivity.java b/src/com/android/providers/media/PermissionActivity.java
index 944353f..0d721f9 100644
--- a/src/com/android/providers/media/PermissionActivity.java
+++ b/src/com/android/providers/media/PermissionActivity.java
@@ -41,6 +41,8 @@
 import android.graphics.ImageDecoder;
 import android.graphics.ImageDecoder.ImageInfo;
 import android.graphics.ImageDecoder.Source;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -68,9 +70,11 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
 import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
 import java.util.stream.Collectors;
 
 /**
@@ -114,6 +118,12 @@
     private static final String DATA_IMAGE = "image";
     private static final String DATA_GENERIC = "generic";
 
+    // Use to sort the thumbnails.
+    private static final int ORDER_IMAGE = 1;
+    private static final int ORDER_VIDEO = 2;
+    private static final int ORDER_AUDIO = 3;
+    private static final int ORDER_GENERIC = 4;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -485,6 +495,25 @@
                 }
             }
 
+            // Sort the uris in DATA_GENERIC case (Image, Video, Audio, Others)
+            if (TextUtils.equals(data, DATA_GENERIC) && uris.size() > 1) {
+                final ToIntFunction<Uri> score = (uri) -> {
+                    final LocalUriMatcher matcher = new LocalUriMatcher(MediaStore.AUTHORITY);
+                    final int match = matcher.matchUri(uri, false);
+
+                    switch (match) {
+                        case AUDIO_MEDIA_ID: return ORDER_AUDIO;
+                        case VIDEO_MEDIA_ID: return ORDER_VIDEO;
+                        case IMAGES_MEDIA_ID: return ORDER_IMAGE;
+                        default: return ORDER_GENERIC;
+                    }
+                };
+                final Comparator<Uri> bestScore = (a, b) ->
+                        score.applyAsInt(a) - score.applyAsInt(b);
+
+                uris.sort(bestScore);
+            }
+
             for (Uri uri : uris) {
                 try {
                     final Description desc = new Description(bodyView.getContext(), uri, loadFlags);
@@ -527,15 +556,23 @@
         }
 
         /**
-         * Bind dialog as a single full-bleed image.
+         * Bind dialog as a single full-bleed image. If there is no image, use
+         * the icon of Mime type instead.
          */
         private void bindAsFull(@NonNull Description result) {
             final ImageView thumbFull = bodyView.requireViewById(R.id.thumb_full);
-            result.bindFull(thumbFull);
+            if (result.full != null) {
+                result.bindFull(thumbFull);
+            } else {
+                thumbFull.setScaleType(ImageView.ScaleType.FIT_CENTER);
+                thumbFull.setBackground(new ColorDrawable(getColor(R.color.thumb_gray_color)));
+                result.bindMimeIcon(thumbFull);
+            }
         }
 
         /**
-         * Bind dialog as a list of multiple thumbnails.
+         * Bind dialog as a list of multiple thumbnails. If there is no thumbnail for some
+         * items, use the icons of the MIME type instead.
          */
         private void bindAsThumbs(@NonNull List<Description> results,
                 @NonNull List<Description> visualResults) {
@@ -552,6 +589,7 @@
                 final View thumbMoreContainer = bodyView.requireViewById(R.id.thumb_more_container);
                 final ImageView thumbMore = bodyView.requireViewById(R.id.thumb_more);
                 final TextView thumbMoreText = bodyView.requireViewById(R.id.thumb_more_text);
+                final View gradientView = bodyView.requireViewById(R.id.thumb_more_gradient);
 
                 // Since we only want three tiles displayed maximum, swap out
                 // the first tile for our "more" tile
@@ -565,6 +603,7 @@
 
                 thumbMoreText.setText(moreText);
                 thumbMoreContainer.setVisibility(View.VISIBLE);
+                gradientView.setVisibility(View.VISIBLE);
             }
 
             // Trim off extra thumbnails from the front of our list, so that we
@@ -577,7 +616,11 @@
             for (int i = 0; i < thumbs.size(); i++) {
                 final Description desc = visualResults.get(i);
                 final ImageView imageView = thumbs.get(i);
-                desc.bindThumbnail(imageView);
+                if (desc.thumbnail != null) {
+                    desc.bindThumbnail(imageView);
+                } else {
+                    desc.bindMimeIcon(imageView);
+                }
             }
         }
 
@@ -612,6 +655,7 @@
         public @Nullable CharSequence contentDescription;
         public @Nullable Bitmap thumbnail;
         public @Nullable Bitmap full;
+        public @Nullable Icon mimeIcon;
 
         public static final int LOAD_CONTENT_DESCRIPTION = 1 << 0;
         public static final int LOAD_THUMBNAIL = 1 << 1;
@@ -650,11 +694,15 @@
                 }
             } catch (IOException e) {
                 Log.w(TAG, e);
+                if (thumbnail == null && full == null) {
+                    final String mimeType = resolver.getType(uri);
+                    mimeIcon = resolver.getTypeInfo(mimeType).getIcon();
+                }
             }
         }
 
         public boolean isVisual() {
-            return thumbnail != null || full != null;
+            return thumbnail != null || full != null || mimeIcon != null;
         }
 
         public void bindThumbnail(ImageView imageView) {
@@ -671,6 +719,14 @@
             imageView.setContentDescription(contentDescription);
             imageView.setVisibility(View.VISIBLE);
         }
+
+        public void bindMimeIcon(ImageView imageView) {
+            Objects.requireNonNull(mimeIcon);
+            imageView.setImageIcon(mimeIcon);
+            imageView.setContentDescription(contentDescription);
+            imageView.setVisibility(View.VISIBLE);
+            imageView.setClipToOutline(true);
+        }
     }
 
     /**