Merge changes from topic "presubmit-am-7cdc57ecaf194d2d990a0d381cd9d593" into sc-qpr1-dev am: affece888e am: a3d0cec6d6

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/ThemePicker/+/16473299

Change-Id: I0e1276eacf1d3d09aa4f6afbc7954265c31fab92
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ccadc12..c6e79a9 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -52,6 +52,7 @@
             tools:node="replace"
             android:name="com.android.wallpaper.picker.CustomizationPickerActivity"
             android:label="@string/app_name"
+            android:relinquishTaskIdentity="true"
             android:resizeableActivity="false"
             android:theme="@style/CustomizationTheme.NoActionBar"
             android:exported="false"/>
diff --git a/res/color-night/check_circle_grey_large_not_select_background_color.xml b/res/color-night/check_circle_grey_large_not_select_background_color.xml
new file mode 100644
index 0000000..ab5c0cd
--- /dev/null
+++ b/res/color-night/check_circle_grey_large_not_select_background_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:color="?androidprv:attr/textColorSecondary" />
+</selector>
\ No newline at end of file
diff --git a/res/color-night/check_circle_grey_large_not_select_color.xml b/res/color-night/check_circle_grey_large_not_select_color.xml
new file mode 100644
index 0000000..6e8db34
--- /dev/null
+++ b/res/color-night/check_circle_grey_large_not_select_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" >
+    <item android:color="?androidprv:attr/textColorOnAccent" />
+</selector>
\ No newline at end of file
diff --git a/res/color-night/option_background_new_selection_color.xml b/res/color-night/option_background_new_selection_color.xml
new file mode 100644
index 0000000..0158ea2
--- /dev/null
+++ b/res/color-night/option_background_new_selection_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+</selector>
\ No newline at end of file
diff --git a/res/color/check_circle_grey_large_not_select_background_color.xml b/res/color/check_circle_grey_large_not_select_background_color.xml
new file mode 100644
index 0000000..c023611
--- /dev/null
+++ b/res/color/check_circle_grey_large_not_select_background_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:color="?androidprv:attr/textColorSecondaryInverse" />
+</selector>
\ No newline at end of file
diff --git a/res/color/check_circle_grey_large_not_select_color.xml b/res/color/check_circle_grey_large_not_select_color.xml
new file mode 100644
index 0000000..252665f
--- /dev/null
+++ b/res/color/check_circle_grey_large_not_select_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:color="?androidprv:attr/textColorPrimary" />
+</selector>
\ No newline at end of file
diff --git a/res/color/option_background_new_selection_color.xml b/res/color/option_background_new_selection_color.xml
new file mode 100644
index 0000000..0158ea2
--- /dev/null
+++ b/res/color/option_background_new_selection_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/check_circle_grey_large_not_select.xml b/res/drawable/check_circle_grey_large_not_select.xml
new file mode 100644
index 0000000..544d852
--- /dev/null
+++ b/res/drawable/check_circle_grey_large_not_select.xml
@@ -0,0 +1,32 @@
+<!--
+     Copyright (C) 2021 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item>
+        <shape android:shape="oval">
+            <size android:width="@dimen/center_check_size"
+                android:height="@dimen/center_check_size" />
+            <solid android:color="@color/check_circle_grey_large_not_select_background_color" />
+        </shape>
+    </item>
+    <item>
+        <inset android:drawable="@drawable/ic_check_24dp_not_select"
+            android:insetTop="@dimen/center_check_padding"
+            android:insetRight="@dimen/center_check_padding"
+            android:insetBottom="@dimen/center_check_padding"
+            android:insetLeft="@dimen/center_check_padding"/>
+    </item>
+</layer-list>
diff --git a/res/drawable/ic_check_24dp_not_select.xml b/res/drawable/ic_check_24dp_not_select.xml
new file mode 100644
index 0000000..e6af76c
--- /dev/null
+++ b/res/drawable/ic_check_24dp_not_select.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@color/check_circle_grey_large_not_select_color"
+        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41L9,16.17z"/>
+</vector>
diff --git a/res/drawable/option_border_new_selection.xml b/res/drawable/option_border_new_selection.xml
new file mode 100644
index 0000000..6c02caa
--- /dev/null
+++ b/res/drawable/option_border_new_selection.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <solid android:color="@android:color/white"/>
+            <corners android:radius="@dimen/option_tile_radius" />
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="rectangle">
+            <solid android:color="@color/option_background_new_selection_color" />
+            <corners android:radius="@dimen/option_tile_radius" />
+        </shape>
+    </item>
+</ripple>
diff --git a/res/layout/themed_icon_section_view.xml b/res/layout/themed_icon_section_view.xml
index 97892ee..cf7b842 100644
--- a/res/layout/themed_icon_section_view.xml
+++ b/res/layout/themed_icon_section_view.xml
@@ -28,6 +28,7 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:gravity="center_vertical"
         android:orientation="horizontal">
 
         <TextView
