[ThemePicker 9/N] Read shape and icon from theme stub

Load the shape and icons from stub and overlays and display
them in the theme thumbnails.

Bug: 120559294
Change-Id: I40ae07070370fb33ada7060bf7161a0565109107
diff --git a/res/drawable/option_color.xml b/res/drawable/option_color.xml
index 87e2532..1fc1837 100644
--- a/res/drawable/option_color.xml
+++ b/res/drawable/option_color.xml
@@ -17,5 +17,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <solid android:color="@android:color/black"  />
-    <corners android:radius="8dp" />
+    <corners android:radius="6dp" />
 </shape>
diff --git a/res/layout/theme_option.xml b/res/layout/theme_option.xml
index 9e2ef82..5560a35 100644
--- a/res/layout/theme_option.xml
+++ b/res/layout/theme_option.xml
@@ -36,7 +36,7 @@
         android:background="@drawable/option_border">
         <TextView
             android:id="@+id/theme_option_font"
-            android:layout_width="wrap_content"
+            android:layout_width="@dimen/theme_option_sample_width"
             android:layout_height="@dimen/theme_option_sample_height"
             android:layout_alignParentTop="true"
             android:layout_alignParentLeft="true"
@@ -45,22 +45,26 @@
             android:text="@string/theme_font_example"/>
         <ImageView
             android:id="@+id/theme_option_shape"
-            android:layout_width="@dimen/theme_option_sample_right_width"
+            android:layout_width="@dimen/theme_option_sample_width"
             android:layout_height="@dimen/theme_option_sample_height"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"/>
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:padding="@dimen/theme_option_sample_padding"/>
         <ImageView
             android:id="@+id/theme_option_color"
-            android:layout_width="@dimen/theme_option_sample_left_width"
+            android:layout_width="@dimen/theme_option_sample_width"
             android:layout_height="@dimen/theme_option_sample_height"
             android:layout_alignParentBottom="true"
             android:layout_alignParentLeft="true"
+            android:padding="@dimen/theme_option_sample_padding"
             android:src="@drawable/option_color"/>
         <ImageView
             android:id="@+id/theme_option_icon"
-            android:layout_width="@dimen/theme_option_sample_right_width"
+            android:layout_width="@dimen/theme_option_sample_width"
             android:layout_height="@dimen/theme_option_sample_height"
             android:layout_alignParentBottom="true"
-            android:layout_alignParentRight="true"/>
+            android:layout_alignParentRight="true"
+            android:padding="@dimen/theme_option_sample_padding"/>
     </RelativeLayout>
 </LinearLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 2bdd26a..bbfb5df 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -20,4 +20,7 @@
 
     <color name="system_navigation_bar_background">@android:color/white</color>
     <color name="system_navigation_bar_divider">#1f000000</color>
+
+    <color name="shape_thumbnail_color">#b2b2b2</color>
+    <color name="icon_thumbnail_color">@android:color/black</color>
 </resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 10a40f0..9405314 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -34,14 +34,14 @@
     <!-- Dimensions for the customization option tiles -->
     <dimen name="options_container_height">100dp</dimen>
     <dimen name="option_tile_width">72dp</dimen>
-    <dimen name="option_tile_padding_vertical">16dp</dimen>
+    <dimen name="theme_option_sample_height">23dp</dimen>
+    <dimen name="theme_option_sample_width">23dp</dimen>
+    <dimen name="theme_option_sample_padding">2dp</dimen>
+    <dimen name="option_tile_padding_vertical">12dp</dimen>
     <dimen name="option_tile_padding_horizontal">10dp</dimen>
     <!-- Note, using dp instead of sp as this text is more like a "snapshot" of the font -->
     <dimen name="theme_option_font_text_size">10dp</dimen>
 
-    <dimen name="theme_option_sample_right_width">20dp</dimen>
-    <dimen name="theme_option_sample_height">18dp</dimen>
-    <dimen name="theme_option_sample_left_width">22dp</dimen>
     <dimen name="option_tile_margin_horizontal">4dp</dimen>
     <dimen name="theme_option_label_margin">4dp</dimen>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 01bdca1..1e46cad 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -32,7 +32,7 @@
         <item name="android:windowNoTitle">true</item>
     </style>
 
