Merge Coral/Flame into AOSP master

Bug: 141248619
Change-Id: I549bae611a1699ab4ed112fa30a7d2a8ad02985f
Merged-In: Idff1f3caff103926cd2cb267dab1d96bbb4daf33
diff --git a/res/drawable/ic_colorize_24px.xml b/res/drawable/ic_colorize_24px.xml
index 8363683..fb70972 100644
--- a/res/drawable/ic_colorize_24px.xml
+++ b/res/drawable/ic_colorize_24px.xml
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="32dp"
-    android:height="32dp"
+    android:width="24dp"
+    android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
     <path
diff --git a/res/drawable/ic_font.xml b/res/drawable/ic_font.xml
index 6ce8308..f5df7ba 100644
--- a/res/drawable/ic_font.xml
+++ b/res/drawable/ic_font.xml
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="32dp"
-    android:height="32dp"
+    android:width="24dp"
+    android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
     <!-- This path represents a square with rounded corners -->
diff --git a/res/drawable/ic_nav_wallpaper.xml b/res/drawable/ic_nav_wallpaper.xml
index a884a44..c935666 100644
--- a/res/drawable/ic_nav_wallpaper.xml
+++ b/res/drawable/ic_nav_wallpaper.xml
@@ -15,8 +15,8 @@
 -->
 <!-- Represents the wallpaper icon (a "landscape" shape in a box) -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="32dp"
-    android:height="32dp"
+    android:width="24dp"
+    android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
     <path
diff --git a/res/drawable/ic_shapes_24px.xml b/res/drawable/ic_shapes_24px.xml
index 6debc53..525f757 100644
--- a/res/drawable/ic_shapes_24px.xml
+++ b/res/drawable/ic_shapes_24px.xml
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="32dp"
-    android:height="32dp"
+    android:width="24dp"
+    android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
     <path
diff --git a/res/drawable/ic_wifi_24px.xml b/res/drawable/ic_wifi_24px.xml
index 64834e0..0e27c57 100644
--- a/res/drawable/ic_wifi_24px.xml
+++ b/res/drawable/ic_wifi_24px.xml
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="32dp"
-    android:height="32dp"
+    android:width="24dp"
+    android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
     <path
diff --git a/res/layout/theme_color_option.xml b/res/layout/theme_color_option.xml
index 12fe623..33e4668 100644
--- a/res/layout/theme_color_option.xml
+++ b/res/layout/theme_color_option.xml
@@ -22,8 +22,8 @@
 
     <ImageView
         android:id="@+id/option_tile"
-        android:layout_width="@dimen/component_color_chip_size"
-        android:layout_height="@dimen/component_color_chip_size"
+        android:layout_width="@dimen/component_color_chip_container_size"
+        android:layout_height="@dimen/component_color_chip_container_size"
         android:layout_gravity="center"
         android:src="@drawable/color_chip"/>
 </FrameLayout>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 3dd33ed..7c372ae 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -47,7 +47,7 @@
     <string name="apply_theme_error_msg" msgid="791364062636538317">"Se produjo un error al aplicar el estilo"</string>
     <string name="custom_theme_next" msgid="6235420097213197301">"Siguiente"</string>
     <string name="custom_theme_previous" msgid="4941132112640503022">"Anterior"</string>
-    <string name="custom_theme_title" msgid="2192300350332693631">"<xliff:g id="ID_1">%1$d</xliff:g> personalizado"</string>
+    <string name="custom_theme_title" msgid="2192300350332693631">"Personalizado <xliff:g id="ID_1">%1$d</xliff:g>"</string>
     <string name="custom_theme_fragment_title" msgid="6615547284702040280">"Estilo personalizado"</string>
     <string name="custom_theme_delete" msgid="4744494663184126202">"Borrar"</string>
     <string name="font_component_title" msgid="8800340833695292049">"Elegir fuente"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 1b9c7cc..67721f8 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -23,7 +23,7 @@
     <string name="grid_title" msgid="2825094404523390773">"Petak"</string>
     <string name="wallpaper_title" msgid="6952635398953194544">"Wallpaper"</string>
     <string name="apply_theme_btn" msgid="6293081192321303991">"Terapkan"</string>