@@ -42,7 +43,7 @@
         <Switch
             android:id="@+id/themed_icon_toggle"
             android:layout_width="wrap_content"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:background="@null"
             android:clickable="false"
             android:focusable="false"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0ea2f7e..f2d0f21 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -42,10 +42,6 @@
         the one bundled with selected Theme [CHAR LIMIT=35]-->
     <string name="keep_my_wallpaper">Keep current wallpaper</string>
 
-    <!-- Label for a button that allows the user to apply the currently selected customization option.
-        [CHAR LIMIT=20] -->
-    <string name="apply_btn">Apply</string>
-
     <!-- Content description of theme preview card. [CHAR_LIMIT=30]-->
     <string name="theme_preview_card_content_description">Style preview</string>
 
@@ -73,6 +69,9 @@
     <!-- Content description indicating that the selected option is currently being previewed. [CHAR_LIMIT=NONE] -->
     <string name="option_previewed_description"><xliff:g name="style_name">%1$s</xliff:g>, currently previewed</string>
 
+    <!-- Content description indicating that the focused option can be selected and previewed if clicked. [CHAR_LIMIT=NONE] -->
+    <string name="option_change_applied_previewed_description"><xliff:g name="style_name">%1$s</xliff:g>, change selected and previewed</string>
+
     <!-- Sample text used to show a preview of a selected font [CHAR LIMIT=3] -->
     <string name="theme_font_example" translatable="false">ABC</string>
 
@@ -237,6 +236,8 @@
     <!-- The title of mode section view. [CHAR_LIMIT=20] -->
     <string name="mode_title" msgid="1000319159005403986">Dark theme</string>
     <string name="mode_disabled_msg" msgid="1926077857799715086">Temporarily disabled due to Battery Saver</string>
+    <!-- The text for A11y announcement when theme changes. -->
+    <string name="mode_changed">Theme changed</string>
 
     <!-- Title of a section of the customization where the user can select color override for icon. [CHAR LIMIT=30] -->
     <string name="themed_icon_title" msgid="4305612684940220645">Themed icons</string>
diff --git a/src/com/android/customization/model/grid/GridOption.java b/src/com/android/customization/model/grid/GridOption.java
index 16a5eb0..19c5d4f 100644
--- a/src/com/android/customization/model/grid/GridOption.java
+++ b/src/com/android/customization/model/grid/GridOption.java
@@ -93,11 +93,18 @@
         Context context = view.getContext();
 
         int colorFilter = ResourceUtils.getColorAttr(context,
-                view.isActivated() ? android.R.attr.textColorPrimary :
-                android.R.attr.textColorTertiary);
+                view.isActivated()
+                        ? (mIsCurrent
+                            ? android.R.attr.textColorPrimary
+                            : android.R.attr.textColorPrimaryInverse)
+                        : android.R.attr.textColorTertiary);
         mTileDrawable.setColorFilter(colorFilter, Mode.SRC_ATOP);
         ((ImageView) view.findViewById(R.id.grid_option_thumbnail))
                 .setImageDrawable(mTileDrawable);
+
+        int backgroundResource = view.isActivated() && !mIsCurrent
+                ? R.drawable.option_border_new_selection : R.drawable.option_border;
+        view.findViewById(R.id.option_tile).setBackgroundResource(backgroundResource);
     }
 
     @Override
