Custom Theme 4/n: icon step screen

Implement the icon component provider and hook it up in the
Custom Theme Activity to have a 2 step custom theme.

Bug: 124796742
Change-Id: Ib63bef083d7366136e4a12f2e27c6d6fbd9bbb9c
diff --git a/res/layout/theme_icon_option.xml b/res/layout/theme_icon_option.xml
new file mode 100644
index 0000000..4872ffc
--- /dev/null
+++ b/res/layout/theme_icon_option.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="wrap_content"
+              android:layout_height="match_parent"
+              android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/option_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginBottom="@dimen/theme_option_label_margin"
+        android:textAppearance="@style/OptionTitleTextAppearance"/>
+    <FrameLayout
+        android:id="@+id/option_tile"
+        android:layout_width="@dimen/option_tile_width"
+        android:layout_height="@dimen/option_tile_width"
+        android:layout_gravity="center_horizontal"
+        android:paddingHorizontal="@dimen/option_tile_padding_horizontal"
+        android:paddingVertical="@dimen/option_tile_padding_vertical"
+        android:background="@drawable/option_border">
+        <ImageView
+            android:id="@+id/option_icon"
+            android:layout_width="@dimen/component_icon_thumb_size"
+            android:layout_height="@dimen/component_icon_thumb_size"
+            android:layout_gravity="center"/>
+    </FrameLayout>
+</LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 93a24d8..f80e59d 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -66,4 +66,6 @@
 
     <!-- Note, using dp instead of sp as this is just the font thumbnail, not text -->
     <dimen name="font_comonent_option_thumbnail_size">32dp</dimen>
+
+    <dimen name="component_icon_thumb_size">40dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0a981f9..78a8f1f 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -108,6 +108,13 @@
     <!-- Title of a page allowing the user to choose a font for a custom theme -->
     <string name="font_component_title">Choose font</string>
 
+    <!-- Title of a page allowing the user to choose an icon set for a custom theme -->
+    <string name="icon_component_title">Choose icons</string>
+
+    <!-- Title of a set of icons that the user can chose for their custom style (eg, "Icons 2") -->
+    <string name="icon_component_label">Icons <xliff:g name="component_number" example="1">%1$d</xliff:g></string>
+
+
     <string name="font_component_option_thumbnail" translatable="false">A</string>
 
     <!-- Text explaining what the current step is in setting a custom theme, eg: "1 of 4".
diff --git a/src/com/android/customization/model/ResourceConstants.java b/src/com/android/customization/model/ResourceConstants.java
index ad16881..f4c48c0 100644
--- a/src/com/android/customization/model/ResourceConstants.java
+++ b/src/com/android/customization/model/ResourceConstants.java
@@ -60,4 +60,12 @@
     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 = {
+            "ic_qs_bluetooth_on",
+            "ic_dnd",
+            "ic_signal_flashlight",
+            "ic_qs_auto_rotate",
+            "ic_signal_airplane"
+    };
 }
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index a841f87..4d3b90b 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -17,7 +17,9 @@
 
 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.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;
@@ -68,7 +70,6 @@
     private static final String ICON_LAUNCHER_PREFIX = "theme_overlay_icon_launcher_";
     private static final String ICON_SETTINGS_PREFIX = "theme_overlay_icon_settings_";
     private static final String ICON_SYSUI_PREFIX = "theme_overlay_icon_sysui_";
-    private static final String ICON_PREVIEW_DRAWABLE_NAME = "ic_wifi_signal_3";
     private static final String PREVIEW_COLOR_PREFIX = "theme_preview_color_";
     private static final String PREVIEW_SHAPE_PREFIX = "theme_preview_shape_";
     private static final String WALLPAPER_PREFIX = "theme_wallpaper_";
@@ -80,13 +81,6 @@
 
     private static final String ACCENT_COLOR_LIGHT_NAME = "accent_device_default_light";
     private static final String ACCENT_COLOR_DARK_NAME = "accent_device_default_dark";