-    <string name="edit_custom_theme_lbl" msgid="5211377705710775224">"Tap untuk mengedit"</string>
+    <string name="edit_custom_theme_lbl" msgid="5211377705710775224">"Ketuk untuk mengedit"</string>
     <string name="keep_my_wallpaper" msgid="8012385376769568517">"Pertahankan wallpaper saat ini"</string>
     <string name="apply_btn" msgid="7965877231041987336">"Terapkan"</string>
     <string name="accessibility_preview_pager" msgid="3548503287402185430">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> dari <xliff:g id="ID_2">%2$d</xliff:g>"</string>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index ddf84e8..985987f 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -18,6 +18,7 @@
 <resources>
     <dimen name="card_title_text_size">12sp</dimen>
     <dimen name="card_cover_title_text_size">14sp</dimen>
+    <dimen name="card_header_icon_size">24dp</dimen>
     <dimen name="card_header_top_margin">6dp</dimen>
     <dimen name="preview_card_padding">8dp</dimen>
     <dimen name="preview_card_top_padding">6dp</dimen>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5c98fda..a2cb88b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -66,6 +66,7 @@
 
     <dimen name="card_title_text_size">16sp</dimen>
     <dimen name="card_cover_title_text_size">24sp</dimen>
+    <dimen name="card_header_icon_size">32dp</dimen>
     <dimen name="card_header_top_margin">0dp</dimen>
     <dimen name="preview_pager_max_height">450dp</dimen>
     <dimen name="preview_pager_min_height">350dp</dimen>
@@ -95,6 +96,7 @@
     <dimen name="component_icon_thumb_size">40dp</dimen>
 
     <dimen name="component_color_chip_size">32dp</dimen>
+    <dimen name="component_color_chip_container_size">33dp</dimen>
 
     <dimen name="component_shape_thumb_size">72dp</dimen>
     <dimen name="option_border_width">2dp</dimen>
diff --git a/src/com/android/customization/model/ResourcesApkProvider.java b/src/com/android/customization/model/ResourcesApkProvider.java
index f770dbc..92e03b9 100644
--- a/src/com/android/customization/model/ResourcesApkProvider.java
+++ b/src/com/android/customization/model/ResourcesApkProvider.java
@@ -25,8 +25,8 @@
             Resources apkResources = null;
             try {
                 PackageManager pm = mContext.getPackageManager();
-                ApplicationInfo stubAppInfo = pm.getApplicationInfo(
-                        mStubPackageName, PackageManager.GET_META_DATA);
+                ApplicationInfo stubAppInfo = pm.getApplicationInfo(mStubPackageName,
+                        PackageManager.GET_META_DATA | PackageManager.MATCH_SYSTEM_ONLY);
                 if (stubAppInfo != null) {
                     apkResources = pm.getResourcesForApplication(stubAppInfo);
                 }
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index 9fdb0c9..ce12d35 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -35,7 +35,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.service.wallpaper.WallpaperService;
 import android.text.TextUtils;
@@ -53,6 +52,7 @@
 import com.android.wallpaper.model.LiveWallpaperInfo;
 
 import com.bumptech.glide.request.RequestOptions;
+import com.google.android.apps.wallpaper.asset.ThemeBundleThumbAsset;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -204,7 +204,7 @@
                         mStubApkResources.getIdentifier(WALLPAPER_ACTION_PREFIX + themeName,
                                 "string", mStubPackageName))
                         .setWallpaperAsset(wallpaperThumbnailResId != ID_NULL ?
-                                getDrawableResourceAsset(WALLPAPER_THUMB_PREFIX, themeName)
+                                getThumbAsset(WALLPAPER_THUMB_PREFIX, themeName)
                                 : getDrawableResourceAsset(WALLPAPER_PREFIX, themeName));
             } else {
                 // Try to see if it's a live wallpaper reference
@@ -234,7 +234,7 @@
                             LiveWallpaperInfo liveInfo = new LiveWallpaperInfo(wallpaperInfo);
                             builder.setLiveWallpaperInfo(liveInfo).setWallpaperAsset(
                                     wallpaperThumbnailResId != ID_NULL ?
-                                        getDrawableResourceAsset(WALLPAPER_THUMB_PREFIX, themeName)
+                                            getThumbAsset(WALLPAPER_THUMB_PREFIX, themeName)
                                         : liveInfo.getThumbAsset(mContext))
                                     .setWallpaperOptions(wallpaperOptions);
                         } catch (XmlPullParserException | IOException e) {
@@ -484,4 +484,11 @@
         return drawableResId == 0 ? null : new ResourceAsset(mStubApkResources, drawableResId,
                 RequestOptions.fitCenterTransform());
     }
