Merging from ub-launcher3-master @ build 6632592

Bug:154410862
Test: manual, presubmit on the source branch
x20/teams/android-launcher/merge/ub-launcher3-master_rvc-d1-dev_6632592.html

Change-Id: Ibd958ce06b510beb44efed5daf36e814d366e565
diff --git a/res/layout/fragment_custom_theme_component.xml b/res/layout/fragment_custom_theme_component.xml
index fb3e5b3..26feab8 100644
--- a/res/layout/fragment_custom_theme_component.xml
+++ b/res/layout/fragment_custom_theme_component.xml
@@ -58,32 +58,39 @@
             android:background="@color/divider_color"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/component_preview_container"/>
-        
-        <TextView
-            android:id="@+id/component_options_title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginVertical="18dp"
-            android:layout_marginHorizontal="16dp"
-            android:textAlignment="center"
-            android:textAppearance="@style/TitleTextAppearance"
-            android:textSize="@dimen/component_options_title_size"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/component_preview_container"
-            app:layout_constraintBottom_toTopOf="@+id/options_container"/>
+            app:layout_constraintBottom_toTopOf="@+id/component_scroll_view"/>
 
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/options_container"
+        <ScrollView
+            android:id="@+id/component_scroll_view"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_gravity="center_horizontal"
-            app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/component_options_title"
-            app:layout_constraintVertical_bias="1"/>
+            app:layout_constraintTop_toBottomOf="@+id/divider"
+            app:layout_constraintBottom_toBottomOf="parent">
 
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+        
+                <TextView
+                    android:id="@+id/component_options_title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginVertical="18dp"
+                    android:layout_marginHorizontal="16dp"
+                    android:textAlignment="center"
+                    android:textAppearance="@style/TitleTextAppearance"
+                    android:textSize="@dimen/component_options_title_size" />
+
+                <androidx.recyclerview.widget.RecyclerView
+                    android:id="@+id/options_container"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_horizontal"/>
+            </LinearLayout>
+        </ScrollView>
     </androidx.constraintlayout.widget.ConstraintLayout>
 </LinearLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index d5291c0..02b3472 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -31,14 +31,9 @@
     <color name="clockface_preview_background">@android:color/black</color>
 
     <color name="theme_preview_icon_color">@color/google_grey700</color>
-    <color name="theme_preview_workspace_shadow_color_dark">#B0000000</color>
-    <color name="theme_preview_workspace_shadow_color_transparent">@android:color/transparent</color>
     <color name="theme_preview_color_icons_background">@color/material_white_100</color>
     <color name="theme_preview_color_icons_title_color">@color/black_87_alpha</color>
 
-    <color name="text_color_dark">#2d2d2d</color>
-    <color name="text_color_light">@color/material_white_text</color>
-
     <color name="control_grey">#757575</color>
     <color name="switch_track_tint">#acacac</color>
     <color name="switch_thumb_tint">#f1f1f1</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1c6242e..280c187 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -86,7 +86,6 @@
     <dimen name="preview_theme_color_icons_title_text_size">12sp</dimen>
     <dimen name="preview_theme_color_icons_icon_size">@dimen/preview_theme_icon_size</dimen>
     <dimen name="preview_theme_color_icons_tile_size">@dimen/preview_theme_tile_size</dimen>
-    <dimen name="preview_theme_smartspace_key_ambient_shadow_blur">1.5dp</dimen>
     <dimen name="preview_theme_app_name_key_ambient_shadow_blur">2.5dp</dimen>
 
     <!--  For the customization previews on the picker. -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 569600e..b4ec835 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -121,7 +121,7 @@
         [CHAR LIMIT=20] -->
     <string name="custom_theme_previous">Previous</string>
 
-    <!-- Title for "Custom theme" option. [CHAR LIMIT=15] -->
+    <!-- Title for "Custom theme" option. [CHAR LIMIT=20] -->
     <string name="custom_theme">Custom</string>
 
     <!-- Generic label for one system Style/Theme (combination of fonts/colors/icons) that is
@@ -198,7 +198,7 @@
     <!-- Title for a section of a style preview screen that shows a preview of the style color and icons. [CHAR_LIMIT=30]-->
     <string name="theme_preview_icons_section_title">Color / Icons</string>
 
-    <!-- Bottom sheet dialog which displaying different theme's info. [CHAR_LIMIT=30]
+    <!-- Bottom sheet dialog which displaying different theme's info. [CHAR_LIMIT=80]
     (eg, Fonts, icons, shape, color will change to the "Default" Style) -->
     <string name="style_info_description">Fonts, icons, shape, color will change to the <xliff:g name="style_name">%1$s</xliff:g> Style</string>
 </resources>
diff --git a/src/com/android/customization/model/grid/GridOptionsManager.java b/src/com/android/customization/model/grid/GridOptionsManager.java
index a0ae04c..cf55147 100644
--- a/src/com/android/customization/model/grid/GridOptionsManager.java
+++ b/src/com/android/customization/model/grid/GridOptionsManager.java
@@ -17,7 +17,6 @@
 
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.util.Pair;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -66,7 +65,7 @@
         return mProvider.renderPreview(gridName, bundle);
     }
 