-    <style name="BottomNavStyle" parent="@style/Widget.MaterialComponents.BottomNavigationView">
+    <style name="BottomNavStyle">
         <item name="itemIconTint">@color/bottom_nav_item_color</item>
         <item name="itemTextColor">@color/bottom_nav_item_color</item>
         <item name="itemTextAppearanceActive">@style/BottomNavTextAppearance</item>
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index 0ab3bba..92c7946 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -22,6 +22,7 @@
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -43,6 +44,11 @@
     private static final String TITLE_PREFIX = "theme_title_";
     private static final String FONT_PREFIX = "theme_overlay_font_";
     private static final String COLOR_PREFIX = "theme_overlay_color_";
+    private static final String SHAPE_PREFIX = "theme_overlay_shape_";
+    private static final String ICON_ANDROID_PREFIX = "theme_overlay_icon_android_";
+    private static final String ICON_SETTINGS_PREFIX = "theme_overlay_icon_settings_";
+    private static final String ICON_SYSTEM_PREFIX = "theme_overlay_icon_system_";
+    private static final String ICON_PREVIEW_DRAWABLE_NAME = "ic_wifi_signal_3";
 
     private static final String DEFAULT_THEME_NAME= "default";
 
@@ -50,6 +56,8 @@
     private static final String ACCENT_COLOR_DARK_NAME = "accent_device_default_dark";
     private static final String CONFIG_BODY_FONT_FAMILY = "config_bodyFontFamily";
     private static final String CONFIG_HEADLINE_FONT_FAMILY = "config_headlineFontFamily";
+    private static final String CONFIG_ICON_MASK = "config_icon_mask";
+    private static final String ANDROID_PACKAGE = "android";
 
     private final Context mContext;
     private final String mStubPackageName;
@@ -75,7 +83,7 @@
                 mStubApkResources = pm.getResourcesForApplication(stubAppInfo);
             }
         } catch (NameNotFoundException e) {
-            Log.w(TAG, "Themes stub APK not found.");
+            Log.w(TAG, String.format("Themes stub APK for %s not found.", mStubPackageName));
         }
     }
 
@@ -134,7 +142,41 @@
                                     colorOverlayPackage));
                 }
 
-                //TODO (santie) read the other overlays
+                String shapeOverlayPackage = getOverlayPackage(SHAPE_PREFIX, themeName);
+
+                if (!TextUtils.isEmpty(shapeOverlayPackage)) {
+                    builder.setShapePackage(shapeOverlayPackage)
+                            .setShapePath(loadString(CONFIG_ICON_MASK, shapeOverlayPackage));
+                } else {
+                    builder.setShapePath(mContext.getResources().getString(
+                            Resources.getSystem().getIdentifier(CONFIG_ICON_MASK, "string",
+                                    ANDROID_PACKAGE)));
+                }
+
+                String iconAndroidOverlayPackage = getOverlayPackage(ICON_ANDROID_PREFIX, themeName);
+
+                if (!TextUtils.isEmpty(iconAndroidOverlayPackage)) {
+                    builder.addIconPackage(iconAndroidOverlayPackage)
+                            .addIcon(loadIconPreviewDrawable(ICON_PREVIEW_DRAWABLE_NAME,
+                                    iconAndroidOverlayPackage));
+                } else {
+                    builder.addIcon(mContext.getResources().getDrawable(
+                            Resources.getSystem().getIdentifier(ICON_PREVIEW_DRAWABLE_NAME,
+                                    "drawable", ANDROID_PACKAGE), null));
+                }
+
+                String iconSystemOverlayPackage = getOverlayPackage(ICON_SYSTEM_PREFIX, themeName);
+
+                if (!TextUtils.isEmpty(iconSystemOverlayPackage)) {
+                    builder.addIconPackage(iconSystemOverlayPackage);
+                }
+
+                String iconSettingsOverlayPackage = getOverlayPackage(ICON_SETTINGS_PREFIX,
+                        themeName);
+
+                if (!TextUtils.isEmpty(iconSettingsOverlayPackage)) {
+                    builder.addIconPackage(iconSettingsOverlayPackage);
+                }
 
                 mThemes.add(builder.build());
             } catch (NameNotFoundException | NotFoundException e) {
@@ -171,11 +213,11 @@
         } catch (NameNotFoundException | NotFoundException e) {
             Log.i(TAG, "Didn't find color overlay for default theme, will use system default", e);
             int colorAccentLight = system.getColor(
-                    system.getIdentifier(ACCENT_COLOR_LIGHT_NAME, "color", "android"), null);
+                    system.getIdentifier(ACCENT_COLOR_LIGHT_NAME, "color", ANDROID_PACKAGE), null);
             builder.setColorAccentLight(colorAccentLight);
 
             int colorAccentDark = system.getColor(
-                    system.getIdentifier(ACCENT_COLOR_DARK_NAME, "color", "android"), null);
+                    system.getIdentifier(ACCENT_COLOR_DARK_NAME, "color", ANDROID_PACKAGE), null);
             builder.setColorAccentDark(colorAccentDark);
             builder.setColorPackage(null);
         }
