Handle custom theme with default components

If a selected component (font, icon, etc) for a custom theme
is the default one, there's no overlay package, so handle
that case.

Bug: 124796742
Change-Id: I5555af21fe96b73b6b432affb4a6185d05804421
diff --git a/src/com/android/customization/model/ResourceConstants.java b/src/com/android/customization/model/ResourceConstants.java
index 8a3e436..1b52ec9 100644
--- a/src/com/android/customization/model/ResourceConstants.java
+++ b/src/com/android/customization/model/ResourceConstants.java
@@ -71,8 +71,8 @@
     String THEME_SETTING = Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES;
     String CONFIG_BODY_FONT_FAMILY = "config_bodyFontFamily";
     String CONFIG_HEADLINE_FONT_FAMILY = "config_headlineFontFamily";
-    String ICON_PREVIEW_DRAWABLE_NAME = "ic_wifi_signal_3";
-    String[] SYSUI_ICONS_FOR_PREVIEW = {
+    String[] ICONS_FOR_PREVIEW = {
+            "ic_wifi_signal_3",
             "ic_qs_bluetooth_on",
             "ic_dnd",
             "ic_signal_flashlight",
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index f4a09e8..439a7d6 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -19,14 +19,13 @@
 import static com.android.customization.model.ResourceConstants.ACCENT_COLOR_LIGHT_NAME;
 import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
 import static com.android.customization.model.ResourceConstants.CONFIG_ICON_MASK;
-import static com.android.customization.model.ResourceConstants.ICON_PREVIEW_DRAWABLE_NAME;
+import static com.android.customization.model.ResourceConstants.ICONS_FOR_PREVIEW;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_LAUNCHER;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SETTINGS;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SYSUI;
 import static com.android.customization.model.ResourceConstants.SETTINGS_PACKAGE;
-import static com.android.customization.model.ResourceConstants.SYSUI_ICONS_FOR_PREVIEW;
 import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
 
 import android.content.Context;
@@ -235,27 +234,23 @@
     private void addSysUiIconOverlay(Builder builder, String iconSysUiOverlayPackage)
             throws NameNotFoundException {
         if (!TextUtils.isEmpty(iconSysUiOverlayPackage)) {
-            builder.addOverlayPackage(getOverlayCategory(iconSysUiOverlayPackage),
-                    iconSysUiOverlayPackage);
-            for (String iconName : SYSUI_ICONS_FOR_PREVIEW) {
-                builder.addIcon(loadIconPreviewDrawable(iconName, iconSysUiOverlayPackage));
-            }
+            addIconOverlay(builder, iconSysUiOverlayPackage, ICONS_FOR_PREVIEW);
         }
     }
 
     private void addAndroidIconOverlay(Builder builder, String iconAndroidOverlayPackage)
             throws NameNotFoundException {
         if (!TextUtils.isEmpty(iconAndroidOverlayPackage)) {
-            builder.addOverlayPackage(getOverlayCategory(iconAndroidOverlayPackage),
-                        iconAndroidOverlayPackage)
-                    .addIcon(loadIconPreviewDrawable(
-                            ICON_PREVIEW_DRAWABLE_NAME,
-                            iconAndroidOverlayPackage));
+            addIconOverlay(builder, iconAndroidOverlayPackage, ICONS_FOR_PREVIEW);
         } else {
-            builder.addIcon(mContext.getResources().getDrawable(
-                    Resources.getSystem().getIdentifier(
-                            ICON_PREVIEW_DRAWABLE_NAME,
-                            "drawable", ANDROID_PACKAGE), null));
+            addSystemDefaultIcons(builder, ANDROID_PACKAGE, ICONS_FOR_PREVIEW);
+        }
+    }
+    private void addIconOverlay(Builder builder, String packageName, String... previewIcons)
+            throws NameNotFoundException {
+        builder.addOverlayPackage(getOverlayCategory(packageName), packageName);
+        for (String iconName : previewIcons) {
+            builder.addIcon(loadIconPreviewDrawable(iconName, packageName, false));
         }
     }
 
@@ -270,6 +265,8 @@
                     .setHeadlineFontFamily(loadTypeface(
                             ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,
                             fontOverlayPackage));
+        } else {
+            addSystemDefaultFont(builder);
         }
     }
 