-    private static class FetchTask extends AsyncTask<Void, Void, Pair<List<GridOption>, String>> {
+    private static class FetchTask extends AsyncTask<Void, Void, List<GridOption>> {
         private final LauncherGridOptionsProvider mProvider;
         @Nullable private final OptionsFetchedListener<GridOption> mCallback;
         private final boolean mReload;
@@ -79,16 +78,15 @@
         }
 
         @Override
-        protected Pair<List<GridOption>, String> doInBackground(Void[] params) {
+        protected List<GridOption> doInBackground(Void[] params) {
             return mProvider.fetch(mReload);
         }
 
         @Override
-        protected void onPostExecute(Pair<List<GridOption>, String> gridOptionsResult) {
+        protected void onPostExecute(List<GridOption> gridOptions) {
             if (mCallback != null) {
-                if (gridOptionsResult != null && gridOptionsResult.first != null
-                        && !gridOptionsResult.first.isEmpty()) {
-                    mCallback.onOptionsLoaded(gridOptionsResult.first);
+                if (gridOptions != null && !gridOptions.isEmpty()) {
+                    mCallback.onOptionsLoaded(gridOptions);
                 } else {
                     mCallback.onError(null);
                 }
diff --git a/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java b/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java
index 175f71a..cdab1a6 100644
--- a/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java
+++ b/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java
@@ -21,7 +21,6 @@
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.os.Bundle;
-import android.util.Pair;
 import android.view.SurfaceView;
 
 import androidx.annotation.Nullable;
@@ -59,7 +58,6 @@
     private final Context mContext;
     private final PreviewUtils mPreviewUtils;
     private List<GridOption> mOptions;
-    private String mVersion;
 
     public LauncherGridOptionsProvider(Context context, String authorityMetadataKey) {
         mPreviewUtils = new PreviewUtils(context, authorityMetadataKey);
@@ -76,19 +74,18 @@
      */
     @WorkerThread
     @Nullable
-    Pair<List<GridOption>, String> fetch(boolean reload) {
+    List<GridOption> fetch(boolean reload) {
         if (!areGridsAvailable()) {
             return null;
         }
         if (mOptions != null && !reload) {
-            return Pair.create(mOptions, mVersion);
+            return mOptions;
         }
         ContentResolver resolver = mContext.getContentResolver();
         String iconPath = mContext.getResources().getString(Resources.getSystem().getIdentifier(
                 ResourceConstants.CONFIG_ICON_MASK, "string", ResourceConstants.ANDROID_PACKAGE));
         try (Cursor c = resolver.query(mPreviewUtils.getUri(LIST_OPTIONS), null, null, null,
                 null)) {
-            mVersion = c.getExtras().getString(METADATA_KEY_PREVIEW_VERSION);
             mOptions = new ArrayList<>();
             while(c.moveToNext()) {
                 String name = c.getString(c.getColumnIndex(COL_NAME));
@@ -105,9 +102,8 @@
             Glide.get(mContext).clearDiskCache();
         } catch (Exception e) {
             mOptions = null;
-            mVersion = null;
         }
-        return Pair.create(mOptions, mVersion);
+        return mOptions;
     }
 
     /**
diff --git a/src/com/android/customization/picker/CustomizationPickerActivity.java b/src/com/android/customization/picker/CustomizationPickerActivity.java
index 2ee114b..240f879 100644
--- a/src/com/android/customization/picker/CustomizationPickerActivity.java
+++ b/src/com/android/customization/picker/CustomizationPickerActivity.java
@@ -126,10 +126,19 @@
 
         setContentView(R.layout.activity_customization_picker_main);
         setUpBottomNavView();
+        mBottomActionBar = findViewById(R.id.bottom_actionbar);
+        mBottomActionBar.addVisibilityChangeListener(
+                isBottomActionBarVisible -> {
+                    boolean isBottomNavVisible = mBottomNav.getVisibility() == View.VISIBLE;
+                    // Switch the visibility of BottomNav if visibility of BottomActionBar and
+                    // BottomNav are same.
+                    if (isBottomActionBarVisible == isBottomNavVisible) {
+                        mBottomNav.setVisibility(isBottomActionBarVisible
+                                ? View.GONE : View.VISIBLE);
+                    }
+                });
 
-        FragmentManager fm = getSupportFragmentManager();
-        Fragment fragment = fm.findFragmentById(R.id.fragment_container);
-
+        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
         if (fragment == null) {
             // App launch specific logic: log the "app launched" event and set up daily logging.
             mUserEventLogger.logAppLaunched();
@@ -143,10 +152,6 @@
                     WALLPAPER_FOCUS.equals(getIntent().getStringExtra(WALLPAPER_FLAVOR_EXTRA))
                             ? R.id.nav_wallpaper : R.id.nav_theme);
         }
-
-        mBottomActionBar = findViewById(R.id.bottom_actionbar);
-        mBottomActionBar.addVisibilityChangeListener(
-                isVisible -> mBottomNav.setVisibility(isVisible ? View.GONE : View.VISIBLE));
     }
 
     @Override
@@ -362,6 +367,11 @@
     }
 
     @Override
+    public boolean isNavigationTabsContained() {
+        return true;
+    }
+
+    @Override
     public void onWallpapersReady() {
 
     }
diff --git a/src/com/android/customization/picker/WallpaperPreviewer.java b/src/com/android/customization/picker/WallpaperPreviewer.java
index 34688c5..ba750c9 100644
--- a/src/com/android/customization/picker/WallpaperPreviewer.java
+++ b/src/com/android/customization/picker/WallpaperPreviewer.java
@@ -19,6 +19,7 @@
 import static android.view.View.MeasureSpec.makeMeasureSpec;
 
 import android.app.Activity;
+import android.app.WallpaperColors;
 import android.content.Intent;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -27,10 +28,12 @@
 import android.view.SurfaceControlViewHost;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
+import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 
 import androidx.annotation.MainThread;
+import androidx.annotation.Nullable;
 import androidx.cardview.widget.CardView;
 import androidx.core.content.ContextCompat;
 import androidx.lifecycle.Lifecycle;
@@ -43,7 +46,9 @@
 import com.android.wallpaper.util.ScreenSizeCalculator;
 import com.android.wallpaper.util.SizeCalculator;
 import com.android.wallpaper.util.WallpaperConnection;
+import com.android.wallpaper.util.WallpaperConnection.WallpaperConnectionListener;
 import com.android.wallpaper.widget.LiveTileOverlay;
+import com.android.wallpaper.widget.WallpaperColorsLoader;
 
 /** A class to load the wallpaper to the view. */
 public class WallpaperPreviewer implements LifecycleObserver {
@@ -63,6 +68,13 @@
     // Home workspace surface is behind the app window, and so must the home image wallpaper like
     // the live wallpaper. This view is rendered on mWallpaperSurface for home image wallpaper.
     private ImageView mHomeImageWallpaper;
+    @Nullable private WallpaperColorsListener mWallpaperColorsListener;
+
+    /** Interface for getting {@link WallpaperColors} from wallpaper. */
+    public interface WallpaperColorsListener {
+        /** Gets called when wallpaper color is available or updated. */
+        void onWallpaperColorsChanged(WallpaperColors colors);
+    }
 
     public WallpaperPreviewer(Lifecycle lifecycle, Activity activity, ImageView homePreview,
                               SurfaceView wallpaperSurface) {
@@ -73,6 +85,16 @@
         mWallpaperSurface = wallpaperSurface;
         mWallpaperSurface.setZOrderMediaOverlay(false);
         mWallpaperSurface.getHolder().addCallback(mWallpaperSurfaceCallback);
+
+        View rootView = homePreview.getRootView();
+        rootView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                                       int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                updatePreviewCardRadius();
+                rootView.removeOnLayoutChangeListener(this);
+            }
+        });
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@@ -117,21 +139,16 @@
         }
     }
 
-    /** Updates the preview card view radius to match the device radius. */
-    public void updatePreviewCardRadius() {
-        final float screenAspectRatio =
-                ScreenSizeCalculator.getInstance().getScreenAspectRatio(mActivity);
-        CardView cardView = (CardView) mHomePreview.getParent();
-        final int cardWidth = (int) (cardView.getMeasuredHeight() / screenAspectRatio);
-        ViewGroup.LayoutParams layoutParams = cardView.getLayoutParams();
-        layoutParams.width = cardWidth;
-        cardView.setLayoutParams(layoutParams);
-        cardView.setRadius(SizeCalculator.getPreviewCornerRadius(mActivity, cardWidth));
-    }
-
-    /** Loads the wallpaper. */
-    public void setWallpaper(WallpaperInfo wallpaperInfo) {
-        mWallpaper =  wallpaperInfo;
+    /**
+     * Sets a wallpaper to be shown on preview screen.
+     *
+     * @param wallpaperInfo the wallpaper to preview
+     * @param listener the listener for getting the wallpaper color of {@param wallpaperInfo}
+     */
+    public void setWallpaper(WallpaperInfo wallpaperInfo,
+                             @Nullable WallpaperColorsListener listener) {
+        mWallpaper = wallpaperInfo;
+        mWallpaperColorsListener = listener;
         setUpWallpaperPreview();
     }
 
@@ -151,10 +168,19 @@
                                 mActivity.getColor(R.color.secondary_color));
                 setUpLiveWallpaperPreview(mWallpaper);
             } else {
+                // Ensure live wallpaper connection is disconnected.
                 if (mWallpaperConnection != null) {
                     mWallpaperConnection.disconnect();
                     mWallpaperConnection = null;
                 }
+
+                // Load wallpaper color for static wallpaper.
+                if (mWallpaperColorsListener != null) {
+                    WallpaperColorsLoader.getWallpaperColors(
+                            mActivity,
+                            mWallpaper.getThumbAsset(mActivity),
+                            mWallpaperColorsListener::onWallpaperColorsChanged);
+                }
             }
         }
     }
@@ -176,7 +202,14 @@
 
         mWallpaperConnection = new WallpaperConnection(
                 getWallpaperIntent(homeWallpaper.getWallpaperComponent()), mActivity,
-                /* listener= */ null, mPreviewGlobalRect);
+                new WallpaperConnectionListener() {
+                    @Override
+                    public void onWallpaperColorsChanged(WallpaperColors colors, int displayId) {
+                        if (mWallpaperColorsListener != null) {
+                            mWallpaperColorsListener.onWallpaperColorsChanged(colors);
+                        }
+                    }
+                }, mPreviewGlobalRect);
 
         LiveTileOverlay.INSTANCE.update(new RectF(mPreviewLocalRect),
                 ((CardView) mHomePreview.getParent()).getRadius());
@@ -190,6 +223,23 @@
         });
     }
 