diff --git a/src/com/android/customization/model/grid/GridOptionViewModel.java b/src/com/android/customization/model/grid/GridOptionViewModel.java
new file mode 100644
index 0000000..33fa8e179
--- /dev/null
+++ b/src/com/android/customization/model/grid/GridOptionViewModel.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.grid;
+
+import androidx.lifecycle.SavedStateHandle;
+import androidx.lifecycle.ViewModel;
+
+/** The class to store status of the grid fragment view. */
+public class GridOptionViewModel extends ViewModel {
+    private static final String SELECTED_OPTION_KEY = "selected_option";
+    private static final String BOTTOM_ACTION_BAR_VISIBLE_KEY = "bottom_action_bar_visible";
+
+    private SavedStateHandle mState;
+
+    public GridOptionViewModel(SavedStateHandle savedStateHandle) {
+        mState = savedStateHandle;
+    }
+
+    /** Gets selected {@link GridOption} from {@link SavedStateHandle} */
+    public GridOption getSelectedOption() {
+        return mState.get(SELECTED_OPTION_KEY);
+    }
+
+    /** Sets selected {@link GridOption} to {@link SavedStateHandle} */
+    public void setSelectedOption(GridOption selectedOption) {
+        mState.set(SELECTED_OPTION_KEY, selectedOption);
+    }
+
+    /** Gets bottom action bar visible from {@link SavedStateHandle} */
+    public boolean getBottomActionBarVisible() {
+        return mState.contains(BOTTOM_ACTION_BAR_VISIBLE_KEY)
+                ? mState.get(BOTTOM_ACTION_BAR_VISIBLE_KEY)
+                : false;
+    }
+
+    /** Sets bottom action bar visible to {@link SavedStateHandle} */
+    public void setBottomActionBarVisible(boolean bottomActionBarVisible) {
+        mState.set(BOTTOM_ACTION_BAR_VISIBLE_KEY, bottomActionBarVisible);
+    }
+}
diff --git a/src/com/android/customization/model/grid/GridSectionController.java b/src/com/android/customization/model/grid/GridSectionController.java
index 5470d77..64a6cce 100644
--- a/src/com/android/customization/model/grid/GridSectionController.java
+++ b/src/com/android/customization/model/grid/GridSectionController.java
@@ -74,8 +74,8 @@
             }
         }, /* reload= */ true);
 
-        gridSectionView.setOnClickListener(v -> mSectionNavigationController.navigateTo(
-                GridFragment.newInstance(context.getString(R.string.grid_title))));
+        gridSectionView.setOnClickListener(
+                v -> mSectionNavigationController.navigateTo(new GridFragment()));
 
         return gridSectionView;
     }
diff --git a/src/com/android/customization/model/mode/DarkModeSectionController.java b/src/com/android/customization/model/mode/DarkModeSectionController.java
index 382162e..f56b709 100644
--- a/src/com/android/customization/model/mode/DarkModeSectionController.java
+++ b/src/com/android/customization/model/mode/DarkModeSectionController.java
@@ -128,7 +128,11 @@
         UiModeManager uiModeManager = context.getSystemService(UiModeManager.class);
         int shortDelay = context.getResources().getInteger(android.R.integer.config_shortAnimTime);
         new Handler(Looper.getMainLooper()).postDelayed(
-                () -> uiModeManager.setNightModeActivated(viewActivated),
+                () -> {
+                    mDarkModeSectionView.announceForAccessibility(
+                            context.getString(R.string.mode_changed));
+                    uiModeManager.setNightModeActivated(viewActivated);
+                },
                 /* delayMillis= */ shortDelay);
     }
 
diff --git a/src/com/android/customization/module/DefaultCustomizationInjector.java b/src/com/android/customization/module/DefaultCustomizationInjector.java
index db899a3..c906281 100644
--- a/src/com/android/customization/module/DefaultCustomizationInjector.java
+++ b/src/com/android/customization/module/DefaultCustomizationInjector.java
@@ -95,8 +95,10 @@
             WallpaperInfo wallpaperInfo,
             int mode,
             boolean viewAsHome,