-    private static final String[] SYSUI_ICONS_FOR_PREVIEW = {
-            "ic_qs_bluetooth_on",
-            "ic_dnd",
-            "ic_signal_flashlight",
-            "ic_qs_auto_rotate",
-            "ic_signal_airplane"
-    };
 
     private List<ThemeBundle> mThemes;
     private Map<String, OverlayInfo> mOverlayInfos;
@@ -177,11 +171,13 @@
                 if (!TextUtils.isEmpty(iconAndroidOverlayPackage)) {
                     builder.addOverlayPackage(getOverlayCategory(iconAndroidOverlayPackage),
                                 iconAndroidOverlayPackage)
-                            .addIcon(loadIconPreviewDrawable(ICON_PREVIEW_DRAWABLE_NAME,
+                            .addIcon(loadIconPreviewDrawable(
+                                    ICON_PREVIEW_DRAWABLE_NAME,
                                     iconAndroidOverlayPackage));
                 } else {
                     builder.addIcon(mContext.getResources().getDrawable(
-                            Resources.getSystem().getIdentifier(ICON_PREVIEW_DRAWABLE_NAME,
+                            Resources.getSystem().getIdentifier(
+                                    ICON_PREVIEW_DRAWABLE_NAME,
                                     "drawable", ANDROID_PACKAGE), null));
                 }
 
@@ -327,7 +323,8 @@
         } 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,
+            builder.addIcon(system.getDrawable(system.getIdentifier(
+                    ICON_PREVIEW_DRAWABLE_NAME,
                             "drawable", ANDROID_PACKAGE), null));
         }
 
diff --git a/src/com/android/customization/model/theme/custom/IconOptionsProvider.java b/src/com/android/customization/model/theme/custom/IconOptionsProvider.java
new file mode 100644
index 0000000..6c85fc8
--- /dev/null
+++ b/src/com/android/customization/model/theme/custom/IconOptionsProvider.java
@@ -0,0 +1,146 @@
+/*
+ * 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.android.customization.model.theme.custom;
+
+import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
+import static com.android.customization.model.ResourceConstants.DEFAULT_TARGET_PACKAGES;
+import static com.android.customization.model.ResourceConstants.ICON_PREVIEW_DRAWABLE_NAME;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
+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;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.customization.model.theme.OverlayManagerCompat;
+import com.android.customization.model.theme.custom.ThemeComponentOption.IconOption;
+import com.android.wallpaper.R;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of {@link ThemeComponentOptionProvider} that reads {@link IconOption}s from
+ * icon overlays.
+ */
+public class IconOptionsProvider extends ThemeComponentOptionProvider<IconOption> {
+
+    private static final String TAG = "IconOptionsProvider";
+
+    private final List<String> mSysUiIconsOverlayPackages = new ArrayList<>();
+    private final List<String> mSettingsIconsOverlayPackages = new ArrayList<>();
+
+    public IconOptionsProvider(Context context, OverlayManagerCompat manager) {
+        super(context, manager, OVERLAY_CATEGORY_ICON_ANDROID);
+        mSysUiIconsOverlayPackages.addAll(manager.getOverlayPackagesForCategory(
+                OVERLAY_CATEGORY_ICON_SYSUI, UserHandle.myUserId(), DEFAULT_TARGET_PACKAGES));
+        mSettingsIconsOverlayPackages.addAll(manager.getOverlayPackagesForCategory(
+                OVERLAY_CATEGORY_ICON_SETTINGS, UserHandle.myUserId(), DEFAULT_TARGET_PACKAGES));
+    }
+
+    @Override
+    protected void loadOptions() {
+        addDefault();
+
+        Map<String, IconOption> optionsByPrefix = new HashMap<>();
+        for (String overlayPackage : mOverlayPackages) {
+            IconOption option = addOrUpdateOption(optionsByPrefix, overlayPackage,
+                    OVERLAY_CATEGORY_ICON_ANDROID);
+            try{
+                option.addIcon(loadIconPreviewDrawable(ICON_PREVIEW_DRAWABLE_NAME, overlayPackage));
+            } catch (NotFoundException | NameNotFoundException e) {
+                Log.w(TAG, String.format("Couldn't load icon overlay details for %s, will skip it",
+                        overlayPackage), e);
+            }
+        }
+
+        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);
+            }
+        }
+
+        for (String overlayPackage : mSettingsIconsOverlayPackages) {
+            addOrUpdateOption(optionsByPrefix, overlayPackage, OVERLAY_CATEGORY_ICON_SETTINGS);
+        }
+
+        for (IconOption option : optionsByPrefix.values()) {
+            if (option.isValid()) {
+                mOptions.add(option);
+                option.setLabel(mContext.getString(R.string.icon_component_label, mOptions.size()));
+            }
+        }
+    }
+
+    private IconOption addOrUpdateOption(Map<String, IconOption> optionsByPrefix,
+            String overlayPackage, String category) {
+        String prefix = overlayPackage.substring(0, overlayPackage.lastIndexOf("."));
+        IconOption option;
+        if (!optionsByPrefix.containsKey(prefix)) {
+            option = new IconOption();
+            optionsByPrefix.put(prefix, option);
+        } else {
+            option = optionsByPrefix.get(prefix);
+        }
+        option.addOverlayPackage(category, overlayPackage);
+        return option;
+    }
+
+    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);
+    }
+
+    private void addDefault() {
+        Resources system = Resources.getSystem();
+        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));
+            }
+
+            mOptions.add(option);
+        } catch (NameNotFoundException | NotFoundException e) {
+            Log.w(TAG, "Didn't find SystemUi package icons, will skip option", e);
+        }
+
+    }
+
+}
diff --git a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
index 53c9d37..f973ac5 100644
--- a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
+++ b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
@@ -15,16 +15,30 @@
  */
 package com.android.customization.model.theme.custom;
 