+
+    private ThemeBundleThumbAsset getThumbAsset(String prefix, String themeName) {
+        int drawableResId = mStubApkResources.getIdentifier(prefix + themeName,
+                "drawable", mStubPackageName);
+        return drawableResId == 0 ? null : new ThemeBundleThumbAsset(mStubApkResources,
+                drawableResId);
+    }
 }
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index 2fc5d90..e83e852 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -113,7 +113,7 @@
                 mPreviewInfo.headlineFontFamily);
         if (mPreviewInfo.shapeDrawable != null) {
             ((ShapeDrawable) mPreviewInfo.shapeDrawable).getPaint().setColor(
-                    mPreviewInfo.colorAccentLight);
+                    mPreviewInfo.resolveAccentColor(res));
             ((ImageView) view.findViewById(R.id.theme_option_shape)).setImageDrawable(
                     mPreviewInfo.shapeDrawable);
         }
diff --git a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
index ff8da08..f918d8e 100644
--- a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
+++ b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
@@ -163,7 +163,13 @@
             @DrawableRes int headerIcon) {
         TextView header = container.findViewById(R.id.theme_preview_card_header);
         header.setText(headerTextResId);
-        header.setCompoundDrawablesWithIntrinsicBounds(0, headerIcon, 0, 0);
+
+        Context context = container.getContext();
+        Drawable icon = context.getResources().getDrawable(headerIcon, context.getTheme());
+        int size = context.getResources().getDimensionPixelSize(R.dimen.card_header_icon_size);
+        icon.setBounds(0, 0, size, size);
+
+        header.setCompoundDrawables(null, icon, null, null);
         header.setCompoundDrawableTintList(ColorStateList.valueOf(
                 header.getCurrentTextColor()));
     }