@@ -280,7 +277,6 @@
      */
     private void addDefaultTheme() {
         ThemeBundle.Builder builder = new Builder().asDefault();
-        Resources system = Resources.getSystem();
 
         int titleId = mStubApkResources.getIdentifier(TITLE_PREFIX + DEFAULT_THEME_NAME,
                 "string", mStubPackageName);
@@ -298,13 +294,7 @@
                     .setColorAccentDark(loadColor(ACCENT_COLOR_DARK_NAME, colorOverlayPackage));
         } catch (NameNotFoundException | NotFoundException e) {
             Log.d(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_PACKAGE), null);
-            builder.setColorAccentLight(colorAccentLight);
-
-            int colorAccentDark = system.getColor(
-                    system.getIdentifier(ACCENT_COLOR_DARK_NAME, "color", ANDROID_PACKAGE), null);
-            builder.setColorAccentDark(colorAccentDark);
+            addSystemDefaultColor(builder);
         }
 
         String fontOverlayPackage = getOverlayPackage(FONT_PREFIX, DEFAULT_THEME_NAME);
@@ -318,24 +308,16 @@
                             fontOverlayPackage));
         } catch (NameNotFoundException | NotFoundException e) {
             Log.d(TAG, "Didn't find font overlay for default theme, will use system default", e);
-            String headlineFontFamily = system.getString(system.getIdentifier(
-                    ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,"string", ANDROID_PACKAGE));
-            String bodyFontFamily = system.getString(system.getIdentifier(
-                    ResourceConstants.CONFIG_BODY_FONT_FAMILY,
-                    "string", ANDROID_PACKAGE));
-            builder.setHeadlineFontFamily(Typeface.create(headlineFontFamily, Typeface.NORMAL))
-                    .setBodyFontFamily(Typeface.create(bodyFontFamily, Typeface.NORMAL));
+            addSystemDefaultFont(builder);
         }
 
         try {
             String shapeOverlayPackage = getOverlayPackage(SHAPE_PREFIX, DEFAULT_THEME_NAME);
             builder.addOverlayPackage(getOverlayCategory(shapeOverlayPackage), shapeOverlayPackage)
-                    .setShapePath(loadString(ICON_PREVIEW_DRAWABLE_NAME, colorOverlayPackage));
+                    .setShapePath(loadString(CONFIG_ICON_MASK, shapeOverlayPackage));
         } catch (NameNotFoundException | NotFoundException e) {
             Log.d(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);
+            addSystemDefaultShape(builder);
         }
         for (String packageName : mShapePreviewIconPackages) {
             try {
@@ -353,13 +335,11 @@
             builder.addOverlayPackage(getOverlayCategory(iconAndroidOverlayPackage),
                         iconAndroidOverlayPackage)
                     .addIcon(loadIconPreviewDrawable(ICON_ANDROID_PREFIX,
-                            iconAndroidOverlayPackage));
+                            iconAndroidOverlayPackage, false));
         } catch (NameNotFoundException | NotFoundException e) {
             Log.d(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));
+            addSystemDefaultIcons(builder, ANDROID_PACKAGE, ICONS_FOR_PREVIEW);
         }
 
         try {
@@ -369,13 +349,7 @@
         } catch (NameNotFoundException | NotFoundException e) {
             Log.d(TAG, "Didn't find SystemUi icons overlay for default theme, using system default",
                     e);
-            try {
-                for (String iconName : SYSUI_ICONS_FOR_PREVIEW) {
-                    builder.addIcon(loadIconPreviewDrawable(iconName, SYSUI_PACKAGE));
-                }
-            } catch (NameNotFoundException | NotFoundException e2) {
-                Log.w(TAG, "Didn't find SystemUi package icons, will skip preview", e);
-            }
+            addSystemDefaultIcons(builder, SYSUI_PACKAGE, ICONS_FOR_PREVIEW);
         }
 
         try {
@@ -405,6 +379,45 @@
         mThemes.add(builder.build());
     }
 