+            boolean viewFullScreen,
             boolean testingModeEnabled) {
-        return PreviewFragment.newInstance(wallpaperInfo, mode, viewAsHome, testingModeEnabled);
+        return PreviewFragment.newInstance(wallpaperInfo, mode, viewAsHome, viewFullScreen,
+                testingModeEnabled);
     }
 
     @Override
diff --git a/src/com/android/customization/picker/grid/GridFragment.java b/src/com/android/customization/picker/grid/GridFragment.java
index bb29d55..9896edc 100644
--- a/src/com/android/customization/picker/grid/GridFragment.java
+++ b/src/com/android/customization/picker/grid/GridFragment.java
@@ -17,23 +17,27 @@
 
 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY_TEXT;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.core.widget.ContentLoadingProgressBar;
+import androidx.lifecycle.ViewModelProvider;
 import androidx.recyclerview.widget.RecyclerView;
 
 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.GridOptionViewModel;
 import com.android.customization.model.grid.GridOptionsManager;
 import com.android.customization.module.ThemesUserEventLogger;
 import com.android.customization.picker.WallpaperPreviewer;
@@ -57,27 +61,18 @@
 public class GridFragment extends AppbarFragment {
 
     private static final String TAG = "GridFragment";
-    private static final String KEY_STATE_SELECTED_OPTION = "GridFragment.selectedOption";
-    private static final String KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE =
-            "GridFragment.bottomActionBarVisible";
-
-    public static GridFragment newInstance(CharSequence title) {
-        GridFragment fragment = new GridFragment();
-        fragment.setArguments(AppbarFragment.createArguments(title));
-        return fragment;
-    }
 
     private WallpaperInfo mHomeWallpaper;
     private RecyclerView mOptionsContainer;
     private OptionSelectorController<GridOption> mOptionsController;
     private GridOptionsManager mGridManager;
-    private GridOption mSelectedOption;
     private ContentLoadingProgressBar mLoading;
     private View mContent;
     private View mError;
     private BottomActionBar mBottomActionBar;
     private ThemesUserEventLogger mEventLogger;
     private GridOptionPreviewer mGridOptionPreviewer;
+    private GridOptionViewModel mGridOptionViewModel;
 
     private final Callback mApplyGridCallback = new Callback() {
         @Override
@@ -95,10 +90,18 @@
             // Since we disabled it when clicked apply button.
             mBottomActionBar.enableActions();
             mBottomActionBar.hide();
+            mGridOptionViewModel.setBottomActionBarVisible(false);
             //TODO(chihhangchuang): handle
         }
     };
 
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mGridOptionViewModel = new ViewModelProvider(requireActivity()).get(
+                GridOptionViewModel.class);
+    }
+
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@@ -108,6 +111,12 @@
         setUpToolbar(view);
         mContent = view.findViewById(R.id.content_section);
         mOptionsContainer = view.findViewById(R.id.options_container);