+    /** Updates the preview card view corner radius to match the device corner radius. */
+    private void updatePreviewCardRadius() {
+        final float screenAspectRatio =
+                ScreenSizeCalculator.getInstance().getScreenAspectRatio(mActivity);
+        CardView cardView = (CardView) mHomePreview.getParent();
+        final int cardWidth = (int) (cardView.getMeasuredHeight() / screenAspectRatio);
+        ViewGroup.LayoutParams layoutParams = cardView.getLayoutParams();
+        layoutParams.width = cardWidth;
+        cardView.setLayoutParams(layoutParams);
+        cardView.setRadius(SizeCalculator.getPreviewCornerRadius(mActivity, cardWidth));
+    }
+
+    private static Intent getWallpaperIntent(android.app.WallpaperInfo info) {
+        return new Intent(WallpaperService.SERVICE_INTERFACE)
+                .setClassName(info.getPackageName(), info.getServiceName());
+    }
+
     private class WallpaperSurfaceCallback implements SurfaceHolder.Callback {
 
         private Surface mLastSurface;
@@ -228,10 +278,5 @@
                 mHost = null;
             }
         }
-    };
-
-    private static Intent getWallpaperIntent(android.app.WallpaperInfo info) {
-        return new Intent(WallpaperService.SERVICE_INTERFACE)
-                .setClassName(info.getPackageName(), info.getServiceName());
     }
 }
