[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 6749343f10 -s ours

am skip reason: contains skip directive

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

Change-Id: I36efcf2a181c3d8733d73b0867b74d879b59c37d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index b973cf4..1c6d0d2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -35,7 +35,7 @@
         "androidx.lifecycle_lifecycle-runtime-ktx",
         "androidx.recyclerview_recyclerview",
         "androidx.slice_slice-view",
-        "androidx.transition_transition-ktx-nodeps",
+        "androidx.transition_transition-ktx",
         "androidx.viewpager2_viewpager2",
         "androidx.navigation_navigation-ui-ktx",
         "androidx.navigation_navigation-fragment-ktx",
@@ -56,6 +56,7 @@
         "SettingsLibActivityEmbedding",
         "monet",
         "hilt_android",
+        "accessibility_settings_flags_lib",
     ],
 
     resource_dirs: ["res"],
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index 281ae78..5c6b55d 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -1,7 +1,7 @@
 aconfig_declarations {
     name: "com_android_wallpaper_flags",
     package: "com.android.wallpaper",
-    container: "system",
+    container: "system_ext",
     srcs: ["customization_picker.aconfig"],
 }
 
diff --git a/aconfig/customization_picker.aconfig b/aconfig/customization_picker.aconfig
index bf1d760..80fa274 100644
--- a/aconfig/customization_picker.aconfig
+++ b/aconfig/customization_picker.aconfig
@@ -1,12 +1,5 @@
 package: "com.android.wallpaper"
-container: "system"
-
-flag {
-    name: "multi_crop_preview_ui_flag"
-    namespace: "customization_picker"
-    description: "Enables new preview UI if both the SysUI multi crop flag and this flag are true."
-    bug: "291761856"
-}
+container: "system_ext"
 
 flag {
     name: "wallpaper_restorer_flag"
diff --git a/res/drawable/ic_file_download.xml b/res/drawable/ic_file_download.xml
index 78ecd17..1c34024 100644
--- a/res/drawable/ic_file_download.xml
+++ b/res/drawable/ic_file_download.xml
@@ -18,7 +18,7 @@
     android:height="@dimen/wallpaper_control_icon_size"
     android:viewportHeight="@dimen/wallpaper_control_icon_viewport_size"
     android:viewportWidth="@dimen/wallpaper_control_icon_viewport_size"
-    android:tint="@color/wallpaper_control_button_ic_color_tint"
+    android:tint="?android:textColorPrimary"
     android:tintMode="multiply">
     <path
         android:fillColor="@android:color/white"
diff --git a/res/drawable/wallpaper_control_button_download.xml b/res/drawable/wallpaper_control_button_download.xml
index 343a0cb..0f330b9 100644
--- a/res/drawable/wallpaper_control_button_download.xml
+++ b/res/drawable/wallpaper_control_button_download.xml
@@ -15,6 +15,6 @@
      limitations under the License.
 -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/wallpaper_control_button_background" />
+    <item android:drawable="@drawable/wallpaper_control_button_off_background" />
     <item android:drawable="@drawable/ic_file_download" />
 </layer-list>
\ No newline at end of file
diff --git a/res/layout/activity_wallpaper_preview.xml b/res/layout/activity_wallpaper_preview.xml
index 72f1ca3..ad33cd3 100644
--- a/res/layout/activity_wallpaper_preview.xml
+++ b/res/layout/activity_wallpaper_preview.xml
@@ -20,5 +20,4 @@
     android:name="androidx.navigation.fragment.NavHostFragment"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    app:defaultNavHost="true"
-    app:navGraph="@navigation/wallpaper_preview_nav_graph" />
\ No newline at end of file
+    app:defaultNavHost="true"/>
\ No newline at end of file
diff --git a/res/layout/floating_sheet2.xml b/res/layout/floating_sheet2.xml
index c0637f1..64fcf06 100644
--- a/res/layout/floating_sheet2.xml
+++ b/res/layout/floating_sheet2.xml
@@ -35,7 +35,7 @@
             android:layout_width="match_parent"
             android:padding="@dimen/wallpaper_info_pane_padding"
             android:layout_marginHorizontal="@dimen/floating_sheet_margin"
-            android:layout_marginBottom="120dp"
+            android:layout_marginBottom="@dimen/floating_sheet_bottom_margin"
             android:background="@drawable/floating_sheet_background" />
     </FrameLayout>
 </androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/res/layout/fragment_full_preview.xml b/res/layout/fragment_full_preview.xml
index c32b050..092ac71 100644
--- a/res/layout/fragment_full_preview.xml
+++ b/res/layout/fragment_full_preview.xml
@@ -50,7 +50,7 @@
             android:background="@drawable/check_circle_full_preview"
             android:elevation="@dimen/wallpaper_preview_buttons_elevation"
             android:layout_marginEnd="@dimen/set_wallpaper_button_margin_end"
-            android:contentDescription="@string/show_preview_controls_action"
+            android:contentDescription="@string/full_preview_check_button_description"
             android:textColor="@color/system_on_primary"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintTop_toTopOf="@id/toolbar_container"
diff --git a/res/layout/fragment_small_preview_foldable.xml b/res/layout/fragment_small_preview_foldable.xml
index 2ea100b..2ca96a0 100644
--- a/res/layout/fragment_small_preview_foldable.xml
+++ b/res/layout/fragment_small_preview_foldable.xml
@@ -21,51 +21,67 @@
     android:id="@+id/container"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:transitionGroup="true">
 
     <include
         android:id="@+id/toolbar_container"
         layout="@layout/section_header_content"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        app:layout_constraintEnd_toStartOf="@id/button_set_wallpaper"
+        app:layout_constraintBottom_toTopOf="@+id/pager_group"
+        app:layout_constraintVertical_chainStyle="spread_inside" />
 
     <Button
         android:id="@+id/button_set_wallpaper"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:elevation="@dimen/wallpaper_preview_buttons_elevation"
         android:layout_marginEnd="@dimen/set_wallpaper_button_margin_end"
         android:background="@drawable/set_wallpaper_button_background_variant"
+        android:elevation="@dimen/wallpaper_preview_buttons_elevation"
+        android:gravity="center"
+        android:minHeight="@dimen/touch_target_min_height"
         android:text="@string/set_wallpaper_button_text"
         android:textColor="@color/system_on_primary"
         android:textAppearance="@style/WallpaperPicker.Preview.TextAppearance.NoAllCaps"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="@id/toolbar_container"
+        app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="@id/toolbar_container"/>
 
-    <com.android.wallpaper.picker.preview.ui.fragment.smallpreview.DualPreviewViewPager
-        android:id="@+id/dual_preview_pager"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingHorizontal="@dimen/small_dual_preview_edge_space"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"/>
-
-    <com.android.wallpaper.picker.preview.ui.fragment.smallpreview.views.TabsPagerContainer
-        android:id="@+id/pager_container"
+    <LinearLayout
+        android:id="@+id/pager_group"
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:clipChildren="false"
-        android:clipToPadding="false"
-        android:layout_marginTop="@dimen/spacing_10dp"
-        app:layout_constraintTop_toBottomOf="@id/dual_preview_pager"
+        android:paddingBottom="@dimen/wallpaper_control_button_size"
+        android:gravity="center"
+        android:importantForAccessibility="no"
+        android:orientation="vertical"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/toolbar_container"
+        app:layout_constraintBottom_toBottomOf="parent">
+
+        <com.android.wallpaper.picker.preview.ui.fragment.smallpreview.DualPreviewViewPager
+            android:id="@+id/dual_preview_pager"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="bottom"
+            android:paddingHorizontal="@dimen/small_dual_preview_edge_space"
+            android:importantForAccessibility="no" />
+
+        <com.android.wallpaper.picker.preview.ui.fragment.smallpreview.views.TabsPagerContainer
+            android:id="@+id/pager_container"
+            android:importantForAccessibility="no"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:layout_marginTop="@dimen/spacing_10dp"
+            android:layout_marginBottom="@dimen/spacing_10dp" />
+    </LinearLayout>
 
     <com.android.wallpaper.picker.preview.ui.view.PreviewActionFloatingSheet
         android:id="@+id/floating_sheet"
@@ -77,8 +93,10 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/wallpaper_control_button_group_margin_end"
+        android:layout_marginTop="@dimen/wallpaper_control_button_group_margin_top"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"/>
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintVertical_weight="1" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/res/layout/fragment_small_preview_handheld.xml b/res/layout/fragment_small_preview_handheld.xml
index a255ace..7596c22 100644
--- a/res/layout/fragment_small_preview_handheld.xml
+++ b/res/layout/fragment_small_preview_handheld.xml
@@ -22,7 +22,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:transitionGroup="true">
 
     <include
         android:id="@+id/toolbar_container"
@@ -37,9 +38,11 @@
         android:id="@+id/button_set_wallpaper"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:elevation="@dimen/wallpaper_preview_buttons_elevation"
         android:layout_marginEnd="@dimen/set_wallpaper_button_margin_end"
         android:background="@drawable/set_wallpaper_button_background_variant"
+        android:elevation="@dimen/wallpaper_preview_buttons_elevation"
+        android:gravity="center"
+        android:minHeight="@dimen/touch_target_min_height"
         android:text="@string/set_wallpaper_button_text"
         android:textColor="@color/system_on_primary"
         android:textAppearance="@style/WallpaperPicker.Preview.TextAppearance.NoAllCaps"
diff --git a/res/layout/full_wallpaper_preview_card.xml b/res/layout/full_wallpaper_preview_card.xml
index 624de83..1112830 100644
--- a/res/layout/full_wallpaper_preview_card.xml
+++ b/res/layout/full_wallpaper_preview_card.xml
@@ -17,8 +17,7 @@
 <com.android.wallpaper.picker.preview.ui.view.FullPreviewFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/wallpaper_preview_crop"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_gravity="center">
+    android:layout_height="match_parent">
 
     <androidx.cardview.widget.CardView
         android:id="@+id/preview_card"
@@ -26,9 +25,10 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:clipChildren="true"
-        android:contentDescription="@string/wallpaper_preview_card_content_description">
+        android:contentDescription="@string/wallpaper_preview_card_content_description"
+        android:layout_gravity="center">
 
-        <com.android.wallpaper.picker.preview.ui.view.SystemScaledWallpaperPreviewSurfaceView
+        <SurfaceView
             android:id="@+id/wallpaper_surface"
             android:layout_width="match_parent"
             android:layout_height="match_parent" />
@@ -38,6 +38,15 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:importantForAccessibility="noHideDescendants" />
+
+        <View
+            android:id="@+id/preview_scrim"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@drawable/gradient_black_scrim"
+            android:importantForAccessibility="noHideDescendants"
+            android:visibility="gone" />
     </androidx.cardview.widget.CardView>
 
+
 </com.android.wallpaper.picker.preview.ui.view.FullPreviewFrameLayout>
diff --git a/res/layout/fullscreen_wallpaper_preview_old.xml b/res/layout/fullscreen_wallpaper_preview_old.xml
new file mode 100644
index 0000000..40f7193
--- /dev/null
+++ b/res/layout/fullscreen_wallpaper_preview_old.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2020 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id="@+id/low_res_image"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:scaleType="centerCrop"
+        android:background="?android:colorBackground" />
+
+    <com.android.wallpaper.picker.preview.ui.view.SystemScaledSubsamplingScaleImageView
+        android:id="@+id/full_res_image"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/grid_item_category.xml b/res/layout/grid_item_category.xml
index 04cb5f1..60f63e4 100755
--- a/res/layout/grid_item_category.xml
+++ b/res/layout/grid_item_category.xml
@@ -17,6 +17,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/tile"
+    android:importantForAccessibility="no"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">
@@ -25,6 +26,7 @@
         android:id="@+id/category"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+        android:importantForAccessibility="no"
         android:foreground="?attr/selectableItemBackground"
         app:cardCornerRadius="?android:dialogCornerRadius"
         app:cardElevation="0dp">
diff --git a/res/layout/my_photos.xml b/res/layout/my_photos.xml
index 52b5b97..441c8cc 100644
--- a/res/layout/my_photos.xml
+++ b/res/layout/my_photos.xml
@@ -20,22 +20,26 @@
     android:id="@+id/tile_group"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:focusable="false"
     android:orientation="vertical"
     android:layout_marginTop="10dp"
-    android:importantForAccessibility="no">
+    android:importantForAccessibility="yes">
 
     <TextView
         android:id="@+id/tile_title"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:contentDescription="@string/choose_a_wallpaper_section_title"
         android:text="@string/choose_a_wallpaper_section_title"
         android:textAppearance="@style/CategorySectionTitleTextAppearance"
+        android:focusable="false"
         android:layout_gravity="bottom" />
 
     <include android:id="@+id/tile"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="20dp"
+        android:focusable="true"
         layout="@layout/grid_item_category">
     </include>
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/preview_customize_settings2.xml b/res/layout/preview_customize_settings2.xml
new file mode 100644
index 0000000..eeae7bf
--- /dev/null
+++ b/res/layout/preview_customize_settings2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2024 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="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="@dimen/floating_sheet_customize_content_min_height"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <!-- TODO(b/179127651): Figure out where these slices are generated to update them -->
+    <androidx.slice.widget.SliceView
+        android:id="@+id/settings_slice"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/res/layout/set_wallpaper_dialog.xml b/res/layout/set_wallpaper_dialog.xml
index 41917c2..8105e6c 100644
--- a/res/layout/set_wallpaper_dialog.xml
+++ b/res/layout/set_wallpaper_dialog.xml
@@ -14,70 +14,77 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
 -->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:paddingStart="@dimen/spacing_8dp"
-    android:paddingEnd="@dimen/spacing_8dp"
-    android:paddingBottom="@dimen/set_wallpaper_dialog_bottom_padding">
-
-    <TextView
-        android:id="@+id/title"
-        style="@style/TextAppearance.SetWallpaperDialog.Title"
+    android:overScrollMode="never">
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="@string/set_wallpaper_button_text"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent" />
+        android:paddingStart="@dimen/spacing_8dp"
+        android:paddingEnd="@dimen/spacing_8dp"
+        android:paddingBottom="@dimen/set_wallpaper_dialog_bottom_padding"
+        android:layout_gravity="center_horizontal">
 
-    <FrameLayout
-        android:id="@+id/preview_container"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        app:layout_constraintTop_toBottomOf="@+id/title"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent">
-        <include layout="@layout/set_wallpaper_dialog_foldable_preview"
-            android:id="@+id/foldable_previews"
+        <TextView
+            android:id="@+id/title"
+            style="@style/TextAppearance.SetWallpaperDialog.Title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingTop="@dimen/abc_dialog_title_divider_material"
-            android:paddingBottom="@dimen/abc_dialog_title_divider_material"
-            android:visibility="gone">
-        </include>
-        <include layout="@layout/set_wallpaper_dialog_handheld_preview"
-            android:id="@+id/handheld_previews"
-            android:layout_width="@dimen/set_wallpaper_dialog_handheld_width"
+            android:text="@string/set_wallpaper_button_text"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent" />
+
+        <FrameLayout
+            android:id="@+id/preview_container"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingTop="@dimen/abc_dialog_title_divider_material"
-            android:paddingBottom="@dimen/abc_dialog_title_divider_material"
-            android:visibility="gone">
-        </include>
-    </FrameLayout>
+            app:layout_constraintTop_toBottomOf="@+id/title"
+            app:layout_constraintBottom_toTopOf="@+id/button_set"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent">
+            <include layout="@layout/set_wallpaper_dialog_foldable_preview"
+                android:id="@+id/foldable_previews"
+                android:layout_width="@dimen/set_wallpaper_dialog_foldable_content_width"
+                android:layout_height="wrap_content"
+                android:paddingTop="@dimen/abc_dialog_title_divider_material"
+                android:paddingBottom="@dimen/abc_dialog_title_divider_material"
+                android:visibility="gone"/>
+            <include layout="@layout/set_wallpaper_dialog_handheld_preview"
+                android:id="@+id/handheld_previews"
+                android:layout_width="@dimen/set_wallpaper_dialog_handheld_content_width"
+                android:layout_height="wrap_content"
+                android:paddingTop="@dimen/abc_dialog_title_divider_material"
+                android:paddingBottom="@dimen/abc_dialog_title_divider_material"
+                android:visibility="gone"/>
+        </FrameLayout>
 
-    <Button
-        android:id="@+id/button_set"
-        style="@style/SetWallpaperDialog.Button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/set_wallpaper_dialog_set_button"
-        android:layout_marginVertical="@dimen/set_wallpaper_dialog_button_margin_vertical"
-        app:layout_constraintTop_toBottomOf="@id/preview_container"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        <Button
+            android:id="@+id/button_set"
+            style="@style/SetWallpaperDialog.Button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginVertical="@dimen/set_wallpaper_dialog_button_margin_vertical"
+            android:gravity="center"
+            android:minHeight="@dimen/touch_target_min_height"
+            android:text="@string/set_wallpaper_dialog_set_button"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
 
-    <Button
-        android:id="@+id/button_cancel"
-        style="@style/SetWallpaperDialog.Button.OutlinedButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/cancel"
-        android:layout_marginEnd="@dimen/spacing_8dp"
-        android:layout_marginVertical="@dimen/set_wallpaper_dialog_button_margin_vertical"
-        app:layout_constraintTop_toBottomOf="@id/preview_container"
-        app:layout_constraintEnd_toStartOf="@+id/button_set"/>
+        <Button
+            android:id="@+id/button_cancel"
+            style="@style/SetWallpaperDialog.Button.OutlinedButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/spacing_8dp"
+            android:layout_marginVertical="@dimen/set_wallpaper_dialog_button_margin_vertical"
+            android:gravity="center"
+            android:minHeight="@dimen/touch_target_min_height"
+            android:text="@string/cancel"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@+id/button_set"/>
 
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</ScrollView>
diff --git a/res/layout/set_wallpaper_dialog_foldable_preview.xml b/res/layout/set_wallpaper_dialog_foldable_preview.xml
index 71471ec..65cc955 100644
--- a/res/layout/set_wallpaper_dialog_foldable_preview.xml
+++ b/res/layout/set_wallpaper_dialog_foldable_preview.xml
@@ -22,13 +22,16 @@
     <include layout="@layout/small_preview_foldable_card_view_selector"
         android:id="@+id/lock_preview_selector"
         android:layout_width="@dimen/set_wallpaper_dialog_foldable_preview_width"
-        android:layout_height="match_parent"/>
+        android:layout_height="match_parent"
+        android:layout_gravity="center_horizontal"/>
     <TextView
         style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:labelFor="@+id/lock_preview_selector"
         android:layout_gravity="center_horizontal"
-        android:text="@string/set_wallpaper_lock_screen_destination"/>
+        android:text="@string/set_wallpaper_lock_screen_destination"
+        android:maxWidth="@dimen/set_wallpaper_dialog_foldable_preview_width"/>
 
     <android.widget.Space
         android:layout_width="match_parent"
@@ -37,12 +40,15 @@
     <include layout="@layout/small_preview_foldable_card_view_selector"
         android:id="@+id/home_preview_selector"
         android:layout_width="@dimen/set_wallpaper_dialog_foldable_preview_width"
-        android:layout_height="match_parent"/>
+        android:layout_height="match_parent"
+        android:layout_gravity="center_horizontal"/>
     <TextView
         style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
         android:layout_width="wrap_content"
+        android:labelFor="@+id/home_preview_selector"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
-        android:text="@string/set_wallpaper_home_screen_destination"/>
+        android:text="@string/set_wallpaper_home_screen_destination"
+        android:maxWidth="@dimen/set_wallpaper_dialog_foldable_preview_width"/>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/set_wallpaper_dialog_handheld_preview.xml b/res/layout/set_wallpaper_dialog_handheld_preview.xml
index d82e438..b79642f 100644
--- a/res/layout/set_wallpaper_dialog_handheld_preview.xml
+++ b/res/layout/set_wallpaper_dialog_handheld_preview.xml
@@ -34,7 +34,9 @@
         style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:labelFor="@+id/lock_preview_selector"
         android:text="@string/set_wallpaper_lock_screen_destination"
+        android:maxWidth="@dimen/set_wallpaper_dialog_handheld_preview_width"
         app:layout_constraintTop_toBottomOf="@id/lock_preview_selector"
         app:layout_constraintStart_toStartOf="@+id/lock_preview_selector"
         app:layout_constraintEnd_toEndOf="@+id/lock_preview_selector"/>
@@ -53,7 +55,9 @@
         style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:labelFor="@+id/home_preview_selector"
         android:text="@string/set_wallpaper_home_screen_destination"
+        android:maxWidth="@dimen/set_wallpaper_dialog_handheld_preview_width"
         app:layout_constraintTop_toBottomOf="@id/home_preview_selector"
         app:layout_constraintStart_toStartOf="@+id/home_preview_selector"
         app:layout_constraintEnd_toEndOf="@+id/home_preview_selector"/>
diff --git a/res/layout/set_wallpaper_progress_dialog_view.xml b/res/layout/set_wallpaper_progress_dialog_view.xml
new file mode 100644
index 0000000..80df67e
--- /dev/null
+++ b/res/layout/set_wallpaper_progress_dialog_view.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 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"
+    style="@style/LightDialogTheme"
+    android:orientation="horizontal"
+    android:gravity="center_vertical"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:padding="@dimen/set_wallpaper_progress_dialog_padding">
+
+    <ProgressBar
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/set_wallpaper_progress_dialog_progress_bar_margin_end"/>
+
+    <TextView
+        android:id="@+id/set_wallpaper_progress_dialog_text"
+        android:textAppearance="?android:textAppearance"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/set_wallpaper_progress_message" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/small_preview_foldable_card_view_selector.xml b/res/layout/small_preview_foldable_card_view_selector.xml
index c5e295e..0793c1d 100644
--- a/res/layout/small_preview_foldable_card_view_selector.xml
+++ b/res/layout/small_preview_foldable_card_view_selector.xml
@@ -26,7 +26,8 @@
 
         <FrameLayout
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content">
+            android:layout_height="wrap_content"
+            android:importantForAccessibility="noHideDescendants">
             <include
                 android:id="@+id/small_preview_folded_preview"
                 layout="@layout/small_wallpaper_preview_card"
@@ -65,7 +66,6 @@
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
                 android:background="@drawable/set_wallpaper_dialog_preview_selector"/>
-
         </FrameLayout>
 
     </com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout>
diff --git a/res/layout/wallpaper_info_view2.xml b/res/layout/wallpaper_info_view2.xml
index 737a822..ca41219 100644
--- a/res/layout/wallpaper_info_view2.xml
+++ b/res/layout/wallpaper_info_view2.xml
@@ -19,6 +19,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:divider="@drawable/horizontal_divider_8dp"
+    android:textDirection="locale"
     android:orientation="vertical">
 
     <TextView
@@ -51,5 +52,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/explore"
+        android:minHeight="@dimen/touch_target_min_height"
         android:visibility="gone" />
 </LinearLayout>
diff --git a/res/navigation/wallpaper_preview_nav_graph.xml b/res/navigation/wallpaper_preview_nav_graph.xml
index a6bb666..298d8f8 100644
--- a/res/navigation/wallpaper_preview_nav_graph.xml
+++ b/res/navigation/wallpaper_preview_nav_graph.xml
@@ -16,7 +16,7 @@
 <navigation xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/wallpaper_preview_nav_graph"
-    app:startDestination="@id/smallPreviewFragment">
+    app:startDestination="@+id/smallPreviewFragment">
 
     <fragment
         android:id="@+id/smallPreviewFragment"
@@ -26,13 +26,16 @@
             app:destination="@+id/fullPreviewFragment" />
         <action
             android:id="@+id/action_smallPreviewFragment_to_setWallpaperDialog"
-            app:destination="@id/setWallpaperDialog" />
+            app:destination="@+id/setWallpaperDialog" />
+        <action
+            android:id="@+id/action_smallPreviewFragment_to_creativeEditPreviewFragment"
+            app:destination="@+id/creativeEditPreviewFragment" />
     </fragment>
     <fragment
-        android:id="@+id/creativeNewPreviewFragment"
-        android:name="com.android.wallpaper.picker.preview.ui.fragment.CreativeNewPreviewFragment">
+        android:id="@+id/creativeEditPreviewFragment"
+        android:name="com.android.wallpaper.picker.preview.ui.fragment.CreativeEditPreviewFragment">
         <action
-            android:id="@+id/action_creativeNewPreviewFragment_to_smallPreviewFragment"
+            android:id="@+id/action_creativeEditPreviewFragment_to_smallPreviewFragment"
             app:destination="@+id/smallPreviewFragment" />
     </fragment>
     <fragment
@@ -42,5 +45,8 @@
     <dialog
         android:id="@+id/setWallpaperDialog"
         android:name="com.android.wallpaper.picker.preview.ui.fragment.SetWallpaperDialogFragment">
+        <action
+            android:id="@+id/action_setWallpaperDialog_self"
+            app:destination="@+id/setWallpaperDialog" />
     </dialog>
 </navigation>
\ No newline at end of file
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 8a1324c..06d9fec 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Herlaai daaglikse tuisskermmuurpapier"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Herlaai daaglikse muurpapier"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Muurpapiervoorskouskerm"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Klaar muurpapier geredigeer"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Herlaai tans daaglikse muurpapier …"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Kon nie daaglikse muurpapier herlaai nie. Gaan jou netwerkverbinding na en probeer weer."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Muurpapiere op toestel"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 4d0e868..fed9820 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"የዕለታዊ መነሻ ማያ ገፅ ልጣፍን ያድሱ"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"ዕለታዊ ልጣፍን ያድሱ"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"የልጣፍ ቅድመ ዕይታ ማያ ገጽ"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"የልጣፍ አርትዖት ተከናውኗል"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"ዕለታዊ ልጣፍን በማደስ ላይ…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"ዕለታዊ ልጣፍን ማደስ አልተሳካም። እባክዎ የእርስዎን የአውታረ መረብ ግንኙነት ይፈትሹ እና እንደገና ይሞክሩ።"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"የመሣሪያ ላይ ልጣፎች"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 21586fa..948ba2f 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"إعادة تحميل خلفية الشاشة الرئيسية اليومية"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"إعادة تحميل الخلفية اليومية"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"شاشة معاينة الخلفية"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"تم تعديل الخلفية"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"تجري إعادة تحميل الخلفية اليومية…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"تعذّرت إعادة تحميل الخلفية اليومية. يُرجى التحقق من اتصالك بالشبكة وإعادة المحاولة."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"خلفيات على الجهاز"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index f8497f3..aab9cfd 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"গৃহ স্ক্ৰীনৰ দৈনিক ৱালপেপাৰ ৰিফ্ৰেশ্ব কৰক"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"দৈনিক ৱালপেপাৰ ৰিফ্ৰেশ্ব কৰক"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"ৱালপেপাৰৰ পূৰ্বদৰ্শনৰ স্ক্ৰীন"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"ৱালপেপাৰ সম্পাদনা কৰি হ’ল"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"দৈনিক ৱালপেপাৰ ৰিফ্ৰেশ্ব কৰি থকা হৈছে …"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"দৈনিক ৱালপেপাৰ ৰিফ্ৰেশ্ব কৰিব পৰা নগ\'ল। অনুগ্ৰহ কৰি আপোনাৰ নেটৱর্ক সংযোগ পৰীক্ষা কৰক আৰু আকৌ চেষ্টা কৰক।"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ডিভাইচত থকা ৱালপেপাৰ"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index d206b65..7ba8b60 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Əsas ekranın divar kağızını gündəlik yeniləyin"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Divar kağızını gündəlik yeniləyin"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Divar kağızını önizləmə ekranı"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Divar kağızı redaktə edildi"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Günlük divar kağızı yenilənir..."</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Gündəlik divar kağızını yeniləmək olmadı. Şəbəkəni yoxlayın və yenidən cəhd edin."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Cihazdakı divar kağızları"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 847506f..212dcf0 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Osveži dnevnu pozadinu za početni ekran"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Osveži dnevnu pozadinu"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Ekran prikaza pozadine"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Izmene pozadine su završene"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Dnevna pozadina se osvežava…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Osvežavanje dnevne pozadine nije uspelo. Proverite mrežnu vezu i probajte ponovo."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Pozadine na uređaju"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index e4e7d04..132b975 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Абнавіць шпалеры галоўнага экрана на кожны дзень"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Абнавіць шпалеры на кожны дзень"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Экран перадпрагляду шпалер"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Рэдагаванне шпалер завершана"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Абнаўленне шпалер на кожны дзень…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Не атрымалася абнавіць шпалеры на кожны дзень. Спраўдзіце падключэнне да сеткі і паўтарыце спробу."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Шпалеры на прыладзе"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index df706e3..c3c722a 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Опресняване на тапета за деня на началния екран"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Опресняване на тапета за деня"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Екран за визуализация на тапета"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Край на редактирането на тапета"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Тапетът за деня се опреснява…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Опресняването на тапета за деня не бе успешно. Моля, проверете връзката си с мрежата и опитайте отново."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Тапети, съхранявани на у-вото"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 707487c..01d3fcf 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"প্রতিদিনের হোম স্ক্রিন ওয়ালপেপার রিফ্রেশ করুন"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"প্রতিদিনের ওয়ালপেপার রিফ্রেশ করুন"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"ওয়ালপেপার প্রিভিউ স্ক্রিন"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"ওয়ালপেপার এডিট করা হয়ে গেছে"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"প্রতিদিনের ওয়ালপেপার রিফ্রশ করা হচ্ছে…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"প্রতিদিনের ওয়ালপেপার রিফ্রেশ করা গেল না। অনুগ্রহ করে আপনার কানেকশন যাচাই করে আবার চেষ্টা করুন।"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ডিভাইসে থাকা ওয়ালপেপার"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 38e2d6e..d1550a0 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Osvježite dnevnu pozadinsku sliku na početnom ekranu"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Osvježite dnevnu pozadinsku sliku"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Ekran pregleda pozadinske slike"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Gotovo je uređivanje pozadinske slike"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Osvježavanje dnevne pozadinske slike…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Osvježavanje dnevne pozadinske slike nije uspjelo. Provjerite vezu s mrežom i pokušajte ponovo."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Pozadinske slike na uređaju"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index e03efb4..50e9bff 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Actualitza el fons de pantalla diari de la pantalla d\'inici"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Actualitza el fons de pantalla diari"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Pantalla de previsualització del fons de pantalla"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"He acabat d\'editar el fons de pantalla"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"S\'està actualitzant el fons de pantalla diari…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"No s\'ha pogut actualitzar el fons de pantalla diari. Comprova la connexió a la xarxa i torna-ho a provar."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Fons de pantalla del dispositiu"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 0285c47..1bf3819 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Obnovit denní tapetu plochy"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Obnovit denní tapetu"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Obrazovka náhledu tapety"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Úprava tapety je dokončena"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Obnovování denní tapety…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Denní tapetu se nepodařilo obnovit. Zkontrolujte připojení k síti a zkuste to znovu."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Tapety v zařízení"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 3f503e4..c36b973 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Opdater daglig baggrund på startskærmen"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Opdater daglig baggrund"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Skærm til forhåndsvisning af baggrund"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Redigering af baggrund er udført"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Opdaterer daglig baggrund…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Opdateringen af din daglige baggrund mislykkedes. Tjek din netværksforbindelse, og prøv igen."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Baggrunde på enheden"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 8501057..8d788b1 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Täglichen Hintergrund des Startbildschirms aktualisieren"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Täglichen Hintergrund aktualisieren"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Vorschau für Bildschirmhintergrund"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Bearbeitung des Hintergrunds abgeschlossen"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Täglicher Hintergrund wird aktualisiert…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Aktualisierung des täglichen Hintergrunds fehlgeschlagen. Prüfe die Netzwerkverbindung und versuche es noch einmal."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Hintergründe auf dem Gerät"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index afcb36a..ced134f 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Ανανέωση ημερήσιας ταπετσαρίας αρχικής οθόνης"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Ανανέωση ημερήσιας ταπετσαρίας"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Οθόνη προεπισκόπησης ταπετσαρίας"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Η επεξεργασία της ταπετσαρίας ολοκληρώθηκε"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Ανανέωση ημερήσιας ταπετσαρίας…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Αποτυχία ανανέωσης ημερήσιας ταπετσαρίας. Ελέγξτε τη σύνδεση δικτύου σας και δοκιμάστε ξανά."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Ταπετσαρίες στη συσκευή"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index f3dca5e..e637345 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Refresh daily home screen wallpaper"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Refresh daily wallpaper"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Wallpaper preview screen"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Done editing wallpaper"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Refreshing daily wallpaper…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Failed to refresh daily wallpaper. Please check your network connection and try again."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"On-device wallpapers"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index e9bec55..c658dfe 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -71,6 +71,12 @@
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Refresh daily wallpaper"</string>
     <!-- no translation found for preview_screen_description (3386387053327775919) -->
     <skip />
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <!-- no translation found for full_preview_check_button_description (700484353763952975) -->
+    <skip />
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Refreshing daily wallpaper…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Failed to refresh daily wallpaper. Please check your network connection and try again."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"On-device wallpapers"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index f3dca5e..e637345 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Refresh daily home screen wallpaper"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Refresh daily wallpaper"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Wallpaper preview screen"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Done editing wallpaper"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Refreshing daily wallpaper…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Failed to refresh daily wallpaper. Please check your network connection and try again."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"On-device wallpapers"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index f3dca5e..e637345 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Refresh daily home screen wallpaper"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Refresh daily wallpaper"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Wallpaper preview screen"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Done editing wallpaper"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Refreshing daily wallpaper…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Failed to refresh daily wallpaper. Please check your network connection and try again."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"On-device wallpapers"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index bfefc9d..4f45c14 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -67,6 +67,9 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎Refresh daily home screen wallpaper‎‏‎‎‏‎"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎Refresh daily wallpaper‎‏‎‎‏‎"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎Wallpaper preview screen‎‏‎‎‏‎"</string>
+    <string name="folded_device_state_description" msgid="4972608448265616264">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎Folded‎‏‎‎‏‎"</string>
+    <string name="unfolded_device_state_description" msgid="3071975681472460627">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‎Unfolded‎‏‎‎‏‎"</string>
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎Done editing wallpaper‎‏‎‎‏‎"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‎Refreshing daily wallpaper…‎‏‎‎‏‎"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎Failed to refresh daily wallpaper. Please check your network connection and try again.‎‏‎‎‏‎"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‎‎‎On-device wallpapers‎‏‎‎‏‎"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 5308783..54ef733 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Actualiza el fondo diario de la pantalla principal"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Actualiza el fondo de pantalla diario"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Pantalla de vista previa del fondo de pantalla"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Dejar de editar el fondo de pantalla"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Actualizando fondo de pantalla diario…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"No se pudo actualizar el fondo de pantalla diario. Comprueba tu conexión de red y vuelve a intentarlo."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Fondos del dispositivo"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index d3a6bce..da11fe7 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Actualizar el fondo de la pantalla de inicio diario"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Actualizar el fondo de pantalla diario"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Pantalla de vista previa del fondo de pantalla"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Dejar de editar fondo de pantalla"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Actualizando el fondo de pantalla diario…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"No se ha podido actualizar el fondo de pantalla diario. Comprueba tu conexión a Internet y vuelve a intentarlo."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Fondos pantalla en dispositivo"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 5ab6284..b8df98b 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Avaekraani päeva taustapildi värskendamine"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Päeva taustapildi värskendamine"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Taustapildi eelvaatekuva"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Olen taustapildi muutmisega valmis"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Päeva taustapildi värskendamine …"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Päeva taustapildi värskendamine ebaõnnestus. Kontrollige võrguühendust ja proovige uuesti."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Seadmes olevad taustapildid"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index a0797e9..7c0857d 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Freskatu orri nagusiaren eguneko horma-papera"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Freskatu eguneko horma-papera"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Horma-paperaren aurrebistaren pantaila"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Amaitu da horma-papera editatzeko prozesua"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Eguneko horma-papera freskatzen…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Ezin izan da freskatu eguneko horma-papera. Egiaztatu sarera konektatuta zaudela eta saiatu berriro."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Gailuko horma-paperak"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 22b1547..e2b2722 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"بازآوری کاغذدیواری روزانه در صفحه اصلی"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"بازآوری کاغذدیواری روزانه"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"صفحه پیش‌نمای کاغذدیواری"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"پایان ویرایش کاغذدیواری"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"درحال بازآوری کاغذدیواری روزانه…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"کاغذدیواری روزانه بازآوری نشد. لطفاً اتصال شبکه‌تان را بررسی و دوباره امتحان کنید."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"کاغذدیواری‌های موجود در دستگاه"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 2cf1c7f..2e9933e 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Päivitä etusivun päivittäinen taustakuva."</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Siirry seuraavaan taustakuvaan"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Taustakuvan esikatselunäkymä"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Taustakuvan muokkaus valmis"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Päivitetään päivän taustakuvaa…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Päivän taustakuvan päivittäminen epäonnistui. Tarkista verkkoasetukset ja yritä uudelleen."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Laitteella olevat taustakuvat"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index cf4a84e..3d4c445 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Actualiser le fond d\'écran quotidien de l\'écran d\'accueil"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Actualiser le fond d\'écran quotidien"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Écran d\'aperçu du fond d\'écran"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Terminer la modification du fond d\'écran"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Actualisation du fond d\'écran quotidien en cours…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Échec de l\'actualisation du fond d\'écran quotidien. Veuillez vérifier votre connexion réseau, puis réessayer."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Fonds d\'écran sur l\'appareil"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index ad665fe..6acf8b7 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Actualiser le fond d\'écran quotidien de l\'écran d\'accueil"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Actualiser le fond d\'écran quotidien"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Écran d\'aperçu des fonds d\'écran"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Modification du fond d\'écran terminée"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Actualisation du fond d\'écran quotidien…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Échec de l\'actualisation du fond d\'écran quotidien. Veuillez vérifier votre connexion réseau, puis réessayer."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Fonds d\'écran sur l\'appareil"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index ce8f5da..310d13a 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Actualiza o fondo de pantalla diario para a pantalla de inicio"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Actualiza o fondo de pantalla diario"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Pantalla de vista previa do fondo de pantalla"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Acabouse de editar o fondo de pantalla"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Actualizando fondo de pantalla diario…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Produciuse un erro ao actualizar o fondo de pantalla diario. Comproba a conexión de rede e téntao de novo."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Fondos no dispositivo"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index d6e27de..a00a406 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"દૈનિક હોમ સ્ક્રીન વૉલપેપર રિફ્રેશ કરો"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"દૈનિક વૉલપેપર રિફ્રેશ કરો"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"વૉલપેપરનો પ્રીવ્યૂ બતાવતી સ્ક્રીન"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"વૉલપેપરમાં ફેરફાર કરવાનું કામ પૂરું થયું"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"દૈનિક વૉલપેપર રિફ્રેશ કરી રહ્યાં છીએ…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"દૈનિક વૉલપેપર રિફ્રેશ કરવામાં નિષ્ફળ રહ્યાં. કૃપા કરીને તમારું નેટવર્ક કનેક્શન ચેક કરો અને ફરી પ્રયાસ કરો."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ઉપકરણ પરના વૉલપેપર"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index a824c90..4d559ea 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"होम स्क्रीन का रोज़ बदलने वाला वॉलपेपर रीफ़्रेश करें"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"रोज़ बदलने वाला वॉलपेपर रीफ़्रेश करें"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"स्क्रीन पर दिखने वाले वॉलपेपर की झलक"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"वॉलपेपर में बदलाव हो गया"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"रोज़ बदलने वाला वॉलपेपर रीफ़्रेश हो रहा है…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"रोज़ बदलने वाला वॉलपेपर रीफ़्रेश नहीं हो पा रहा है. कृपया अपना इंटरनेट कनेक्शन जाँचें और फिर से कोशिश करें."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"डिवाइस पर पहले से मौजूद वॉलपेपर"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 0f8057b..3abe68f 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Osvježi dnevnu pozadinu početnog zaslona"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Osvježi dnevnu pozadinu"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Zaslon pregleda pozadine"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Dovršeno je uređivanje pozadine"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Osvježavanje dnevne pozadine…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Osvježavanje dnevne pozadine nije uspjelo. Provjerite mrežnu vezu i pokušajte ponovo."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Pozadine na uređaju"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index fe8312c..c3ec937 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"A kezdőképernyő napi háttérképének frissítése"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Napi háttérkép frissítése"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Háttérkép előnézeti képernyője"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Háttérkép szerkesztésének befejezése"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Napi háttérkép frissítése…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Nem sikerült frissíteni a napi háttérképet. Ellenőrizze hálózati kapcsolatát, majd próbálkozzon újra."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Eszközön lévő háttérképek"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 4115b2e..5386e1b 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Թարմացնել հիմնական էկրանի օրվա պաստառը"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Թարմացնել օրվա պաստառը"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Պաստառի նախադիտման էկրան"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Ավարտել պաստառի խմբագրումը"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Օրվա պաստառը թարմացվում է…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Չհաջողվեց թարմացնել օրվա պաստառը: Ստուգեք ինտերնետ կապը և նորից փորձեք:"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Սարքում պահված պաստառներ"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 8d5caa9..7e731a3 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Muat ulang wallpaper layar utama harian"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Muat ulang wallpaper harian"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Layar pratinjau wallpaper"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Selesai mengedit wallpaper"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Memuat ulang wallpaper harian…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Gagal memuat ulang wallpaper harian. Harap periksa koneksi jaringan Anda dan coba lagi."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Wallpaper di perangkat"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 2c88685..75ba708 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Uppfæra daglegt veggfóður á heimaskjá"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Uppfæra daglegt veggfóður"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Forskoðunarskjár veggfóðurs"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Búið að breyta veggfóðri"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Uppfærir daglegt veggfóður…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Ekki tókst að endurnýja daglegt veggfóður. Athugaðu nettenginguna og reyndu aftur."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Veggfóður í tækinu"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index c29404b..49b31f3 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Aggiorna lo sfondo giornaliero della schermata Home"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Aggiorna lo sfondo giornaliero"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Schermata di anteprima sfondo"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Modifica sfondo completata"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Aggiornamento dello sfondo giornaliero…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Impossibile aggiornare lo sfondo giornaliero. Controlla la connessione di rete e riprova."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Sfondi sul dispositivo"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 681af26..2e1b9f8 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"רענון הטפט היומי של מסך הבית"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"רענון הטפט היומי"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"מסך התצוגה המקדימה של הטפט"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"סיימתי לערוך את הטפט"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"מרענן את הטפט היומי..."</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"רענון הטפט היומי נכשל. יש לבדוק את החיבור לרשת ולנסות שוב."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"טפטים במכשיר"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index e4a5606..b8f31b2 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"ホーム画面の日替り壁紙を更新"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"毎日の壁紙を更新"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"壁紙のプレビュー画面"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"壁紙の編集を終了します"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"日替り壁紙を更新しています…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"日替り壁紙を更新できませんでした。ネットワーク接続を確認してからもう一度お試しください。"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"デバイスに保存されている壁紙"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 14377c3..319b90f 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"მთავარი ეკრანის ყოველდღიური ფონის განახლება"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"ყოველდღიური ფონის განახლება"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"ფონის გადახედვის ეკრანი"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"ფონის რედაქტირება დასრულდა"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"მიმდინარეობს ყოველდღიური ფონის განახლება…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"ყოველდღიური ფონი ვერ განახლდა. გთხოვთ, შეამოწმოთ ქსელის კავშირი და ხელახლა ცადოთ."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"მოწყობილობაზე შენახული ფონები"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 8132694..69b2034 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Негізгі экрандағы күнделікті тұсқағазды ауыстыру"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Күнделікті тұсқағазды ауыстыру"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Тұсқағазды алдын ала көру экраны"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Тұсқағазды өзгерту аяқталды."</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Күнделікті тұсқағаз ауыстырылуда…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Күнделікті тұсқағаз ауыстырылмады. Желі байланысын тексеріп, әрекетті қайталаңыз."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Құрылғыдағы тұсқағаздар"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index fcd775f..c615865 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"ផ្ទុកផ្ទាំងរូបភាពអេក្រង់ដើមប្រចាំថ្ងៃឡើងវិញ"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"ផ្ទុកផ្ទាំងរូបភាពប្រចាំថ្ងៃឡើងវិញ"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"អេក្រង់មើល​ផ្ទាំងរូបភាព​សាកល្បង"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"រួចរាល់ក្នុងការកែផ្ទាំង​រូបភាព"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"កំពុងផ្ទុកផ្ទាំងរូបភាពប្រចាំថ្ងៃឡើងវិញ…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"បានបរាជ័យក្នុងការផ្ទុកផ្ទាំងរូបភាពប្រចាំថ្ងៃឡើងវិញ។ សូមពិនិត្យការតភ្ជាប់បណ្តាញរបស់អ្នក ហើយព្យាយាមម្តងទៀត។"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ផ្ទាំងរូបភាពនៅលើឧបករណ៍"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 12e51fb..e16618f 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"ದೈನಂದಿನ ಮುಖಪುಟ ಪರದೆಯ ವಾಲ್‌ಪೇಪರ್ ರಿಫ್ರೆಶ್ ಮಾಡಿ"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"ದಿನನಿತ್ಯದ ವಾಲ್‌ಪೇಪರ್ ಅನ್ನು ರಿಫ್ರೆಶ್ ಮಾಡಿ"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"ವಾಲ್‌ಪೇಪರ್ ಪೂರ್ವವೀಕ್ಷಣೆಯ ಪರದೆ"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"ವಾಲ್‌ಪೇಪರ್ ಎಡಿಟಿಂಗ್ ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"ದೈನಂದಿನ ವಾಲ್‌ಪೇಪರ್ ಅನ್ನು ರಿಫ್ರೆಶ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"ಪ್ರತಿದಿನದ ವಾಲ್‌ಪೇಪರ್ ರಿಫ್ರೆಶ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ. ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ಸಾಧನದಲ್ಲಿನ ವಾಲ್‌ಪೇಪರ್‌ಗಳು"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index cf5c88a..ebf6ce3 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -67,6 +67,9 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"일일 홈 화면 배경화면 새로고침"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"일일 배경화면 새로고침"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"배경화면 미리보기 화면"</string>
+    <string name="folded_device_state_description" msgid="4972608448265616264">"접힌 상태"</string>
+    <string name="unfolded_device_state_description" msgid="3071975681472460627">"펼친 상태"</string>
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"배경화면 편집 완료"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"일일 배경화면 새로고침 중..."</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"일일 배경화면을 새로고침할 수 없습니다. 네트워크 연결을 확인한 후 다시 시도해 주세요."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"기기 배경화면"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 3611b13..565dd45 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Башкы экрандын күнүмдүк тушкагазын жаңыртуу"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Күнүмдүк тушкагазды жаңыртуу"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Тушкагазды карап көрүү экраны"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Тушкагаз түзөтүлүп бүттү"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Күнүмдүк тушкагаз жаңыртылууда…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Күнүмдүк тушкагаз жаңыртылбай калды. Интернетке туташууңузду текшерип, дагы бир жолу аракет кылыңыз."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Түзмөктөгү тушкагаздар"</string>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 438d4b2..3ab06eb 100755
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -25,4 +25,10 @@
     <dimen name="preview_page_gap">60dp</dimen>
     <dimen name="preview_page_horizontal_margin">92dp</dimen>
     <dimen name="preview_card_padding">8dp</dimen>
+
+    <!-- Dimensions for wallpaper effects dialog -->
+    <dimen name="set_wallpaper_dialog_handheld_width">900dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_content_width">840dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_width">416dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_height">260dp</dimen>
 </resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 267cc10..11fa89e 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"ໂຫຼດຂໍ້ມູນຮູບພື້ນຫຼັງໜ້າຈໍຫຼັກຄືນໃໝ່ທຸກມື້"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"ໂຫຼດຮູບພື້ນຫຼັງຄືນໃໝ່ທຸກມື້"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"ໜ້າຈໍຕົວຢ່າງຮູບພື້ນຫຼັງ"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"ການແກ້ໄຂຮູບພື້ນຫຼັງແລ້ວໆ"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"ກຳລັງໂຫຼດຂໍ້ມູນຮູບພື້ນຫຼັງປະຈຳວັນຄືນໃໝ່…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"ໂຫຼດຮູບພື້ນຫຼັງຄືນໃໝ່ທຸກມື້ບໍ່ສຳເລັດ. ກະລຸນາກວດສອບການເຊື່ອມຕໍ່ອິນເຕີເນັດຂອງທ່ານແລ້ວລອງໃໝ່ອີກຄັ້ງ."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ຮູບພື້ນຫຼັງໃນເຄື່ອງ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 24772a3..0d7e3ed 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Atnaujinti dienos pagrindinio ekrano foną"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Atnaujinti dienos ekrano foną"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Ekrano fono peržiūra"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Ekrano fonas baigtas redaguoti"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Atnaujinamas dienos ekrano fonas…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Nepavyko atnaujinti dienos ekrano fono. Patikrinkite tinklo ryšį ir bandykite dar kartą."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Ekrano fonai įrenginyje"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 59e5fb4..6845731 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Atsvaidzināt dienas fona tapeti sākuma ekrānā"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Atsvaidzināt dienas fona tapeti"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Fona tapetes priekšskatījuma ekrāns"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Pabeigt fona tapetes rediģēšanu"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Notiek dienas fona tapetes atsvaidzināšana…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Neizdevās atsvaidzināt dienas fona tapeti. Lūdzu, pārbaudiet tīkla savienojumu un mēģiniet vēlreiz."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Fona tapetes ierīcē"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index c00b32c..4bcd102 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Освежи го дневниот тапет за почетниот екран"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Освежи го дневниот тапет"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Екран за преглед на тапет"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Изменувањето на тапетот е завршено"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Се освежува дневниот тапет…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Освежувањето на дневниот тапет не успеа. Проверете ја мрежната врска и обидете се повторно."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Тапети на уредот"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index d40bdb9..9154a28 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"പ്രതിദിന ഹോം സ്ക്രീൻ വാൾപേപ്പർ പുതുക്കുക"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"പ്രതിദിന വാൾപേപ്പർ പുതുക്കുക"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"വാൾപേപ്പർ പ്രിവ്യൂ സ്‌ക്രീൻ"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"വാൾപേപ്പർ എഡിറ്റിംഗ് പൂർത്തിയായി"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"പ്രതിദിന വാൾപേപ്പർ പുതുക്കുന്നു…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"പ്രതിദിന വാൾപേപ്പർ പുതുക്കിയെടുക്കുന്നത് പരാജയപ്പെട്ടു. നിങ്ങളുടെ നെറ്റ്‌വർക്ക് കണക്ഷൻ പരിശോധിച്ച് വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ഉപകരണത്തിലെ വാൾപേപ്പറുകൾ"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 18f052f..518471a 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Үндсэн нүүрийн өдөр тутмын дэлгэцийн зургийг сэргээх"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Өдөр тутмын дэлгэцийн зургийг сэргээх"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Дэлгэцийн зургийг урьдчилан үзэх дэлгэц"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Дэлгэцийн зургийг засаж дууслаа"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Өдөр тутмын дэлгэцийн зургийг сэргээж байна…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Өдөр тутмын дэлгэцийн зургийг сэргээж чадсангүй. Сүлжээний холболтоо шалгаад дахин оролдоно уу."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Төхөөрөмжийн дэлгэцийн зураг"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 4b03f12..e98d3fb 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"दैनिक होम स्क्रीन वॉलपेपर रिफ्रेश करा"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"दैनिक वॉलपेपर रिफ्रेश करा"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"वॉलपेपर पूर्वावलोकन स्क्रीन"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"वॉलपेपर संपादित करणे पूर्ण झाले आहे"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"दैनिक वॉलपेपर रिफ्रेश करत आहे…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"दैनिक वॉलपेपर रिफ्रेश करता आला नाही. कृपया तुमचे नेटवर्क कनेक्शन तपासा आणि पुन्हा प्रयत्न करा."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"डिव्हाइसवरील वॉलपेपर"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 268cdb0..b2c4c77 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Muat semula kertas dinding skrin utama harian"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Muat semula kertas dinding harian"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Skrin pratonton hiasan latar"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Selesai mengedit hiasan latar"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Memuat semula kertas dinding harian…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Gagal memuat semula kertas dinding harian. Sila semak sambungan rangkaian anda dan cuba lagi."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Kertas dinding pada peranti"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 79e927f..1d84009 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"နေ့စဉ်ပင်မစာမျက်နှာနောက်ခံကို ပြန်လည်စတင်ရန်"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"နေ့စဉ်နောက်ခံကို ပြန်လည် စတင်ရန်"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"နောက်ခံ အစမ်းကြည့်ရှုခြင်း ဖန်သားပြင်"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"နောက်ခံ တည်းဖြတ်ခြင်း ပြီးပါပြီ"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"နေ့စဉ်နောက်ခံကို ပြန်လည်စတင်နေသည်…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"နေ့စဉ် နောက်ခံကို ပြန်လည် စတင်ခြင်း မအောင်မြင်ပါ။ ကွန်ရက်ချိတ်ဆက်မှုကို စစ်ဆေးပြီး ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"စက်ပေါ်ရှိ နောက်ခံများ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 7617997..6c2fe8c 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Oppdater den daglige bakgrunnen på startskjermen"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Oppdater daglig bakgrunn"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Skjerm for forhåndsvisning av bakgrunn"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Ferdig med å endre bakgrunnen"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Oppdaterer daglig bakgrunn …"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Kunne ikke oppdatere den daglige bakgrunnen. Sjekk nettverkstilkoblingen din, og prøv igjen."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Bakgrunner på enheten"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 55179f7..bf45984 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"गृहपृष्ठको दैनिक वालपेपर पुनः ताजा गर्नुहोस्"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"दैनिक वालपेपर पुनः ताजा गर्नुहोस्"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"वालपेपरको प्रिभ्यू स्क्रिन"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"वालपेपर सम्पादन गर्ने कार्य पूरा भयो"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"दैनिक वालपेपर पुनः ताजा गर्दै…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"दैनिक वालपेपर पुनः ताजा गर्न सकिएन। कृपया आफ्नो नेटवर्कको जडान जाँच गरी फेरि प्रयास गर्नुहोस्।"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"यन्त्रमा रहेका वालपेपरहरू"</string>
diff --git a/res/transition/shared_view.xml b/res/values-night/bools.xml
similarity index 75%
rename from res/transition/shared_view.xml
rename to res/values-night/bools.xml
index 184d918..f47f4d7 100644
--- a/res/transition/shared_view.xml
+++ b/res/values-night/bools.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2023 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 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.
@@ -15,7 +14,6 @@
   ~ limitations under the License.
   -->
 
-<transitionSet>
-    <changeTransform />
-    <changeBounds />
-</transitionSet>
\ No newline at end of file
+<resources>
+    <bool name="isFragmentStatusBarLightText">true</bool>
+</resources>
\ No newline at end of file
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 200a153..d91aeb3 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Dagelijkse startschermachtergrond vernieuwen"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Dagelijkse achtergrond vernieuwen"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Voorbeeldscherm achtergrond"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Klaar met bewerken van achtergrond"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Dagelijkse achtergrond vernieuwen…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Dagelijkse achtergrond kan niet worden vernieuwd. Controleer je netwerkverbinding en probeer het opnieuw."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Achtergronden op apparaat"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index cf94efb..7bec191 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"ଦୈନିକ ହୋମ ସ୍କ୍ରିନ ୱାଲପେପର୍‌କୁ ରିଫ୍ରେସ କରନ୍ତୁ"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"ଦୈନିକ ୱାଲପେପର୍‌କୁ ରିଫ୍ରେଶ୍ କରନ୍ତୁ"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"ୱାଲପେପରର ପ୍ରିଭ୍ୟୁ ସ୍କ୍ରିନ"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"ୱାଲପେପର ଏଡିଟିଂ ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"ଦୈନିକ ୱାଲପେପର୍ ରିଫ୍ରେଶ୍ ହେଉଛି…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"ଦୈନିକ ୱାଲପେପର୍‌କୁ ରିଫ୍ରେଶ କରିବାରେ ବିଫଳ ହୋଇଛି। ଦୟାକରି ଆପଣଙ୍କର ନେଟୱର୍କ କନେକ୍ସନ୍‍କୁ ଯାଞ୍ଚ କରିବା ସହିତ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ଅନ୍-ଡିଭାଇସ୍ ୱାଲପେପର୍"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 66dd503..d377825 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"ਰੋਜ਼ਾਨਾ ਹੋਮ ਸਕ੍ਰੀਨ ਵਾਲਪੇਪਰ ਨੂੰ ਰਿਫ੍ਰੈਸ਼ ਕਰੋ"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"ਰੋਜ਼ਾਨਾ ਵਾਲਪੇਪਰ ਰਿਫ੍ਰੈਸ਼ ਕਰੋ"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"ਵਾਲਪੇਪਰ ਦੀ ਪੂਰਵ-ਝਲਕ ਸਕ੍ਰੀਨ"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"ਵਾਲਪੇਪਰ ਦਾ ਸੰਪਾਦਨ ਕਰਨ ਦੀ ਪ੍ਰਕਿਰਿਆ ਪੂਰੀ ਹੋਈ"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"ਰੋਜ਼ਾਨਾ ਵਾਲਪੇਪਰ ਰਿਫ੍ਰੈਸ਼ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..."</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"ਰੋਜ਼ਾਨਾ ਵਾਲਪੇਪਰ ਰਿਫ੍ਰੈਸ਼ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ। ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੀ ਜਾਂਚ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"ਡੀਵਾਈਸ ਵਿੱਚ ਮੌਜੂਦ ਵਾਲਪੇਪਰ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index e044da0..8d23252 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Odśwież codzienną tapetę na ekranie głównym"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Odśwież codzienną tapetę"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Ekran podglądu tapety"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Zakończono edytowanie tapety"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Odświeżam codzienną tapetę…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Nie udało się odświeżyć codziennej tapety. Sprawdź połączenie sieciowe i spróbuj ponownie."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Tapety na urządzeniu"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 0c6eb1e..c97a26a 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Atualizar a imagem de fundo do ecrã principal diária"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Atualizar a imagem de fundo diária"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Ecrã de pré-visualização da imagem de fundo"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Concluir edição da imagem de fundo"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"A atualizar a imagem de fundo diária…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Falha ao atualizar a imagem de fundo diária. Verifique a sua ligação de rede e tente novamente."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Imagens de fundo no disposit."</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index ccc5463..2078ae9 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Atualizar o plano de fundo diário da tela inicial"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Atualizar o plano de fundo diário"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Tela de prévia do plano de fundo"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Edição do plano de fundo concluída"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Atualizando plano de fundo diário…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Falha na atualização do plano de fundo diário. Verifique sua conexão de rede e tente novamente."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Planos de fundo no dispositivo"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index ac5d350..4e83f41 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Actualizează imaginea de fundal zilnică a ecranului de pornire"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Actualizează imaginea de fundal zilnică"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Ecranul de previzualizare a imaginii de fundal"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Editarea imaginii de fundal s-a încheiat"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Se actualizează imaginea de fundal zilnică…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Nu s-a putut actualiza imaginea de fundal zilnică. Verifică-ți conexiunea la rețea și încearcă din nou."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Imagini fundal pe dispozitiv"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index ac8b527..05c1f62 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Обновить ежедневные обои на главном экране"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Обновить ежедневные обои"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Предварительный просмотр обоев"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Завершить редактирование обоев"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Обновление ежедневных обоев…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Не удалось обновить обои. Проверьте подключение к Интернету и повторите попытку."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Сохраненные на устройстве"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 4ced87c..81e57c5 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -67,6 +67,9 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"දිනපතා මුල් පිටු තිර වෝල්පේපරය නැවුම් කරන්න"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"දිනපතා වෝල්පේපරය නැවුම් කරන්න"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"වෝල්පේපර පෙරදසුන් තිරය"</string>
+    <string name="folded_device_state_description" msgid="4972608448265616264">"නැවූ"</string>
+    <string name="unfolded_device_state_description" msgid="3071975681472460627">"නොනැවූ"</string>
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"වෝල්පේපරය සංස්කරණය කර නිමයි"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"දෛනික වෝල්පේපරය නැවුම් කරමින්…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"දෛනික වෝල්පේපරය යළි නැවුම් කිරීම අසාර්ථක විය. කරුණාකර ඔබගේ ජාල සම්බන්ධතාව පරික්ෂා කර නැවත උත්සාහ කරන්න."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"උපාංගය-මත වෝල්පේපර"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index b3ee9ee..8bc8b88 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Obnoviť dennú tapetu na ploche"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Obnoviť dennú tapetu"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Obrazovka ukážky tapety"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Úprava tapety bola dokončená"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Obnovuje sa denná tapeta…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Dennú tapetu sa nepodarilo obnoviť. Skontrolujte pripojenie k sieti a skúste to znova."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Tapety v zariadení"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 7bd153f..5470c40 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Osvežitev dnevnega ozadja za začetni zaslon"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Osvežitev dnevnega ozadja"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Zaslon s predogledom zaslonskega ozadja"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Urejanje zaslonska ozadja je končano"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Osvežitev dnevnega ozadja …"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Dnevnega ozadja ni bilo mogoče osvežiti. Preverite omrežno povezavo in poskusite znova."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Ozadja v napravi"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 2b9ddee..83fa62a 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Rifresko imazhin e përditshëm të sfondit të ekranit kryesor"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Rifresko imazhin e përditshëm të sfondit"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Ekrani i pamjes paraprake të imazhit të sfondit"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Modifikimi i imazhit të sfondit u krye"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Po rifreskon imazhin e përditshëm të sfondit..."</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Rifreskimi i imazhit të përditshëm të sfondit dështoi. Kontrollo lidhjen e rrjetit dhe provo përsëri."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Imazhet e sfondit në pajisje"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index a00ff99..28a4290 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Освежи дневну позадину за почетни екран"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Освежи дневну позадину"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Екран приказа позадине"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Измене позадине су завршене"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Дневна позадина се освежава…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Освежавање дневне позадине није успело. Проверите мрежну везу и пробајте поново."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Позадине на уређају"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index a2e867d..b49a1fe 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Uppdatera dagens bakgrund för startskärmen"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Uppdatera dagens bakgrund"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Förhandsgranskning av skärmens bakgrund"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Bakgrunden har redigerats klart"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Dagens bakgrund uppdateras …"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Det gick inte att uppdatera dagens bakgrund. Kontrollera nätverksanslutningen och försök igen."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Bakgrunder på enheten"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 3354aaa..61aba03 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Onyesha upya mandhari ya skrini ya kwanza ya kila siku"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Onyesha upya mandhari ya kila siku"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Skrini ya kukagua mandhari"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Nimemaliza kubadilisha mandhari"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Inaonyesha upya mandhari ya kila siku..."</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Imeshindwa kuonyesha upya mandhari ya kila siku. Tafadhali kagua muunganisho wako kisha ujaribu tena."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Mandhari yaliyo kwenye kifaa"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 8cb3083..aecb231 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"முகப்புத் திரையில் தினசரி வால்பேப்பரைப் புதுப்பிக்கும் பட்டன்"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"தினசரி வால்பேப்பரைப் புதுப்பிக்கும் பட்டன்"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"வால்பேப்பர் மாதிரிக்காட்சித் திரை"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"வால்பேப்பரை எடிட் செய்வதை முடிக்கும்"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"தினசரி வால்பேப்பரைப் புதுப்பிக்கிறது…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"தினசரி வால்பேப்பரைப் புதுப்பிக்க முடியவில்லை. நெட்வொர்க் இணைப்பைச் சரிபார்த்து, மீண்டும் முயலவும்."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"சாதனத்திலுள்ள வால்பேப்பர்கள்"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index b1b15f1..7b45e62 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"రోజువారీ హోమ్ స్క్రీన్ వాల్‌పేపర్‌ను రిఫ్రెష్ చేస్తుంది"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"రోజువారీ వాల్‌పేపర్‌ను రిఫ్రెష్ చేస్తుంది"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"వాల్‌పేపర్ ప్రివ్యూ స్క్రీన్"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"వాల్‌పేపర్‌ను ఎడిట్ చేయడం పూర్తయింది"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"రోజువారీ వాల్‌పేపర్‌ను రిఫ్రెష్ చేస్తోంది…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"రోజువారీ వాల్‌పేపర్‌ను రిఫ్రెష్ చేయడంలో విఫలమైంది. దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ను చెక్ చేసుకొని, ఆపై మళ్లీ ట్రై చేయండి."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"పరికరంలో వాల్‌పేపర్‌లు"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 1e6e472..c871e10 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"รีเฟรชวอลเปเปอร์หน้าจอหลักรายวัน"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"รีเฟรชวอลเปเปอร์รายวัน"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"หน้าจอตัวอย่างวอลเปเปอร์"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"แก้ไขวอลเปเปอร์เสร็จแล้ว"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"กำลังรีเฟรชวอลเปเปอร์รายวัน…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"รีเฟรชวอลเปเปอร์รายวันไม่ได้ โปรดตรวจสอบการเชื่อมต่อเครือข่าย แล้วลองใหม่อีกครั้ง"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"วอลเปเปอร์บนอุปกรณ์"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index cc6abb8..a8ecb04 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"I-refresh ang pang-araw-araw na wallpaper ng home screen"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"I-refresh ang pang-araw-araw na wallpaper"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Screen ng preview ng wallpaper"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Tapos nang mag-edit ng wallpaper"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Nire-refresh ang pang-araw-araw na wallpaper…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Hindi na-refresh ang pang-araw-araw na wallpaper. Pakitingnan ang iyong koneksyon sa network at subukan ulit."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Mga nasa device na wallpaper"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 5711719..d84eec7 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Günlük ana ekran duvar kağıdını yenile"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Günlük duvar kağıdını yenile"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Duvar kağıdı önizleme ekranı"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Duvar kağıdı düzenleme işlemi tamamlandı"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Günlük duvar kağıdı yenileniyor…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Günlük duvar kağıdı yenilenemedi. Lütfen ağ bağlantınızı kontrol edip tekrar deneyin."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Cihazdaki duvar kağıtları"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 921409c..874406e 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Оновити щоденний фоновий малюнок на головному екрані"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Оновити щоденний фоновий малюнок"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Екран попереднього перегляду фонового малюнка"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Завершити редагування фонового малюнка"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Оновлення щоденного фонового малюнка…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Не вдалось оновити щоденний фоновий малюнок. Перевірте з’єднання з мережею й повторіть спробу."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Фонові малюнки на пристрої"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 30e80e2..51a0e26 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"روزانہ ہوم اسکرین کا وال پیپر ریفریش کریں"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"روزانہ وال پیپر ریفریش کریں"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"وال پیپر پیش منظر اسکرین"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"وال پیپر میں ترمیم ہو گئی"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"روزانہ وال پیپر ریفریش ہو رہا ہے…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"روزانہ وال پیپر ریفریش کرنے میں ناکام۔ براہ کرم اپنا نیٹ ورک کنکشن چیک کر کے دوبارہ کوشش کریں۔"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"آلہ میں اسٹور کردہ وال پیپرز"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index e37e90c..c7b4f50 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Kunlik bosh ekran fon rasmini yangilash"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Kunlik fon rasmini yangilash"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Fon rasmiga razm solish ekrani"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Fon rasmi tahririni yakunlash"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Kunlik fon rasmi yangilanmoqda…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Kunlik fon rasmi yangilanmadi. Internet aloqasini tekshiring va qaytadan urining."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Qurilmadagi fon rasmlari"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 645ea85..bd13014 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Làm mới hình nền màn hình chính hàng ngày"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Làm mới hình nền hàng ngày"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Màn hình xem trước hình nền"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Hoàn tất chỉnh sửa hình nền"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Đang làm mới hình nền hàng ngày…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Không thể làm mới hình nền hàng ngày. Vui lòng kiểm tra kết nối mạng của bạn và thử lại."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Hình nền trên thiết bị"</string>
diff --git a/res/values-w600dp-port/dimens.xml b/res/values-w600dp-port/dimens.xml
index 07d8b0f..381565c 100644
--- a/res/values-w600dp-port/dimens.xml
+++ b/res/values-w600dp-port/dimens.xml
@@ -51,4 +51,9 @@
     <!-- Clipping of the home screen overlay -->
     <dimen name="home_screen_overlay_top_clipping">0dp</dimen>
     <dimen name="home_screen_overlay_bottom_clipping">100dp</dimen>
+
+    <!-- Dimensions for set wallpaper dialog with previews -->
+    <dimen name="set_wallpaper_dialog_foldable_width">360dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_content_width">320dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_preview_width">250dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/res/values-w600dp/dimens.xml b/res/values-w600dp/dimens.xml
index c976b0c..7a79d82 100644
--- a/res/values-w600dp/dimens.xml
+++ b/res/values-w600dp/dimens.xml
@@ -26,5 +26,12 @@
     <!-- Dimensions for small "dual" previews screen. -->
     <dimen name="small_dual_preview_edge_space">94dp</dimen>
 
-    <dimen name="set_wallpaper_dialog_foldable_preview_width">280dp</dimen>
+    <!-- Dimensions for set wallpaper dialog with previews -->
+    <dimen name="set_wallpaper_dialog_handheld_width">520dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_content_width">450dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_width">220dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_height">352dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_width">410dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_content_width">370dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_preview_width">300dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/res/values-w700dp-port/dimens.xml b/res/values-w700dp-port/dimens.xml
new file mode 100644
index 0000000..b7dd74a
--- /dev/null
+++ b/res/values-w700dp-port/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 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
+  -->
+<resources>
+    <!-- Dimensions for set wallpaper dialog with previews -->
+    <dimen name="set_wallpaper_dialog_foldable_width">410dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_content_width">370dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_preview_width">300dp</dimen>
+</resources>
diff --git a/res/values-w700dp/dimens.xml b/res/values-w700dp/dimens.xml
new file mode 100644
index 0000000..36018a5
--- /dev/null
+++ b/res/values-w700dp/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 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
+  -->
+<resources>
+    <!-- Dimensions for set wallpaper dialog with previews -->
+    <dimen name="set_wallpaper_dialog_foldable_width">330dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_content_width">290dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_preview_width">220dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-w800dp-port/dimens.xml b/res/values-w800dp-port/dimens.xml
new file mode 100644
index 0000000..bee39f9
--- /dev/null
+++ b/res/values-w800dp-port/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 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
+  -->
+<resources>
+    <!-- Dimensions for wallpaper effects dialog -->
+    <dimen name="set_wallpaper_dialog_handheld_width">540dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_content_width">450dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_width">220dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_height">352dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-w800dp/dimens.xml b/res/values-w800dp/dimens.xml
index 54c607c..67b3706 100644
--- a/res/values-w800dp/dimens.xml
+++ b/res/values-w800dp/dimens.xml
@@ -69,4 +69,13 @@
     display.
     -->
     <dimen name="screen_preview_width">600dp</dimen>
+
+    <!-- Dimensions for wallpaper effects dialog -->
+    <dimen name="set_wallpaper_dialog_handheld_width">900dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_content_width">840dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_width">416dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_preview_height">260dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_width">410dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_content_width">370dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_preview_width">300dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index e1d2f84..31c5884 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"刷新每日主屏幕壁纸"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"刷新每日壁纸"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"壁纸预览画面"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"壁纸编辑完毕"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"正在刷新每日壁纸…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"无法刷新每日壁纸。请检查您的网络连接状况,然后重试。"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"设备上的壁纸"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 1b11ad9..b58a094 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"重新整理主畫面的每日桌布"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"重新整理每日桌布"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"桌布預覽畫面"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"完成編輯桌布"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"正在重新整理每日桌布…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"無法重新整理每日桌布。請檢查你的網絡連線,然後再試一次。"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"裝置上的桌布"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index e086c29..bfca996 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"重新整理主畫面每日桌布"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"重新整理每日桌布"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"桌布預覽畫面"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"桌布編輯完畢"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"正在重新整理每日桌布…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"無法重新整理每日桌布。請檢查你的網路連線,然後再試一次。"</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"裝置桌布"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index b2f207d..2079961 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -67,6 +67,11 @@
     <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Vuselela isithombe sangemuva sasekhaya sansuku zonke"</string>
     <string name="refresh_daily_wallpaper_content_description" msgid="4362142658237147583">"Vuselela isithombe sangemuva sansuku zonke"</string>
     <string name="preview_screen_description" msgid="3386387053327775919">"Isikrini sokubuka kuqala sangemuva"</string>
+    <!-- no translation found for folded_device_state_description (4972608448265616264) -->
+    <skip />
+    <!-- no translation found for unfolded_device_state_description (3071975681472460627) -->
+    <skip />
+    <string name="full_preview_check_button_description" msgid="700484353763952975">"Iqedile ukuhlela isithombe sangemuva"</string>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Ivuselela isithombe sangemuva sansuku zonke…"</string>
     <string name="refresh_daily_wallpaper_failed_message" msgid="4749879993812557166">"Yehlulekile ukuvuselela isithombe sangemuva sansuku zonke. Sicela uhlole ukuxhumeka kwakho kwenethiwekhi uphinde uzame futhi."</string>
     <string name="on_device_wallpapers_category_title" msgid="805819102071369004">"Izithombe zangemuva ezikudivayisi"</string>
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 1c2e03b..ba9d2a6 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -16,4 +16,5 @@
 -->
 <resources>
     <bool name="is_large_screen">false</bool>
+    <bool name="isFragmentStatusBarLightText">false</bool>
 </resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 0da23c5..276de54 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -185,6 +185,9 @@
     <dimen name="wallpaper_info_pane_interaction_top_margin">39dp</dimen>
     <dimen name="wallpaper_info_pane_explore_button_top_margin">50dp</dimen>
 
+    <!-- Minimum height for the wallpaper info explore button. -->
+    <dimen name="wallpaper_touch_target_min_height">48dp</dimen>
+
     <dimen name="option_border_width">2dp</dimen>
     <dimen name="option_selected_border_width">3dp</dimen>
     <dimen name="option_title_font_text_size">14sp</dimen>
@@ -264,6 +267,10 @@
     <dimen name="set_wallpaper_button_margin_end">16dp</dimen>
     <dimen name="set_wallpaper_button_min_height">48dp</dimen>
 
+    <!-- Set wallpaper dialog -->
+    <dimen name="set_wallpaper_progress_dialog_padding">16dp</dimen>
+    <dimen name="set_wallpaper_progress_dialog_progress_bar_margin_end">10dp</dimen>
+
     <!-- Wallpaper control button group -->
     <dimen name="wallpaper_control_button_group_divider_space">16dp</dimen>
     <dimen name="wallpaper_control_button_group_margin_top">24dp</dimen>
@@ -281,6 +288,8 @@
     <!-- Floating Sheet -->
     <dimen name="floating_sheet_corner_radius">12dp</dimen>
     <dimen name="floating_sheet_margin">24dp</dimen>
+    <dimen name="floating_sheet_bottom_margin">120dp</dimen>
+    <dimen name="floating_sheet_customize_content_min_height">120dp</dimen>
 
     <!-- Dimensions for "Wallpaper category headers" -->
     <dimen name="wallpaper_header_text_size">16sp</dimen>
@@ -357,11 +366,14 @@
     <dimen name="small_preview_button_radius">15dp</dimen>
 
     <!-- Dimensions for set wallpaper dialog with previews -->
-    <dimen name="set_wallpaper_dialog_foldable_preview_width">270dp</dimen>
-    <dimen name="set_wallpaper_dialog_handheld_width">270dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_width">370dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_content_width">320dp</dimen>
+    <dimen name="set_wallpaper_dialog_foldable_preview_width">290dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_width">340dp</dimen>
+    <dimen name="set_wallpaper_dialog_handheld_content_width">270dp</dimen>
     <dimen name="set_wallpaper_dialog_handheld_preview_width">130dp</dimen>
     <dimen name="set_wallpaper_dialog_handheld_preview_height">260dp</dimen>
-    <dimen name="set_wallpaper_dialog_button_margin_vertical">16dp</dimen>
+    <dimen name="set_wallpaper_dialog_button_margin_vertical">8dp</dimen>
     <dimen name="set_wallpaper_dialog_bottom_padding">16dp</dimen>
     <dimen name="set_wallpaper_dialog_preview_corner_radius">14dp</dimen>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3600e55..11a1064 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -237,6 +237,16 @@
     <!-- Content description for the wallpaper preview screen. [CHAR LIMIT=none] -->
     <string name="preview_screen_description">Wallpaper preview screen</string>
 
+    <!-- Content description when the device is in a folded state. [CHAR LIMIT=none] -->
+    <string name="folded_device_state_description">Folded</string>
+
+    <!-- Content description when device is in an unfolded state. [CHAR LIMIT=none] -->
+    <string name="unfolded_device_state_description">Unfolded</string>
+
+    <!-- Content description for a button on full preview screen to confirm user's wallpaper
+         edit. [CHAR LIMIT=none] -->
+    <string name="full_preview_check_button_description">Done editing wallpaper</string>
+
     <!-- Message shown to user in a progress dialog when the app is in the process of refreshing the
          daily wallpaper. [CHAR LIMIT=none] -->
     <string name="refreshing_daily_wallpaper_dialog_message">
diff --git a/src/com/android/wallpaper/config/BaseFlags.kt b/src/com/android/wallpaper/config/BaseFlags.kt
index 6c713c6..35b4f16 100644
--- a/src/com/android/wallpaper/config/BaseFlags.kt
+++ b/src/com/android/wallpaper/config/BaseFlags.kt
@@ -17,10 +17,10 @@
 
 import android.app.WallpaperManager
 import android.content.Context
+import com.android.settings.accessibility.Flags.enableColorContrastControl
 import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
 import com.android.systemui.shared.customization.data.content.CustomizationProviderClientImpl
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
-import com.android.wallpaper.Flags.multiCropPreviewUiFlag
 import com.android.wallpaper.Flags.refactorWallpaperCategoryFlag
 import com.android.wallpaper.Flags.wallpaperRestorerFlag
 import com.android.wallpaper.module.InjectorProvider
@@ -36,9 +36,7 @@
     open fun isInterruptModelDownloadEnabled() = false
     open fun isWallpaperRestorerEnabled() = wallpaperRestorerFlag()
     open fun isWallpaperCategoryRefactoringEnabled() = refactorWallpaperCategoryFlag()
-
-    /** Enables new preview UI if both [isMultiCropEnabled] and this flag are true. */
-    open fun isMultiCropPreviewUiEnabled() = multiCropPreviewUiFlag()
+    open fun isColorContrastControlEnabled() = enableColorContrastControl()
 
     open fun isMultiCropEnabled() = WallpaperManager.isMultiCropEnabled()
 
diff --git a/src/com/android/wallpaper/effects/EffectsController.java b/src/com/android/wallpaper/effects/EffectsController.java
index b7f4f04..965fd69 100644
--- a/src/com/android/wallpaper/effects/EffectsController.java
+++ b/src/com/android/wallpaper/effects/EffectsController.java
@@ -15,10 +15,13 @@
  */
 package com.android.wallpaper.effects;
 
+import android.app.WallpaperInfo;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 
+import androidx.annotation.NonNull;
+
 /**
  * Utility class to provide methods to generate effects for the wallpaper.
  */
@@ -44,13 +47,16 @@
     public static final int RESULT_FOREGROUND_DOWNLOAD_SUCCEEDED = 512;
     public static final int RESULT_FOREGROUND_DOWNLOAD_FAILED = 1024;
     public static final int RESULT_PROBE_FOREGROUND_DOWNLOADING = 2048;
+
     /**
      * Interface of the Effect enum.
      */
     public interface EffectEnumInterface {
     }
+
     public enum Effect implements EffectEnumInterface {
         NONE,
+        UNKNOWN,
     }
 
     protected boolean mBound = false;
@@ -71,6 +77,21 @@
     }
 
     /**
+     * Returns true if an effects component is available on the current device
+     */
+    public boolean areEffectsAvailable() {
+        return false;
+    }
+
+    /**
+     * Returns true if the given {@link WallpaperInfo} corresponds to a wallpaper matching the
+     * "Effects" wallpaper.
+     */
+    public boolean isEffectsWallpaper(@NonNull WallpaperInfo info) {
+        return false;
+    }
+
+    /**
      * Destroys the controller
      */
     public void destroy() {
@@ -94,10 +115,12 @@
     }
 
     /** Sets the {@link EffectsServiceListener} to receive updates. */
-    public void setListener(EffectsServiceListener listener) {}
+    public void setListener(EffectsServiceListener listener) {
+    }
 
     /** Removes the listener set via {@link #setListener(EffectsServiceListener)}. */
-    public void removeListener() {}
+    public void removeListener() {
+    }
 
     /** Returns true if the effect is expected by this controller. */
     public boolean isTargetEffect(EffectEnumInterface effect) {
@@ -113,7 +136,8 @@
          *
          * @param effect The effect that was generated.
          * @param bundle The data that the Service might have sent to the picker.
-         * @param error The error code. if there's an error, value is greater than zero.
+         * @param error The error code. if there's an error, value is greater than
+         *              zero.
          * @param originalStatusCode The original status code used for metrics logging.
          * @param errorMessage The error message.
          */
@@ -157,4 +181,14 @@
     public Uri getContentUri() {
         return Uri.EMPTY;
     }
+
+    /** */
+    public void interruptGenerate(com.android.wallpaper.effects.Effect effect) {}
+
+    /**
+     * This initiates the downloading of the ML models for a given effect
+     *
+     * @param effect The Effect for which we want to download the ML model
+     */
+    public void startForegroundDownload(com.android.wallpaper.effects.Effect effect){}
 }
diff --git a/src/com/android/wallpaper/model/CurrentWallpaperInfo.java b/src/com/android/wallpaper/model/CurrentWallpaperInfo.java
index a1f1a81..2093053 100755
--- a/src/com/android/wallpaper/model/CurrentWallpaperInfo.java
+++ b/src/com/android/wallpaper/model/CurrentWallpaperInfo.java
@@ -127,8 +127,7 @@
         BaseFlags flags = InjectorProvider.getInjector().getFlags();
         // Only get the full wallpaper asset when previewing a multi-crop wallpaper, otherwise get
         // the cropped asset.
-        boolean getFullAsset = flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()
-                && !mCropHints.isEmpty();
+        boolean getFullAsset = flags.isMultiCropEnabled() && !mCropHints.isEmpty();
 
         return (isSystemBuiltIn)
                 ? new BuiltInWallpaperAsset(context)
diff --git a/src/com/android/wallpaper/model/WallpaperInfo.java b/src/com/android/wallpaper/model/WallpaperInfo.java
index 82b0e40..eefcadb 100755
--- a/src/com/android/wallpaper/model/WallpaperInfo.java
+++ b/src/com/android/wallpaper/model/WallpaperInfo.java
@@ -321,9 +321,7 @@
     /** Returns the crop {@link Rect} of each displaySize for this wallpaper. */
     public @Nullable Map<Point, Rect> getWallpaperCropHints() {
         BaseFlags flags = InjectorProvider.getInjector().getFlags();
-        boolean isMultiCropEnabled =
-                flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled();
-        if (!isMultiCropEnabled) {
+        if (!flags.isMultiCropEnabled()) {
             return null;
         }
 
diff --git a/src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt b/src/com/android/wallpaper/model/wallpaper/DeviceDisplayType.kt
similarity index 71%
rename from src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt
rename to src/com/android/wallpaper/model/wallpaper/DeviceDisplayType.kt
index 4001f83..f3a05d9 100644
--- a/src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt
+++ b/src/com/android/wallpaper/model/wallpaper/DeviceDisplayType.kt
@@ -15,7 +15,12 @@
  */
 package com.android.wallpaper.model.wallpaper
 
-enum class FoldableDisplay {
-    FOLDED,
-    UNFOLDED,
+enum class DeviceDisplayType {
+    SINGLE, // The screen of a single-screen device
+    FOLDED, // The outer screen of a foldable
+    UNFOLDED; // The inner screen of a foldable
+
+    companion object {
+        val FOLDABLE_DISPLAY_TYPES = setOf(FOLDED, UNFOLDED)
+    }
 }
diff --git a/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java b/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
index 9e8cb95..46e0f27 100755
--- a/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
+++ b/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
@@ -60,8 +60,7 @@
             WallpaperInfoCallback callback) {
 
         BaseFlags flags = InjectorProvider.getInjector().getFlags();
-        final boolean isMultiCropEnabled =
-                flags.isMultiCropEnabled() && flags.isMultiCropPreviewUiEnabled();
+        final boolean isMultiCropEnabled = flags.isMultiCropEnabled();
 
         boolean isHomeWallpaperSynced  = homeWallpaperSynced(context);
         boolean isLockWallpaperSynced  = lockWallpaperSynced(context);
@@ -74,7 +73,8 @@
                 DisplayUtils displayUtils = InjectorProvider.getInjector().getDisplayUtils(context);
                 WallpaperClient wallpaperClient = InjectorProvider.getInjector().getWallpaperClient(
                         context);
-                List<Point> displaySizes = displayUtils.getInternalDisplaySizes();
+                List<Point> displaySizes = displayUtils
+                        .getInternalDisplaySizes(/* allDimensions= */ true);
                 if (mHomeWallpaper != null) {
                     boolean isHomeWallpaperStatic = mHomeWallpaper.getWallpaperComponent() == null
                             || mHomeWallpaper.getWallpaperComponent().getComponent() == null;
diff --git a/src/com/android/wallpaper/module/DefaultNetworkStatusNotifier.java b/src/com/android/wallpaper/module/DefaultNetworkStatusNotifier.java
index 8bd3a8f..5b8aabf 100755
--- a/src/com/android/wallpaper/module/DefaultNetworkStatusNotifier.java
+++ b/src/com/android/wallpaper/module/DefaultNetworkStatusNotifier.java
@@ -22,22 +22,29 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 
+import dagger.hilt.android.qualifiers.ApplicationContext;
+
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Implementation of {@link NetworkStatusNotifier} which uses
  * {@link android.net.ConnectivityManager} to provide network status.
  */
-public class DefaultNetworkStatusNotifier implements NetworkStatusNotifier {
+@Singleton
+public class DefaultNetworkStatusNotifier implements NetworkStatusNotifier  {
 
     private Context mAppContext;
     private ConnectivityManager mConnectivityManager;
     private BroadcastReceiver mReceiver;
     private List<Listener> mListeners;
 
-    public DefaultNetworkStatusNotifier(Context context) {
-        mAppContext = context.getApplicationContext();
+    @Inject
+    public DefaultNetworkStatusNotifier(@ApplicationContext Context context) {
+        mAppContext = context;
 
         mConnectivityManager =
                 (ConnectivityManager) mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt b/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt
index a59b0a3..5f10d59 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt
+++ b/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt
@@ -905,19 +905,36 @@
         wallpaperModel: LiveWallpaperModel
     ) {}
 
-    override fun setHasPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
+    override fun setHasSmallPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
         sharedPrefs
             .edit()
             .putBoolean(
-                WallpaperPreferenceKeys.KEY_HAS_PREVIEW_TOOLTIP_BEEN_SHOWN,
+                WallpaperPreferenceKeys.KEY_HAS_SMALL_PREVIEW_TOOLTIP_BEEN_SHOWN,
                 hasTooltipBeenShown
             )
             .apply()
     }
 
-    override fun getHasPreviewTooltipBeenShown(): Boolean {
+    override fun getHasSmallPreviewTooltipBeenShown(): Boolean {
         return sharedPrefs.getBoolean(
-            WallpaperPreferenceKeys.KEY_HAS_PREVIEW_TOOLTIP_BEEN_SHOWN,
+            WallpaperPreferenceKeys.KEY_HAS_SMALL_PREVIEW_TOOLTIP_BEEN_SHOWN,
+            false
+        )
+    }
+
+    override fun setHasFullPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
+        sharedPrefs
+            .edit()
+            .putBoolean(
+                WallpaperPreferenceKeys.KEY_HAS_FULL_PREVIEW_TOOLTIP_BEEN_SHOWN,
+                hasTooltipBeenShown
+            )
+            .apply()
+    }
+
+    override fun getHasFullPreviewTooltipBeenShown(): Boolean {
+        return sharedPrefs.getBoolean(
+            WallpaperPreferenceKeys.KEY_HAS_FULL_PREVIEW_TOOLTIP_BEEN_SHOWN,
             false
         )
     }
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java b/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
index fd13598..ed071fb 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
+++ b/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
@@ -44,6 +44,8 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 
 /**
  * Default implementation of {@link WallpaperRefresher} which refreshes wallpaper metadata
@@ -63,6 +65,8 @@
 
     private final WallpaperClient mWallpaperClient;
 
+    private final Executor mExecutor = Executors.newCachedThreadPool();
+
 
     /**
      * @param context The application's context.
@@ -84,7 +88,7 @@
     @Override
     public void refresh(RefreshListener listener) {
         GetWallpaperMetadataAsyncTask task = new GetWallpaperMetadataAsyncTask(listener);
-        task.execute();
+        task.executeOnExecutor(mExecutor);
     }
 
     /**
@@ -370,7 +374,8 @@
 
         private Map<Point, Rect> getCurrentWallpaperCropHints(
                 @WallpaperManager.SetWallpaperFlags int which) {
-            List<Point> displaySizes = mDisplayUtils.getInternalDisplaySizes();
+            List<Point> displaySizes = mDisplayUtils
+                    .getInternalDisplaySizes(/* allDimensions= */ true);
             return mWallpaperClient.getCurrentCropHints(displaySizes, which);
         }
     }
diff --git a/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt b/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
index c71b5ae..3f37594 100755
--- a/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
+++ b/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
@@ -56,6 +56,7 @@
 import com.android.wallpaper.picker.individual.IndividualPickerFragment
 import com.android.wallpaper.picker.undo.data.repository.UndoRepository
 import com.android.wallpaper.picker.undo.domain.interactor.UndoInteractor
+import com.android.wallpaper.system.UiModeManagerWrapper
 import com.android.wallpaper.util.DisplayUtils
 import dagger.Lazy
 import javax.inject.Inject
@@ -102,6 +103,8 @@
     private var viewOnlyPreviewActivityIntentFactory: InlinePreviewIntentFactory? = null
     @Inject lateinit var userEventLogger: Lazy<UserEventLogger>
 
+    @Inject lateinit var uiModeManager: UiModeManagerWrapper
+
     override fun getApplicationCoroutineScope(): CoroutineScope {
         return mainScope
     }
@@ -305,7 +308,7 @@
     }
 
     override fun getWallpaperInteractor(context: Context): WallpaperInteractor {
-        if (getFlags().isMultiCropEnabled() && getFlags().isMultiCropPreviewUiEnabled()) {
+        if (getFlags().isMultiCropEnabled()) {
             return injectedWallpaperInteractor.get()
         }
 
@@ -324,7 +327,7 @@
     }
 
     override fun getWallpaperClient(context: Context): WallpaperClient {
-        if (getFlags().isMultiCropEnabled() && getFlags().isMultiCropPreviewUiEnabled()) {
+        if (getFlags().isMultiCropEnabled()) {
             return injectedWallpaperClient.get()
         }
 
diff --git a/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java b/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
index 20e8dee..0e7a88e 100755
--- a/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
+++ b/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
@@ -34,8 +34,10 @@
     public static final String KEY_LOCK_WALLPAPER_ACTION_URL = "lock_wallpaper_action_url";
     public static final String KEY_LOCK_WALLPAPER_HASH_CODE = "lock_wallpaper_hash_code";
     public static final String KEY_LOCK_WALLPAPER_COLLECTION_ID = "lock_wallpaper_collection_id";
-    public static final String KEY_HAS_PREVIEW_TOOLTIP_BEEN_SHOWN =
-            "has_preview_tooltip_been_shown";
+    public static final String KEY_HAS_SMALL_PREVIEW_TOOLTIP_BEEN_SHOWN =
+            "has_small_preview_tooltip_been_shown";
+    public static final String KEY_HAS_FULL_PREVIEW_TOOLTIP_BEEN_SHOWN =
+            "has_full_preview_tooltip_been_shown";
 
     /**
      * Preferences with these keys should not be backed up
diff --git a/src/com/android/wallpaper/module/WallpaperPreferences.kt b/src/com/android/wallpaper/module/WallpaperPreferences.kt
index 6fbb34a..5563a06 100755
--- a/src/com/android/wallpaper/module/WallpaperPreferences.kt
+++ b/src/com/android/wallpaper/module/WallpaperPreferences.kt
@@ -407,10 +407,16 @@
     )
 
     /** Sets whether the preview tooltip should be shown. */
-    fun setHasPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean)
+    fun setHasSmallPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean)
 
     /** Gets whether the preview tooltip should be shown. */
-    fun getHasPreviewTooltipBeenShown(): Boolean
+    fun getHasSmallPreviewTooltipBeenShown(): Boolean
+
+    /** Sets whether the preview tooltip should be shown. */
+    fun setHasFullPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean)
+
+    /** Gets whether the preview tooltip should be shown. */
+    fun getHasFullPreviewTooltipBeenShown(): Boolean
 
     /** The possible wallpaper presentation modes, i.e., either "static" or "rotating". */
     @IntDef(PRESENTATION_MODE_STATIC, PRESENTATION_MODE_ROTATING) annotation class PresentationMode
diff --git a/src/com/android/wallpaper/picker/AppbarFragment.java b/src/com/android/wallpaper/picker/AppbarFragment.java
index 339b8c6..f668d67 100644
--- a/src/com/android/wallpaper/picker/AppbarFragment.java
+++ b/src/com/android/wallpaper/picker/AppbarFragment.java
@@ -19,17 +19,21 @@
 import static android.view.View.VISIBLE;
 
 import android.annotation.MenuRes;
+import android.app.Activity;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.Window;
 import android.widget.TextView;
 import android.widget.Toolbar;
 import android.widget.Toolbar.OnMenuItemClickListener;
 
 import androidx.annotation.Nullable;
+import androidx.core.view.WindowCompat;
+import androidx.core.view.WindowInsetsControllerCompat;
 
 import com.android.wallpaper.R;
 import com.android.wallpaper.config.BaseFlags;
@@ -129,6 +133,7 @@
 
         // Update toolbar and status bar color.
         setToolbarColor(getToolbarColorId());
+        setUpStatusBar(isStatusBarLightText());
 
         CharSequence title;
         if (getArguments() != null) {
@@ -168,6 +173,21 @@
         return R.color.toolbar_color;
     }
 
+    protected void setUpStatusBar(boolean shouldUseLightText) {
+        Activity activity = getActivity();
+        if (activity == null) {
+            return;
+        }
+        Window window = activity.getWindow();
+        WindowInsetsControllerCompat windowInsetsController =
+                WindowCompat.getInsetsController(window, window.getDecorView());
+        windowInsetsController.setAppearanceLightStatusBars(!shouldUseLightText);
+    }
+
+    protected boolean isStatusBarLightText() {
+        return getResources().getBoolean(R.bool.isFragmentStatusBarLightText);
+    }
+
     protected int getToolbarTextColor() {
         return ResourceUtils.getColorAttr(getActivity(), android.R.attr.textColorPrimary);
     }
diff --git a/src/com/android/wallpaper/picker/CustomizationPickerActivity.java b/src/com/android/wallpaper/picker/CustomizationPickerActivity.java
index 9bdc85b..bcb6f9e 100644
--- a/src/com/android/wallpaper/picker/CustomizationPickerActivity.java
+++ b/src/com/android/wallpaper/picker/CustomizationPickerActivity.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.Window;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -36,6 +37,7 @@
 import androidx.fragment.app.FragmentManager;
 
 import com.android.wallpaper.R;
+import com.android.wallpaper.config.BaseFlags;
 import com.android.wallpaper.model.Category;
 import com.android.wallpaper.model.CustomizationSectionController.CustomizationSectionNavigationController;
 import com.android.wallpaper.model.PermissionRequester;
@@ -94,6 +96,11 @@
 
         enforcePortraitForHandheldAndFoldedDisplay();
 
+        BaseFlags flags = injector.getFlags();
+        if (flags.isMultiCropEnabled()) {
+            getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
+        }
+
         // Restore this Activity's state before restoring contained Fragments state.
         super.onCreate(savedInstanceState);
         // Trampoline for the two panes
diff --git a/src/com/android/wallpaper/picker/ImagePreviewFragment.java b/src/com/android/wallpaper/picker/ImagePreviewFragment.java
index aacb04b..3f2ec34 100755
--- a/src/com/android/wallpaper/picker/ImagePreviewFragment.java
+++ b/src/com/android/wallpaper/picker/ImagePreviewFragment.java
@@ -484,7 +484,7 @@
 
             mProgressBar.setVisibility(View.VISIBLE);
             View wallpaperPreviewContainer = LayoutInflater.from(context).inflate(
-                    R.layout.fullscreen_wallpaper_preview, null);
+                    R.layout.fullscreen_wallpaper_preview_old, null);
             mFullResImageView = wallpaperPreviewContainer.findViewById(R.id.full_res_image);
             mLowResImageView = wallpaperPreviewContainer.findViewById(R.id.low_res_image);
             mLowResImageView.setRenderEffect(
diff --git a/src/com/android/wallpaper/picker/PreviewActivity.java b/src/com/android/wallpaper/picker/PreviewActivity.java
index da0d3e3..c1fc1f7 100644
--- a/src/com/android/wallpaper/picker/PreviewActivity.java
+++ b/src/com/android/wallpaper/picker/PreviewActivity.java
@@ -130,7 +130,7 @@
             LargeScreenMultiPanesChecker multiPanesChecker = new LargeScreenMultiPanesChecker();
             final boolean isMultiPanel = multiPanesChecker.isMultiPanesEnabled(appContext);
 
-            if (flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()) {
+            if (flags.isMultiCropEnabled()) {
                 return WallpaperPreviewActivity.Companion.newIntent(appContext,
                         wallpaper, isAssetIdPresent, mIsViewAsHome, /* isNewTask= */ isMultiPanel);
             }
diff --git a/src/com/android/wallpaper/picker/StandalonePreviewActivity.java b/src/com/android/wallpaper/picker/StandalonePreviewActivity.java
index 2a9ea51..096aa7b 100644
--- a/src/com/android/wallpaper/picker/StandalonePreviewActivity.java
+++ b/src/com/android/wallpaper/picker/StandalonePreviewActivity.java
@@ -32,7 +32,6 @@
 import com.android.wallpaper.R;
 import com.android.wallpaper.config.BaseFlags;
 import com.android.wallpaper.model.ImageWallpaperInfo;
-import com.android.wallpaper.model.WallpaperInfo;
 import com.android.wallpaper.module.InjectorProvider;
 import com.android.wallpaper.picker.AppbarFragment.AppbarFragmentHost;
 import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity;
@@ -143,17 +142,17 @@
     private void loadPreviewFragment() {
         BaseFlags flags = InjectorProvider.getInjector().getFlags();
         Intent intent = getIntent();
-        WallpaperInfo wallpaper = new ImageWallpaperInfo(intent.getData());
-        if (flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()) {
-            startActivity(WallpaperPreviewActivity.Companion.newIntent(
-                    this.getApplicationContext(), wallpaper, /* isAssetIdPresent= */ false,
-                    /* isViewAsHome= */ true, /* isNewTask= */ false));
+        if (flags.isMultiCropEnabled()) {
+            Intent wallpaperIntent = WallpaperPreviewActivity.Companion.newIntent(
+                    this.getApplicationContext(), intent, /* isAssetIdPresent= */ false,
+                    /* isViewAsHome= */ true, /* isNewTask= */ false);
+            startActivity(wallpaperIntent);
             finish();
             return;
         }
         Fragment fragment = InjectorProvider.getInjector().getPreviewFragment(
                 /* context */ this,
-                wallpaper,
+                new ImageWallpaperInfo(intent.getData()),
                 /* viewAsHome= */ true,
                 /* isAssetIdPresent= */ false,
                 /* isNewTask= */ false);
diff --git a/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java b/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java
index 48734a7..4d1b398 100644
--- a/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java
+++ b/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java
@@ -110,7 +110,7 @@
             LargeScreenMultiPanesChecker multiPanesChecker = new LargeScreenMultiPanesChecker();
             final boolean isMultiPanel = multiPanesChecker.isMultiPanesEnabled(appContext);
             final BaseFlags flags = InjectorProvider.getInjector().getFlags();
-            if (flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()) {
+            if (flags.isMultiCropEnabled()) {
                 return WallpaperPreviewActivity.Companion.newIntent(appContext, wallpaper,
                         isAssetIdPresent, mIsViewAsHome, /* isNewTask= */ isMultiPanel);
             }
diff --git a/src/com/android/wallpaper/picker/category/client /DefaultWallpaperCategoryClient.kt b/src/com/android/wallpaper/picker/category/client /DefaultWallpaperCategoryClient.kt
new file mode 100644
index 0000000..d2d3a39
--- /dev/null
+++ b/src/com/android/wallpaper/picker/category/client /DefaultWallpaperCategoryClient.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.picker.category.client
+
+import android.content.Context
+import android.util.Log
+import com.android.wallpaper.R
+import com.android.wallpaper.model.Category
+import com.android.wallpaper.model.DefaultWallpaperInfo
+import com.android.wallpaper.model.ImageCategory
+import com.android.wallpaper.model.LegacyPartnerWallpaperInfo
+import com.android.wallpaper.model.PartnerWallpaperInfo
+import com.android.wallpaper.model.WallpaperCategory
+import com.android.wallpaper.model.WallpaperInfo
+import com.android.wallpaper.module.DefaultCategoryProvider
+import com.android.wallpaper.module.PartnerProvider
+import com.android.wallpaper.picker.data.category.CategoryModel
+import com.android.wallpaper.util.WallpaperXMLParser
+import com.android.wallpaper.util.converter.category.CategoryFactory
+import dagger.hilt.android.qualifiers.ApplicationContext
+import java.io.IOException
+import java.util.Locale
+import javax.inject.Inject
+import org.xmlpull.v1.XmlPullParser
+import org.xmlpull.v1.XmlPullParserException
+
+/**
+ * This class is responsible for fetching wallpaper categories, listed as follows:
+ * 1. MyPhotos category that allows users to select custom photos
+ * 2. OnDevice category that are pre-loaded wallpapers on device (legacy way of pre-loading
+ *    wallpapers, modern way is described below)
+ * 3. System categories on device (modern way of pre-loading wallpapers on device)
+ */
+class DefaultWallpaperCategoryClient
+@Inject
+constructor(
+    @ApplicationContext val context: Context,
+    private val partnerProvider: PartnerProvider,
+    private val categoryFactory: CategoryFactory,
+    private val wallpaperXMLParser: WallpaperXMLParser
+) {
+
+    /** This method is used for fetching and creating the MyPhotos category tile. */
+    fun getMyPhotosCategory(): CategoryModel {
+        val imageCategory =
+            ImageCategory(
+                context.getString(R.string.my_photos_category_title),
+                context.getString(R.string.image_wallpaper_collection_id),
+                DefaultCategoryProvider.getPriorityMyPhotos(context),
+                R.drawable.wallpaperpicker_emptystate /* overlayIconResId */
+            )
+        return categoryFactory.getCategoryModel(context, imageCategory)
+    }
+
+    /**
+     * This method is used for fetching the on-device categories. This returns a category which
+     * incorporates both GEL and bundled wallpapers.
+     */
+    suspend fun getOnDeviceCategory(): CategoryModel? {
+        val onDeviceWallpapers = mutableListOf<WallpaperInfo?>()
+
+        if (!partnerProvider.shouldHideDefaultWallpaper()) {
+            val defaultWallpaperInfo = DefaultWallpaperInfo()
+            onDeviceWallpapers.add(defaultWallpaperInfo)
+        }
+
+        val partnerWallpaperInfos = PartnerWallpaperInfo.getAll(context)
+        onDeviceWallpapers.addAll(partnerWallpaperInfos)
+
+        val legacyPartnerWallpaperInfos = LegacyPartnerWallpaperInfo.getAll(context)
+        onDeviceWallpapers.addAll(legacyPartnerWallpaperInfos)
+
+        val privateWallpapers = getPrivateDeviceWallpapers()
+        privateWallpapers?.let { onDeviceWallpapers.addAll(it) }
+
+        return onDeviceWallpapers
+            .takeIf { it.isNotEmpty() }
+            ?.let {
+                val wallpaperCategory =
+                    WallpaperCategory(
+                        context.getString(R.string.on_device_wallpapers_category_title),
+                        context.getString(R.string.on_device_wallpaper_collection_id),
+                        it,
+                        PRIORITY_ON_DEVICE
+                    )
+                categoryFactory.getCategoryModel(context, wallpaperCategory)
+            }
+    }
+
+    /** This method is used for fetching the system categories. */
+    suspend fun getSystemCategories(): List<CategoryModel> {
+        val partnerRes = partnerProvider.resources
+        val packageName = partnerProvider.packageName
+        val categories = mutableListOf<Category>()
+        val categoryModels = mutableListOf<CategoryModel>()
+        if (partnerRes == null || packageName == null) {
+            return categoryModels
+        }
+
+        val wallpapersResId =
+            partnerRes.getIdentifier(PartnerProvider.WALLPAPER_RES_ID, "xml", packageName)
+        // Certain partner configurations don't have wallpapers provided, so need to check;
+        // return early if they are missing.
+        if (wallpapersResId == 0) {
+            return categoryModels
+        }
+
+        try {
+            val parser = partnerRes.getXml(wallpapersResId)
+            val depth = parser.depth
+            var type: Int
+            while (
+                parser.next().also { type = it } != XmlPullParser.END_TAG ||
+                    parser.depth > depth && type != XmlPullParser.END_DOCUMENT
+            ) {
+                if (type == XmlPullParser.START_TAG && WallpaperCategory.TAG_NAME == parser.name) {
+                    val category = wallpaperXMLParser.parseCategory(parser)
+                    category?.let { categories.add(it) }
+                }
+            }
+        } catch (e: Exception) {
+            when (e) {
+                is IOException,
+                is XmlPullParserException -> {
+                    Log.w(TAG, "Couldn't read system wallpapers definition", e)
+                    return emptyList()
+                }
+                else -> throw e
+            }
+        }
+        return categories.map { category -> categoryFactory.getCategoryModel(context, category) }
+    }
+
+    private fun getLocale(): Locale {
+        return context.resources.configuration.locales.get(0)
+    }
+
+    private fun getPrivateDeviceWallpapers(): Collection<WallpaperInfo?>? {
+        return null
+    }
+
+    companion object {
+        private const val TAG = "DefaultWallpaperCategoryClient"
+
+        /**
+         * Relative category priorities. Lower numbers correspond to higher priorities (i.e., should
+         * appear higher in the categories list).
+         */
+        const val PRIORITY_MY_PHOTOS_WHEN_CREATIVE_WALLPAPERS_DISABLED = 1
+        private const val PRIORITY_MY_PHOTOS_WHEN_CREATIVE_WALLPAPERS_ENABLED = 51
+        private const val PRIORITY_SYSTEM = 100
+        private const val PRIORITY_ON_DEVICE = 200
+        private const val PRIORITY_LIVE = 300
+        private const val PRIORITY_THIRD_PARTY = 400
+        const val CREATIVE_CATEGORY_PRIORITY = 1
+    }
+}
diff --git a/src/com/android/wallpaper/picker/customization/animation/view/LoadingAnimation.kt b/src/com/android/wallpaper/picker/customization/animation/view/LoadingAnimation.kt
index 175516f..95a3be6 100644
--- a/src/com/android/wallpaper/picker/customization/animation/view/LoadingAnimation.kt
+++ b/src/com/android/wallpaper/picker/customization/animation/view/LoadingAnimation.kt
@@ -111,8 +111,12 @@
 
         elapsedTime = seed ?: (0L..10000L).random()
 
+        fadeInAnimator?.removeAllListeners()
+        fadeInAnimator?.removeAllUpdateListeners()
         fadeInAnimator?.cancel()
         timeAnimator?.cancel()
+        revealAnimator?.removeAllListeners()
+        revealAnimator?.removeAllUpdateListeners()
         revealAnimator?.cancel()
 
         fadeInAnimator =
@@ -159,7 +163,11 @@
         )
             return
 
-        if (animationState == AnimationState.FADE_IN_PLAYING) fadeInAnimator?.cancel()
+        if (animationState == AnimationState.FADE_IN_PLAYING) {
+            fadeInAnimator?.removeAllListeners()
+            fadeInAnimator?.removeAllUpdateListeners()
+            fadeInAnimator?.cancel()
+        }
 
         animationState = AnimationState.REVEAL_PLAYING
 
@@ -221,7 +229,11 @@
         )
             return
 
-        if (animationState == AnimationState.FADE_IN_PLAYING) fadeInAnimator?.cancel()
+        if (animationState == AnimationState.FADE_IN_PLAYING) {
+            fadeInAnimator?.removeAllListeners()
+            fadeInAnimator?.removeAllUpdateListeners()
+            fadeInAnimator?.cancel()
+        }
 
         animationState = AnimationState.FADE_OUT_PLAYING
 
@@ -329,6 +341,8 @@
 
     /** Cancels the animation. Unlike end() , cancel() causes the animation to stop in its tracks */
     fun cancel() {
+        fadeInAnimator?.removeAllListeners()
+        fadeInAnimator?.removeAllUpdateListeners()
         fadeInAnimator?.cancel()
         timeAnimator?.cancel()
         revealAnimator?.removeAllListeners()
@@ -338,6 +352,8 @@
 
     /** Ends the animation, and causes the animation to skip to the end state */
     fun end() {
+        fadeInAnimator?.removeAllListeners()
+        fadeInAnimator?.removeAllUpdateListeners()
         fadeInAnimator?.end()
         timeAnimator?.end()
         revealAnimator?.removeAllListeners()
diff --git a/src/com/android/wallpaper/picker/customization/data/content/WallpaperClient.kt b/src/com/android/wallpaper/picker/customization/data/content/WallpaperClient.kt
index 649a140..bead9ae 100644
--- a/src/com/android/wallpaper/picker/customization/data/content/WallpaperClient.kt
+++ b/src/com/android/wallpaper/picker/customization/data/content/WallpaperClient.kt
@@ -22,13 +22,13 @@
 import android.graphics.Bitmap
 import android.graphics.Point
 import android.graphics.Rect
+import com.android.wallpaper.asset.Asset
 import com.android.wallpaper.module.logging.UserEventLogger.SetWallpaperEntryPoint
 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
 import com.android.wallpaper.picker.customization.shared.model.WallpaperModel
 import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
-import java.io.InputStream
 import kotlinx.coroutines.flow.Flow
 
 /** Defines interface for classes that can interact with the Wallpaper API. */
@@ -48,16 +48,17 @@
      * @param wallpaperModel The wallpaper model of the wallpaper.
      * @param bitmap The bitmap of the static wallpaper. Note that the bitmap should be the
      *   original, full-size bitmap.
-     * @param wallpaperSize raw wallpaper size
-     * @param fullPreviewCropModels full preview crop info for each dimension that user has cropped
+     * @param wallpaperSize raw wallpaper size.
+     * @param asset wallpaper asset.
+     * @param fullPreviewCropModels full preview crop info for each dimension that user has cropped.
      */
     suspend fun setStaticWallpaper(
         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperModel: StaticWallpaperModel,
-        inputStream: InputStream?,
         bitmap: Bitmap,
         wallpaperSize: Point,
+        asset: Asset,
         fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
     )
 
diff --git a/src/com/android/wallpaper/picker/customization/data/content/WallpaperClientImpl.kt b/src/com/android/wallpaper/picker/customization/data/content/WallpaperClientImpl.kt
index 7edc234..5e6ddfd 100644
--- a/src/com/android/wallpaper/picker/customization/data/content/WallpaperClientImpl.kt
+++ b/src/com/android/wallpaper/picker/customization/data/content/WallpaperClientImpl.kt
@@ -35,9 +35,13 @@
 import android.net.Uri
 import android.os.Looper
 import android.util.Log
-import androidx.collection.ArrayMap
+import com.android.app.tracing.TraceUtils.traceAsync
+import com.android.wallpaper.asset.Asset
 import com.android.wallpaper.asset.BitmapUtils
+import com.android.wallpaper.asset.CurrentWallpaperAsset
+import com.android.wallpaper.asset.StreamableAsset
 import com.android.wallpaper.model.CreativeCategory
+import com.android.wallpaper.model.CreativeWallpaperInfo
 import com.android.wallpaper.model.LiveWallpaperPrefMetadata
 import com.android.wallpaper.model.StaticWallpaperPrefMetadata
 import com.android.wallpaper.model.WallpaperInfo
@@ -54,9 +58,12 @@
 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
 import com.android.wallpaper.util.WallpaperCropUtils
+import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getCommonWallpaperData
+import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getCreativeWallpaperData
 import java.io.IOException
 import java.io.InputStream
 import java.util.EnumMap
+import kotlinx.coroutines.CancellableContinuation
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.callbackFlow
@@ -131,44 +138,48 @@
         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperModel: StaticWallpaperModel,
-        inputStream: InputStream?,
         bitmap: Bitmap,
         wallpaperSize: Point,
+        asset: Asset,
         fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
     ) {
         if (destination == HOME || destination == BOTH) {
-            // Disable rotation wallpaper when setting to home screen. Daily rotation rotates both
-            // home and lock screen wallpaper when lock screen is not set; otherwise daily rotation
-            // only rotates home screen while lock screen wallpaper stays as what it's set to.
+            // Disable rotation wallpaper when setting to home screen. Daily rotation rotates
+            // both home and lock screen wallpaper when lock screen is not set; otherwise daily
+            // rotation only rotates home screen while lock screen wallpaper stays as what it's
+            // set to.
             stopWallpaperRotation()
         }
 
-        val cropHintsWithParallax =
-            fullPreviewCropModels?.let { cropModels ->
-                cropModels.mapValues { it.value.adjustCropForParallax(wallpaperSize) }
-            }
-                ?: emptyMap()
-        val managerId =
-            wallpaperManager.setStaticWallpaperToSystem(
-                inputStream,
-                bitmap,
-                cropHintsWithParallax,
-                destination,
+        traceAsync(TAG, "setStaticWallpaper") {
+            val cropHintsWithParallax =
+                fullPreviewCropModels?.let { cropModels ->
+                    cropModels.mapValues { it.value.adjustCropForParallax(wallpaperSize) }
+                }
+                    ?: emptyMap()
+            val managerId =
+                wallpaperManager.setStaticWallpaperToSystem(
+                    asset.getStream(),
+                    bitmap,
+                    cropHintsWithParallax,
+                    destination,
+                    asset,
+                )
+
+            wallpaperPreferences.setStaticWallpaperMetadata(
+                metadata = wallpaperModel.getMetadata(bitmap, managerId),
+                destination = destination,
             )
 
-        wallpaperPreferences.setStaticWallpaperMetadata(
-            metadata = wallpaperModel.getMetadata(bitmap, managerId),
-            destination = destination,
-        )
-
-        // Save the static wallpaper to recent wallpapers
-        // TODO(b/309138446): check if we can update recent with all cropHints from WM later
-        wallpaperPreferences.addStaticWallpaperToRecentWallpapers(
-            destination,
-            wallpaperModel,
-            bitmap,
-            cropHintsWithParallax,
-        )
+            // Save the static wallpaper to recent wallpapers
+            // TODO(b/309138446): check if we can update recent with all cropHints from WM later
+            wallpaperPreferences.addStaticWallpaperToRecentWallpapers(
+                destination,
+                wallpaperModel,
+                bitmap,
+                cropHintsWithParallax,
+            )
+        }
     }
 
     private fun stopWallpaperRotation() {
@@ -188,8 +199,11 @@
         bitmap: Bitmap,
         cropHints: Map<Point, Rect>,
         destination: WallpaperDestination,
+        asset: Asset,
     ): Int {
-        return if (inputStream != null) {
+        // The InputStream of current wallpaper points to system wallpaper file which will be
+        // overwritten during set wallpaper and reads 0 bytes, use Bitmap instead.
+        return if (inputStream != null && asset !is CurrentWallpaperAsset) {
             setStreamWithCrops(
                 inputStream,
                 cropHints,
@@ -254,46 +268,73 @@
         wallpaperModel: LiveWallpaperModel,
     ) {
         if (destination == HOME || destination == BOTH) {
-            // Disable rotation wallpaper when setting to home screen. Daily rotation rotates both
-            // home and lock screen wallpaper when lock screen is not set; otherwise daily rotation
-            // only rotates home screen while lock screen wallpaper stays as what it's set to.
+            // Disable rotation wallpaper when setting to home screen. Daily rotation rotates
+            // both home and lock screen wallpaper when lock screen is not set; otherwise daily
+            // rotation only rotates home screen while lock screen wallpaper stays as what it's
+            // set to.
             stopWallpaperRotation()
         }
 
-        if (wallpaperModel.creativeWallpaperData != null) {
-            saveCreativeWallpaperAtExternal(wallpaperModel, destination)
+        traceAsync(TAG, "setLiveWallpaper") {
+            val updatedWallpaperModel =
+                wallpaperModel.creativeWallpaperData?.let {
+                    saveCreativeWallpaperAtExternal(wallpaperModel, destination)
+                }
+                    ?: wallpaperModel
+
+            val managerId =
+                wallpaperManager.setLiveWallpaperToSystem(updatedWallpaperModel, destination)
+
+            wallpaperPreferences.setLiveWallpaperMetadata(
+                metadata = updatedWallpaperModel.getMetadata(managerId),
+                destination = destination,
+            )
+
+            wallpaperPreferences.addLiveWallpaperToRecentWallpapers(
+                destination,
+                updatedWallpaperModel
+            )
         }
-
-        val managerId = wallpaperManager.setLiveWallpaperToSystem(wallpaperModel, destination)
-
-        wallpaperPreferences.setLiveWallpaperMetadata(
-            metadata = wallpaperModel.getMetadata(managerId),
-            destination = destination,
-        )
-
-        wallpaperPreferences.addLiveWallpaperToRecentWallpapers(destination, wallpaperModel)
     }
 
-    /** Call the external app to save the creative wallpaper. */
+    /**
+     * Call the external app to save the creative wallpaper, and return an updated model based on
+     * the response.
+     */
     private fun saveCreativeWallpaperAtExternal(
         wallpaperModel: LiveWallpaperModel,
         destination: WallpaperDestination,
-    ) {
+    ): LiveWallpaperModel? {
         wallpaperModel.getSaveWallpaperUriAndAuthority(destination)?.let { (uri, authority) ->
             try {
                 context.contentResolver.acquireContentProviderClient(authority).use { client ->
-                    client?.query(
-                        /* url= */ uri,
-                        /* projection= */ null,
-                        /* selection= */ null,
-                        /* selectionArgs= */ null,
-                        /* sortOrder= */ null,
+                    val cursor =
+                        client?.query(
+                            /* url= */ uri,
+                            /* projection= */ null,
+                            /* selection= */ null,
+                            /* selectionArgs= */ null,
+                            /* sortOrder= */ null,
+                        )
+                    if (cursor == null || !cursor.moveToFirst()) return null
+                    val info =
+                        CreativeWallpaperInfo.buildFromCursor(
+                            wallpaperModel.liveWallpaperData.systemWallpaperInfo,
+                            cursor
+                        )
+                    // NB: need to regenerate common data to update the thumbnail asset
+                    return LiveWallpaperModel(
+                        info.getCommonWallpaperData(context),
+                        wallpaperModel.liveWallpaperData,
+                        info.getCreativeWallpaperData(),
+                        wallpaperModel.internalLiveWallpaperData
                     )
                 }
             } catch (e: Exception) {
                 Log.e(TAG, "Failed updating creative live wallpaper at external.")
             }
         }
+        return null
     }
 
     /**
@@ -392,11 +433,14 @@
         updateValues.put(KEY_ID, wallpaperId)
         updateValues.put(KEY_SCREEN, destination.asString())
         updateValues.put(KEY_SET_WALLPAPER_ENTRY_POINT, setWallpaperEntryPoint)
-        val updatedRowCount = context.contentResolver.update(SET_WALLPAPER_URI, updateValues, null)
-        if (updatedRowCount == 0) {
-            Log.e(TAG, "Error setting wallpaper: $wallpaperId")
+        traceAsync(TAG, "setRecentWallpaper") {
+            val updatedRowCount =
+                context.contentResolver.update(SET_WALLPAPER_URI, updateValues, null)
+            if (updatedRowCount == 0) {
+                Log.e(TAG, "Error setting wallpaper: $wallpaperId")
+            }
+            onDone.invoke()
         }
-        onDone.invoke()
     }
 
     private suspend fun queryRecentWallpapers(
@@ -556,19 +600,13 @@
         @SetWallpaperFlags which: Int
     ): Map<Point, Rect>? {
         val flags = InjectorProvider.getInjector().getFlags()
-        val isMultiCropEnabled = flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()
-        if (!isMultiCropEnabled) {
+        if (!flags.isMultiCropEnabled()) {
             return null
         }
         val cropHints: List<Rect>? =
             wallpaperManager.getBitmapCrops(displaySizes, which, /* originalBitmap= */ true)
-        val cropHintsMap: MutableMap<Point, Rect> = ArrayMap()
-        if (cropHints != null) {
-            for (i in cropHints.indices) {
-                cropHintsMap[displaySizes[i]] = cropHints[i]
-            }
-        }
-        return cropHintsMap
+
+        return cropHints?.indices?.associate { displaySizes[it] to cropHints[it] }
     }
 
     override suspend fun getWallpaperColors(
@@ -612,7 +650,7 @@
             WallpaperCropUtils.calculateCropRect(
                     context,
                     it.hostViewSize,
-                    it.cropSurfaceSize,
+                    it.cropViewSize,
                     wallpaperSize,
                     cropHint,
                     it.wallpaperZoom,
@@ -623,6 +661,15 @@
             ?: cropHint
     }
 
+    private suspend fun Asset.getStream(): InputStream? =
+        suspendCancellableCoroutine { k: CancellableContinuation<InputStream?> ->
+            if (this is StreamableAsset) {
+                fetchInputStream { k.resumeWith(Result.success(it)) }
+            } else {
+                k.resumeWith(Result.success(null))
+            }
+        }
+
     companion object {
         private const val TAG = "WallpaperClientImpl"
         private const val AUTHORITY = "com.google.android.apps.wallpaper.recents"
diff --git a/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepository.kt b/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepository.kt
index ec3e58c..ac69bdd 100644
--- a/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepository.kt
+++ b/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepository.kt
@@ -22,6 +22,7 @@
 import android.graphics.Point
 import android.graphics.Rect
 import android.util.LruCache
+import com.android.wallpaper.asset.Asset
 import com.android.wallpaper.module.WallpaperPreferences
 import com.android.wallpaper.module.logging.UserEventLogger.SetWallpaperEntryPoint
 import com.android.wallpaper.picker.customization.data.content.WallpaperClient
@@ -30,7 +31,6 @@
 import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
-import java.io.InputStream
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
@@ -124,9 +124,9 @@
         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperModel: StaticWallpaperModel,
-        inputStream: InputStream?,
         bitmap: Bitmap,
         wallpaperSize: Point,
+        asset: Asset,
         fullPreviewCropModels: Map<Point, FullPreviewCropModel>? = null,
     ) {
         // TODO(b/303317694): provide set wallpaper status as flow
@@ -135,9 +135,9 @@
                 setWallpaperEntryPoint,
                 destination,
                 wallpaperModel,
-                inputStream,
                 bitmap,
                 wallpaperSize,
+                asset,
                 fullPreviewCropModels,
             )
         }
diff --git a/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt b/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt
index 891177b..62ac400 100644
--- a/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt
@@ -134,7 +134,7 @@
 
         val flags = BaseFlags.get()
         val isPageTransitionsFeatureEnabled = flags.isPageTransitionsFeatureEnabled(activity)
-        val isMultiCropEnabled = flags.isMultiCropEnabled() && flags.isMultiCropPreviewUiEnabled()
+        val isMultiCropEnabled = flags.isMultiCropEnabled()
 
         val showLoadingAnimation =
             flags.isPreviewLoadingAnimationEnabled(activity.applicationContext)
diff --git a/src/com/android/wallpaper/picker/data/CreativeWallpaperData.kt b/src/com/android/wallpaper/picker/data/CreativeWallpaperData.kt
index 2b50acb..8c5362a 100644
--- a/src/com/android/wallpaper/picker/data/CreativeWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/CreativeWallpaperData.kt
@@ -29,4 +29,5 @@
     val description: String,
     val contentDescription: String?,
     val isCurrent: Boolean,
+    val creativeWallpaperEffectsData: CreativeWallpaperEffectsData?,
 )
diff --git a/src/com/android/wallpaper/picker/data/CreativeWallpaperEffectsData.kt b/src/com/android/wallpaper/picker/data/CreativeWallpaperEffectsData.kt
new file mode 100644
index 0000000..b7d6897
--- /dev/null
+++ b/src/com/android/wallpaper/picker/data/CreativeWallpaperEffectsData.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 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.wallpaper.picker.data
+
+import android.net.Uri
+
+/** Represents data that is specific to only effects for CreativeWallpapers. */
+data class CreativeWallpaperEffectsData(
+    val effectsBottomSheetTitle: String,
+    val effectsBottomSheetSubtitle: String,
+    val currentEffectId: String,
+    val clearActionUri: Uri,
+    val effectsUri: Uri,
+)
diff --git a/src/com/android/wallpaper/picker/data/DownloadableWallpaperData.kt b/src/com/android/wallpaper/picker/data/DownloadableWallpaperData.kt
index a739ab8..a6a95b2 100644
--- a/src/com/android/wallpaper/picker/data/DownloadableWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/DownloadableWallpaperData.kt
@@ -24,5 +24,4 @@
     val systemWallpaperInfo: WallpaperInfo,
     val isTitleVisible: Boolean,
     val isApplied: Boolean,
-    val effectNames: String?,
 )
diff --git a/src/com/android/wallpaper/picker/data/LiveWallpaperData.kt b/src/com/android/wallpaper/picker/data/LiveWallpaperData.kt
index 73180f3..7efa2ea 100644
--- a/src/com/android/wallpaper/picker/data/LiveWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/LiveWallpaperData.kt
@@ -24,5 +24,6 @@
     val systemWallpaperInfo: WallpaperInfo,
     val isTitleVisible: Boolean,
     val isApplied: Boolean,
+    val isEffectWallpaper: Boolean,
     val effectNames: String?
 )
diff --git a/src/com/android/wallpaper/picker/data/category /CollectionCategoryData.kt b/src/com/android/wallpaper/picker/data/category /CollectionCategoryData.kt
index 80d9cb3..a02cbab 100644
--- a/src/com/android/wallpaper/picker/data/category /CollectionCategoryData.kt
+++ b/src/com/android/wallpaper/picker/data/category /CollectionCategoryData.kt
@@ -21,7 +21,7 @@
 
 /** Represents set of attributes that depict a collection of wallpapers. */
 data class CollectionCategoryData(
-    val wallpaperModels: List<WallpaperModel>,
+    val wallpaperModels: MutableList<WallpaperModel>,
     val thumbAsset: Asset,
     val featuredThumbnailIndex: Int,
     val isSingleWallpaperCategory: Boolean
diff --git a/src/com/android/wallpaper/picker/preview/data/repository/CreativeEffectsRepository.kt b/src/com/android/wallpaper/picker/preview/data/repository/CreativeEffectsRepository.kt
new file mode 100644
index 0000000..1b520c6
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/data/repository/CreativeEffectsRepository.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.picker.preview.data.repository
+
+import android.content.ContentValues
+import android.content.Context
+import android.net.Uri
+import android.util.Log
+import com.android.wallpaper.model.WallpaperAction
+import com.android.wallpaper.model.WallpaperInfoContract
+import com.android.wallpaper.picker.data.CreativeWallpaperEffectsData
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
+import com.android.wallpaper.picker.preview.shared.model.CreativeEffectsModel
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.android.scopes.ActivityRetainedScoped
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.withContext
+
+@ActivityRetainedScoped
+class CreativeEffectsRepository
+@Inject
+constructor(
+    @ApplicationContext private val context: Context,
+    @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
+) {
+
+    private val _creativeEffectsModel = MutableStateFlow<CreativeEffectsModel?>(null)
+    val creativeEffectsModel = _creativeEffectsModel.asStateFlow()
+
+    private var clearActionUri: Uri? = null
+
+    suspend fun initializeEffect(data: CreativeWallpaperEffectsData) {
+        withContext(bgDispatcher) {
+            clearActionUri = data.clearActionUri
+            try {
+                data.effectsUri.authority
+                    ?.let { context.contentResolver.acquireContentProviderClient(it) }
+                    ?.use { it.query(data.effectsUri, null, null, null, null) }
+                    ?.use { effectsCursor ->
+                        while (effectsCursor.moveToNext()) {
+                            val effectsToggleUri =
+                                Uri.parse(
+                                    effectsCursor.getString(
+                                        effectsCursor.getColumnIndex(
+                                            WallpaperInfoContract.WALLPAPER_EFFECTS_TOGGLE_URI
+                                        )
+                                    )
+                                )
+                            val effectsButtonLabel: String =
+                                effectsCursor.getString(
+                                    effectsCursor.getColumnIndex(
+                                        WallpaperInfoContract.WALLPAPER_EFFECTS_BUTTON_LABEL
+                                    )
+                                )
+                            val effectsId: String =
+                                effectsCursor.getString(
+                                    effectsCursor.getColumnIndex(
+                                        WallpaperInfoContract.WALLPAPER_EFFECTS_TOGGLE_ID
+                                    )
+                                )
+                            _creativeEffectsModel.value =
+                                CreativeEffectsModel(
+                                    title = data.effectsBottomSheetTitle,
+                                    subtitle = data.effectsBottomSheetSubtitle,
+                                    actions =
+                                        listOf(
+                                            WallpaperAction(
+                                                label = effectsButtonLabel,
+                                                applyActionUri = effectsToggleUri,
+                                                effectId = effectsId,
+                                                toggled = effectsId == data.currentEffectId,
+                                            )
+                                        ),
+                                )
+                        }
+                    }
+            } catch (e: Exception) {
+                Log.e(TAG, "Read wallpaper effects with exception.", e)
+            }
+        }
+    }
+
+    suspend fun turnOnCreativeEffect(actionPosition: Int) {
+        withContext(bgDispatcher) {
+            val clearActionUri =
+                clearActionUri
+                    ?: throw NullPointerException(
+                        "clearActionUri should be initialized already if creative wallpaper" +
+                            " effects are available."
+                    )
+            val model = _creativeEffectsModel.value ?: return@withContext
+            val updatedActions =
+                model.actions.mapIndexed { index, action ->
+                    val applyActionUri = action.applyActionUri
+                    if (actionPosition == index && applyActionUri != null) {
+                        context.contentResolver.update(applyActionUri, ContentValues(), null)
+                    }
+                    action.copy(toggled = actionPosition == index && applyActionUri != null)
+                }
+            if (actionPosition < 0) {
+                context.contentResolver.update(clearActionUri, ContentValues(), null)
+            }
+            _creativeEffectsModel.value = model.copy(actions = updatedActions)
+        }
+    }
+
+    fun destroy() {
+        _creativeEffectsModel.value = null
+        clearActionUri = null
+    }
+
+    companion object {
+        private const val TAG = "CreativeEffectsRepository"
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/data/repository/EffectsRepository.kt b/src/com/android/wallpaper/picker/preview/data/repository/ImageEffectsRepository.kt
similarity index 68%
rename from src/com/android/wallpaper/picker/preview/data/repository/EffectsRepository.kt
rename to src/com/android/wallpaper/picker/preview/data/repository/ImageEffectsRepository.kt
index 0fd887e..699de62 100644
--- a/src/com/android/wallpaper/picker/preview/data/repository/EffectsRepository.kt
+++ b/src/com/android/wallpaper/picker/preview/data/repository/ImageEffectsRepository.kt
@@ -24,12 +24,17 @@
 import android.content.pm.PackageManager
 import android.net.Uri
 import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
 import android.service.wallpaper.WallpaperService
+import android.stats.style.StyleEnums
 import android.util.Log
 import com.android.wallpaper.config.BaseFlags
 import com.android.wallpaper.effects.Effect
 import com.android.wallpaper.effects.EffectContract
 import com.android.wallpaper.effects.EffectsController
+import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
+import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.picker.data.LiveWallpaperData
 import com.android.wallpaper.picker.data.WallpaperId
 import com.android.wallpaper.picker.data.WallpaperModel
@@ -38,21 +43,22 @@
 import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
 import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.EffectTextRes
 import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.android.scopes.ActivityRetainedScoped
 import java.io.IOException
 import javax.inject.Inject
-import javax.inject.Singleton
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.withContext
 import org.xmlpull.v1.XmlPullParserException
 
-@Singleton
-class EffectsRepository
+@ActivityRetainedScoped
+class ImageEffectsRepository
 @Inject
 constructor(
     @ApplicationContext private val context: Context,
     private val effectsController: EffectsController,
+    private val logger: UserEventLogger,
     @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
 ) {
     enum class EffectStatus {
@@ -62,31 +68,43 @@
         EFFECT_DOWNLOAD_IN_PROGRESS,
         EFFECT_APPLY_IN_PROGRESS,
         EFFECT_APPLIED,
+        EFFECT_DOWNLOAD_FAILED,
     }
 
     private val _effectStatus = MutableStateFlow(EffectStatus.EFFECT_DISABLE)
     val effectStatus = _effectStatus.asStateFlow()
-    val wallpaperEffect = MutableStateFlow<Effect?>(null)
+    private val _wallpaperEffect = MutableStateFlow<Effect?>(null)
+    val wallpaperEffect = _wallpaperEffect.asStateFlow()
     // This StaticWallpaperModel is set when initializing the repository and used for
     // 1. Providing essential data to construct LiveWallpaperData when effect is enabled
     // 2. Reverting back to the original static image wallpaper when effect is disabled
     private lateinit var staticWallpaperModel: StaticWallpaperModel
     private lateinit var onWallpaperUpdated: (wallpaper: WallpaperModel) -> Unit
 
+    private val timeOutHandler: Handler = Handler(Looper.getMainLooper())
+    private var startGeneratingTime = 0L
+    private var startDownloadTime = 0L
+
+    /** Returns whether effects are available at all on the device */
+    fun areEffectsAvailable(): Boolean {
+        return effectsController.areEffectsAvailable()
+    }
+
     suspend fun initializeEffect(
         staticWallpaperModel: StaticWallpaperModel,
         onWallpaperModelUpdated: (wallpaper: WallpaperModel) -> Unit
     ) {
         this.staticWallpaperModel = staticWallpaperModel
         onWallpaperUpdated = onWallpaperModelUpdated
+
         withContext(bgDispatcher) {
             val listener =
                 EffectsController.EffectsServiceListener {
-                    _,
+                    effect,
                     bundle,
                     resultCode,
                     originalStatusCode,
-                    errorMessage ->
+                    _ ->
                     when (resultCode) {
                         EffectsController.RESULT_PROBE_SUCCESS -> {
                             _effectStatus.value = EffectStatus.EFFECT_READY
@@ -103,36 +121,52 @@
                             _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_IN_PROGRESS
                         }
                         EffectsController.RESULT_FOREGROUND_DOWNLOAD_SUCCEEDED -> {
-                            // TODO logger.logEffectForegroundDownload
+                            logger.logEffectForegroundDownload(
+                                getEffectNameForLogging(),
+                                StyleEnums.EFFECT_APPLIED_ON_SUCCESS,
+                                System.currentTimeMillis() - startDownloadTime,
+                            )
                             _effectStatus.value = EffectStatus.EFFECT_READY
                         }
-                        EffectsController.RESULT_FOREGROUND_DOWNLOAD_FAILED -> {
-                            // TODO logger.logEffectForegroundDownload
-                            _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_READY
+                        EffectsController.RESULT_FOREGROUND_DOWNLOAD_FAILED,
+                        EffectsController.RESULT_ERROR_TRY_AGAIN_LATER -> {
+                            logger.logEffectForegroundDownload(
+                                getEffectNameForLogging(),
+                                StyleEnums.EFFECT_APPLIED_ON_FAILED,
+                                System.currentTimeMillis() - startDownloadTime,
+                            )
+                            _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_FAILED
                         }
-                        EffectsController.RESULT_SUCCESS -> {
-                            _effectStatus.value = EffectStatus.EFFECT_APPLIED
-                            // TODO logger.logEffectApply
-                            bundle.getCinematicWallpaperModel()?.let {
-                                onWallpaperUpdated.invoke(it)
-                            }
-                        }
+                        EffectsController.RESULT_SUCCESS,
                         EffectsController.RESULT_SUCCESS_WITH_GENERATION_ERROR -> {
                             _effectStatus.value = EffectStatus.EFFECT_APPLIED
-                            // TODO logger.logEffectApply
-                            bundle.getCinematicWallpaperModel()?.let {
+                            logger.logEffectApply(
+                                getEffectNameForLogging(),
+                                StyleEnums.EFFECT_APPLIED_ON_SUCCESS,
+                                /* timeElapsedMillis= */ System.currentTimeMillis() -
+                                    startGeneratingTime,
+                                /* resultCode= */ originalStatusCode
+                            )
+                            bundle.getCinematicWallpaperModel(effect)?.let {
                                 onWallpaperUpdated.invoke(it)
                             }
                         }
                         EffectsController.RESULT_SUCCESS_REUSED -> {
                             _effectStatus.value = EffectStatus.EFFECT_APPLIED
-                            bundle.getCinematicWallpaperModel()?.let {
+                            bundle.getCinematicWallpaperModel(effect)?.let {
                                 onWallpaperUpdated.invoke(it)
                             }
                         }
                         else -> {
                             // TODO onImageEffectFailed
-                            _effectStatus.value = EffectStatus.EFFECT_READY
+                            _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_FAILED
+                            logger.logEffectApply(
+                                getEffectNameForLogging(),
+                                StyleEnums.EFFECT_APPLIED_ON_FAILED,
+                                /* timeElapsedMillis= */ System.currentTimeMillis() -
+                                    startGeneratingTime,
+                                /* resultCode= */ originalStatusCode
+                            )
                         }
                     }
                 }
@@ -157,7 +191,7 @@
                         while (it.moveToNext()) {
                             val titleRow: Int = it.getColumnIndex(EffectContract.KEY_EFFECT_TITLE)
                             val idRow: Int = it.getColumnIndex(EffectContract.KEY_EFFECT_ID)
-                            wallpaperEffect.value =
+                            _wallpaperEffect.value =
                                 Effect(
                                     it.getInt(idRow),
                                     it.getString(titleRow),
@@ -175,7 +209,9 @@
         }
     }
 
-    private fun Bundle.getCinematicWallpaperModel(): LiveWallpaperModel? {
+    private fun Bundle.getCinematicWallpaperModel(
+        effect: EffectEnumInterface
+    ): LiveWallpaperModel? {
         val componentName =
             if (containsKey(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT)) {
                 getParcelable<ComponentName>(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT)
@@ -219,7 +255,8 @@
                     systemWallpaperInfo = wallpaperInfo,
                     isTitleVisible = false,
                     isApplied = false,
-                    effectNames = null,
+                    isEffectWallpaper = effectsController.isEffectsWallpaper(wallpaperInfo),
+                    effectNames = effect.toString(),
                 )
             return LiveWallpaperModel(
                 commonWallpaperData = commonWallpaperData,
@@ -236,7 +273,8 @@
         }
     }
 
-    fun enableImageEffect(effect: EffectsController.EffectEnumInterface) {
+    fun enableImageEffect(effect: EffectEnumInterface) {
+        startGeneratingTime = System.currentTimeMillis()
         _effectStatus.value = EffectStatus.EFFECT_APPLY_IN_PROGRESS
         // TODO: Maybe we should call reconnect wallpaper if we have created a LiveWallpaperModel
         //       if (mLiveWallpaperInfo != null) {
@@ -245,20 +283,39 @@
         //       }
         val uri = staticWallpaperModel.imageWallpaperData?.uri ?: return
         effectsController.generateEffect(effect, uri)
-        // TODO: Implement time out
+        timeOutHandler.postDelayed(
+            {
+                wallpaperEffect.value?.let { effectsController.interruptGenerate(it) }
+                _effectStatus.value = EffectStatus.EFFECT_READY
+                logger.logEffectApply(
+                    getEffectNameForLogging(),
+                    StyleEnums.EFFECT_APPLIED_ON_FAILED,
+                    System.currentTimeMillis() - startGeneratingTime,
+                    EffectsController.ERROR_ORIGINAL_TIME_OUT,
+                )
+            },
+            TIME_OUT_TIME_IN_MS
+        )
     }
 
     fun disableImageEffect() {
         // TODO implement disabling effect
         _effectStatus.value = EffectStatus.EFFECT_READY
+        logger.logEffectApply(
+            wallpaperEffect.value?.type.toString(),
+            StyleEnums.EFFECT_APPLIED_OFF,
+            0L,
+            0,
+        )
         onWallpaperUpdated.invoke(staticWallpaperModel)
     }
 
     fun destroy() {
         effectsController.removeListener()
+        _wallpaperEffect.value = null
     }
 
-    fun isTargetEffect(effect: EffectsController.EffectEnumInterface): Boolean {
+    fun isTargetEffect(effect: EffectEnumInterface): Boolean {
         return effectsController.isTargetEffect(effect)
     }
 
@@ -272,7 +329,28 @@
         )
     }
 
+    /**
+     * This function triggers the downloading of the machine learning models. The downloading occurs
+     * in the foreground off the main thread so it's safe to trigger it from the main thread.
+     */
+    fun startEffectsModelDownload(effect: Effect) {
+        effectsController.startForegroundDownload(effect)
+        _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_IN_PROGRESS
+        startDownloadTime = System.currentTimeMillis()
+        logger.logEffectForegroundDownload(
+            getEffectNameForLogging(),
+            StyleEnums.EFFECT_APPLIED_STARTED,
+            0,
+        )
+    }
+
+    private fun getEffectNameForLogging(): String {
+        val effect = wallpaperEffect.value
+        return effect?.type?.toString() ?: EffectsController.Effect.UNKNOWN.toString()
+    }
+
     companion object {
         private const val TAG = "EffectsRepository"
+        private const val TIME_OUT_TIME_IN_MS = 90000L
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepository.kt b/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepository.kt
index 020593c..deaaca7 100644
--- a/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepository.kt
+++ b/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepository.kt
@@ -47,13 +47,24 @@
         _wallpaperModel.value = wallpaperModel
     }
 
-    private val _hasTooltipBeenShown: MutableStateFlow<Boolean> =
-        MutableStateFlow(preferences.getHasPreviewTooltipBeenShown())
-    val hasTooltipBeenShown: StateFlow<Boolean> = _hasTooltipBeenShown.asStateFlow()
+    private val _hasSmallPreviewTooltipBeenShown: MutableStateFlow<Boolean> =
+        MutableStateFlow(preferences.getHasFullPreviewTooltipBeenShown())
+    val hasSmallPreviewTooltipBeenShown: StateFlow<Boolean> =
+        _hasSmallPreviewTooltipBeenShown.asStateFlow()
 
-    fun dismissTooltip() {
-        _hasTooltipBeenShown.value = true
-        preferences.setHasPreviewTooltipBeenShown(true)
+    fun hideSmallPreviewTooltip() {
+        _hasSmallPreviewTooltipBeenShown.value = true
+        preferences.setHasSmallPreviewTooltipBeenShown(true)
+    }
+
+    private val _hasFullPreviewTooltipBeenShown: MutableStateFlow<Boolean> =
+        MutableStateFlow(preferences.getHasFullPreviewTooltipBeenShown())
+    val hasFullPreviewTooltipBeenShown: StateFlow<Boolean> =
+        _hasFullPreviewTooltipBeenShown.asStateFlow()
+
+    fun hideFullPreviewTooltip() {
+        _hasFullPreviewTooltipBeenShown.value = true
+        preferences.setHasFullPreviewTooltipBeenShown(true)
     }
 
     suspend fun downloadWallpaper(): LiveWallpaperDownloadResultModel? =
diff --git a/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt b/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt
index 1b471cd..870497e 100644
--- a/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt
+++ b/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt
@@ -16,9 +16,11 @@
 
 package com.android.wallpaper.picker.preview.domain.interactor
 
+import com.android.wallpaper.effects.Effect
 import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
 import com.android.wallpaper.picker.data.WallpaperModel
-import com.android.wallpaper.picker.preview.data.repository.EffectsRepository
+import com.android.wallpaper.picker.preview.data.repository.CreativeEffectsRepository
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository
 import com.android.wallpaper.picker.preview.data.repository.WallpaperPreviewRepository
 import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultModel
 import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
@@ -35,30 +37,36 @@
 @Inject
 constructor(
     private val wallpaperPreviewRepository: WallpaperPreviewRepository,
-    private val effectsRepository: EffectsRepository,
+    private val imageEffectsRepository: ImageEffectsRepository,
+    private val creativeEffectsRepository: CreativeEffectsRepository,
 ) {
     val wallpaperModel: StateFlow<WallpaperModel?> = wallpaperPreviewRepository.wallpaperModel
 
     private val _isDownloadingWallpaper = MutableStateFlow<Boolean>(false)
     val isDownloadingWallpaper: Flow<Boolean> = _isDownloadingWallpaper.asStateFlow()
 
-    val effectsStatus = effectsRepository.effectStatus
-    val effect = effectsRepository.wallpaperEffect
+    val imageEffectsStatus = imageEffectsRepository.effectStatus
+    val imageEffect = imageEffectsRepository.wallpaperEffect
+    val creativeEffectsModel = creativeEffectsRepository.creativeEffectsModel
+
+    suspend fun turnOnCreativeEffect(actionPosition: Int) {
+        creativeEffectsRepository.turnOnCreativeEffect(actionPosition)
+    }
 
     fun enableImageEffect(effect: EffectEnumInterface) {
-        effectsRepository.enableImageEffect(effect)
+        imageEffectsRepository.enableImageEffect(effect)
     }
 
     fun disableImageEffect() {
-        effectsRepository.disableImageEffect()
+        imageEffectsRepository.disableImageEffect()
     }
 
     fun isTargetEffect(effect: EffectEnumInterface): Boolean {
-        return effectsRepository.isTargetEffect(effect)
+        return imageEffectsRepository.isTargetEffect(effect)
     }
 
     fun getEffectTextRes(): WallpaperEffectsView2.EffectTextRes {
-        return effectsRepository.getEffectTextRes()
+        return imageEffectsRepository.getEffectTextRes()
     }
 
     suspend fun downloadWallpaper(): LiveWallpaperDownloadResultModel? {
@@ -67,4 +75,8 @@
         _isDownloadingWallpaper.value = false
         return wallpaperModel
     }
+
+    fun startEffectsMLDownload(effect: Effect) {
+        imageEffectsRepository.startEffectsModelDownload(effect)
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/domain/interactor/WallpaperPreviewInteractor.kt b/src/com/android/wallpaper/picker/preview/domain/interactor/WallpaperPreviewInteractor.kt
index 20da4f4..da6b835 100644
--- a/src/com/android/wallpaper/picker/preview/domain/interactor/WallpaperPreviewInteractor.kt
+++ b/src/com/android/wallpaper/picker/preview/domain/interactor/WallpaperPreviewInteractor.kt
@@ -20,6 +20,7 @@
 import android.graphics.Bitmap
 import android.graphics.Point
 import android.graphics.Rect
+import com.android.wallpaper.asset.Asset
 import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository
 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
@@ -28,7 +29,6 @@
 import com.android.wallpaper.picker.preview.data.repository.WallpaperPreviewRepository
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
 import dagger.hilt.android.scopes.ActivityRetainedScoped
-import java.io.InputStream
 import javax.inject.Inject
 import kotlinx.coroutines.flow.StateFlow
 
@@ -41,25 +41,30 @@
 ) {
     val wallpaperModel: StateFlow<WallpaperModel?> = wallpaperPreviewRepository.wallpaperModel
 
-    val hasTooltipBeenShown: StateFlow<Boolean> = wallpaperPreviewRepository.hasTooltipBeenShown
-    fun dismissTooltip() = wallpaperPreviewRepository.dismissTooltip()
+    val hasSmallPreviewTooltipBeenShown: StateFlow<Boolean> =
+        wallpaperPreviewRepository.hasSmallPreviewTooltipBeenShown
+    fun hideSmallPreviewTooltip() = wallpaperPreviewRepository.hideSmallPreviewTooltip()
+
+    val hasFullPreviewTooltipBeenShown: StateFlow<Boolean> =
+        wallpaperPreviewRepository.hasFullPreviewTooltipBeenShown
+    fun hideFullPreviewTooltip() = wallpaperPreviewRepository.hideFullPreviewTooltip()
 
     suspend fun setStaticWallpaper(
         @UserEventLogger.SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperModel: StaticWallpaperModel,
-        inputStream: InputStream?,
         bitmap: Bitmap,
         wallpaperSize: Point,
+        asset: Asset,
         fullPreviewCropModels: Map<Point, FullPreviewCropModel>? = null,
     ) {
         wallpaperRepository.setStaticWallpaper(
             setWallpaperEntryPoint,
             destination,
             wallpaperModel,
-            inputStream,
             bitmap,
             wallpaperSize,
+            asset,
             fullPreviewCropModels,
         )
     }
diff --git a/src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt b/src/com/android/wallpaper/picker/preview/shared/model/CreativeEffectsModel.kt
similarity index 65%
copy from src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt
copy to src/com/android/wallpaper/picker/preview/shared/model/CreativeEffectsModel.kt
index 4001f83..11cb86d 100644
--- a/src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt
+++ b/src/com/android/wallpaper/picker/preview/shared/model/CreativeEffectsModel.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -13,9 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.wallpaper.model.wallpaper
 
-enum class FoldableDisplay {
-    FOLDED,
-    UNFOLDED,
-}
+package com.android.wallpaper.picker.preview.shared.model
+
+import com.android.wallpaper.model.WallpaperAction
+
+data class CreativeEffectsModel(
+    val title: String,
+    val subtitle: String,
+    val actions: List<WallpaperAction>,
+)
diff --git a/src/com/android/wallpaper/picker/preview/shared/model/FullPreviewCropModel.kt b/src/com/android/wallpaper/picker/preview/shared/model/FullPreviewCropModel.kt
index 6e83b21..3d13184 100644
--- a/src/com/android/wallpaper/picker/preview/shared/model/FullPreviewCropModel.kt
+++ b/src/com/android/wallpaper/picker/preview/shared/model/FullPreviewCropModel.kt
@@ -44,5 +44,5 @@
     /** The size of the view hosting the wallpaper, e.g. SurfaceView. */
     val hostViewSize: Point,
     /** A larger version of hostViewSize that can safely contain parallax. */
-    val cropSurfaceSize: Point,
+    val cropViewSize: Point,
 )
diff --git a/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt b/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
index 74e8eff..e0fc0d1 100644
--- a/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
@@ -18,9 +18,9 @@
 import android.content.Context
 import android.content.Intent
 import android.content.pm.ActivityInfo
-import android.content.res.Configuration
 import android.graphics.Color
 import android.os.Bundle
+import android.view.Window
 import android.widget.Toast
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.activity.viewModels
@@ -28,11 +28,14 @@
 import androidx.lifecycle.lifecycleScope
 import androidx.navigation.fragment.NavHostFragment
 import com.android.wallpaper.R
+import com.android.wallpaper.model.ImageWallpaperInfo
 import com.android.wallpaper.model.WallpaperInfo
 import com.android.wallpaper.picker.AppbarFragment
 import com.android.wallpaper.picker.BasePreviewActivity
 import com.android.wallpaper.picker.data.WallpaperModel
-import com.android.wallpaper.picker.preview.data.repository.EffectsRepository
+import com.android.wallpaper.picker.di.modules.MainDispatcher
+import com.android.wallpaper.picker.preview.data.repository.CreativeEffectsRepository
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository
 import com.android.wallpaper.picker.preview.data.repository.WallpaperPreviewRepository
 import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
 import com.android.wallpaper.picker.preview.ui.fragment.SmallPreviewFragment
@@ -47,8 +50,8 @@
 import dagger.hilt.android.AndroidEntryPoint
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
 
 /** This activity holds the flow for the preview screen. */
 @AndroidEntryPoint(BasePreviewActivity::class)
@@ -58,25 +61,46 @@
     @Inject lateinit var displayUtils: DisplayUtils
     @Inject lateinit var wallpaperModelFactory: WallpaperModelFactory
     @Inject lateinit var wallpaperPreviewRepository: WallpaperPreviewRepository
-    @Inject lateinit var effectsRepository: EffectsRepository
+
+    @Inject lateinit var imageEffectsRepository: ImageEffectsRepository
+    @Inject lateinit var creativeEffectsRepository: CreativeEffectsRepository
     @Inject lateinit var liveWallpaperDownloader: LiveWallpaperDownloader
+    @MainDispatcher @Inject lateinit var mainScope: CoroutineScope
 
     private val wallpaperPreviewViewModel: WallpaperPreviewViewModel by viewModels()
 
     override fun onCreate(savedInstanceState: Bundle?) {
+        window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
         super.onCreate(savedInstanceState)
         enforcePortraitForHandheldAndFoldedDisplay()
+        wallpaperPreviewViewModel.updateDisplayConfiguration()
         window.navigationBarColor = Color.TRANSPARENT
         window.statusBarColor = Color.TRANSPARENT
         setContentView(R.layout.activity_wallpaper_preview)
+        val wallpaper =
+            checkNotNull(intent.getParcelableExtra(EXTRA_WALLPAPER_INFO, WallpaperInfo::class.java))
+                .convertToWallpaperModel()
+        val navController =
+            (supportFragmentManager.findFragmentById(R.id.wallpaper_preview_nav_host)
+                    as NavHostFragment)
+                .navController
+        val graph = navController.navInflater.inflate(R.navigation.wallpaper_preview_nav_graph)
+        val startDestinationArgs: Bundle? =
+            (wallpaper as? WallpaperModel.LiveWallpaperModel)
+                ?.let {
+                    if (it.isNewCreativeWallpaper()) it.getNewCreativeWallpaperArgs() else null
+                }
+                ?.also {
+                    // For creating a new creative wallpaper, replace the default start destination
+                    // with CreativeEditPreviewFragment.
+                    graph.setStartDestination(R.id.creativeEditPreviewFragment)
+                }
+        navController.setGraph(graph, startDestinationArgs)
         // Fits screen to navbar and statusbar
         WindowCompat.setDecorFitsSystemWindows(window, ActivityUtils.isSUWMode(this))
         val isAssetIdPresent = intent.getBooleanExtra(IS_ASSET_ID_PRESENT, false)
         wallpaperPreviewViewModel.isNewTask = intent.getBooleanExtra(IS_NEW_TASK, false)
         wallpaperPreviewViewModel.isViewAsHome = intent.getBooleanExtra(EXTRA_VIEW_AS_HOME, false)
-        val wallpaper =
-            checkNotNull(intent.getParcelableExtra(EXTRA_WALLPAPER_INFO, WallpaperInfo::class.java))
-                .convertToWallpaperModel()
         wallpaperPreviewRepository.setWallpaperModel(wallpaper)
         val whichPreview =
             if (isAssetIdPresent) WallpaperConnection.WhichPreview.EDIT_NON_CURRENT
@@ -97,9 +121,20 @@
             )
         }
 
-        if ((wallpaper as? WallpaperModel.StaticWallpaperModel)?.imageWallpaperData != null) {
+        val creativeWallpaperEffectData =
+            (wallpaper as? WallpaperModel.LiveWallpaperModel)
+                ?.creativeWallpaperData
+                ?.creativeWallpaperEffectsData
+        if (creativeWallpaperEffectData != null) {
             lifecycleScope.launch {
-                effectsRepository.initializeEffect(
+                creativeEffectsRepository.initializeEffect(creativeWallpaperEffectData)
+            }
+        } else if (
+            (wallpaper as? WallpaperModel.StaticWallpaperModel)?.imageWallpaperData != null &&
+                imageEffectsRepository.areEffectsAvailable()
+        ) {
+            lifecycleScope.launch {
+                imageEffectsRepository.initializeEffect(
                     staticWallpaperModel = wallpaper,
                     onWallpaperModelUpdated = { wallpaper ->
                         wallpaperPreviewRepository.setWallpaperModel(wallpaper)
@@ -107,28 +142,6 @@
                 )
             }
         }
-
-        val liveWallpaperModel = (wallpaper as? WallpaperModel.LiveWallpaperModel)
-        if (liveWallpaperModel != null && liveWallpaperModel.isNewCreativeWallpaper()) {
-            // If it's a new creative wallpaper, override the start destination to the fullscreen
-            // fragment for the create-new flow of creative wallpapers
-            val navController =
-                (supportFragmentManager.findFragmentById(R.id.wallpaper_preview_nav_host)
-                        as NavHostFragment)
-                    .navController
-            val navGraph =
-                navController.navInflater.inflate(R.navigation.wallpaper_preview_nav_graph)
-            navGraph.setStartDestination(R.id.creativeNewPreviewFragment)
-            navController.setGraph(
-                navGraph,
-                Bundle().apply {
-                    putParcelable(
-                        SmallPreviewFragment.ARG_EDIT_INTENT,
-                        liveWallpaperModel.liveWallpaperData.getEditActivityIntent()
-                    )
-                }
-            )
-        }
     }
 
     override fun onUpArrowPressed() {
@@ -148,17 +161,31 @@
     }
 
     override fun onDestroy() {
-        liveWallpaperDownloader.cleanup()
-        (wallpaperPreviewViewModel.wallpaper.value as? WallpaperModel.LiveWallpaperModel)?.let {
-            runBlocking { WallpaperConnectionUtils.disconnect(applicationContext, it) }
+        imageEffectsRepository.destroy()
+        creativeEffectsRepository.destroy()
+        // TODO(b/333879532): Only disconnect when leaving the Activity without introducing black
+        //  preview. If onDestroy is caused by an orientation change, we should keep the connection
+        //  to avoid initiating the engines again.
+        // TODO(b/328302105): MainScope ensures the job gets done non-blocking even if the
+        //   activity has been destroyed already. Consider making this part of
+        //   WallpaperConnectionUtils.
+        mainScope.launch {
+            liveWallpaperDownloader.cleanup()
+            (wallpaperPreviewViewModel.wallpaper.value as? WallpaperModel.LiveWallpaperModel)?.let {
+                WallpaperConnectionUtils.disconnect(
+                    appContext,
+                    it,
+                    wallpaperPreviewViewModel.smallerDisplaySize
+                )
+                WallpaperConnectionUtils.disconnect(
+                    appContext,
+                    it,
+                    wallpaperPreviewViewModel.wallpaperDisplaySize.value
+                )
+            }
         }
-        effectsRepository.destroy()
-        super.onDestroy()
-    }
 
-    override fun onConfigurationChanged(newConfig: Configuration) {
-        super.onConfigurationChanged(newConfig)
-        enforcePortraitForHandheldAndFoldedDisplay()
+        super.onDestroy()
     }
 
     private fun WallpaperInfo.convertToWallpaperModel(): WallpaperModel {
@@ -192,6 +219,46 @@
             intent.putExtra(IS_NEW_TASK, isNewTask)
             return intent
         }
+
+        /**
+         * Returns a new [Intent] that can be used to start [WallpaperPreviewActivity], explicitly
+         * propagating any permissions on the wallpaper data to the new [Intent].
+         *
+         * @param context application context.
+         * @param wallpaperInfo selected by user for editing preview.
+         * @param isNewTask true to launch at a new task.
+         *
+         * TODO(b/291761856): Use wallpaper model to replace wallpaper info.
+         */
+        fun newIntent(
+            context: Context,
+            originalIntent: Intent,
+            isAssetIdPresent: Boolean,
+            isViewAsHome: Boolean = false,
+            isNewTask: Boolean = false,
+        ): Intent {
+            val data = originalIntent.data
+            val intent =
+                newIntent(
+                    context,
+                    ImageWallpaperInfo(data),
+                    isAssetIdPresent,
+                    isViewAsHome,
+                    isNewTask
+                )
+            // Both these lines are required for permission propagation
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+            intent.setData(data)
+            return intent
+        }
+
+        private fun WallpaperModel.LiveWallpaperModel.getNewCreativeWallpaperArgs() =
+            Bundle().apply {
+                putParcelable(
+                    SmallPreviewFragment.ARG_EDIT_INTENT,
+                    liveWallpaperData.getEditActivityIntent(true),
+                )
+            }
     }
 
     /**
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
index 50f3062..042d6b7 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
@@ -17,16 +17,16 @@
 
 import android.content.Context
 import android.view.View
+import android.view.View.OVER_SCROLL_NEVER
 import androidx.lifecycle.LifecycleOwner
 import com.android.wallpaper.R
-import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.model.wallpaper.PreviewPagerPage
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.DualPreviewViewPager
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.DualPreviewPagerAdapter
 import com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
 import com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout.Companion.getViewId
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
-import kotlinx.coroutines.CoroutineScope
 
 /** Binds dual preview home screen and lock screen view pager. */
 object DualPreviewPagerBinder {
@@ -36,16 +36,14 @@
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         applicationContext: Context,
         viewLifecycleOwner: LifecycleOwner,
-        mainScope: CoroutineScope,
         currentNavDestId: Int,
         navigate: (View) -> Unit,
     ) {
         // implement adapter for the dual preview pager
         dualPreviewView.adapter = DualPreviewPagerAdapter { view, position ->
-            PreviewTooltipBinder.bind(
+            PreviewTooltipBinder.bindSmallPreviewTooltip(
                 tooltipStub = view.requireViewById(R.id.tooltip_stub),
-                enableClickToDismiss = false,
-                viewModel = wallpaperPreviewViewModel,
+                viewModel = wallpaperPreviewViewModel.smallTooltipViewModel,
                 lifecycleOwner = viewLifecycleOwner,
             )
 
@@ -54,29 +52,31 @@
 
             val displaySizes =
                 mapOf(
-                    FoldableDisplay.FOLDED to wallpaperPreviewViewModel.smallerDisplaySize,
-                    FoldableDisplay.UNFOLDED to wallpaperPreviewViewModel.wallpaperDisplaySize,
+                    DeviceDisplayType.FOLDED to wallpaperPreviewViewModel.smallerDisplaySize,
+                    DeviceDisplayType.UNFOLDED to
+                        wallpaperPreviewViewModel.wallpaperDisplaySize.value,
                 )
             dualDisplayAspectRatioLayout.setDisplaySizes(displaySizes)
             dualPreviewView.setDisplaySizes(displaySizes)
 
-            FoldableDisplay.entries.forEach { display ->
+            DeviceDisplayType.FOLDABLE_DISPLAY_TYPES.forEach { display ->
                 val previewDisplaySize = dualDisplayAspectRatioLayout.getPreviewDisplaySize(display)
                 previewDisplaySize?.let {
                     SmallPreviewBinder.bind(
                         applicationContext = applicationContext,
                         view = dualDisplayAspectRatioLayout.requireViewById(display.getViewId()),
                         viewModel = wallpaperPreviewViewModel,
-                        mainScope = mainScope,
                         viewLifecycleOwner = viewLifecycleOwner,
                         screen = PreviewPagerPage.entries[position].screen,
                         displaySize = it,
-                        foldableDisplay = display,
+                        deviceDisplayType = display,
                         currentNavDestId = currentNavDestId,
                         navigate = navigate,
                     )
                 }
             }
+
+            dualPreviewView.overScrollMode = OVER_SCROLL_NEVER
         }
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
index a69f29d..1721376 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
@@ -20,8 +20,8 @@
 import androidx.lifecycle.LifecycleOwner
 import androidx.viewpager.widget.ViewPager
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.DualPreviewViewPager
+import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.TabTextPagerAdapter
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
-import kotlinx.coroutines.CoroutineScope
 
 /**
  * This binder binds the data and view models for the dual preview collection on the small preview
@@ -35,7 +35,6 @@
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         applicationContext: Context,
         viewLifecycleOwner: LifecycleOwner,
-        mainScope: CoroutineScope,
         currentNavDestId: Int,
         navigate: (View) -> Unit,
     ) {
@@ -50,10 +49,13 @@
             wallpaperPreviewViewModel,
             applicationContext,
             viewLifecycleOwner,
-            mainScope,
             currentNavDestId,
             navigate,
         )
+        tabsViewPager.currentItem =
+            (tabsViewPager.adapter as TabTextPagerAdapter).getPageNumber(
+                wallpaperPreviewViewModel.isViewAsHome
+            )
     }
 
     private fun synchronizePreviewAndTabsPager(
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
index f9179cd..b047feb 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
@@ -15,21 +15,30 @@
  */
 package com.android.wallpaper.picker.preview.ui.binder
 
+import android.annotation.SuppressLint
 import android.content.Context
-import android.graphics.Rect
+import android.graphics.Point
+import android.os.Bundle
+import android.view.Gravity
 import android.view.LayoutInflater
 import android.view.SurfaceHolder
 import android.view.SurfaceView
 import android.view.View
+import android.widget.FrameLayout
 import android.widget.ImageView
+import androidx.cardview.widget.CardView
+import androidx.core.view.doOnLayout
+import androidx.core.view.isVisible
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import androidx.transition.Transition
+import androidx.transition.doOnEnd
 import com.android.wallpaper.R
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.picker.TouchForwardingLayout
 import com.android.wallpaper.picker.data.WallpaperModel
-import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.shared.model.CropSizeModel
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
 import com.android.wallpaper.picker.preview.ui.util.SubsamplingScaleImageViewUtil.setOnNewCropListener
@@ -38,12 +47,14 @@
 import com.android.wallpaper.picker.preview.ui.view.FullPreviewFrameLayout
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
+import com.android.wallpaper.util.RtlUtils.isRtl
 import com.android.wallpaper.util.WallpaperCropUtils
 import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils
+import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils.shouldEnforceSingleEngine
 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
 import java.lang.Integer.min
 import kotlin.math.max
-import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
 
@@ -54,121 +65,277 @@
         applicationContext: Context,
         view: View,
         viewModel: WallpaperPreviewViewModel,
+        transition: Transition?,
         displayUtils: DisplayUtils,
         lifecycleOwner: LifecycleOwner,
-        @MainDispatcher mainScope: CoroutineScope,
+        savedInstanceState: Bundle?,
+        onWallpaperLoaded: ((Boolean) -> Unit)? = null,
     ) {
         val wallpaperPreviewCrop: FullPreviewFrameLayout =
             view.requireViewById(R.id.wallpaper_preview_crop)
+        val previewCard: CardView = view.requireViewById(R.id.preview_card)
+        val scrimView: View = view.requireViewById(R.id.preview_scrim)
+        var transitionDisposableHandle: DisposableHandle? = null
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
-                viewModel.fullWallpaper.collect { (_, config, _) ->
+                viewModel.fullWallpaper.collect { (_, _, displaySize, _) ->
+                    val currentSize = displayUtils.getRealSize(checkNotNull(view.context.display))
                     wallpaperPreviewCrop.setCurrentAndTargetDisplaySize(
-                        displayUtils.getRealSize(checkNotNull(view.context.display)),
-                        config.displaySize,
+                        currentSize,
+                        displaySize,
                     )
+
+                    val setFinalPreviewCardRadiusAndEndLoading = { isWallpaperFullScreen: Boolean ->
+                        if (isWallpaperFullScreen) {
+                            previewCard.radius = 0f
+                        }
+                        scrimView.isVisible = isWallpaperFullScreen
+                        onWallpaperLoaded?.invoke(isWallpaperFullScreen)
+                    }
+                    val isPreviewingFullScreen = displaySize == currentSize
+                    if (transition == null || savedInstanceState != null) {
+                        setFinalPreviewCardRadiusAndEndLoading(isPreviewingFullScreen)
+                    } else {
+                        transitionDisposableHandle?.dispose()
+                        val listener =
+                            transition.doOnEnd {
+                                setFinalPreviewCardRadiusAndEndLoading(isPreviewingFullScreen)
+                            }
+                        transitionDisposableHandle = DisposableHandle {
+                            listener.let { transition.removeListener(it) }
+                        }
+                    }
                 }
             }
+            transitionDisposableHandle?.dispose()
         }
         val surfaceView: SurfaceView = view.requireViewById(R.id.wallpaper_surface)
         val surfaceTouchForwardingLayout: TouchForwardingLayout =
             view.requireViewById(R.id.touch_forwarding_layout)
-        var job: Job? = null
-        surfaceView.setZOrderMediaOverlay(true)
-        surfaceView.holder.addCallback(
-            object : SurfaceViewUtil.SurfaceCallback {
-                override fun surfaceCreated(holder: SurfaceHolder) {
-                    val surfaceSize = holder.surface.defaultSize
-                    val cropSurfaceSize =
-                        WallpaperCropUtils.calculateCropSurfaceSize(
-                            view.resources,
-                            max(surfaceSize.x, surfaceSize.y),
-                            min(surfaceSize.x, surfaceSize.y),
-                            surfaceSize.x,
-                            surfaceSize.y
-                        )
-                    job =
-                        lifecycleOwner.lifecycleScope.launch {
-                            viewModel.fullWallpaper.collect {
-                                (wallpaper, config, allowUserCropping, whichPreview) ->
-                                if (wallpaper is WallpaperModel.LiveWallpaperModel) {
-                                    WallpaperConnectionUtils.connect(
-                                        applicationContext,
-                                        mainScope,
-                                        wallpaper,
-                                        whichPreview,
-                                        config.screen.toFlag(),
-                                        surfaceView,
-                                    )
-                                } else if (wallpaper is WallpaperModel.StaticWallpaperModel) {
-                                    val (lowResImageView, fullResImageView) =
-                                        initStaticPreviewSurface(
-                                            applicationContext,
-                                            surfaceView,
-                                        ) { crop, zoom ->
-                                            viewModel.staticWallpaperPreviewViewModel
-                                                .fullPreviewCropModels[config.displaySize] =
-                                                FullPreviewCropModel(
-                                                    cropHint = crop,
-                                                    cropSizeModel =
-                                                        CropSizeModel(
-                                                            wallpaperZoom = zoom,
-                                                            hostViewSize = surfaceSize,
-                                                            cropSurfaceSize = cropSurfaceSize,
-                                                        ),
-                                                )
-                                        }
 
-                                    // We do not allow users to pinch to crop if it is a
-                                    // downloadable wallpaper.
-                                    if (allowUserCropping) {
-                                        surfaceTouchForwardingLayout.initTouchForwarding(
-                                            fullResImageView
-                                        )
-                                    }
-
-                                    // Bind static wallpaper
-                                    StaticWallpaperPreviewBinder.bind(
-                                        lowResImageView,
-                                        fullResImageView,
-                                        viewModel.staticWallpaperPreviewViewModel,
-                                        config.displaySize,
-                                        lifecycleOwner,
-                                    )
-                                }
-                            }
-                        }
+        val displayId = view.context.display.displayId
+        if (displayUtils.hasMultiInternalDisplays()) {
+            val currentDescription = surfaceTouchForwardingLayout.contentDescription?.toString()
+            val descriptionResourceId =
+                if (viewModel.getDisplayId(DeviceDisplayType.FOLDED) == displayId) {
+                    R.string.folded_device_state_description
+                } else {
+                    R.string.unfolded_device_state_description
                 }
+            val descriptionString =
+                surfaceTouchForwardingLayout.context.getString(descriptionResourceId)
+            surfaceTouchForwardingLayout.contentDescription = currentDescription + descriptionString
+        }
 
-                override fun surfaceDestroyed(holder: SurfaceHolder) {
-                    job?.cancel()
-                    // Note that we disconnect wallpaper connection for live wallpapers in
-                    // WallpaperPreviewActivity's onDestroy().
-                    // This is to reduce multiple times of connecting and disconnecting live
-                    // wallpaper services, when going back and forth small and full preview.
-                }
+        var surfaceCallback: SurfaceViewUtil.SurfaceCallback? = null
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
+                surfaceCallback =
+                    bindSurface(
+                        applicationContext = applicationContext,
+                        surfaceView = surfaceView,
+                        surfaceTouchForwardingLayout = surfaceTouchForwardingLayout,
+                        viewModel = viewModel,
+                        lifecycleOwner = lifecycleOwner,
+                    )
+                surfaceView.setZOrderMediaOverlay(true)
+                surfaceView.holder.addCallback(surfaceCallback)
             }
-        )
-        // TODO (b/300979155): Clean up surface when no longer needed, e.g. onDestroyed
+            // When OnDestroy, release the surface
+            surfaceCallback?.let {
+                surfaceView.holder.removeCallback(it)
+                surfaceCallback = null
+            }
+        }
     }
 
-    private fun initStaticPreviewSurface(
+    /**
+     * Create a surface callback that binds the surface when surface created. Note that we return
+     * the surface callback reference so that we can remove the callback from the surface when the
+     * screen is destroyed.
+     */
+    private fun bindSurface(
         applicationContext: Context,
         surfaceView: SurfaceView,
-        onNewCrop: (crop: Rect, zoom: Float) -> Unit
-    ): Pair<ImageView, SubsamplingScaleImageView> {
-        val preview =
-            LayoutInflater.from(applicationContext)
-                .inflate(R.layout.fullscreen_wallpaper_preview, null)
-        surfaceView.attachView(preview)
-        val fullResImageView =
-            preview.requireViewById<SubsamplingScaleImageView>(R.id.full_res_image)
-        fullResImageView.setOnNewCropListener { crop, zoom -> onNewCrop.invoke(crop, zoom) }
-        return Pair(preview.requireViewById(R.id.low_res_image), fullResImageView)
+        surfaceTouchForwardingLayout: TouchForwardingLayout,
+        viewModel: WallpaperPreviewViewModel,
+        lifecycleOwner: LifecycleOwner,
+    ): SurfaceViewUtil.SurfaceCallback {
+        return object : SurfaceViewUtil.SurfaceCallback {
+
+            var job: Job? = null
+            var surfaceOrigWidth: Int? = null
+            var surfaceOrigHeight: Int? = null
+
+            // Suppress lint warning for setting on touch listener to a live wallpaper surface view.
+            // This is because the touch effect on a live wallpaper is purely visual, instead of
+            // functional. The effect can be different for different live wallpapers.
+            @SuppressLint("ClickableViewAccessibility")
+            override fun surfaceCreated(holder: SurfaceHolder) {
+                job =
+                    lifecycleOwner.lifecycleScope.launch {
+                        viewModel.fullWallpaper.collect {
+                            (wallpaper, config, displaySize, allowUserCropping, whichPreview) ->
+                            if (wallpaper is WallpaperModel.LiveWallpaperModel) {
+                                val engineRenderingConfig =
+                                    WallpaperConnectionUtils.EngineRenderingConfig(
+                                        wallpaper.shouldEnforceSingleEngine(),
+                                        config.deviceDisplayType,
+                                        viewModel.smallerDisplaySize,
+                                        displaySize,
+                                    )
+                                WallpaperConnectionUtils.connect(
+                                    applicationContext,
+                                    wallpaper,
+                                    whichPreview,
+                                    config.screen.toFlag(),
+                                    surfaceView,
+                                    engineRenderingConfig,
+                                )
+                                surfaceTouchForwardingLayout.initTouchForwarding(surfaceView)
+                                surfaceView.setOnTouchListener { _, event ->
+                                    lifecycleOwner.lifecycleScope.launch {
+                                        WallpaperConnectionUtils.dispatchTouchEvent(
+                                            wallpaper,
+                                            engineRenderingConfig,
+                                            event,
+                                        )
+                                    }
+                                    false
+                                }
+                            } else if (wallpaper is WallpaperModel.StaticWallpaperModel) {
+                                val preview =
+                                    LayoutInflater.from(applicationContext)
+                                        .inflate(R.layout.fullscreen_wallpaper_preview, null)
+                                adjustSizeAndAttachPreview(
+                                    applicationContext,
+                                    surfaceOrigWidth
+                                        ?: surfaceView.width.also { surfaceOrigWidth = it },
+                                    surfaceOrigHeight
+                                        ?: surfaceView.height.also { surfaceOrigHeight = it },
+                                    surfaceView,
+                                    preview,
+                                )
+
+                                val fullResImageView =
+                                    preview.requireViewById<SubsamplingScaleImageView>(
+                                        R.id.full_res_image
+                                    )
+                                fullResImageView.doOnLayout {
+                                    val imageSize =
+                                        Point(fullResImageView.width, fullResImageView.height)
+                                    val cropImageSize =
+                                        WallpaperCropUtils.calculateCropSurfaceSize(
+                                            applicationContext.resources,
+                                            max(imageSize.x, imageSize.y),
+                                            min(imageSize.x, imageSize.y),
+                                            imageSize.x,
+                                            imageSize.y
+                                        )
+                                    fullResImageView.setOnNewCropListener { crop, zoom ->
+                                        viewModel.staticWallpaperPreviewViewModel
+                                            .fullPreviewCropModels[displaySize] =
+                                            FullPreviewCropModel(
+                                                cropHint = crop,
+                                                cropSizeModel =
+                                                    CropSizeModel(
+                                                        wallpaperZoom = zoom,
+                                                        hostViewSize = imageSize,
+                                                        cropViewSize = cropImageSize,
+                                                    ),
+                                            )
+                                    }
+                                }
+                                val lowResImageView =
+                                    preview.requireViewById<ImageView>(R.id.low_res_image)
+
+                                // We do not allow users to pinch to crop if it is a
+                                // downloadable wallpaper.
+                                if (allowUserCropping) {
+                                    surfaceTouchForwardingLayout.initTouchForwarding(
+                                        fullResImageView
+                                    )
+                                }
+
+                                // Bind static wallpaper
+                                StaticWallpaperPreviewBinder.bind(
+                                    lowResImageView = lowResImageView,
+                                    fullResImageView = fullResImageView,
+                                    viewModel = viewModel.staticWallpaperPreviewViewModel,
+                                    displaySize = displaySize,
+                                    viewLifecycleOwner = lifecycleOwner,
+                                    isFullScreen = true,
+                                )
+                            }
+                        }
+                    }
+            }
+
+            override fun surfaceDestroyed(holder: SurfaceHolder) {
+                job?.cancel()
+                job = null
+                // Clean up surface view's on touche listener
+                surfaceTouchForwardingLayout.removeTouchForwarding()
+                surfaceView.setOnTouchListener(null)
+                // Note that we disconnect wallpaper connection for live wallpapers in
+                // WallpaperPreviewActivity's onDestroy().
+                // This is to reduce multiple times of connecting and disconnecting live
+                // wallpaper services, when going back and forth small and full preview.
+            }
+        }
+    }
+
+    // When showing full screen, we set the parent SurfaceView to be bigger than the image by N
+    // percent (usually 10%) as given by getSystemWallpaperMaximumScale. This ensures that no matter
+    // what scale and pan is set by the user, at least N% of the source image in the preview will be
+    // preserved around the visible crop. This is needed for system zoom out animations.
+    private fun adjustSizeAndAttachPreview(
+        applicationContext: Context,
+        origWidth: Int,
+        origHeight: Int,
+        surfaceView: SurfaceView,
+        preview: View,
+    ) {
+        val scale = WallpaperCropUtils.getSystemWallpaperMaximumScale(applicationContext)
+
+        val width = (origWidth * scale).toInt()
+        val height = (origHeight * scale).toInt()
+        val left =
+            ((origWidth - width) / 2).let {
+                if (isRtl(applicationContext)) {
+                    -it
+                } else {
+                    it
+                }
+            }
+        val top = (origHeight - height) / 2
+
+        val params = surfaceView.layoutParams
+        params.width = width
+        params.height = height
+        surfaceView.x = left.toFloat()
+        surfaceView.y = top.toFloat()
+        surfaceView.layoutParams = params
+        surfaceView.requestLayout()
+
+        preview.measure(
+            View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+            View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
+        )
+        preview.layout(0, 0, width, height)
+
+        surfaceView.attachView(preview, width, height)
     }
 
     private fun TouchForwardingLayout.initTouchForwarding(targetView: View) {
+        // Make sure the touch forwarding layout same size of the target view
+        layoutParams = FrameLayout.LayoutParams(targetView.width, targetView.height, Gravity.CENTER)
         setForwardingEnabled(true)
         setTargetView(targetView)
     }
+
+    private fun TouchForwardingLayout.removeTouchForwarding() {
+        setForwardingEnabled(false)
+        setTargetView(null)
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt
index d392c66..df0c9d5 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt
@@ -16,13 +16,13 @@
 package com.android.wallpaper.picker.preview.ui.binder
 
 import android.content.Intent
-import android.graphics.Point
 import android.net.Uri
 import android.view.View
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.picker.preview.ui.view.PreviewActionFloatingSheet
 import com.android.wallpaper.picker.preview.ui.view.PreviewActionGroup
@@ -36,6 +36,7 @@
 import com.android.wallpaper.picker.preview.ui.viewmodel.DeleteConfirmationDialogViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.PreviewActionsViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperActionsToggleAdapter
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
 import kotlinx.coroutines.launch
@@ -47,7 +48,7 @@
         floatingSheet: PreviewActionFloatingSheet,
         previewViewModel: WallpaperPreviewViewModel,
         actionsViewModel: PreviewActionsViewModel,
-        displaySize: Point,
+        deviceDisplayType: DeviceDisplayType,
         lifecycleOwner: LifecycleOwner,
         logger: UserEventLogger,
         onStartEditActivity: (intent: Intent) -> Unit,
@@ -93,30 +94,6 @@
                     }
                 }
 
-                launch {
-                    actionsViewModel.informationFloatingSheetViewModel.collect { viewModel ->
-                        if (viewModel == null) {
-                            floatingSheet.collapse()
-                        } else {
-                            val onExploreButtonClicked =
-                                viewModel.exploreActionUrl?.let { url ->
-                                    {
-                                        logger.logWallpaperExploreButtonClicked()
-                                        val appContext = floatingSheet.context.applicationContext
-                                        appContext.startActivity(
-                                            Intent(Intent.ACTION_VIEW, Uri.parse(url))
-                                        )
-                                    }
-                                }
-                            floatingSheet.setInformationContent(
-                                viewModel.attributions,
-                                onExploreButtonClicked
-                            )
-                            floatingSheet.expand()
-                        }
-                    }
-                }
-
                 /** [DOWNLOAD] */
                 launch {
                     actionsViewModel.isDownloadVisible.collect {
@@ -187,8 +164,8 @@
                                 {
                                     // We need to set default wallpaper preview config view model
                                     // before entering full screen with edit activity overlay.
-                                    previewViewModel.setDefaultWallpaperPreviewConfigViewModel(
-                                        displaySize
+                                    previewViewModel.setDefaultFullPreviewConfigViewModel(
+                                        deviceDisplayType
                                     )
                                     onStartEditActivity.invoke(it)
                                 }
@@ -235,28 +212,6 @@
                     }
                 }
 
-                launch {
-                    actionsViewModel.effectFloatingSheetViewModel.collect { viewModel ->
-                        if (viewModel == null) {
-                            floatingSheet.collapse()
-                        } else {
-                            floatingSheet.setEffectContent(
-                                viewModel.effectType,
-                                viewModel.myPhotosClickListener,
-                                viewModel.collapseFloatingSheetListener,
-                                viewModel.effectSwitchListener,
-                                viewModel.effectDownloadClickListener,
-                                viewModel.status,
-                                viewModel.resultCode,
-                                viewModel.errorMessage,
-                                viewModel.title,
-                                viewModel.effectTextRes,
-                            )
-                            floatingSheet.expand()
-                        }
-                    }
-                }
-
                 /** [SHARE] */
                 launch {
                     actionsViewModel.isShareVisible.collect { actionGroup.setIsVisible(SHARE, it) }
@@ -272,6 +227,71 @@
                         )
                     }
                 }
+
+                /** Floating sheet behavior */
+                launch {
+                    actionsViewModel.previewFloatingSheetViewModel.collect { floatingSheetViewModel
+                        ->
+                        if (floatingSheetViewModel != null) {
+                            val (
+                                informationViewModel,
+                                imageEffectViewModel,
+                                creativeEffectViewModel,
+                                customizeViewModel,
+                            ) = floatingSheetViewModel
+                            when {
+                                informationViewModel != null -> {
+                                    floatingSheet.setInformationContent(
+                                        informationViewModel.attributions,
+                                        informationViewModel.exploreActionUrl?.let { url ->
+                                            {
+                                                logger.logWallpaperExploreButtonClicked()
+                                                floatingSheet.context.startActivity(
+                                                    Intent(Intent.ACTION_VIEW, Uri.parse(url))
+                                                )
+                                            }
+                                        },
+                                    )
+                                }
+                                imageEffectViewModel != null ->
+                                    floatingSheet.setImageEffectContent(
+                                        imageEffectViewModel.effectType,
+                                        imageEffectViewModel.myPhotosClickListener,
+                                        imageEffectViewModel.collapseFloatingSheetListener,
+                                        imageEffectViewModel.effectSwitchListener,
+                                        imageEffectViewModel.effectDownloadClickListener,
+                                        imageEffectViewModel.status,
+                                        imageEffectViewModel.resultCode,
+                                        imageEffectViewModel.errorMessage,
+                                        imageEffectViewModel.title,
+                                        imageEffectViewModel.effectTextRes,
+                                    )
+                                creativeEffectViewModel != null ->
+                                    floatingSheet.setCreativeEffectContent(
+                                        creativeEffectViewModel.title,
+                                        creativeEffectViewModel.subtitle,
+                                        creativeEffectViewModel.wallpaperActions,
+                                        object :
+                                            WallpaperActionsToggleAdapter.WallpaperEffectSwitchListener {
+                                            override fun onEffectSwitchChanged(checkedItem: Int) {
+                                                launch {
+                                                    creativeEffectViewModel
+                                                        .wallpaperEffectSwitchListener(checkedItem)
+                                                }
+                                            }
+                                        },
+                                    )
+                                customizeViewModel != null ->
+                                    floatingSheet.setCustomizeContent(
+                                        customizeViewModel.customizeSliceUri
+                                    )
+                            }
+                            floatingSheet.expand()
+                        } else {
+                            floatingSheet.collapse()
+                        }
+                    }
+                }
             }
         }
     }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewEffectsLoadingBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewEffectsLoadingBinder.kt
new file mode 100644
index 0000000..fc952ef
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewEffectsLoadingBinder.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 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.wallpaper.picker.preview.ui.binder
+
+import android.content.Context
+import android.content.res.Configuration
+import android.view.View
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.monet.ColorScheme
+import com.android.wallpaper.picker.customization.animation.view.LoadingAnimation
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_APPLIED
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_APPLY_IN_PROGRESS
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_DOWNLOAD_FAILED
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_READY
+import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
+import com.android.wallpaper.util.ResourceUtils
+import kotlinx.coroutines.launch
+
+object PreviewEffectsLoadingBinder {
+    interface Binding {
+        fun destroy()
+    }
+
+    fun bind(
+        view: View,
+        viewModel: WallpaperPreviewViewModel,
+        viewLifecycleOwner: LifecycleOwner,
+    ): Binding {
+        var loadingAnimation: LoadingAnimation? = null
+        val job =
+            viewLifecycleOwner.lifecycleScope.launch {
+                viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
+                    loadingAnimation = getLoadingAnimation(view)
+                    viewModel.effectStatus.collect { status ->
+                        if (status == EFFECT_APPLY_IN_PROGRESS) {
+                            loadingAnimation?.playLoadingAnimation(seed = null)
+                        } else if (
+                            status == EFFECT_APPLIED ||
+                                status == EFFECT_READY ||
+                                status == EFFECT_DOWNLOAD_FAILED
+                        ) {
+                            // Play reveal animation whether applying the effect succeeded or
+                            // failed.
+                            loadingAnimation?.playRevealAnimation()
+                        }
+                    }
+                }
+                loadingAnimation?.cancel()
+                loadingAnimation = null
+            }
+        return object : Binding {
+            override fun destroy() {
+                job.cancel()
+                loadingAnimation?.cancel()
+                loadingAnimation = null
+            }
+        }
+    }
+
+    private fun getLoadingAnimation(view: View): LoadingAnimation {
+        val context: Context = view.context
+        val loadingAnimation =
+            LoadingAnimation(
+                revealOverlay = view,
+                revealType = LoadingAnimation.RevealType.FADE,
+                timeOutDuration = null
+            )
+        val colorAccent = ResourceUtils.getColorAttr(context, android.R.attr.colorAccent)
+        val isDarkTheme =
+            (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==
+                Configuration.UI_MODE_NIGHT_YES
+        loadingAnimation.updateColor(ColorScheme(colorAccent, isDarkTheme))
+        return loadingAnimation
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
index 2e0bf54..8ced558 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
@@ -23,11 +23,11 @@
 import androidx.recyclerview.widget.RecyclerView
 import androidx.viewpager2.widget.ViewPager2
 import com.android.wallpaper.R
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.model.wallpaper.PreviewPagerPage
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.SinglePreviewPagerAdapter
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.pagetransformers.PreviewCardPageTransformer
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
-import kotlinx.coroutines.CoroutineScope
 
 /** Binds single preview home screen and lock screen tabs view pager. */
 object PreviewPagerBinder {
@@ -36,7 +36,6 @@
     fun bind(
         applicationContext: Context,
         viewLifecycleOwner: LifecycleOwner,
-        mainScope: CoroutineScope,
         previewsViewPager: ViewPager2,
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         previewDisplaySize: Point,
@@ -45,10 +44,9 @@
     ) {
         previewsViewPager.apply {
             adapter = SinglePreviewPagerAdapter { viewHolder, position ->
-                PreviewTooltipBinder.bind(
+                PreviewTooltipBinder.bindSmallPreviewTooltip(
                     tooltipStub = viewHolder.itemView.requireViewById(R.id.tooltip_stub),
-                    enableClickToDismiss = false,
-                    viewModel = wallpaperPreviewViewModel,
+                    viewModel = wallpaperPreviewViewModel.smallTooltipViewModel,
                     lifecycleOwner = viewLifecycleOwner,
                 )
 
@@ -58,8 +56,7 @@
                     viewModel = wallpaperPreviewViewModel,
                     screen = PreviewPagerPage.entries[position].screen,
                     displaySize = previewDisplaySize,
-                    foldableDisplay = null,
-                    mainScope = mainScope,
+                    deviceDisplayType = DeviceDisplayType.SINGLE,
                     viewLifecycleOwner = viewLifecycleOwner,
                     currentNavDestId = currentNavDestId,
                     navigate = navigate,
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
index 4747e0b..1245efc 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
@@ -21,8 +21,8 @@
 import androidx.lifecycle.LifecycleOwner
 import androidx.viewpager.widget.ViewPager
 import androidx.viewpager2.widget.ViewPager2
+import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.TabTextPagerAdapter
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
-import kotlinx.coroutines.CoroutineScope
 
 /** Binds and synchronizes the tab and preview view pagers. */
 object PreviewSelectorBinder {
@@ -34,7 +34,6 @@
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         applicationContext: Context,
         viewLifecycleOwner: LifecycleOwner,
-        mainScope: CoroutineScope,
         currentNavDestId: Int,
         navigate: (View) -> Unit,
     ) {
@@ -45,7 +44,6 @@
         PreviewPagerBinder.bind(
             applicationContext,
             viewLifecycleOwner,
-            mainScope,
             previewsViewPager,
             wallpaperPreviewViewModel,
             previewDisplaySize,
@@ -55,6 +53,10 @@
 
         // synchronize the two pagers
         synchronizePreviewAndTabsPager(tabsViewPager, previewsViewPager)
+        tabsViewPager.currentItem =
+            (tabsViewPager.adapter as TabTextPagerAdapter).getPageNumber(
+                wallpaperPreviewViewModel.isViewAsHome
+            )
     }
 
     private fun synchronizePreviewAndTabsPager(
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewTooltipBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewTooltipBinder.kt
index d116fd5..82c4550 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewTooltipBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewTooltipBinder.kt
@@ -17,35 +17,104 @@
 
 import android.view.View
 import android.view.ViewStub
+import android.view.animation.AccelerateDecelerateInterpolator
+import androidx.core.view.doOnLayout
 import androidx.core.view.isVisible
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
-import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.launch
 
 object PreviewTooltipBinder {
-    fun bind(
+    interface TooltipViewModel {
+        val shouldShowTooltip: Flow<Boolean>
+        fun dismissTooltip()
+    }
+
+    fun bindSmallPreviewTooltip(
         tooltipStub: ViewStub,
-        enableClickToDismiss: Boolean,
-        viewModel: WallpaperPreviewViewModel,
+        viewModel: TooltipViewModel,
         lifecycleOwner: LifecycleOwner,
     ) {
         var tooltip: View? = null
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                 launch {
-                    viewModel.shouldShowTooltip().collect { shouldShowTooltip ->
+                    viewModel.shouldShowTooltip.collect { shouldShowTooltip ->
                         if (shouldShowTooltip && tooltip == null) {
                             tooltip = tooltipStub.inflate()
-                            if (enableClickToDismiss) {
-                                tooltip?.setOnClickListener { viewModel.dismissTooltip() }
+                        }
+                        tooltip?.doOnLayout {
+                            it.isVisible = true
+                            it.alpha = if (shouldShowTooltip) 0f else 1f
+                            it.pivotX = it.measuredWidth / 2f
+                            it.pivotY = it.measuredHeight.toFloat()
+                            it.scaleX = if (shouldShowTooltip) 0.2f else 1f
+                            it.scaleY = if (shouldShowTooltip) 0.2f else 1f
+
+                            if (shouldShowTooltip) {
+                                it.animate()
+                                    .scaleX(1f)
+                                    .scaleY(1f)
+                                    .alpha(1f)
+                                    .setStartDelay(1000L)
+                                    .setDuration(200L)
+                                    .setInterpolator(AccelerateDecelerateInterpolator())
+                                    .start()
+                            } else {
+                                it.animate()
+                                    .alpha(0f)
+                                    .setDuration(75L)
+                                    .setInterpolator(AccelerateDecelerateInterpolator())
+                                    .withEndAction { tooltip?.isVisible = false }
+                                    .start()
                             }
                         }
-                        // TODO (b/303318205): animate tooltip
-                        // Only show tooltip if it has not been shown before.
-                        tooltip?.isVisible = shouldShowTooltip
+                    }
+                }
+            }
+        }
+    }
+
+    fun bindFullPreviewTooltip(
+        tooltipStub: ViewStub,
+        viewModel: TooltipViewModel,
+        lifecycleOwner: LifecycleOwner,
+    ) {
+        var tooltip: View? = null
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                launch {
+                    viewModel.shouldShowTooltip.collect { shouldShowTooltip ->
+                        if (shouldShowTooltip && tooltip == null) {
+                            tooltip = tooltipStub.inflate()
+                            tooltip?.setOnClickListener { viewModel.dismissTooltip() }
+                        }
+                        tooltip?.doOnLayout {
+                            it.isVisible = true
+                            it.alpha = if (shouldShowTooltip) 0f else 1f
+                            it.translationY = if (shouldShowTooltip) -20f else 0f
+
+                            if (shouldShowTooltip) {
+                                it.animate()
+                                    .alpha(1f)
+                                    .translationY(0f)
+                                    .setStartDelay(500L)
+                                    .setDuration(200L)
+                                    .setInterpolator(AccelerateDecelerateInterpolator())
+                                    .start()
+                            } else {
+                                it.animate()
+                                    .alpha(0f)
+                                    .translationY(-20f)
+                                    .setDuration(75L)
+                                    .setInterpolator(AccelerateDecelerateInterpolator())
+                                    .withEndAction { tooltip?.isVisible = false }
+                                    .start()
+                            }
+                        }
                     }
                 }
             }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperDialogBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperDialogBinder.kt
index 6e35021..afbae67 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperDialogBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperDialogBinder.kt
@@ -26,7 +26,7 @@
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.wallpaper.R
-import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.module.CustomizationSections.Screen
 import com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
 import com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout.Companion.getViewId
@@ -62,7 +62,6 @@
                 previewLayout,
                 wallpaperPreviewViewModel,
                 lifecycleOwner,
-                mainScope,
                 currentNavDestId,
                 navigate,
             )
@@ -72,7 +71,6 @@
                 wallpaperPreviewViewModel,
                 handheldDisplaySize,
                 lifecycleOwner,
-                mainScope,
                 currentNavDestId,
                 navigate,
             )
@@ -125,7 +123,6 @@
         previewLayout: View,
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         lifecycleOwner: LifecycleOwner,
-        mainScope: CoroutineScope,
         currentNavDestId: Int,
         navigate: ((View) -> Unit)?,
     ) {
@@ -138,22 +135,22 @@
 
             dualDisplayAspectRatioLayout.setDisplaySizes(
                 mapOf(
-                    FoldableDisplay.FOLDED to wallpaperPreviewViewModel.smallerDisplaySize,
-                    FoldableDisplay.UNFOLDED to wallpaperPreviewViewModel.wallpaperDisplaySize,
+                    DeviceDisplayType.FOLDED to wallpaperPreviewViewModel.smallerDisplaySize,
+                    DeviceDisplayType.UNFOLDED to
+                        wallpaperPreviewViewModel.wallpaperDisplaySize.value,
                 )
             )
-            FoldableDisplay.entries.forEach { display ->
+            DeviceDisplayType.FOLDABLE_DISPLAY_TYPES.forEach { display ->
                 val previewDisplaySize = dualDisplayAspectRatioLayout.getPreviewDisplaySize(display)
                 previewDisplaySize?.let {
                     SmallPreviewBinder.bind(
                         applicationContext = previewLayout.context.applicationContext,
                         view = dualDisplayAspectRatioLayout.requireViewById(display.getViewId()),
                         viewModel = wallpaperPreviewViewModel,
-                        mainScope = mainScope,
                         viewLifecycleOwner = lifecycleOwner,
                         screen = screenId.key,
                         displaySize = it,
-                        foldableDisplay = display,
+                        deviceDisplayType = display,
                         currentNavDestId = currentNavDestId,
                         navigate = navigate,
                     )
@@ -167,7 +164,6 @@
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         displaySize: Point,
         lifecycleOwner: LifecycleOwner,
-        mainScope: CoroutineScope,
         currentNavDestId: Int,
         navigate: ((View) -> Unit)?,
     ) {
@@ -182,8 +178,7 @@
                 viewModel = wallpaperPreviewViewModel,
                 screen = screenId.key,
                 displaySize = displaySize,
-                foldableDisplay = null,
-                mainScope = mainScope,
+                deviceDisplayType = DeviceDisplayType.SINGLE,
                 viewLifecycleOwner = lifecycleOwner,
                 currentNavDestId = currentNavDestId,
                 navigate = navigate,
@@ -198,6 +193,7 @@
         dialogViewModel: WallpaperPreviewViewModel,
     ) {
         selector.isActivated = selectedScreens.contains(screen)
+        selector.isSelected = selector.isActivated
         selector.setOnClickListener { dialogViewModel.onSetWallpaperDialogScreenSelected(screen) }
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperProgressDialogBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperProgressDialogBinder.kt
index 4d97fb2..c61f670 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperProgressDialogBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperProgressDialogBinder.kt
@@ -16,7 +16,7 @@
 
 package com.android.wallpaper.picker.preview.ui.binder
 
-import android.app.ProgressDialog
+import android.app.AlertDialog
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
@@ -28,7 +28,7 @@
 object SetWallpaperProgressDialogBinder {
 
     fun bind(
-        dialog: ProgressDialog,
+        dialog: AlertDialog,
         viewModel: WallpaperPreviewViewModel,
         lifecycleOwner: LifecycleOwner,
     ) {
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
index 36f4d57..c6ac7d0 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
@@ -20,24 +20,25 @@
 import android.view.SurfaceView
 import android.view.View
 import androidx.cardview.widget.CardView
+import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import com.android.wallpaper.R
-import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.module.CustomizationSections.Screen
-import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
-import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 object SmallPreviewBinder {
-    /** @param foldableDisplay Only used for foldable devices; otherwise, set to null. */
+
     fun bind(
         applicationContext: Context,
         view: View,
         viewModel: WallpaperPreviewViewModel,
         screen: Screen,
         displaySize: Point,
-        foldableDisplay: FoldableDisplay?,
-        @MainDispatcher mainScope: CoroutineScope,
+        deviceDisplayType: DeviceDisplayType,
         viewLifecycleOwner: LifecycleOwner,
         currentNavDestId: Int,
         navigate: ((View) -> Unit)? = null,
@@ -46,19 +47,27 @@
         val wallpaperSurface: SurfaceView = view.requireViewById(R.id.wallpaper_surface)
         val workspaceSurface: SurfaceView = view.requireViewById(R.id.workspace_surface)
 
-        if (R.id.smallPreviewFragment == currentNavDestId) {
-            view.setOnClickListener {
-                viewModel.onSmallPreviewClicked(screen, foldableDisplay)
-                navigate?.invoke(previewCard)
+        viewLifecycleOwner.lifecycleScope.launch {
+            launch {
+                viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
+                    if (R.id.smallPreviewFragment == currentNavDestId) {
+                        view.setOnClickListener {
+                            viewModel.onSmallPreviewClicked(screen, deviceDisplayType)
+                            navigate?.invoke(previewCard)
+                        }
+                    } else if (R.id.setWallpaperDialog == currentNavDestId) {
+                        previewCard.radius =
+                            previewCard.resources.getDimension(
+                                R.dimen.set_wallpaper_dialog_preview_corner_radius
+                            )
+                    }
+                }
+                // Remove on click listener when on destroyed
+                view.setOnClickListener(null)
             }
-        } else if (R.id.setWallpaperDialog == currentNavDestId) {
-            previewCard.radius =
-                previewCard.resources.getDimension(
-                    R.dimen.set_wallpaper_dialog_preview_corner_radius
-                )
         }
 
-        val config = viewModel.getWorkspacePreviewConfig(screen, foldableDisplay)
+        val config = viewModel.getWorkspacePreviewConfig(screen, deviceDisplayType)
         WorkspacePreviewBinder.bind(
             workspaceSurface,
             config,
@@ -72,8 +81,8 @@
             screen = screen,
             displaySize = displaySize,
             applicationContext = applicationContext,
-            mainScope = mainScope,
             viewLifecycleOwner = viewLifecycleOwner,
+            deviceDisplayType = deviceDisplayType,
         )
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
index 0453495..ddfa0b6 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
@@ -21,19 +21,21 @@
 import android.view.LayoutInflater
 import android.view.SurfaceHolder
 import android.view.SurfaceView
+import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import com.android.wallpaper.R
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.module.CustomizationSections.Screen
 import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel
 import com.android.wallpaper.picker.data.WallpaperModel
-import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.util.SurfaceViewUtil
 import com.android.wallpaper.picker.preview.ui.util.SurfaceViewUtil.attachView
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils
+import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils.shouldEnforceSingleEngine
 import com.android.wallpaper.util.wallpaperconnection.WallpaperEngineConnection.WallpaperEngineConnectionListener
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
 
@@ -53,71 +55,122 @@
         screen: Screen,
         displaySize: Point,
         applicationContext: Context,
-        @MainDispatcher mainScope: CoroutineScope,
         viewLifecycleOwner: LifecycleOwner,
+        deviceDisplayType: DeviceDisplayType,
     ) {
-        var job: Job? = null
-        surface.setZOrderMediaOverlay(true)
-        surface.holder.addCallback(
-            object : SurfaceViewUtil.SurfaceCallback {
-                override fun surfaceCreated(holder: SurfaceHolder) {
-                    job =
-                        viewLifecycleOwner.lifecycleScope.launch {
-                            viewModel.smallWallpaper.collect { (wallpaper, whichPreview) ->
-                                if (wallpaper is WallpaperModel.LiveWallpaperModel) {
-                                    WallpaperConnectionUtils.connect(
-                                        applicationContext,
-                                        mainScope,
-                                        wallpaper,
-                                        whichPreview,
-                                        screen.toFlag(),
-                                        surface,
-                                        object : WallpaperEngineConnectionListener {
-                                            override fun onWallpaperColorsChanged(
-                                                colors: WallpaperColors?,
-                                                displayId: Int
-                                            ) {
-                                                viewModel.setWallpaperConnectionColors(
-                                                    WallpaperColorsModel.Loaded(colors)
-                                                )
-                                            }
+        var surfaceCallback: SurfaceViewUtil.SurfaceCallback? = null
+        viewLifecycleOwner.lifecycleScope.launch {
+            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
+                surfaceCallback =
+                    bindSurface(
+                        applicationContext = applicationContext,
+                        surface = surface,
+                        viewModel = viewModel,
+                        screen = screen,
+                        deviceDisplayType = deviceDisplayType,
+                        displaySize = displaySize,
+                        lifecycleOwner = viewLifecycleOwner,
+                    )
+                surface.setZOrderMediaOverlay(true)
+                surfaceCallback?.let { surface.holder.addCallback(it) }
+            }
+            // When OnDestroy, release the surface
+            surfaceCallback?.let {
+                surface.holder.removeCallback(it)
+                surfaceCallback = null
+            }
+        }
+    }
+
+    /**
+     * Create a surface callback that binds the surface when surface created. Note that we return
+     * the surface callback reference so that we can remove the callback from the surface when the
+     * screen is destroyed.
+     */
+    private fun bindSurface(
+        applicationContext: Context,
+        surface: SurfaceView,
+        viewModel: WallpaperPreviewViewModel,
+        screen: Screen,
+        deviceDisplayType: DeviceDisplayType,
+        displaySize: Point,
+        lifecycleOwner: LifecycleOwner,
+    ): SurfaceViewUtil.SurfaceCallback {
+
+        return object : SurfaceViewUtil.SurfaceCallback {
+
+            var job: Job? = null
+            var loadingAnimationBinding: PreviewEffectsLoadingBinder.Binding? = null
+
+            override fun surfaceCreated(holder: SurfaceHolder) {
+                job =
+                    lifecycleOwner.lifecycleScope.launch {
+                        viewModel.smallWallpaper.collect { (wallpaper, whichPreview) ->
+                            if (wallpaper is WallpaperModel.LiveWallpaperModel) {
+                                WallpaperConnectionUtils.connect(
+                                    applicationContext,
+                                    wallpaper,
+                                    whichPreview,
+                                    screen.toFlag(),
+                                    surface,
+                                    WallpaperConnectionUtils.EngineRenderingConfig(
+                                        wallpaper.shouldEnforceSingleEngine(),
+                                        deviceDisplayType = deviceDisplayType,
+                                        viewModel.smallerDisplaySize,
+                                        viewModel.wallpaperDisplaySize.value,
+                                    ),
+                                    object : WallpaperEngineConnectionListener {
+                                        override fun onWallpaperColorsChanged(
+                                            colors: WallpaperColors?,
+                                            displayId: Int
+                                        ) {
+                                            viewModel.setWallpaperConnectionColors(
+                                                WallpaperColorsModel.Loaded(colors)
+                                            )
                                         }
-                                    )
-                                } else if (wallpaper is WallpaperModel.StaticWallpaperModel) {
-                                    val staticPreviewView =
-                                        LayoutInflater.from(applicationContext)
-                                            .inflate(R.layout.fullscreen_wallpaper_preview, null)
-                                    surface.attachView(staticPreviewView)
-                                    // Bind static wallpaper
-                                    StaticWallpaperPreviewBinder.bind(
-                                        lowResImageView =
-                                            staticPreviewView.requireViewById(R.id.low_res_image),
-                                        fullResImageView =
+                                    },
+                                )
+                            } else if (wallpaper is WallpaperModel.StaticWallpaperModel) {
+                                val staticPreviewView =
+                                    LayoutInflater.from(applicationContext)
+                                        .inflate(R.layout.fullscreen_wallpaper_preview, null)
+                                surface.attachView(staticPreviewView)
+                                // Bind static wallpaper
+                                StaticWallpaperPreviewBinder.bind(
+                                    lowResImageView =
+                                        staticPreviewView.requireViewById(R.id.low_res_image),
+                                    fullResImageView =
+                                        staticPreviewView.requireViewById(R.id.full_res_image),
+                                    viewModel = viewModel.staticWallpaperPreviewViewModel,
+                                    displaySize = displaySize,
+                                    viewLifecycleOwner = lifecycleOwner,
+                                )
+                                // This is to possibly shut down all live wallpaper services
+                                // if they exist; otherwise static wallpaper can not show up.
+                                WallpaperConnectionUtils.disconnectAllServices(applicationContext)
+
+                                loadingAnimationBinding =
+                                    PreviewEffectsLoadingBinder.bind(
+                                        view =
                                             staticPreviewView.requireViewById(R.id.full_res_image),
-                                        viewModel = viewModel.staticWallpaperPreviewViewModel,
-                                        displaySize = displaySize,
-                                        viewLifecycleOwner = viewLifecycleOwner,
-                                        shouldCalibrateWithSystemScale = true,
+                                        viewModel = viewModel,
+                                        viewLifecycleOwner = lifecycleOwner,
                                     )
-                                    // This is to possibly shut down all live wallpaper services
-                                    // if they exist; otherwise static wallpaper can not show up.
-                                    WallpaperConnectionUtils.disconnectAllServices(
-                                        applicationContext
-                                    )
-                                }
                             }
                         }
-                }
-
-                override fun surfaceDestroyed(holder: SurfaceHolder) {
-                    job?.cancel()
-                    // Note that we disconnect wallpaper connection for live wallpapers in
-                    // WallpaperPreviewActivity's onDestroy().
-                    // This is to reduce multiple times of connecting and disconnecting live
-                    // wallpaper services, when going back and forth small and full preview.
-                }
+                    }
             }
-        )
-        // TODO (b/300979155): Clean up surface when no longer needed, e.g. onDestroyed
+
+            override fun surfaceDestroyed(holder: SurfaceHolder) {
+                job?.cancel()
+                job = null
+                loadingAnimationBinding?.destroy()
+                loadingAnimationBinding = null
+                // Note that we disconnect wallpaper connection for live wallpapers in
+                // WallpaperPreviewActivity's onDestroy().
+                // This is to reduce multiple times of connecting and disconnecting live
+                // wallpaper services, when going back and forth small and full preview.
+            }
+        }
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
index c481ea7..10abd08 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
@@ -25,13 +25,13 @@
 import android.view.animation.Interpolator
 import android.view.animation.PathInterpolator
 import android.widget.ImageView
+import androidx.core.view.doOnLayout
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.tracing.TraceUtils.trace
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
 import com.android.wallpaper.picker.preview.ui.util.FullResImageViewUtil
-import com.android.wallpaper.picker.preview.ui.view.SystemScaledWallpaperPreviewSurfaceView
 import com.android.wallpaper.picker.preview.ui.viewmodel.StaticWallpaperPreviewViewModel
 import com.android.wallpaper.util.RtlUtils
 import com.android.wallpaper.util.WallpaperCropUtils
@@ -45,23 +45,23 @@
     private val ALPHA_OUT: Interpolator = PathInterpolator(0f, 0f, 0.8f, 1f)
     private const val CROSS_FADE_DURATION: Long = 200
 
-    fun bind(
+    suspend fun bind(
         lowResImageView: ImageView,
         fullResImageView: SubsamplingScaleImageView,
         viewModel: StaticWallpaperPreviewViewModel,
         displaySize: Point,
         viewLifecycleOwner: LifecycleOwner,
-        shouldCalibrateWithSystemScale: Boolean = false,
+        isFullScreen: Boolean = false,
     ) {
         lowResImageView.initLowResImageView()
         fullResImageView.initFullResImageView()
 
-        viewLifecycleOwner.lifecycleScope.launch {
-            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
-                launch { viewModel.lowResBitmap.collect { lowResImageView.setImageBitmap(it) } }
+        viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+            launch { viewModel.lowResBitmap.collect { lowResImageView.setImageBitmap(it) } }
 
-                launch {
-                    viewModel.subsamplingScaleImageViewModel.collect { imageModel ->
+            launch {
+                viewModel.subsamplingScaleImageViewModel.collect { imageModel ->
+                    trace(TAG) {
                         val cropHint = imageModel.fullPreviewCropModels?.get(displaySize)?.cropHint
                         fullResImageView.setFullResImage(
                             ImageSource.cachedBitmap(imageModel.rawWallpaperBitmap),
@@ -69,11 +69,11 @@
                             displaySize,
                             cropHint,
                             RtlUtils.isRtl(lowResImageView.context),
-                            shouldCalibrateWithSystemScale,
+                            isFullScreen,
                         )
 
-                        // Fill in the default crop region if the displaySize for this preview is
-                        // missing.
+                        // Fill in the default crop region if the displaySize for this preview
+                        // is missing.
                         viewModel.fullPreviewCropModels.putIfAbsent(
                             displaySize,
                             FullPreviewCropModel(
@@ -111,42 +111,42 @@
         setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE)
     }
 
-    /**
-     * @param shouldCalibrateWithSystemScale This flag should be true for rendering small previews.
-     *   Unlikely full wallpaper preview for static wallpapers, small wallpaper preview does not
-     *   scale up the surface view larger than the display view to conform with the system's actual
-     *   wallpaper scale (see [SystemScaledWallpaperPreviewSurfaceView]). Instead we need to apply
-     *   this system scale to [SubsamplingScaleImageView].
-     */
     private fun SubsamplingScaleImageView.setFullResImage(
         imageSource: ImageSource,
         rawWallpaperSize: Point,
         displaySize: Point,
         cropHint: Rect?,
         isRtl: Boolean,
-        shouldCalibrateWithSystemScale: Boolean = false,
+        isFullScreen: Boolean,
     ) {
         // Set the full res image
         setImage(imageSource)
         // Calculate the scale and the center point for the full res image
-        FullResImageViewUtil.getScaleAndCenter(
-                Point(measuredWidth, measuredHeight),
-                rawWallpaperSize,
-                displaySize,
-                cropHint,
-                isRtl,
-            )
-            .let { scaleAndCenter ->
-                minScale = scaleAndCenter.minScale
-                maxScale = scaleAndCenter.maxScale
-                val scale =
-                    if (shouldCalibrateWithSystemScale)
-                        WallpaperCropUtils.getSystemWallpaperMaximumScale(
-                            context.applicationContext
-                        )
-                    else 1F
-                setScaleAndCenter(scaleAndCenter.defaultScale * scale, scaleAndCenter.center)
-            }
+        doOnLayout {
+            FullResImageViewUtil.getScaleAndCenter(
+                    Point(measuredWidth, measuredHeight),
+                    rawWallpaperSize,
+                    displaySize,
+                    cropHint,
+                    isRtl,
+                )
+                .let { scaleAndCenter ->
+                    // For full screen, the preview image container size has already been adjusted
+                    // to preserve a boundary beyond the visible crop per comment at
+                    // FullWallpaperPreviewBinder#adjustSizesForCropping.
+                    // For small screen preview, we need to apply additional scaling since the
+                    // container is the same size as the preview.
+                    val scale =
+                        if (isFullScreen) 1f
+                        else
+                            WallpaperCropUtils.getSystemWallpaperMaximumScale(
+                                context.applicationContext
+                            )
+                    minScale = scaleAndCenter.minScale * scale
+                    maxScale = scaleAndCenter.maxScale
+                    setScaleAndCenter(scaleAndCenter.defaultScale * scale, scaleAndCenter.center)
+                }
+        }
     }
 
     private fun crossFadeInFullResImageView(lowResImageView: ImageView, fullResImageView: View) {
@@ -164,4 +164,6 @@
                 }
             )
     }
+
+    private const val TAG = "StaticWallpaperPreviewBinder"
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/WorkspacePreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/WorkspacePreviewBinder.kt
index b629d5b..d1af583 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/WorkspacePreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/WorkspacePreviewBinder.kt
@@ -17,20 +17,27 @@
 
 import android.app.WallpaperColors
 import android.os.Bundle
+import android.os.Message
 import android.util.Log
 import android.view.SurfaceHolder
 import android.view.SurfaceView
 import androidx.core.os.bundleOf
+import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel
 import com.android.wallpaper.picker.preview.ui.util.SurfaceViewUtil
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WorkspacePreviewConfigViewModel
 import com.android.wallpaper.util.PreviewUtils
 import com.android.wallpaper.util.SurfaceViewUtils
+import kotlin.coroutines.resume
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.suspendCancellableCoroutine
 
 object WorkspacePreviewBinder {
     fun bind(
@@ -39,25 +46,73 @@
         viewModel: WallpaperPreviewViewModel,
         lifecycleOwner: LifecycleOwner,
     ) {
-        surface.setZOrderMediaOverlay(true)
-        surface.holder.addCallback(
-            object : SurfaceViewUtil.SurfaceCallback {
-                override fun surfaceCreated(holder: SurfaceHolder) {
+        var surfaceCallback: SurfaceViewUtil.SurfaceCallback? = null
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
+                surfaceCallback =
+                    bindSurface(
+                        surface = surface,
+                        viewModel = viewModel,
+                        config = config,
+                        lifecycleOwner = lifecycleOwner,
+                    )
+                surface.setZOrderMediaOverlay(true)
+                surface.holder.addCallback(surfaceCallback)
+            }
+            // When OnDestroy, release the surface
+            surfaceCallback?.let {
+                surface.holder.removeCallback(it)
+                surfaceCallback = null
+            }
+        }
+    }
+
+    /**
+     * Create a surface callback that binds the surface when surface created. Note that we return
+     * the surface callback reference so that we can remove the callback from the surface when the
+     * screen is destroyed.
+     */
+    private fun bindSurface(
+        surface: SurfaceView,
+        viewModel: WallpaperPreviewViewModel,
+        config: WorkspacePreviewConfigViewModel,
+        lifecycleOwner: LifecycleOwner,
+    ): SurfaceViewUtil.SurfaceCallback {
+        return object : SurfaceViewUtil.SurfaceCallback {
+
+            var job: Job? = null
+            var previewDisposableHandle: DisposableHandle? = null
+
+            override fun surfaceCreated(holder: SurfaceHolder) {
+                job =
                     lifecycleOwner.lifecycleScope.launch {
                         viewModel.wallpaperColorsModel.collect {
                             if (it is WallpaperColorsModel.Loaded) {
-                                renderWorkspacePreview(
-                                    surface = surface,
-                                    previewUtils = config.previewUtils,
-                                    displayId = config.displayId,
-                                    wallpaperColors = it.colors
-                                )
+                                val workspaceCallback =
+                                    renderWorkspacePreview(
+                                        surface = surface,
+                                        previewUtils = config.previewUtils,
+                                        displayId =
+                                            viewModel.getDisplayId(config.deviceDisplayType),
+                                        wallpaperColors = it.colors
+                                    )
+                                // Dispose the previous preview on the renderer side.
+                                previewDisposableHandle?.dispose()
+                                previewDisposableHandle = DisposableHandle {
+                                    config.previewUtils.cleanUp(workspaceCallback)
+                                }
                             }
                         }
                     }
-                }
             }
-        )
+
+            override fun surfaceDestroyed(holder: SurfaceHolder) {
+                job?.cancel()
+                job = null
+                previewDisposableHandle?.dispose()
+                previewDisposableHandle = null
+            }
+        }
     }
 
     /**
@@ -69,10 +124,43 @@
         viewModel: WallpaperPreviewViewModel,
         lifecycleOwner: LifecycleOwner,
     ) {
-        surface.setZOrderMediaOverlay(true)
-        surface.holder.addCallback(
-            object : SurfaceViewUtil.SurfaceCallback {
-                override fun surfaceCreated(holder: SurfaceHolder) {
+        var surfaceCallback: SurfaceViewUtil.SurfaceCallback? = null
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
+                surfaceCallback =
+                    bindFullSurface(
+                        surface = surface,
+                        viewModel = viewModel,
+                        lifecycleOwner = lifecycleOwner,
+                    )
+                surface.setZOrderMediaOverlay(true)
+                surface.holder.addCallback(surfaceCallback)
+            }
+            // When OnDestroy, release the surface
+            surfaceCallback?.let {
+                surface.holder.removeCallback(it)
+                surfaceCallback = null
+            }
+        }
+    }
+
+    /**
+     * Create a surface callback that binds the surface when surface created. Note that we return
+     * the surface callback reference so that we can remove the callback from the surface when the
+     * screen is destroyed.
+     */
+    private fun bindFullSurface(
+        surface: SurfaceView,
+        viewModel: WallpaperPreviewViewModel,
+        lifecycleOwner: LifecycleOwner,
+    ): SurfaceViewUtil.SurfaceCallback {
+        return object : SurfaceViewUtil.SurfaceCallback {
+
+            var job: Job? = null
+            var previewDisposableHandle: DisposableHandle? = null
+
+            override fun surfaceCreated(holder: SurfaceHolder) {
+                job =
                     lifecycleOwner.lifecycleScope.launch {
                         combine(
                                 viewModel.fullWorkspacePreviewConfigViewModel,
@@ -82,26 +170,40 @@
                             }
                             .collect { (config, colorsModel) ->
                                 if (colorsModel is WallpaperColorsModel.Loaded) {
-                                    renderWorkspacePreview(
-                                        surface = surface,
-                                        previewUtils = config.previewUtils,
-                                        displayId = config.displayId,
-                                        wallpaperColors = colorsModel.colors
-                                    )
+                                    val workspaceCallback =
+                                        renderWorkspacePreview(
+                                            surface = surface,
+                                            previewUtils = config.previewUtils,
+                                            displayId =
+                                                viewModel.getDisplayId(config.deviceDisplayType),
+                                            wallpaperColors = colorsModel.colors
+                                        )
+                                    // Dispose the previous preview on the renderer side.
+                                    previewDisposableHandle?.dispose()
+                                    previewDisposableHandle = DisposableHandle {
+                                        config.previewUtils.cleanUp(workspaceCallback)
+                                    }
                                 }
                             }
                     }
-                }
             }
-        )
+
+            override fun surfaceDestroyed(holder: SurfaceHolder) {
+                job?.cancel()
+                job = null
+                previewDisposableHandle?.dispose()
+                previewDisposableHandle = null
+            }
+        }
     }
 
-    private fun renderWorkspacePreview(
+    private suspend fun renderWorkspacePreview(
         surface: SurfaceView,
         previewUtils: PreviewUtils,
         displayId: Int,
         wallpaperColors: WallpaperColors? = null,
-    ) {
+    ): Message? {
+        var workspaceCallback: Message? = null
         if (previewUtils.supportsPreview()) {
             val extras = bundleOf(Pair(SurfaceViewUtils.KEY_DISPLAY_ID, displayId))
             wallpaperColors?.let {
@@ -112,29 +214,34 @@
                     surface,
                     extras,
                 )
-            previewUtils.renderPreview(
-                request,
-                object : PreviewUtils.WorkspacePreviewCallback {
-                    override fun onPreviewRendered(resultBundle: Bundle?) {
-                        if (resultBundle != null) {
-                            SurfaceViewUtils.getSurfacePackage(resultBundle).apply {
-                                if (this != null) {
-                                    surface.setChildSurfacePackage(this)
-                                } else {
-                                    Log.w(
-                                        TAG,
-                                        "Result bundle from rendering preview does not contain " +
-                                            "a child surface package."
-                                    )
+            workspaceCallback = suspendCancellableCoroutine { continuation ->
+                previewUtils.renderPreview(
+                    request,
+                    object : PreviewUtils.WorkspacePreviewCallback {
+                        override fun onPreviewRendered(resultBundle: Bundle?) {
+                            if (resultBundle != null) {
+                                SurfaceViewUtils.getSurfacePackage(resultBundle).apply {
+                                    if (this != null) {
+                                        surface.setChildSurfacePackage(this)
+                                    } else {
+                                        Log.w(
+                                            TAG,
+                                            "Result bundle from rendering preview does not contain " +
+                                                "a child surface package."
+                                        )
+                                    }
                                 }
+                                continuation.resume(SurfaceViewUtils.getCallback(resultBundle))
+                            } else {
+                                Log.w(TAG, "Result bundle from rendering preview is null.")
+                                continuation.resume(null)
                             }
-                        } else {
-                            Log.w(TAG, "Result bundle from rendering preview is null.")
                         }
                     }
-                }
-            )
+                )
+            }
         }
+        return workspaceCallback
     }
 
     const val TAG = "WorkspacePreviewBinder"
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeEditPreviewFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeEditPreviewFragment.kt
new file mode 100644
index 0000000..9d3d308
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeEditPreviewFragment.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2023 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.wallpaper.picker.preview.ui.fragment
+
+import android.app.Activity.RESULT_OK
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.SurfaceView
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.Toolbar
+import androidx.activity.result.contract.ActivityResultContract
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.core.view.isVisible
+import androidx.fragment.app.activityViewModels
+import androidx.navigation.fragment.findNavController
+import com.android.wallpaper.R
+import com.android.wallpaper.picker.AppbarFragment
+import com.android.wallpaper.picker.preview.ui.binder.FullWallpaperPreviewBinder
+import com.android.wallpaper.picker.preview.ui.fragment.SmallPreviewFragment.Companion.ARG_EDIT_INTENT
+import com.android.wallpaper.picker.preview.ui.viewmodel.PreviewActionsViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
+import com.android.wallpaper.util.DisplayUtils
+import dagger.hilt.android.AndroidEntryPoint
+import dagger.hilt.android.qualifiers.ApplicationContext
+import javax.inject.Inject
+
+/** Shows full preview with an edit activity overlay. */
+@AndroidEntryPoint(AppbarFragment::class)
+class CreativeEditPreviewFragment : Hilt_CreativeEditPreviewFragment() {
+
+    @Inject @ApplicationContext lateinit var appContext: Context
+    @Inject lateinit var displayUtils: DisplayUtils
+
+    private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        val view = inflater.inflate(R.layout.fragment_full_preview, container, false)
+        setUpToolbar(view)
+
+        wallpaperPreviewViewModel.setDefaultFullPreviewConfigViewModel(
+            deviceDisplayType = displayUtils.getCurrentDisplayType(requireActivity()),
+        )
+
+        FullWallpaperPreviewBinder.bind(
+            applicationContext = appContext,
+            view = view,
+            viewModel = wallpaperPreviewViewModel,
+            transition = null,
+            displayUtils = displayUtils,
+            lifecycleOwner = viewLifecycleOwner,
+            savedInstanceState = savedInstanceState,
+        )
+
+        view.requireViewById<Toolbar>(R.id.toolbar).isVisible = false
+        view.requireViewById<SurfaceView>(R.id.workspace_surface).isVisible = false
+        view.requireViewById<Button>(R.id.crop_wallpaper_button).isVisible = false
+
+        val intent =
+            arguments?.getParcelable(ARG_EDIT_INTENT, Intent::class.java)
+                ?: throw IllegalArgumentException(
+                    "To render the first screen in the create new creative wallpaper flow, the intent for rendering the edit activity overlay can not be null."
+                )
+        val isCreateNew =
+            intent.getBooleanExtra(PreviewActionsViewModel.EXTRA_KEY_IS_CREATE_NEW, false)
+        val creativeWallpaperEditActivityResult =
+            if (isCreateNew) {
+                requireActivity().activityResultRegistry.register(
+                    CREATIVE_RESULT_REGISTRY,
+                    ActivityResultContracts.StartActivityForResult()
+                ) {
+                    wallpaperPreviewViewModel.isCurrentlyEditingCreativeWallpaper = false
+                    // Callback when the overlaying edit activity is finished. Result code of
+                    // RESULT_OK means the user clicked on the check button; RESULT_CANCELED
+                    // otherwise.
+                    if (it.resultCode == RESULT_OK) {
+                        // When clicking on the check button, navigate to the small preview
+                        // fragment.
+                        findNavController()
+                            .navigate(
+                                R.id.action_creativeEditPreviewFragment_to_smallPreviewFragment
+                            )
+                    } else {
+                        activity?.finish()
+                    }
+                }
+            } else {
+                requireActivity().activityResultRegistry.register(
+                    CREATIVE_RESULT_REGISTRY,
+                    object : ActivityResultContract<Intent, Int>() {
+                        override fun createIntent(context: Context, input: Intent): Intent {
+                            return input
+                        }
+
+                        override fun parseResult(resultCode: Int, intent: Intent?): Int {
+                            wallpaperPreviewViewModel.isCurrentlyEditingCreativeWallpaper = false
+                            return resultCode
+                        }
+                    },
+                ) {
+                    findNavController().popBackStack()
+                }
+            }
+
+        if (!wallpaperPreviewViewModel.isCurrentlyEditingCreativeWallpaper) {
+            wallpaperPreviewViewModel.isCurrentlyEditingCreativeWallpaper = true
+            creativeWallpaperEditActivityResult.launch(intent)
+        }
+
+        return view
+    }
+
+    override fun getToolbarColorId(): Int {
+        return android.R.color.transparent
+    }
+
+    companion object {
+        private const val CREATIVE_RESULT_REGISTRY = "creative_result_registry"
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeNewPreviewFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeNewPreviewFragment.kt
deleted file mode 100644
index e4f7491..0000000
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeNewPreviewFragment.kt
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2023 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.wallpaper.picker.preview.ui.fragment
-
-import android.app.Activity.RESULT_OK
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.SurfaceView
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.Toolbar
-import androidx.activity.result.contract.ActivityResultContract
-import androidx.core.view.isVisible
-import androidx.fragment.app.activityViewModels
-import androidx.navigation.fragment.findNavController
-import com.android.wallpaper.R
-import com.android.wallpaper.picker.AppbarFragment
-import com.android.wallpaper.picker.di.modules.MainDispatcher
-import com.android.wallpaper.picker.preview.ui.binder.FullWallpaperPreviewBinder
-import com.android.wallpaper.picker.preview.ui.fragment.SmallPreviewFragment.Companion.ARG_EDIT_INTENT
-import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
-import com.android.wallpaper.util.DisplayUtils
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.qualifiers.ApplicationContext
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-
-/** Shows full preview with an edit activity overlay. */
-@AndroidEntryPoint(AppbarFragment::class)
-class CreativeNewPreviewFragment : Hilt_CreativeNewPreviewFragment() {
-
-    @Inject @ApplicationContext lateinit var appContext: Context
-    @Inject lateinit var displayUtils: DisplayUtils
-    @Inject @MainDispatcher lateinit var mainScope: CoroutineScope
-
-    private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
-
-    override fun onCreateView(
-        inflater: LayoutInflater,
-        container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View? {
-        val view = inflater.inflate(R.layout.fragment_full_preview, container, false)
-        setUpToolbar(view)
-
-        FullWallpaperPreviewBinder.bind(
-            applicationContext = appContext,
-            view = view,
-            viewModel = wallpaperPreviewViewModel,
-            displayUtils = displayUtils,
-            lifecycleOwner = viewLifecycleOwner,
-            mainScope = mainScope,
-        )
-
-        wallpaperPreviewViewModel.setDefaultWallpaperPreviewConfigViewModel(
-            displayUtils.getRealSize(requireActivity().display)
-        )
-        view.requireViewById<Toolbar>(R.id.toolbar).isVisible = false
-        view.requireViewById<SurfaceView>(R.id.workspace_surface).isVisible = false
-        view.requireViewById<Button>(R.id.crop_wallpaper_button).isVisible = false
-
-        val intent =
-            arguments?.getParcelable(ARG_EDIT_INTENT, Intent::class.java)
-                ?: throw IllegalArgumentException(
-                    "To render the first screen in the create new creative wallpaper flow, the intent for rendering the edit activity overlay can not be null."
-                )
-        val creativeWallpaperEditActivityResult =
-            registerForActivityResult(
-                object : ActivityResultContract<Intent, Int>() {
-                    override fun createIntent(context: Context, input: Intent): Intent {
-                        return input
-                    }
-
-                    override fun parseResult(resultCode: Int, intent: Intent?): Int {
-                        return resultCode
-                    }
-                },
-            ) {
-                // Callback when the overlaying edit activity is finished. Result code of RESULT_OK
-                // means the user clicked on the check button; RESULT_CANCELED otherwise.
-                if (it == RESULT_OK) {
-                    // When clicking on the check button, navigate to the small preview fragment.
-                    findNavController()
-                        .navigate(R.id.action_creativeNewPreviewFragment_to_smallPreviewFragment)
-                } else {
-                    activity?.finish()
-                }
-            }
-        creativeWallpaperEditActivityResult.launch(intent)
-
-        return view
-    }
-
-    override fun getToolbarColorId(): Int {
-        return android.R.color.transparent
-    }
-}
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
index 1a34086..eb0bc8f 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
@@ -16,36 +16,28 @@
 package com.android.wallpaper.picker.preview.ui.fragment
 
 import android.content.Context
-import android.content.Intent
 import android.os.Bundle
 import android.view.LayoutInflater
-import android.view.SurfaceView
 import android.view.View
 import android.view.ViewGroup
-import android.widget.Button
-import android.widget.Toolbar
-import androidx.activity.result.contract.ActivityResultContract
 import androidx.cardview.widget.CardView
 import androidx.core.content.ContextCompat
 import androidx.core.view.ViewCompat
-import androidx.core.view.isVisible
 import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.findNavController
-import androidx.transition.TransitionInflater
+import androidx.transition.Transition
 import com.android.wallpaper.R
 import com.android.wallpaper.picker.AppbarFragment
-import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.binder.CropWallpaperButtonBinder
 import com.android.wallpaper.picker.preview.ui.binder.FullWallpaperPreviewBinder
 import com.android.wallpaper.picker.preview.ui.binder.PreviewTooltipBinder
 import com.android.wallpaper.picker.preview.ui.binder.WorkspacePreviewBinder
-import com.android.wallpaper.picker.preview.ui.fragment.SmallPreviewFragment.Companion.ARG_EDIT_INTENT
+import com.android.wallpaper.picker.preview.ui.transition.ChangeScaleAndPosition
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
 import dagger.hilt.android.AndroidEntryPoint
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
 
 /** Shows full preview of user selected wallpaper for cropping, zooming and positioning. */
 @AndroidEntryPoint(AppbarFragment::class)
@@ -53,16 +45,13 @@
 
     @Inject @ApplicationContext lateinit var appContext: Context
     @Inject lateinit var displayUtils: DisplayUtils
-    @Inject @MainDispatcher lateinit var mainScope: CoroutineScope
 
     private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
+    private var useLightToolbar = false
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        if (ENABLE_ANIMATION) {
-            sharedElementEnterTransition =
-                TransitionInflater.from(appContext).inflateTransition(R.transition.shared_view)
-        }
+        sharedElementEnterTransition = ChangeScaleAndPosition()
     }
 
     override fun onCreateView(
@@ -79,40 +68,18 @@
             SmallPreviewFragment.FULL_PREVIEW_SHARED_ELEMENT_ID
         )
 
-        val creativeWallpaperEditActivityResult =
-            registerForActivityResult(
-                object : ActivityResultContract<Intent, Int>() {
-                    override fun createIntent(context: Context, input: Intent): Intent {
-                        return input
-                    }
-
-                    override fun parseResult(resultCode: Int, intent: Intent?): Int {
-                        return resultCode
-                    }
-                },
-            ) {
-                // Callback when the overlaying edit activity is finished. Result code of RESULT_OK
-                // means the user clicked on the check button; RESULT_CANCELED otherwise.
-                findNavController().popBackStack()
-            }
-        // If edit intent is nonnull, we launch the edit overlay activity, with the wallpaper
-        // preview from the Wallpaper Picker app's fragment.
-        arguments?.getParcelable(ARG_EDIT_INTENT, Intent::class.java)?.let {
-            view.requireViewById<Toolbar>(R.id.toolbar).isVisible = false
-            view.requireViewById<SurfaceView>(R.id.workspace_surface).isVisible = false
-            view.requireViewById<Button>(R.id.crop_wallpaper_button).isVisible = false
-            creativeWallpaperEditActivityResult.launch(it)
-            return view
-        }
-
         FullWallpaperPreviewBinder.bind(
             applicationContext = appContext,
             view = view,
             viewModel = wallpaperPreviewViewModel,
+            transition = sharedElementEnterTransition as? Transition,
             displayUtils = displayUtils,
             lifecycleOwner = viewLifecycleOwner,
-            mainScope = mainScope,
-        )
+            savedInstanceState = savedInstanceState,
+        ) { isFullScreen ->
+            useLightToolbar = isFullScreen
+            setUpToolbar(view)
+        }
 
         CropWallpaperButtonBinder.bind(
             button = view.requireViewById(R.id.crop_wallpaper_button),
@@ -128,10 +95,9 @@
             lifecycleOwner = viewLifecycleOwner,
         )
 
-        PreviewTooltipBinder.bind(
+        PreviewTooltipBinder.bindFullPreviewTooltip(
             tooltipStub = view.requireViewById(R.id.tooltip_stub),
-            enableClickToDismiss = true,
-            viewModel = wallpaperPreviewViewModel,
+            viewModel = wallpaperPreviewViewModel.fullTooltipViewModel,
             lifecycleOwner = viewLifecycleOwner,
         )
 
@@ -148,10 +114,15 @@
     }
 
     override fun getToolbarTextColor(): Int {
-        return ContextCompat.getColor(requireContext(), R.color.system_on_surface)
+        return if (useLightToolbar) {
+            ContextCompat.getColor(requireContext(), android.R.color.system_on_primary_light)
+        } else {
+            ContextCompat.getColor(requireContext(), R.color.system_on_surface)
+        }
     }
 
-    companion object {
-        const val ENABLE_ANIMATION = false
+    override fun isStatusBarLightText(): Boolean {
+        return requireContext().resources.getBoolean(R.bool.isFragmentStatusBarLightText) or
+            useLightToolbar
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/SetWallpaperDialogFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/SetWallpaperDialogFragment.kt
index 24ceaf4..be1d58c 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/SetWallpaperDialogFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/SetWallpaperDialogFragment.kt
@@ -17,12 +17,16 @@
 package com.android.wallpaper.picker.preview.ui.fragment
 
 import android.app.Activity
+import android.app.ActivityOptions
 import android.app.AlertDialog
 import android.app.Dialog
 import android.content.DialogInterface
 import android.content.Intent
 import android.os.Bundle
+import android.transition.Slide
+import android.view.Gravity
 import android.view.LayoutInflater
+import android.widget.FrameLayout.LayoutParams
 import android.widget.Toast
 import androidx.fragment.app.DialogFragment
 import androidx.fragment.app.activityViewModels
@@ -50,6 +54,17 @@
 
     private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
 
+    override fun onStart() {
+        super.onStart()
+        // Set dialog size
+        val widthDimenId =
+            if (displayUtils.hasMultiInternalDisplays()) R.dimen.set_wallpaper_dialog_foldable_width
+            else R.dimen.set_wallpaper_dialog_handheld_width
+        requireDialog()
+            .window
+            ?.setLayout(resources.getDimension(widthDimenId).toInt(), LayoutParams.WRAP_CONTENT)
+    }
+
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
         super.onCreateDialog(savedInstanceState)
 
@@ -83,6 +98,7 @@
                     .show()
                 if (activityReference != null) {
                     if (wallpaperPreviewViewModel.isNewTask) {
+                        activityReference.window?.exitTransition = Slide(Gravity.END)
                         val intent = Intent(activityReference, TrampolinePickerActivity::class.java)
                         intent.setFlags(
                             Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
@@ -92,11 +108,15 @@
                             if (wallpaperPreviewViewModel.isViewAsHome) LAUNCH_SOURCE_LAUNCHER
                             else LAUNCH_SOURCE_SETTINGS_HOMEPAGE
                         )
-                        activityReference.startActivity(intent)
+                        activityReference.startActivity(
+                            intent,
+                            ActivityOptions.makeSceneTransitionAnimation(activityReference)
+                                .toBundle()
+                        )
                     } else {
                         activityReference.setResult(Activity.RESULT_OK)
-                        activityReference.finish()
                     }
+                    activityReference.finish()
                 }
             },
             onDismissDialog = { findNavController().popBackStack() },
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
index d0ec9e5..a269252 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
@@ -16,7 +16,6 @@
 package com.android.wallpaper.picker.preview.ui.fragment
 
 import android.app.AlertDialog
-import android.app.ProgressDialog
 import android.content.Context
 import android.content.Intent
 import android.os.Bundle
@@ -27,18 +26,21 @@
 import androidx.core.content.ContextCompat
 import androidx.core.view.ViewCompat
 import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import androidx.navigation.fragment.FragmentNavigatorExtras
 import androidx.navigation.fragment.findNavController
 import com.android.wallpaper.R
 import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.picker.AppbarFragment
-import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.binder.DualPreviewSelectorBinder
 import com.android.wallpaper.picker.preview.ui.binder.PreviewActionsBinder
 import com.android.wallpaper.picker.preview.ui.binder.PreviewSelectorBinder
 import com.android.wallpaper.picker.preview.ui.binder.SetWallpaperButtonBinder
 import com.android.wallpaper.picker.preview.ui.binder.SetWallpaperProgressDialogBinder
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.DualPreviewViewPager
+import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.TabTextPagerAdapter
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.views.TabsPagerContainer
 import com.android.wallpaper.picker.preview.ui.view.PreviewActionGroup
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action
@@ -47,7 +49,7 @@
 import dagger.hilt.android.AndroidEntryPoint
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 /**
  * This fragment displays the preview of the selected wallpaper on all available workspaces and
@@ -58,11 +60,10 @@
 
     @Inject @ApplicationContext lateinit var appContext: Context
     @Inject lateinit var displayUtils: DisplayUtils
-    @Inject @MainDispatcher lateinit var mainScope: CoroutineScope
     @Inject lateinit var logger: UserEventLogger
 
     private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
-    private lateinit var setWallpaperProgressDialog: ProgressDialog
+    private lateinit var setWallpaperProgressDialog: AlertDialog
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -86,14 +87,10 @@
             viewModel = wallpaperPreviewViewModel,
             lifecycleOwner = viewLifecycleOwner,
         ) {
-            findNavController().navigate(R.id.action_smallPreviewFragment_to_setWallpaperDialog)
+            findNavController().navigate(R.id.setWallpaperDialog)
         }
-        setWallpaperProgressDialog =
-            ProgressDialog(context, R.style.LightDialogTheme).apply {
-                setTitle(null)
-                setMessage(context.getString(R.string.set_wallpaper_progress_message))
-                isIndeterminate = true
-            }
+
+        setWallpaperProgressDialog = getSetWallpaperProgressDialog(inflater)
         SetWallpaperProgressDialogBinder.bind(
             dialog = setWallpaperProgressDialog,
             viewModel = wallpaperPreviewViewModel,
@@ -120,20 +117,24 @@
         if (displayUtils.hasMultiInternalDisplays()) {
             val dualPreviewView: DualPreviewViewPager =
                 view.requireViewById(R.id.dual_preview_pager)
-            val tabPager: TabsPagerContainer = view.requireViewById(R.id.pager_container)
+            val viewPager =
+                view.requireViewById<TabsPagerContainer>(R.id.pager_container).getViewPager()
 
             DualPreviewSelectorBinder.bind(
-                tabPager.getViewPager(),
+                viewPager,
                 dualPreviewView,
                 wallpaperPreviewViewModel,
                 appContext,
                 viewLifecycleOwner,
-                mainScope,
                 currentNavDestId,
             ) { sharedElement ->
+                wallpaperPreviewViewModel.isViewAsHome =
+                    (viewPager.adapter as TabTextPagerAdapter).getIsHome(viewPager.currentItem)
                 ViewCompat.setTransitionName(sharedElement, SMALL_PREVIEW_SHARED_ELEMENT_ID)
                 val extras =
                     FragmentNavigatorExtras(sharedElement to FULL_PREVIEW_SHARED_ELEMENT_ID)
+                // Set to false on small-to-full preview transition to remove surfaceView jank.
+                (view as ViewGroup).isTransitionGroup = false
                 findNavController()
                     .navigate(
                         resId = R.id.action_smallPreviewFragment_to_fullPreviewFragment,
@@ -143,22 +144,26 @@
                     )
             }
         } else {
-            val tabPager: TabsPagerContainer = view.requireViewById(R.id.pager_container)
+            val viewPager =
+                view.requireViewById<TabsPagerContainer>(R.id.pager_container).getViewPager()
 
             PreviewSelectorBinder.bind(
-                tabPager.getViewPager(),
+                viewPager,
                 view.requireViewById(R.id.pager_previews),
                 displayUtils.getRealSize(displayUtils.getWallpaperDisplay()),
                 // TODO: pass correct view models for the view pager
                 wallpaperPreviewViewModel,
                 appContext,
                 viewLifecycleOwner,
-                mainScope,
                 currentNavDestId,
             ) { sharedElement ->
+                wallpaperPreviewViewModel.isViewAsHome =
+                    (viewPager.adapter as TabTextPagerAdapter).getIsHome(viewPager.currentItem)
                 ViewCompat.setTransitionName(sharedElement, SMALL_PREVIEW_SHARED_ELEMENT_ID)
                 val extras =
                     FragmentNavigatorExtras(sharedElement to FULL_PREVIEW_SHARED_ELEMENT_ID)
+                // Set to false on small-to-full preview transition to remove surfaceView jank.
+                (view as ViewGroup).isTransitionGroup = false
                 findNavController()
                     .navigate(
                         resId = R.id.action_smallPreviewFragment_to_fullPreviewFragment,
@@ -168,6 +173,14 @@
                     )
             }
         }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                // Always reset isTransitionGroup value on start for the edge case that the
+                // navigation is cancelled and the fragment resumes.
+                (view as ViewGroup).isTransitionGroup = true
+            }
+        }
     }
 
     private fun bindPreviewActions(view: View) {
@@ -192,13 +205,13 @@
             floatingSheet = view.requireViewById(R.id.floating_sheet),
             previewViewModel = wallpaperPreviewViewModel,
             actionsViewModel = wallpaperPreviewViewModel.previewActionsViewModel,
-            displaySize = displayUtils.getRealSize(requireActivity().display),
+            deviceDisplayType = displayUtils.getCurrentDisplayType(requireActivity()),
             lifecycleOwner = viewLifecycleOwner,
             logger = logger,
             onStartEditActivity = {
                 findNavController()
                     .navigate(
-                        resId = R.id.action_smallPreviewFragment_to_fullPreviewFragment,
+                        resId = R.id.action_smallPreviewFragment_to_creativeEditPreviewFragment,
                         args = Bundle().apply { putParcelable(ARG_EDIT_INTENT, it) },
                         navOptions = null,
                         navigatorExtras = null,
@@ -228,6 +241,13 @@
         )
     }
 
+    private fun getSetWallpaperProgressDialog(
+        inflater: LayoutInflater,
+    ): AlertDialog {
+        val dialogView = inflater.inflate(R.layout.set_wallpaper_progress_dialog_view, null)
+        return AlertDialog.Builder(activity).setView(dialogView).create()
+    }
+
     companion object {
         const val SMALL_PREVIEW_SHARED_ELEMENT_ID = "small_preview_shared_element"
         const val FULL_PREVIEW_SHARED_ELEMENT_ID = "full_preview_shared_element"
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/DualPreviewViewPager.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/DualPreviewViewPager.kt
index 9ed8e06..1f4cc93 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/DualPreviewViewPager.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/DualPreviewViewPager.kt
@@ -20,7 +20,7 @@
 import android.util.AttributeSet
 import androidx.viewpager.widget.ViewPager
 import com.android.wallpaper.R
-import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
 
 /**
@@ -32,7 +32,7 @@
 class DualPreviewViewPager
 @JvmOverloads
 constructor(context: Context, attrs: AttributeSet? = null /* attrs */) : ViewPager(context, attrs) {
-    private var previewDisplaySizes: Map<FoldableDisplay, Point>? = null
+    private var previewDisplaySizes: Map<DeviceDisplayType, Point>? = null
 
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
         if (previewDisplaySizes == null) {
@@ -47,13 +47,13 @@
                         it.getDimension(R.dimen.small_preview_inter_preview_margin) * 3
                 }
 
-        val smallDisplayAR =
-            getPreviewDisplaySize(FoldableDisplay.FOLDED).let { it.x.toFloat() / it.y }
+        val smallDisplayAspectRatio =
+            getPreviewDisplaySize(DeviceDisplayType.FOLDED).let { it.x.toFloat() / it.y }
 
-        val largeDisplayAR =
-            getPreviewDisplaySize(FoldableDisplay.UNFOLDED).let { it.x.toFloat() / it.y }
+        val largeDisplayAspectRatio =
+            getPreviewDisplaySize(DeviceDisplayType.UNFOLDED).let { it.x.toFloat() / it.y }
 
-        val viewPagerHeight = parentWidth / (largeDisplayAR + smallDisplayAR)
+        val viewPagerHeight = parentWidth / (largeDisplayAspectRatio + smallDisplayAspectRatio)
 
         super.onMeasure(
             widthMeasureSpec,
@@ -64,7 +64,7 @@
         )
     }
 
-    fun setDisplaySizes(displaySizes: Map<FoldableDisplay, Point>) {
+    fun setDisplaySizes(displaySizes: Map<DeviceDisplayType, Point>) {
         previewDisplaySizes = displaySizes
     }
 
@@ -74,7 +74,7 @@
      * Outside this class we should get display size via
      * [DualDisplayAspectRatioLayout.getPreviewDisplaySize].
      */
-    private fun getPreviewDisplaySize(display: FoldableDisplay): Point {
+    private fun getPreviewDisplaySize(display: DeviceDisplayType): Point {
         return checkNotNull(previewDisplaySizes?.get(display))
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/TabTextPagerAdapter.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/TabTextPagerAdapter.kt
index 6f4e98c..dfba8c4 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/TabTextPagerAdapter.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/TabTextPagerAdapter.kt
@@ -37,6 +37,22 @@
         return view == `object`
     }
 
+    /**
+     * Obtains the page number for the home or lock tab
+     *
+     * @param isHome if true, this function will return the page number for the home tab, if false
+     *   if false, the one for the lock tab
+     */
+    fun getPageNumber(isHome: Boolean): Int {
+        return textPages.indexOf(
+            if (isHome) R.string.home_screen_message else R.string.lock_screen_message
+        )
+    }
+
+    fun getIsHome(currentItem: Int): Boolean {
+        return textPages[currentItem] == R.string.home_screen_message
+    }
+
     override fun instantiateItem(container: ViewGroup, position: Int): Any {
         val itemView =
             LayoutInflater.from(container.context).inflate(R.layout.item_text, container, false)
diff --git a/src/com/android/wallpaper/picker/preview/ui/transition/ChangeScaleAndPosition.kt b/src/com/android/wallpaper/picker/preview/ui/transition/ChangeScaleAndPosition.kt
new file mode 100644
index 0000000..3a93a47
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/transition/ChangeScaleAndPosition.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.picker.preview.ui.transition
+
+import android.animation.Animator
+import android.animation.ObjectAnimator
+import android.animation.PropertyValuesHolder
+import android.view.ViewGroup
+import androidx.core.animation.doOnStart
+import androidx.transition.Transition
+import androidx.transition.TransitionValues
+
+class ChangeScaleAndPosition : Transition() {
+
+    override fun captureStartValues(transitionValues: TransitionValues) {
+        captureValues(transitionValues)
+    }
+
+    override fun captureEndValues(transitionValues: TransitionValues) {
+        captureValues(transitionValues)
+    }
+
+    override fun getTransitionProperties() = properties
+
+    private fun captureValues(transitionValues: TransitionValues) {
+        val view = transitionValues.view
+        val values = transitionValues.values
+
+        val screenLocation = IntArray(2)
+        view.getLocationOnScreen(screenLocation)
+        values[PROPNAME_POSX] = screenLocation[0]
+        values[PROPNAME_POSY] = screenLocation[1]
+
+        values[PROPNAME_WIDTH] = view.width
+        values[PROPNAME_HEIGHT] = view.height
+    }
+
+    override fun createAnimator(
+        sceneRoot: ViewGroup,
+        startValues: TransitionValues?,
+        endValues: TransitionValues?
+    ): Animator? {
+        if (startValues == null || endValues == null) return null
+
+        val leftDelta =
+            ((startValues.values[PROPNAME_POSX] as Int) - (endValues.values[PROPNAME_POSX] as Int))
+                .toFloat()
+        val topDelta =
+            ((startValues.values[PROPNAME_POSY] as Int) - (endValues.values[PROPNAME_POSY] as Int))
+                .toFloat()
+
+        val scaleWidth =
+            (startValues.values[PROPNAME_WIDTH] as Int).toFloat() /
+                (endValues.values[PROPNAME_WIDTH] as Int).toFloat()
+        val scaleHeight =
+            (startValues.values[PROPNAME_HEIGHT] as Int).toFloat() /
+                (endValues.values[PROPNAME_HEIGHT] as Int).toFloat()
+
+        val view = endValues.view
+        val anim =
+            ObjectAnimator.ofPropertyValuesHolder(
+                view,
+                PropertyValuesHolder.ofFloat("scaleX", scaleWidth, 1f),
+                PropertyValuesHolder.ofFloat("scaleY", scaleHeight, 1f),
+                PropertyValuesHolder.ofFloat("translationX", leftDelta, 0f),
+                PropertyValuesHolder.ofFloat("translationY", topDelta, 0f)
+            )
+        anim.doOnStart {
+            view.pivotX = 0f
+            view.pivotY = 0f
+        }
+        return anim
+    }
+
+    companion object {
+        private const val PROPNAME_POSX = "changeScaleAndPosition:posX"
+        private const val PROPNAME_POSY = "changeScaleAndPosition:posY"
+        private const val PROPNAME_WIDTH = "changeScaleAndPosition:width"
+        private const val PROPNAME_HEIGHT = "changeScaleAndPosition:height"
+        val properties = arrayOf(PROPNAME_POSX, PROPNAME_POSY, PROPNAME_WIDTH, PROPNAME_HEIGHT)
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/ui/util/SurfaceViewUtil.kt b/src/com/android/wallpaper/picker/preview/ui/util/SurfaceViewUtil.kt
index 635e9b8..4fd5593 100644
--- a/src/com/android/wallpaper/picker/preview/ui/util/SurfaceViewUtil.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/util/SurfaceViewUtil.kt
@@ -24,11 +24,11 @@
 
 object SurfaceViewUtil {
 
-    fun SurfaceView.attachView(view: View) {
+    fun SurfaceView.attachView(view: View, newWidth: Int = width, newHeight: Int = height) {
         // Detach view from its parent, if the view has one
         (view.parent as ViewGroup?)?.removeView(view)
         val host = SurfaceControlViewHost(context, display, hostToken)
-        host.setView(view, width, height)
+        host.setView(view, newWidth, newHeight)
         setChildSurfacePackage(checkNotNull(host.surfacePackage))
     }
 
diff --git a/src/com/android/wallpaper/picker/preview/ui/view/DualDisplayAspectRatioLayout.kt b/src/com/android/wallpaper/picker/preview/ui/view/DualDisplayAspectRatioLayout.kt
index 376a88b..5c806ef 100644
--- a/src/com/android/wallpaper/picker/preview/ui/view/DualDisplayAspectRatioLayout.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/view/DualDisplayAspectRatioLayout.kt
@@ -20,7 +20,7 @@
 import android.util.AttributeSet
 import android.widget.LinearLayout
 import com.android.wallpaper.R
-import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import kotlin.math.max
 
 /**
@@ -32,7 +32,7 @@
     attrs: AttributeSet?,
 ) : LinearLayout(context, attrs) {
 
-    private var previewDisplaySizes: Map<FoldableDisplay, Point>? = null
+    private var previewDisplaySizes: Map<DeviceDisplayType, Point>? = null
 
     /**
      * This measures the desired size of the preview views for both of foldable device's displays.
@@ -56,8 +56,8 @@
         // TODO: This only works for portrait mode currently, need to incorporate landscape
         val parentWidth = this.measuredWidth - totalMarginPixels
 
-        val smallDisplaySize = checkNotNull(getPreviewDisplaySize(FoldableDisplay.FOLDED))
-        val largeDisplaySize = checkNotNull(getPreviewDisplaySize(FoldableDisplay.UNFOLDED))
+        val smallDisplaySize = checkNotNull(getPreviewDisplaySize(DeviceDisplayType.FOLDED))
+        val largeDisplaySize = checkNotNull(getPreviewDisplaySize(DeviceDisplayType.UNFOLDED))
 
         // calculate the aspect ratio (ar) of the folded display
         val smallDisplayAR = smallDisplaySize.x.toFloat() / smallDisplaySize.y
@@ -134,20 +134,24 @@
         )
     }
 
-    fun setDisplaySizes(displaySizes: Map<FoldableDisplay, Point>) {
+    fun setDisplaySizes(displaySizes: Map<DeviceDisplayType, Point>) {
         previewDisplaySizes = displaySizes
     }
 
-    fun getPreviewDisplaySize(display: FoldableDisplay): Point? {
+    fun getPreviewDisplaySize(display: DeviceDisplayType): Point? {
         return previewDisplaySizes?.get(display)
     }
 
     companion object {
         /** Defines children view ids for [DualDisplayAspectRatioLayout]. */
-        fun FoldableDisplay.getViewId(): Int {
+        fun DeviceDisplayType.getViewId(): Int {
             return when (this) {
-                FoldableDisplay.FOLDED -> R.id.small_preview_folded_preview
-                FoldableDisplay.UNFOLDED -> R.id.small_preview_unfolded_preview
+                DeviceDisplayType.SINGLE ->
+                    throw IllegalStateException(
+                        "DualDisplayAspectRatioLayout does not supper handheld DeviceDisplayType"
+                    )
+                DeviceDisplayType.FOLDED -> R.id.small_preview_folded_preview
+                DeviceDisplayType.UNFOLDED -> R.id.small_preview_unfolded_preview
             }
         }
     }
diff --git a/src/com/android/wallpaper/picker/preview/ui/view/FullPreviewFrameLayout.kt b/src/com/android/wallpaper/picker/preview/ui/view/FullPreviewFrameLayout.kt
index 810bcc8..5aa5c9d 100644
--- a/src/com/android/wallpaper/picker/preview/ui/view/FullPreviewFrameLayout.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/view/FullPreviewFrameLayout.kt
@@ -52,7 +52,6 @@
         val maxRect = targetSize.findMaxRectWithRatioIn(currentSize)
         val width = maxRect.x.toInt()
         val height = maxRect.y.toInt()
-        setMeasuredDimension(width, height)
         measureChildren(
             MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
             MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
diff --git a/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt b/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt
index b5081fe..e23703e 100644
--- a/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt
@@ -16,6 +16,7 @@
 package com.android.wallpaper.picker.preview.ui.view
 
 import android.content.Context
+import android.net.Uri
 import android.util.AttributeSet
 import android.view.LayoutInflater
 import android.view.ViewGroup
@@ -23,9 +24,17 @@
 import android.widget.FrameLayout
 import android.widget.TextView
 import androidx.core.view.isVisible
+import androidx.lifecycle.LiveData
+import androidx.slice.Slice
+import androidx.slice.widget.SliceLiveData
+import androidx.slice.widget.SliceView
 import com.android.wallpaper.R
 import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
+import com.android.wallpaper.model.WallpaperAction
 import com.android.wallpaper.util.SizeCalculator
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperActionSelectionBottomSheet
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperActionsToggleAdapter
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperActionsToggleAdapter.WallpaperEffectSwitchListener
 import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
@@ -41,6 +50,8 @@
     private val floatingSheetContainer: ViewGroup
     private val floatingSheetBehavior: BottomSheetBehavior<ViewGroup>
 
+    private var customizeLiveDataAndView: Pair<LiveData<Slice>, SliceView>? = null
+
     init {
         LayoutInflater.from(context).inflate(R.layout.floating_sheet2, this, true)
         floatingSheetView = requireViewById(R.id.floating_sheet_content)
@@ -50,7 +61,7 @@
         floatingSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
     }
 
-    fun setEffectContent(
+    fun setImageEffectContent(
         effect: EffectEnumInterface,
         myPhotosClickListener: OnClickListener,
         collapseFloatingSheetListener: OnClickListener,
@@ -81,9 +92,34 @@
         floatingSheetView.addView(view)
     }
 
+    fun setCreativeEffectContent(
+        title: String,
+        subtitle: String,
+        wallpaperActions: List<WallpaperAction>,
+        wallpaperEffectSwitchListener: WallpaperEffectSwitchListener,
+    ) {
+        val view =
+            LayoutInflater.from(context)
+                .inflate(R.layout.wallpaper_action_selection_bottom_sheet, this, false)
+                as WallpaperActionSelectionBottomSheet
+        view.setBottomSheetTitle(title)
+        view.setBottomSheetSubtitle(subtitle)
+        view.setUpActionToggleOptions(
+            WallpaperActionsToggleAdapter(
+                // TODO(b/270729418): enable multiple effect options once final design is
+                //  agreed upon.
+                // Forcing only one effect item for now
+                if (wallpaperActions.isNotEmpty()) wallpaperActions.subList(0, 1) else listOf(),
+                wallpaperEffectSwitchListener,
+            )
+        )
+        floatingSheetView.removeAllViews()
+        floatingSheetView.addView(view)
+    }
+
     fun setInformationContent(
         attributions: List<String?>?,
-        onExploreButtonClicked: (() -> Unit)?,
+        onExploreButtonClickListener: OnClickListener?,
     ) {
         val view = LayoutInflater.from(context).inflate(R.layout.wallpaper_info_view2, this, false)
         val title: TextView = view.requireViewById(R.id.wallpaper_info_title)
@@ -111,21 +147,36 @@
                     }
                 }
             }
-            if (onExploreButtonClicked != null) {
-                exploreButton.isVisible = true
-                exploreButton.setOnClickListener { onExploreButtonClicked.invoke() }
-            }
+
+            exploreButton.isVisible = onExploreButtonClickListener != null
+            exploreButton.setOnClickListener(onExploreButtonClickListener)
         }
         floatingSheetView.removeAllViews()
         floatingSheetView.addView(view)
     }
 
+    fun setCustomizeContent(uri: Uri) {
+        removeCustomizeLiveDataObserver()
+        val view =
+            LayoutInflater.from(context).inflate(R.layout.preview_customize_settings2, this, false)
+        val settingsSliceView: SliceView =
+            view.requireViewById<SliceView>(R.id.settings_slice).apply {
+                mode = SliceView.MODE_LARGE
+                isScrollable = false
+            }
+        customizeLiveDataAndView = SliceLiveData.fromUri(view.context, uri) to settingsSliceView
+        customizeLiveDataAndView?.let { (liveData, observer) -> liveData.observeForever(observer) }
+        floatingSheetView.removeAllViews()
+        floatingSheetView.addView(view)
+    }
+
     fun expand() {
         floatingSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
     }
 
     fun collapse() {
         floatingSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+        removeCustomizeLiveDataObserver()
     }
 
     /**
@@ -142,4 +193,9 @@
     fun removeFloatingSheetCallback(callback: BottomSheetCallback) {
         floatingSheetBehavior.removeBottomSheetCallback(callback)
     }
+
+    private fun removeCustomizeLiveDataObserver() {
+        customizeLiveDataAndView?.let { (liveData, observer) -> liveData.removeObserver(observer) }
+        customizeLiveDataAndView = null
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/view/SystemScaledWallpaperPreviewSurfaceView.kt b/src/com/android/wallpaper/picker/preview/ui/view/SystemScaledSubsamplingScaleImageView.kt
similarity index 82%
rename from src/com/android/wallpaper/picker/preview/ui/view/SystemScaledWallpaperPreviewSurfaceView.kt
rename to src/com/android/wallpaper/picker/preview/ui/view/SystemScaledSubsamplingScaleImageView.kt
index 78127da..d6874cc 100644
--- a/src/com/android/wallpaper/picker/preview/ui/view/SystemScaledWallpaperPreviewSurfaceView.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/view/SystemScaledSubsamplingScaleImageView.kt
@@ -17,15 +17,15 @@
 
 import android.content.Context
 import android.util.AttributeSet
-import android.view.SurfaceView
 import com.android.wallpaper.util.WallpaperCropUtils
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
 
 /**
- * A [SurfaceView] for wallpaper preview that scales and centers the surface to simulate the actual
- * wallpaper surface's default system zoom.
+ * A [SubsamplingScaleImageView] for wallpaper preview that scales and centers the surface to
+ * simulate the actual wallpaper surface's default system zoom.
  */
-class SystemScaledWallpaperPreviewSurfaceView(context: Context, attrs: AttributeSet? = null) :
-    SurfaceView(context, attrs) {
+class SystemScaledSubsamplingScaleImageView(context: Context, attrs: AttributeSet? = null) :
+    SubsamplingScaleImageView(context, attrs) {
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
 
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewConfigViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullPreviewConfigViewModel.kt
similarity index 73%
rename from src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewConfigViewModel.kt
rename to src/com/android/wallpaper/picker/preview/ui/viewmodel/FullPreviewConfigViewModel.kt
index 4e4707b..34a1656 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewConfigViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullPreviewConfigViewModel.kt
@@ -15,15 +15,15 @@
  */
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
-import android.graphics.Point
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.module.CustomizationSections.Screen
 
-/** Configuration for a wallpaper preview. */
-data class WallpaperPreviewConfigViewModel(
+/** Configuration for a full preview, used by both wallpaper and workspace. */
+data class FullPreviewConfigViewModel(
 
     /** The [Screen] the preview is rendering. */
     val screen: Screen,
 
-    /** The display size the preview is based on. */
-    val displaySize: Point,
+    /** Is it a folded or unfolded display. Null for handheld. */
+    val deviceDisplayType: DeviceDisplayType,
 )
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
index 57aba6a..90facf3 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
@@ -17,12 +17,12 @@
 
 import android.graphics.Bitmap
 import android.graphics.Point
+import com.android.wallpaper.asset.Asset
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
-import java.io.InputStream
 
 data class FullResWallpaperViewModel(
     val rawWallpaperBitmap: Bitmap,
     val rawWallpaperSize: Point,
-    val stream: InputStream?,
+    val asset: Asset,
     val fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
 )
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullWallpaperPreviewViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullWallpaperPreviewViewModel.kt
index 7ab1f36..7bd2991 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullWallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullWallpaperPreviewViewModel.kt
@@ -15,12 +15,20 @@
  */
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
+import android.graphics.Point
 import com.android.wallpaper.picker.data.WallpaperModel
 import com.android.wallpaper.util.WallpaperConnection.WhichPreview
 
+/** Information needed to bind a wallpaper in the full preview. */
 data class FullWallpaperPreviewViewModel(
+    /** The wallpaper model to preview. */
     val wallpaper: WallpaperModel,
-    val config: WallpaperPreviewConfigViewModel,
+    /** Configuration for a full preview. */
+    val config: FullPreviewConfigViewModel,
+    /** The display size the preview is based on. */
+    val displaySize: Point,
+    /** Whether to enable user cropping on the given wallpaper. */
     val allowUserCropping: Boolean,
+    /** Different possible scenarios for the preview. */
     val whichPreview: WhichPreview,
 )
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt
index 463182f..bba0e0d 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt
@@ -18,16 +18,22 @@
 
 import android.content.ClipData
 import android.content.ComponentName
+import android.content.Context
 import android.content.Intent
 import android.net.Uri
 import android.service.wallpaper.WallpaperSettingsActivity
+import com.android.wallpaper.effects.Effect
 import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
 import com.android.wallpaper.picker.data.CreativeWallpaperData
 import com.android.wallpaper.picker.data.DownloadableWallpaperData
 import com.android.wallpaper.picker.data.LiveWallpaperData
 import com.android.wallpaper.picker.data.WallpaperModel
 import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
-import com.android.wallpaper.picker.preview.data.repository.EffectsRepository
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_APPLIED
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_APPLY_IN_PROGRESS
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_DOWNLOAD_IN_PROGRESS
+import com.android.wallpaper.picker.preview.data.repository.ImageEffectsRepository.EffectStatus.EFFECT_DOWNLOAD_READY
 import com.android.wallpaper.picker.preview.domain.interactor.PreviewActionsInteractor
 import com.android.wallpaper.picker.preview.ui.util.LiveWallpaperDeleteUtil
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.CUSTOMIZE
@@ -36,16 +42,26 @@
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.EFFECTS
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.INFORMATION
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.SHARE
-import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.EffectFloatingSheetViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.CreativeEffectFloatingSheetViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.CustomizeFloatingSheetViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.ImageEffectFloatingSheetViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.InformationFloatingSheetViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.PreviewFloatingSheetViewModel
 import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.EffectDownloadClickListener
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.EffectSwitchListener
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.Status.DOWNLOADING
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.Status.IDLE
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.Status.PROCESSING
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.Status.SHOW_DOWNLOAD_BUTTON
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.Status.SUCCESS
+import dagger.hilt.android.qualifiers.ApplicationContext
 import dagger.hilt.android.scopes.ViewModelScoped
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 
 /** View model for the preview action buttons */
@@ -55,37 +71,30 @@
 constructor(
     private val interactor: PreviewActionsInteractor,
     liveWallpaperDeleteUtil: LiveWallpaperDeleteUtil,
+    @ApplicationContext private val context: Context,
 ) {
     /** [INFORMATION] */
-    private val _informationFloatingSheetViewModel: Flow<InformationFloatingSheetViewModel?> =
+    private val informationFloatingSheetViewModel: Flow<InformationFloatingSheetViewModel?> =
         interactor.wallpaperModel.map { wallpaperModel ->
             if (wallpaperModel == null || !wallpaperModel.shouldShowInformationFloatingSheet()) {
                 null
             } else {
                 InformationFloatingSheetViewModel(
                     wallpaperModel.commonWallpaperData.attributions,
-                    wallpaperModel.commonWallpaperData.exploreActionUrl,
+                    if (wallpaperModel.commonWallpaperData.exploreActionUrl.isNullOrEmpty()) {
+                        null
+                    } else {
+                        wallpaperModel.commonWallpaperData.exploreActionUrl
+                    }
                 )
             }
         }
 
-    val isInformationVisible: Flow<Boolean> = _informationFloatingSheetViewModel.map { it != null }
+    val isInformationVisible: Flow<Boolean> = informationFloatingSheetViewModel.map { it != null }
 
     private val _isInformationChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
     val isInformationChecked: Flow<Boolean> = _isInformationChecked.asStateFlow()
 
-    // Floating sheet contents for the bottom sheet dialog. If content is null, the bottom sheet
-    // should collapse, otherwise, expended.
-    val informationFloatingSheetViewModel: Flow<InformationFloatingSheetViewModel?> =
-        combine(isInformationChecked, _informationFloatingSheetViewModel) { checked, viewModel ->
-                if (checked && viewModel != null) {
-                    viewModel
-                } else {
-                    null
-                }
-            }
-            .distinctUntilChanged()
-
     val onInformationClicked: Flow<(() -> Unit)?> =
         combine(isInformationVisible, isInformationChecked) { show, isChecked ->
             if (show) {
@@ -180,8 +189,11 @@
 
     /** [EDIT] */
     val editIntent: Flow<Intent?> =
-        interactor.wallpaperModel.map {
-            (it as? WallpaperModel.LiveWallpaperModel)?.liveWallpaperData?.getEditActivityIntent()
+        interactor.wallpaperModel.map { model ->
+            (model as? LiveWallpaperModel)?.liveWallpaperData?.getEditActivityIntent(false)?.let {
+                intent ->
+                if (intent.resolveActivityInfo(context.packageManager, 0) != null) intent else null
+            }
         }
     val isEditVisible: Flow<Boolean> = editIntent.map { it != null }
 
@@ -189,8 +201,15 @@
     val isEditChecked: Flow<Boolean> = _isEditChecked.asStateFlow()
 
     /** [CUSTOMIZE] */
-    private val _isCustomizeVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isCustomizeVisible: Flow<Boolean> = _isCustomizeVisible.asStateFlow()
+    private val customizeFloatingSheetViewModel: Flow<CustomizeFloatingSheetViewModel?> =
+        interactor.wallpaperModel.map {
+            (it as? LiveWallpaperModel)
+                ?.liveWallpaperData
+                ?.systemWallpaperInfo
+                ?.settingsSliceUri
+                ?.let { CustomizeFloatingSheetViewModel(it) }
+        }
+    val isCustomizeVisible: Flow<Boolean> = customizeFloatingSheetViewModel.map { it != null }
 
     private val _isCustomizeChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
     val isCustomizeChecked: Flow<Boolean> = _isCustomizeChecked.asStateFlow()
@@ -210,41 +229,66 @@
         }
 
     /** [EFFECTS] */
-    private val _effectFloatingSheetViewModel: Flow<EffectFloatingSheetViewModel?> =
-        combine(interactor.wallpaperModel, interactor.effectsStatus, interactor.effect) {
-            wallpaper,
-            status,
-            effect ->
-            (wallpaper as? WallpaperModel.StaticWallpaperModel)?.imageWallpaperData?.uri
-                ?: return@combine null
-            effect ?: return@combine null
-            when (status) {
-                EffectsRepository.EffectStatus.EFFECT_DISABLE -> {
-                    null
-                }
-                else -> {
-                    getEffectFloatingSheetViewModel(status, effect.title, effect.type)
+    private val imageEffectFloatingSheetViewModel: Flow<ImageEffectFloatingSheetViewModel?> =
+        combine(interactor.imageEffectsStatus, interactor.imageEffect) {
+            imageEffectStatus,
+            imageEffect ->
+            imageEffect?.let {
+                when (imageEffectStatus) {
+                    ImageEffectsRepository.EffectStatus.EFFECT_DISABLE -> {
+                        null
+                    }
+                    else -> {
+                        getImageEffectFloatingSheetViewModel(
+                            imageEffectStatus,
+                            imageEffect,
+                        )
+                    }
                 }
             }
         }
 
-    private fun getEffectFloatingSheetViewModel(
-        status: EffectsRepository.EffectStatus,
-        title: String,
-        effectType: EffectEnumInterface,
-    ): EffectFloatingSheetViewModel {
+    private val creativeEffectFloatingSheetViewModel: Flow<CreativeEffectFloatingSheetViewModel?> =
+        interactor.creativeEffectsModel.map { creativeEffectsModel ->
+            creativeEffectsModel?.let {
+                CreativeEffectFloatingSheetViewModel(
+                    title = it.title,
+                    subtitle = it.subtitle,
+                    wallpaperActions = it.actions,
+                    wallpaperEffectSwitchListener = { interactor.turnOnCreativeEffect(it) },
+                )
+            }
+        }
+
+    private fun getImageEffectFloatingSheetViewModel(
+        status: ImageEffectsRepository.EffectStatus,
+        effect: Effect,
+    ): ImageEffectFloatingSheetViewModel {
         val floatingSheetViewStatus =
             when (status) {
-                EffectsRepository.EffectStatus.EFFECT_APPLY_IN_PROGRESS ->
-                    WallpaperEffectsView2.Status.PROCESSING
-                EffectsRepository.EffectStatus.EFFECT_APPLIED ->
-                    WallpaperEffectsView2.Status.SUCCESS
-                else -> WallpaperEffectsView2.Status.IDLE
+                EFFECT_APPLY_IN_PROGRESS -> {
+                    PROCESSING
+                }
+                EFFECT_APPLIED -> {
+                    SUCCESS
+                }
+                EFFECT_DOWNLOAD_READY -> {
+                    SHOW_DOWNLOAD_BUTTON
+                }
+                EFFECT_DOWNLOAD_IN_PROGRESS -> {
+                    DOWNLOADING
+                }
+                ImageEffectsRepository.EffectStatus.EFFECT_DOWNLOAD_FAILED -> {
+                    WallpaperEffectsView2.Status.FAILED
+                }
+                else -> {
+                    IDLE
+                }
             }
-        return EffectFloatingSheetViewModel(
+        return ImageEffectFloatingSheetViewModel(
             myPhotosClickListener = {},
             collapseFloatingSheetListener = {},
-            object : WallpaperEffectsView2.EffectSwitchListener {
+            object : EffectSwitchListener {
                 override fun onEffectSwitchChanged(
                     effect: EffectEnumInterface,
                     isChecked: Boolean
@@ -258,37 +302,30 @@
                     }
                 }
             },
-            object : WallpaperEffectsView2.EffectDownloadClickListener {
+            object : EffectDownloadClickListener {
                 override fun onEffectDownloadClick() {
-                    TODO("Not yet implemented")
+                    interactor.startEffectsMLDownload(effect)
                 }
             },
             floatingSheetViewStatus,
             resultCode = null,
             errorMessage = null,
-            title,
-            effectType,
+            effect.title,
+            effect.type,
             interactor.getEffectTextRes(),
         )
     }
 
-    val isEffectsVisible: Flow<Boolean> = _effectFloatingSheetViewModel.map { it != null }
+    val isEffectsVisible: Flow<Boolean> =
+        combine(imageEffectFloatingSheetViewModel, creativeEffectFloatingSheetViewModel) {
+            imageEffect,
+            creativeEffect ->
+            imageEffect != null || creativeEffect != null
+        }
 
     private val _isEffectsChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
     val isEffectsChecked: Flow<Boolean> = _isEffectsChecked.asStateFlow()
 
-    // Floating sheet contents for the bottom sheet dialog. If content is null, the bottom sheet
-    // should collapse, otherwise, expended.
-    val effectFloatingSheetViewModel: Flow<EffectFloatingSheetViewModel?> =
-        combine(isEffectsChecked, _effectFloatingSheetViewModel) { checked, viewModel ->
-                if (checked && viewModel != null) {
-                    viewModel
-                } else {
-                    null
-                }
-            }
-            .distinctUntilChanged()
-
     val onEffectsClicked: Flow<(() -> Unit)?> =
         combine(isEffectsVisible, isEffectsChecked) { show, isChecked ->
             if (show) {
@@ -310,6 +347,46 @@
         }
     val isShareVisible: Flow<Boolean> = shareIntent.map { it != null }
 
+    // Floating sheet contents for the bottom sheet dialog. If content is null, the bottom sheet
+    // should collapse, otherwise, expended.
+    val previewFloatingSheetViewModel: Flow<PreviewFloatingSheetViewModel?> =
+        combine7(
+            isInformationChecked,
+            isEffectsChecked,
+            isCustomizeChecked,
+            informationFloatingSheetViewModel,
+            imageEffectFloatingSheetViewModel,
+            creativeEffectFloatingSheetViewModel,
+            customizeFloatingSheetViewModel,
+        ) {
+            isInformationChecked,
+            isEffectsChecked,
+            isCustomizeChecked,
+            informationFloatingSheetViewModel,
+            imageEffectFloatingSheetViewModel,
+            creativeEffectFloatingSheetViewModel,
+            customizeFloatingSheetViewModel ->
+            if (isInformationChecked && informationFloatingSheetViewModel != null) {
+                PreviewFloatingSheetViewModel(
+                    informationFloatingSheetViewModel = informationFloatingSheetViewModel
+                )
+            } else if (isEffectsChecked && imageEffectFloatingSheetViewModel != null) {
+                PreviewFloatingSheetViewModel(
+                    imageEffectFloatingSheetViewModel = imageEffectFloatingSheetViewModel
+                )
+            } else if (isEffectsChecked && creativeEffectFloatingSheetViewModel != null) {
+                PreviewFloatingSheetViewModel(
+                    creativeEffectFloatingSheetViewModel = creativeEffectFloatingSheetViewModel
+                )
+            } else if (isCustomizeChecked && customizeFloatingSheetViewModel != null) {
+                PreviewFloatingSheetViewModel(
+                    customizeFloatingSheetViewModel = customizeFloatingSheetViewModel
+                )
+            } else {
+                null
+            }
+        }
+
     fun onFloatingSheetCollapsed() {
         // When floating collapsed, we should look for those actions that expand the floating sheet
         // and see which is checked, and uncheck it.
@@ -320,6 +397,10 @@
         if (_isEffectsChecked.value) {
             _isEffectsChecked.value = false
         }
+
+        if (_isCustomizeChecked.value) {
+            _isCustomizeChecked.value = false
+        }
     }
 
     private fun uncheckAllOthersExcept(action: Action) {
@@ -341,6 +422,8 @@
     }
 
     companion object {
+        const val EXTRA_KEY_IS_CREATE_NEW = "is_create_new"
+
         private fun WallpaperModel.shouldShowInformationFloatingSheet(): Boolean {
             if (
                 this is LiveWallpaperModel &&
@@ -377,7 +460,11 @@
             }
         }
 
-        fun LiveWallpaperData.getEditActivityIntent(): Intent? {
+        /**
+         * @param isCreateNew: True means creating a new creative wallpaper. False means editing an
+         *   existing wallpaper.
+         */
+        fun LiveWallpaperData.getEditActivityIntent(isCreateNew: Boolean): Intent? {
             val settingsActivity = systemWallpaperInfo.settingsActivity
             if (settingsActivity.isNullOrEmpty()) {
                 return null
@@ -386,6 +473,7 @@
                 Intent().apply {
                     component = ComponentName(systemWallpaperInfo.packageName, settingsActivity)
                     putExtra(WallpaperSettingsActivity.EXTRA_PREVIEW_MODE, true)
+                    putExtra(EXTRA_KEY_IS_CREATE_NEW, isCreateNew)
                 }
             return intent
         }
@@ -393,6 +481,31 @@
         fun LiveWallpaperModel.isNewCreativeWallpaper(): Boolean {
             return creativeWallpaperData?.deleteUri?.toString()?.isEmpty() == true
         }
+
+        /** The original combine function can only take up to 5 flows. */
+        inline fun <T1, T2, T3, T4, T5, T6, T7, R> combine7(
+            flow: Flow<T1>,
+            flow2: Flow<T2>,
+            flow3: Flow<T3>,
+            flow4: Flow<T4>,
+            flow5: Flow<T5>,
+            flow6: Flow<T6>,
+            flow7: Flow<T7>,
+            crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7) -> R
+        ): Flow<R> {
+            return combine(flow, flow2, flow3, flow4, flow5, flow6, flow7) { args: Array<*> ->
+                @Suppress("UNCHECKED_CAST")
+                transform(
+                    args[0] as T1,
+                    args[1] as T2,
+                    args[2] as T3,
+                    args[3] as T4,
+                    args[4] as T5,
+                    args[5] as T6,
+                    args[6] as T7,
+                )
+            }
+        }
     }
 }
 
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
index 15f33b2..e0d84e6 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
@@ -23,7 +23,6 @@
 import android.graphics.Point
 import android.graphics.Rect
 import com.android.wallpaper.asset.Asset
-import com.android.wallpaper.asset.StreamableAsset
 import com.android.wallpaper.module.WallpaperPreferences
 import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel
 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
@@ -34,7 +33,6 @@
 import dagger.hilt.android.qualifiers.ApplicationContext
 import dagger.hilt.android.scopes.ViewModelScoped
 import java.io.ByteArrayOutputStream
-import java.io.InputStream
 import javax.inject.Inject
 import kotlinx.coroutines.CancellableContinuation
 import kotlinx.coroutines.CoroutineDispatcher
@@ -91,8 +89,8 @@
             .map { it.staticWallpaperData.asset.getLowResBitmap(context) }
             .filterNotNull()
             .flowOn(bgDispatcher)
-    // Asset detail includes the dimensions, bitmap and input stream decoded from the asset.
-    private val assetDetail: Flow<Triple<Point, Bitmap?, InputStream?>?> =
+    // Asset detail includes the dimensions, bitmap and the asset.
+    private val assetDetail: Flow<Triple<Point, Bitmap?, Asset>?> =
         interactor.wallpaperModel
             .map { (it as? StaticWallpaperModel)?.staticWallpaperData?.asset }
             .map {
@@ -101,8 +99,7 @@
                 } else {
                     val dimensions = it.decodeRawDimensions()
                     val bitmap = it.decodeBitmap(dimensions)
-                    val stream = it.getStream()
-                    Triple(dimensions, bitmap, stream)
+                    Triple(dimensions, bitmap, it)
                 }
             }
             .flowOn(bgDispatcher)
@@ -115,9 +112,14 @@
                 if (assetDetail == null) {
                     null
                 } else {
-                    val (dimensions, bitmap, stream) = assetDetail
+                    val (dimensions, bitmap, asset) = assetDetail
                     bitmap?.let {
-                        FullResWallpaperViewModel(bitmap, dimensions, stream, cropHintsInfo)
+                        FullResWallpaperViewModel(
+                            bitmap,
+                            dimensions,
+                            asset,
+                            cropHintsInfo,
+                        )
                     }
                 }
             }
@@ -174,15 +176,6 @@
             decodeBitmap(dimensions.x, dimensions.y, /* hardwareBitmapAllowed= */ false, callback)
         }
 
-    private suspend fun Asset.getStream(): InputStream? =
-        suspendCancellableCoroutine { k: CancellableContinuation<InputStream?> ->
-            if (this is StreamableAsset) {
-                fetchInputStream { k.resumeWith(Result.success(it)) }
-            } else {
-                k.resumeWith(Result.success(null))
-            }
-        }
-
     // TODO b/296288298 Create a util class functions for Bitmap and Asset
     private fun Bitmap.extractColors(): WallpaperColors? {
         val tmpOut = ByteArrayOutputStream()
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
index 3cd5286..f4a4133 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
@@ -20,7 +20,7 @@
 import android.stats.style.StyleEnums
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
-import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.module.CustomizationSections
 import com.android.wallpaper.module.CustomizationSections.Screen
 import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel
@@ -30,9 +30,11 @@
 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.picker.di.modules.PreviewUtilsModule.HomeScreenPreviewUtils
 import com.android.wallpaper.picker.di.modules.PreviewUtilsModule.LockScreenPreviewUtils
+import com.android.wallpaper.picker.preview.domain.interactor.PreviewActionsInteractor
 import com.android.wallpaper.picker.preview.domain.interactor.WallpaperPreviewInteractor
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
 import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity
+import com.android.wallpaper.picker.preview.ui.binder.PreviewTooltipBinder
 import com.android.wallpaper.util.DisplayUtils
 import com.android.wallpaper.util.PreviewUtils
 import com.android.wallpaper.util.WallpaperConnection.WhichPreview
@@ -45,6 +47,7 @@
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.map
@@ -57,6 +60,7 @@
 @Inject
 constructor(
     private val interactor: WallpaperPreviewInteractor,
+    actionsInteractor: PreviewActionsInteractor,
     staticWallpaperPreviewViewModelFactory: StaticWallpaperPreviewViewModel.Factory,
     val previewActionsViewModel: PreviewActionsViewModel,
     private val displayUtils: DisplayUtils,
@@ -64,30 +68,63 @@
     @LockScreenPreviewUtils private val lockPreviewUtils: PreviewUtils,
 ) : ViewModel() {
 
+    // Don't update smaller display since we always use portrait, always use wallpaper display on
+    // single display device.
+    val smallerDisplaySize = displayUtils.getRealSize(displayUtils.getSmallerDisplay())
+    private val _wallpaperDisplaySize =
+        MutableStateFlow(displayUtils.getRealSize(displayUtils.getWallpaperDisplay()))
+    val wallpaperDisplaySize = _wallpaperDisplaySize.asStateFlow()
+
     val staticWallpaperPreviewViewModel =
         staticWallpaperPreviewViewModelFactory.create(viewModelScope)
-    val smallerDisplaySize = displayUtils.getRealSize(displayUtils.getSmallerDisplay())
-    val wallpaperDisplaySize = displayUtils.getRealSize(displayUtils.getWallpaperDisplay())
     var isViewAsHome = false
     var isNewTask = false
 
     val wallpaper: StateFlow<WallpaperModel?> = interactor.wallpaperModel
 
-    fun shouldShowTooltip(): Flow<Boolean> =
-        combine(interactor.wallpaperModel.filterNotNull(), interactor.hasTooltipBeenShown) {
-            wallpaper,
-            hasTooltipBeenShown ->
-            // Only show tooltip for non-downloadable static wallpapers. Hide tooltip for live
-            // wallpaper and downloadable wallpaper as their crop is not adjustable.
-            if (wallpaper is StaticWallpaperModel && !wallpaper.isDownloadableWallpaper()) {
-                // Only show tooltip if it has not been shown before.
-                !hasTooltipBeenShown
-            } else {
-                false
-            }
+    // Used to display loading indication on the preview.
+    val effectStatus = actionsInteractor.imageEffectsStatus
+
+    // This flag prevents launching the creative edit activity again when orientation change.
+    // On orientation change, the fragment's onCreateView will be called again.
+    var isCurrentlyEditingCreativeWallpaper = false
+
+    fun updateDisplayConfiguration() {
+        _wallpaperDisplaySize.value = displayUtils.getRealSize(displayUtils.getWallpaperDisplay())
+    }
+
+    private val isWallpaperCroppable: Flow<Boolean> =
+        wallpaper.map { wallpaper ->
+            wallpaper is StaticWallpaperModel && !wallpaper.isDownloadableWallpaper()
         }
 
-    fun dismissTooltip() = interactor.dismissTooltip()
+    val smallTooltipViewModel =
+        object : PreviewTooltipBinder.TooltipViewModel {
+            override val shouldShowTooltip: Flow<Boolean> =
+                combine(isWallpaperCroppable, interactor.hasSmallPreviewTooltipBeenShown) {
+                        isCroppable,
+                        hasTooltipBeenShown ->
+                        // Only show tooltip if it has not been shown before.
+                        isCroppable && !hasTooltipBeenShown
+                    }
+                    .distinctUntilChanged()
+
+            override fun dismissTooltip() = interactor.hideSmallPreviewTooltip()
+        }
+
+    val fullTooltipViewModel =
+        object : PreviewTooltipBinder.TooltipViewModel {
+            override val shouldShowTooltip: Flow<Boolean> =
+                combine(isWallpaperCroppable, interactor.hasFullPreviewTooltipBeenShown) {
+                        isCroppable,
+                        hasTooltipBeenShown ->
+                        // Only show tooltip if it has not been shown before.
+                        isCroppable && !hasTooltipBeenShown
+                    }
+                    .distinctUntilChanged()
+
+            override fun dismissTooltip() = interactor.hideFullPreviewTooltip()
+        }
 
     private val _whichPreview = MutableStateFlow<WhichPreview?>(null)
     private val whichPreview: Flow<WhichPreview> = _whichPreview.asStateFlow().filterNotNull()
@@ -129,10 +166,10 @@
     val wallpaperColorsModel: Flow<WallpaperColorsModel> =
         merge(liveWallpaperColors, staticWallpaperPreviewViewModel.wallpaperColors)
 
-    // This is only used for the full screen wallpaper preview.
-    private val fullWallpaperPreviewConfigViewModel:
-        MutableStateFlow<WallpaperPreviewConfigViewModel?> =
+    // This is only used for the full screen preview.
+    private val _fullPreviewConfigViewModel: MutableStateFlow<FullPreviewConfigViewModel?> =
         MutableStateFlow(null)
+    val fullPreviewConfigViewModel = _fullPreviewConfigViewModel.asStateFlow()
 
     // This is only used for the small screen wallpaper preview.
     val smallWallpaper: Flow<Pair<WallpaperModel, WhichPreview>> =
@@ -144,29 +181,38 @@
     val fullWallpaper: Flow<FullWallpaperPreviewViewModel> =
         combine(
             wallpaper.filterNotNull(),
-            fullWallpaperPreviewConfigViewModel.filterNotNull(),
+            fullPreviewConfigViewModel.filterNotNull(),
             whichPreview,
-        ) { wallpaper, config, whichPreview ->
+            wallpaperDisplaySize,
+        ) { wallpaper, config, whichPreview, wallpaperDisplaySize ->
+            val displaySize =
+                when (config.deviceDisplayType) {
+                    DeviceDisplayType.SINGLE -> wallpaperDisplaySize
+                    DeviceDisplayType.FOLDED -> smallerDisplaySize
+                    DeviceDisplayType.UNFOLDED -> wallpaperDisplaySize
+                }
             FullWallpaperPreviewViewModel(
                 wallpaper = wallpaper,
-                config = config,
+                config =
+                    FullPreviewConfigViewModel(
+                        config.screen,
+                        config.deviceDisplayType,
+                    ),
+                displaySize = displaySize,
                 allowUserCropping =
                     wallpaper is StaticWallpaperModel && !wallpaper.isDownloadableWallpaper(),
                 whichPreview = whichPreview,
             )
         }
 
-    // This is only used for the full screen wallpaper preview.
-    private val _fullWorkspacePreviewConfigViewModel:
-        MutableStateFlow<WorkspacePreviewConfigViewModel?> =
-        MutableStateFlow(null)
-
-    // This is only used for the full screen wallpaper preview.
+    // This is only used for the full screen workspace preview.
     val fullWorkspacePreviewConfigViewModel: Flow<WorkspacePreviewConfigViewModel> =
-        _fullWorkspacePreviewConfigViewModel.filterNotNull()
+        fullPreviewConfigViewModel.filterNotNull().map {
+            getWorkspacePreviewConfig(it.screen, it.deviceDisplayType)
+        }
 
     val onCropButtonClick: Flow<(() -> Unit)?> =
-        combine(wallpaper, fullWallpaperPreviewConfigViewModel.filterNotNull()) { wallpaper, _ ->
+        combine(wallpaper, fullPreviewConfigViewModel.filterNotNull()) { wallpaper, _ ->
             if (wallpaper is StaticWallpaperModel && !wallpaper.isDownloadableWallpaper()) {
                 {
                     staticWallpaperPreviewViewModel.run {
@@ -235,10 +281,15 @@
                                     StyleEnums.SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                                 destination = destination,
                                 wallpaperModel = wallpaper,
-                                inputStream = it.stream,
                                 bitmap = it.rawWallpaperBitmap,
                                 wallpaperSize = it.rawWallpaperSize,
-                                fullPreviewCropModels = it.fullPreviewCropModels,
+                                asset = it.asset,
+                                fullPreviewCropModels =
+                                    if (it.fullPreviewCropModels.isNullOrEmpty()) {
+                                        staticWallpaperPreviewViewModel.fullPreviewCropModels
+                                    } else {
+                                        it.fullPreviewCropModels
+                                    },
                             )
                         }
                     is LiveWallpaperModel -> {
@@ -275,7 +326,7 @@
 
     fun getWorkspacePreviewConfig(
         screen: Screen,
-        foldableDisplay: FoldableDisplay?,
+        deviceDisplayType: DeviceDisplayType,
     ): WorkspacePreviewConfigViewModel {
         val previewUtils =
             when (screen) {
@@ -286,67 +337,50 @@
                     lockPreviewUtils
                 }
             }
-        val displayId =
-            when (foldableDisplay) {
-                FoldableDisplay.FOLDED -> {
-                    displayUtils.getSmallerDisplay().displayId
-                }
-                FoldableDisplay.UNFOLDED -> {
-                    displayUtils.getWallpaperDisplay().displayId
-                }
-                null -> {
-                    displayUtils.getWallpaperDisplay().displayId
-                }
-            }
+        // Do not directly store display Id in the view model because display Id can change on fold
+        // and unfold whereas view models persist. Store FoldableDisplay instead and convert in the
+        // binder.
         return WorkspacePreviewConfigViewModel(
             previewUtils = previewUtils,
-            displayId = displayId,
+            deviceDisplayType = deviceDisplayType,
         )
     }
 
+    fun getDisplayId(deviceDisplayType: DeviceDisplayType): Int {
+        return when (deviceDisplayType) {
+            DeviceDisplayType.SINGLE -> {
+                displayUtils.getWallpaperDisplay().displayId
+            }
+            DeviceDisplayType.FOLDED -> {
+                displayUtils.getSmallerDisplay().displayId
+            }
+            DeviceDisplayType.UNFOLDED -> {
+                displayUtils.getWallpaperDisplay().displayId
+            }
+        }
+    }
+
     fun onSmallPreviewClicked(
         screen: Screen,
-        foldableDisplay: FoldableDisplay?,
+        deviceDisplayType: DeviceDisplayType,
     ) {
-        fullWallpaperPreviewConfigViewModel.value =
-            getWallpaperPreviewConfig(screen, foldableDisplay)
-        _fullWorkspacePreviewConfigViewModel.value =
-            getWorkspacePreviewConfig(screen, foldableDisplay)
+        smallTooltipViewModel.dismissTooltip()
+        _fullPreviewConfigViewModel.value = FullPreviewConfigViewModel(screen, deviceDisplayType)
     }
 
-    fun setDefaultWallpaperPreviewConfigViewModel(displaySize: Point) {
-        fullWallpaperPreviewConfigViewModel.value =
-            WallpaperPreviewConfigViewModel(
+    fun setDefaultFullPreviewConfigViewModel(
+        deviceDisplayType: DeviceDisplayType,
+    ) {
+        _fullPreviewConfigViewModel.value =
+            FullPreviewConfigViewModel(
                 Screen.HOME_SCREEN,
-                displaySize,
+                deviceDisplayType,
             )
     }
 
-    private fun getWallpaperPreviewConfig(
-        screen: Screen,
-        foldableDisplay: FoldableDisplay?,
-    ): WallpaperPreviewConfigViewModel {
-        val displaySize =
-            when (foldableDisplay) {
-                FoldableDisplay.FOLDED -> {
-                    smallerDisplaySize
-                }
-                FoldableDisplay.UNFOLDED -> {
-                    wallpaperDisplaySize
-                }
-                null -> {
-                    wallpaperDisplaySize
-                }
-            }
-        return WallpaperPreviewConfigViewModel(
-            screen = screen,
-            displaySize = displaySize,
-        )
-    }
-
     companion object {
         private fun WallpaperModel.isDownloadableWallpaper(): Boolean {
-            return this is StaticWallpaperModel && this.downloadableWallpaperData != null
+            return this is StaticWallpaperModel && downloadableWallpaperData != null
         }
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WorkspacePreviewConfigViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WorkspacePreviewConfigViewModel.kt
index 35f5111..01abe30 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WorkspacePreviewConfigViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WorkspacePreviewConfigViewModel.kt
@@ -15,6 +15,7 @@
  */
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.util.PreviewUtils
 
 /** Defines configuration associated with a single workspace preview. */
@@ -23,6 +24,6 @@
     /** The preview utils for rendering the workspace preview, different for Home & Lock screens. */
     val previewUtils: PreviewUtils,
 
-    /** The ID of the display to be rendered. */
-    val displayId: Int,
+    /** The foldable display to be rendered, or null if the device is not a foldable. */
+    val deviceDisplayType: DeviceDisplayType,
 )
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/CreativeEffectFloatingSheetViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/CreativeEffectFloatingSheetViewModel.kt
new file mode 100644
index 0000000..0e7f551
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/CreativeEffectFloatingSheetViewModel.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.picker.preview.ui.viewmodel.floatingSheet
+
+import com.android.wallpaper.model.WallpaperAction
+
+/** This data class represents the view data for the creative wallpaper effect floating sheet */
+data class CreativeEffectFloatingSheetViewModel(
+    val title: String,
+    val subtitle: String,
+    val wallpaperActions: List<WallpaperAction>,
+    val wallpaperEffectSwitchListener: suspend (checkedItem: Int) -> Unit,
+)
diff --git a/src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/CustomizeFloatingSheetViewModel.kt
similarity index 70%
copy from src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt
copy to src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/CustomizeFloatingSheetViewModel.kt
index 4001f83..1a07603 100644
--- a/src/com/android/wallpaper/model/wallpaper/FoldableDisplay.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/CustomizeFloatingSheetViewModel.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -13,9 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.wallpaper.model.wallpaper
 
-enum class FoldableDisplay {
-    FOLDED,
-    UNFOLDED,
-}
+package com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet
+
+import android.net.Uri
+
+data class CustomizeFloatingSheetViewModel(
+    val customizeSliceUri: Uri,
+)
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/EffectFloatingSheetViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/ImageEffectFloatingSheetViewModel.kt
similarity index 90%
rename from src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/EffectFloatingSheetViewModel.kt
rename to src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/ImageEffectFloatingSheetViewModel.kt
index 3ff26d2..b4ad10b 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/EffectFloatingSheetViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/ImageEffectFloatingSheetViewModel.kt
@@ -20,8 +20,8 @@
 import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
 import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
 
-/** This data class represents the view data for the effect floating sheet */
-data class EffectFloatingSheetViewModel(
+/** This data class represents the view data for the image wallpaper effect floating sheet */
+data class ImageEffectFloatingSheetViewModel(
     val myPhotosClickListener: View.OnClickListener,
     val collapseFloatingSheetListener: View.OnClickListener,
     val effectSwitchListener: WallpaperEffectsView2.EffectSwitchListener,
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/PreviewFloatingSheetViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/PreviewFloatingSheetViewModel.kt
new file mode 100644
index 0000000..a2a6bc7
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/PreviewFloatingSheetViewModel.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.picker.preview.ui.viewmodel.floatingSheet
+
+/**
+ * Represents the floating sheet view model. Note that we expect that when
+ * PreviewFloatingSheetViewModel is present, only one of the field is nonnull, while others should
+ * be null.
+ */
+data class PreviewFloatingSheetViewModel(
+    val informationFloatingSheetViewModel: InformationFloatingSheetViewModel? = null,
+    val imageEffectFloatingSheetViewModel: ImageEffectFloatingSheetViewModel? = null,
+    val creativeEffectFloatingSheetViewModel: CreativeEffectFloatingSheetViewModel? = null,
+    val customizeFloatingSheetViewModel: CustomizeFloatingSheetViewModel? = null,
+)
diff --git a/src/com/android/wallpaper/system/UiModeManagerImpl.kt b/src/com/android/wallpaper/system/UiModeManagerImpl.kt
new file mode 100644
index 0000000..4fe55f0
--- /dev/null
+++ b/src/com/android/wallpaper/system/UiModeManagerImpl.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.system
+
+import android.app.UiModeManager
+import android.content.Context
+import dagger.hilt.android.qualifiers.ApplicationContext
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class UiModeManagerImpl @Inject constructor(@ApplicationContext context: Context) :
+    UiModeManagerWrapper {
+    val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager?
+    override fun addContrastChangeListener(
+        executor: Executor,
+        listener: UiModeManager.ContrastChangeListener,
+    ) {
+        uiModeManager?.addContrastChangeListener(executor, listener)
+    }
+
+    override fun removeContrastChangeListener(listener: UiModeManager.ContrastChangeListener) {
+        uiModeManager?.removeContrastChangeListener(listener)
+    }
+
+    override fun getContrast(): Float? {
+        return uiModeManager?.contrast
+    }
+
+    override fun setNightModeActivated(isActive: Boolean) {
+        uiModeManager?.setNightModeActivated(isActive)
+    }
+}
diff --git a/src/com/android/wallpaper/system/UiModeManagerWrapper.kt b/src/com/android/wallpaper/system/UiModeManagerWrapper.kt
new file mode 100644
index 0000000..8dd419c
--- /dev/null
+++ b/src/com/android/wallpaper/system/UiModeManagerWrapper.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.system
+
+import android.app.UiModeManager.ContrastChangeListener
+import java.util.concurrent.Executor
+
+interface UiModeManagerWrapper {
+
+    fun addContrastChangeListener(executor: Executor, listener: ContrastChangeListener)
+
+    fun removeContrastChangeListener(listener: ContrastChangeListener)
+
+    fun getContrast(): Float?
+
+    fun setNightModeActivated(isActive: Boolean)
+}
diff --git a/src/com/android/wallpaper/util/DisplayUtils.kt b/src/com/android/wallpaper/util/DisplayUtils.kt
index fa1d879..35979a4 100644
--- a/src/com/android/wallpaper/util/DisplayUtils.kt
+++ b/src/com/android/wallpaper/util/DisplayUtils.kt
@@ -25,6 +25,7 @@
 import android.view.Surface.ROTATION_270
 import android.view.Surface.ROTATION_90
 import com.android.systemui.shared.recents.utilities.Utilities
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import kotlin.math.min
 
 /**
@@ -153,6 +154,17 @@
         return smallestDisplay ?: largestDisplay
     }
 
+    fun getCurrentDisplayType(activity: Activity): DeviceDisplayType {
+        if (!hasMultiInternalDisplays()) {
+            return DeviceDisplayType.SINGLE
+        }
+        return if (isOnWallpaperDisplay(activity)) {
+            DeviceDisplayType.UNFOLDED
+        } else {
+            DeviceDisplayType.FOLDED
+        }
+    }
+
     private fun getRealArea(display: Display): Int {
         val displayInfo = DisplayInfo()
         display.getDisplayInfo(displayInfo)
@@ -169,7 +181,17 @@
         return allDisplays.filter { it.type == Display.TYPE_INTERNAL }
     }
 
-    fun getInternalDisplaySizes(): List<Point> {
-        return getInternalDisplays().map { getRealSize(it) }
+    fun getInternalDisplaySizes(
+        allDimensions: Boolean = false,
+    ): List<Point> {
+        return getInternalDisplays()
+            .map { getRealSize(it) }
+            .let {
+                if (allDimensions) {
+                    it + it.map { size -> Point(size.y, size.x) }
+                } else {
+                    it
+                }
+            }
     }
 }
diff --git a/src/com/android/wallpaper/util/PreviewUtils.kt b/src/com/android/wallpaper/util/PreviewUtils.kt
index cf1a1e5..8754c2c 100644
--- a/src/com/android/wallpaper/util/PreviewUtils.kt
+++ b/src/com/android/wallpaper/util/PreviewUtils.kt
@@ -24,6 +24,7 @@
 import android.os.Bundle
 import android.os.Handler
 import android.os.Looper
+import android.os.Message
 import android.text.TextUtils
 import java.util.concurrent.Executors
 
@@ -95,6 +96,12 @@
         }
     }
 
+    /** Cleans up the preview on the renderer side */
+    fun cleanUp(workspaceCallback: Message?) {
+        // Send any message to clean up the corresponding preview on the renderer side.
+        workspaceCallback?.replyTo?.send(workspaceCallback)
+    }
+
     /** Easy way to generate a Uri with the provider info from this class. */
     fun getUri(path: String?): Uri {
         return Uri.Builder()
diff --git a/src/com/android/wallpaper/util/WallpaperCropUtils.java b/src/com/android/wallpaper/util/WallpaperCropUtils.java
index 2fcc2fd..4e770b4 100755
--- a/src/com/android/wallpaper/util/WallpaperCropUtils.java
+++ b/src/com/android/wallpaper/util/WallpaperCropUtils.java
@@ -195,8 +195,7 @@
             Point defaultCropSurfaceSize, Point targetHostSize, int scrollX, int scrollY,
             boolean cropExtraWidth) {
         BaseFlags flags = InjectorProvider.getInjector().getFlags();
-        boolean isMultiCropEnabled =
-                flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled();
+        boolean isMultiCropEnabled = flags.isMultiCropEnabled();
         // Calculate Rect of wallpaper in physical pixel terms (i.e., scaled to current zoom).
         int scaledWallpaperWidth = Math.round(wallpaperSize.x * wallpaperZoom);
         int scaledWallpaperHeight = Math.round(wallpaperSize.y * wallpaperZoom);
diff --git a/src/com/android/wallpaper/util/WallpaperXMLParser.kt b/src/com/android/wallpaper/util/WallpaperXMLParser.kt
new file mode 100644
index 0000000..271992a
--- /dev/null
+++ b/src/com/android/wallpaper/util/WallpaperXMLParser.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.util
+
+import android.content.Context
+import android.content.res.XmlResourceParser
+import android.util.Xml
+import com.android.wallpaper.model.LiveWallpaperInfo
+import com.android.wallpaper.model.SystemStaticWallpaperInfo
+import com.android.wallpaper.model.WallpaperCategory
+import com.android.wallpaper.model.WallpaperInfo
+import com.android.wallpaper.module.PartnerProvider
+import javax.inject.Inject
+import javax.inject.Singleton
+import org.xmlpull.v1.XmlPullParser
+
+/**
+ * Utility class for parsing an XML file containing information about a list of wallpapers. The
+ * logic in this class has been extracted into a separate class which uses dependency injection and
+ * was earlier present in a single method.
+ */
+@Singleton
+class WallpaperXMLParser
+@Inject
+constructor(private val context: Context, private val partnerProvider: PartnerProvider) {
+
+    fun parseCategory(parser: XmlResourceParser): WallpaperCategory? {
+        val categoryBuilder =
+            WallpaperCategory.Builder(partnerProvider.resources, Xml.asAttributeSet(parser))
+        categoryBuilder.setPriorityIfEmpty(PRIORITY_SYSTEM)
+        var publishedPlaceholder = false
+        val pair = parseXML(parser, parser.depth, categoryBuilder, false)
+        publishedPlaceholder = pair.first
+        val category = categoryBuilder.build()
+        return if (category.unmodifiableWallpapers.isNotEmpty()) category else null
+    }
+
+    private fun parseXML(
+        parser: XmlResourceParser,
+        categoryDepth: Int,
+        categoryBuilder: WallpaperCategory.Builder,
+        publishedPlaceholder: Boolean
+    ): Pair<Boolean, Int> {
+        var type1 = parser.eventType
+        var publishedPlaceholder1 = publishedPlaceholder
+        while (
+            parser.next().also { type1 = it } != XmlPullParser.END_TAG ||
+                parser.depth > categoryDepth
+        ) {
+            if (type1 == XmlPullParser.START_TAG) {
+                var wallpaper: WallpaperInfo? = null
+                if (SystemStaticWallpaperInfo.TAG_NAME == parser.name) {
+                    wallpaper =
+                        SystemStaticWallpaperInfo.fromAttributeSet(
+                            partnerProvider.packageName,
+                            categoryBuilder.id,
+                            Xml.asAttributeSet(parser)
+                        )
+                } else if (LiveWallpaperInfo.TAG_NAME == parser.name) {
+                    wallpaper =
+                        LiveWallpaperInfo.fromAttributeSet(
+                            context,
+                            categoryBuilder.id,
+                            Xml.asAttributeSet(parser)
+                        )
+                }
+                if (wallpaper != null) {
+                    categoryBuilder.addWallpaper(wallpaper)
+                    if (!publishedPlaceholder1) {
+                        publishedPlaceholder1 = true
+                    }
+                }
+            }
+        }
+        return Pair(publishedPlaceholder1, type1)
+    }
+
+    companion object {
+        private const val PRIORITY_SYSTEM = 100
+    }
+}
diff --git a/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt b/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
index 7bd24e2..63a0113 100644
--- a/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
+++ b/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
@@ -20,6 +20,7 @@
 import android.content.ComponentName
 import android.content.Context
 import android.util.Log
+import com.android.wallpaper.effects.EffectsController
 import com.android.wallpaper.model.CreativeWallpaperInfo
 import com.android.wallpaper.model.CurrentWallpaperInfo
 import com.android.wallpaper.model.ImageWallpaperInfo
@@ -28,6 +29,7 @@
 import com.android.wallpaper.picker.data.ColorInfo
 import com.android.wallpaper.picker.data.CommonWallpaperData
 import com.android.wallpaper.picker.data.CreativeWallpaperData
+import com.android.wallpaper.picker.data.CreativeWallpaperEffectsData
 import com.android.wallpaper.picker.data.Destination
 import com.android.wallpaper.picker.data.ImageWallpaperData
 import com.android.wallpaper.picker.data.LiveWallpaperData
@@ -100,7 +102,10 @@
             )
         }
 
-        fun LiveWallpaperInfo.getLiveWallpaperData(context: Context): LiveWallpaperData {
+        fun LiveWallpaperInfo.getLiveWallpaperData(
+            context: Context,
+            effectsController: EffectsController? = null
+        ): LiveWallpaperData {
             val groupNameOfWallpaper = (this as? CreativeWallpaperInfo)?.groupName ?: ""
             val wallpaperManager = WallpaperManager.getInstance(context)
             val currentHomeWallpaper =
@@ -111,6 +116,10 @@
                 systemWallpaperInfo = info,
                 isTitleVisible = isVisibleTitle,
                 isApplied = isApplied(currentHomeWallpaper, currentLockWallpaper),
+                // TODO (331227828): don't relay on effectNames to determine if this is an effect
+                // live wallpaper
+                isEffectWallpaper = effectsController?.isEffectsWallpaper(info)
+                        ?: (effectNames != null),
                 effectNames = effectNames,
             )
         }
@@ -126,6 +135,25 @@
                 description = description ?: "",
                 contentDescription = contentDescription,
                 isCurrent = isCurrent,
+                creativeWallpaperEffectsData = getCreativeWallpaperEffectData(),
+            )
+        }
+
+        private fun CreativeWallpaperInfo.getCreativeWallpaperEffectData():
+            CreativeWallpaperEffectsData? {
+            val effectsBottomSheetTitle =
+                effectsBottomSheetTitle.takeUnless { it.isNullOrEmpty() } ?: return null
+            val effectsBottomSheetSubtitle =
+                effectsBottomSheetSubtitle.takeUnless { it.isNullOrEmpty() } ?: return null
+            val clearActionsUri =
+                clearActionsUri.takeUnless { it?.scheme.isNullOrEmpty() } ?: return null
+            val effectsUri = effectsUri.takeUnless { it?.scheme.isNullOrEmpty() } ?: return null
+            return CreativeWallpaperEffectsData(
+                effectsBottomSheetTitle = effectsBottomSheetTitle,
+                effectsBottomSheetSubtitle = effectsBottomSheetSubtitle,
+                currentEffectId = currentlyAppliedEffectId ?: "",
+                clearActionUri = clearActionsUri,
+                effectsUri = effectsUri,
             )
         }
 
diff --git a/src/com/android/wallpaper/util/converter/category/CategoryFactory.kt b/src/com/android/wallpaper/util/converter/category/CategoryFactory.kt
index 9c55656..72edccb 100644
--- a/src/com/android/wallpaper/util/converter/category/CategoryFactory.kt
+++ b/src/com/android/wallpaper/util/converter/category/CategoryFactory.kt
@@ -57,11 +57,13 @@
 
     private fun WallpaperCategory.getCollectionsCategoryData(
         context: Context
-    ): CollectionCategoryData? {
+    ): CollectionCategoryData {
         val wallpaperModelList =
-            wallpapers.map { wallpaperInfo ->
-                wallpaperModelFactory.getWallpaperModel(context, wallpaperInfo)
-            }
+            wallpapers
+                .map { wallpaperInfo ->
+                    wallpaperModelFactory.getWallpaperModel(context, wallpaperInfo)
+                }
+                .toMutableList()
         return CollectionCategoryData(
             wallpaperModels = wallpaperModelList,
             thumbAsset = thumbAsset,
diff --git a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
index fc344cb..0ac6014 100644
--- a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
+++ b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
@@ -1,31 +1,32 @@
 package com.android.wallpaper.util.wallpaperconnection
 
 import android.app.WallpaperInfo
+import android.app.WallpaperManager
 import android.content.ContentValues
 import android.content.Context
 import android.content.Intent
 import android.content.ServiceConnection
 import android.graphics.Matrix
 import android.graphics.Point
+import android.net.Uri
 import android.os.RemoteException
 import android.service.wallpaper.IWallpaperEngine
 import android.service.wallpaper.IWallpaperService
 import android.service.wallpaper.WallpaperService
 import android.util.Log
-import android.view.Display
+import android.view.MotionEvent
 import android.view.SurfaceControl
 import android.view.SurfaceView
-import android.view.View
+import com.android.app.tracing.TraceUtils.traceAsync
+import com.android.wallpaper.model.wallpaper.DeviceDisplayType
 import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
-import com.android.wallpaper.picker.di.modules.MainDispatcher
-import com.android.wallpaper.util.ScreenSizeCalculator
 import com.android.wallpaper.util.WallpaperConnection
 import com.android.wallpaper.util.WallpaperConnection.WhichPreview
 import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils.getKey
 import kotlinx.coroutines.CancellableContinuation
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Deferred
 import kotlinx.coroutines.async
+import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
@@ -40,80 +41,108 @@
     // Note that when one wallpaper engine's render is mirrored to a new surface view, we call
     // engine.mirrorSurfaceControl() and will have a new surface control instance.
     private val surfaceControlMap = mutableMapOf<String, MutableList<SurfaceControl>>()
+    // Track the currently used creative wallpaper config preview URI to avoid unnecessary multiple
+    // update queries for the same preview.
+    private val creativeWallpaperConfigPreviewUriMap = mutableMapOf<String, Uri>()
 
     private val mutex = Mutex()
 
     /** Only call this function when the surface view is attached. */
     suspend fun connect(
         context: Context,
-        @MainDispatcher mainScope: CoroutineScope,
         wallpaperModel: LiveWallpaperModel,
         whichPreview: WhichPreview,
         destinationFlag: Int,
         surfaceView: SurfaceView,
+        engineRenderingConfig: EngineRenderingConfig,
         listener: WallpaperEngineConnection.WallpaperEngineConnectionListener? = null,
     ) {
         val wallpaperInfo = wallpaperModel.liveWallpaperData.systemWallpaperInfo
-        val engineKey = wallpaperInfo.getKey()
-        val displayMetrics = getDisplayMetrics(surfaceView)
+        val engineDisplaySize = engineRenderingConfig.getEngineDisplaySize()
+        val engineKey = wallpaperInfo.getKey(engineDisplaySize)
 
-        // Update the creative wallpaper uri before starting the service.
-        wallpaperModel.creativeWallpaperData?.configPreviewUri?.let {
-            context.contentResolver.update(it, ContentValues(), null)
-        }
-
-        if (!engineMap.containsKey(engineKey)) {
-            mutex.withLock {
-                if (!engineMap.containsKey(engineKey)) {
-                    engineMap[engineKey] =
-                        mainScope.async {
-                            initEngine(
-                                context,
-                                wallpaperModel.getWallpaperServiceIntent(),
-                                displayMetrics,
-                                destinationFlag,
-                                whichPreview,
-                                surfaceView,
-                                listener,
-                            )
+        traceAsync(TAG, "connect") {
+            // Update the creative wallpaper uri before starting the service.
+            wallpaperModel.creativeWallpaperData?.configPreviewUri?.let {
+                val uriKey = wallpaperInfo.getKey()
+                if (!creativeWallpaperConfigPreviewUriMap.containsKey(uriKey)) {
+                    mutex.withLock {
+                        if (!creativeWallpaperConfigPreviewUriMap.containsKey(uriKey)) {
+                            context.contentResolver.update(it, ContentValues(), null)
+                            creativeWallpaperConfigPreviewUriMap[uriKey] = it
                         }
+                    }
                 }
             }
-        }
 
-        engineMap[engineKey]?.await()?.let { (_, engineConnection) ->
-            engineConnection.engine?.let {
-                mirrorAndReparent(engineKey, it, surfaceView, displayMetrics)
+            if (!engineMap.containsKey(engineKey)) {
+                mutex.withLock {
+                    if (!engineMap.containsKey(engineKey)) {
+                        engineMap[engineKey] = coroutineScope {
+                            async {
+                                initEngine(
+                                    context,
+                                    wallpaperModel.getWallpaperServiceIntent(),
+                                    engineDisplaySize,
+                                    destinationFlag,
+                                    whichPreview,
+                                    surfaceView,
+                                    listener,
+                                )
+                            }
+                        }
+                    }
+                }
             }
-        }
-    }
 
-    private fun LiveWallpaperModel.getWallpaperServiceIntent(): Intent {
-        return liveWallpaperData.systemWallpaperInfo.let {
-            Intent(WallpaperService.SERVICE_INTERFACE).setClassName(it.packageName, it.serviceName)
+            engineMap[engineKey]?.await()?.let { (_, engineConnection) ->
+                engineConnection.engine?.let {
+                    mirrorAndReparent(
+                        engineKey,
+                        it,
+                        surfaceView,
+                        engineRenderingConfig.getEngineDisplaySize(),
+                        engineRenderingConfig.enforceSingleEngine,
+                    )
+                }
+            }
         }
     }
 
     suspend fun disconnect(
         context: Context,
         wallpaperModel: LiveWallpaperModel,
+        displaySize: Point,
     ) {
-        val engineKey = wallpaperModel.liveWallpaperData.systemWallpaperInfo.getKey()
-        if (engineMap.containsKey(engineKey)) {
-            mutex.withLock {
-                engineMap.remove(engineKey)?.await()?.let { (serviceConnection, engineConnection) ->
-                    engineConnection.engine?.destroy()
-                    engineConnection.removeListener()
-                    context.unbindService(serviceConnection)
+        val engineKey = wallpaperModel.liveWallpaperData.systemWallpaperInfo.getKey(displaySize)
+
+        traceAsync(TAG, "disconnect") {
+            if (engineMap.containsKey(engineKey)) {
+                mutex.withLock {
+                    engineMap.remove(engineKey)?.await()?.let {
+                        (serviceConnection, engineConnection) ->
+                        engineConnection.engine?.destroy()
+                        engineConnection.removeListener()
+                        context.unbindService(serviceConnection)
+                    }
                 }
             }
-        }
 
-        if (surfaceControlMap.containsKey(engineKey)) {
-            mutex.withLock {
-                surfaceControlMap.remove(engineKey)?.let { surfaceControls ->
-                    surfaceControls.forEach { it.release() }
-                    surfaceControls.clear()
+            if (surfaceControlMap.containsKey(engineKey)) {
+                mutex.withLock {
+                    surfaceControlMap.remove(engineKey)?.let { surfaceControls ->
+                        surfaceControls.forEach { it.release() }
+                        surfaceControls.clear()
+                    }
+                }
+            }
+
+            val uriKey = wallpaperModel.liveWallpaperData.systemWallpaperInfo.getKey()
+            if (creativeWallpaperConfigPreviewUriMap.containsKey(uriKey)) {
+                mutex.withLock {
+                    if (creativeWallpaperConfigPreviewUriMap.containsKey(uriKey)) {
+                        creativeWallpaperConfigPreviewUriMap.remove(uriKey)
+                    }
                 }
             }
         }
@@ -137,6 +166,53 @@
                 }
             }
         }
+
+        creativeWallpaperConfigPreviewUriMap.clear()
+    }
+
+    suspend fun dispatchTouchEvent(
+        wallpaperModel: LiveWallpaperModel,
+        engineRenderingConfig: EngineRenderingConfig,
+        event: MotionEvent,
+    ) {
+        val engine =
+            wallpaperModel.liveWallpaperData.systemWallpaperInfo
+                .getKey(engineRenderingConfig.getEngineDisplaySize())
+                .let { engineKey -> engineMap[engineKey]?.await()?.second?.engine }
+
+        if (engine != null) {
+            val action: Int = event.actionMasked
+            val dup = MotionEvent.obtainNoHistory(event).also { it.setLocation(event.x, event.y) }
+            val pointerIndex = event.actionIndex
+            try {
+                engine.dispatchPointer(dup)
+                if (action == MotionEvent.ACTION_UP) {
+                    engine.dispatchWallpaperCommand(
+                        WallpaperManager.COMMAND_TAP,
+                        event.x.toInt(),
+                        event.y.toInt(),
+                        0,
+                        null
+                    )
+                } else if (action == MotionEvent.ACTION_POINTER_UP) {
+                    engine.dispatchWallpaperCommand(
+                        WallpaperManager.COMMAND_SECONDARY_TAP,
+                        event.getX(pointerIndex).toInt(),
+                        event.getY(pointerIndex).toInt(),
+                        0,
+                        null
+                    )
+                }
+            } catch (e: RemoteException) {
+                Log.e(TAG, "Remote exception of wallpaper connection", e)
+            }
+        }
+    }
+
+    private fun LiveWallpaperModel.getWallpaperServiceIntent(): Intent {
+        return liveWallpaperData.systemWallpaperInfo.let {
+            Intent(WallpaperService.SERVICE_INTERFACE).setClassName(it.packageName, it.serviceName)
+        }
     }
 
     private suspend fun initEngine(
@@ -157,8 +233,13 @@
         return Pair(serviceConnection, engineConnection)
     }
 
-    private fun WallpaperInfo.getKey(): String {
-        return this.packageName.plus(":").plus(this.serviceName)
+    private fun WallpaperInfo.getKey(displaySize: Point? = null): String {
+        val keyWithoutSizeInformation = this.packageName.plus(":").plus(this.serviceName)
+        return if (displaySize != null) {
+            keyWithoutSizeInformation.plus(":").plus("${displaySize.x}x${displaySize.y}")
+        } else {
+            keyWithoutSizeInformation
+        }
     }
 
     private suspend fun bindWallpaperService(
@@ -195,7 +276,8 @@
         engineKey: String,
         engine: IWallpaperEngine,
         parentSurface: SurfaceView,
-        displayMetrics: Point
+        displayMetrics: Point,
+        enforceSingleEngine: Boolean,
     ) {
         fun logError(e: Exception) {
             Log.e(WallpaperConnection::class.simpleName, "Fail to reparent wallpaper surface", e)
@@ -211,10 +293,10 @@
             SurfaceControl.Transaction().use { t ->
                 t.setMatrix(
                     wallpaperSurfaceControl,
-                    values[Matrix.MSCALE_X],
-                    values[Matrix.MSKEW_Y],
+                    if (enforceSingleEngine) values[Matrix.MSCALE_Y] else values[Matrix.MSCALE_X],
                     values[Matrix.MSKEW_X],
-                    values[Matrix.MSCALE_Y]
+                    values[Matrix.MSKEW_Y],
+                    values[Matrix.MSCALE_Y],
                 )
                 t.reparent(wallpaperSurfaceControl, parentSurfaceControl)
                 t.show(wallpaperSurfaceControl)
@@ -256,9 +338,35 @@
         return values
     }
 
-    private fun getDisplayMetrics(view: View): Point {
-        val screenSizeCalculator = ScreenSizeCalculator.getInstance()
-        val display: Display = view.display
-        return screenSizeCalculator.getScreenSize(display)
+    data class EngineRenderingConfig(
+        val enforceSingleEngine: Boolean,
+        val deviceDisplayType: DeviceDisplayType,
+        val smallDisplaySize: Point,
+        val wallpaperDisplaySize: Point,
+    ) {
+        fun getEngineDisplaySize(): Point {
+            // If we need to enforce single engine, always return the larger screen's preview
+            return if (enforceSingleEngine) {
+                return wallpaperDisplaySize
+            } else {
+                getPreviewDisplaySize()
+            }
+        }
+
+        private fun getPreviewDisplaySize(): Point {
+            return when (deviceDisplayType) {
+                DeviceDisplayType.SINGLE -> wallpaperDisplaySize
+                DeviceDisplayType.FOLDED -> smallDisplaySize
+                DeviceDisplayType.UNFOLDED -> wallpaperDisplaySize
+            }
+        }
+    }
+
+    fun LiveWallpaperModel.shouldEnforceSingleEngine(): Boolean {
+        return when {
+            creativeWallpaperData != null -> false
+            liveWallpaperData.isEffectWallpaper -> false
+            else -> true // Only fallback to single engine rendering for legacy live wallpapers
+        }
     }
 }
diff --git a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionSelectionBottomSheetContent.kt b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionSelectionBottomSheetContent.kt
index 29377d5..57d9fce 100644
--- a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionSelectionBottomSheetContent.kt
+++ b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionSelectionBottomSheetContent.kt
@@ -60,7 +60,6 @@
                 //  agreed upon.
                 // Forcing only one effect item for now
                 Arrays.asList(wallpaperActions.get(0)),
-                clearActionsUri,
                 wallpaperEffectSwitchListener
             )
         )
diff --git a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionsToggleAdapter.kt b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionsToggleAdapter.kt
index b145a92..b131cf1 100644
--- a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionsToggleAdapter.kt
+++ b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperActionsToggleAdapter.kt
@@ -15,7 +15,6 @@
  */
 package com.android.wallpaper.widget.floatingsheetcontent
 
-import android.net.Uri
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
@@ -31,7 +30,6 @@
  */
 class WallpaperActionsToggleAdapter(
     private val actionToggles: List<WallpaperAction>,
-    private val clearToggle: Uri,
     private val wallpaperEffectSwitchListener: WallpaperEffectSwitchListener
 ) : RecyclerView.Adapter<WallpaperActionsToggleAdapter.ViewHolder>() {
 
diff --git a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperEffectsView2.kt b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperEffectsView2.kt
index 3dadf54..ef52194 100644
--- a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperEffectsView2.kt
+++ b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperEffectsView2.kt
@@ -73,7 +73,7 @@
         SUCCESS,
         PROCESSING,
         SHOW_DOWNLOAD_BUTTON,
-        DOWNLOADING,
+        DOWNLOADING, // downloading of ml models in progress
     }
 
     /**
@@ -210,7 +210,6 @@
         container?.visibility = INVISIBLE
         downloadProgression?.visibility = INVISIBLE
         downloadButtonLayout?.visibility = INVISIBLE
-        downloadProgression?.visibility = INVISIBLE
     }
 
     private fun showFailedLayout(errorMessage: String?) {
@@ -220,7 +219,6 @@
         container?.visibility = VISIBLE
         downloadProgression?.visibility = INVISIBLE
         downloadButtonLayout?.visibility = INVISIBLE
-        downloadProgression?.visibility = INVISIBLE
     }
 
     private fun controlButtonByCode(view: View?, resultCode: Int?, mask: Int) {
diff --git a/src_override/com/android/wallpaper/module/AppModule.kt b/src_override/com/android/wallpaper/module/AppModule.kt
index 6cd5e4d..9d1a6ea 100644
--- a/src_override/com/android/wallpaper/module/AppModule.kt
+++ b/src_override/com/android/wallpaper/module/AppModule.kt
@@ -20,6 +20,8 @@
 import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.picker.preview.data.util.DefaultLiveWallpaperDownloader
 import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
+import com.android.wallpaper.system.UiModeManagerImpl
+import com.android.wallpaper.system.UiModeManagerWrapper
 import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
 import com.android.wallpaper.util.converter.WallpaperModelFactory
 import dagger.Binds
@@ -47,6 +49,8 @@
         impl: DefaultLiveWallpaperDownloader
     ): LiveWallpaperDownloader
 
+    @Binds @Singleton abstract fun bindUiModeManager(impl: UiModeManagerImpl): UiModeManagerWrapper
+
     companion object {
         @Provides
         @Singleton
diff --git a/tests/common/src/com/android/wallpaper/testing/FakeUiModeManager.kt b/tests/common/src/com/android/wallpaper/testing/FakeUiModeManager.kt
new file mode 100644
index 0000000..649133d
--- /dev/null
+++ b/tests/common/src/com/android/wallpaper/testing/FakeUiModeManager.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.testing
+
+import android.app.UiModeManager.ContrastChangeListener
+import com.android.wallpaper.system.UiModeManagerWrapper
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class FakeUiModeManager @Inject constructor() : UiModeManagerWrapper {
+    val listeners = mutableListOf<ContrastChangeListener>()
+    private var _contrast: Float? = 0.0f
+
+    override fun addContrastChangeListener(
+        executor: Executor,
+        listener: ContrastChangeListener,
+    ) {
+        listeners.add(listener)
+    }
+
+    override fun removeContrastChangeListener(listener: ContrastChangeListener) {
+        listeners.remove(listener)
+    }
+
+    override fun getContrast(): Float? {
+        return _contrast
+    }
+
+    fun setContrast(contrast: Float?) {
+        _contrast = contrast
+        contrast?.let { v -> listeners.forEach { it.onContrastChanged(v) } }
+    }
+
+    override fun setNightModeActivated(isActive: Boolean) {
+        // no-op
+    }
+}
diff --git a/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt b/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt
index 58d83c6..bed547e 100644
--- a/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt
+++ b/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt
@@ -21,6 +21,7 @@
 import android.graphics.Bitmap
 import android.graphics.Point
 import android.graphics.Rect
+import com.android.wallpaper.asset.Asset
 import com.android.wallpaper.module.logging.UserEventLogger.SetWallpaperEntryPoint
 import com.android.wallpaper.picker.customization.data.content.WallpaperClient
 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
@@ -28,7 +29,6 @@
 import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
-import java.io.InputStream
 import kotlin.math.min
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -89,9 +89,9 @@
         setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperModel: StaticWallpaperModel,
-        inputStream: InputStream?,
         bitmap: Bitmap,
         wallpaperSize: Point,
+        asset: Asset,
         fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
     ) {
         TODO("Not yet implemented")
diff --git a/tests/common/src/com/android/wallpaper/testing/TestInjector.kt b/tests/common/src/com/android/wallpaper/testing/TestInjector.kt
index 6e1321d..0d75080 100644
--- a/tests/common/src/com/android/wallpaper/testing/TestInjector.kt
+++ b/tests/common/src/com/android/wallpaper/testing/TestInjector.kt
@@ -266,7 +266,7 @@
     }
 
     override fun getWallpaperInteractor(context: Context): WallpaperInteractor {
-        if (getFlags().isMultiCropEnabled() && getFlags().isMultiCropPreviewUiEnabled()) {
+        if (getFlags().isMultiCropEnabled()) {
             return injectedWallpaperInteractor
         }
 
diff --git a/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt b/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt
index e7480cf..0ddfb26 100644
--- a/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt
+++ b/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt
@@ -84,7 +84,8 @@
     private var mLockLiveWallpaperPrefMetadata: LiveWallpaperPrefMetadata? = null
     private val mWallStoredColor: HashMap<String, String> = HashMap()
 
-    private var hasPreviewTooltipBeenShown = true
+    private var hasSmallPreviewTooltipBeenShown = false
+    private var hasFullPreviewTooltipBeenShown = false
 
     init {
         wallpaperPresentationMode = WallpaperPreferences.PRESENTATION_MODE_STATIC
@@ -485,12 +486,20 @@
         wallpaperModel: WallpaperModel.LiveWallpaperModel
     ) {}
 
-    override fun setHasPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
-        this.hasPreviewTooltipBeenShown = hasTooltipBeenShown
+    override fun setHasSmallPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
+        this.hasSmallPreviewTooltipBeenShown = hasTooltipBeenShown
     }
 
-    override fun getHasPreviewTooltipBeenShown(): Boolean {
-        return hasPreviewTooltipBeenShown
+    override fun getHasSmallPreviewTooltipBeenShown(): Boolean {
+        return hasSmallPreviewTooltipBeenShown
+    }
+
+    override fun setHasFullPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
+        this.hasFullPreviewTooltipBeenShown = hasTooltipBeenShown
+    }
+
+    override fun getHasFullPreviewTooltipBeenShown(): Boolean {
+        return hasFullPreviewTooltipBeenShown
     }
 
     private fun setAppLaunchCount(count: Int) {
diff --git a/tests/common/src/com/android/wallpaper/testing/WallpaperModelUtils.kt b/tests/common/src/com/android/wallpaper/testing/WallpaperModelUtils.kt
index 4ec057f..22aee65 100644
--- a/tests/common/src/com/android/wallpaper/testing/WallpaperModelUtils.kt
+++ b/tests/common/src/com/android/wallpaper/testing/WallpaperModelUtils.kt
@@ -128,6 +128,7 @@
                         systemWallpaperInfo,
                         isTitleVisible,
                         isApplied,
+                        effectNames != null,
                         effectNames
                     ),
                 creativeWallpaperData = null,
diff --git a/tests/module/src/com/android/wallpaper/TestModule.kt b/tests/module/src/com/android/wallpaper/TestModule.kt
index 18b3a9f..d86f75b 100644
--- a/tests/module/src/com/android/wallpaper/TestModule.kt
+++ b/tests/module/src/com/android/wallpaper/TestModule.kt
@@ -22,6 +22,8 @@
 import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.picker.preview.data.util.DefaultLiveWallpaperDownloader
 import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
+import com.android.wallpaper.system.UiModeManagerWrapper
+import com.android.wallpaper.testing.FakeUiModeManager
 import com.android.wallpaper.testing.TestInjector
 import com.android.wallpaper.testing.TestWallpaperPreferences
 import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
@@ -54,4 +56,6 @@
     abstract fun bindLiveWallpaperDownloader(
         impl: DefaultLiveWallpaperDownloader
     ): LiveWallpaperDownloader
+
+    @Binds @Singleton abstract fun bindUiModeManager(impl: FakeUiModeManager): UiModeManagerWrapper
 }
diff --git a/tests/robotests/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepositoryTest.kt b/tests/robotests/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepositoryTest.kt
index 26e8820..c63cfa9 100644
--- a/tests/robotests/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepositoryTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepositoryTest.kt
@@ -98,18 +98,22 @@
 
     @Test
     fun dismissTooltip() {
-        prefs.setHasPreviewTooltipBeenShown(false)
+        prefs.setHasSmallPreviewTooltipBeenShown(false)
+        prefs.setHasFullPreviewTooltipBeenShown(false)
         underTest =
             WallpaperPreviewRepository(
                 liveWallpaperDownloader = TestLiveWallpaperDownloader(null),
                 preferences = prefs,
                 bgDispatcher = testDispatcher,
             )
-        assertThat(underTest.hasTooltipBeenShown.value).isFalse()
+        assertThat(underTest.hasSmallPreviewTooltipBeenShown.value).isFalse()
+        assertThat(underTest.hasFullPreviewTooltipBeenShown.value).isFalse()
 
-        underTest.dismissTooltip()
-        assertThat(prefs.getHasPreviewTooltipBeenShown()).isTrue()
-        assertThat(underTest.hasTooltipBeenShown.value).isTrue()
+        underTest.hideSmallPreviewTooltip()
+        assertThat(prefs.getHasSmallPreviewTooltipBeenShown()).isTrue()
+        assertThat(underTest.hasSmallPreviewTooltipBeenShown.value).isTrue()
+        assertThat(prefs.getHasFullPreviewTooltipBeenShown()).isFalse()
+        assertThat(underTest.hasFullPreviewTooltipBeenShown.value).isFalse()
     }
 
     @Test
@@ -195,6 +199,7 @@
                     systemWallpaperInfo = wallpaperInfo,
                     isTitleVisible = false,
                     isApplied = false,
+                    isEffectWallpaper = false,
                     effectNames = null,
                 ),
             creativeWallpaperData = null,
diff --git a/tests/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivityTest.kt b/tests/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivityTest.kt
index 7778b91..fce9ed8 100644
--- a/tests/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivityTest.kt
+++ b/tests/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivityTest.kt
@@ -22,7 +22,6 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import com.android.wallpaper.Flags.FLAG_MULTI_CROP_PREVIEW_UI_FLAG
 import com.android.wallpaper.model.WallpaperInfo
 import com.android.wallpaper.module.InjectorProvider
 import com.android.wallpaper.testing.TestInjector
@@ -67,7 +66,7 @@
 
     @Test
     @Ignore("b/327241549")
-    @EnableFlags(FLAG_MULTI_CROP_PREVIEW_UI_FLAG, FLAG_MULTI_CROP)
+    @EnableFlags(FLAG_MULTI_CROP)
     fun showsNavHostFragment() {
         val scenario: ActivityScenario<WallpaperPreviewActivity> =
             ActivityScenario.launch(activityStartIntent)