+        AccessibilityManager accessibilityManager =
+                (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+        if (accessibilityManager.isEnabled()) {
+            // Make Talkback focus won't reset when notifyDataSetChange
+            mOptionsContainer.setItemAnimator(null);
+        }
         mLoading = view.findViewById(R.id.loading_indicator);
         mError = view.findViewById(R.id.error_section);
 
@@ -127,7 +136,7 @@
         mGridManager = GridOptionsManager.getInstance(getContext());
         mEventLogger = (ThemesUserEventLogger) InjectorProvider.getInjector()
                 .getUserEventLogger(getContext());
-        setUpOptions(savedInstanceState);
+        setUpOptions();
 
         SurfaceView wallpaperSurface = view.findViewById(R.id.wallpaper_preview_surface);
         WallpaperPreviewer wallpaperPreviewer = new WallpaperPreviewer(getLifecycle(),
@@ -147,6 +156,13 @@
     }
 
     @Override
+    public boolean onBackPressed() {
+        mGridOptionViewModel.setSelectedOption(null);
+        mGridOptionViewModel.setBottomActionBarVisible(false);
+        return super.onBackPressed();
+    }
+
+    @Override
     public void onDestroy() {
         super.onDestroy();
         if (mGridOptionPreviewer != null) {
@@ -155,14 +171,8 @@
     }
 
     @Override
-    public void onSaveInstanceState(@NonNull Bundle outState) {
-        super.onSaveInstanceState(outState);
-        if (mSelectedOption != null) {
-            outState.putParcelable(KEY_STATE_SELECTED_OPTION, mSelectedOption);
-        }
-        if (mBottomActionBar != null) {
-            outState.putBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE, mBottomActionBar.isVisible());
-        }
+    public CharSequence getDefaultTitle() {
+        return getString(R.string.grid_title);
     }
 
     @Override
@@ -170,7 +180,8 @@
         super.onBottomActionBarReady(bottomActionBar);
         mBottomActionBar = bottomActionBar;
         mBottomActionBar.showActionsOnly(APPLY_TEXT);
-        mBottomActionBar.setActionClickListener(APPLY_TEXT, v -> applyGridOption(mSelectedOption));
+        mBottomActionBar.setActionClickListener(APPLY_TEXT,
+                v -> applyGridOption(mGridOptionViewModel.getSelectedOption()));
     }
 
     private void applyGridOption(GridOption gridOption) {
@@ -178,7 +189,7 @@
         mGridManager.apply(gridOption, mApplyGridCallback);
     }
 
-    private void setUpOptions(@Nullable Bundle savedInstanceState) {
+    private void setUpOptions() {
         hideError();
         mLoading.show();
         mGridManager.fetchOptions(new OptionsFetchedListener<GridOption>() {
@@ -186,26 +197,24 @@
             public void onOptionsLoaded(List<GridOption> options) {
                 mLoading.hide();
                 mOptionsController = new OptionSelectorController<>(
-                        mOptionsContainer, options, /* useGrid= */ false, CheckmarkStyle.CENTER);
+                        mOptionsContainer, options, /* useGrid= */ false,
+                        CheckmarkStyle.CENTER_CHANGE_COLOR_WHEN_NOT_SELECTED);
                 mOptionsController.initOptions(mGridManager);
+                GridOption previouslySelectedOption = findEquivalent(options,
+                        mGridOptionViewModel.getSelectedOption());
+                mGridOptionViewModel.setSelectedOption(
+                        previouslySelectedOption != null
+                                ? previouslySelectedOption
+                                : getActiveOption(options));
 
-                // Find the selected Grid option.
-                GridOption previouslySelectedOption = null;
-                if (savedInstanceState != null) {
-                    previouslySelectedOption = findEquivalent(
-                            options, savedInstanceState.getParcelable(KEY_STATE_SELECTED_OPTION));
-                }
-                mSelectedOption = previouslySelectedOption != null
-                        ? previouslySelectedOption
-                        : getActiveOption(options);
-
-                mOptionsController.setSelectedOption(mSelectedOption);
-                onOptionSelected(mSelectedOption);
-                restoreBottomActionBarVisibility(savedInstanceState);
+                mOptionsController.setSelectedOption(mGridOptionViewModel.getSelectedOption());
+                onOptionSelected(mGridOptionViewModel.getSelectedOption());
+                restoreBottomActionBarVisibility();
 
                 mOptionsController.addListener(selectedOption -> {
                     onOptionSelected(selectedOption);
                     mBottomActionBar.show();
+                    mGridOptionViewModel.setBottomActionBarVisible(true);
                 });
             }
 
@@ -247,15 +256,13 @@
     }
 
     private void onOptionSelected(CustomizationOption selectedOption) {
-        mSelectedOption = (GridOption) selectedOption;
-        mEventLogger.logGridSelected(mSelectedOption);
-        mGridOptionPreviewer.setGridOption(mSelectedOption);
+        mGridOptionViewModel.setSelectedOption((GridOption) selectedOption);
+        mEventLogger.logGridSelected(mGridOptionViewModel.getSelectedOption());
+        mGridOptionPreviewer.setGridOption(mGridOptionViewModel.getSelectedOption());
     }
 
-    private void restoreBottomActionBarVisibility(@Nullable Bundle savedInstanceState) {
-        boolean isBottomActionBarVisible = savedInstanceState != null
-                && savedInstanceState.getBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE);
-        if (isBottomActionBarVisible) {
+    private void restoreBottomActionBarVisibility() {
+        if (mGridOptionViewModel.getBottomActionBarVisible()) {
             mBottomActionBar.show();
         } else {
             mBottomActionBar.hide();
diff --git a/src/com/android/customization/widget/OptionSelectorController.java b/src/com/android/customization/widget/OptionSelectorController.java
index 8e85c01..0f1b6a6 100644
--- a/src/com/android/customization/widget/OptionSelectorController.java
+++ b/src/com/android/customization/widget/OptionSelectorController.java
@@ -68,11 +68,13 @@
         void onOptionSelected(CustomizationOption selected);
     }
 
-    @IntDef({CheckmarkStyle.NONE, CheckmarkStyle.CORNER, CheckmarkStyle.CENTER})
+    @IntDef({CheckmarkStyle.NONE, CheckmarkStyle.CORNER, CheckmarkStyle.CENTER,
+            CheckmarkStyle.CENTER_CHANGE_COLOR_WHEN_NOT_SELECTED})
     public @interface CheckmarkStyle {
         int NONE = 0;
         int CORNER = 1;
         int CENTER = 2;
+        int CENTER_CHANGE_COLOR_WHEN_NOT_SELECTED = 3;
     }
 
     private static final float LINEAR_LAYOUT_HORIZONTAL_DISPLAY_OPTIONS_MAX = 4.35f;
@@ -114,8 +116,6 @@
         if (!mOptions.contains(option)) {
             throw new IllegalArgumentException("Invalid option");
         }
-        updateActivatedStatus(mSelectedOption, false);
-        updateActivatedStatus(option, true);
         T lastSelectedOption = mSelectedOption;
         mSelectedOption = option;
         mAdapter.notifyItemChanged(mOptions.indexOf(option));
@@ -149,38 +149,6 @@
         }
     }
 
-    private void updateActivatedStatus(T option, boolean isActivated) {
-        int index = mOptions.indexOf(option);
-        if (index < 0) {
-            return;
-        }
-        RecyclerView.ViewHolder holder = mContainer.findViewHolderForAdapterPosition(index);
-        if (holder != null && holder.itemView != null) {
-            holder.itemView.setActivated(isActivated);
-
-            if (holder instanceof TileViewHolder) {
-                TileViewHolder tileHolder = (TileViewHolder) holder;
-                if (isActivated) {
-                    if (option == mAppliedOption && mCheckmarkStyle != CheckmarkStyle.NONE) {
-                        tileHolder.setContentDescription(mContainer.getContext(), option,
-                            R.string.option_applied_previewed_description);
-                    } else {
-                        tileHolder.setContentDescription(mContainer.getContext(), option,
-                            R.string.option_previewed_description);
-                    }
-                } else if (option == mAppliedOption && mCheckmarkStyle != CheckmarkStyle.NONE) {
-                    tileHolder.setContentDescription(mContainer.getContext(), option,
-                        R.string.option_applied_description);
-                } else {
-                    tileHolder.resetContentDescription();
-                }
-            }
-        } else {
-            // Item is not visible, make sure the item is re-bound when it becomes visible
-            mAdapter.notifyItemChanged(index);
-        }
-    }
-
     /**
      * Notify that a given option has changed.
      * @param option the option that changed
@@ -226,7 +194,16 @@
                 }
                 holder.itemView.setActivated(option.equals(mSelectedOption));
                 option.bindThumbnailTile(holder.tileView);
-                holder.itemView.setOnClickListener(view -> setSelectedOption(option));
+                holder.itemView.setOnClickListener(view -> {
+                    setSelectedOption(option);
+                    String title = option.getTitle();
+                    int stringId = R.string.option_previewed_description;
+                    if (mSelectedOption.equals(mAppliedOption)) {
+                        stringId = R.string.option_applied_previewed_description;
+                    }
+                    CharSequence cd = holder.itemView.getContext().getString(stringId, title);
+                    view.announceForAccessibility(cd);
+                });
 
                 Resources res = mContainer.getContext().getResources();
                 if (mCheckmarkStyle == CheckmarkStyle.CORNER && option.equals(mAppliedOption)) {
@@ -235,19 +212,39 @@
                                     mContainer.getContext().getTheme()),
                             Gravity.BOTTOM | Gravity.RIGHT,
                             res.getDimensionPixelSize(R.dimen.check_size),
-                            res.getDimensionPixelOffset(R.dimen.check_offset));
+                            res.getDimensionPixelOffset(R.dimen.check_offset), true);
                 } else if (mCheckmarkStyle == CheckmarkStyle.CENTER
                         && option.equals(mAppliedOption)) {
                     drawCheckmark(option, holder,
                             res.getDrawable(R.drawable.check_circle_grey_large,
                                     mContainer.getContext().getTheme()),
                             Gravity.CENTER, res.getDimensionPixelSize(R.dimen.center_check_size),
-                            0);
+                            0, true);
+                }  else if (mCheckmarkStyle == CheckmarkStyle.CENTER_CHANGE_COLOR_WHEN_NOT_SELECTED
+                        && option.equals(mAppliedOption)) {
+                    int drawableRes = option.equals(mSelectedOption)
+                            ? R.drawable.check_circle_grey_large
+                            : R.drawable.check_circle_grey_large_not_select;
+                    drawCheckmark(option, holder,
+                            res.getDrawable(drawableRes,
+                                    mContainer.getContext().getTheme()),
+                            Gravity.CENTER, res.getDimensionPixelSize(R.dimen.center_check_size),
+                            0, option.equals(mSelectedOption));
                 } else if (option.equals(mAppliedOption)) {
                     // Initialize with "previewed" description if we don't show checkmark
                     holder.setContentDescription(mContainer.getContext(), option,
                         R.string.option_previewed_description);
                 } else if (mCheckmarkStyle != CheckmarkStyle.NONE) {
+                    if (mCheckmarkStyle == CheckmarkStyle.CENTER_CHANGE_COLOR_WHEN_NOT_SELECTED) {
+                        if (option.equals(mSelectedOption)) {
+                            holder.setContentDescription(mContainer.getContext(), option,
+                                    R.string.option_previewed_description);
+                        } else {
+                            holder.setContentDescription(mContainer.getContext(), option,
+                                    R.string.option_change_applied_previewed_description);
+                        }
+                    }
+
                     holder.tileView.setForeground(null);
                 }
             }
@@ -259,7 +256,7 @@
 
             private void drawCheckmark(CustomizationOption<?> option, TileViewHolder holder,
                     Drawable checkmark, int gravity, @Dimension int checkSize,
-                    @Dimension int checkOffset) {
+                    @Dimension int checkOffset, boolean currentlyPreviewed) {
                 Drawable frame = holder.tileView.getForeground();
                 Drawable[] layers = {frame, checkmark};
                 if (frame == null) {
@@ -277,8 +274,13 @@
                 holder.tileView.setForeground(checkedFrame);
 
                 // Initialize the currently applied option
-                holder.setContentDescription(mContainer.getContext(), option,
-                        R.string.option_applied_previewed_description);
+                if (currentlyPreviewed) {
+                    holder.setContentDescription(mContainer.getContext(), option,
+                            R.string.option_applied_previewed_description);
+                } else {
+                    holder.setContentDescription(mContainer.getContext(), option,
+                            R.string.option_applied_description);
+                }
             }
         };
 
diff --git a/src_override/com/android/wallpaper/module/WallpapersInjector.java b/src_override/com/android/wallpaper/module/WallpapersInjector.java
index f1748b4..f8a4182 100755
--- a/src_override/com/android/wallpaper/module/WallpapersInjector.java
+++ b/src_override/com/android/wallpaper/module/WallpapersInjector.java
@@ -72,8 +72,9 @@
             WallpaperInfo wallpaperInfo,
             int mode,
             boolean viewAsHome,
+            boolean viewFullScreen,
             boolean testingModeEnabled) {
-        return ImagePreviewFragment.newInstance(wallpaperInfo, mode, viewAsHome,
+        return ImagePreviewFragment.newInstance(wallpaperInfo, mode, viewAsHome, viewFullScreen,
                 testingModeEnabled);
     }