diff --git a/src/com/android/customization/picker/grid/GridFragment.java b/src/com/android/customization/picker/grid/GridFragment.java
index b6a749e..ad37fbf 100644
--- a/src/com/android/customization/picker/grid/GridFragment.java
+++ b/src/com/android/customization/picker/grid/GridFragment.java
@@ -39,6 +39,7 @@
 
 import com.android.customization.model.CustomizationManager.Callback;
 import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
+import com.android.customization.model.CustomizationOption;
 import com.android.customization.model.grid.GridOption;
 import com.android.customization.model.grid.GridOptionsManager;
 import com.android.customization.module.ThemesUserEventLogger;
@@ -63,8 +64,8 @@
 
     private static final int FULL_PREVIEW_REQUEST_CODE = 1000;
     private static final String KEY_STATE_SELECTED_OPTION = "GridFragment.selectedOption";
-    private static final String KEY_STATE_BOTTOM_ACTION_BAR_VISIBILITY =
-            "GridFragment.bottomActionBarVisibility";
+    private static final String KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE =
+            "GridFragment.bottomActionBarVisible";
 
     private static final String TAG = "GridFragment";
 
@@ -143,21 +144,12 @@
                 .getCurrentWallpaperFactory(getContext().getApplicationContext());
         factory.createCurrentWallpaperInfos((homeWallpaper, lockWallpaper, presentationMode) -> {
             mHomeWallpaper = homeWallpaper;
-            wallpaperPreviewer.setWallpaper(mHomeWallpaper);
+            wallpaperPreviewer.setWallpaper(mHomeWallpaper, /* listener= */ null);
         }, false);
 
         mGridOptionPreviewer = new GridOptionPreviewer(mGridManager,
                 view.findViewById(R.id.grid_preview_container));
 
-        view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                                       int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                wallpaperPreviewer.updatePreviewCardRadius();
-                view.removeOnLayoutChangeListener(this);
-            }
-        });
-
         view.findViewById(R.id.grid_preview_card).setOnClickListener(v -> showFullPreview());
         return view;
     }
@@ -177,8 +169,7 @@
             outState.putParcelable(KEY_STATE_SELECTED_OPTION, mSelectedOption);
         }
         if (mBottomActionBar != null) {
-            outState.putBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBILITY,
-                    mBottomActionBar.isVisible());
+            outState.putBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE, mBottomActionBar.isVisible());
         }
     }
 