+import static com.android.customization.model.ResourceConstants.DEFAULT_TARGET_PACKAGES;
+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.res.Resources;
 import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.android.customization.model.CustomizationManager;
 import com.android.customization.model.CustomizationOption;
 import com.android.wallpaper.R;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Represents an option of a component of a custom Theme (for example, a possible color, or font,
  * shape, etc).
@@ -33,14 +47,14 @@
  */
 public abstract class ThemeComponentOption implements CustomizationOption<ThemeComponentOption> {
 
-    protected final String mOverlayPackageName;
+    protected final Map<String, String> mOverlayPackageNames = new HashMap<>();
 
-    ThemeComponentOption(String packageName) {
-        mOverlayPackageName = packageName;
+    protected void addOverlayPackage(String category, String packageName) {
+        mOverlayPackageNames.put(category, packageName);
     }
 
-    public String getOverlayPackageName() {
-        return mOverlayPackageName;
+    public Map<String, String> getOverlayPackageNames() {
+        return mOverlayPackageNames;
     }
 
     @Override
@@ -58,7 +72,7 @@
 
         public FontOption(String packageName, String label, Typeface headlineFont,
                 Typeface bodyFont) {
-            super(packageName);
+            addOverlayPackage(OVERLAY_CATEGORY_FONT, packageName);
             mLabel = label;
             mHeadlineFont = headlineFont;
             mBodyFont = bodyFont;
@@ -106,13 +120,22 @@
 
     public static class IconOption extends ThemeComponentOption {
 
-        IconOption(String packageName) {
-            super(packageName);
-        }
+        public static final int THUMBNAIL_ICON_POSITION = 0;
+        private static int[] mIconIds = {
+                R.id.preview_icon_0, R.id.preview_icon_1, R.id.preview_icon_2, R.id.preview_icon_3,
+                R.id.preview_icon_4, R.id.preview_icon_5
+        };
+
+        private List<Drawable> mIcons = new ArrayList<>();
+        private String mLabel;
 
         @Override
         public void bindThumbnailTile(View view) {
-
+            Resources res = view.getContext().getResources();
+            Drawable icon = mIcons.get(THUMBNAIL_ICON_POSITION).mutate();
+            icon.setTint(res.getColor(R.color.icon_thumbnail_color, null));
+            ((ImageView) view.findViewById(R.id.option_icon)).setImageDrawable(
+                    icon);
         }
 
         @Override
@@ -122,19 +145,44 @@
 
         @Override
         public int getLayoutResId() {
-            return 0;
+            return R.layout.theme_icon_option;
         }
 
         @Override
         public void bindPreview(ViewGroup container) {
+            TextView header = container.findViewById(R.id.theme_preview_card_header);
+            header.setText(mLabel);
+            header.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_wifi_24px, 0, 0);
 
+            ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
+            if (cardBody.getChildCount() == 0) {
+                LayoutInflater.from(container.getContext()).inflate(
+                        R.layout.preview_card_icon_content, cardBody, true);
+            }
+            for (int i = 0; i < mIconIds.length; i++) {
+                ((ImageView) container.findViewById(mIconIds[i])).setImageDrawable(
+                        mIcons.get(i));
+            }
+        }
+
+        public void addIcon(Drawable previewIcon) {
+            mIcons.add(previewIcon);
+        }
+
+        public boolean isValid() {
+            return getOverlayPackageNames().keySet().size() == DEFAULT_TARGET_PACKAGES.length
+                && mIcons.size() == SYSUI_ICONS_FOR_PREVIEW.length + 1;
+        }
+
+        public void setLabel(String label) {
+            mLabel = label;
         }
     }
 
     public static class ColorOption extends ThemeComponentOption {
 
         ColorOption(String packageName) {
-            super(packageName);
+            addOverlayPackage(OVERLAY_CATEGORY_COLOR, packageName);
         }
 
         @Override
@@ -161,7 +209,7 @@
     public static class ShapeOption extends ThemeComponentOption {
 
         ShapeOption(String packageName) {
-            super(packageName);
+            addOverlayPackage(OVERLAY_CATEGORY_SHAPE, packageName);
         }
 
         @Override
diff --git a/src/com/android/customization/picker/theme/CustomThemeActivity.java b/src/com/android/customization/picker/theme/CustomThemeActivity.java
index 0d97715..1b668d9 100644
--- a/src/com/android/customization/picker/theme/CustomThemeActivity.java
+++ b/src/com/android/customization/picker/theme/CustomThemeActivity.java
@@ -16,6 +16,7 @@
 package com.android.customization.picker.theme;
 
 import android.os.Bundle;
+import android.widget.TextView;
 
 import androidx.annotation.StringRes;
 import androidx.fragment.app.Fragment;
@@ -26,8 +27,10 @@
 import com.android.customization.model.theme.OverlayManagerCompat;
 import com.android.customization.model.theme.custom.CustomThemeManager;
 import com.android.customization.model.theme.custom.FontOptionsProvider;
+import com.android.customization.model.theme.custom.IconOptionsProvider;
 import com.android.customization.model.theme.custom.ThemeComponentOption;
 import com.android.customization.model.theme.custom.ThemeComponentOption.FontOption;
+import com.android.customization.model.theme.custom.ThemeComponentOption.IconOption;
 import com.android.customization.model.theme.custom.ThemeComponentOptionProvider;
 import com.android.customization.picker.theme.CustomThemeComponentFragment.CustomThemeComponentFragmentHost;
 import com.android.wallpaper.R;
@@ -43,6 +46,8 @@
 
     private UserEventLogger mUserEventLogger;
     private List<ComponentStep<?>> mSteps;
+    private int mCurrentStep;
+    private TextView mApplyButton;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -50,11 +55,12 @@
         Injector injector = InjectorProvider.getInjector();
         mUserEventLogger = injector.getUserEventLogger(this);
         setContentView(R.layout.activity_custom_theme);
+        mApplyButton = findViewById(R.id.next_button);
+        mApplyButton.setOnClickListener(view -> onNextOrApply());
         initSteps();
 
         FragmentManager fm = getSupportFragmentManager();
         Fragment fragment = fm.findFragmentById(R.id.fragment_container);
-
         if (fragment == null) {
             // Navigate to the first step
             navigateToStep(0);
@@ -62,21 +68,47 @@
     }
 
     private void navigateToStep(int i) {
-        final FragmentManager fragmentManager = getSupportFragmentManager();
+        FragmentManager fragmentManager = getSupportFragmentManager();
         ComponentStep step = mSteps.get(i);
         Fragment fragment = step.getFragment();
 
-        final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
         fragmentTransaction.replace(R.id.fragment_container, fragment);
-        fragmentTransaction.commitNow();
+        // Don't add step 0 to the back stack so that going back from it just finishes the Activity
+        if (i > 0) {
+            fragmentTransaction.addToBackStack("Step " + i);
+        }
+        fragmentTransaction.commit();
+        fragmentManager.executePendingTransactions();
+        updateApplyButtonLabel();
     }
 
     private void initSteps() {
         mSteps = new ArrayList<>();
         OverlayManagerCompat manager = new OverlayManagerCompat(this);
-        mSteps.add(new FontStep(new FontOptionsProvider(this, manager), 0, mSteps.size() + 1));
+        mSteps.add(new FontStep(new FontOptionsProvider(this, manager), 0, 2));
+        mSteps.add(new IconStep(new IconOptionsProvider(this, manager), 1, 2));
+        mCurrentStep = 0;
     }
 
+    private void onNextOrApply() {
+        if (mCurrentStep < mSteps.size() - 1) {
+            // TODO: gather current step's selection
+            navigateToStep(mCurrentStep + 1);
+        }
+        // TODO: handle Apply
+    }
+
+    @Override
+    public void setCurrentStep(int i) {
+        mCurrentStep = i;
+        updateApplyButtonLabel();
+    }
+
+    private void updateApplyButtonLabel() {
+        mApplyButton.setText((mCurrentStep < mSteps.size() -1) ? R.string.custom_theme_next
+                : R.string.apply_btn);
+    }
 
     @Override
     public void delete() {
@@ -148,4 +180,21 @@
                     titleResId);
         }
     }
+
+    private class IconStep extends ComponentStep<IconOption> {
+
+        protected IconStep(ThemeComponentOptionProvider<IconOption> provider,
+                int position, int totalSteps) {
+            super(R.string.icon_component_title, provider, position, totalSteps);
+        }
+
+        @Override
+        CustomThemeComponentFragment createFragment() {
+            return CustomThemeComponentFragment.newInstance(
+                    CustomThemeActivity.this.getString(R.string.custom_theme_fragment_title),
+                    position,
+                    totalSteps,
+                    titleResId);
+        }
+    }
 }
diff --git a/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java b/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
index 5c74ca3..d2dcd61 100644
--- a/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
+++ b/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
@@ -39,6 +39,7 @@
     private static final String ARG_KEY_POSITION = "CustomThemeComponentFragment.position";
     private static final String ARG_KEY_TOTAL_STEPS = "CustomThemeComponentFragment.steps";
     private static final String ARG_KEY_TITLE_RES_ID = "CustomThemeComponentFragment.title_res";
+    private CustomThemeComponentFragmentHost mHost;
 
     public interface CustomThemeComponentFragmentHost {
         void delete();
@@ -47,6 +48,8 @@
                 int position);
 
         CustomThemeManager getCustomThemeManager();
+
+        void setCurrentStep(int step);
     }
 
     public static CustomThemeComponentFragment newInstance(CharSequence toolbarTitle, int position,
@@ -78,14 +81,14 @@
         mPosition = getArguments().getInt(ARG_KEY_POSITION);
         mTotalSteps = getArguments().getInt(ARG_KEY_TOTAL_STEPS);
         mTitleResId = getArguments().getInt(ARG_KEY_TITLE_RES_ID);
+        mProvider = mHost.getComponentOptionProvider(mPosition);
+        mCustomThemeManager = mHost.getCustomThemeManager();
     }
 
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        CustomThemeComponentFragmentHost host = (CustomThemeComponentFragmentHost) context;
-        mProvider = host.getComponentOptionProvider(mPosition);
-        mCustomThemeManager = host.getCustomThemeManager();
+        mHost = (CustomThemeComponentFragmentHost) context;
     }
 
     @Nullable
@@ -107,6 +110,12 @@
         return view;
     }
 
+    @Override
+    public void onResume() {
+        super.onResume();
+        mHost.setCurrentStep(mPosition);
+    }
+
     private void bindPreview() {
         mSelectedOption.bindPreview(mPreviewCard);
     }