+    private void addSystemDefaultIcons(Builder builder, String packageName, String... previewIcons) {
+        try {
+            for (String iconName : previewIcons) {
+                builder.addIcon(loadIconPreviewDrawable(iconName, packageName, true));
+            }
+        } catch (NameNotFoundException | NotFoundException e) {
+            Log.w(TAG, "Didn't find android package icons, will skip preview", e);
+        }
+    }
+
+    private void addSystemDefaultShape(Builder builder) {
+        Resources system = Resources.getSystem();
+        String iconMaskPath = system.getString(system.getIdentifier(CONFIG_ICON_MASK,
+                "string", ANDROID_PACKAGE));
+        builder.setShapePath(iconMaskPath);
+    }
+
+    private void addSystemDefaultColor(Builder builder) {
+        Resources system = Resources.getSystem();
+        int colorAccentLight = system.getColor(
+                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_PACKAGE), null);
+        builder.setColorAccentDark(colorAccentDark);
+    }
+
+    private void addSystemDefaultFont(Builder builder) {
+        Resources system = Resources.getSystem();
+        String headlineFontFamily = system.getString(system.getIdentifier(
+                ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,"string", ANDROID_PACKAGE));
+        String bodyFontFamily = system.getString(system.getIdentifier(
+                ResourceConstants.CONFIG_BODY_FONT_FAMILY,
+                "string", ANDROID_PACKAGE));
+        builder.setHeadlineFontFamily(Typeface.create(headlineFontFamily, Typeface.NORMAL))
+                .setBodyFontFamily(Typeface.create(bodyFontFamily, Typeface.NORMAL));
+    }
+
     @Override
     public void storeCustomTheme(CustomTheme theme) {
         mCustomizationPreferences.storeCustomTheme(theme.getSerializedPackages());
@@ -501,12 +514,13 @@
         return overlayRes.getString(overlayRes.getIdentifier(stringName, "string", packageName));
     }
 
-    private Drawable loadIconPreviewDrawable(String drawableName, String packageName)
-         throws NameNotFoundException, NotFoundException {
+    private Drawable loadIconPreviewDrawable(String drawableName, String packageName,
+            boolean fromSystem) throws NameNotFoundException, NotFoundException {
 
-        Resources overlayRes = mContext.getPackageManager().getResourcesForApplication(packageName);
-        return overlayRes.getDrawable(
-                overlayRes.getIdentifier(drawableName, "drawable", packageName), null);
+        Resources packageRes = mContext.getPackageManager().getResourcesForApplication(packageName);
+        Resources res = fromSystem ? Resources.getSystem() : packageRes;
+        return res.getDrawable(
+                packageRes.getIdentifier(drawableName, "drawable", packageName), null);
     }
 
     @Nullable
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index 8e5061d..578b2cd 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -52,8 +52,11 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Represents a Theme component available in the system as a "persona" bundle.
@@ -148,16 +151,32 @@
         return mIsDefault;
     }
 