@@ -211,14 +202,9 @@
             public void onOptionsLoaded(List<GridOption> options) {
                 mLoading.hide();
                 mOptionsController = new OptionSelectorController<>(mOptionsContainer, options);
-                mOptionsController.addListener(selected -> {
-                    mSelectedOption = (GridOption) selected;
-                    mBottomActionBar.show();
-                    mEventLogger.logGridSelected(mSelectedOption);
-                    mGridOptionPreviewer.setGridOption(mSelectedOption);
-                });
                 mOptionsController.initOptions(mGridManager);
 
+                // Find the selected Grid option.
                 GridOption previouslySelectedOption = null;
                 if (savedInstanceState != null) {
                     previouslySelectedOption = findEquivalent(
@@ -227,15 +213,15 @@
                 mSelectedOption = previouslySelectedOption != null
                         ? previouslySelectedOption
                         : getActiveOption(options);
-                // Will trigger selected listener.
+
                 mOptionsController.setSelectedOption(mSelectedOption);
-                boolean bottomActionBarVisibility = savedInstanceState != null
-                        && savedInstanceState.getBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBILITY);
-                if (bottomActionBarVisibility) {
+                onOptionSelected(mSelectedOption);
+                restoreBottomActionBarVisibility(savedInstanceState);
+
+                mOptionsController.addListener(selectedOption -> {
+                    onOptionSelected(selectedOption);
                     mBottomActionBar.show();
-                } else {
-                    mBottomActionBar.hide();
-                }
+                });
             }
 
             @Override
@@ -275,6 +261,22 @@
         mError.setVisibility(View.VISIBLE);
     }
 
+    private void onOptionSelected(CustomizationOption selectedOption) {
+        mSelectedOption = (GridOption) selectedOption;
+        mEventLogger.logGridSelected(mSelectedOption);
+        mGridOptionPreviewer.setGridOption(mSelectedOption);
+    }
+
+    private void restoreBottomActionBarVisibility(@Nullable Bundle savedInstanceState) {
+        boolean isBottomActionBarVisible = savedInstanceState != null
+                && savedInstanceState.getBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE);
+        if (isBottomActionBarVisible) {
+            mBottomActionBar.show();
+        } else {
+            mBottomActionBar.hide();
+        }
+    }
+
     private void showFullPreview() {
         Bundle bundle = new Bundle();
         bundle.putParcelable(EXTRA_WALLPAPER_INFO, mHomeWallpaper);
diff --git a/src/com/android/customization/picker/grid/GridFullPreviewFragment.java b/src/com/android/customization/picker/grid/GridFullPreviewFragment.java
index 27293d6..69105df 100644
--- a/src/com/android/customization/picker/grid/GridFullPreviewFragment.java
+++ b/src/com/android/customization/picker/grid/GridFullPreviewFragment.java
@@ -104,22 +104,13 @@
 
         mGridOptionPreviewer = new GridOptionPreviewer(gridManager,
                 view.findViewById(R.id.grid_preview_container));
-
-        view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                                       int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                mWallpaperPreviewer.updatePreviewCardRadius();
-                view.removeOnLayoutChangeListener(this);
-            }
-        });
         return view;
     }
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        mWallpaperPreviewer.setWallpaper(mWallpaper);
+        mWallpaperPreviewer.setWallpaper(mWallpaper, /* listener= */ null);
         mGridOptionPreviewer.setGridOption(mGridOption);
     }
 
diff --git a/src/com/android/customization/picker/grid/GridOptionPreviewer.java b/src/com/android/customization/picker/grid/GridOptionPreviewer.java
index 47303e9..fdefa05 100644
--- a/src/com/android/customization/picker/grid/GridOptionPreviewer.java
+++ b/src/com/android/customization/picker/grid/GridOptionPreviewer.java
@@ -17,7 +17,6 @@
 
 import android.content.Context;
 import android.os.Bundle;
-import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.ViewGroup;
@@ -54,11 +53,6 @@
     public void release() {
         if (mGridOptionSurface != null) {
             mSurfaceCallback.cleanUp();
-            mGridOptionSurface.getHolder().removeCallback(mSurfaceCallback);
-            Surface surface = mGridOptionSurface.getHolder().getSurface();
-            if (surface != null) {
-                surface.release();
-            }
             mGridOptionSurface = null;
         }
         mPreviewContainer.removeAllViews();
diff --git a/src/com/android/customization/picker/theme/CustomThemeNameFragment.java b/src/com/android/customization/picker/theme/CustomThemeNameFragment.java
index f4a1106..f36c80b 100644
--- a/src/com/android/customization/picker/theme/CustomThemeNameFragment.java
+++ b/src/com/android/customization/picker/theme/CustomThemeNameFragment.java
@@ -20,7 +20,6 @@
 import static com.android.customization.picker.theme.ThemeFullPreviewFragment.EXTRA_THEME_OPTION_TITLE;
 import static com.android.customization.picker.theme.ThemeFullPreviewFragment.EXTRA_WALLPAPER_INFO;
 
-import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.text.TextUtils;
@@ -45,7 +44,6 @@
 import com.android.wallpaper.module.CurrentWallpaperInfoFactory;
 import com.android.wallpaper.module.InjectorProvider;
 import com.android.wallpaper.picker.AppbarFragment;
-import com.android.wallpaper.widget.WallpaperColorsLoader;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -101,28 +99,13 @@
         currentWallpaperFactory.createCurrentWallpaperInfos(
                 (homeWallpaper, lockWallpaper, presentationMode) -> {
                     mCurrentHomeWallpaper = homeWallpaper;
-                    wallpaperPreviewer.setWallpaper(homeWallpaper);
-                    Context context =  getContext();
-                    if (context != null) {
-                        WallpaperColorsLoader.getWallpaperColors(
-                                context,
-                                mCurrentHomeWallpaper.getThumbAsset(context),
-                                mThemeOptionPreviewer::updateColorForLauncherWidgets);
-                    }
+                    wallpaperPreviewer.setWallpaper(homeWallpaper,
+                            mThemeOptionPreviewer::updateColorForLauncherWidgets);
                 }, false);
 
         // Set theme default name.
         mNameEditor = view.findViewById(R.id.custom_theme_name);
         mNameEditor.setText(getOriginalThemeName());
-
-        view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                                       int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                wallpaperPreviewer.updatePreviewCardRadius();
-                view.removeOnLayoutChangeListener(this);
-            }
-        });
         return view;
     }
 