diff --git a/src/com/android/customization/module/StatsLogUserEventLogger.java b/src/com/android/customization/module/StatsLogUserEventLogger.java
index b77d7dc..37c64ac 100644
--- a/src/com/android/customization/module/StatsLogUserEventLogger.java
+++ b/src/com/android/customization/module/StatsLogUserEventLogger.java
@@ -39,32 +39,33 @@
 public class StatsLogUserEventLogger extends NoOpUserEventLogger implements ThemesUserEventLogger {
 
     private static final String TAG = "StatsLogUserEventLogger";
+    private static final int CODE = 179;
 
     @Override
     public void logResumed(boolean provisioned, boolean wallpaper) {
-        StatsLogCompat.write(StyleEnums.ONRESUME, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+        WallpaperStatsLog.write(CODE, StyleEnums.ONRESUME, 0, 0, 0, 0, 0, 0, 0, 0, 0);
     }
 
     @Override
     public void logStopped() {
-        StatsLogCompat.write(StyleEnums.ONSTOP, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+        WallpaperStatsLog.write(CODE, StyleEnums.ONSTOP, 0, 0, 0, 0, 0, 0, 0, 0, 0);
     }
 
     @Override
     public void logActionClicked(String collectionId, int actionLabelResId) {
-        StatsLogCompat.write(StyleEnums.WALLPAPER_EXPLORE, 0, 0, 0, 0, 0, collectionId.hashCode(),
+        WallpaperStatsLog.write(CODE, StyleEnums.WALLPAPER_EXPLORE, 0, 0, 0, 0, 0, collectionId.hashCode(),
                 0, 0, 0);
     }
 
     @Override
     public void logIndividualWallpaperSelected(String collectionId) {
-        StatsLogCompat.write(StyleEnums.WALLPAPER_SELECT, 0, 0, 0, 0, 0, 0,
+        WallpaperStatsLog.write(CODE, StyleEnums.WALLPAPER_SELECT, 0, 0, 0, 0, 0, 0,
                 collectionId.hashCode(), 0, 0);
     }
 
     @Override
     public void logCategorySelected(String collectionId) {
-        StatsLogCompat.write(StyleEnums.WALLPAPER_SELECT,
+        WallpaperStatsLog.write(CODE, StyleEnums.WALLPAPER_SELECT,
                 0, 0, 0, 0, 0,
                 collectionId.hashCode(),
                 0, 0, 0);
@@ -72,7 +73,7 @@
 
     @Override
     public void logWallpaperSet(String collectionId, @Nullable String wallpaperId) {
-        StatsLogCompat.write(StyleEnums.WALLPAPER_SELECT,
+        WallpaperStatsLog.write(CODE, StyleEnums.WALLPAPER_SELECT,
                 0, 0, 0, 0, 0,
                 collectionId.hashCode(),
                 0, 0, 0);
@@ -86,7 +87,7 @@
 
     @Override
     public void logThemeSelected(ThemeBundle theme, boolean isCustomTheme) {
-        StatsLogCompat.write(StyleEnums.PICKER_SELECT,
+        WallpaperStatsLog.write(CODE, StyleEnums.PICKER_SELECT,
                 Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_COLOR)),
                 Objects.hashCode(getThemePackage(theme,OVERLAY_CATEGORY_FONT)),
                 Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_SHAPE)),
@@ -95,7 +96,7 @@
 
     @Override
     public void logThemeApplied(ThemeBundle theme, boolean isCustomTheme) {
-        StatsLogCompat.write(StyleEnums.PICKER_APPLIED,
+        WallpaperStatsLog.write(CODE, StyleEnums.PICKER_APPLIED,
                 Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_COLOR)),
                 Objects.hashCode(getThemePackage(theme,OVERLAY_CATEGORY_FONT)),
                 Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_SHAPE)),
@@ -104,7 +105,7 @@
 
     @Override
     public void logClockSelected(Clockface clock) {
-        StatsLogCompat.write(StyleEnums.PICKER_SELECT,
+        WallpaperStatsLog.write(CODE, StyleEnums.PICKER_SELECT,
                 0, 0, 0,
                 Objects.hashCode(clock.getId()),
                 0, 0, 0, 0, 0);
@@ -112,7 +113,7 @@
 
     @Override
     public void logClockApplied(Clockface clock) {
-        StatsLogCompat.write(StyleEnums.PICKER_APPLIED,
+        WallpaperStatsLog.write(CODE, StyleEnums.PICKER_APPLIED,
                 0, 0, 0,
                 Objects.hashCode(clock.getId()),
                 0, 0, 0, 0, 0);
@@ -120,7 +121,7 @@
 
     @Override
     public void logGridSelected(GridOption grid) {
-        StatsLogCompat.write(StyleEnums.PICKER_SELECT,
+        WallpaperStatsLog.write(CODE, StyleEnums.PICKER_SELECT,
                 0, 0, 0, 0,
                 grid.cols,
                 0, 0, 0, 0);
@@ -128,7 +129,7 @@
 
     @Override
     public void logGridApplied(GridOption grid) {
-        StatsLogCompat.write(StyleEnums.PICKER_APPLIED,
+        WallpaperStatsLog.write(CODE, StyleEnums.PICKER_APPLIED,
                 0, 0, 0, 0,
                 grid.cols,
                 0, 0, 0, 0);
diff --git a/src/com/android/customization/module/WallpaperStatsLog.java b/src/com/android/customization/module/WallpaperStatsLog.java
new file mode 100644
index 0000000..9f5761f
--- /dev/null
+++ b/src/com/android/customization/module/WallpaperStatsLog.java
@@ -0,0 +1,147 @@
+// This file is autogenerated
+
+package com.android.customization.module;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.util.StatsLog;
+import android.os.SystemClock;
+
+import java.util.ArrayList;
+
+
+/**
+ * Utility class for logging statistics events.
+ */
+public class WallpaperStatsLog {
+    private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
+    private static final int MAX_EVENT_PAYLOAD = LOGGER_ENTRY_MAX_PAYLOAD - 4;
+    private static final byte INT_TYPE = 0;
+    private static final byte LONG_TYPE = 1;
+    private static final byte STRING_TYPE = 2;
+    private static final byte LIST_TYPE = 3;
+    private static final byte FLOAT_TYPE = 4;
+    private static final int INT_TYPE_SIZE = 5;
+    private static final int FLOAT_TYPE_SIZE = 5;
+    private static final int LONG_TYPE_SIZE = 9;
+    private static final int STRING_TYPE_OVERHEAD = 5;
+    private static final int LIST_TYPE_OVERHEAD = 2;
+    // Constants for atom codes.
+
+    /**
+     * StyleUIChanged style_ui_changed<br>
+     * Usage: StatsLog.write(StatsLog.STYLE_UI_CHANGED, int action, int color_package_hash, int font_package_hash, int shape_package_hash, int clock_package_hash, int launcher_grid, int wallpaper_category_hash, int wallpaper_id_hash, int color_preference, int location_preference);<br>
+     */
+    public static final int STYLE_UI_CHANGED = 179;
+
+    // Constants for enum values.
+
+    // Values for StyleUIChanged.action
+    public static final int STYLE_UICHANGED__ACTION__DEFAULT_ACTION = 0;
+    public static final int STYLE_UICHANGED__ACTION__ONRESUME = 1;
+    public static final int STYLE_UICHANGED__ACTION__ONSTOP = 2;
+    public static final int STYLE_UICHANGED__ACTION__PICKER_SELECT = 3;
+    public static final int STYLE_UICHANGED__ACTION__PICKER_APPLIED = 4;
+    public static final int STYLE_UICHANGED__ACTION__WALLPAPER_OPEN_CATEGORY = 5;
+    public static final int STYLE_UICHANGED__ACTION__WALLPAPER_SELECT = 6;
+    public static final int STYLE_UICHANGED__ACTION__WALLPAPER_APPLIED = 7;
+    public static final int STYLE_UICHANGED__ACTION__WALLPAPER_EXPLORE = 8;
+    public static final int STYLE_UICHANGED__ACTION__WALLPAPER_DOWNLOAD = 9;
+    public static final int STYLE_UICHANGED__ACTION__WALLPAPER_REMOVE = 10;
+    public static final int STYLE_UICHANGED__ACTION__LIVE_WALLPAPER_DOWNLOAD_SUCCESS = 11;
+    public static final int STYLE_UICHANGED__ACTION__LIVE_WALLPAPER_DOWNLOAD_FAILED = 12;
+    public static final int STYLE_UICHANGED__ACTION__LIVE_WALLPAPER_DOWNLOAD_CANCELLED = 13;
+    public static final int STYLE_UICHANGED__ACTION__LIVE_WALLPAPER_DELETE_SUCCESS = 14;
+    public static final int STYLE_UICHANGED__ACTION__LIVE_WALLPAPER_DELETE_FAILED = 15;
+    public static final int STYLE_UICHANGED__ACTION__LIVE_WALLPAPER_APPLIED = 16;
+
+    // Values for StyleUIChanged.location_preference
+    public static final int STYLE_UICHANGED__LOCATION_PREFERENCE__LOCATION_PREFERENCE_UNSPECIFIED = 0;
+    public static final int STYLE_UICHANGED__LOCATION_PREFERENCE__LOCATION_UNAVAILABLE = 1;
+    public static final int STYLE_UICHANGED__LOCATION_PREFERENCE__LOCATION_CURRENT = 2;
+    public static final int STYLE_UICHANGED__LOCATION_PREFERENCE__LOCATION_MANUAL = 3;
+
+    // Write methods
+    public static void write(int code, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10) {
+        // Initial overhead of the list, timestamp, and atom tag.
+        int needed = LIST_TYPE_OVERHEAD + LONG_TYPE_SIZE + INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        needed += INT_TYPE_SIZE;
+        if (needed > MAX_EVENT_PAYLOAD) {
+            return;
+        }
+        byte[] buff = new byte[needed];
+        int pos = 0;
+        buff[pos] = LIST_TYPE;
+        buff[pos + 1] = 12;
+        pos += LIST_TYPE_OVERHEAD;
+        long elapsedRealtime = SystemClock.elapsedRealtimeNanos();
+        buff[pos] = LONG_TYPE;
+        copyLong(buff, pos + 1, elapsedRealtime);
+        pos += LONG_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, code);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg1);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg2);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg3);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg4);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg5);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg6);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg7);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg8);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg9);
+        pos += INT_TYPE_SIZE;
+        buff[pos] = INT_TYPE;
+        copyInt(buff, pos + 1, arg10);
+        pos += INT_TYPE_SIZE;
+        StatsLog.writeRaw(buff, pos);
+    }
+
+    // Helper methods for copying primitives
+    private static void copyInt(byte[] buff, int pos, int val) {
+        buff[pos] = (byte) (val);
+        buff[pos + 1] = (byte) (val >> 8);
+        buff[pos + 2] = (byte) (val >> 16);
+        buff[pos + 3] = (byte) (val >> 24);
+        return;
+    }
+
+    private static void copyLong(byte[] buff, int pos, long val) {
+        buff[pos] = (byte) (val);
+        buff[pos + 1] = (byte) (val >> 8);
+        buff[pos + 2] = (byte) (val >> 16);
+        buff[pos + 3] = (byte) (val >> 24);
+        buff[pos + 4] = (byte) (val >> 32);
+        buff[pos + 5] = (byte) (val >> 40);
+        buff[pos + 6] = (byte) (val >> 48);
+        buff[pos + 7] = (byte) (val >> 56);
+        return;
+    }
+
+}
diff --git a/src/com/android/customization/picker/theme/ThemePreviewPage.java b/src/com/android/customization/picker/theme/ThemePreviewPage.java
index f00cd3f..0543b24 100644
--- a/src/com/android/customization/picker/theme/ThemePreviewPage.java
+++ b/src/com/android/customization/picker/theme/ThemePreviewPage.java
@@ -38,8 +38,7 @@
 
     @StringRes
     final int nameResId;
-    @DrawableRes
-    final int iconSrc;
+    final Drawable icon;
     @LayoutRes
     final int contentLayoutRes;
     @ColorInt
@@ -51,7 +50,13 @@
             @ColorInt int accentColor) {
         super(null);
         this.nameResId = titleResId;
-        this.iconSrc = iconSrc;
+        if (iconSrc != Resources.ID_NULL) {
+            this.icon = context.getResources().getDrawable(iconSrc, context.getTheme());
+            int size = context.getResources().getDimensionPixelSize(R.dimen.card_header_icon_size);
+            icon.setBounds(0, 0, size, size);
+        } else {
+            this.icon = null;
+        }
         this.contentLayoutRes = contentLayoutRes;
         this.accentColor = accentColor;
         this.inflater = LayoutInflater.from(context);
@@ -61,7 +66,7 @@
     public void bindPreviewContent() {
         TextView header = card.findViewById(R.id.theme_preview_card_header);
         header.setText(nameResId);
-        header.setCompoundDrawablesWithIntrinsicBounds(0, iconSrc, 0, 0);
+        header.setCompoundDrawables(null, icon, null, null);
         header.setCompoundDrawableTintList(ColorStateList.valueOf(accentColor));
         card.findViewById(R.id.theme_preview_top_bar).setVisibility(View.GONE);
         card.findViewById(R.id.edit_label).setVisibility(View.GONE);
diff --git a/src/com/google/android/apps/wallpaper/asset/ThemeBundleThumbAsset.java b/src/com/google/android/apps/wallpaper/asset/ThemeBundleThumbAsset.java
new file mode 100644
index 0000000..bc5f309
--- /dev/null
+++ b/src/com/google/android/apps/wallpaper/asset/ThemeBundleThumbAsset.java
@@ -0,0 +1,108 @@
+/*
+ * 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 com.google.android.apps.wallpaper.asset;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.AsyncTask;
+
+import androidx.annotation.Nullable;
+
+import com.android.wallpaper.asset.Asset;
+import com.android.wallpaper.module.DrawableLayerResolver;
+import com.android.wallpaper.module.InjectorProvider;
+
+public class ThemeBundleThumbAsset extends Asset {
+    private final Resources mRes;
+    private final int mResId;
+    private final DrawableLayerResolver mLayerResolver;
+
+    public ThemeBundleThumbAsset(Resources res, int resId) {
+        mRes = res;
+        mResId = resId;
+        mLayerResolver = InjectorProvider.getInjector().getDrawableLayerResolver();
+    }
+
+    @Override
+    public void decodeBitmap(int targetWidth, int targetHeight, BitmapReceiver receiver) {
+        // No scaling is needed, as the thumbnail is already a thumbnail.
+        LoadThumbnailTask task = new LoadThumbnailTask(mRes, mResId, mLayerResolver, receiver);
+        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    @Override
+    public void decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight,
+            BitmapReceiver receiver) {
+
+    }
+
+    @Override
+    public void decodeRawDimensions(@Nullable Activity activity, DimensionsReceiver receiver) {
+
+    }
+
+    @Override
+    public boolean supportsTiling() {
+        return false;
+    }
+
+    /**
+     * AsyncTask subclass which loads the live wallpaper's thumbnail bitmap off the main UI thread.
+     * Resolves with null if live wallpaper thumbnail is not a bitmap.
+     */
+    private static class LoadThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
+        private final DrawableLayerResolver mLayerResolver;
+        private final Resources mResources;
+        private final int mResId;
+        private BitmapReceiver mReceiver;
+
+        public LoadThumbnailTask(Resources res, int resId, DrawableLayerResolver resolver,
+                BitmapReceiver receiver) {
+            mLayerResolver = resolver;
+            mReceiver = receiver;
+            mResources = res;
+            mResId = resId;
+        }
+
+        @Override
+        protected Bitmap doInBackground(Void... unused) {
+            Drawable thumb = mResources.getDrawable(mResId, null);
+
+            // Live wallpaper components may or may not specify a thumbnail drawable.
+            if (thumb instanceof BitmapDrawable) {
+                return ((BitmapDrawable) thumb).getBitmap();
+            } else if (thumb instanceof LayerDrawable) {
+                Drawable layer = mLayerResolver.resolveLayer((LayerDrawable) thumb);
+                if (layer instanceof BitmapDrawable) {
+                    return ((BitmapDrawable) layer).getBitmap();
+                }
+            }
+
+            // If no thumbnail was specified, return a null bitmap.
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Bitmap bitmap) {
+            mReceiver.onBitmapDecoded(bitmap);
+        }
+    }
+}