-    Collection<String> getAllPackages() {
-        return mPackagesByCategory.values();
+    public Map<String, String> getPackagesByCategory() {
+        return mPackagesByCategory;
     }
 
     public String getSerializedPackages() {
         if (isDefault()) {
             return "";
         }
+        JSONObject json = new JSONObject(mPackagesByCategory);
+        // Remove items with null values to avoid deserialization issues.
+        removeNullValues(json);
+        return json.toString();
+    }
 
-        return new JSONObject(mPackagesByCategory).toString();
+    private void removeNullValues(JSONObject json) {
+        Iterator<String> keys = json.keys();
+        Set<String> keysToRemove = new HashSet<>();
+        while(keys.hasNext()) {
+            String key = keys.next();
+            if (json.isNull(key)) {
+                keysToRemove.add(key);
+            }
+        }
+        for (String key : keysToRemove) {
+            json.remove(key);
+        }
     }
 
 
diff --git a/src/com/android/customization/model/theme/ThemeManager.java b/src/com/android/customization/model/theme/ThemeManager.java
index 83420df..313798f 100644
--- a/src/com/android/customization/model/theme/ThemeManager.java
+++ b/src/com/android/customization/model/theme/ThemeManager.java
@@ -29,6 +29,7 @@
 import android.graphics.Point;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.text.TextUtils;
 
 import androidx.annotation.Nullable;
 import androidx.fragment.app.FragmentActivity;
@@ -151,21 +152,26 @@
     private void applyOverlays(ThemeBundle theme, Callback callback) {
         boolean allApplied = true;
         if (theme.isDefault()) {
+            allApplied &= disableCurrentOverlay(ANDROID_PACKAGE, OVERLAY_CATEGORY_SHAPE);
             allApplied &= disableCurrentOverlay(ANDROID_PACKAGE, OVERLAY_CATEGORY_COLOR);
             allApplied &= disableCurrentOverlay(ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT);
-            allApplied &= disableCurrentOverlay(ANDROID_PACKAGE, OVERLAY_CATEGORY_SHAPE);
             allApplied &= disableCurrentOverlay(ANDROID_PACKAGE, OVERLAY_CATEGORY_ICON_ANDROID);
             allApplied &= disableCurrentOverlay(SYSUI_PACKAGE, OVERLAY_CATEGORY_ICON_SYSUI);
             allApplied &= disableCurrentOverlay(SETTINGS_PACKAGE, OVERLAY_CATEGORY_ICON_SETTINGS);
             allApplied &= disableCurrentOverlay(ResourceConstants.getLauncherPackage(mActivity),
                     OVERLAY_CATEGORY_ICON_LAUNCHER);
         } else {
-            for (String packageName : theme.getAllPackages()) {
-                if (packageName != null) {
-                    allApplied &= mOverlayManagerCompat.setEnabledExclusiveInCategory(packageName,
-                            UserHandle.myUserId());
-                }
-            }
+            allApplied &= applyOverlayOrDefault(theme, ANDROID_PACKAGE, OVERLAY_CATEGORY_SHAPE);
+            allApplied &= applyOverlayOrDefault(theme, ANDROID_PACKAGE, OVERLAY_CATEGORY_COLOR);
+            allApplied &= applyOverlayOrDefault(theme, ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT);
+            allApplied &= applyOverlayOrDefault(theme, ANDROID_PACKAGE,
+                    OVERLAY_CATEGORY_ICON_ANDROID);
+            allApplied &= applyOverlayOrDefault(theme, SYSUI_PACKAGE, OVERLAY_CATEGORY_ICON_SYSUI);
+            allApplied &= applyOverlayOrDefault(theme, SETTINGS_PACKAGE,
+                    OVERLAY_CATEGORY_ICON_SETTINGS);
+            allApplied &= applyOverlayOrDefault(theme,
+                    ResourceConstants.getLauncherPackage(mActivity),
+                    OVERLAY_CATEGORY_ICON_LAUNCHER);
         }
         allApplied &= Settings.Secure.putString(mActivity.getContentResolver(),
                 ResourceConstants.THEME_SETTING, theme.getSerializedPackages());
@@ -198,6 +204,16 @@
         return true;
     }
 
+    private boolean applyOverlayOrDefault(ThemeBundle theme, String targetPkg, String category) {
+        String themePackage = theme.getPackagesByCategory().get(category);
+        if (!TextUtils.isEmpty(themePackage)) {
+            return mOverlayManagerCompat.setEnabledExclusiveInCategory(themePackage,
+                    UserHandle.myUserId());
+        } else {
+            return disableCurrentOverlay(targetPkg, category);
+        }
+    }
+
     public Map<String, String> getCurrentOverlays() {
         if (mCurrentOverlays == null) {
             mCurrentOverlays = mOverlayManagerCompat.getEnabledOverlaysForTargets(
diff --git a/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java b/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
index 3603533..b9b35dc 100644
--- a/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
+++ b/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
@@ -23,7 +23,7 @@
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SYSUI;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SHAPE;
 import static com.android.customization.model.ResourceConstants.PATH_SIZE;
-import static com.android.customization.model.ResourceConstants.SYSUI_ICONS_FOR_PREVIEW;
+import static com.android.customization.model.ResourceConstants.ICONS_FOR_PREVIEW;
 import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
 import static com.android.customization.model.theme.custom.ThemeComponentOption.ColorOption.COLOR_TILES_ICON_IDS;
 
@@ -77,7 +77,7 @@
         if (TextUtils.isEmpty(iconPackage)) {
             iconPackage = SYSUI_PACKAGE;
         }
-        for (String iconName : SYSUI_ICONS_FOR_PREVIEW) {
+        for (String iconName : ICONS_FOR_PREVIEW) {
             try {
                 if (previewIcons.size() == COLOR_TILES_ICON_IDS.length) {
                     break;
diff --git a/src/com/android/customization/model/theme/custom/CustomTheme.java b/src/com/android/customization/model/theme/custom/CustomTheme.java
index aea6897..5ab6d39 100644
--- a/src/com/android/customization/model/theme/custom/CustomTheme.java
+++ b/src/com/android/customization/model/theme/custom/CustomTheme.java
@@ -58,10 +58,6 @@
         return getPreviewInfo() != null;
     }
 
-    Map<String, String> getPackagesByCategory() {
-        return mPackagesByCategory;
-    }
-
     public static class Builder extends ThemeBundle.Builder {
         @Override
         public CustomTheme build() {
diff --git a/src/com/android/customization/model/theme/custom/IconOptionsProvider.java b/src/com/android/customization/model/theme/custom/IconOptionsProvider.java
index 6850e90..2319387 100644
--- a/src/com/android/customization/model/theme/custom/IconOptionsProvider.java
+++ b/src/com/android/customization/model/theme/custom/IconOptionsProvider.java
@@ -16,13 +16,11 @@
 package com.android.customization.model.theme.custom;
 
 import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
-import static com.android.customization.model.ResourceConstants.ICON_PREVIEW_DRAWABLE_NAME;
+import static com.android.customization.model.ResourceConstants.ICONS_FOR_PREVIEW;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_LAUNCHER;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SETTINGS;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SYSUI;
-import static com.android.customization.model.ResourceConstants.SYSUI_ICONS_FOR_PREVIEW;
-import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
 
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -74,7 +72,9 @@
             IconOption option = addOrUpdateOption(optionsByPrefix, overlayPackage,
                     OVERLAY_CATEGORY_ICON_ANDROID);
             try{
-                option.addIcon(loadIconPreviewDrawable(ICON_PREVIEW_DRAWABLE_NAME, overlayPackage));
+                for (String iconName : ICONS_FOR_PREVIEW) {
+                    option.addIcon(loadIconPreviewDrawable(iconName, overlayPackage));
+                }
             } catch (NotFoundException | NameNotFoundException e) {
                 Log.w(TAG, String.format("Couldn't load icon overlay details for %s, will skip it",
                         overlayPackage), e);
@@ -82,16 +82,7 @@
         }
 
         for (String overlayPackage : mSysUiIconsOverlayPackages) {
-            IconOption option = addOrUpdateOption(optionsByPrefix, overlayPackage,
-                    OVERLAY_CATEGORY_ICON_SYSUI);
-            try{
-                for (String iconName : SYSUI_ICONS_FOR_PREVIEW) {
-                    option.addIcon(loadIconPreviewDrawable(iconName, overlayPackage));
-                }
-            } catch (NotFoundException | NameNotFoundException e) {
-                Log.w(TAG, String.format("Couldn't load icon overlay details for %s, will skip it",
-                        overlayPackage), e);
-            }
+            addOrUpdateOption(optionsByPrefix, overlayPackage,  OVERLAY_CATEGORY_ICON_SYSUI);
         }
 
         for (String overlayPackage : mSettingsIconsOverlayPackages) {
@@ -134,22 +125,16 @@
 
     private void addDefault() {
         Resources system = Resources.getSystem();
+        IconOption option = new IconOption();
+        option.setLabel(mContext.getString(R.string.default_theme_title));
         try {
-            IconOption option = new IconOption();
-            option.setLabel(mContext.getString(R.string.default_theme_title));
-
-            option.addIcon(system.getDrawable(system.getIdentifier(ICON_PREVIEW_DRAWABLE_NAME,
-                    "drawable", ANDROID_PACKAGE), null));
-
-            for (String iconName : SYSUI_ICONS_FOR_PREVIEW) {
-                option.addIcon(loadIconPreviewDrawable(iconName, SYSUI_PACKAGE));
+            for (String iconName : ICONS_FOR_PREVIEW) {
+                option.addIcon(loadIconPreviewDrawable(iconName, ANDROID_PACKAGE));
             }
-
-            mOptions.add(option);
         } catch (NameNotFoundException | NotFoundException e) {
             Log.w(TAG, "Didn't find SystemUi package icons, will skip option", e);
         }
-
+        mOptions.add(option);
     }
 
 }
diff --git a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
index f3cf7cc..e1e29cb 100644
--- a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
+++ b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
@@ -18,7 +18,6 @@
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SHAPE;
-import static com.android.customization.model.ResourceConstants.SYSUI_ICONS_FOR_PREVIEW;
 
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -183,7 +182,7 @@
                 LayoutInflater.from(container.getContext()).inflate(
                         R.layout.preview_card_icon_content, cardBody, true);
             }
-            for (int i = 0; i < mIconIds.length; i++) {
+            for (int i = 0; i < mIconIds.length && i < mIcons.size(); i++) {
                 ((ImageView) container.findViewById(mIconIds[i])).setImageDrawable(
                         mIcons.get(i));
             }
@@ -198,8 +197,7 @@
          */
         public boolean isValid(Context context) {
             return getOverlayPackages().keySet().size() ==
-                    ResourceConstants.getPackagesToOverlay(context).length
-                && mIcons.size() == SYSUI_ICONS_FOR_PREVIEW.length + 1;
+                    ResourceConstants.getPackagesToOverlay(context).length;
         }
 
         public void setLabel(String label) {
diff --git a/src/com/android/customization/picker/theme/ThemeFragment.java b/src/com/android/customization/picker/theme/ThemeFragment.java
index 246aa5e..d5f8abe 100644
--- a/src/com/android/customization/picker/theme/ThemeFragment.java
+++ b/src/com/android/customization/picker/theme/ThemeFragment.java
@@ -375,7 +375,7 @@
                         previewInfo.resolveAccentColor(res), editClickListener) {
                     @Override
                     protected void bindBody(boolean forceRebind) {
-                        for (int i = 0; i < mIconIds.length; i++) {
+                        for (int i = 0; i < mIconIds.length && i < previewInfo.icons.size(); i++) {
                             ((ImageView) card.findViewById(mIconIds[i])).setImageDrawable(
                                     previewInfo.icons.get(i));
                         }
@@ -416,7 +416,8 @@
                         // Disable seekbar
                         seekbar.setOnTouchListener((view, motionEvent) -> true);
 
-                        for (int i = 0; i < mColorTileIds.length; i++) {
+                        for (int i = 0; i < mColorTileIds.length && i < previewInfo.icons.size();
+                                i++) {
                             Drawable icon =
                                 previewInfo.icons.get(i).getConstantState().newDrawable();
                             Drawable bgShape =