diff --git a/src/com/android/customization/picker/theme/ThemeFragment.java b/src/com/android/customization/picker/theme/ThemeFragment.java
index 18cc3b4..de8aa69 100644
--- a/src/com/android/customization/picker/theme/ThemeFragment.java
+++ b/src/com/android/customization/picker/theme/ThemeFragment.java
@@ -43,6 +43,7 @@
 
 import com.android.customization.model.CustomizationManager.Callback;
 import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
+import com.android.customization.model.CustomizationOption;
 import com.android.customization.model.theme.ThemeBundle;
 import com.android.customization.model.theme.ThemeManager;
 import com.android.customization.model.theme.custom.CustomTheme;
@@ -57,7 +58,7 @@
 import com.android.wallpaper.module.InjectorProvider;
 import com.android.wallpaper.picker.AppbarFragment;
 import com.android.wallpaper.widget.BottomActionBar;
-import com.android.wallpaper.widget.WallpaperColorsLoader;
+import com.android.wallpaper.widget.BottomActionBar.AccessibilityCallback;
 
 import java.util.List;
 
@@ -68,8 +69,8 @@
 
     private static final String TAG = "ThemeFragment";
     private static final String KEY_SELECTED_THEME = "ThemeFragment.SelectedThemeBundle";
-    private static final String KEY_STATE_BOTTOM_ACTION_BAR_VISIBILITY =
-            "ThemeFragment.bottomActionBarVisibility";
+    private static final String KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE =
+            "ThemeFragment.bottomActionBarVisible";
     private static final int FULL_PREVIEW_REQUEST_CODE = 1000;
 
     /**
@@ -138,25 +139,10 @@
         mCurrentWallpaperFactory.createCurrentWallpaperInfos(
                 (homeWallpaper, lockWallpaper, presentationMode) -> {
                     mCurrentHomeWallpaper = homeWallpaper;
-                    mWallpaperPreviewer.setWallpaper(mCurrentHomeWallpaper);
-                    Context context = getContext();
-                    if (context != null) {
-                        WallpaperColorsLoader.getWallpaperColors(
-                                context,
-                                mCurrentHomeWallpaper.getThumbAsset(context),
-                                mThemeOptionPreviewer::updateColorForLauncherWidgets);
-                    }
+                    mWallpaperPreviewer.setWallpaper(mCurrentHomeWallpaper,
+                            mThemeOptionPreviewer::updateColorForLauncherWidgets);
                 }, false);
 
-        view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                                       int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                mWallpaperPreviewer.updatePreviewCardRadius();
-                view.removeOnLayoutChangeListener(this);
-            }
-        });
-
         view.findViewById(R.id.theme_preview_card).setOnClickListener(v -> showFullPreview());
         return view;
     }
@@ -173,6 +159,22 @@
                 R.layout.theme_info_view, /* root= */ null);
         mBottomActionBar.attachViewToBottomSheetAndBindAction(mThemeInfoView, INFORMATION);
         mBottomActionBar.setActionClickListener(CUSTOMIZE, this::onCustomizeClicked);
+
+        // Update target view's accessibility param since it will be blocked by the bottom sheet
+        // when expanded.
+        mBottomActionBar.setAccessibilityCallback(new AccessibilityCallback() {
+            @Override
+            public void onBottomSheetCollapsed() {
+                mOptionsContainer.setImportantForAccessibility(
+                        View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+            }
+
+            @Override
+            public void onBottomSheetExpanded() {
+                mOptionsContainer.setImportantForAccessibility(
+                        View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+            }
+        });
     }
 
     @Override
@@ -211,8 +213,7 @@
             outState.putString(KEY_SELECTED_THEME, mSelectedTheme.getSerializedPackages());
         }
         if (mBottomActionBar != null) {
-            outState.putBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBILITY,
-                    mBottomActionBar.isVisible());
+            outState.putBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE, mBottomActionBar.isVisible());
         }
     }
 