@@ -191,14 +233,38 @@
         } catch (NameNotFoundException | NotFoundException e) {
             Log.i(TAG, "Didn't find font overlay for default theme, will use system default", e);
             String headlineFontFamily = system.getString(system.getIdentifier(
-                    CONFIG_HEADLINE_FONT_FAMILY,"string", "android"));
+                    CONFIG_HEADLINE_FONT_FAMILY,"string", ANDROID_PACKAGE));
             String bodyFontFamily = system.getString(system.getIdentifier(CONFIG_BODY_FONT_FAMILY,
-                    "string", "android"));
+                    "string", ANDROID_PACKAGE));
             builder.setHeadlineFontFamily(Typeface.create(headlineFontFamily, Typeface.NORMAL))
                     .setBodyFontFamily(Typeface.create(bodyFontFamily, Typeface.NORMAL));
             builder.setFontOverlayPackage(null);
         }
 
+        try {
+            builder.setShapePackage(getOverlayPackage(SHAPE_PREFIX, DEFAULT_THEME_NAME))
+                    .setShapePath(loadString(ICON_PREVIEW_DRAWABLE_NAME, colorOverlayPackage));
+        } catch (NameNotFoundException | NotFoundException e) {
+            Log.i(TAG, "Didn't find shape overlay for default theme, will use system default", e);
+            String iconMaskPath = system.getString(system.getIdentifier(CONFIG_ICON_MASK,
+                    "string", ANDROID_PACKAGE));
+            builder.setShapePath(iconMaskPath);
+        }
+
+
+        try {
+            String iconAndroidOverlayPackage = getOverlayPackage(ICON_ANDROID_PREFIX,
+                    DEFAULT_THEME_NAME);
+            builder.addIconPackage(iconAndroidOverlayPackage)
+                    .addIcon(loadIconPreviewDrawable(ICON_ANDROID_PREFIX,
+                            iconAndroidOverlayPackage));
+        } catch (NameNotFoundException | NotFoundException e) {
+            Log.i(TAG, "Didn't find Android icons overlay for default theme, using system default",
+                    e);
+            builder.addIcon(system.getDrawable(system.getIdentifier(ICON_PREVIEW_DRAWABLE_NAME,
+                            "drawable", ANDROID_PACKAGE), null));
+        }
+
         mThemes.add(builder.build());
     }
 
@@ -229,4 +295,19 @@
         return overlayRes.getColor(overlayRes.getIdentifier(colorName, "color", colorPackage),
                 null);
     }
+
+    private String loadString(String stringName, String packageName)
+            throws NameNotFoundException, NotFoundException {
+
+        Resources overlayRes = mContext.getPackageManager().getResourcesForApplication(packageName);
+        return overlayRes.getString(overlayRes.getIdentifier(stringName, "string", packageName));
+    }
+
+    private Drawable loadIconPreviewDrawable(String drawableName, String packageName)
+         throws NameNotFoundException, NotFoundException {
+
+        Resources overlayRes = mContext.getPackageManager().getResourcesForApplication(packageName);
+        return overlayRes.getDrawable(
+                overlayRes.getIdentifier(drawableName, "drawable", packageName), null);
+    }
 }
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index 6df7592..cf6055c 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -16,8 +16,13 @@
 package com.android.customization.model.theme;
 
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.PathShape;
+import android.text.TextUtils;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -25,6 +30,7 @@
 import androidx.annotation.ColorInt;
 import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