@@ -265,30 +266,10 @@
             @Override
             public void onOptionsLoaded(List<ThemeBundle> options) {
                 mOptionsController = new OptionSelectorController<>(mOptionsContainer, options);
-                mOptionsController.addListener(selected -> {
-                    mLoading.hide();
-                    if (selected instanceof CustomTheme && !((CustomTheme) selected).isDefined()) {
-                        navigateToCustomTheme((CustomTheme) selected);
-                    } else {
-                        mSelectedTheme = (ThemeBundle) selected;
-                        mSelectedTheme.setOverrideThemeWallpaper(mCurrentHomeWallpaper);
-                        mEventLogger.logThemeSelected(mSelectedTheme,
-                                selected instanceof CustomTheme);
-                        mThemeOptionPreviewer.setPreviewInfo(mSelectedTheme.getPreviewInfo());
-                        if (mThemeInfoView != null && mSelectedTheme != null) {
-                            mThemeInfoView.populateThemeInfo(mSelectedTheme);
-                        }
-
-                        if (selected instanceof CustomTheme) {
-                            mBottomActionBar.showActionsOnly(INFORMATION, CUSTOMIZE, APPLY);
-                        } else {
-                            mBottomActionBar.showActionsOnly(INFORMATION, APPLY);
-                        }
-                        mBottomActionBar.show();
-                    }
-                });
                 mOptionsController.initOptions(mThemeManager);
 
+                // Find out the selected theme option.
+                // 1. Find previously selected theme.
                 String previouslySelected = savedInstanceState != null
                         ? savedInstanceState.getString(KEY_SELECTED_THEME) : null;
                 ThemeBundle previouslySelectedTheme = null;
@@ -302,22 +283,26 @@
                         activeTheme = theme;
                     }
                 }
+                // 2. Use active theme if no previously selected theme.
                 mSelectedTheme = previouslySelectedTheme != null
                         ? previouslySelectedTheme
                         : activeTheme;
-
+                // 3. Select the default theme if there is no matching custom enabled theme.
                 if (mSelectedTheme == null) {
-                    // Select the default theme if there is no matching custom enabled theme
                     mSelectedTheme = findDefaultThemeBundle(options);
                 }
+
                 mOptionsController.setSelectedOption(mSelectedTheme);
-                boolean bottomActionBarVisibility = savedInstanceState != null
-                        && savedInstanceState.getBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBILITY);
-                if (bottomActionBarVisibility) {
-                    mBottomActionBar.show();
-                } else {
-                    mBottomActionBar.hide();
-                }
+                onOptionSelected(mSelectedTheme);
+                restoreBottomActionBarVisibility(savedInstanceState);
+
+                mOptionsController.addListener(selectedOption -> {
+                    onOptionSelected(selectedOption);
+                    if (!isAddCustomThemeOption(selectedOption)) {
+                        mBottomActionBar.show();
+                    }
+                });
+                mLoading.hide();
             }
             @Override
             public void onError(@Nullable Throwable throwable) {
@@ -360,6 +345,41 @@
         return null;
     }
 