+import androidx.core.graphics.PathParser;
 
 import com.android.customization.model.CustomizationOption;
 import com.android.wallpaper.R;
@@ -56,10 +62,24 @@
 
     @Override
     public void bindThumbnailTile(View view) {
+        Resources res = view.getContext().getResources();
+
         ((ImageView) view.findViewById(R.id.theme_option_color)).setImageTintList(
                 ColorStateList.valueOf(mPreviewInfo.colorAccentLight));
         ((TextView) view.findViewById(R.id.theme_option_font)).setTypeface(
                 mPreviewInfo.headlineFontFamily);
+        if (mPreviewInfo.shapeDrawable != null) {
+            ((ShapeDrawable)mPreviewInfo.shapeDrawable).getPaint().setColor(res.getColor(
+                    R.color.shape_thumbnail_color, null));
+            ((ImageView) view.findViewById(R.id.theme_option_shape)).setImageDrawable(
+                    mPreviewInfo.shapeDrawable);
+        }
+        if (!mPreviewInfo.icons.isEmpty()) {
+            Drawable icon = mPreviewInfo.icons.get(0).mutate();
+            icon.setTint(res.getColor(R.color.icon_thumbnail_color, null));
+            ((ImageView) view.findViewById(R.id.theme_option_icon)).setImageDrawable(
+                    icon);
+        }
     }
 
     @Override
@@ -82,24 +102,25 @@
         @ColorInt public final int colorAccentLight;
         @ColorInt public final int colorAccentDark;
         public final List<Drawable> icons;
-        public final String shapePath;
+        public final Drawable shapeDrawable;
         @DrawableRes public final int wallpaperDrawableRes;
 
         public PreviewInfo(Typeface bodyFontFamily, Typeface headlineFontFamily,
                 int colorAccentLight,
-                int colorAccentDark, List<Drawable> icons, String shapePath,
+                int colorAccentDark, List<Drawable> icons, Drawable shapeDrawable,
                 int wallpaperDrawableRes) {
             this.bodyFontFamily = bodyFontFamily;
             this.headlineFontFamily = headlineFontFamily;
             this.colorAccentLight = colorAccentLight;
             this.colorAccentDark = colorAccentDark;
             this.icons = icons;
-            this.shapePath = shapePath;
+            this.shapeDrawable = shapeDrawable;
             this.wallpaperDrawableRes = wallpaperDrawableRes;
         }
     }
 
     public static class Builder {
+        private static final float PATH_SIZE = 100f;
         private String mTitle;
         private Typeface mBodyFontFamily;
         private Typeface mHeadlineFontFamily;
@@ -115,9 +136,17 @@
         private String mShapePackage;
 
         public ThemeBundle build() {
+            ShapeDrawable shapeDrawable = null;
+            if (!TextUtils.isEmpty(mShapePath)) {
+                PathShape shape = new PathShape(PathParser.createPathFromPathData(mShapePath),
+                                PATH_SIZE, PATH_SIZE);
+                shapeDrawable = new ShapeDrawable(shape);
+                shapeDrawable.setIntrinsicHeight((int) PATH_SIZE);
+                shapeDrawable.setIntrinsicWidth((int) PATH_SIZE);
+            }
             return new ThemeBundle(mTitle,
                     new PreviewInfo(mBodyFontFamily, mHeadlineFontFamily, mColorAccentLight,
-                            mColorAccentDark, mIcons, mShapePath, mWallpaperDrawableResId));
+                            mColorAccentDark, mIcons, shapeDrawable, mWallpaperDrawableResId));
         }
 
         public Builder setTitle(String title) {
@@ -154,5 +183,25 @@
             mColorAccentDark = colorAccentDark;
             return this;
         }
+
+        public Builder addIcon(Drawable icon) {
+            mIcons.add(icon);
+            return this;
+        }
+
+        public Builder addIconPackage(String packageName) {
+            mIconPackages.add(packageName);
+            return this;
+        }
+
+        public Builder setShapePackage(String packageName) {
+            mShapePackage = packageName;
+            return this;
+        }
+
+        public Builder setShapePath(String path) {
+            mShapePath = path;
+            return this;
+        }
     }
 }