+    private void onOptionSelected(CustomizationOption selectedOption) {
+        if (isAddCustomThemeOption(selectedOption)) {
+            navigateToCustomTheme((CustomTheme) selectedOption);
+        } else {
+            mSelectedTheme = (ThemeBundle) selectedOption;
+            mSelectedTheme.setOverrideThemeWallpaper(mCurrentHomeWallpaper);
+            mEventLogger.logThemeSelected(mSelectedTheme,
+                    selectedOption instanceof CustomTheme);
+            mThemeOptionPreviewer.setPreviewInfo(mSelectedTheme.getPreviewInfo());
+            if (mThemeInfoView != null && mSelectedTheme != null) {
+                mThemeInfoView.populateThemeInfo(mSelectedTheme);
+            }
+
+            if (selectedOption instanceof CustomTheme) {
+                mBottomActionBar.showActionsOnly(INFORMATION, CUSTOMIZE, APPLY);
+            } else {
+                mBottomActionBar.showActionsOnly(INFORMATION, APPLY);
+            }
+        }
+    }
+
+    private void restoreBottomActionBarVisibility(@Nullable Bundle savedInstanceState) {
+        boolean isBottomActionBarVisible = savedInstanceState != null
+                && savedInstanceState.getBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE);
+        if (isBottomActionBarVisible) {
+            mBottomActionBar.show();
+        } else {
+            mBottomActionBar.hide();
+        }
+    }
+
+    private boolean isAddCustomThemeOption(CustomizationOption option) {
+        return option instanceof CustomTheme && !((CustomTheme) option).isDefined();
+    }
+
     private void navigateToCustomTheme(CustomTheme themeToEdit) {
         Intent intent = new Intent(getActivity(), CustomThemeActivity.class);
         intent.putExtra(CustomThemeActivity.EXTRA_THEME_TITLE, themeToEdit.getTitle());
diff --git a/src/com/android/customization/picker/theme/ThemeFullPreviewFragment.java b/src/com/android/customization/picker/theme/ThemeFullPreviewFragment.java
index 1821f84..7cbeab9 100644
--- a/src/com/android/customization/picker/theme/ThemeFullPreviewFragment.java
+++ b/src/com/android/customization/picker/theme/ThemeFullPreviewFragment.java
@@ -21,7 +21,6 @@
 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.INFORMATION;
 
 import android.app.Activity;
-import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
@@ -44,7 +43,6 @@
 import com.android.wallpaper.module.InjectorProvider;
 import com.android.wallpaper.picker.AppbarFragment;
 import com.android.wallpaper.widget.BottomActionBar;
-import com.android.wallpaper.widget.WallpaperColorsLoader;
 
 import com.bumptech.glide.Glide;
 
@@ -106,6 +104,13 @@
         setUpToolbar(view);
         Glide.get(getContext()).clearMemory();
 
+        // Set theme option.
+        final ThemeOptionPreviewer themeOptionPreviewer = new ThemeOptionPreviewer(
+                getLifecycle(),
+                getContext(),
+                view.findViewById(R.id.theme_preview_container));
+        themeOptionPreviewer.setPreviewInfo(mThemeBundle.getPreviewInfo());
+
         // Set wallpaper background.
         ImageView wallpaperImageView = view.findViewById(R.id.wallpaper_preview_image);
         final WallpaperPreviewer wallpaperPreviewer = new WallpaperPreviewer(
@@ -113,29 +118,8 @@
                 getActivity(),
                 wallpaperImageView,
                 view.findViewById(R.id.wallpaper_preview_surface));
-        wallpaperPreviewer.setWallpaper(mWallpaper);
-
-        // Set theme option.
-        final ThemeOptionPreviewer themeOptionPreviewer = new ThemeOptionPreviewer(
-                getLifecycle(),
-                getContext(),
-                view.findViewById(R.id.theme_preview_container));
-        themeOptionPreviewer.setPreviewInfo(mThemeBundle.getPreviewInfo());
-        view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                                       int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                wallpaperPreviewer.updatePreviewCardRadius();
-                Context context = getContext();
-                if (context != null) {
-                    WallpaperColorsLoader.getWallpaperColors(
-                            context,
-                            mWallpaper.getThumbAsset(context),
-                            themeOptionPreviewer::updateColorForLauncherWidgets);
-                }
-                view.removeOnLayoutChangeListener(this);
-            }
-        });
+        wallpaperPreviewer.setWallpaper(mWallpaper,
+                themeOptionPreviewer::updateColorForLauncherWidgets);
         return view;
     }
 
diff --git a/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java b/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java
index d9b7f4d..7b4d220 100644
--- a/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java
+++ b/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java
@@ -128,8 +128,8 @@
             public void onLayoutChange(View view, int left, int top, int right, int bottom,
                                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
                 // Calculate the full preview card height and width.
-                int fullPreviewCardHeight = getFullPreviewCardHeight();
-                int fullPreviewCardWidth = (int) (getFullPreviewCardHeight() / screenAspectRatio);
+                final int fullPreviewCardHeight = getFullPreviewCardHeight();
+                final int fullPreviewCardWidth = (int) (fullPreviewCardHeight / screenAspectRatio);
 
                 // Relayout the content view to match full preview card size.
                 mContentView.measure(
@@ -139,8 +139,7 @@
 
                 // Scale the content view from full preview size to the container size. For full
                 // preview, the scale value is 1.
-                float scale =
-                        (float) previewContainer.getMeasuredHeight() / getFullPreviewCardHeight();
+                float scale = (float) previewContainer.getMeasuredHeight() / fullPreviewCardHeight;
                 mContentView.setScaleX(scale);
                 mContentView.setScaleY(scale);
                 // The pivot point is centered by default, set to (0, 0).
@@ -188,8 +187,8 @@
                 ? R.color.text_color_light
                 : R.color.text_color_dark);
         int textShadowColor = mContext.getColor(useLightTextColor
-                ? R.color.theme_preview_workspace_shadow_color_dark
-                : R.color.theme_preview_workspace_shadow_color_transparent);
+                ? R.color.smartspace_preview_shadow_color_dark
+                : R.color.smartspace_preview_shadow_color_transparent);
         // Update the top status bar clock text color.
         mStatusBarClock.setTextColor(textColor);
         // Update the top status bar icon color.
@@ -202,7 +201,7 @@
         mSmartSpaceDate.setTextColor(textColor);
         mSmartSpaceDate.setShadowLayer(
                 mContext.getResources().getDimension(
-                        R.dimen.preview_theme_smartspace_key_ambient_shadow_blur),
+                        R.dimen.smartspace_preview_key_ambient_shadow_blur),
                 /* dx = */ 0,
                 /* dy = */ 0,
                 textShadowColor);