Merge tag 'android-14.0.0_r50' into leaf-3.2

Android 14.0.0 Release 50 (AP2A.240605.024)

* tag 'android-14.0.0_r50': (123 commits)
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Multicrop: adds crop hints to recents
  Multi-crop: refactors adding recents for better code reuse
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Fix static wallpaper crash
  Fix editing current wallpaper crop on foldable
  Fix preview crash on unfold in multi-crop
  Use default crop if no crop when set wallpaper
  Fix setting Emoji wallpaper issue
  Revert^2 "Use Wallpaper Manager to preview crop color"
  Ignore WallpaperPreviewActivityTest due to permission failures
  Add SetFlagRule to WallpaperPreviewActivityTest (1/3)
  Fix preview screen issue on foldables when unfolding
  Align preview based on layout direction
  Fix Emoji wallpaper crash when clicking on preview
  Use the current display size for CreativeNewPreviewFragment
  Remove unnecessary vertical parallax
  Add parallax to cropHints for multi-crop
  ...

Change-Id: Iad7f64ff88e5f8e0cedd9df36e0bf85d8d2fe90b
diff --git a/Android.bp b/Android.bp
index 8479134..b973cf4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,7 +22,8 @@
 }
 
 android_library {
-    name: "wallpaper-common-deps",
+    name: "WallpaperPicker2Lib",
+    platform_apis: true,
 
     static_libs: [
         "androidx.activity_activity-ktx",
@@ -47,23 +48,29 @@
         "kotlinx-coroutines-core",
         "libbackup",
         "SettingsLibCollapsingToolbarBaseActivity",
+	"SettingsLibSettingsTheme",
         "subsampling-scale-image-view",
         "SystemUISharedLib",
         "SystemUICustomizationLib",
         "volley",
         "SettingsLibActivityEmbedding",
+        "monet",
+        "hilt_android",
     ],
 
     resource_dirs: ["res"],
 
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+
     optimize: {
         enabled: false,
     },
 
     kotlincflags: ["-Xjvm-default=all"],
 
-    sdk_version: "current",
-
     manifest: "AndroidManifest-empty.xml",
 
     visibility: [
@@ -73,24 +80,6 @@
     ],
 }
 
-filegroup {
-    name: "WallpaperPicker2_srcs",
-    srcs: [
-        "src/**/*.java",
-        "src/**/*.kt",
-    ],
-}
-
-// If these targets are included in WallpaperPicker2_defaults directly instead of in a filegroup,
-// the tests can't find them.
-filegroup {
-    name: "WallpaperPicker2_src_overrides",
-    srcs: [
-        "src_override/**/*.java",
-        "src_override/**/*.kt",
-    ],
-}
-
 // Production-only files that should be excluded in tests.
 filegroup {
     name: "WallpaperPicker2_src_prod",
@@ -98,16 +87,29 @@
     srcs: ["src_override/com/android/wallpaper/picker/WallpapersApplication.java"],
 }
 
-genrule {
-   name: "WallpaperPicker2_res",
-   tools: ["soong_zip"],
-   srcs: [
-       "res/**/*"
-   ],
-   out: ["wallpaperpicker2_res.zip"],
-   cmd: "INPUTS=($(in)) && "
-       + "RES_DIR=$$(dirname $$(dirname $${INPUTS[0]})) && "
-       + "$(location soong_zip) -o $(out) -C $$RES_DIR -D $$RES_DIR"
+java_library {
+    name: "WallpaperPicker2OverridesLib",
+    srcs: [
+        "src_override/**/*.java",
+        "src_override/**/*.kt",
+    ],
+    exclude_srcs: [
+        ":WallpaperPicker2_src_prod",
+    ],
+    libs: [
+        "WallpaperPicker2Lib",
+        "hilt_android",
+    ],
+}
+
+java_library {
+    name: "WallpaperPicker2ApplicationLib",
+    srcs: [":WallpaperPicker2_src_prod"],
+    libs: [
+        "WallpaperPicker2Lib",
+        "WallpaperPicker2OverridesLib",
+        "hilt_android",
+    ],
 }
 
 filegroup {
@@ -117,20 +119,8 @@
     ],
 }
 
-// Common defaults that doesn't have WallpaperPicker2 specifics.
 java_defaults {
-    name: "WallpaperPicker2_common_defaults",
-
-    static_libs: [
-        "wallpaper-common-deps",
-        "monet",
-        "hilt_android",
-    ],
-
-    srcs: [
-        ":WallpaperPicker2_srcs",
-    ],
-    resource_zips: [":WallpaperPicker2_res"],
+    name: "WallpaperPicker2_defaults",
 
     certificate: "",
 
@@ -143,14 +133,11 @@
     system_ext_specific: true,
 
     use_embedded_native_libs: true,
-}
 
-java_defaults {
-    name: "WallpaperPicker2_defaults",
-    defaults: ["WallpaperPicker2_common_defaults"],
-
-    srcs: [
-        ":WallpaperPicker2_src_overrides",
+    static_libs: [
+        "WallpaperPicker2Lib",
+        "WallpaperPicker2OverridesLib",
+        "hilt_android",
     ],
 }
 
@@ -159,10 +146,12 @@
 //
 android_app {
     name: "WallpaperPicker2",
+    package_name: "com.android.wallpaper",
 
     defaults: ["WallpaperPicker2_defaults"],
     manifest: ":WallpaperPicker2_Manifest",
 
     platform_apis: true,
     overrides: ["WallpaperPicker"],
+    static_libs: ["WallpaperPicker2ApplicationLib"],
 }
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7281160..e1e505d 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,8 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 
+<!-- The package name here must match the Studio namespace given in
+     WallpaperPickerGoogle gradle config for Studio builds to succeed.
+     `package_name` in Android.bp overrides this with the actual package name.
+ -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
-     package="com.android.wallpaper">
+     package="com.google.android.apps.wallpaper">
 
   <!-- Custom permission to enforce that only this app can notify the running live wallpaper that
              the rotating wallpaper image data changed. -->
@@ -21,6 +25,7 @@
   <uses-permission android:name="android.permission.BIND_WALLPAPER" />
   <uses-permission android:name="android.permission.WAKE_LOCK"/>
   <uses-permission android:name="com.android.wallpaper.NOTIFY_ROTATING_WALLPAPER_CHANGED"/>
+  <uses-permission android:name="android.permission.SET_WALLPAPER_DIM_AMOUNT" />
 
   <queries>
       <!-- Specific intents Wallpaper picker query for -->
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index 0e019d0..281ae78 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -1,10 +1,11 @@
 aconfig_declarations {
     name: "com_android_wallpaper_flags",
     package: "com.android.wallpaper",
+    container: "system",
     srcs: ["customization_picker.aconfig"],
 }
 
 java_aconfig_library {
     name: "com_android_wallpaper_flags_lib",
     aconfig_declarations: "com_android_wallpaper_flags",
-}
\ No newline at end of file
+}
diff --git a/aconfig/customization_picker.aconfig b/aconfig/customization_picker.aconfig
index 7c7cc45..bf1d760 100644
--- a/aconfig/customization_picker.aconfig
+++ b/aconfig/customization_picker.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.wallpaper"
+container: "system"
 
 flag {
     name: "multi_crop_preview_ui_flag"
diff --git a/res/drawable/effect_continue_button_background.xml b/res/drawable/effect_continue_button_background.xml
new file mode 100644
index 0000000..eb86f0f
--- /dev/null
+++ b/res/drawable/effect_continue_button_background.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android">
+    <shape android:shape="rectangle">
+        <corners android:radius="@dimen/wallpaper_effect_failed_button_background_radius" />
+        <stroke
+            android:width="1dp"
+            android:color="@color/color_accent_secondary" />
+    </shape>
+</inset>
diff --git a/res/drawable/effect_download_button_background.xml b/res/drawable/effect_download_button_background.xml
new file mode 100644
index 0000000..fee55c3
--- /dev/null
+++ b/res/drawable/effect_download_button_background.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:colorControlHighlight">
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/wallpaper_effect_download_button_corner_radius" />
+            <solid android:color="@color/color_accent_primary" />
+        </shape>
+    </item>
+</ripple>
diff --git a/res/drawable/ic_check_wallpaper_32dp.xml b/res/drawable/ic_check_wallpaper_32dp.xml
new file mode 100644
index 0000000..d898ddf
--- /dev/null
+++ b/res/drawable/ic_check_wallpaper_32dp.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@color/text_color_on_accent"
+        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41L9,16.17z"/>
+</vector>
diff --git a/res/drawable/ic_effects_download_24px.xml b/res/drawable/ic_effects_download_24px.xml
new file mode 100644
index 0000000..a26ca50
--- /dev/null
+++ b/res/drawable/ic_effects_download_24px.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24">
+    <path
+        android:fillColor="@color/text_color_primary_inverse"
+        android:pathData="M4,15h2v3h12v-3h2v3c0,1.1 -0.9,2 -2,2H6c-1.1,0 -2,-0.9 -2,-2m11.59,-8.41L13,12.17V4h-2v8.17L8.41,9.59 7,11l5,5 5,-5 -1.41,-1.41z" />
+</vector>
diff --git a/res/drawable/ic_pinch.xml b/res/drawable/ic_pinch.xml
new file mode 100644
index 0000000..3bd65e6
--- /dev/null
+++ b/res/drawable/ic_pinch.xml
@@ -0,0 +1,24 @@
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M380,240L380,142L142,380L240,380L240,440L40,440L40,240L100,240L100,338L338,100L240,100L240,40L440,40L440,240L380,240ZM593,920Q569,920 547,911Q525,902 508,885L304,680L334,649Q350,633 371.5,627.5Q393,622 414,628L480,647L480,320Q480,303 491.5,291.5Q503,280 520,280Q537,280 548.5,291.5Q560,303 560,320L560,753L463,726L565,828Q570,833 577.5,836.5Q585,840 593,840L760,840Q793,840 816.5,816.5Q840,793 840,760L840,600Q840,583 851.5,571.5Q863,560 880,560Q897,560 908.5,571.5Q920,583 920,600L920,760Q920,826 873,873Q826,920 760,920L593,920ZM600,640L600,480Q600,463 611.5,451.5Q623,440 640,440Q657,440 668.5,451.5Q680,463 680,480L680,640L600,640ZM720,640L720,520Q720,503 731.5,491.5Q743,480 760,480Q777,480 788.5,491.5Q800,503 800,520L800,640L720,640ZM700,720L700,720L700,720Q700,720 700,720Q700,720 700,720L700,720Q700,720 700,720Q700,720 700,720L700,720L700,720L700,720Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_tap_screen.xml b/res/drawable/ic_tap_screen.xml
new file mode 100644
index 0000000..b7a3b68
--- /dev/null
+++ b/res/drawable/ic_tap_screen.xml
@@ -0,0 +1,24 @@
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M419,880Q391,880 366.5,868Q342,856 325,834L107,557L126,537Q146,516 174,512Q202,508 226,523L300,568L300,240Q300,223 311.5,211.5Q323,200 340,200Q357,200 369,211.5Q381,223 381,240L381,712L284,652L388,785Q394,792 402,796Q410,800 419,800L640,800Q673,800 696.5,776.5Q720,753 720,720L720,560Q720,543 708.5,531.5Q697,520 680,520L461,520L461,440L680,440Q730,440 765,475Q800,510 800,560L800,720Q800,786 753,833Q706,880 640,880L419,880ZM167,340Q154,318 147,292.5Q140,267 140,240Q140,157 198.5,98.5Q257,40 340,40Q423,40 481.5,98.5Q540,157 540,240Q540,267 533,292.5Q526,318 513,340L444,300Q452,286 456,271.5Q460,257 460,240Q460,190 425,155Q390,120 340,120Q290,120 255,155Q220,190 220,240Q220,257 224,271.5Q228,286 236,300L167,340ZM502,620L502,620L502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620L502,620L502,620Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_uncheck_wallpaper_32dp.xml b/res/drawable/ic_uncheck_wallpaper_32dp.xml
new file mode 100644
index 0000000..d4f6f02
--- /dev/null
+++ b/res/drawable/ic_uncheck_wallpaper_32dp.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41L9,16.17z"/>
+</vector>
diff --git a/res/drawable/set_wallpaper_dialog_button.xml b/res/drawable/set_wallpaper_dialog_button.xml
index 1011e80..a5670a3 100644
--- a/res/drawable/set_wallpaper_dialog_button.xml
+++ b/res/drawable/set_wallpaper_dialog_button.xml
@@ -37,7 +37,7 @@
                 android:top="@dimen/set_wallpaper_button_vertical_padding"
                 android:right="@dimen/set_wallpaper_button_horizontal_padding"
                 android:bottom="@dimen/set_wallpaper_button_vertical_padding" />
-            <solid  android:color="@color/system_secondary" />
+            <solid android:color="@color/system_secondary" />
         </shape>
     </item>
 </ripple>
\ No newline at end of file
diff --git a/res/layout/preview_foldable_card_view.xml b/res/drawable/set_wallpaper_dialog_preview_border_selector.xml
similarity index 63%
rename from res/layout/preview_foldable_card_view.xml
rename to res/drawable/set_wallpaper_dialog_preview_border_selector.xml
index 98984f5..abed39a 100644
--- a/res/layout/preview_foldable_card_view.xml
+++ b/res/drawable/set_wallpaper_dialog_preview_border_selector.xml
@@ -12,14 +12,9 @@
   ~ 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="match_parent"
-    android:layout_height="match_parent">
-
-    <com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
-        android:id="@+id/dual_preview"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-</FrameLayout>
\ No newline at end of file
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_activated="true"
+        android:drawable="@drawable/set_wallpaper_dialog_preview_selection_border"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/set_wallpaper_dialog_preview_selection_border.xml b/res/drawable/set_wallpaper_dialog_preview_selection_border.xml
new file mode 100644
index 0000000..7887239
--- /dev/null
+++ b/res/drawable/set_wallpaper_dialog_preview_selection_border.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Inner border -->
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/set_wallpaper_dialog_preview_corner_radius" />
+            <stroke
+                android:width="6dp"
+                android:color="@color/color_surface" />
+        </shape>
+    </item>
+
+    <!-- Outer border -->
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/set_wallpaper_dialog_preview_corner_radius" />
+            <stroke
+                android:width="3dp"
+                android:color="@color/system_secondary" />
+        </shape>
+    </item>
+</layer-list>
diff --git a/res/layout/preview_foldable_card_view.xml b/res/drawable/set_wallpaper_dialog_preview_selection_checked.xml
similarity index 63%
copy from res/layout/preview_foldable_card_view.xml
copy to res/drawable/set_wallpaper_dialog_preview_selection_checked.xml
index 98984f5..6b72c20 100644
--- a/res/layout/preview_foldable_card_view.xml
+++ b/res/drawable/set_wallpaper_dialog_preview_selection_checked.xml
@@ -12,14 +12,13 @@
   ~ 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="match_parent"
-    android:layout_height="match_parent">
-
-    <com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
-        android:id="@+id/dual_preview"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-</FrameLayout>
\ No newline at end of file
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape android:shape="oval">
+            <size android:width="32dp" android:height="32dp" />
+            <solid android:color="@color/system_secondary" />
+        </shape>
+    </item>
+    <item android:drawable="@drawable/ic_check_wallpaper_32dp" android:gravity="fill" />
+</layer-list>
\ No newline at end of file
diff --git a/res/layout/preview_foldable_card_view.xml b/res/drawable/set_wallpaper_dialog_preview_selection_unchecked.xml
similarity index 62%
copy from res/layout/preview_foldable_card_view.xml
copy to res/drawable/set_wallpaper_dialog_preview_selection_unchecked.xml
index 98984f5..2edd532 100644
--- a/res/layout/preview_foldable_card_view.xml
+++ b/res/drawable/set_wallpaper_dialog_preview_selection_unchecked.xml
@@ -12,14 +12,13 @@
   ~ 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="match_parent"
-    android:layout_height="match_parent">
-
-    <com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
-        android:id="@+id/dual_preview"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-</FrameLayout>
\ No newline at end of file
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape android:shape="oval">
+            <size android:width="32dp" android:height="32dp" />
+            <stroke android:color="@color/white" android:width="1dp" />
+        </shape>
+    </item>
+    <item android:drawable="@drawable/ic_uncheck_wallpaper_32dp" android:gravity="fill" />
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/set_wallpaper_dialog_preview_selector.xml b/res/drawable/set_wallpaper_dialog_preview_selector.xml
new file mode 100644
index 0000000..a8377b2
--- /dev/null
+++ b/res/drawable/set_wallpaper_dialog_preview_selector.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_activated="false"
+        android:drawable="@drawable/set_wallpaper_dialog_preview_selection_unchecked"/>
+    <item
+        android:state_activated="true"
+        android:drawable="@drawable/set_wallpaper_dialog_preview_selection_checked"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/small_preview_tab_background.xml b/res/drawable/small_preview_tab_background_selected.xml
similarity index 94%
rename from res/drawable/small_preview_tab_background.xml
rename to res/drawable/small_preview_tab_background_selected.xml
index ced9242..c524687 100644
--- a/res/drawable/small_preview_tab_background.xml
+++ b/res/drawable/small_preview_tab_background_selected.xml
@@ -1,5 +1,5 @@
 <!--
-  ~ Copyright (C) 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.
diff --git a/res/drawable/up_arrow_tip.xml b/res/drawable/up_arrow_tip.xml
new file mode 100644
index 0000000..9442199
--- /dev/null
+++ b/res/drawable/up_arrow_tip.xml
@@ -0,0 +1,25 @@
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="100dp"
+    android:width="100dp"
+    android:viewportHeight="100"
+    android:viewportWidth="100">
+    <path
+        android:name="triangle"
+        android:fillColor="@color/color_surface"
+        android:pathData="m 50,0 l 50,100 -100,0 z" />
+</vector>
diff --git a/res/layout/dialog_set_wallpaper_title.xml b/res/layout/dialog_set_wallpaper_title.xml
index 4dbc4f2..ab8a5f1 100755
--- a/res/layout/dialog_set_wallpaper_title.xml
+++ b/res/layout/dialog_set_wallpaper_title.xml
@@ -39,6 +39,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:fontFamily="@*android:string/config_headlineFontFamily"
+        android:paddingHorizontal="@dimen/set_wallpaper_dialog_title_padding"
+        android:maxLines="2"
         android:minHeight="32dp"
         android:textColor="@color/text_color_primary"
         android:textSize="24sp"
diff --git a/res/layout/fragment_customization_picker.xml b/res/layout/fragment_customization_picker.xml
index b4afca5..978d149 100755
--- a/res/layout/fragment_customization_picker.xml
+++ b/res/layout/fragment_customization_picker.xml
@@ -23,7 +23,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@android:color/transparent"
-        android:overScrollMode="always"
+        android:overScrollMode="never"
         android:scrollbars="vertical">
         <LinearLayout
             android:id="@+id/home_section_container"
@@ -38,7 +38,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@android:color/transparent"
-        android:overScrollMode="always"
+        android:overScrollMode="never"
         android:scrollbars="vertical"
         android:visibility="gone">
         <LinearLayout
diff --git a/res/layout/fragment_full_preview.xml b/res/layout/fragment_full_preview.xml
index d9f59ba..c32b050 100644
--- a/res/layout/fragment_full_preview.xml
+++ b/res/layout/fragment_full_preview.xml
@@ -27,7 +27,7 @@
         android:background="@android:color/transparent"
         android:contentDescription="@string/preview_screen_description"/>
 
-    <include layout="@layout/wallpaper_preview_full"/>
+    <include layout="@layout/full_wallpaper_preview_card"/>
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
@@ -57,4 +57,11 @@
             app:layout_constraintBottom_toBottomOf="@id/toolbar_container"/>
     </androidx.constraintlayout.widget.ConstraintLayout>
 
+    <ViewStub
+        android:id="@+id/tooltip_stub"
+        android:inflatedId="@+id/tooltip"
+        android:layout="@layout/tooltip_full_preview"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"/>
+
 </FrameLayout>
diff --git a/res/layout/full_wallpaper_preview_card.xml b/res/layout/full_wallpaper_preview_card.xml
new file mode 100644
index 0000000..624de83
--- /dev/null
+++ b/res/layout/full_wallpaper_preview_card.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<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">
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/preview_card"
+        style="@style/FullContentPreviewCard"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipChildren="true"
+        android:contentDescription="@string/wallpaper_preview_card_content_description">
+
+        <com.android.wallpaper.picker.preview.ui.view.SystemScaledWallpaperPreviewSurfaceView
+            android:id="@+id/wallpaper_surface"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <SurfaceView
+            android:id="@+id/workspace_surface"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:importantForAccessibility="noHideDescendants" />
+    </androidx.cardview.widget.CardView>
+
+</com.android.wallpaper.picker.preview.ui.view.FullPreviewFrameLayout>
diff --git a/res/layout/grid_item_category.xml b/res/layout/grid_item_category.xml
index 4bfd88f..04cb5f1 100755
--- a/res/layout/grid_item_category.xml
+++ b/res/layout/grid_item_category.xml
@@ -19,8 +19,6 @@
     android:id="@+id/tile"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:clickable="true"
-    android:focusable="true"
     android:orientation="vertical">
 
     <androidx.cardview.widget.CardView
diff --git a/res/layout/item_text.xml b/res/layout/item_text.xml
index 97fe155..131e969 100644
--- a/res/layout/item_text.xml
+++ b/res/layout/item_text.xml
@@ -22,8 +22,16 @@
         android:id="@+id/preview_tab_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:background="@drawable/small_preview_tab_background"
+        android:background="@drawable/small_preview_tab_background_selected"
         android:layout_gravity="center"
         android:textAppearance="@style/WallpaperPicker.Preview.TextAppearance.NoAllCaps"
         android:textColor="@color/system_on_primary" />
+
+    <TextView
+        android:id="@+id/preview_tab_text_overlay_disabled"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:textAppearance="@style/WallpaperPicker.Preview.TextAppearance.NoAllCaps"
+        android:textColor="@color/system_secondary" />
 </FrameLayout>
diff --git a/res/layout/my_photos.xml b/res/layout/my_photos.xml
index d3b5a56..52b5b97 100644
--- a/res/layout/my_photos.xml
+++ b/res/layout/my_photos.xml
@@ -21,7 +21,8 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    android:layout_marginTop="10dp">
+    android:layout_marginTop="10dp"
+    android:importantForAccessibility="no">
 
     <TextView
         android:id="@+id/tile_title"
diff --git a/res/layout/set_wallpaper_dialog.xml b/res/layout/set_wallpaper_dialog.xml
index c90a421..41917c2 100644
--- a/res/layout/set_wallpaper_dialog.xml
+++ b/res/layout/set_wallpaper_dialog.xml
@@ -17,37 +17,67 @@
 <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    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:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="?attr/dialogPreferredPadding"
-        android:paddingRight="?attr/dialogPreferredPadding"
-        android:paddingTop="@dimen/abc_dialog_padding_top_material"
-        android:text="Set wallpaper"
+        android:text="@string/set_wallpaper_button_text"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent" />
 
-    <android.widget.Space
-        android:id="@+id/titleDividerNoCustom"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/abc_dialog_title_divider_material"
-        app:layout_constraintTop_toBottomOf="@id/title"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <LinearLayout
-        android:id="@+id/previews"
+    <FrameLayout
+        android:id="@+id/preview_container"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        app:layout_constraintTop_toBottomOf="@+id/titleDividerNoCustom"
+        app:layout_constraintTop_toBottomOf="@+id/title"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent" />
+        app:layout_constraintEnd_toEndOf="parent">
+        <include layout="@layout/set_wallpaper_dialog_foldable_preview"
+            android:id="@+id/foldable_previews"
+            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: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>
+
+    <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_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"/>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/res/layout/set_wallpaper_dialog_foldable_preview.xml b/res/layout/set_wallpaper_dialog_foldable_preview.xml
new file mode 100644
index 0000000..71471ec
--- /dev/null
+++ b/res/layout/set_wallpaper_dialog_foldable_preview.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <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"/>
+    <TextView
+        style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="@string/set_wallpaper_lock_screen_destination"/>
+
+    <android.widget.Space
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/abc_dialog_title_divider_material"/>
+
+    <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"/>
+    <TextView
+        style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="@string/set_wallpaper_home_screen_destination"/>
+
+</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
new file mode 100644
index 0000000..d82e438
--- /dev/null
+++ b/res/layout/set_wallpaper_dialog_handheld_preview.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    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">
+
+    <include layout="@layout/small_preview_handheld_card_view_selector"
+        android:id="@+id/lock_preview_selector"
+        android:layout_width="@dimen/set_wallpaper_dialog_handheld_preview_width"
+        android:layout_height="@dimen/set_wallpaper_dialog_handheld_preview_height"
+        android:clickable="true"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/home_preview_selector"
+        app:layout_constraintBottom_toTopOf="@+id/lock_screen_title"/>
+    <TextView
+        android:id="@+id/lock_screen_title"
+        style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/set_wallpaper_lock_screen_destination"
+        app:layout_constraintTop_toBottomOf="@id/lock_preview_selector"
+        app:layout_constraintStart_toStartOf="@+id/lock_preview_selector"
+        app:layout_constraintEnd_toEndOf="@+id/lock_preview_selector"/>
+
+    <include layout="@layout/small_preview_handheld_card_view_selector"
+        android:id="@+id/home_preview_selector"
+        android:layout_width="@dimen/set_wallpaper_dialog_handheld_preview_width"
+        android:layout_height="@dimen/set_wallpaper_dialog_handheld_preview_height"
+        android:clickable="true"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toEndOf="@+id/lock_preview_selector"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toTopOf="@+id/home_screen_title"/>
+    <TextView
+        android:id="@+id/home_screen_title"
+        style="@style/TextAppearance.SetWallpaperDialog.Subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/set_wallpaper_home_screen_destination"
+        app:layout_constraintTop_toBottomOf="@id/home_preview_selector"
+        app:layout_constraintStart_toStartOf="@+id/home_preview_selector"
+        app:layout_constraintEnd_toEndOf="@+id/home_preview_selector"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/res/layout/small_preview_foldable_card_view.xml b/res/layout/small_preview_foldable_card_view.xml
new file mode 100644
index 0000000..1dd3b0b
--- /dev/null
+++ b/res/layout/small_preview_foldable_card_view.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  ~
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
+        android:id="@+id/dual_preview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <include
+            android:id="@+id/small_preview_folded_preview"
+            layout="@layout/small_wallpaper_preview_card"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+
+        <include
+            android:id="@+id/small_preview_unfolded_preview"
+            layout="@layout/small_wallpaper_preview_card"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+    </com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout>
+
+    <ViewStub
+        android:id="@+id/tooltip_stub"
+        android:inflatedId="@+id/tooltip"
+        android:layout="@layout/tooltip_small_preview"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_gravity="center"/>
+</FrameLayout>
\ 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
new file mode 100644
index 0000000..c5e295e
--- /dev/null
+++ b/res/layout/small_preview_foldable_card_view_selector.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout
+        android:id="@+id/dual_preview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            <include
+                android:id="@+id/small_preview_folded_preview"
+                layout="@layout/small_wallpaper_preview_card"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+
+            <ImageView
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@drawable/set_wallpaper_dialog_preview_border_selector"/>
+
+            <ImageView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:background="@drawable/set_wallpaper_dialog_preview_selector"/>
+
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            <include
+                android:id="@+id/small_preview_unfolded_preview"
+                layout="@layout/small_wallpaper_preview_card"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+
+            <ImageView
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@drawable/set_wallpaper_dialog_preview_border_selector"/>
+
+            <ImageView
+                android:layout_width="wrap_content"
+                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>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/preview_handheld_card_view.xml b/res/layout/small_preview_handheld_card_view.xml
similarity index 70%
rename from res/layout/preview_handheld_card_view.xml
rename to res/layout/small_preview_handheld_card_view.xml
index d43bc77..2976be2 100644
--- a/res/layout/preview_handheld_card_view.xml
+++ b/res/layout/small_preview_handheld_card_view.xml
@@ -20,15 +20,22 @@
     android:clipChildren="false">
 
     <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="@dimen/small_preview_preview_top_padding"
-        android:paddingBottom="@dimen/small_preview_preview_bottom_padding">
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
         <include
             android:id="@+id/preview"
-            layout="@layout/wallpaper_preview_small"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
+            layout="@layout/small_wallpaper_preview_card"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
             android:layout_gravity="center"/>
     </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
-</FrameLayout>
\ No newline at end of file
+
+    <ViewStub
+        android:id="@+id/tooltip_stub"
+        android:inflatedId="@+id/tooltip"
+        android:layout="@layout/tooltip_small_preview"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_gravity="center"/>
+</FrameLayout>
diff --git a/res/layout/small_preview_handheld_card_view_selector.xml b/res/layout/small_preview_handheld_card_view_selector.xml
new file mode 100644
index 0000000..ba9df1a
--- /dev/null
+++ b/res/layout/small_preview_handheld_card_view_selector.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="@dimen/set_wallpaper_dialog_handheld_preview_width"
+    android:layout_height="@dimen/set_wallpaper_dialog_handheld_preview_height">
+
+    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <include
+            android:id="@+id/preview"
+            layout="@layout/small_wallpaper_preview_card"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"/>
+    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/set_wallpaper_dialog_preview_border_selector"/>
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:background="@drawable/set_wallpaper_dialog_preview_selector"/>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/small_wallpaper_preview_card.xml b/res/layout/small_wallpaper_preview_card.xml
new file mode 100644
index 0000000..78d2d7d
--- /dev/null
+++ b/res/layout/small_wallpaper_preview_card.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+<FrameLayout 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">
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/preview_card"
+        style="@style/FullContentPreviewCard"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipChildren="true"
+        android:contentDescription="@string/wallpaper_preview_card_content_description">
+
+        <SurfaceView
+            android:id="@+id/wallpaper_surface"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <SurfaceView
+            android:id="@+id/workspace_surface"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:importantForAccessibility="noHideDescendants" />
+    </androidx.cardview.widget.CardView>
+</FrameLayout>
diff --git a/res/layout/tooltip_full_preview.xml b/res/layout/tooltip_full_preview.xml
new file mode 100644
index 0000000..62f9026
--- /dev/null
+++ b/res/layout/tooltip_full_preview.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/tooltip"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:visibility="invisible">
+    <!-- A 30% opacity black scrim that can be shown to "dim" the wallpaper. -->
+    <View
+        android:id="@+id/wallpaper_dimming_scrim"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/wallpaper_preview_scrim_color"
+        android:importantForAccessibility="noHideDescendants"/>
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginHorizontal="10dp"
+        android:maxWidth="220dp"
+        android:background="@drawable/small_preview_tab_background_selected"
+        android:padding="12dp"
+        android:text="@string/full_preview_tooltip"
+        android:textColor="@color/system_on_primary"
+        android:drawableStart="@drawable/ic_pinch"
+        android:drawablePadding="10dp"
+        android:drawableTint="@color/system_on_primary"/>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/tooltip_small_preview.xml b/res/layout/tooltip_small_preview.xml
new file mode 100644
index 0000000..a00c77d
--- /dev/null
+++ b/res/layout/tooltip_small_preview.xml
@@ -0,0 +1,46 @@
+<?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:id="@+id/tooltip"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:layout_gravity="center"
+    android:visibility="invisible">
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="10dp"
+        android:maxWidth="220dp"
+        android:background="@drawable/small_preview_tab_background_selected"
+        android:padding="12dp"
+        android:text="@string/small_preview_tooltip"
+        android:textColor="@color/system_on_primary"
+        android:drawableStart="@drawable/ic_tap_screen"
+        android:drawablePadding="5dp"
+        android:drawableTint="@color/system_on_primary"/>
+    <ImageView
+        android:layout_width="15dp"
+        android:layout_height="12dp"
+        android:layout_gravity="center_horizontal"
+        android:rotation="180"
+        android:background="@drawable/up_arrow_tip"
+        android:backgroundTint="@color/system_secondary"
+        android:importantForAccessibility="no"/>
+</LinearLayout>
diff --git a/res/layout/wallpaper_effects_view2.xml b/res/layout/wallpaper_effects_view2.xml
new file mode 100644
index 0000000..2ddbfe6
--- /dev/null
+++ b/res/layout/wallpaper_effects_view2.xml
@@ -0,0 +1,158 @@
+<?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.
+  -->
+
+<com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:padding="@dimen/wallpaper_info_pane_padding"
+    android:theme="@style/WallpaperPicker.BottomPaneStyle">
+
+    <TextView
+        android:id="@+id/wallpaper_effects_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAlignment="viewStart"
+        android:textAppearance="@style/TitleTextAppearance"
+        android:textColor="?android:textColorPrimary" />
+
+    <TextView
+        android:id="@+id/wallpaper_effects_subtitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/wallpaper_info_pane_subtitle1_top_margin"
+        android:textColor="?android:textColorSecondary"
+        android:textSize="14sp" />
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/wallpaper_info_pane_interaction_top_margin">
+
+        <LinearLayout
+            android:id="@+id/wallpaper_effect_linear_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:clickable="true"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/wallpaper_effect_toggle_title"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:textAlignment="viewStart"
+                android:textColor="?android:textColorSecondary" />
+
+            <Switch
+                android:id="@+id/wallpaper_effect_switch"
+                style="@style/Switch.SettingsLib"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@null"
+                android:clickable="false"
+                android:focusable="false" />
+        </LinearLayout>
+
+        <RelativeLayout
+            android:id="@+id/button_layout"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true">
+
+            <Button
+                android:id="@+id/download_model_button"
+                android:layout_width="@dimen/wallpaper_effect_download_button_width"
+                android:layout_height="@dimen/wallpaper_effect_download_button_height"
+                android:background="@drawable/effect_download_button_background"
+                android:visibility="visible" />
+
+            <LinearLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:elevation="2dp">
+
+                <ImageView
+                    android:layout_width="@dimen/wallpaper_effect_download_image_size"
+                    android:layout_height="@dimen/wallpaper_effect_download_image_size"
+                    android:layout_gravity="center_vertical"
+                    android:src="@drawable/ic_effects_download_24px" />
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:paddingStart="@dimen/wallpaper_effect_download_text_padding_start"
+                    android:text="@string/bottom_action_bar_download"
+                    android:textAppearance="@style/SeparatedTabsTextAppearance"
+                    android:textColor="@color/text_color_on_accent" />
+            </LinearLayout>
+        </RelativeLayout>
+
+        <ProgressBar
+            android:id="@+id/action_progress"
+            android:layout_width="@dimen/wallpaper_effect_downloading_progress_size"
+            android:layout_height="@dimen/wallpaper_effect_downloading_progress_size"
+            android:indeterminateTint="?android:attr/textColorPrimary"
+            android:layout_centerHorizontal="true"
+            android:layout_marginBottom="5dp"
+            android:visibility="visible" />
+
+        <RelativeLayout
+            android:id="@+id/buttons_container"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/wallpaper_effect_failed_container_height"
+            android:visibility="invisible">
+
+            <Button
+                android:id="@+id/open_my_photo_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:text="@string/open_my_photos"
+                android:textColor="@color/color_accent_primary_variant"
+                android:textSize="@dimen/wallpaper_effect_failed_button_size"
+                android:visibility="gone" />
+
+            <Button
+                android:id="@+id/continue_button"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentEnd="true"
+                android:layout_centerVertical="true"
+                android:background="@drawable/effect_continue_button_background"
+                android:gravity="center"
+                android:paddingHorizontal="@dimen/wallpaper_picker_entry_horizontal_padding"
+                android:text="@string/start_rotation_dialog_continue"
+                android:textColor="@color/text_color_primary"
+                android:textSize="@dimen/wallpaper_effect_failed_button_size"
+                android:visibility="gone" />
+
+            <Button
+                android:id="@+id/try_again_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:textColor="@color/color_accent_primary_variant"
+                android:textSize="@dimen/wallpaper_effect_failed_button_size"
+                android:visibility="gone" />
+        </RelativeLayout>
+    </RelativeLayout>
+</com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2>
\ No newline at end of file
diff --git a/res/layout/wallpaper_info_view.xml b/res/layout/wallpaper_info_view.xml
deleted file mode 100644
index 16ee1af..0000000
--- a/res/layout/wallpaper_info_view.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?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.
--->
-<com.android.wallpaper.widget.WallpaperInfoView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:padding="@dimen/wallpaper_info_pane_padding"
-    android:theme="@style/WallpaperPicker.BottomPaneStyle">
-
-    <TextView
-        android:id="@+id/wallpaper_info_title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:lineHeight="24dp"
-        android:textAppearance="@style/TitleTextAppearance"
-        android:textColor="?android:textColorPrimary" />
-
-    <TextView
-        android:id="@+id/wallpaper_info_subtitle1"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/wallpaper_info_pane_subtitle1_top_margin"
-        android:lineHeight="20dp"
-        android:textColor="?android:textColorSecondary"
-        android:textSize="14sp"
-        android:visibility="gone" />
-
-    <TextView
-        android:id="@+id/wallpaper_info_subtitle2"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/wallpaper_info_pane_subtitle2_top_margin"
-        android:lineHeight="20dp"
-        android:textColor="?android:textColorSecondary"
-        android:textSize="14sp"
-        android:visibility="gone" />
-
-    <Button
-        android:id="@+id/wallpaper_info_explore_button"
-        style="@style/ExploreButtonStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/wallpaper_info_pane_explore_button_top_margin"
-        android:text="@string/explore"
-        android:visibility="gone" />
-</com.android.wallpaper.widget.WallpaperInfoView>
diff --git a/res/layout/wallpaper_preview_full.xml b/res/layout/wallpaper_preview_full.xml
deleted file mode 100644
index f2aebf8..0000000
--- a/res/layout/wallpaper_preview_full.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<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">
-    <com.android.wallpaper.picker.preview.ui.view.SystemScaledWallpaperPreviewSurfaceView
-        android:id="@+id/wallpaper_surface"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
-
-    <SurfaceView
-        android:id="@+id/workspace_surface"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
-
-</com.android.wallpaper.picker.preview.ui.view.FullPreviewFrameLayout>
\ No newline at end of file
diff --git a/res/layout/wallpaper_preview_small.xml b/res/layout/wallpaper_preview_small.xml
deleted file mode 100644
index 7f35bf8..0000000
--- a/res/layout/wallpaper_preview_small.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/FullContentPreviewCard"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="true"
-    android:contentDescription="@string/wallpaper_preview_card_content_description">
-
-    <com.android.wallpaper.picker.preview.ui.view.SystemScaledWallpaperPreviewSurfaceView
-        android:id="@+id/wallpaper_surface"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <SurfaceView
-        android:id="@+id/wallpaper_surface_cinematic"
-        android:visibility="gone"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <!-- A 30% opacity black scrim that can be shown to "dim" the wallpaper. -->
-    <View
-        android:id="@+id/wallpaper_dimming_scrim"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/wallpaper_preview_scrim_color"
-        android:visibility="invisible"
-        android:importantForAccessibility="noHideDescendants" />
-
-    <SurfaceView
-        android:id="@+id/workspace_surface"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="invisible"
-        android:importantForAccessibility="noHideDescendants" />
-
-    <FrameLayout
-        android:id="@+id/lock_screen_preview_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:importantForAccessibility="noHideDescendants" />
-
-    <androidx.core.widget.ContentLoadingProgressBar
-        android:id="@+id/wallpaper_preview_spinner"
-        style="?android:progressBarStyleLarge"
-        android:background="@android:color/transparent"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:visibility="gone" />
-
-    <ImageView
-        android:id="@+id/wallpaper_fadein_scrim"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/color_surface"
-        android:forceHasOverlappingRendering="false"
-        android:importantForAccessibility="no"
-        android:visibility="invisible" />
-
-    <ImageView
-        android:id="@+id/loading_view"
-        android:layerType="hardware"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:scaleType="centerCrop"
-        android:importantForAccessibility="no" />
-
-</androidx.cardview.widget.CardView>
diff --git a/res/navigation/wallpaper_preview_nav_graph.xml b/res/navigation/wallpaper_preview_nav_graph.xml
index 68723b5..a6bb666 100644
--- a/res/navigation/wallpaper_preview_nav_graph.xml
+++ b/res/navigation/wallpaper_preview_nav_graph.xml
@@ -29,6 +29,13 @@
             app:destination="@id/setWallpaperDialog" />
     </fragment>
     <fragment
+        android:id="@+id/creativeNewPreviewFragment"
+        android:name="com.android.wallpaper.picker.preview.ui.fragment.CreativeNewPreviewFragment">
+        <action
+            android:id="@+id/action_creativeNewPreviewFragment_to_smallPreviewFragment"
+            app:destination="@+id/smallPreviewFragment" />
+    </fragment>
+    <fragment
         android:id="@+id/fullPreviewFragment"
         android:name="com.android.wallpaper.picker.preview.ui.fragment.FullPreviewFragment">
     </fragment>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index a9f9fe2..8a1324c 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Daaglikse muurpapier"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Tuis- en sluitskerm"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Kies ’n muurpapier"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Skep ’n muurpapier"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Skep muurpapier"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Tuisskerm"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Sluitskerm"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Tuis- en sluitskerm"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Voorskou van tuisskerm se muurpapier"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Die versameling bestaan nie"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Verlaat deelskermmodus en probeer weer"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Stel"</string>
     <string name="cancel" msgid="4970902691067201584">"Kanselleer"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Versteek UI-voorskou"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI word versteek in voorskou. Dubbeltik om te wys"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Stel veranderinge terug?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Jou veranderinge sal nie gestoor word nie"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Nog muurpapiere"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Muurpapier %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Muurpapier"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tik om jou foto te redigeer"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Pas die posisie, skaal en hoek van jou foto\'s aan"</string>
 </resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 4634e71..4d0e868 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"ዕለታዊ ልጣፍ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"መነሻ ገፅ እና የማያ ገፅ ቁልፍ"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ልጣፍ ይምረጡ"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ልጣፍ ይፍጠሩ"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ልጣፍ ይፍጠሩ"</string>
     <string name="home_screen_message" msgid="106444102822522813">"መነሻ ገፅ"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ማያ ገፅ ቁልፍ"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"መነሻ እና ቁልፍ"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"የመነሻ ማያ ገጽ ልጣፍ ቅድመ ዕይታ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ስብስቡ የለም"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"እባክዎ ከየተከፈለ ማያ ገጽ ሁነታ ይውጡ እና እንደገና ይሞክሩ"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"አዋቅር"</string>
     <string name="cancel" msgid="4970902691067201584">"ይቅር"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"የዩአይ ቅድመ-ዕይታን ደብቅ"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"ዩአይ በቅድመ-ዕይታ ውስጥ ተደብቋል። ላለመደበቅ ሁለቴ መታ ያድርጉ"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"ለውጦች ዳግም ይጀመሩ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"የእርስዎ ለውጦች አይቀመጡም"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"ተጨማሪ ልጣፎች"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ልጣፍ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s፣ %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ልጣፍ"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ፎቶዎን ለማርትዕ መታ ያድርጉ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"የፎቶዎችዎን አቀማመጥ፣ ልኬት ለውጥ እና አንግል ያስተካክሉ"</string>
 </resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index a1fb1e5..21586fa 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"خلفية يومية"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"الشاشة الرئيسية وشاشة القفل"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"اختيار خلفية"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"إنشاء خلفية"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"إنشاء خلفية"</string>
     <string name="home_screen_message" msgid="106444102822522813">"الشاشة الرئيسية"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"شاشة القفل"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"الشاشة الرئيسية وشاشة القفل"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"معاينة خلفية الشاشة الرئيسية"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"المجموعة غير متوفرة."</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"يُرجى الخروج من \"وضع تقسيم الشاشة\" ثم إعادة المحاولة."</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"ضبط"</string>
     <string name="cancel" msgid="4970902691067201584">"إلغاء"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"إخفاء معاينة واجهة المستخدم"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"تم إخفاء معاينة واجهة مستخدم. انقر مرّتين للإظهار."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"هل تريد إعادة ضبط التغييرات؟"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"لن يتم حفظ تغييراتك."</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"المزيد من الخلفيات"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"‏الخلفية %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"‏%1$s،‏ %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"الخلفية"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"انقر لتعديل الصورة."</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"يمكنك تعديل موضع الصور وحجمها وزاويتها."</string>
 </resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 283cfc2..f8497f3 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"দৈনিক ৱালপেপাৰ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"গৃহ আৰু লক স্ক্ৰীন"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ৱালপেপাৰ বাছনি কৰক"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ৱালপেপাৰ সৃষ্টি কৰক"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ৱালপেপাৰ সৃষ্টি কৰক"</string>
     <string name="home_screen_message" msgid="106444102822522813">"গৃহ স্ক্ৰীন"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"লক স্ক্ৰীন"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"গৃহ স্ক্ৰীন আৰু লক স্ক্ৰীন"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"গৃহ স্ক্ৰীনৰ ৱালপেপাৰৰ পূৰ্বদৰ্শন"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"এই সংগ্ৰহটোৰ অস্তিত্ব নাই"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"অনুগ্ৰহ কৰি, বিভাজিত-স্ক্ৰীন ম’ডটোৰ পৰা বাহিৰ হৈ পুনৰ চেষ্টা কৰক"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"ছেট কৰক"</string>
     <string name="cancel" msgid="4970902691067201584">"বাতিল কৰক"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UIৰ পূৰ্বদৰ্শন লুকুৱাওক"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"পূর্বদর্শনত UI লুকুওৱা হৈছে। দেখুৱাবলৈ দুবাৰ টিপক"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"সালসলনিসমূহ ৰিছেট কৰিবনে?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"আপোনাৰ সম্পাদনাবোৰ ছেভ কৰা নহ’ব"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"অধিক ৱালপেপাৰ"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ৱালপেপাৰ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ৱালপেপাৰ"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"আপোনাৰ ফট\' সম্পাদনা কৰিবলৈ টিপক"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"স্থান, পৰিমাণ আৰু আপোনাৰ ফট\'ৰ কোণ মিলাওক"</string>
 </resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 28bab64..d206b65 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Günlük divar kağızları"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Əsas səhifə &amp; Ekran kilidi"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Divar kağızı seçin"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Divar kağızı yaradın"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Divar kağızı yaradın"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Əsas ekran"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Ekran kilidi"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Əsas səhifə və Kilid"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Əsas ekranda divar kağızı önizləməsi"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Kolleksiya mövcud deyil"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Bölünmüş ekran rejimindən çıxıb, yenidən cəhd edin"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Ayarlayın"</string>
     <string name="cancel" msgid="4970902691067201584">"Ləğv edin"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI Önizləməsini gizlədin"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI önizləmədə gizlədilib. Göstərmək üçün iki dəfə toxunun"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Dəyişikliklər sıfırlansın?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Dəyişiklikləriniz yadda saxlanılmayacaq"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Digər divar kağızları"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Divar kağızı %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Divar kağızı"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Toxunaraq fotonu redaktə edin"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Fotoların mövqe, miqyas və bucağını tənzimləyin"</string>
 </resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index d3907ad..847506f 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -30,13 +30,13 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dnevna pozadina"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Početni i zaključani ekran"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Odaberite pozadinu"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Napravite pozadinu"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Napravite pozadinu"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Početni ekran"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Zaključan ekran"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Početni i zaključani ekran"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"Podesite pozadinu na"</string>
     <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"Početni ekran"</string>
-    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Zaključan ekran"</string>
+    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Zaključani ekran"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"Početni i zaključani ekran"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"Rotirajuća pozadina sa slikom"</string>
     <string name="permission_needed_explanation" msgid="139166837541426823">"Da bi se aktuelna pozadina prikazivala ovde, aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> treba da ima pristup memorijskom prostoru na uređaju."</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Prikaz pozadine početnog ekrana"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Kolekcija ne postoji"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Napustite režim podeljenog ekrana i probajte ponovo"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Podesi"</string>
     <string name="cancel" msgid="4970902691067201584">"Otkaži"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Sakrij korisnički interfejs"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Krijemo korisnič. interfejs. Otkrijte u dva dodira"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Želite da resetujete promene?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Promene neće biti sačuvane"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Još pozadina"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Pozadina %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Pozadina"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Dodirnite da biste izmenili sliku"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Prilagodite položaj, razmeru i ugao slike"</string>
 </resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index b6fadf5..e4e7d04 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Шпалеры на кожны дзень"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Галоўная старонка і экран блакіроўкі"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Выбраць шпалеры"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Стварыць шпалеры"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Стварыць шпалеры"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Галоўны экран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Экран блакіроўкі"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Стандартна"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Перадпрагляд шпалер галоўнага экрана"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Калекцыя не існуе"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Выйдзіце з рэжыму падзеленага экрана і паўтарыце спробу"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Задаць"</string>
     <string name="cancel" msgid="4970902691067201584">"Скасаваць"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Схаваць перадпрагляд UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Інтэрфейс схаваны. Двойчы націсніце, каб убачыць"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Скінуць змяненні?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Вашы змяненні не будуць захаваны"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Дадатковыя шпалеры"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Шпалеры – %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Шпалеры"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Націсніце, каб змяніць фота"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Адкарэкціруйце пазіцыю, маштаб і вугал нахілу сваіх фота"</string>
 </resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 02a6059..df706e3 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Тапет за деня"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Начален и заключен екран"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Избиране на тапет"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Създаване на тапет"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Създаване на тапет"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Начален екран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Заключен екран"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Начален и заключен екран"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Визуализация на тапета на началния екран"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Колекцията не съществува"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Излезте от режима за разделен екран и опитайте отново"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Задаване"</string>
     <string name="cancel" msgid="4970902691067201584">"Отказ"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Скриване на визуал. на ПИ"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"ПИ е скрит във визуализацията. Докоснете два пъти за показване."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Да се нулират ли промените?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Промените ви няма да бъдат запазени"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Още тапети"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Тапет %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Тапет"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Докоснете, за да редактирате снимката си"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Коригирайте позицията, мащаба и ъгъла на снимките си"</string>
 </resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index a242b42..707487c 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"প্রতিদিনের ওয়ালপেপার"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"হোম ও লক স্ক্রিন"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ওয়ালপেপার বেছে নিন"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ওয়ালপেপার তৈরি করুন"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ওয়ালপেপার তৈরি করুন"</string>
     <string name="home_screen_message" msgid="106444102822522813">"হোম স্ক্রিন"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"লক স্ক্রিন"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"হোম ও লক"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"হোম স্ক্রিন ওয়ালপেপার প্রিভিউ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"কালেকশন উপলভ্য নেই"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"\'স্প্লিট স্ক্রিন\' মোড থেকে বেরিয়ে আবার চেষ্টা করুন"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"সেট করুন"</string>
     <string name="cancel" msgid="4970902691067201584">"বাতিল করুন"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI প্রিভিউ লুকান"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"প্রিভিউতে UI লুকানো হয়েছে। দেখাতে ডবল ট্যাপ করুন"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"পরিবর্তন রিসেট করবেন?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"আপনার করা পরিবর্তন সেভ করা হবে না"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"আরও ওয়ালপেপার"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ওয়ালপেপার %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ওয়ালপেপার"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"আপনার ফটো এডিট করতে ট্যাপ করুন"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"আপনার ফটোর পজিশন, স্কেল ও কোণ অ্যাডজাস্ট করুন"</string>
 </resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 9ee36c1..38e2d6e 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dnevna pozadinska slika"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Početni ekran i zaključani ekran"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Odaberite pozadinsku sliku"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Kreirajte pozadinsku sliku"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Kreirajte pozadinsku sliku"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Početni ekran"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Zaključavanje ekrana"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Početni i zaključani ekran"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Pregled pozadinske slike na početnom ekranu"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Kolekcija ne postoji"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Izađite iz načina rada podijeljenog ekrana i pokušajte ponovo"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Postavi"</string>
     <string name="cancel" msgid="4970902691067201584">"Otkaži"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Sakrij pregled UI-a"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI skriven u pregledu. Dodirnite dvaput da otkrijete"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Poništiti izmjene?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Vaše izmjene se neće sačuvati"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Više pozadinskih slika"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Pozadinska slika %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Pozadinska slika"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Dodirnite da uredite fotografiju"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Podesite položaj, razmjer i ugao fotografija"</string>
 </resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 9be4522..e03efb4 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Fons de pantalla diari"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Pantalla d\'inici i de bloqueig"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Tria un fons de pantalla"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Crea un fons de pantalla"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Crea un fons de pantalla"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Pantalla d\'inici"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Pantalla de bloqueig"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Pantalla d\'inici i de bloqueig"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Previsualització del fons de pantalla d\'inici"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"La col·lecció no existeix"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Surt del mode de pantalla dividida i torna-ho a provar"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Defineix"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancel·la"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Amaga la previsualització de IU"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"IU amagada a la prev. Doble toc per deixar d\'amagar."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Vols restablir els canvis?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Els teus canvis no es desaran"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Més fons de pantalla"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fons de pantalla %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fons de pantalla"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Toca per editar la foto"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajusta la posició, l\'escala i l\'angle de les fotos"</string>
 </resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index c891e9d..0285c47 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Denní tapeta"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Plocha a obrazovka uzamčení"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Vyberte tapetu"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Vytvořte tapetu"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Vytvoření tapety"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Plocha"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Obrazovka uzamčení"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Plocha a uzamknutí"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Náhled tapety na ploše"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Sbírka neexistuje"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Ukončete režim rozdělené obrazovky a zkuste to znovu"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Nastavit"</string>
     <string name="cancel" msgid="4970902691067201584">"Zrušit"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Skrýt náhled rozhraní"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"V náhledu je skryto uživatelské rozhraní. Zobrazíte ho dvojitým klepnutím."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Resetovat změny?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Změny nebudou uloženy"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Více tapet"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Tapeta %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Tapeta"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Klepněte na fotku a upravte ji"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Upravte pozici, měřítko a úhel fotek"</string>
 </resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 65ef3f7..3f503e4 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Daglig baggrund"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Start- og låseskærm"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Vælg en baggrund"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Opret en baggrund"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Opret baggrund"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Startskærm"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Låseskærm"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Start- og låseskærm"</string>
@@ -45,7 +45,7 @@
     <string name="no_backup_image_wallpaper_description" msgid="8303268619408738057">"Animeret baggrundstjeneste til skiftende baggrunde"</string>
     <string name="daily_refresh_tile_title" msgid="3270456074558525091">"Daglig baggrund"</string>
     <string name="daily_refresh_tile_subtitle" msgid="3976682014885446443">"Tryk for at aktivere"</string>
-    <string name="start_rotation_dialog_body_live_wallpaper_needed" msgid="5132580257563846082">"Baggrunden skifter automatisk hver dag. Tryk på &lt;strong&gt;Angiv baggrund&lt;/strong&gt; på næste skærmbillede for at afslutte konfigurationen."</string>
+    <string name="start_rotation_dialog_body_live_wallpaper_needed" msgid="5132580257563846082">"Baggrunden skifter automatisk hver dag. Tryk på &lt;strong&gt;Angiv baggrund&lt;/strong&gt; på næste skærm for at afslutte konfigurationen."</string>
     <string name="start_rotation_dialog_wifi_only_option_message" msgid="3126269859713666225">"Download kun fremtidige baggrunde via Wi-Fi"</string>
     <string name="start_rotation_dialog_continue" msgid="276678987852274872">"Fortsæt"</string>
     <string name="start_rotation_progress_message" msgid="7872623873682262083">"Downloader den første baggrund…"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Forhåndsvisning af startskærmens baggrund"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Samlingen eksisterer ikke"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Afslut opdelt skærm, og prøv igen"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Angiv"</string>
     <string name="cancel" msgid="4970902691067201584">"Annuller"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Skjul forhåndsvisning af brugerflade"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Brugerfladen er skjult i forhåndsvisning. Tryk to gange for at vise den."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Vil du nulstille ændringerne?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Dine ændringer gemmes ikke"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Flere baggrunde"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Baggrund %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Baggrund"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tryk for at redigere dit billede"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Juster dine billeders position, skalering og vinkel"</string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index e2b50c4..8501057 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Täglicher Hintergrund"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Startbildschirm &amp; Sperrbildschirm"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Hintergrund auswählen"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Hintergrund erstellen"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Hintergrund erstellen"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Startbildschirm"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Sperrbildschirm"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Startbildschirm &amp; Sperrbildschirm"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Vorschau für Startbildschirmhintergrund"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Die Sammlung existiert nicht"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Bitte beende den Splitscreen-Modus und versuch es noch einmal"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Festlegen"</string>
     <string name="cancel" msgid="4970902691067201584">"Abbrechen"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI-Vorschau ausblenden"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI in der Vorschau ausgeblendet. Zum Einblenden doppeltippen."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Änderungen zurücksetzen?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Änderungen werden nicht gespeichert."</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Weitere Hintergrundbilder"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Hintergrund %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Hintergrund"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tippen, um das Foto zu bearbeiten"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Position, Maßstab und Winkel von Fotos anpassen"</string>
 </resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index e5960f1..afcb36a 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Ημερήσια ταπετσαρία"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Αρχική οθόνη και οθόνη κλειδώματος"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Επιλέξτε μια ταπετσαρία"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Δημιουργήστε μια ταπετσαρία"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Δημιουργία ταπετσαρίας"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Αρχική οθόνη"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Οθόνη κλειδώματος"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Αρχική και κλειδώματος"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Προεπισκόπηση ταπετσαρίας αρχικής οθόνης"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Η συλλογή δεν υπάρχει."</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Βγείτε από τη λειτουργία διαχωρισμού οθόνης και δοκιμάστε ξανά"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Ορισμός"</string>
     <string name="cancel" msgid="4970902691067201584">"Ακύρωση"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Απόκρυψη προεπ/σης διεπ.χρήστη"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Η διεπαφή χρήστη είναι κρυφή σε προεπισκόπηση. Διπλό πάτημα για κατάργηση απόκρυψης"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Να γίνει επαναφορά αλλαγών;"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Οι αλλαγές σας δεν θα αποθηκευτούν"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Περισσότερες ταπετσαρίες"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Ταπετσαρία %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Ταπετσαρία"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Πατήστε για να επεξεργαστείτε τη φωτογραφία σας"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Προσαρμόστε τη θέση, την κλίμακα και τη γωνία των φωτογραφιών σας"</string>
 </resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 1489217..f3dca5e 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Daily wallpaper"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Home &amp; Lock screen"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Choose a wallpaper"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Create a wallpaper"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Create wallpaper"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Home screen"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lock screen"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Home &amp; Lock"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Home screen wallpaper preview"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"The collection doesn\'t exist"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Please exit split screen mode and try again"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Set"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancel"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Hide UI preview"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI is hidden in preview. Double-tap to unhide"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Reset changes?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Your changes won\'t be saved"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"More wallpapers"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Wallpaper %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Wallpaper"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tap to edit your photo"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Adjust the position, scale and angle of your photos"</string>
 </resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 5c73531..e9bec55 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -32,7 +32,7 @@
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Home &amp; Lock screen"</string>
     <!-- no translation found for choose_a_wallpaper_section_title (1009823506890453891) -->
     <skip />
-    <!-- no translation found for creative_wallpaper_title (8459226435723103934) -->
+    <!-- no translation found for creative_wallpaper_title (3581650238648981372) -->
     <skip />
     <string name="home_screen_message" msgid="106444102822522813">"Home screen"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lock screen"</string>
@@ -115,6 +115,8 @@
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"The collection doesn\'t exist"</string>
     <!-- no translation found for wallpaper_exit_split_screen (1928870664619591636) -->
     <skip />
+    <!-- no translation found for set_wallpaper_dialog_set_button (5760149969510325088) -->
+    <skip />
     <string name="cancel" msgid="4970902691067201584">"Cancel"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Hide UI preview"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI is hidden in preview. Double-tap to unhide"</string>
@@ -152,6 +154,12 @@
     <skip />
     <!-- no translation found for more_wallpapers (8116268433411881705) -->
     <skip />
-    <!-- no translation found for recent_wallpaper_label (3996353584371118367) -->
+    <!-- no translation found for recents_wallpaper_label (8653165542635660222) -->
+    <skip />
+    <!-- no translation found for default_wallpaper_title (2541071182656978180) -->
+    <skip />
+    <!-- no translation found for small_preview_tooltip (1920430079013352071) -->
+    <skip />
+    <!-- no translation found for full_preview_tooltip (4648994028015322759) -->
     <skip />
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 1489217..f3dca5e 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Daily wallpaper"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Home &amp; Lock screen"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Choose a wallpaper"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Create a wallpaper"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Create wallpaper"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Home screen"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lock screen"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Home &amp; Lock"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Home screen wallpaper preview"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"The collection doesn\'t exist"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Please exit split screen mode and try again"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Set"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancel"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Hide UI preview"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI is hidden in preview. Double-tap to unhide"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Reset changes?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Your changes won\'t be saved"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"More wallpapers"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Wallpaper %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Wallpaper"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tap to edit your photo"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Adjust the position, scale and angle of your photos"</string>
 </resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 1489217..f3dca5e 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Daily wallpaper"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Home &amp; Lock screen"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Choose a wallpaper"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Create a wallpaper"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Create wallpaper"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Home screen"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lock screen"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Home &amp; Lock"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Home screen wallpaper preview"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"The collection doesn\'t exist"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Please exit split screen mode and try again"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Set"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancel"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Hide UI preview"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI is hidden in preview. Double-tap to unhide"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Reset changes?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Your changes won\'t be saved"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"More wallpapers"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Wallpaper %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Wallpaper"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tap to edit your photo"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Adjust the position, scale and angle of your photos"</string>
 </resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index fe1a5f4..bfefc9d 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎Daily wallpaper‎‏‎‎‏‎"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎Home &amp; Lock screen‎‏‎‎‏‎"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎Choose a Wallpaper‎‏‎‎‏‎"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‎‎Create a Wallpaper‎‏‎‎‏‎"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎Create wallpaper‎‏‎‎‏‎"</string>
     <string name="home_screen_message" msgid="106444102822522813">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎Home screen‎‏‎‎‏‎"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‏‎Lock screen‎‏‎‎‏‎"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎Home &amp; Lock‎‏‎‎‏‎"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎Home screen wallpaper preview‎‏‎‎‏‎"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‏‎‎The collection doesn\'t exist‎‏‎‎‏‎"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎Please exit split screen mode and try again‎‏‎‎‏‎"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎Set‎‏‎‎‏‎"</string>
     <string name="cancel" msgid="4970902691067201584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎Cancel‎‏‎‎‏‎"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‎Hide UI Preview‎‏‎‎‏‎"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‎UI is hidden in preview. Double tap to unhide‎‏‎‎‏‎"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎Reset changes?‎‏‎‎‏‎"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎Your changes won\'t be saved‎‏‎‎‏‎"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎More wallpapers‎‏‎‎‏‎"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎Wallpaper %1$s‎‏‎‎‏‎"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎%1$s, %2$d‎‏‎‎‏‎"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎Wallpaper‎‏‎‎‏‎"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎Tap to edit your photo‎‏‎‎‏‎"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‎Adjust the position, scale, and angle of your photos‎‏‎‎‏‎"</string>
 </resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 5c41ab0..5308783 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -21,7 +21,7 @@
     <!-- no translation found for app_name (8773648973927541493) -->
     <skip />
     <string name="select_wallpaper_label" msgid="6989581259339646085">"Categorías de fondos de pantalla"</string>
-    <string name="set_wallpaper_button_text" msgid="5445978864530156290">"Definir como fondo de pantalla"</string>
+    <string name="set_wallpaper_button_text" msgid="5445978864530156290">"Definir fondo de pantalla"</string>
     <string name="set_wallpaper_progress_message" msgid="7986528287618716715">"Estableciendo como fondo de pantalla…"</string>
     <string name="try_again" msgid="8278874823700921234">"Reintentar"</string>
     <string name="set_wallpaper_error_message" msgid="6819986999041085130">"No se pudo establecer como fondo de pantalla."</string>
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Fondo de pantalla diario"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Pantalla principal y de bloqueo"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Elige un fondo de pantalla"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Crea un fondo de pantalla"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Crea un fondo de pantalla"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Pantalla principal"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Pantalla de bloqueo"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Pantalla principal y bloqueada"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Vista previa del fondo de pantalla de la pantalla principal"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"La colección no existe"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Sal del modo de pantalla dividida y vuelve a intentarlo"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Definir"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancelar"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ocultar vista previa de la IU"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"IU oculta en vista previa; pres. 2 veces para ver"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"¿Restablecer los cambios?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"No se guardarán los cambios"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Más fondos de pantalla"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fondo de pantalla %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fondo de pantalla"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Presionar para editar tu foto"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajustar la posición, la escala y el ángulo de tus fotos"</string>
 </resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 4983ace..d3a6bce 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Fondo de pantalla diario"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Pantalla de inicio y bloqueo"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Elige un fondo de pantalla"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Crea un fondo de pantalla"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Crear fondo de pantalla"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Pantalla de inicio"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Pantalla de bloqueo"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Inicio y bloqueo"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Vista previa del fondo de pantalla de inicio"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"La colección no existe"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Sal del modo Pantalla dividida y vuelve a intentarlo"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Seleccionar"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancelar"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ocultar vista previa de UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI oculta en la vista previa. Toca dos veces para mostrar."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"¿Revertir cambios?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Tus cambios no se guardarán"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Más fondos de pantalla"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fondo de pantalla %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fondo de pantalla"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Toca para editar tu foto"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajusta la posición, la escala y el ángulo de tus fotos"</string>
 </resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 145f849..5ab6284 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -30,12 +30,12 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Päeva taustapilt"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Ava- ja lukustuskuva"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Taustapildi valimine"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Taustapildi loomine"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Taustapildi loomine"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Avaekraan"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lukustuskuva"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Avaekraan ja lukustuskuva"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"Määra taustapildiks:"</string>
-    <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"Avaekraan"</string>
+    <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"Avakuva"</string>
     <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Lukustuskuva"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"Ava- ja lukustuskuva"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"Vahelduva kujutisega taustapilt"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Avakuva taustapildi eelvaade"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Kogu pole olemas"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Väljuge poolitatud ekraani režiimist ja proovige uuesti"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Määra"</string>
     <string name="cancel" msgid="4970902691067201584">"Tühista"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Peida kasutajaliidese eelvaade"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Kasutajaliides on eelvaates peidetud. Topeltpuudutage kuvamiseks."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Kas lähtestada muudatused?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Muudatusi ei salvestata"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Rohkem taustapilte"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Taustapilt %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Taustapilt"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Puudutage oma foto muutmiseks"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Reguleerige oma fotode asendit, mõõtmeid ja nurka"</string>
 </resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 692ba03..f3720bf 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -30,12 +30,12 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Eguneko horma-papera"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Hasieran eta pantaila blokeatuan"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Hautatu horma-paper bat"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Sortu horma-paper bat"</string>
-    <string name="home_screen_message" msgid="106444102822522813">"Hasierako pantaila"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Sortu horma-papera"</string>
+    <string name="home_screen_message" msgid="106444102822522813">"Orri nagusia"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Pantaila blokeatua"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Hasieran + pantaila blokeatuan"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"Ezarri horma-papera"</string>
-    <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"Hasierako pantaila"</string>
+    <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"Orri nagusia"</string>
     <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Pantaila blokeatua"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"Hasierako pantaila eta pantaila blokeatua"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"Txandakako irudidun horma-papera"</string>
@@ -58,13 +58,13 @@
     <string name="wallpaper_disabled_by_administrator_message" msgid="1551430406714747884">"Gailuaren administratzaileak desgaituta dauka horma-papera ezartzeko aukera"</string>
     <string name="wallpaper_set_successfully_message" msgid="2958998799111688578">"Ezarri da horma-papera"</string>
     <string name="wallpapers_unavailable_offline_message" msgid="8136405438621689532">"Internetera konektatu behar duzu horma-paperak ikusteko. Konekta zaitez eta saiatu berriro."</string>
-    <string name="currently_set_home_wallpaper_thumbnail" msgid="4022381436821898917">"Hasierako pantailan ezarrita dagoen horma-paperaren irudi txikia"</string>
+    <string name="currently_set_home_wallpaper_thumbnail" msgid="4022381436821898917">"Orri nagusian ezarrita dagoen horma-paperaren irudi txikia"</string>
     <string name="currently_set_lock_wallpaper_thumbnail" msgid="2094209303934569997">"Pantaila blokeatuan ezarrita dagoen horma-paperaren irudi txikia"</string>
     <string name="currently_set_wallpaper_thumbnail" msgid="8651887838745545107">"Ezarrita dagoen horma-paperaren irudi txikia"</string>
     <string name="wallpaper_thumbnail" msgid="569931475923605974">"Horma-paperaren irudi txikia"</string>
-    <string name="explore_home_screen" msgid="8756346794535765482">"Arakatu hasierako pantailaren horma-papera"</string>
+    <string name="explore_home_screen" msgid="8756346794535765482">"Arakatu orri nagusiaren horma-papera"</string>
     <string name="explore_lock_screen" msgid="268938342103703665">"Arakatu pantaila blokeatuaren horma-papera"</string>
-    <string name="refresh_daily_wallpaper_home_content_description" msgid="2770445044556164259">"Freskatu hasierako pantailaren eguneko horma-papera"</string>
+    <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>
     <string name="refreshing_daily_wallpaper_dialog_message" msgid="1975910873362855761">"Eguneko horma-papera freskatzen…"</string>
@@ -101,9 +101,10 @@
     <string name="wallpaper_title" msgid="6754214682228331092">"Horma-papera"</string>
     <string name="wallpaper_preview_card_content_description" msgid="6049261033541034584">"Horma-paperaren aurrebista"</string>
     <string name="lock_wallpaper_preview_card_content_description" msgid="5236839857695985498">"Pantaila blokeatuko horma-paperaren aurrebista"</string>
-    <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Hasierako pantailako horma-paperaren aurrebista"</string>
+    <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Orri nagusiko horma-paperaren aurrebista"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Ez dago bildumarik"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Irten pantaila zatituaren modutik eta saiatu berriro"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Ezarri"</string>
     <string name="cancel" msgid="4970902691067201584">"Utzi"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ezkutatu EIaren aurrebista"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Interfazea ezkutatuta dago aurrebistan. Ager dadin, sakatu pantaila birritan."</string>
@@ -125,10 +126,13 @@
     <string name="settings_snackbar_enable" msgid="5992112808061426068">"Gaitu"</string>
     <string name="open_my_photos" msgid="4107196465713868381">"Ireki nire argazkiak"</string>
     <string name="lock_screen_tab" msgid="6672930765010407652">"Pantaila blokeatua"</string>
-    <string name="home_screen_tab" msgid="1080445697837877526">"Hasierako pantaila"</string>
+    <string name="home_screen_tab" msgid="1080445697837877526">"Orri nagusia"</string>
     <string name="reset" msgid="4945445169532850631">"Berrezarri"</string>
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Aldaketak berrezarri?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Ez dira gordeko aldaketak"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Horma-paper gehiago"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"%1$s horma-papera"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Horma-papera"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Sakatu hau argazkia editatzeko"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Doitu argazkien posizioa, eskala eta angelua"</string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index d5acceb..22b1547 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"کاغذ‌دیواری روزانه"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"صفحه اصلی و صفحه قفل"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"انتخاب کاغذدیواری"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ایجاد کاغذدیواری"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ساخت کاغذدیواری"</string>
     <string name="home_screen_message" msgid="106444102822522813">"صفحه اصلی"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"صفحه در حالت قفل"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"صفحه اصلی و صفحه در حالت قفل"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"پیش‌نمای کاغذدیواری صفحه اصلی"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"مجموعه وجود ندارد"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"لطفاً از حالت صفحه تقسیم‌شده خارج شوید و دوباره امتحان کنید"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"تنظیم"</string>
     <string name="cancel" msgid="4970902691067201584">"لغو"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"پنهان کردن پیش‌نمای رابط کاربری"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"رابط در پیش‌دید پنهان است. دوضربه برای نمایش مجدد"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"تغییرات بازنشانی شود؟"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"تغییرات شما ذخیره نخواهد شد"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"کاغذدیواری‌های بیشتر"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"‏کاغذدیواری %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"‏%1$s،‏ %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"کاغذدیواری"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"برای ویرایش عکس ضربه بزنید"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"موقعیت، مقیاس، و زاویه عکس‌هایتان را تنظیم کنید"</string>
 </resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 9c136f6..2cf1c7f 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Päivän taustakuva"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Aloitus- ja lukitusnäyttö"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Valitse taustakuva"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Luo taustakuva"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Luo taustakuva"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Aloitusnäyttö"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lukitusnäyttö"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Aloitus- ja lukitusnäyttö"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Aloitusnäytön taustakuvan esikatselu"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Kyseistä kokoelmaa ei ole olemassa"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Sulje jaettu näyttö ja yritä uudelleen"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Valitse"</string>
     <string name="cancel" msgid="4970902691067201584">"Peru"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Piilota UI:n esikatselu"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI on piilotettu. Näytä kaksoisnapauttamalla"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Nollataanko muutokset?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Muutoksia ei tallenneta"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Lisää taustakuvia"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Taustakuva %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Taustakuva"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Muokkaa kuvaa napauttamalla"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Säädä kuvien paikkaa, mittakaavaa ja kulmaa"</string>
 </resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 71b0bfd..cf4a84e 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Fond d\'écran quotidien"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Écrans d\'accueil et de verrouillage"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Choisir un fond d\'écran"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Créer un fond d\'écran"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Créer un fond d\'écran"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Écran d\'accueil"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Écran de verrouillage"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Écr. d\'accueil et de verrouill."</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Aperçu du fond d\'écran de l\'écran d\'accueil"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"La collection n\'existe pas"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Veuillez quitter le mode d\'écran partagé et réessayer"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Définir"</string>
     <string name="cancel" msgid="4970902691067201584">"Annuler"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Masquer l\'aperçu de l\'IU"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Aperçu : IU masquée. Touchez 2 fois pour afficher"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Réinitialiser les modifications?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Vos modifications ne seront pas enregistrées"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Plus de fonds d\'écran"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fonds d\'écran %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fond d\'écran"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Toucher pour modifier votre photo"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajuster la position, l\'échelle et l\'angle de vos photos"</string>
 </resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 40256e5..ad665fe 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Fond d\'écran quotidien"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Écran d\'accueil et écran de verrouillage"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Choisir un fond d\'écran"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Créer un fond d\'écran"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Créer un fond d\'écran"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Écran d\'accueil"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Écran de verrouillage"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Accueil et verrouillage"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Aperçu du fond d\'écran d\'accueil"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Cette collection n\'existe pas"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Veuillez quitter le mode Écran partagé et réessayer"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Définir"</string>
     <string name="cancel" msgid="4970902691067201584">"Annuler"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Masquer l\'aperçu de l\'UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI masquée dans aperçu. Appuyez 2 fois pour afficher"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Réinitialiser les modifications ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Vos modifications ne seront pas enregistrées"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Autres fonds d\'écran"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fonds d\'écran %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fond d\'écran"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Appuyez pour modifier votre photo"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajustez la position, l\'échelle et l\'angle de vos photos"</string>
 </resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 7aa0db4..ce8f5da 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Fondo de pantalla diario"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Pantallas de inicio e bloqueo"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Escolle un fondo de pantalla"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Crear un fondo de pantalla"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Crear fondo de pantalla"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Pantalla de inicio"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Pantalla de bloqueo"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Pantallas de inicio e bloqueo"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Vista previa do fondo da pantalla de inicio"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"A colección non existe"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Sae do modo de pantalla dividida e téntao de novo"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Definir"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancelar"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ocultar vista previa da IU"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"IU oculta: vista previa. Toca dúas veces para vela"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Queres restablecer os cambios?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Non se gardarán os cambios"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Máis fondos de pantalla"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fondo de pantalla %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fondo de pantalla"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tocar a foto para editala"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Axustar a posición, a escala e o ángulo das fotos"</string>
 </resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 8e4722d..d6e27de 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"દૈનિક વૉલપેપર"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"હોમ અને લૉક સ્ક્રીન"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"વૉલપેપર પસંદ કરો"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"વૉલપેપર બનાવો"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"વૉલપેપર બનાવો"</string>
     <string name="home_screen_message" msgid="106444102822522813">"હોમ સ્ક્રીન"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"લૉક સ્ક્રીન"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"હોમ અને લૉક"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"હોમ સ્ક્રીનના વૉલપેપરનો પ્રીવ્યૂ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"સંગ્રહ અસ્તિત્વમાં નથી"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"કૃપા કરીને સ્ક્રીન-વિભાજન મોડમાંથી બહાર નીકળો અને ફરીથી પ્રયાસ કરો"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"સેટ કરો"</string>
     <string name="cancel" msgid="4970902691067201584">"રદ કરો"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UIનો પ્રીવ્યૂ છુપાવો"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"પ્રીવ્યૂમાં UI છુપાવેલું છે. બતાવવા બે વાર ટૅપ કરો"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"ફેરફારો રીસેટ કરીએ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"તમારા ફેરફારો સાચવવામાં આવશે નહીં"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"વધુ વૉલપેપર"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"વૉલપેપર %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"વૉલપેપર"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"તમારા ફોટામાં ફેરફાર કરવા માટે ટૅપ કરો"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"તમારા ફોટાની જગ્યા, સ્કેલ અને ખૂણાની ગોઠવણી કરો"</string>
 </resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index d268a5b..a824c90 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"रोज़ वॉलपेपर बदलने की सुविधा"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"होम स्क्रीन और लॉक स्क्रीन पर"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"कोई वॉलपेपर चुनें"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"कोई वॉलपेपर बनाएं"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"वॉलपेपर बनाएं"</string>
     <string name="home_screen_message" msgid="106444102822522813">"होम स्क्रीन"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"लॉक स्‍क्रीन"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"होम स्क्रीन और लॉक स्क्रीन पर"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"होम स्क्रीन पर दिखने वाले वॉलपेपर की झलक"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"वॉलपेपर का संग्रह मौजूद नहीं है"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"दो-स्क्रीन मोड को बंद करके दोबारा कोशिश करें"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"सेट करें"</string>
     <string name="cancel" msgid="4970902691067201584">"रद्द करें"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"यूज़र इंटरफ़ेस की झलक छिपाएं"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"झलक में यूआई को छिपाया गया. इसे दिखाने के लिए दो बार टैप करें"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"क्या आपको बदलाव रीसेट करने हैं?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"आपके बदलाव सेव नहीं किए जाएंगे"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"कुछ और वॉलपेपर"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"वॉलपेपर %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"वॉलपेपर"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"फ़ोटो में बदलाव करने के लिए उस पर टैप करें"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"फ़ोटो को अडजस्ट करें, स्केल करें, और उसे सही ऐंगल पर लाएं"</string>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 0a876c0..0f8057b 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dnevna pozadina"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Početni i zaključani zaslon"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Odaberite pozadinu"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Izradite pozadinu"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Izradi pozadinu"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Početni zaslon"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Zaključani zaslon"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Početni i zaključani zaslon"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Pregled pozadine početnog zaslona"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Zbirka ne postoji"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Izađite iz načina podijeljenog zaslona i pokušajte ponovno"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Postavi"</string>
     <string name="cancel" msgid="4970902691067201584">"Odustani"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Sakrij pregled koris. sučelja"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Kor. sučelje skriveno je u pregledu. Dvaput dodirnite za otkrivanje"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Poništiti promjene?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Promjene se neće spremiti"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Više pozadina"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Pozadina %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Pozadina"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Dodirnite da biste uredili fotografiju"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Prilagodite položaj, skaliranje i kut fotografija"</string>
 </resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 3e5f88b..fe8312c 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Napi háttérkép"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Kezdő- és lezárási képernyő"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Háttérkép kiválasztása"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Háttérkép létrehozása"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Háttérkép létrehozása"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Kezdőképernyő"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lezárási képernyő"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Kezdő- és lezárási képernyő"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Kezdőképernyő háttérképének előnézete"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Nincs ilyen gyűjtemény"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Lépjen ki az osztott képernyős módból, és próbálja újra"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Beállítás"</string>
     <string name="cancel" msgid="4970902691067201584">"Mégse"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI előnézetének elrejtése"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI: rejtve előnézetben. Felfedés: dupla koppintás."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Visszavonja a módosításokat?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"A módosítások nem lesznek mentve"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"További hátterek"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Háttérképek %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Háttérkép"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Koppintson fotója szerkesztéséhez"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Korrigálhatja fotói pozícióját, méretét és szögét"</string>
 </resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index bc9de77..3f77e87 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Օրվա պաստառ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Հիմնական էկրան և կողպէկրան"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Ընտրեք պաստառ"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Ստեղծեք պաստառ"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Պաստառի ստեղծում"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Հիմնական էկրան"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Կողպէկրան"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Հիմնական էկրան և կողպէկրան"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Հիմնական էկրանի պաստառի նախադիտում"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Հավաքածուն գոյություն չունի"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Դուրս եկեք էկրանի տրոհման ռեժիմից և նորից փորձեք"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Կարգավորել"</string>
     <string name="cancel" msgid="4970902691067201584">"Չեղարկել"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Թաքցնել նախադիտման էկրանը"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Հպեք՝ նախադիտման էկրանը ցուցադրելու համար"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Զրոյացնե՞լ փոփոխությունները"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Ձեր փոփոխությունները չեն պահվի"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Այլ պաստառներ"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Պաստառ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Պաստառ"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Հպեք՝ ձեր լուսանկարը փոփոխելու համար"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ճշգրտեք լուսանկարների դիրքը, մասշտաբը և անկյունը"</string>
 </resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index fdc1820..8d5caa9 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Wallpaper harian"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Layar utama &amp; layar kunci"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Pilih Wallpaper"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Buat Wallpaper"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Buat wallpaper"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Layar utama"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Layar kunci"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Beranda &amp; Layar Kunci"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Pratinjau wallpaper layar utama"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Koleksi tidak ada"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Keluar dari mode layar terpisah, lalu coba lagi"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Setel"</string>
     <string name="cancel" msgid="4970902691067201584">"Batal"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Sembunyikan Pratinjau UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI disembunyikan di pratinjau. Ketuk dua kali untuk menampilkan"</string>
@@ -129,6 +130,9 @@
     <string name="reset" msgid="4945445169532850631">"Reset"</string>
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Reset perubahan?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Perubahan tidak akan disimpan"</string>
-    <string name="more_wallpapers" msgid="8116268433411881705">"Wallpaper lainnya"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Wallpaper %1$s"</string>
+    <string name="more_wallpapers" msgid="8116268433411881705">"Wallpaper lain"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Wallpaper"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Ketuk untuk mengedit foto Anda"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Sesuaikan posisi, skala, dan sudut foto Anda"</string>
 </resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index e2e115f..2c88685 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Daglegt veggfóður"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Heima- og lásskjár"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Veldu veggfóður"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Búðu til veggfóður"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Búa til veggfóður"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Heimaskjár"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lásskjár"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Heima- og lásskjár"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Forskoðun veggfóðurs á heimaskjá"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Safnið er ekki til"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Lokaðu skjáskiptingu og reyndu aftur"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Velja"</string>
     <string name="cancel" msgid="4970902691067201584">"Hætta við"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Fela forskoðun notendaviðmóts"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Notendaviðmót falið í forskoðun. Ýttu tvisvar til að sýna"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Endurstilla breytingar?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Breytingarnar verða ekki vistaðar"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Fleiri veggfóður"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Veggfóður %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Veggfóður"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Ýttu til að breyta myndinni þinni"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Stilltu afstöðu, kvarða og halla myndanna þinna"</string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 1cd9eae..c29404b 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Sfondo giornaliero"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Schermate Home e di blocco"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Scegli uno sfondo"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Crea uno sfondo"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Crea sfondo"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Schermata Home"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Schermata di blocco"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Schermate Home e di blocco"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Anteprima sfondo schermata Home"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"La raccolta non esiste"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Esci dalla modalità schermo diviso e riprova"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Configura"</string>
     <string name="cancel" msgid="4970902691067201584">"Annulla"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Nascondi UI Anteprima"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Anteprima UI nascosta. Mostra toccando due volte"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Vuoi reimpostare le modifiche?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Le modifiche non verranno salvate"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Altri sfondi"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Sfondo %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Sfondo"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tocca per modificare la foto"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Regola posizione, scala e angolazione delle tue foto"</string>
 </resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 8817f0d..681af26 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"טפט יומי"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"מסך הבית ומסך הנעילה"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"בחירת טפט"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"יצירת טפט"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"יצירת טפט"</string>
     <string name="home_screen_message" msgid="106444102822522813">"מסך הבית"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"מסך נעילה"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"מסך הבית ונעילה"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"תצוגה מקדימה של הטפט במסך הבית"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"האוסף לא קיים"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"יש לצאת ממצב מסך מפוצל ולנסות שוב"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"הגדרה"</string>
     <string name="cancel" msgid="4970902691067201584">"ביטול"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"ללא תצוגה מקדימה בממשק המשתמש"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"הממשק מוסתר בתצוגה. לוחצים פעמיים לביטול ההסתרה"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"לאפס את השינויים?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"השינויים שביצעת לא יישמרו"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"עוד טפטים"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"‏טפט %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"‏%1$s‏, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"טפט"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"אפשר להקיש כדי לערוך את התמונה"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"שינוי המיקום, הגודל והזווית של התמונות"</string>
 </resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index ef05f16..f61c7f5 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"日替り壁紙"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ホーム画面とロック画面"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"壁紙の選択"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"壁紙の作成"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"壁紙の作成"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ホーム画面"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ロック画面"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ホーム画面とロック画面"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ホーム画面の壁紙のプレビュー"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"コレクションは存在しません"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"分割画面モードを終了してから、もう一度お試しください"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"設定"</string>
     <string name="cancel" msgid="4970902691067201584">"キャンセル"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI プレビューを非表示"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI を非表示にしました。ダブルタップで再表示します"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"変更をリセットしますか?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"変更内容は保存されません"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"その他の壁紙"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"壁紙 %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s、%2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"壁紙"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"写真を編集するにはタップします"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"写真の位置、スケール、角度を調整できます"</string>
 </resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index dad2b7b..14377c3 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"ყოველდღიური ფონი"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"მთავარი და ჩაკეტილი ეკრანები"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"აირჩიეთ ფონი"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"შექმენით ფონი"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ფონის შექმნა"</string>
     <string name="home_screen_message" msgid="106444102822522813">"მთავარი ეკრანი"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ჩაკეტილი ეკრანი"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"მთავარი და ჩაკეტილი ეკრანები"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"მთავარი ეკრანის ფონის გადახედვა"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"კოლექცია არ არსებობს"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"გთხოვთ, გახვიდეთ გაყოფილი ეკრანის რეჟიმიდან და ცადოთ ხელახლა"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"დაყენება"</string>
     <string name="cancel" msgid="4970902691067201584">"გაუქმება"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI გადახედვის დამალვა"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI დამალულია გადახედვაში. ორმაგად შეეხეთ გამოსაჩენად"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"ცვლილებების გადაყენება?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"თქვენი ცვლილებები არ შეინახება"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"მეტი ფონი"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ფონი %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"SD%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ფონი"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ფოტოს რედაქტირებისთვის შეეხეთ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"დააკორექტირეთ თქვენი ფოტოების პოზიცია, მასშტაბი და დახრის კუთხე"</string>
 </resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index fa9836e..8132694 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Күнделікті тұсқағаз"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Негізгі экран және құлып экраны"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Тұсқағаз таңдау"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Тұсқағаз жасау"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Тұсқағаз жасау"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Негізгі экран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Құлыптаулы экран"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Негізгі және құлыпталған экран"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Негізгі экран тұсқағазын алдын ала көру"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Жинақ жоқ."</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Экранды бөлу режимінен шығып, қайталап көріңіз."</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Орнату"</string>
     <string name="cancel" msgid="4970902691067201584">"Бас тарту"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Алдын ала көру экранын жасыру"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Пайдаланушы интерфейсі алдын ала көру режимінде жасырылған. Көрсету үшін екі рет түртіңіз."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Өзгертулерді қайтару керек пе?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Өзгертулер сақталмайды."</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Басқа да тұсқағаздар"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Тұсқағаз: %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Тұсқағаз"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Фотосуретті өңдеу үшін түртіңіз."</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Фотосуреттердің орнын, масштабын және бұрышын реттеңіз."</string>
 </resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 171aa55..fcd775f 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"ផ្ទាំងរូបភាពប្រចាំថ្ងៃ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"អេក្រង់ដើម និង​អេក្រង់ចាក់សោ"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ជ្រើសរើសផ្ទាំងរូបភាព"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"បង្កើតផ្ទាំងរូបភាព"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"បង្កើតផ្ទាំងរូបភាព"</string>
     <string name="home_screen_message" msgid="106444102822522813">"អេក្រង់ដើម"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"អេក្រង់​ចាក់សោ"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ដើម និង​ចាក់សោ"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ការមើល​ផ្ទាំងរូបភាព​អេក្រង់ដើម​សាកល្បង"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"បណ្ដុំមិនមានទេ"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"សូមចាកចេញពីមុខងារបំបែកអេក្រង់ រួចព្យាយាមម្ដងទៀត"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"កំណត់"</string>
     <string name="cancel" msgid="4970902691067201584">"បោះបង់"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"លាក់ការមើល UI សាកល្បង"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI ត្រូវបានលាក់ក្នុងការមើលសាកល្បង។ ចុចពីរដង ដើម្បីឈប់លាក់"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"កំណត់​ការផ្លាស់ប្ដូរ​ឡើង​វិញឬ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"ការផ្លាស់ប្ដូររបស់អ្នកនឹងមិនត្រូវបានរក្សាទុកទេ"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"ផ្ទាំងរូបភាព​ច្រើនទៀត"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ផ្ទាំង​រូបភាព %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ផ្ទាំង​រូបភាព"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ចុចដើម្បីកែរូបថតរបស់អ្នក"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"កែតម្រូវទីតាំង មាត្រដ្ឋាន និងមុំនៃរូបថតរបស់អ្នក"</string>
 </resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index d4ba33e..12e51fb 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -30,12 +30,12 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"ದಿನನಿತ್ಯದ ವಾಲ್‌ಪೇಪರ್"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ಹೋಮ್ ಮತ್ತು ಲಾಕ್‌ ಸ್ಕ್ರೀನ್"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ವಾಲ್‌ಪೇಪರ್‌ ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ವಾಲ್‌ಪೇಪರ್ ರಚಿಸಿ"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ವಾಲ್‌ಪೇಪರ್ ಅನ್ನು ರಚಿಸಿ"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ಮುಖಪುಟದ ಪರದೆ"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ಲಾಕ್ ಪರದೆ"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ಮುಖಪುಟ ಮತ್ತು ಲಾಕ್‌"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"ವಾಲ್‌ಪೇಪರ್ ಅನ್ನು ಆನ್‌ಗೆ ಹೊಂದಿಸಿ"</string>
-    <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"ಮುಖಪುಟದ ಪರದೆ"</string>
+    <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"ಹೋಮ್ ಸ್ಕ್ರೀನ್"</string>
     <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"ಲಾಕ್ ಪರದೆ"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"ಹೋಮ್ ಮತ್ತು ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ಗಳು"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"ತಿರುಗುವ ಚಿತ್ರದ ವಾಲ್‌ಪೇಪರ್"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ವಾಲ್‌ಪೇಪರ್‌ನ ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ಸಂಗ್ರಹಣೆ ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಮೋಡ್‌ನಿಂದ ನಿರ್ಗಮಿಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"ಸೆಟ್ ಮಾಡಿ"</string>
     <string name="cancel" msgid="4970902691067201584">"ರದ್ದುಮಾಡಿ"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI ಪೂರ್ವವೀಕ್ಷಣೆಯನ್ನು ಮರೆಮಾಡಿ"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"ಪೂರ್ವವೀಕ್ಷಣೆಯಲ್ಲಿ UI ಅನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ. ಪ್ರದರ್ಶಿಸಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"ಬದಲಾವಣೆಗಳನ್ನು ರೀಸೆಟ್ ಮಾಡಬೇಕೆ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"ನಿಮ್ಮ ಬದಲಾವಣೆಗಳನ್ನು ಉಳಿಸಲಾಗುವುದಿಲ್ಲ"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"ಇನ್ನಷ್ಟು ವಾಲ್‌ಪೇಪರ್‌ಗಳು"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ವಾಲ್‌ಪೇಪರ್ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ವಾಲ್‌ಪೇಪರ್"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ನಿಮ್ಮ ಫೋಟೋ ಎಡಿಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"ನಿಮ್ಮ ಫೋಟೋಗಳ ಸ್ಥಾನ, ಅಳತೆ ಮತ್ತು ಕೋನವನ್ನು ಹೊಂದಿಸಿ"</string>
 </resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 3cdbf3b..cf5c88a 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"일일 배경화면"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"홈 및 잠금 화면"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"배경화면 선택하기"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"배경화면 만들기"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"배경화면 만들기"</string>
     <string name="home_screen_message" msgid="106444102822522813">"홈 화면"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"잠금 화면"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"홈 및 잠금"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"홈 화면 배경화면 미리보기"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"컬렉션이 없습니다."</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"화면 분할 모드를 나간 다음 다시 시도해 주세요."</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"설정"</string>
     <string name="cancel" msgid="4970902691067201584">"취소"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI 미리보기 숨기기"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI를 미리보기에서 숨겼습니다. 숨기기 해제하려면 두 번 탭하세요."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"변경사항을 초기화하시겠습니까?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"변경사항이 저장되지 않습니다."</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"배경화면 더보기"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"배경화면 %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"배경화면"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"탭하여 사진 수정"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"사진의 위치, 크기, 각도 조정"</string>
 </resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index ad32de5..3611b13 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Күнүмдүк тушкагаз"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Башкы жана кулпуланган экран"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Тушкагаз тандоо"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Тушкагаз түзүү"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Тушкагаз түзүү"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Башкы экран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Кулпуланган экран"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Башкы жана кулпуланган экран"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Башкы экрандын тушкагазын карап көрүү"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Мындай жыйнак жок"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Экранды бөлүү режиминен чыгып, кайталап көрүңүз"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Коюу"</string>
     <string name="cancel" msgid="4970902691067201584">"Кереги жок"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Алдын ала көрүү экранын жашыруу"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Эки жолу басып, интерфейсти алдын ала көрүңүз."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Өзгөртүүлөр жоюлсунбу?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Өзгөртүүлөрүңүз сакталбайт"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Дагы башка тушкагаздар"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Тушкагаздар %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Тушкагаз"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Сүрөтүңүздү түзөтүү үчүн таптап коюңуз"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Сүрөттөрдүн абалын, масштабын жана бурчун тууралаңыз"</string>
 </resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 0ed2c21..267cc10 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"ຮູບພື້ນຫຼັງປະຈຳວັນ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ໜ້າຫຼັກ ແລະ ໜ້າຈໍລັອກ"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ເລືອກຮູບພື້ນຫຼັງ"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ສ້າງຮູບພື້ນຫຼັງ"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ສ້າງຮູບພື້ນຫຼັງ"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ໜ້າຈໍຫຼັກ"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ໜ້າຈໍລັອກ"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ໜ້າຈໍຫຼັກ ແລະ ການລັອກ"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ຕົວຢ່າງຮູບພື້ນຫຼັງໂຮມສະກຣີນ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ບໍ່ມິຄໍເລັກຊັນ"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"ກະລຸນາອອກຈາກໂໝດແບ່ງໜ້າຈໍແລ້ວລອງໃໝ່"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"ຕັ້ງ"</string>
     <string name="cancel" msgid="4970902691067201584">"ຍົກເລີກ"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"ເຊື່ອງຕົວຢ່າງສ່ວນຕິດຕໍ່ຜູ້ໃຊ້"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"ເຊື່ອງສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ໃນຕົວຢ່າງແລ້ວ. ແຕະສອງເທື່ອເພື່ອເຊົາເຊື່ອງ"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"ຣີເຊັດການປ່ຽນແປງບໍ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"ການປ່ຽນ​ແປງ​ຂອງ​ທ່ານ​ຈະບໍ່​ຖືກບັນ​ທຶກ"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"ຮູບພື້ນຫຼັງເພີ່ມເຕີມ"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ຮູບພື້ນຫຼັງ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ຮູບພື້ນຫຼັງ"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ແຕະເພື່ອແກ້ໄຂຮູບພາບຂອງທ່ານ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"ປັບຕຳແໜ່ງ, ຂະໜາດ ແລະ ມຸມຂອງຮູບພາບຂອງທ່ານ"</string>
 </resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 2b91da3..4b1c27e 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dienos ekrano fonas"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Pagrindinis ir užrakinimo ekranai"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Pasirinkite ekrano foną"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Sukurkite ekrano foną"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Kurti ekrano foną"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Pagrindinis ekranas"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Užrakinimo ekranas"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Pagrindinis ir užrakinimo ekr."</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Pagrindinio ekrano fono peržiūra"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Rinkinio nėra"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Išeikite iš išskaidyto ekrano režimo ir bandykite dar kartą"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Nustatyti"</string>
     <string name="cancel" msgid="4970902691067201584">"Atšaukti"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Slėpti NS peržiūrą"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"NS paslėpta peržiūroje. Dukart paliesd. parodykite"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Nustatyti pakeitimus iš naujo?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Pakeitimai nebus išsaugoti"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Daugiau darbalaukio fonų"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Ekrano fonas %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Ekrano fonas"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Palieskite, kad redaguotumėte nuotrauką"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Koreguokite nuotraukų padėtį, mastelį ir kampą"</string>
 </resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index f9db856..59e5fb4 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dienas fona tapete"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Sākuma un bloķēšanas ekrāns"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Fona tapetes izvēle"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Fona tapetes izveide"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Fona tapetes izveide"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Sākuma ekrāns"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Bloķēšanas ekrāns"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Sākuma un bloķēšanas ekrāns"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Sākuma ekrāna fona tapetes priekšskatījums"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Kolekcija nepastāv"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Izslēdziet ekrāna sadalīšanas režīmu un mēģiniet vēlreiz"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Iestatīt"</string>
     <string name="cancel" msgid="4970902691067201584">"Atcelt"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Paslēpt saskarnes priekšskatījumu"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Priekšskatījumā saskarne ir paslēpta. Lai to rādītu, veiciet dubultskārienu."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Vai atiestatīt izmaiņas?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Jūsu veiktās izmaiņas netiks saglabātas."</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Citas fona tapetes"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fona tapete: %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fona tapete"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Pieskarieties, lai rediģētu savu fotoattēlu."</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Pielāgojiet savu fotoattēlu pozīciju, mērogu un leņķi."</string>
 </resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 2fb1196..c00b32c 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Дневен тапет"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Почетен и заклучен екран"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Изберете тапет"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Создајте тапет"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Создавање тапет"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Почетен екран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Заклучен екран"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Почетен и заклучен екран"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Преглед на тапетот на почетниот екран"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Збирката не постои"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Излезете од режимот на поделен екран и обидете се повторно"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Постави"</string>
     <string name="cancel" msgid="4970902691067201584">"Откажи"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Скриј го прегледот на UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI е скриен во прегледот. Допрете двапати за да се прикаже"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Да се ресетираат промените?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Промените нема да се зачуваат"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Повеќе тапети"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Тапет %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Тапет"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Допрете за да ја измените фотографијата"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Приспособете ја позицијата, размерот и аголот на вашите фотографии"</string>
 </resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 7fc459b..d40bdb9 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"പ്രതിദിന വാൾപേപ്പർ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ഹോമും ലോക്ക് സ്‌ക്രീനും"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ഒരു വാൾപേപ്പർ തിരഞ്ഞെടുക്കുക"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ഒരു വാൾപേപ്പർ സൃഷ്ടിക്കുക"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"വാൾപേപ്പർ സൃഷ്‌ടിക്കുക"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ഹോം സ്‌ക്രീൻ"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ലോക്ക് സ്‌ക്രീൻ"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ഹോമും ലോക്ക് സ്‌ക്രീനും"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ഹോം സ്‌ക്രീൻ വാൾപേപ്പർ പ്രിവ്യൂ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ശേഖരം നിലവിലില്ല"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"സ്പ്ലിറ്റ് സ്ക്രീൻ മോഡിൽ നിന്ന് പുറത്ത് കടന്ന് വീണ്ടും ശ്രമിക്കുക"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"സജ്ജീകരിക്കുക"</string>
     <string name="cancel" msgid="4970902691067201584">"റദ്ദാക്കുക"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI പ്രിവ്യൂ മറയ്‌ക്കുക"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI പ്രിവ്യൂ മറച്ചു. മറച്ചത് മാറ്റാൻ ഡബിൾ ടാപ്പ് ചെയ്യൂ"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"മാറ്റങ്ങൾ റീസെറ്റ് ചെയ്യണോ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"നിങ്ങളുടെ മാറ്റങ്ങൾ സംരക്ഷിക്കില്ല"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"കൂടുതൽ വാൾപേപ്പറുകൾ"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"വാൾപേപ്പർ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"വാൾപേപ്പർ"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"നിങ്ങളുടെ ഫോട്ടോ എഡിറ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"നിങ്ങളുടെ ഫോട്ടോകളുടെ സ്ഥാനം, സ്‌കെയിൽ, ആംഗിൾ എന്നിവ ക്രമീകരിക്കുക"</string>
 </resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 2673393..18f052f 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Өдөр тутмын дэлгэцийн зураг"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Нүүр болон түгжигдсэн дэлгэц"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Дэлгэцийн зураг сонгох"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Дэлгэцийн зураг үүсгэх"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Дэлгэцийн зураг үүсгэх"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Үндсэн нүүр"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Түгжээтэй дэлгэц"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Нүүр хуудас болон түгжээ"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Үндсэн нүүрний дэлгэцийн зургийг урьдчилан үзэх"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Ийм цуглуулга байхгүй"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Дэлгэц хуваах горимоос гараад дахин оролдоно уу"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Тохируулах"</string>
     <string name="cancel" msgid="4970902691067201584">"Цуцлах"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI урьдчилан үзэлтийг нуух"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI-г урьдчилан үзэх дотор нуусан. Ил болгохын тулд хоёр товшино уу"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Өөрчлөлтийг шинэчлэх үү?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Таны өөрчлөлтийг хадгалахгүй"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Дэлгэцийн бусад зураг"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"%1$s-н дэлгэцийн зураг"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Дэлгэцийн зураг"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Зургаа засахын тулд товшино уу"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Зургуудынхаа байрлал, масштаб болон өнцгийг тохируулна уу"</string>
 </resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index ce0dd2b..4b03f12 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"दैनिक वॉलपेपर"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"होम आणि लॉक स्‍क्रीन"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"वॉलपेपर निवडा"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"वॉलपेपर तयार करा"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"वॉलपेपर तयार करा"</string>
     <string name="home_screen_message" msgid="106444102822522813">"होम स्क्रीन"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"लॉक स्क्रीन"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"होम आणि लॉक"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"होम स्क्रीन वॉलपेपर पूर्वावलोकन"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"संग्रह अस्तित्वात नाही"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"कृपया स्प्लिट स्क्रीन मोडमधून बाहेर पडा आणि पुन्हा प्रयत्न करा"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"सेट करा"</string>
     <string name="cancel" msgid="4970902691067201584">"रद्द करा"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI पूर्वावलोकन लपवा"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI पूर्वावलोकनात लपवले आहे. दाखवण्यासाठी डबल टॅप करा"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"बदल रीसेट करायचे आहेत का?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"तुमचे बदल सेव्ह केले जाणार नाहीत"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"अधिक वॉलपेपर"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"वॉलपेपर %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"वॉलपेपर"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"तुमचा फोटो संपादित करण्यासाठी टॅप करा"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"तुमच्या फोटोचे स्थान, स्केल आणि कोन ॲडजस्ट करा"</string>
 </resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index a796b99..0596735 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -30,13 +30,13 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Kertas dinding harian"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Skrin utama &amp; Skrin kunci"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Pilih Hiasan latar"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Buat Hiasan latar"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Buat hiasan latar"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Skrin utama"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Kunci skrin"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Skrin Utama &amp; Kunci"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"Tetapkan hiasan latar"</string>
     <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"Skrin utama"</string>
-    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Kunci skrin"</string>
+    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Skrin kunci"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"Skrin utama dan skrin kunci"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"Menggilirkan Kertas Dinding Imej"</string>
     <string name="permission_needed_explanation" msgid="139166837541426823">"Untuk memaparkan kertas dinding semasa di sini, <xliff:g id="APP_NAME">%1$s</xliff:g> memerlukan akses kepada storan peranti anda."</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Pratonton hiasan latar skrin utama"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Koleksi tersebut tidak wujud"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Sila keluar daripada mod skrin pisah dan cuba lagi"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Tetapkan"</string>
     <string name="cancel" msgid="4970902691067201584">"Batal"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Sembunyikan Pratontotn UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Sembunyi UI dlm pratonton Dwiketik utk nyahsembunyi"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Tetapkan semula perubahan?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Perubahan anda tidak akan disimpan"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Lagi hiasan latar"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Hiasan latar %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Hiasan latar"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Ketik untuk mengedit foto anda"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Laraskan kedudukan, skala dan sudut foto anda"</string>
 </resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 2a9dc7a..79e927f 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -30,13 +30,13 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"နေ့စဉ် နောက်ခံ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ပင်မစာမျက်နှာနှင့် လော့ခ်ချထားချိန် မျက်နှာပြင်"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"နောက်ခံရွေးရန်"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"နောက်ခံလုပ်ရန်"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"နောက်ခံလုပ်ရန်"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ပင်မစာမျက်နှာ"</string>
-    <string name="lock_screen_message" msgid="1534506081955058013">"လော့ခ်ချထားချိန် မျက်နှာပြင်"</string>
+    <string name="lock_screen_message" msgid="1534506081955058013">"လော့ခ်မျက်နှာပြင်"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ပင်မနှင့် လော့ခ်မျက်နှာပြင်"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"နောက်ခံ သတ်မှတ်ရန်"</string>
     <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"ပင်မစာမျက်နှာ"</string>
-    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"လော့ခ်ချထားချိန် မျက်နှာပြင်"</string>
+    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"လော့ခ်မျက်နှာပြင်"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"ပင်မစာမျက်နှာနှင့် လော့ခ်မျက်နှာပြင်"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"နောက်ခံပုံကို လှည့်နေသည်"</string>
     <string name="permission_needed_explanation" msgid="139166837541426823">"ဤနေရာတွင် လက်ရှိနောက်ခံကို ပြသရန်အတွက် <xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့်စက်၏ သိုလှောင်ခန်းကို အသုံးပြုခွင့်လိုအပ်သည်။"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ပင်မစာမျက်နှာနောက်ခံ အစမ်းကြည့်ရှုခြင်း"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ဤစုစည်းမှု မရှိပါ"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"မျက်နှာပြင်ခွဲပြခြင်းမုဒ်ကို ထွက်၍ ထပ်စမ်းကြည့်ပါ"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"သတ်မှတ်ရန်"</string>
     <string name="cancel" msgid="4970902691067201584">"မလုပ်တော့"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI အစမ်းကြည့်ခြင်းကို ဝှက်ရန်"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"အစမ်းကြည့်ရှုမှုတွင် UI ကို ဝှက်ထားသည်။ ပြန်ပြရန် နှစ်ချက်တို့ပါ"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"အပြောင်းအလဲများ ပြန်သတ်မှတ်မလား။"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"သင့်ပြောင်းလဲမှုများအား သိမ်းမည် မဟုတ်ပါ"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"နောက်ထပ် နောက်ခံပုံများ"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"နောက်ခံ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s၊ %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"နောက်ခံ"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ဓာတ်ပုံတည်းဖြတ်ရန် တို့ပါ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"သင့်ဓာတ်ပုံများ၏ အနေအထား၊ စကေးနှင့် ထောင့်များကို ချိန်ညှိရန်"</string>
 </resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index c104086..c5a62a0 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Daglig bakgrunn"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Startskjermen og låseskjermen"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Velg en bakgrunn"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Opprett en bakgrunn"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Opprett bakgrunn"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Startskjerm"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Låseskjerm"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Startskjermen og låseskjermen"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Forhåndsvisning av bakgrunn for startskjermen"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Samlingen eksisterer ikke"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Gå ut av modus for delt skjerm, og prøv igjen"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Velg"</string>
     <string name="cancel" msgid="4970902691067201584">"Avbryt"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Skjul UI-forhåndsvisning"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI skjult i forhåndsvisn. Dobbelttrykk for å vise"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Vil du tilbakestille endringene?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Endringene lagres ikke"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Flere bakgrunner"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Bakgrunn %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Bakgrunn"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Trykk for å redigere bildet"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Juster posisjonen, skalaen og vinkelen til bildene dine"</string>
 </resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 4df1ff2..4486f72 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"दैनिक वालपेपर"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"होम तथा लक स्क्रिन"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"वालपेपर छान्नुहोस्"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"वालपेपर बनाउनुहोस्"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"वालपेपर बनाउनुहोस्"</string>
     <string name="home_screen_message" msgid="106444102822522813">"होम स्क्रिन"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"लक स्क्रिन"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"होम स्क्रिन &amp; लक स्क्रिन"</string>
@@ -80,7 +80,7 @@
     <string name="center_wallpaper_position" msgid="4166894762352288883">"मध्यभाग"</string>
     <string name="center_crop_wallpaper_position" msgid="1681980019815343348">"मध्यभागमा क्रप गरिएको"</string>
     <string name="stretch_wallpaper_position" msgid="5002680983147456935">"तन्काइएको"</string>
-    <string name="preview" msgid="1774602101743861071">"पूर्वावलोकन"</string>
+    <string name="preview" msgid="1774602101743861071">"प्रिभ्यु"</string>
     <string name="tab_info" msgid="818614080690111416">"जानकारी"</string>
     <string name="tab_customize" msgid="2533745409174959960">"आफू अनुकूल पार्नुहोस्"</string>
     <string name="tab_effects" msgid="3213606157589233901">"इफेक्टहरू"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"होम स्क्रिनमा देखिने वालपेपरको प्रिभ्यू"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"यो सङ्ग्रह छैन"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"कृपया विभाजित स्क्रिन मोडबाट बाहिरिनुहोस् र फेरि प्रयास गर्नुहोस्"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"सेट अप गर्नुहोस्"</string>
     <string name="cancel" msgid="4970902691067201584">"रद्द गर्नुहोस्"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI प्रिभ्यू लुकाइयोस्"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"प्रिभ्यूमा UI लुकाइएको छ। नलुकाउन डबल ट्याप गर्नुहोस्"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"परिवर्तनहरू रिसेट गर्ने हो?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"तपाईंले गरेका परिवर्तनहरू सेभ गरिने छैनन्"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"थप वालपेपरहरू"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"वालपेपर %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"वालपेपर"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"आफ्नो फोटो सम्पादन गर्न ट्याप गर्नुहोस्"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"आफ्ना फोटोहरूको स्थिति, स्केल र कोण मिलाउनुहोस्"</string>
 </resources>
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 20aa862..7d71eae 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -34,7 +34,6 @@
     <color name="system_surface_container_highest">@android:color/system_surface_container_highest_dark</color>
     <color name="system_surface_bright">@android:color/system_surface_bright_dark</color>
     <color name="system_outline">@android:color/system_outline_dark</color>
-    <color name="system_outline_variant">@android:color/system_outline_variant_dark</color>
 
     <!-- UI elements with Dark/Light Theme Variances -->
     <color name="option_item_background">@color/system_surface_bright</color>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 2d2f7a1..200a153 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dagelijkse achtergrond"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Start- en vergrendelscherm"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Een achtergrond kiezen"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Een achtergrond maken"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Achtergrond maken"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Startscherm"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Vergrendelscherm"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Home- en vergrendelscherm"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Voorbeeld achtergrond startscherm"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"De collectie bestaat niet"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Sluit de modus voor gesplitst scherm af en probeer het opnieuw"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Instellen"</string>
     <string name="cancel" msgid="4970902691067201584">"Annuleren"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Voorbeeld van UI verbergen"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI verborgen in voorbeeld. Dubbeltik om zichtbaar te maken"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Wijzigingen resetten?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Je wijzigingen worden niet opgeslagen"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Meer achtergronden"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Achtergrond %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Achtergrond"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tik om je foto te bewerken"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Pas de positie, schaal en hoek van je foto\'s aan"</string>
 </resources>
diff --git a/res/values-notnight-v27/styles.xml b/res/values-notnight-v27/styles.xml
index beeadac..f610646 100755
--- a/res/values-notnight-v27/styles.xml
+++ b/res/values-notnight-v27/styles.xml
@@ -50,7 +50,9 @@
     </style>
 
     <!-- SetWallpaperPreviewDialog -->
-    <style name="SetWallpaperPreviewDialogTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth">
+    <style name="SetWallpaperPreviewDialogTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar">
+        <item name="android:windowMinWidthMajor">0dp</item>
+        <item name="android:windowMinWidthMinor">0dp</item>
         <item name="android:buttonBarPositiveButtonStyle">@style/SetWallpaperDialog.Button</item>
         <item name="android:buttonBarNegativeButtonStyle">@style/SetWallpaperDialog.Button.OutlinedButton</item>
         <item name="android:buttonBarNeutralButtonStyle">@style/SetWallpaperDialog.Button.TextButton</item>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index e8750ee..cf94efb 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -30,13 +30,13 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"ଦୈନିକ ୱାଲପେପର୍"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ହୋମ ଓ ଲକ ସ୍କ୍ରିନ"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ଏକ ୱାଲପେପର ବାଛନ୍ତୁ"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ଏକ ୱାଲପେପର ତିଆରି କରନ୍ତୁ"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ୱାଲପେପର ତିଆରି କରନ୍ତୁ"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ହୋମ ସ୍କ୍ରିନ"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ଲକ୍‌ ସ୍କ୍ରୀନ୍‌"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ହୋମ ଓ ଲକ"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"ଏଥିରେ ୱାଲପେପର ସେଟ କରନ୍ତୁ"</string>
     <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"ହୋମ ସ୍କ୍ରିନ"</string>
-    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"ଲକ୍‌ ସ୍କ୍ରୀନ୍‌"</string>
+    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"ଲକ ସ୍କ୍ରିନ"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"ହୋମ ଏବଂ ଲକ ସ୍କ୍ରିନ"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"ୱାଲପେପର୍‌ ଇମେଜ୍‌କୁ ଘୂରାଇବା"</string>
     <string name="permission_needed_explanation" msgid="139166837541426823">"ଏଠାରେ ସାମ୍ପ୍ରତିକ ୱାଲପେପର୍‌କୁ ଦେଖାଇବା ପାଇଁ, <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କ ଡିଭାଇସ୍‌ ଷ୍ଟୋରେଜ୍‌ର ଆକ୍ସେସ୍ ଆବଶ୍ୟକ।"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ହୋମ ସ୍କ୍ରିନ ୱାଲପେପରର ପ୍ରିଭ୍ୟୁ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ସଂଗ୍ରହ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"ଦୟାକରି ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ମୋଡରୁ ବାହାରି ଯାଇ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"ସେଟ କରାଯାଇଛି"</string>
     <string name="cancel" msgid="4970902691067201584">"ବାତିଲ କରନ୍ତୁ"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI ପ୍ରିଭ୍ୟୁକୁ ଲୁଚାନ୍ତୁ"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"ପ୍ରିଭ୍ୟୁରେ UI ଲୁଚାଯାଇଛି। ଦେଖାଇବାକୁ ଦୁଇଥର ଟାପ କର"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"ପରିବର୍ତ୍ତନଗୁଡ଼ିକୁ ରିସେଟ କରିବେ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"ଆପଣଙ୍କର ପରିବର୍ତ୍ତନଗୁଡ଼ିକୁ ସେଭ କରାଯିବ ନାହିଁ"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"ଅଧିକ ୱାଲପେପର"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ୱାଲପେପର %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ୱାଲପେପର"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ଆପଣଙ୍କ ଫଟୋକୁ ଏଡିଟ କରିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"ଆପଣଙ୍କ ଫଟୋଗୁଡ଼ିକର ପୋଜିସନ, ସ୍କେଲ ଏବଂ ଆଙ୍ଗଲକୁ ଆଡଜଷ୍ଟ କରନ୍ତୁ"</string>
 </resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index c5436a5..66dd503 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"ਰੋਜ਼ਾਨਾ ਵਾਲਪੇਪਰ"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ਹੋਮ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"ਕੋਈ ਵਾਲਪੇਪਰ ਚੁਣੋ"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"ਕੋਈ ਵਾਲਪੇਪਰ ਬਣਾਓ"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"ਵਾਲਪੇਪਰ ਬਣਾਓ"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ਹੋਮ ਸਕ੍ਰੀਨ"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"ਲਾਕ ਸਕ੍ਰੀਨ"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ਹੋਮ ਸਕ੍ਰੀਨ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ਹੋਮ ਸਕ੍ਰੀਨ ਵਾਲਪੇਪਰ ਦੀ ਪੂਰਵ-ਝਲਕ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ਸੰਗ੍ਰਹਿ ਮੌਜੂਦ ਨਹੀਂ ਹੈ"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"ਕਿਰਪਾ ਕਰਕੇ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਮੋਡ ਤੋਂ ਬਾਹਰ ਜਾਓ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"ਸੈੱਟ ਕਰੋ"</string>
     <string name="cancel" msgid="4970902691067201584">"ਰੱਦ ਕਰੋ"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI ਦੀ ਪੂਰਵ-ਝਲਕ ਲੁਕਾਓ"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"ਪੂਰਵ-ਝਲਕ ਵਿੱਚ UI ਨੂੰ ਲੁਕਾਇਆ ਗਿਆ ਹੈ। ਦਿਖਾਉਣ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"ਕੀ ਤਬਦੀਲੀਆਂ ਨੂੰ ਰੀਸੈੱਟ ਕਰਨਾ ਹੈ?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"ਤੁਹਾਡੀਆਂ ਤਬਦੀਲੀਆਂ ਨੂੰ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"ਹੋਰ ਵਾਲਪੇਪਰ"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"ਵਾਲਪੇਪਰ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"ਵਾਲਪੇਪਰ"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ਆਪਣੀ ਫ਼ੋਟੋ ਦਾ ਸੰਪਾਦਨ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"ਆਪਣੀਆਂ ਫ਼ੋਟੋਆਂ ਦੀ ਸਥਿਤੀ, ਸਕੇਲ ਅਤੇ ਕੋਣ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
 </resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 557d5a1..e044da0 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Codzienna tapeta"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Ekran główny i ekran blokady"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Wybierz tapetę"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Utwórz tapetę"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Utwórz tapetę"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Ekran główny"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Ekran blokady"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Ekran główny i ekran blokady"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Podgląd tapety na ekranie głównym"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Taka kolekcja nie istnieje"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Wyłącz tryb podzielonego ekranu i spróbuj jeszcze raz"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Ustaw"</string>
     <string name="cancel" msgid="4970902691067201584">"Anuluj"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ukryj podgląd UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Interfejs jest ukryty na podglądzie. Kliknij dwukrotnie, aby go pokazać"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Zresetować zmiany?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Zmiany nie zostaną zapisane"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Więcej tapet"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Tapeta %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Tapeta"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Kliknij, aby edytować zdjęcie"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Dostosuj położenie, skalę i kąt zdjęć"</string>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 6390028..0c6eb1e 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Imagem de fundo diária"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Ecrã principal e de bloqueio"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Escolha uma imagem de fundo"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Crie uma imagem de fundo"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Criar imagem de fundo"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Ecrã principal"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Ecrã de bloqueio"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Ecrã principal e de bloqueio"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Pré-visualização da imagem de fundo do ecrã principal"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"A coleção não existe."</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Saia do modo de ecrã dividido e tente novamente"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Definir"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancelar"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ocultar pré-visualização da IU"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"IU oculta na pré-visualização. Toque 2x p/ mostrar"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Repor alterações?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"As suas alterações não vão ser guardadas"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Mais imagens de fundo"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Imagem de fundo %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Imagem de fundo"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Toque para editar a sua foto"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajuste a posição, a escala e o ângulo das suas fotos"</string>
 </resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index bbc987e..ccc5463 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Plano de fundo diário"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Tela inicial e de bloqueio"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Escolha um plano de fundo"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Crie um plano de fundo"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Criar plano de fundo"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Tela inicial"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Tela de bloqueio"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Tela inicial e de bloqueio"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Prévia do plano de fundo da tela inicial"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"A coleção não existe"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Saia do modo de tela dividida e tente de novo"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Definir"</string>
     <string name="cancel" msgid="4970902691067201584">"Cancelar"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ocultar visualização da interface"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"IU ocultada na prévia. Toque 2 vezes para mostrar"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Redefinir mudanças?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"As mudanças não vão ser salvas"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Mais planos de fundo"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Plano de fundo %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Plano de fundo"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Toque para editar a foto"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajuste a posição, a escala e o ângulo das suas fotos"</string>
 </resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 6f2c153..ac5d350 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Imaginea de fundal zilnică"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Ecran de pornire și de blocare"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Alege o imagine de fundal"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Creează o imagine de fundal"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Creează o imagine de fundal"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Ecran de pornire"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Ecran de blocare"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"De pornire și de blocare"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Previzualizarea imaginii de fundal pentru ecranul de pornire"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Colecția nu există"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Ieși din modul ecran împărțit și încearcă din nou"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Setează"</string>
     <string name="cancel" msgid="4970902691067201584">"Anulează"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ascunde previzualizarea IU"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"IU ascunsă în previzualizare. Atinge de 2 ori pentru a reafișa"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Resetezi modificările?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Modificările nu se vor salva"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Mai multe imagini de fundal"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Imagine de fundal %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Imaginea de fundal"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Atinge pentru a edita fotografia"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Ajustează poziția, scara și unghiul fotografiilor"</string>
 </resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index abb7e39..ac8b527 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Обои на каждый день"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Главный экран и заблокированный экран"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Выбрать обои"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Создать обои"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Создание обоев"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Главный экран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Заблокированный экран"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Оба экрана"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Предварительный просмотр обоев для главного экрана"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Такой подборки не существует."</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Выйдите из режима разделения экрана и повторите попытку."</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Установить"</string>
     <string name="cancel" msgid="4970902691067201584">"Отмена"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Скрыть экран предпросмотра"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Нажмите дважды, чтобы показать интерфейс в режиме предпросмотра."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Сбросить изменения?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Изменения не будут сохранены."</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Ещё обои"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Обои: %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Обои"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Нажмите, чтобы изменить фотографию"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Измените положение, масштаб и угол наклона фотографий"</string>
 </resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 8f1bd4c..4ced87c 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"දෛනික වෝල්පේපරය"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"මුල් පිටුව සහ අගුළු තිරය"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"වෝල්පේපරයක් තෝරා ගන්න"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"වෝල්පේපරයක් තනන්න"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"වෝල්පේපරය තනන්න"</string>
     <string name="home_screen_message" msgid="106444102822522813">"මුල් පිටු තිරය"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"අගුලු තිරය"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"මුල් පිටුව සහ අගුල"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"මුල් තිරයේ බිතුපත් පෙරදසුන"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"එකතුව නොපවතී"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"බෙදුම් තිර ප්‍රකාරයෙන් පිට වී නැවත උත්සාහ කරන්න"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"සකසන්න"</string>
     <string name="cancel" msgid="4970902691067201584">"අවලංගු කරන්න"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI පෙරදසුන සඟවන්න"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI පෙරදසුන තුළ සඟවා ඇත. නොසැඟවීමට දෙවරක් තට්ටු කරන්න"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"වෙනස්කම් යළි සකසන්න ද?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"ඔබේ වෙනස්කම් සුරැකෙන්නේ නැත"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"තවත් වෝල්පේපර"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"වෝල්පේපරය %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"වෝල්පේපරය"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"ඔබේ ඡායාරූපය සංස්කරණය කිරීමට තට්ටු කරන්න"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"ඔබේ ඡායාරූපවල පිහිටීම, පරිමාණය, සහ කෝණය සකසන්න"</string>
 </resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 63fa104..b77eb26 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Denná tapeta"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Plocha a uzamknutá obrazovka"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Vyberte tapetu"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Vytvorte tapetu"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Vytvoriť tapetu"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Plocha"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Uzamknutá obrazovka"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Plocha a uzamknutá obrazovka"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Ukážka tapety na ploche"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Zbierka neexistuje"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Ukončite režim rozdelenej obrazovky a skúste to znova"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Nastaviť"</string>
     <string name="cancel" msgid="4970902691067201584">"Zrušiť"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Skryť ukážku použ. rozhrania"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Použ. rozhr. je v ukážke skryté. Zobrazíte dvoj. klepnutím."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Chcete resetovať zmeny?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Vaše zmeny nebudú uložené"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Ďalšie tapety"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Tapeta %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Tapeta"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Fotku upravíte klepnutím"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Upravte pozíciu, rozmery a uhol svojich fotiek"</string>
 </resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index f25a490..7bd153f 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dnevno ozadje"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Začetni in zaklenjeni zaslon"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Izberite zaslonsko ozadje"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Ustvarite zaslonsko ozadje"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Ustvari zaslonsko ozadje"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Začetni zaslon"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Zaklenjen zaslon"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Začetni in zaklenjeni zaslon"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Predogled zaslonskega ozadja začetnega zaslona"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Zbirka ne obstaja"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Zapustite način razdeljenega zaslona in poskusite znova"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Nastavi"</string>
     <string name="cancel" msgid="4970902691067201584">"Prekliči"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Skrij predogled upor. vmesnika"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Upor. vm. je skrit. Dvakrat se dot. za razkritje."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Želite ponastaviti spremembe?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Spremembe ne bodo shranjene."</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Več zaslonskih ozadij"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Zaslonsko ozadje %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Zaslonsko ozadje"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Dotik za urejanje fotografije"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Prilagajanje položaja, velikosti in kota fotografij"</string>
 </resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 8e6b87f..2b9ddee 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Imazh sfondi i përditshëm"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"\"Ekrani bazë\" dhe \"Ekrani i kyçjes\""</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Zgjidh një imazh sfondi"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Krijo një imazh sfondi"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Krijo imazh sfondi"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Ekrani bazë"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Ekrani i kyçjes"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"\"Ekrani bazë\" dhe \"Kyçja\""</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Pamja paraprake e imazhit të sfondit të ekranit bazë"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Koleksioni nuk ekziston"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Dil nga modaliteti i ekranit të ndarë dhe provo sërish"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Cakto"</string>
     <string name="cancel" msgid="4970902691067201584">"Anulo"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Fshih pamjen paraprake të ndërfaqes së përdoruesit"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Pamja paraprake: UI fshehur. Shfaq me dy trokitje"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Të rivendosen ndryshimet?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Ndryshimet e tua nuk do të ruhen"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Më shumë imazhe të sfondit"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Imazhi i sfondit %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Imazhi i sfondit"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Trokit për të modifikuar fotografinë tënde"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Rregullo pozicionin, shkallën dhe këndin e fotografive të tua"</string>
 </resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 108f73a..a00ff99 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -30,13 +30,13 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Дневна позадина"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Почетни и закључани екран"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Одаберите позадину"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Направите позадину"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Направите позадину"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Почетни екран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Закључан екран"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Почетни и закључани екран"</string>
     <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"Подесите позадину на"</string>
     <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"Почетни екран"</string>
-    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Закључан екран"</string>
+    <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"Закључани екран"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"Почетни и закључани екран"</string>
     <string name="no_backup_image_wallpaper_label" msgid="6316627676107284851">"Ротирајућа позадина са сликом"</string>
     <string name="permission_needed_explanation" msgid="139166837541426823">"Да би се актуелна позадина приказивала овде, апликација <xliff:g id="APP_NAME">%1$s</xliff:g> треба да има приступ меморијском простору на уређају."</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Приказ позадине почетног екрана"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Колекција не постоји"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Напустите режим подељеног екрана и пробајте поново"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Подеси"</string>
     <string name="cancel" msgid="4970902691067201584">"Откажи"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Сакриј кориснички интерфејс"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Кријемо кориснич. интерфејс. Откријте у два додира"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Желите да ресетујете промене?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Промене неће бити сачуване"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Још позадина"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Позадина %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Позадина"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Додирните да бисте изменили слику"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Прилагодите положај, размеру и угао слике"</string>
 </resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index aedb5a3..a2e867d 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Dagens bakgrund"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Start- och låsskärm"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Välj en bakgrund"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Skapa en bakgrund"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Skapa bakgrund"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Startskärm"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Låsskärm"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Start- och låsskärm"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Förhandsgranskning av startskärmens bakgrund"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Samlingen finns inte"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Avsluta läget för delad skärm och försök igen"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Ställ in"</string>
     <string name="cancel" msgid="4970902691067201584">"Avbryt"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Dölj förhandsgranskning av UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Döljer gränssnitt förhandsg. Dubbeltryck och visa"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Vill du återställa ändringarna?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Dina ändringar sparas inte"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Fler bakgrunder"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Bakgrunden %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Bakgrund"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Tryck för att redigera fotot"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Justera positionen, skalan och vinkeln på dina foton"</string>
 </resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 4e59a71..3354aaa 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Mandhari ya kila siku"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Skrini ya Kwanza na Iliyofungwa"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Chagua Mandhari"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Unda Mandhari"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Buni mandhari"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Skrini ya kwanza"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Skrini iliyofungwa"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Skrini ya Kwanza na Iliyofungwa"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Onyesho la kukagua mandhari ya skrini ya kwanza"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Mkusanyiko huu haupo"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Tafadhali ondoka kwenye hali ya skrini iliyogawanywa na ujaribu tena"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Weka"</string>
     <string name="cancel" msgid="4970902691067201584">"Ghairi"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ficha Onyesho la Kukagua Kiolesura"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Kiolesura kimefichwa katika onyesho la kukagua. Gusa mara mbili ukionyeshe"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Ungependa kuweka mabadiliko upya?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Mabadiliko yako hayatahifadhiwa"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Mandhari zaidi"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Mandhari %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Mandhari"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Gusa ili uhariri picha yako"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Rekebisha uwiano, mkao na namna picha zako zipo"</string>
 </resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index e88c295..8cb3083 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"தினசரி வால்பேப்பர்"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"முகப்பு &amp; பூட்டுத் திரை"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"வால்பேப்பரைத் தேர்வுசெய்யுங்கள்"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"வால்பேப்பரை உருவாக்குங்கள்"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"வால்பேப்பரை உருவாக்குதல்"</string>
     <string name="home_screen_message" msgid="106444102822522813">"முகப்புத் திரை"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"பூட்டுத் திரை"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"முகப்பு &amp; பூட்டு"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"முகப்புத் திரை வால்பேப்பரின் மாதிரிக்காட்சி"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"இந்தத் தொகுப்பு இல்லை"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"திரைப் பிரிப்புப் பயன்முறையிலிருந்து வெளியேறி மீண்டும் முயலவும்"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"அமை"</string>
     <string name="cancel" msgid="4970902691067201584">"வேண்டாம்"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI மாதிரிக்காட்சியை மறை"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"மாதிரிக்காட்சியில் UI மறைந்துள்ளது. காட்ட இருமுறை தட்டவும்"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"மாற்றங்களை மீட்டமைக்கவா?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"உங்கள் மாற்றங்கள் சேமிக்கப்படாது"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"மேலும் வால்பேப்பர்கள்"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"வால்பேப்பர் %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"வால்பேப்பர்"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"உங்கள் படத்தில் மாற்றம் செய்ய தட்டலாம்"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"உங்கள் படங்களின் நிலை, அளவு மற்றும் ஆங்கிளை மாற்றலாம்"</string>
 </resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 73e42eb..b1b15f1 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"రోజువారీ వాల్‌పేపర్"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"హోమ్ &amp; లాక్ స్క్రీన్"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"వాల్‌పేపర్‌ను ఎంచుకోండి"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"వాల్‌పేపర్‌ను క్రియేట్ చేయండి"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"వాల్‌పేపర్‌ను క్రియేట్ చేయండి"</string>
     <string name="home_screen_message" msgid="106444102822522813">"మొదటి స్క్రీన్"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"లాక్ స్క్రీన్"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"హోమ్ &amp; లాక్"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"మొదటి స్క్రీన్ వాల్‌పేపర్ ప్రివ్యూ"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ఈ సేకరణ అందుబాటులో లేదు"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"దయచేసి స్ప్లిట్ స్క్రీన్ మోడ్ నుంచి ఎగ్జిట్ అయ్యి, మళ్లీ ట్రై చేయండి"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"సెట్ చేయండి"</string>
     <string name="cancel" msgid="4970902691067201584">"రద్దు చేయండి"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"UI ప్రివ్యూని దాచిపెట్టు"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"UI ప్రివ్యూలో దాచబడింది. రెండుసార్లు నొక్కి చూడండి"</string>
@@ -121,7 +122,7 @@
     <string name="accessibility_customize_shown" msgid="590964727831547651">"అనుకూలీకరణ ప్యానెల్ చూపబడింది"</string>
     <string name="accessibility_info_hidden" msgid="2288603712350168107">"సమాచార ప్యానెల్ దాచబడింది"</string>
     <string name="accessibility_info_shown" msgid="6626025722456105632">"సమాచార ప్యానెల్ చూపబడింది"</string>
-    <string name="settings_snackbar_description" msgid="890168814524778486">"దయచేసి సెట్టింగ్‌లలో ఫైల్‌లు, మీడియాను ఎనేబుల్ చేయండి."</string>
+    <string name="settings_snackbar_description" msgid="890168814524778486">"దయచేసి సెట్టింగ్‌లలో ఫైళ్లు, మీడియాను ఎనేబుల్ చేయండి."</string>
     <string name="settings_snackbar_enable" msgid="5992112808061426068">"ఎనేబుల్ చేయండి"</string>
     <string name="open_my_photos" msgid="4107196465713868381">"నా ఫోటోలను తెరవండి"</string>
     <string name="lock_screen_tab" msgid="6672930765010407652">"లాక్ స్క్రీన్"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"మార్పులను రీసెట్ చేయాలా?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"మీ మార్పులు సేవ్ చేయబడవు"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"మరిన్ని వాల్‌పేపర్‌లు"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"వాల్‌పేపర్ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"వాల్‌పేపర్"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"మీ ఫోటోను ఎడిట్ చేయడానికి ట్యాప్ చేయండి"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"మీ ఫోటోల స్థానం, స్కేల్ ఇంకా కోణాన్ని సర్దుబాటు చేయండి"</string>
 </resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index b38a8af..1e6e472 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"วอลเปเปอร์รายวัน"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"หน้าจอหลักและหน้าจอล็อก"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"เลือกวอลเปเปอร์"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"สร้างวอลเปเปอร์"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"สร้างวอลเปเปอร์"</string>
     <string name="home_screen_message" msgid="106444102822522813">"หน้าจอหลัก"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"หน้าจอล็อก"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"หน้าแรกและหน้าจอล็อก"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ตัวอย่างวอลเปเปอร์หน้าจอหลัก"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"ไม่มีคอลเล็กชัน"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"โปรดออกจากโหมดแยกหน้าจอและลองอีกครั้ง"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"ตั้งค่า"</string>
     <string name="cancel" msgid="4970902691067201584">"ยกเลิก"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"ซ่อนตัวอย่าง UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"ซ่อน UI ในตัวอย่าง แตะสองครั้งเพื่อเลิกซ่อน"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"รีเซ็ตการเปลี่ยนแปลงไหม"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"ระบบจะไม่บันทึกการเปลี่ยนแปลงของคุณ"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"วอลเปเปอร์เพิ่มเติม"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"วอลเปเปอร์ %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"วอลเปเปอร์"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"แตะเพื่อแก้ไขรูปภาพ"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"ปรับตำแหน่ง ขนาด และมุมของรูปภาพ"</string>
 </resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 3c6996a..cc6abb8 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Pang-araw-araw na wallpaper"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Home &amp; Lock screen"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Pumili ng Wallpaper"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Gumawa ng Wallpaper"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Gumawa ng wallpaper"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Home screen"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Lock screen"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Home at Lock"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Preview ng wallpaper ng home screen"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Wala ang koleksyon"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Lumabas sa split screen mode at subukan ulit"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Itakda"</string>
     <string name="cancel" msgid="4970902691067201584">"Kanselahin"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Itago ang Preview ng UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Hidden ang UI sa preview. Double tap para i-unhide"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"I-reset ang mga pagbabago?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Hindi mase-save ang iyong mga pagbabago"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Higuit pang wallpaper"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Wallpaper %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Wallpaper"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"I-tap para i-edit ang iyong larawan"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"I-adjust ang posisyon, scale, at anggulo ng iyong mga larawan"</string>
 </resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 5f83456..f588c2a 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Günlük duvar kağıdı"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Ana Sayfa ve Kilit ekranı"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Duvar kağıdı seçin"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Duvar kağıdı oluşturun"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Duvar kağıdı oluştur"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Ana ekran"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Kilit ekranı"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Ana Ekran ve Kilit Ekranı"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Ana ekran duvar kağıdı önizlemesi"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Koleksiyon mevcut değil"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Lütfen bölünmüş ekran modundan çıkıp tekrar deneyin"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Ayarla"</string>
     <string name="cancel" msgid="4970902691067201584">"İptal"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Arayüz Önizlemesini Gizle"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Kullanıcı arayüzü önizlemesi gizlenmiş. Göstermek için iki kez dokunun"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Değişiklikler sıfırlansın mı?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Değişiklikleriniz kaydedilmeyecek"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Diğer duvar kağıtları"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Duvar kağıdı %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Duvar kağıdı"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Fotoğrafınızı düzenlemek için dokunun"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Fotoğraflarınızın konumu, ölçeği ve açısını ayarlayın"</string>
 </resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index d9dc2d1..921409c 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Щоденний фоновий малюнок"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Головний і заблокований екрани"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Виберіть фоновий малюнок"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Створіть фоновий малюнок"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Створити фоновий малюнок"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Головний екран"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Заблокований екран"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Головний і заблокований екрани"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Попередній перегляд фонового малюнка головного екрана"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Колекція не існує"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Вимкніть режим розділення екрана й повторіть спробу"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Установити"</string>
     <string name="cancel" msgid="4970902691067201584">"Скасувати"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Сховати інтерфейс перегляду"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Попередній перегляд інтерфейсу приховано. Двічі торкніться, щоб показати."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Скинути зміни?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Зміни не буде збережено"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Більше фонових малюнків"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Фоновий малюнок %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Фоновий малюнок"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Натисніть, щоб редагувати фотографію"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Коригуйте положення, масштаб і кут повороту фотографій"</string>
 </resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 8787b1a..30e80e2 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"روزانہ وال پیپر"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"ہوم اور مقفل اسکرین"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"وال پیپر منتخب کریں"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"وال پیپر تخلیق کریں"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"وال پیپر تخلیق کریں"</string>
     <string name="home_screen_message" msgid="106444102822522813">"ہوم اسکرین"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"مقفل اسکرین"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"ہوم اور لاک"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"ہوم اسکرین وال پیپر کا پیش منظر"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"مجموعہ موجود نہیں ہے"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"براہ کرم سپلٹ اسکرین موڈ سے باہر نکلیں اور دوبارہ کوشش کریں"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"سیٹ کریں"</string>
     <string name="cancel" msgid="4970902691067201584">"منسوخ کریں"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"‏UI کا پیش منظر چھپائیں"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"‏پیش منظر میں UI مخفی ہے۔ پوشیدگی ختم کرنے کیلئے دوبار تھپتھپائیں"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"تبدیلیوں کو ری سیٹ کریں؟"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"آپ کی تبدیلیاں محفوظ نہیں ہوں گی"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"مزید وال پیپرز"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"‏وال پیپرز ‏%1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"وال پیپر"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"اپنی تصویر میں ترمیم کرنے کے لیے تھپتھپائیں"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"اپنی تصاویر کی پوزیشن، اسکیل اور زاویہ کو ایڈجسٹ کریں"</string>
 </resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index bb965c6..e37e90c 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Kunlik fon rasmi"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Bosh ekran va ekran qulfi"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Fon rasmini tanlang"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Fon rasmi yarating"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Fon rasmi yaratish"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Bosh ekran"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Ekran qulfi"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Bosh ekran va ekran qulfi"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Bosh ekran fon rasmiga razm solish"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Bunday terma mavjud emas"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Ajratilgan ekran rejimidan chiqib, qayta urining"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Sozlash"</string>
     <string name="cancel" msgid="4970902691067201584">"Bekor qilish"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Interfeys namunasini berkitish"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Interfeys razm solishda berkitilgan. Chiqarish uchun ikki marta bosing."</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Oʻzgarishlar asliga qaytarilsinmi?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Oʻzgarishlar saqlanmaydi"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Boshqa fon rasmlari"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Fon rasmlari: %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Fon rasmi"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Suratni himoyalash uchun bosing"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Suratlar joylashuvi, miqyosi va burchagini sozlang"</string>
 </resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 81f9d96..645ea85 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Hình nền hàng ngày"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Màn hình chính và màn hình khóa"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Chọn hình nền"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Tạo hình nền"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Tạo hình nền"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Màn hình chính"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Màn hình khóa"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Màn hình chính và khóa"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Xem trước hình nền trên màn hình chính"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Bộ sưu tập không tồn tại"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Vui lòng thoát chế độ chia đôi màn hình rồi thử lại"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Đặt"</string>
     <string name="cancel" msgid="4970902691067201584">"Huỷ"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Ẩn giao diện người dùng xem trước"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"Chế độ xem trước giao diện người dùng hiện đang ẩn. Nhấn đúp để bỏ ẩn"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Đặt lại các thay đổi?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Thay đổi của bạn sẽ không được lưu"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Hình nền khác"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Hình nền %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s, %2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Hình nền"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Nhấn để chỉnh sửa ảnh"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Điều chỉnh vị trí, tỷ lệ và góc ảnh"</string>
 </resources>
diff --git a/res/values-w600dp/dimens.xml b/res/values-w600dp/dimens.xml
index 1b73bd1..c976b0c 100644
--- a/res/values-w600dp/dimens.xml
+++ b/res/values-w600dp/dimens.xml
@@ -25,4 +25,6 @@
 
     <!-- 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>
 </resources>
\ No newline at end of file
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 983232c..e1d2f84 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"每日壁纸"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"主屏幕和锁定屏幕"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"选择一张壁纸"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"制作一张壁纸"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"制作壁纸"</string>
     <string name="home_screen_message" msgid="106444102822522813">"主屏幕"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"锁定屏幕"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"主屏幕和锁定屏幕"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"主屏幕壁纸预览"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"该集合不存在"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"请退出分屏模式并重试"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"设置"</string>
     <string name="cancel" msgid="4970902691067201584">"取消"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"隐藏界面预览"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"界面在预览中处于隐藏状态。点按两次即可取消隐藏"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"要重置更改吗?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"您所做的更改将不会保存"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"更多壁纸"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"壁纸“%1$s”"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s、%2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"壁纸"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"点按即可修改照片"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"调整照片的位置、缩放比和角度"</string>
 </resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 2b87cf7..1b11ad9 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"每日桌布"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"主畫面及上鎖畫面"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"選擇桌布"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"製作桌布"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"製作桌布"</string>
     <string name="home_screen_message" msgid="106444102822522813">"主畫面"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"上鎖畫面"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"主畫面及上鎖畫面"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"主畫面桌布預覽"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"桌布集不存在"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"請退出分割螢幕模式,然後再試一次"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"設定"</string>
     <string name="cancel" msgid="4970902691067201584">"取消"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"隱藏使用者介面預覽"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"預覽入面隱藏咗使用者介面。㩒兩下就可以取消隱藏"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"要重設變更嗎?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"你的變更不會儲存"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"更多桌布"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"桌布 %1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s,%2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"桌布"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"輕按即可編輯相片"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"調整相片的位置、比例和角度"</string>
 </resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index eaf7252..e086c29 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -30,11 +30,11 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"每日桌布"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"主畫面和螢幕鎖定"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"選擇桌布"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"建立桌布"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"建立桌布"</string>
     <string name="home_screen_message" msgid="106444102822522813">"主畫面"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"螢幕鎖定"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"主畫面和螢幕鎖定"</string>
-    <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"設定以下畫面的桌布:"</string>
+    <string name="set_wallpaper_dialog_message" msgid="2110475703996853076">"設為以下畫面的桌布:"</string>
     <string name="set_wallpaper_home_screen_destination" msgid="7315594722013109354">"主畫面"</string>
     <string name="set_wallpaper_lock_screen_destination" msgid="6224685559375417945">"螢幕鎖定"</string>
     <string name="set_wallpaper_both_destination" msgid="2536004558738350775">"主畫面和螢幕鎖定畫面"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"主畫面桌布預覽"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"這個系列不存在"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"請退出分割畫面模式,然後再試一次"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"設定"</string>
     <string name="cancel" msgid="4970902691067201584">"取消"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"隱藏使用者介面預覽畫面"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"預覽畫面隱藏了使用者介面,輕觸兩下即可取消隱藏"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"要重設變更嗎?"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"系統不會儲存你的變更"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"更多桌布"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"「%1$s」桌布"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s,%2$d"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"桌布"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"輕觸即可編輯相片"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"調整相片的位置、比例和角度"</string>
 </resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index cefcfdf..b2f207d 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -30,7 +30,7 @@
     <string name="rotating_wallpaper_presentation_mode_message" msgid="3361676041605733288">"Isithombe sangemuva sansuku zonke"</string>
     <string name="wallpaper_destination_both" msgid="1124197176741944063">"Ikhaya nesikrini sokukhiya"</string>
     <string name="choose_a_wallpaper_section_title" msgid="1009823506890453891">"Khetha Isithombe Sangemuva"</string>
-    <string name="creative_wallpaper_title" msgid="8459226435723103934">"Sungula Isithombe Sangemuva"</string>
+    <string name="creative_wallpaper_title" msgid="3581650238648981372">"Sungula isithombe sangemuva"</string>
     <string name="home_screen_message" msgid="106444102822522813">"Isikrini sasekhaya"</string>
     <string name="lock_screen_message" msgid="1534506081955058013">"Khiya isikrini"</string>
     <string name="home_and_lock_short_label" msgid="2937922943541927983">"Ikhaya nokukhiya"</string>
@@ -104,6 +104,7 @@
     <string name="home_wallpaper_preview_card_content_description" msgid="4059418716070821630">"Ukuhlola kuqala isithombe sangemuva sesikrini sasekhaya"</string>
     <string name="collection_not_exist_msg" msgid="3504852962885064842">"Uqoqo alutholakali"</string>
     <string name="wallpaper_exit_split_screen" msgid="1928870664619591636">"Sicela uphume kumodi yokuhlukanisa isikrini bese uzama futhi"</string>
+    <string name="set_wallpaper_dialog_set_button" msgid="5760149969510325088">"Setha"</string>
     <string name="cancel" msgid="4970902691067201584">"Khansela"</string>
     <string name="hide_ui_preview_text" msgid="6766076482511252295">"Fihla ukuhlola kuqala kwe-UI"</string>
     <string name="hint_hide_ui_preview" msgid="4527603797714586070">"I-UI ifihliwe ekuhloleni kuqala. Thepha kabili ukuze ungafihli"</string>
@@ -130,5 +131,8 @@
     <string name="reset_confirmation_dialog_title" msgid="3391905685838213712">"Setha kabusha izinguquko"</string>
     <string name="reset_confirmation_dialog_message" msgid="888669268626289603">"Izinguquko zakho ngeke zilondolozwe"</string>
     <string name="more_wallpapers" msgid="8116268433411881705">"Izithombe zangemuva ezengeziwe"</string>
-    <string name="recent_wallpaper_label" msgid="3996353584371118367">"Izithombe zangemuva ze-%1$s"</string>
+    <string name="recents_wallpaper_label" msgid="8653165542635660222">"%1$s (%2$d)"</string>
+    <string name="default_wallpaper_title" msgid="2541071182656978180">"Isithombe sangemuva"</string>
+    <string name="small_preview_tooltip" msgid="1920430079013352071">"Thepha ukuze uhlele isithombe sakho"</string>
+    <string name="full_preview_tooltip" msgid="4648994028015322759">"Lungisa ukuma, isilinganeso, kanye ne-engeli yezithombe zakho"</string>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index e1b94b4..ddc6091 100755
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -72,7 +72,6 @@
     <color name="system_surface_container_highest">@android:color/system_surface_container_highest_light</color>
     <color name="system_surface_bright">@android:color/system_surface_bright_light</color>
     <color name="system_outline">@android:color/system_outline_light</color>
-    <color name="system_outline_variant">@android:color/system_outline_variant_light</color>
 
     <!-- UI elements with Dark/Light Theme Variances -->
     <color name="option_item_background">@color/system_surface_container_high</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 8ba305b..0da23c5 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -96,6 +96,8 @@
     <dimen name="set_wallpaper_dialog_item_outer_corner_radius">12dp</dimen>
     <dimen name="set_wallpaper_dialog_item_inner_corner_radius">4dp</dimen>
     <dimen name="set_wallpaper_dialog_icon_size">32dp</dimen>
+    <dimen name="set_wallpaper_dialog_title_padding">5dp</dimen>
+
 
     <!-- Dimensions for the "wallpaper disabled by administrator" UI. -->
     <dimen name="wallpaper_disabled_asset_margin_bottom">26dp</dimen>
@@ -354,6 +356,24 @@
     <dimen name="small_preview_button_padding_horizontal">16dp</dimen>
     <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_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_bottom_padding">16dp</dimen>
+    <dimen name="set_wallpaper_dialog_preview_corner_radius">14dp</dimen>
 
-
+    <!-- Dimensions for wallpaper effects dialog -->
+    <dimen name="wallpaper_effect_download_button_height">48dp</dimen>
+    <dimen name="wallpaper_effect_download_button_width">172dp</dimen>
+    <dimen name="wallpaper_effect_download_button_corner_radius">24dp</dimen>
+    <dimen name="wallpaper_effect_download_image_size">20dp</dimen>
+    <dimen name="wallpaper_effect_download_text_padding_start">8dp</dimen>
+    <dimen name="wallpaper_effect_downloading_progress_size">40dp</dimen>
+    <dimen name="wallpaper_effect_exit_title_size">24sp</dimen>
+    <dimen name="wallpaper_effect_exit_description_size">14sp</dimen>
+    <dimen name="wallpaper_effect_exit_button_height">36dp</dimen>
+    <dimen name="wallpaper_effect_exit_button_text_size">14sp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3e0a6d0..3600e55 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -61,7 +61,7 @@
     <string name="choose_a_wallpaper_section_title">Choose a Wallpaper</string>
 
     <!-- Label indicating the title for Creative Wallpapers block in the WallpaperPicker screen [CHAR LIMIT=100] -->
-    <string name="creative_wallpaper_title">Create a Wallpaper</string>
+    <string name="creative_wallpaper_title">Create wallpaper</string>
 
     <!-- Label referring to the home screen of the device, i.e. shown behind the launcher.
          [CHAR LIMIT=30] -->
@@ -378,6 +378,9 @@
     <!-- Error message advising user to exit our of split screen in order to see preview. [CHAR_LIMIT=NONE] -->
     <string name="wallpaper_exit_split_screen">Please exit split screen mode and try again</string>
 
+    <!-- Label for set wallpaper dialog positive button to set new wallpaper. [CHAR LIMIT=30] -->
+    <string name="set_wallpaper_dialog_set_button">Set</string>
+
     <!-- Label for a cancel button of a dialog. [CHAR LIMIT=30] -->
     <string name="cancel">Cancel</string>
 
@@ -502,6 +505,29 @@
 
     [CHAR LIMIT=128].
     -->
-    <string name="recent_wallpaper_label">Wallpaper %1$s</string>
+    <string name="recents_wallpaper_label">%1$s, %2$d</string>
+
+    <!--
+     Default wallpaper title for wallpapers which do not have an inherent title
+
+    [CHAR LIMIT=128].
+    -->
+    <string name="default_wallpaper_title">Wallpaper</string>
+
+    <!--
+     Tooltip label that appears over the small wallpaper preview, where a user can tap to enter the
+     full screen preview to adjust the wallpaper crop
+
+    [CHAR LIMIT=128].
+    -->
+    <string name="small_preview_tooltip">Tap to edit your photo</string>
+
+    <!--
+     Tooltip label that appears over the full wallpaper preview, where a user can adjust the
+     wallpaper crop
+
+    [CHAR LIMIT=128].
+    -->
+    <string name="full_preview_tooltip">Adjust the position, scale, and angle of your photos</string>
 
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 8112e3a..53588ca 100755
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -259,7 +259,9 @@
     </style>
 
     <!-- SetWallpaperPreviewDialog -->
-    <style name="SetWallpaperPreviewDialogTheme" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar.MinWidth">
+    <style name="SetWallpaperPreviewDialogTheme" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
+        <item name="android:windowMinWidthMajor">0dp</item>
+        <item name="android:windowMinWidthMinor">0dp</item>
         <item name="android:buttonBarPositiveButtonStyle">@style/SetWallpaperDialog.Button</item>
         <item name="android:buttonBarNegativeButtonStyle">@style/SetWallpaperDialog.Button.OutlinedButton</item>
         <item name="android:buttonBarNeutralButtonStyle">@style/SetWallpaperDialog.Button.TextButton</item>
@@ -267,7 +269,7 @@
 
     <style name="SetWallpaperDialog"/>
     <style name="SetWallpaperDialog.Button">
-        <item name="android:textColor">@color/system_on_primary</item>
+        <item name="android:textColor">@color/system_on_secondary</item>
         <item name="android:background">@drawable/set_wallpaper_dialog_button</item>
     </style>
 
@@ -282,10 +284,18 @@
     </style>
 
     <style name="TextAppearance.SetWallpaperDialog.Title" parent="@android:style/TextAppearance.DeviceDefault.Large">
-        <item name="android:textColor">@color/system_on_surface</item>
+        <item name="android:textColor">@color/system_on_surface_variant</item>
         <item name="android:textSize">24sp</item>
-        <item name="android:lineHeight">32sp</item>
         <item name="android:gravity">center</item>
         <item name="android:textAlignment">center</item>
+        <item name="android:paddingVertical">@dimen/abc_dialog_padding_top_material</item>
+        <item name="android:paddingHorizontal">?attr/dialogPreferredPadding</item>
+    </style>
+
+    <style name="TextAppearance.SetWallpaperDialog.Subtitle" parent="@android:style/TextAppearance.DeviceDefault.Small">
+        <item name="android:textColor">@color/system_on_surface</item>
+        <item name="android:gravity">center</item>
+        <item name="android:textAlignment">center</item>
+        <item name="android:paddingVertical">8dp</item>
     </style>
 </resources>
diff --git a/src/com/android/customization/model/color/DefaultWallpaperColorResources.kt b/src/com/android/customization/model/color/DefaultWallpaperColorResources.kt
new file mode 100644
index 0000000..f92b4f3
--- /dev/null
+++ b/src/com/android/customization/model/color/DefaultWallpaperColorResources.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.customization.model.color
+
+import android.R
+import android.app.WallpaperColors
+import android.content.Context
+import com.android.systemui.monet.ColorScheme
+
+/** A class to override colors in a [Context] with wallpaper colors. */
+class DefaultWallpaperColorResources(private val wallpaperColors: WallpaperColors) :
+    WallpaperColorResources() {
+
+    override suspend fun apply(context: Context, callback: () -> Unit) {
+        val wallpaperColorScheme = ColorScheme(wallpaperColors = wallpaperColors, darkTheme = false)
+        with(wallpaperColorScheme) {
+            addOverlayColor(neutral1, R.color.system_neutral1_10)
+            addOverlayColor(neutral2, R.color.system_neutral2_10)
+            addOverlayColor(accent1, R.color.system_accent1_10)
+            addOverlayColor(accent2, R.color.system_accent2_10)
+            addOverlayColor(accent3, R.color.system_accent3_10)
+        }
+        applyToContext(context)
+        callback.invoke()
+    }
+}
diff --git a/src/com/android/customization/model/color/WallpaperColorResources.kt b/src/com/android/customization/model/color/WallpaperColorResources.kt
index 6a7b7ed..dcd33cf 100644
--- a/src/com/android/customization/model/color/WallpaperColorResources.kt
+++ b/src/com/android/customization/model/color/WallpaperColorResources.kt
@@ -13,37 +13,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.customization.model.color
 
-import android.R
-import android.app.WallpaperColors
 import android.content.Context
 import android.util.SparseIntArray
-import android.widget.RemoteViews.ColorResources
-import com.android.systemui.monet.ColorScheme
+import android.widget.RemoteViews
 import com.android.systemui.monet.TonalPalette
 
-/** A class to override colors in a [Context] with wallpaper colors. */
-open class WallpaperColorResources(wallpaperColors: WallpaperColors) {
+abstract class WallpaperColorResources {
     private val colorOverlay = SparseIntArray()
 
-    init {
-        val wallpaperColorScheme = ColorScheme(wallpaperColors = wallpaperColors, darkTheme = false)
-        with(wallpaperColorScheme) {
-            addOverlayColor(neutral1, R.color.system_neutral1_10)
-            addOverlayColor(neutral2, R.color.system_neutral2_10)
-            addOverlayColor(accent1, R.color.system_accent1_10)
-            addOverlayColor(accent2, R.color.system_accent2_10)
-            addOverlayColor(accent3, R.color.system_accent3_10)
-        }
-    }
-
     /** Applies the wallpaper color resources to the `context`. */
-    fun apply(context: Context) {
-        ColorResources.create(context, colorOverlay)?.apply(context)
+    abstract suspend fun apply(context: Context, callback: () -> Unit)
+
+    protected fun applyToContext(context: Context) {
+        RemoteViews.ColorResources.create(context, colorOverlay)?.apply(context)
     }
 
-    fun addOverlayColor(colorSchemeHue: TonalPalette, firstResourceColorId: Int) {
+    protected fun addOverlayColor(colorSchemeHue: TonalPalette, firstResourceColorId: Int) {
         colorSchemeHue.allShades.forEachIndexed { index, color ->
             colorOverlay.put(firstResourceColorId + index, color)
         }
diff --git a/src/com/android/wallpaper/asset/Asset.java b/src/com/android/wallpaper/asset/Asset.java
index 26feca6..e2d3704 100755
--- a/src/com/android/wallpaper/asset/Asset.java
+++ b/src/com/android/wallpaper/asset/Asset.java
@@ -37,6 +37,7 @@
 
 import com.android.wallpaper.module.BitmapCropper;
 import com.android.wallpaper.module.InjectorProvider;
+import com.android.wallpaper.picker.preview.ui.util.CropSizeUtil;
 import com.android.wallpaper.util.RtlUtils;
 import com.android.wallpaper.util.ScreenSizeCalculator;
 import com.android.wallpaper.util.WallpaperCropUtils;
@@ -44,6 +45,7 @@
 import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
 
 import java.io.File;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -327,6 +329,24 @@
      */
     public void loadPreviewImage(Activity activity, ImageView imageView, int placeholderColor,
             boolean offsetToStart) {
+        loadPreviewImage(activity, imageView, placeholderColor, offsetToStart, null);
+    }
+
+    /**
+     * Loads the image for this asset into the provided ImageView which is used for the preview.
+     * While waiting for the image to load, first loads a ColorDrawable based on the provided
+     * placeholder color.
+     *
+     * @param activity         Activity hosting the ImageView.
+     * @param imageView        ImageView which is the target view of this asset.
+     * @param placeholderColor Color of placeholder set to ImageView while waiting for image to
+     *                         load.
+     * @param offsetToStart    true to let the preview show from the start of the image, false to
+     *                         center-aligned to the image.
+     * @param cropHints        A Map of display size to crop rect
+     */
+    public void loadPreviewImage(Activity activity, ImageView imageView, int placeholderColor,
+            boolean offsetToStart, @Nullable Map<Point, Rect> cropHints) {
         boolean needsTransition = imageView.getDrawable() == null;
         Drawable placeholderDrawable = new ColorDrawable(placeholderColor);
         if (needsTransition) {
@@ -344,17 +364,26 @@
                 return;
             }
 
+            boolean isRtl = RtlUtils.isRtl(activity);
             Display defaultDisplay = activity.getWindowManager().getDefaultDisplay();
             Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(defaultDisplay);
             Rect visibleRawWallpaperRect =
                     WallpaperCropUtils.calculateVisibleRect(dimensions, screenSize);
+            if (cropHints != null && cropHints.containsKey(screenSize)) {
+                visibleRawWallpaperRect = CropSizeUtil.INSTANCE.fitCropRectToLayoutDirection(
+                        cropHints.get(screenSize), screenSize, RtlUtils.isRtl(activity));
+                // For multi-crop, the visibleRawWallpaperRect above is already the exact size of
+                // the part of wallpaper we should show on the screen, turning off the old RTL
+                // logic by assigning false.
+                isRtl = false;
+            }
 
             // TODO(b/264234793): Make offsetToStart general support or for the specific asset.
             adjustCropRect(activity, dimensions, visibleRawWallpaperRect, offsetToStart);
 
             BitmapCropper bitmapCropper = InjectorProvider.getInjector().getBitmapCropper();
             bitmapCropper.cropAndScaleBitmap(this, /* scale= */ 1f, visibleRawWallpaperRect,
-                    RtlUtils.isRtl(activity),
+                    isRtl,
                     new BitmapCropper.Callback() {
                         @Override
                         public void onBitmapCropped(Bitmap croppedBitmap) {
diff --git a/src/com/android/wallpaper/asset/BitmapCachingAsset.java b/src/com/android/wallpaper/asset/BitmapCachingAsset.java
index 666c4ef..61888b8 100644
--- a/src/com/android/wallpaper/asset/BitmapCachingAsset.java
+++ b/src/com/android/wallpaper/asset/BitmapCachingAsset.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.LruCache;
 import android.widget.ImageView;
@@ -26,6 +27,7 @@
 import androidx.annotation.Nullable;
 import androidx.core.app.ActivityManagerCompat;
 
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -167,4 +169,12 @@
         // Honor the original Asset's preview image loading
         mOriginalAsset.loadPreviewImage(activity, imageView, placeholderColor, offsetToStart);
     }
+
+    @Override
+    public void loadPreviewImage(Activity activity, ImageView imageView, int placeholderColor,
+            boolean offsetToStart, @Nullable Map<Point, Rect> cropHints) {
+        // Honor the original Asset's preview image loading
+        mOriginalAsset.loadPreviewImage(activity, imageView, placeholderColor, offsetToStart,
+                cropHints);
+    }
 }
diff --git a/src/com/android/wallpaper/asset/CurrentWallpaperAsset.java b/src/com/android/wallpaper/asset/CurrentWallpaperAsset.java
index 22a9e6c..b2c58bc 100755
--- a/src/com/android/wallpaper/asset/CurrentWallpaperAsset.java
+++ b/src/com/android/wallpaper/asset/CurrentWallpaperAsset.java
@@ -57,10 +57,14 @@
     @SetWallpaperFlags
     private final int mWallpaperManagerFlag;
 
-    public CurrentWallpaperAsset(Context context, @SetWallpaperFlags int wallpaperManagerFlag) {
+    private final boolean mCropped;
+
+    public CurrentWallpaperAsset(Context context, @SetWallpaperFlags int wallpaperManagerFlag,
+            boolean getCropped) {
         mWallpaperManager = WallpaperManager.getInstance(context.getApplicationContext());
         mWallpaperManagerFlag = wallpaperManagerFlag;
         mWallpaperId = mWallpaperManager.getWallpaperId(mWallpaperManagerFlag);
+        mCropped = getCropped;
     }
 
     @Override
@@ -149,7 +153,7 @@
     }
 
     ParcelFileDescriptor getWallpaperPfd() {
-        return mWallpaperManager.getWallpaperFile(mWallpaperManagerFlag);
+        return mWallpaperManager.getWallpaperFile(mWallpaperManagerFlag, mCropped);
     }
 
     /**
diff --git a/src/com/android/wallpaper/asset/StreamableAsset.java b/src/com/android/wallpaper/asset/StreamableAsset.java
index c2281c4..61817b9 100755
--- a/src/com/android/wallpaper/asset/StreamableAsset.java
+++ b/src/com/android/wallpaper/asset/StreamableAsset.java
@@ -106,17 +106,22 @@
             }
 
             InputStream inputStream = openInputStream();
-            Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
-            closeInputStream(
-                    inputStream, "Error closing the input stream used to decode the full bitmap");
+            Bitmap bitmap = null;
+            if (inputStream != null) {
+                bitmap = BitmapFactory.decodeStream(inputStream, null, options);
+                closeInputStream(
+                        inputStream, "Error closing the input stream used "
+                                + "to decode the full bitmap");
 
-            // Rotate output bitmap if necessary because of EXIF orientation tag.
-            int matrixRotation = getDegreesRotationForExifOrientation(exifOrientation);
-            if (matrixRotation > 0) {
-                Matrix rotateMatrix = new Matrix();
-                rotateMatrix.setRotate(matrixRotation);
-                bitmap = Bitmap.createBitmap(
-                        bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), rotateMatrix, false);
+                // Rotate output bitmap if necessary because of EXIF orientation tag.
+                int matrixRotation = getDegreesRotationForExifOrientation(exifOrientation);
+                if (matrixRotation > 0) {
+                    Matrix rotateMatrix = new Matrix();
+                    rotateMatrix.setRotate(matrixRotation);
+                    bitmap = Bitmap.createBitmap(
+                            bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
+                            rotateMatrix, false);
+                }
             }
             decodeBitmapCompleted(receiver, bitmap);
         });
@@ -128,18 +133,21 @@
             BitmapFactory.Options options = new BitmapFactory.Options();
             options.inPreferredConfig = Config.HARDWARE;
             InputStream inputStream = openInputStream();
-            Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
-            closeInputStream(inputStream,
-                    "Error closing the input stream used to decode the full bitmap");
+            Bitmap bitmap = null;
+            if (inputStream != null) {
+                bitmap = BitmapFactory.decodeStream(inputStream, null, options);
+                closeInputStream(inputStream,
+                        "Error closing the input stream used to decode the full bitmap");
 
-            // Rotate output bitmap if necessary because of EXIF orientation tag.
-            int exifOrientation = getExifOrientation();
-            int matrixRotation = getDegreesRotationForExifOrientation(exifOrientation);
-            if (matrixRotation > 0) {
-                Matrix rotateMatrix = new Matrix();
-                rotateMatrix.setRotate(matrixRotation);
-                bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
-                        rotateMatrix, false);
+                // Rotate output bitmap if necessary because of EXIF orientation tag.
+                int exifOrientation = getExifOrientation();
+                int matrixRotation = getDegreesRotationForExifOrientation(exifOrientation);
+                if (matrixRotation > 0) {
+                    Matrix rotateMatrix = new Matrix();
+                    rotateMatrix.setRotate(matrixRotation);
+                    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
+                            bitmap.getHeight(), rotateMatrix, false);
+                }
             }
             decodeBitmapCompleted(receiver, bitmap);
         });
diff --git a/src/com/android/wallpaper/backup/MissingHashCodeGeneratorJobService.java b/src/com/android/wallpaper/backup/MissingHashCodeGeneratorJobService.java
index e7a970e..a449005 100755
--- a/src/com/android/wallpaper/backup/MissingHashCodeGeneratorJobService.java
+++ b/src/com/android/wallpaper/backup/MissingHashCodeGeneratorJobService.java
@@ -38,7 +38,6 @@
 import com.android.wallpaper.module.InjectorProvider;
 import com.android.wallpaper.module.JobSchedulerJobIds;
 import com.android.wallpaper.module.WallpaperPreferences;
-import com.android.wallpaper.util.DiskBasedLogger;
 
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -95,12 +94,6 @@
                     // platform issue -- being extra defensive with this check due to instability
                     // and variability of underlying platform.
                     if (wallpaperDrawable == null) {
-                        DiskBasedLogger.e(
-                                TAG,
-                                "WallpaperManager#getDrawable returned null and there's no live "
-                                        + "wallpaper set",
-                                context
-                        );
                         jobFinished(jobParameters, false /* needsReschedule */);
                         return;
                     }
diff --git a/src/com/android/wallpaper/model/category /ThirdPartyCategoryData.kt b/src/com/android/wallpaper/categorypicker/viewmodel/SectionViewModel.kt
similarity index 64%
copy from src/com/android/wallpaper/model/category /ThirdPartyCategoryData.kt
copy to src/com/android/wallpaper/categorypicker/viewmodel/SectionViewModel.kt
index 0db6766..0420734 100644
--- a/src/com/android/wallpaper/model/category /ThirdPartyCategoryData.kt
+++ b/src/com/android/wallpaper/categorypicker/viewmodel/SectionViewModel.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.
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.category
-
-import android.content.pm.ResolveInfo
+package com.android.wallpaper.categorypicker.viewmodel
 
 /**
- * Represents set of attributes required for displaying a 3rd party wallpaper app installed on
- * device.
+ * This class represents the view model for a single section that can contain a number of individual
+ * tiles.
  */
-data class ThirdPartyCategoryData(val resolveInfo: ResolveInfo)
+class SectionViewModel(private val items: List<TileViewModel>, private val columnCount: Int)
diff --git a/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt b/src/com/android/wallpaper/categorypicker/viewmodel/TileViewModel.kt
similarity index 63%
copy from src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt
copy to src/com/android/wallpaper/categorypicker/viewmodel/TileViewModel.kt
index 0eca60f..9c1489e 100644
--- a/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt
+++ b/src/com/android/wallpaper/categorypicker/viewmodel/TileViewModel.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.
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.categorypicker.viewmodel
 
-import android.graphics.Rect
 import com.android.wallpaper.asset.Asset
 
-/** Represents set of attributes that are needed for a static wallpaper. */
-data class StaticWallpaperData(
-    val asset: Asset,
-    val cropHints: Map<ScreenOrientation, Rect>? = null,
+/** This class represents the view model for a single category tile. */
+class TileViewModel(
+    private val thumbAsset: Asset,
+    private val overlayAsset: Asset,
+    private val text: String,
+    val onClicked: (() -> Unit)? = null
 )
diff --git a/src/com/android/wallpaper/model/category /CommonCategoryData.kt b/src/com/android/wallpaper/effects/DefaultEffectsController.kt
similarity index 63%
copy from src/com/android/wallpaper/model/category /CommonCategoryData.kt
copy to src/com/android/wallpaper/effects/DefaultEffectsController.kt
index bf28bb6..8ce1438 100644
--- a/src/com/android/wallpaper/model/category /CommonCategoryData.kt
+++ b/src/com/android/wallpaper/effects/DefaultEffectsController.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.
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.category
+package com.android.wallpaper.effects
 
-/** Represents set of attributes that are common for all categories. */
-data class CommonCategoryData(val title: String, val collectionId: String, val priority: Int)
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/** Default [EffectsController] implementation for injecting into public picker app. */
+@Singleton class DefaultEffectsController @Inject constructor() : EffectsController()
diff --git a/src/com/android/wallpaper/model/wallpaper/ImageWallpaperData.kt b/src/com/android/wallpaper/effects/Effect.kt
similarity index 62%
copy from src/com/android/wallpaper/model/wallpaper/ImageWallpaperData.kt
copy to src/com/android/wallpaper/effects/Effect.kt
index b53b7a7..d416952 100644
--- a/src/com/android/wallpaper/model/wallpaper/ImageWallpaperData.kt
+++ b/src/com/android/wallpaper/effects/Effect.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.
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.effects
 
-import android.net.Uri
+import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
 
-/**
- * Represents data that is specific only for image wallpapers (i.e. wallpapers that are fetched from
- * local storage through the MyPhotos block in WallpaperPicker)
- */
-data class ImageWallpaperData(val uri: Uri)
+/** A class that includes effect's data from wallpaper effects. */
+data class Effect(
+    val id: Int,
+    val title: String,
+    val type: EffectEnumInterface,
+)
diff --git a/src/com/android/wallpaper/effects/EffectContract.kt b/src/com/android/wallpaper/effects/EffectContract.kt
new file mode 100644
index 0000000..18ae625
--- /dev/null
+++ b/src/com/android/wallpaper/effects/EffectContract.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.effects
+
+/** Contract between picker and effects. */
+object EffectContract {
+    const val ASSET_ID = "ASSET_ID"
+
+    /** Key value for querying effect id. */
+    const val KEY_EFFECT_ID = "id"
+
+    /** Key value for querying effect title. */
+    const val KEY_EFFECT_TITLE = "effectTitle"
+}
diff --git a/src/com/android/wallpaper/effects/EffectsController.java b/src/com/android/wallpaper/effects/EffectsController.java
index ab92efb..b7f4f04 100644
--- a/src/com/android/wallpaper/effects/EffectsController.java
+++ b/src/com/android/wallpaper/effects/EffectsController.java
@@ -61,7 +61,7 @@
      * @param effect the effect type we want to generate.
      * @param image  the image that will have the effect applied.
      */
-    public void generateEffect(Effect effect, Uri image) {
+    public void generateEffect(EffectEnumInterface effect, Uri image) {
     }
 
     /**
@@ -93,6 +93,17 @@
     public void triggerEffect(Context context) {
     }
 
+    /** Sets the {@link EffectsServiceListener} to receive updates. */
+    public void setListener(EffectsServiceListener listener) {}
+
+    /** Removes the listener set via {@link #setListener(EffectsServiceListener)}. */
+    public void removeListener() {}
+
+    /** Returns true if the effect is expected by this controller. */
+    public boolean isTargetEffect(EffectEnumInterface effect) {
+        return effect == getTargetEffect();
+    }
+
     /**
      * Interface to listen to different key moments of the connection with the Effects Service.
      */
@@ -110,6 +121,10 @@
                 int originalStatusCode, String errorMessage);
     }
 
+    public EffectEnumInterface getTargetEffect() {
+        return Effect.NONE;
+    }
+
     /**
      * Gets whether the effect triggering is successful or not.
      *
@@ -119,4 +134,27 @@
         return false;
     }
 
+    public String getEffectTitle() {
+        return "";
+    }
+
+    public String getEffectFailedTitle() {
+        return "";
+    }
+
+    public String getEffectSubTitle() {
+        return "";
+    }
+
+    public String getRetryInstruction() {
+        return "";
+    }
+
+    public String getNoEffectInstruction() {
+        return "";
+    }
+
+    public Uri getContentUri() {
+        return Uri.EMPTY;
+    }
 }
diff --git a/src/com/android/wallpaper/model/CurrentWallpaperInfo.java b/src/com/android/wallpaper/model/CurrentWallpaperInfo.java
index 1f22310..a1f1a81 100755
--- a/src/com/android/wallpaper/model/CurrentWallpaperInfo.java
+++ b/src/com/android/wallpaper/model/CurrentWallpaperInfo.java
@@ -25,6 +25,7 @@
 import com.android.wallpaper.asset.Asset;
 import com.android.wallpaper.asset.BuiltInWallpaperAsset;
 import com.android.wallpaper.asset.CurrentWallpaperAsset;
+import com.android.wallpaper.config.BaseFlags;
 import com.android.wallpaper.module.InjectorProvider;
 
 import java.util.ArrayList;
@@ -123,10 +124,16 @@
         boolean isSystemBuiltIn = mWallpaperManagerFlag == WallpaperManager.FLAG_SYSTEM
                 && !InjectorProvider.getInjector().getWallpaperStatusChecker(context)
                 .isHomeStaticWallpaperSet();
+        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();
 
         return (isSystemBuiltIn)
                 ? new BuiltInWallpaperAsset(context)
-                : new CurrentWallpaperAsset(context, mWallpaperManagerFlag);
+                : new CurrentWallpaperAsset(context, mWallpaperManagerFlag, /* getCropped= */
+                        !getFullAsset);
     }
 
     @Override
diff --git a/src/com/android/wallpaper/model/LiveWallpaperMetadata.java b/src/com/android/wallpaper/model/LiveWallpaperMetadata.java
index 26ed9fc..3deaa5d 100644
--- a/src/com/android/wallpaper/model/LiveWallpaperMetadata.java
+++ b/src/com/android/wallpaper/model/LiveWallpaperMetadata.java
@@ -16,12 +16,11 @@
 package com.android.wallpaper.model;
 
 import android.app.WallpaperInfo;
+import android.graphics.Point;
 import android.graphics.Rect;
 
 import androidx.annotation.Nullable;
 
-import com.android.wallpaper.model.wallpaper.ScreenOrientation;
-
 import java.util.List;
 import java.util.Map;
 
@@ -55,7 +54,7 @@
 
     @Nullable
     @Override
-    public Map<ScreenOrientation, Rect> getWallpaperCropHints() {
+    public Map<Point, Rect> getWallpaperCropHints() {
         throw new UnsupportedOperationException("Not implemented for live wallpapers");
     }
 }
diff --git a/src/com/android/wallpaper/model/StaticWallpaperMetadata.kt b/src/com/android/wallpaper/model/LiveWallpaperPrefMetadata.kt
similarity index 68%
copy from src/com/android/wallpaper/model/StaticWallpaperMetadata.kt
copy to src/com/android/wallpaper/model/LiveWallpaperPrefMetadata.kt
index d30479e..033c46b 100755
--- a/src/com/android/wallpaper/model/StaticWallpaperMetadata.kt
+++ b/src/com/android/wallpaper/model/LiveWallpaperPrefMetadata.kt
@@ -15,16 +15,11 @@
  */
 package com.android.wallpaper.model
 
-import android.graphics.Rect
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-
-/** Metadata for the static image wallpaper to be saved to the system preferences. */
-data class StaticWallpaperMetadata(
+/** Metadata for the live wallpaper to be saved to the system preferences. */
+data class LiveWallpaperPrefMetadata(
     val attributions: List<String?>?,
-    val actionUrl: String?,
+    val serviceName: String,
+    val effectName: String?,
     val collectionId: String?,
-    val hashCode: Long?,
     val managerId: Int,
-    val remoteId: String,
-    val cropHints: Map<ScreenOrientation, Rect>?,
 )
diff --git a/src/com/android/wallpaper/model/StaticWallpaperMetadata.kt b/src/com/android/wallpaper/model/StaticWallpaperPrefMetadata.kt
similarity index 83%
rename from src/com/android/wallpaper/model/StaticWallpaperMetadata.kt
rename to src/com/android/wallpaper/model/StaticWallpaperPrefMetadata.kt
index d30479e..8a29b27 100755
--- a/src/com/android/wallpaper/model/StaticWallpaperMetadata.kt
+++ b/src/com/android/wallpaper/model/StaticWallpaperPrefMetadata.kt
@@ -15,16 +15,12 @@
  */
 package com.android.wallpaper.model
 
-import android.graphics.Rect
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-
 /** Metadata for the static image wallpaper to be saved to the system preferences. */
-data class StaticWallpaperMetadata(
+data class StaticWallpaperPrefMetadata(
     val attributions: List<String?>?,
     val actionUrl: String?,
     val collectionId: String?,
     val hashCode: Long?,
     val managerId: Int,
     val remoteId: String,
-    val cropHints: Map<ScreenOrientation, Rect>?,
 )
diff --git a/src/com/android/wallpaper/model/ThirdPartyAppCategory.java b/src/com/android/wallpaper/model/ThirdPartyAppCategory.java
index ddc12a7..84d991d 100755
--- a/src/com/android/wallpaper/model/ThirdPartyAppCategory.java
+++ b/src/com/android/wallpaper/model/ThirdPartyAppCategory.java
@@ -131,4 +131,8 @@
     public boolean containsThirdParty(String packageName) {
         return mResolveInfo.activityInfo.packageName.equals(packageName);
     }
+
+    public ResolveInfo getResolveInfo() {
+        return mResolveInfo;
+    }
 }
diff --git a/src/com/android/wallpaper/model/WallpaperCategory.java b/src/com/android/wallpaper/model/WallpaperCategory.java
index 77dbd7c..bea8d4b 100755
--- a/src/com/android/wallpaper/model/WallpaperCategory.java
+++ b/src/com/android/wallpaper/model/WallpaperCategory.java
@@ -78,6 +78,17 @@
         // No op
     }
 
+    public List<WallpaperInfo> getWallpapers() {
+        return mWallpapers;
+    }
+
+    public Asset getThumbAsset() {
+        return mThumbAsset;
+    }
+
+    public int getFeaturedThumbnailIndex() {
+        return mFeaturedThumbnailIndex;
+    }
     @Override
     public boolean isEnumerable() {
         return true;
diff --git a/src/com/android/wallpaper/model/WallpaperInfo.java b/src/com/android/wallpaper/model/WallpaperInfo.java
index 31cb367..82b0e40 100755
--- a/src/com/android/wallpaper/model/WallpaperInfo.java
+++ b/src/com/android/wallpaper/model/WallpaperInfo.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -29,9 +30,11 @@
 
 import androidx.annotation.DrawableRes;
 import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
 
 import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.model.wallpaper.ScreenOrientation;
+import com.android.wallpaper.config.BaseFlags;
+import com.android.wallpaper.module.InjectorProvider;
 
 import java.util.HashMap;
 import java.util.Iterator;
@@ -53,7 +56,7 @@
 
     private PriorityQueue<String> mEffectNames = new PriorityQueue<>();
 
-    protected final HashMap<Integer, String> mCropHints = new HashMap<>();
+    protected final HashMap<String, String> mCropHints = new HashMap<>();
 
     public WallpaperInfo() {
     }
@@ -301,26 +304,33 @@
         return Resources.ID_NULL;
     }
 
-    /** Sets the crop {@link Rect} of each {@link ScreenOrientation} for this wallpaper. */
-    public void setWallpaperCropHints(Map<ScreenOrientation, Rect> cropHints) {
+    /** Sets the crop {@link Rect} of each displaySize for this wallpaper. */
+    public void setWallpaperCropHints(Map<Point, Rect> cropHints) {
         if (cropHints == null) {
             return;
         }
 
-        cropHints.forEach((orientation, rect) -> {
+        cropHints.forEach((displaySize, rect) -> {
             if (rect != null) {
-                mCropHints.put(orientation.ordinal(),
+                mCropHints.put(displaySize.flattenToString(),
                         rect.flattenToString());
             }
         });
     }
 
-    /** Returns the crop {@link Rect} of each {@link ScreenOrientation} for this wallpaper. */
-    public Map<ScreenOrientation, Rect> getWallpaperCropHints() {
-        Map<ScreenOrientation, Rect> cropHints = new HashMap<>();
+    /** 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) {
+            return null;
+        }
+
+        Map<Point, Rect> cropHints = new HashMap<>();
         mCropHints.forEach(
-                (orientation, rect) -> cropHints.put(
-                        ScreenOrientation.getEntries().get(orientation),
+                (displaySize, rect) -> cropHints.put(
+                        Point.unflattenFromString(displaySize),
                         Rect.unflattenFromString(rect)));
         return cropHints;
     }
diff --git a/src/com/android/wallpaper/model/WallpaperMetadata.java b/src/com/android/wallpaper/model/WallpaperMetadata.java
index 2ac7c49..8febb72 100755
--- a/src/com/android/wallpaper/model/WallpaperMetadata.java
+++ b/src/com/android/wallpaper/model/WallpaperMetadata.java
@@ -16,12 +16,11 @@
 package com.android.wallpaper.model;
 
 import android.app.WallpaperInfo;
+import android.graphics.Point;
 import android.graphics.Rect;
 
 import androidx.annotation.Nullable;
 
-import com.android.wallpaper.model.wallpaper.ScreenOrientation;
-
 import java.util.List;
 import java.util.Map;
 
@@ -33,11 +32,11 @@
     private final List<String> mAttributions;
     private final String mActionUrl;
     private final String mCollectionId;
-    @Nullable private final Map<ScreenOrientation, Rect> mCropHints;
+    @Nullable private final Map<Point, Rect> mCropHints;
     protected final android.app.WallpaperInfo mWallpaperComponent;
 
     public WallpaperMetadata(List<String> attributions, String actionUrl, String collectionId,
-            android.app.WallpaperInfo wallpaperComponent, Map<ScreenOrientation, Rect> cropHints) {
+            android.app.WallpaperInfo wallpaperComponent, Map<Point, Rect> cropHints) {
         mAttributions = attributions;
         mActionUrl = actionUrl;
         mCollectionId = collectionId;
@@ -75,12 +74,12 @@
     }
 
     /**
-     * Returns the crop {@link Rect} of each {@link ScreenOrientation} for this wallpaper.
+     * Returns the crop {@link Rect} of each display size for this wallpaper.
      *
      * <p>Live wallpaper metadata should return null.
      */
     @Nullable
-    public Map<ScreenOrientation, Rect> getWallpaperCropHints() {
+    public Map<Point, Rect> getWallpaperCropHints() {
         return mCropHints;
     }
 }
diff --git a/src/com/android/wallpaper/model/wallpaper/ScreenOrientation.kt b/src/com/android/wallpaper/model/wallpaper/ScreenOrientation.kt
deleted file mode 100644
index c7ed038..0000000
--- a/src/com/android/wallpaper/model/wallpaper/ScreenOrientation.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 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.model.wallpaper
-
-import android.graphics.Point
-
-/** Orientation of the screen. */
-enum class ScreenOrientation {
-    /** For screen of handheld, tablet, and outer screen of foldable, in portrait mode */
-    PORTRAIT,
-    /** For screen of handheld, tablet, and outer screen of foldable, in landscape mode */
-    LANDSCAPE,
-    /** For inner screen of foldable, in portrait mode */
-    UNFOLDED_PORTRAIT,
-    /** For inner screen of foldable, in landscape mode */
-    UNFOLDED_LANDSCAPE,
-}
-
-/**
- * Gets the [ScreenOrientation] based on the display and its size.
- *
- * @param displaySize size of the display.
- * @param foldableDisplay the display of [displaySize] on foldable devices, null for single display
- *   devices.
- */
-fun getScreenOrientation(
-    displaySize: Point,
-    foldableDisplay: FoldableDisplay? = null,
-): ScreenOrientation {
-    return if (foldableDisplay == null || foldableDisplay == FoldableDisplay.FOLDED) {
-        if (displaySize.y >= displaySize.x) ScreenOrientation.PORTRAIT
-        else ScreenOrientation.LANDSCAPE
-    } else {
-        if (displaySize.y >= displaySize.x) ScreenOrientation.UNFOLDED_PORTRAIT
-        else ScreenOrientation.UNFOLDED_LANDSCAPE
-    }
-}
diff --git a/src/com/android/wallpaper/module/DailyLoggingAlarmReceiver.java b/src/com/android/wallpaper/module/DailyLoggingAlarmReceiver.java
index aa78b98..c22ac78 100755
--- a/src/com/android/wallpaper/module/DailyLoggingAlarmReceiver.java
+++ b/src/com/android/wallpaper/module/DailyLoggingAlarmReceiver.java
@@ -20,7 +20,6 @@
 import android.content.Intent;
 
 import com.android.wallpaper.module.logging.UserEventLogger;
-import com.android.wallpaper.util.DiskBasedLogger;
 
 /**
  * Performs daily logging operations when alarm is received.
@@ -31,14 +30,11 @@
     public void onReceive(Context context, Intent intent) {
         Context appContext = context.getApplicationContext();
         Injector injector = InjectorProvider.getInjector();
-        UserEventLogger logger = injector.getUserEventLogger(appContext);
+        UserEventLogger logger = injector.getUserEventLogger();
         WallpaperPreferences preferences = injector.getPreferences(appContext);
 
         logger.logSnapshot();
 
         preferences.setLastDailyLogTimestamp(System.currentTimeMillis());
-
-        // Clear disk-based logs older than 7 days if they exist.
-        DiskBasedLogger.clearOldLogs(appContext);
     }
 }
diff --git a/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java b/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
index 3a877f4..9e8cb95 100755
--- a/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
+++ b/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
@@ -18,6 +18,7 @@
 import android.app.WallpaperManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.graphics.Point;
 
 import androidx.annotation.Nullable;
 
@@ -26,6 +27,11 @@
 import com.android.wallpaper.model.LiveWallpaperMetadata;
 import com.android.wallpaper.model.WallpaperInfo;
 import com.android.wallpaper.module.WallpaperPreferences.PresentationMode;
+import com.android.wallpaper.picker.customization.data.content.WallpaperClient;
+import com.android.wallpaper.util.DisplayUtils;
+
+import java.util.HashMap;
+import java.util.List;
 
 /**
  * Default implementation of {@link CurrentWallpaperInfoFactory} which actually constructs
@@ -52,10 +58,49 @@
     @Override
     public synchronized void createCurrentWallpaperInfos(Context context, boolean forceRefresh,
             WallpaperInfoCallback callback) {
+
+        BaseFlags flags = InjectorProvider.getInjector().getFlags();
+        final boolean isMultiCropEnabled =
+                flags.isMultiCropEnabled() && flags.isMultiCropPreviewUiEnabled();
+
         boolean isHomeWallpaperSynced  = homeWallpaperSynced(context);
         boolean isLockWallpaperSynced  = lockWallpaperSynced(context);
         if (!forceRefresh && isHomeWallpaperSynced && isLockWallpaperSynced
                 && mPresentationMode != WallpaperPreferences.PRESENTATION_MODE_ROTATING) {
+            // Update wallpaper crop hints for static wallpaper even if home & lock wallpaper are
+            // considered synced because wallpaper info are considered synced as long as both are
+            // static
+            if (isMultiCropEnabled) {
+                DisplayUtils displayUtils = InjectorProvider.getInjector().getDisplayUtils(context);
+                WallpaperClient wallpaperClient = InjectorProvider.getInjector().getWallpaperClient(
+                        context);
+                List<Point> displaySizes = displayUtils.getInternalDisplaySizes();
+                if (mHomeWallpaper != null) {
+                    boolean isHomeWallpaperStatic = mHomeWallpaper.getWallpaperComponent() == null
+                            || mHomeWallpaper.getWallpaperComponent().getComponent() == null;
+                    if (isHomeWallpaperStatic) {
+                        mHomeWallpaper.setWallpaperCropHints(
+                                wallpaperClient.getCurrentCropHints(displaySizes,
+                                        WallpaperManager.FLAG_SYSTEM));
+                    } else {
+                        mHomeWallpaper.setWallpaperCropHints(new HashMap<>());
+                    }
+                }
+                if (mLockWallpaper != null) {
+                    boolean isLockWallpaperStatic = mLockWallpaper.getWallpaperComponent() == null
+                            || mLockWallpaper.getWallpaperComponent().getComponent() == null;
+                    if (isLockWallpaperStatic) {
+                        mLockWallpaper.setWallpaperCropHints(
+                                wallpaperClient.getCurrentCropHints(displaySizes,
+                                        WallpaperManager.FLAG_LOCK));
+                    } else {
+                        mLockWallpaper.setWallpaperCropHints(new HashMap<>());
+                    }
+                }
+            } else {
+                if (mHomeWallpaper != null) mHomeWallpaper.setWallpaperCropHints(null);
+                if (mLockWallpaper != null) mLockWallpaper.setWallpaperCropHints(null);
+            }
             callback.onWallpaperInfoCreated(mHomeWallpaper, mLockWallpaper, mPresentationMode);
             return;
         }
@@ -69,9 +114,6 @@
 
         mWallpaperRefresher.refresh(
                 (homeWallpaperMetadata, lockWallpaperMetadata, presentationMode) -> {
-                    BaseFlags flags = InjectorProvider.getInjector().getFlags();
-                    final boolean multiCropEnabled =
-                            flags.isMultiCropEnabled() && flags.isMultiCropPreviewUiEnabled();
                     WallpaperInfo homeWallpaper;
                     if (homeWallpaperMetadata instanceof LiveWallpaperMetadata) {
                         homeWallpaper = mLiveWallpaperInfoFactory.getLiveWallpaperInfo(
@@ -82,7 +124,7 @@
                                 homeWallpaperMetadata.getActionUrl(),
                                 homeWallpaperMetadata.getCollectionId(),
                                 WallpaperManager.FLAG_SYSTEM);
-                        if (multiCropEnabled) {
+                        if (isMultiCropEnabled) {
                             homeWallpaper.setWallpaperCropHints(
                                     homeWallpaperMetadata.getWallpaperCropHints());
                         }
@@ -102,7 +144,7 @@
                                     lockWallpaperMetadata.getCollectionId(),
                                     WallpaperManager.FLAG_LOCK);
 
-                            if (multiCropEnabled) {
+                            if (isMultiCropEnabled) {
                                 lockWallpaper.setWallpaperCropHints(
                                         lockWallpaperMetadata.getWallpaperCropHints());
                             }
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperPersister.java b/src/com/android/wallpaper/module/DefaultWallpaperPersister.java
index 2eeba49..9683857 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperPersister.java
+++ b/src/com/android/wallpaper/module/DefaultWallpaperPersister.java
@@ -45,7 +45,7 @@
 import com.android.wallpaper.asset.BitmapUtils;
 import com.android.wallpaper.asset.StreamableAsset;
 import com.android.wallpaper.asset.StreamableAsset.StreamReceiver;
-import com.android.wallpaper.model.StaticWallpaperMetadata;
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata;
 import com.android.wallpaper.model.WallpaperInfo;
 import com.android.wallpaper.module.BitmapCropper.Callback;
 import com.android.wallpaper.util.BitmapTransformer;
@@ -59,6 +59,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Concrete implementation of WallpaperPersister which actually sets wallpapers to the system via
@@ -278,7 +279,7 @@
 
     @Override
     public boolean saveStaticWallpaperToPreferences(@Destination int destination,
-            @NonNull StaticWallpaperMetadata metadata) {
+            @NonNull StaticWallpaperPrefMetadata metadata) {
         if (destination == DEST_HOME_SCREEN || destination == DEST_BOTH) {
             mWallpaperPreferences.clearHomeWallpaperMetadata();
             mWallpaperPreferences.setHomeStaticImageWallpaperMetadata(metadata);
@@ -395,7 +396,7 @@
     }
 
     @Override
-    public int setStreamToWallpaperManager(InputStream inputStream, Rect cropHint,
+    public int setStreamToWallpaperManager(InputStream inputStream, @Nullable Rect cropHint,
             boolean allowBackup, int whichWallpaper) {
         try {
             return mWallpaperManager.setStream(inputStream, cropHint, allowBackup,
@@ -406,6 +407,17 @@
     }
 
     @Override
+    public int setStreamWithCropsToWallpaperManager(InputStream inputStream,
+            @NonNull Map<Point, Rect> cropHints, boolean allowBackup, int whichWallpaper) {
+        try {
+            return mWallpaperManager.setStreamWithCrops(inputStream, cropHints, allowBackup,
+                whichWallpaper);
+        } catch (IOException e) {
+            return 0;
+        }
+    }
+
+    @Override
     public void setWallpaperInfoInPreview(WallpaperInfo wallpaper) {
         mWallpaperInfoInPreview = wallpaper;
     }
@@ -739,15 +751,13 @@
                 int wallpaperId, long bitmapHash, WallpaperColors colors) {
             saveStaticWallpaperToPreferences(
                     destination,
-                    new StaticWallpaperMetadata(
+                    new StaticWallpaperPrefMetadata(
                             mWallpaper.getAttributions(mAppContext),
                             mWallpaper.getActionUrl(mAppContext),
                             mWallpaper.getCollectionId(mAppContext),
                             bitmapHash,
                             wallpaperId,
-                            mWallpaper.getWallpaperId(),
-                            // Always null cropHints as this path doesn't support multi-crop
-                            /* cropHints= */ null));
+                            mWallpaper.getWallpaperId()));
 
             if (destination == DEST_HOME_SCREEN || destination == DEST_BOTH) {
                 mWallpaperPreferences.storeLatestWallpaper(
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt b/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt
index 7592f7b..a59b0a3 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt
+++ b/src/com/android/wallpaper/module/DefaultWallpaperPreferences.kt
@@ -23,20 +23,21 @@
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener
 import android.graphics.Bitmap
 import android.graphics.Color
+import android.graphics.Point
 import android.graphics.Rect
 import android.util.Log
-import androidx.core.content.edit
 import com.android.wallpaper.model.LiveWallpaperInfo
-import com.android.wallpaper.model.StaticWallpaperMetadata
+import com.android.wallpaper.model.LiveWallpaperPrefMetadata
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel
 import com.android.wallpaper.module.WallpaperPreferenceKeys.NoBackupKeys
 import com.android.wallpaper.module.WallpaperPreferences.Companion.generateRecentsKey
 import com.android.wallpaper.module.WallpaperPreferences.PendingDailyWallpaperUpdateStatus
 import com.android.wallpaper.module.WallpaperPreferences.PendingWallpaperSetStatus
 import com.android.wallpaper.module.WallpaperPreferences.PresentationMode
 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
+import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
+import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 import java.text.SimpleDateFormat
 import java.util.Calendar
 import java.util.Locale
@@ -280,14 +281,10 @@
             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_REMOTE_ID)
             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_BASE_IMAGE_URL)
             .remove(NoBackupKeys.KEY_HOME_WALLPAPER_BACKING_FILE)
-            .remove(NoBackupKeys.KEY_CROP_HINT_PORTRAIT)
-            .remove(NoBackupKeys.KEY_CROP_HINT_LANDSCAPE)
-            .remove(NoBackupKeys.KEY_CROP_HINT_UNFOLDED_PORTRAIT)
-            .remove(NoBackupKeys.KEY_CROP_HINT_UNFOLDED_LANDSCAPE)
             .apply()
     }
 
-    override fun setHomeStaticImageWallpaperMetadata(metadata: StaticWallpaperMetadata) {
+    override fun setHomeStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata) {
         val sharedEditor = sharedPrefs.edit()
         val attributions = metadata.attributions
         if (!attributions.isNullOrEmpty()) {
@@ -331,6 +328,43 @@
         noBackupEditor.apply()
     }
 
+    override fun setHomeLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata) {
+        val sharedEditor = sharedPrefs.edit()
+        val attributions = metadata.attributions
+        if (!attributions.isNullOrEmpty()) {
+            attributions.take(3).forEachIndexed { index, attr ->
+                when (index) {
+                    0 ->
+                        sharedEditor.putString(
+                            WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1,
+                            attr
+                        )
+                    1 ->
+                        sharedEditor.putString(
+                            WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2,
+                            attr
+                        )
+                    2 ->
+                        sharedEditor.putString(
+                            WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_3,
+                            attr
+                        )
+                }
+            }
+        }
+        sharedEditor.putString(
+            WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID,
+            metadata.collectionId
+        )
+        sharedEditor.apply()
+
+        val noBackupEditor = noBackupPrefs.edit()
+        noBackupEditor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, metadata.serviceName)
+        noBackupEditor.putString(NoBackupKeys.KEY_HOME_WALLPAPER_EFFECTS, metadata.effectName)
+        noBackupEditor.putInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, metadata.managerId)
+        noBackupEditor.apply()
+    }
+
     override fun getHomeWallpaperHashCode(): Long {
         return sharedPrefs.getLong(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE, 0)
     }
@@ -464,14 +498,10 @@
             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID)
             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID)
             .remove(NoBackupKeys.KEY_LOCK_WALLPAPER_BACKING_FILE)
-            .remove(NoBackupKeys.KEY_CROP_HINT_PORTRAIT)
-            .remove(NoBackupKeys.KEY_CROP_HINT_LANDSCAPE)
-            .remove(NoBackupKeys.KEY_CROP_HINT_UNFOLDED_PORTRAIT)
-            .remove(NoBackupKeys.KEY_CROP_HINT_UNFOLDED_LANDSCAPE)
             .apply()
     }
 
-    override fun setLockStaticImageWallpaperMetadata(metadata: StaticWallpaperMetadata) {
+    override fun setLockStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata) {
         val sharedEditor = sharedPrefs.edit()
         val attributions = metadata.attributions
         if (!attributions.isNullOrEmpty()) {
@@ -515,6 +545,43 @@
         noBackupEditor.apply()
     }
 
+    override fun setLockLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata) {
+        val sharedEditor = sharedPrefs.edit()
+        val attributions = metadata.attributions
+        if (!attributions.isNullOrEmpty()) {
+            attributions.take(3).forEachIndexed { index, attr ->
+                when (index) {
+                    0 ->
+                        sharedEditor.putString(
+                            WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1,
+                            attr
+                        )
+                    1 ->
+                        sharedEditor.putString(
+                            WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2,
+                            attr
+                        )
+                    2 ->
+                        sharedEditor.putString(
+                            WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_3,
+                            attr
+                        )
+                }
+            }
+        }
+        sharedEditor.putString(
+            WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID,
+            metadata.collectionId
+        )
+        sharedEditor.apply()
+
+        val noBackupEditor = noBackupPrefs.edit()
+        noBackupEditor.putString(NoBackupKeys.KEY_LOCK_WALLPAPER_SERVICE_NAME, metadata.serviceName)
+        noBackupEditor.putString(NoBackupKeys.KEY_LOCK_WALLPAPER_EFFECTS, metadata.effectName)
+        noBackupEditor.putInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, metadata.managerId)
+        noBackupEditor.apply()
+    }
+
     override fun getLockWallpaperHashCode(): Long {
         return sharedPrefs.getLong(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE, 0)
     }
@@ -828,32 +895,31 @@
 
     override suspend fun addStaticWallpaperToRecentWallpapers(
         destination: WallpaperDestination,
-        wallpaperModel: WallpaperModel.StaticWallpaperModel,
+        wallpaperModel: StaticWallpaperModel,
         bitmap: Bitmap,
-        cropHints: Map<ScreenOrientation, Rect?>,
+        cropHints: Map<Point, Rect>?,
     ) {}
 
-    override fun storeWallpaperCropHints(cropHints: Map<ScreenOrientation, Rect?>) {
-        noBackupPrefs.edit {
-            cropHints.forEach { (orientation, rect) ->
-                putString(getScreenOrientationPrefKey(orientation), rect?.flattenToString())
-            }
-        }
+    override suspend fun addLiveWallpaperToRecentWallpapers(
+        destination: WallpaperDestination,
+        wallpaperModel: LiveWallpaperModel
+    ) {}
+
+    override fun setHasPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
+        sharedPrefs
+            .edit()
+            .putBoolean(
+                WallpaperPreferenceKeys.KEY_HAS_PREVIEW_TOOLTIP_BEEN_SHOWN,
+                hasTooltipBeenShown
+            )
+            .apply()
     }
 
-    override fun getWallpaperCropHints(): Map<ScreenOrientation, Rect?> {
-        return ScreenOrientation.entries.associateWith {
-            Rect.unflattenFromString(noBackupPrefs.getString(getScreenOrientationPrefKey(it), null))
-        }
-    }
-
-    private fun getScreenOrientationPrefKey(orientation: ScreenOrientation): String {
-        return when (orientation) {
-            ScreenOrientation.PORTRAIT -> NoBackupKeys.KEY_CROP_HINT_PORTRAIT
-            ScreenOrientation.LANDSCAPE -> NoBackupKeys.KEY_CROP_HINT_LANDSCAPE
-            ScreenOrientation.UNFOLDED_LANDSCAPE -> NoBackupKeys.KEY_CROP_HINT_UNFOLDED_LANDSCAPE
-            ScreenOrientation.UNFOLDED_PORTRAIT -> NoBackupKeys.KEY_CROP_HINT_UNFOLDED_PORTRAIT
-        }
+    override fun getHasPreviewTooltipBeenShown(): Boolean {
+        return sharedPrefs.getBoolean(
+            WallpaperPreferenceKeys.KEY_HAS_PREVIEW_TOOLTIP_BEEN_SHOWN,
+            false
+        )
     }
 
     private fun setFirstLaunchDateSinceSetup(firstLaunchDate: Int) {
@@ -889,6 +955,7 @@
     companion object {
         const val PREFS_NAME = "wallpaper"
         const val NO_BACKUP_PREFS_NAME = "wallpaper-nobackup"
+        const val KEY_VALUE_DIVIDER = "="
         private const val TAG = "DefaultWallpaperPreferences"
     }
 }
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java b/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
index 1d30827..fd13598 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
+++ b/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.AsyncTask;
@@ -33,14 +34,14 @@
 import com.android.wallpaper.asset.BitmapUtils;
 import com.android.wallpaper.model.LiveWallpaperMetadata;
 import com.android.wallpaper.model.WallpaperMetadata;
-import com.android.wallpaper.model.wallpaper.ScreenOrientation;
+import com.android.wallpaper.picker.customization.data.content.WallpaperClient;
+import com.android.wallpaper.util.DisplayUtils;
 
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -58,6 +59,11 @@
     private final WallpaperManager mWallpaperManager;
     private final WallpaperStatusChecker mWallpaperStatusChecker;
 
+    private final DisplayUtils mDisplayUtils;
+
+    private final WallpaperClient mWallpaperClient;
+
+
     /**
      * @param context The application's context.
      */
@@ -67,6 +73,8 @@
         Injector injector = InjectorProvider.getInjector();
         mWallpaperPreferences = injector.getPreferences(mAppContext);
         mWallpaperStatusChecker = injector.getWallpaperStatusChecker(context);
+        mDisplayUtils = injector.getDisplayUtils(mAppContext);
+        mWallpaperClient = injector.getWallpaperClient(mAppContext);
 
         // Retrieve WallpaperManager using Context#getSystemService instead of
         // WallpaperManager#getInstance so it can be mocked out in test.
@@ -360,10 +368,10 @@
                     && attributions.get(2) == null;
         }
 
-        private Map<ScreenOrientation, Rect> getCurrentWallpaperCropHints(
+        private Map<Point, Rect> getCurrentWallpaperCropHints(
                 @WallpaperManager.SetWallpaperFlags int which) {
-            // TODO(b/303317694): Get cropHints from interactor.
-            return new HashMap<ScreenOrientation, Rect>();
+            List<Point> displaySizes = mDisplayUtils.getInternalDisplaySizes();
+            return mWallpaperClient.getCurrentCropHints(displaySizes, which);
         }
     }
 }
diff --git a/src/com/android/wallpaper/module/Injector.kt b/src/com/android/wallpaper/module/Injector.kt
index 97443cc..2c89502 100755
--- a/src/com/android/wallpaper/module/Injector.kt
+++ b/src/com/android/wallpaper/module/Injector.kt
@@ -32,6 +32,7 @@
 import com.android.wallpaper.monitor.PerformanceMonitor
 import com.android.wallpaper.network.Requester
 import com.android.wallpaper.picker.MyPhotosStarter.MyPhotosIntentProvider
+import com.android.wallpaper.picker.customization.data.content.WallpaperClient
 import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository
 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperSnapshotRestorer
@@ -99,7 +100,7 @@
 
     fun getSystemFeatureChecker(): SystemFeatureChecker
 
-    fun getUserEventLogger(context: Context): UserEventLogger
+    fun getUserEventLogger(): UserEventLogger
 
     fun getWallpaperPersister(context: Context): WallpaperPersister
 
@@ -126,6 +127,8 @@
 
     fun getWallpaperInteractor(context: Context): WallpaperInteractor
 
+    fun getWallpaperClient(context: Context): WallpaperClient
+
     fun getWallpaperSnapshotRestorer(context: Context): WallpaperSnapshotRestorer
 
     fun getWallpaperColorsRepository(): WallpaperColorsRepository
diff --git a/src/com/android/wallpaper/module/RotationWallpaperUpdateReceiver.java b/src/com/android/wallpaper/module/RotationWallpaperUpdateReceiver.java
index 4a31475..9e9f45d 100644
--- a/src/com/android/wallpaper/module/RotationWallpaperUpdateReceiver.java
+++ b/src/com/android/wallpaper/module/RotationWallpaperUpdateReceiver.java
@@ -20,8 +20,8 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.util.Log;
 
-import com.android.wallpaper.util.DiskBasedLogger;
 import com.android.wallpaper.util.FileMover;
 
 import java.io.File;
@@ -45,10 +45,6 @@
         if (intent.getAction() == null
                 || !(intent.getAction().equals(Intent.ACTION_MY_PACKAGE_REPLACED)
                 || intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))) {
-            DiskBasedLogger.e(
-                    TAG,
-                    "Unexpected action or Android version!",
-                    context);
             throw new IllegalStateException(
                     "Unexpected broadcast action or unsupported Android version");
         }
@@ -76,11 +72,8 @@
             FileMover.moveFileBetweenContexts(context, ROTATING_WALLPAPER_FILE_PATH,
                     deviceProtectedContext, ROTATING_WALLPAPER_FILE_PATH);
         } catch (Exception ex) {
-            DiskBasedLogger.e(
-                    TAG,
-                    "Failed to move rotating wallpaper file to device protected storage: "
-                            + ex.getMessage(),
-                    context);
+            Log.e(TAG, "Failed to move rotating wallpaper file to device protected storage: "
+                            + ex.getMessage());
         }
     }
 
@@ -102,7 +95,7 @@
             wallpaperFile.delete();
 
         } catch (Exception ex) {
-            DiskBasedLogger.e(TAG, "Unable to set static wallpaper", appContext);
+            Log.e(TAG, "Unable to set static wallpaper");
         }
     }
 }
diff --git a/src/com/android/wallpaper/module/WallpaperPersister.java b/src/com/android/wallpaper/module/WallpaperPersister.java
index 00e0143..585aa13 100755
--- a/src/com/android/wallpaper/module/WallpaperPersister.java
+++ b/src/com/android/wallpaper/module/WallpaperPersister.java
@@ -20,17 +20,20 @@
 import static android.app.WallpaperManager.SetWallpaperFlags;
 
 import android.graphics.Bitmap;
+import android.graphics.Point;
 import android.graphics.Rect;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.model.StaticWallpaperMetadata;
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata;
 import com.android.wallpaper.model.WallpaperInfo;
 
 import java.io.InputStream;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Interface for classes which persist wallpapers to the system.
@@ -133,7 +136,7 @@
      * Save static image wallpaper's meta to the system preferences.
      */
     boolean saveStaticWallpaperToPreferences(int destination,
-            StaticWallpaperMetadata metadata);
+            StaticWallpaperPrefMetadata metadata);
 
     /**
      * @return the flag indicating which wallpaper to set when we're trying to set a wallpaper with
@@ -159,7 +162,18 @@
      * Android, otherwise on pre-N versions of Android will return a positive integer when the
      * operation was successful and zero if the operation encountered an error.
      */
-    int setStreamToWallpaperManager(InputStream inputStream, Rect cropHint,
+    int setStreamToWallpaperManager(InputStream inputStream, @Nullable Rect cropHint,
+            boolean allowBackup, int whichWallpaper);
+
+    /**
+     * Sets a wallpaper stream to the {@link android.app.WallpaperManager}.
+     *
+     * @return an integer wallpaper ID. This is an actual wallpaper ID on N and later versions of
+     * Android, otherwise on pre-N versions of Android will return a positive integer when the
+     * operation was successful and zero if the operation encountered an error.
+     */
+    int setStreamWithCropsToWallpaperManager(InputStream inputStream,
+            @NonNull Map<Point, Rect> cropModel,
             boolean allowBackup, int whichWallpaper);
 
     /**
diff --git a/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt b/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
index d135020..c71b5ae 100755
--- a/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
+++ b/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
@@ -24,7 +24,10 @@
 import androidx.activity.ComponentActivity
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.LifecycleOwner
+import com.android.customization.model.color.DefaultWallpaperColorResources
 import com.android.customization.model.color.WallpaperColorResources
+import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
+import com.android.systemui.shared.settings.data.repository.SecureSettingsRepositoryImpl
 import com.android.wallpaper.config.BaseFlags
 import com.android.wallpaper.effects.EffectsController
 import com.android.wallpaper.model.CategoryProvider
@@ -42,6 +45,7 @@
 import com.android.wallpaper.picker.PreviewActivity
 import com.android.wallpaper.picker.PreviewFragment
 import com.android.wallpaper.picker.ViewOnlyPreviewActivity
+import com.android.wallpaper.picker.customization.data.content.WallpaperClient
 import com.android.wallpaper.picker.customization.data.content.WallpaperClientImpl
 import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository
 import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository
@@ -52,9 +56,8 @@
 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.settings.data.repository.SecureSettingsRepository
-import com.android.wallpaper.settings.data.repository.SecureSettingsRepositoryImpl
 import com.android.wallpaper.util.DisplayUtils
+import dagger.Lazy
 import javax.inject.Inject
 import javax.inject.Singleton
 import kotlinx.coroutines.CoroutineDispatcher
@@ -63,10 +66,9 @@
 @Singleton
 open class WallpaperPicker2Injector
 @Inject
-internal constructor(
+constructor(
     @MainDispatcher private val mainScope: CoroutineScope,
     @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
-    private val userEventLogger: UserEventLogger,
 ) : Injector {
     private var alarmManagerWrapper: AlarmManagerWrapper? = null
     private var bitmapCropper: BitmapCropper? = null
@@ -90,12 +92,15 @@
     private var flags: BaseFlags? = null
     private var undoInteractor: UndoInteractor? = null
     private var wallpaperInteractor: WallpaperInteractor? = null
-    @Inject lateinit var injectedWallpaperInteractor: WallpaperInteractor
+    @Inject lateinit var injectedWallpaperInteractor: Lazy<WallpaperInteractor>
+    private var wallpaperClient: WallpaperClient? = null
+    @Inject lateinit var injectedWallpaperClient: Lazy<WallpaperClient>
     private var wallpaperSnapshotRestorer: WallpaperSnapshotRestorer? = null
     private var secureSettingsRepository: SecureSettingsRepository? = null
     private var wallpaperColorsRepository: WallpaperColorsRepository? = null
     private var previewActivityIntentFactory: InlinePreviewIntentFactory? = null
     private var viewOnlyPreviewActivityIntentFactory: InlinePreviewIntentFactory? = null
+    @Inject lateinit var userEventLogger: Lazy<UserEventLogger>
 
     override fun getApplicationCoroutineScope(): CoroutineScope {
         return mainScope
@@ -240,8 +245,8 @@
             ?: DefaultSystemFeatureChecker().also { systemFeatureChecker = it }
     }
 
-    override fun getUserEventLogger(context: Context): UserEventLogger {
-        return userEventLogger
+    override fun getUserEventLogger(): UserEventLogger {
+        return userEventLogger.get()
     }
 
     @Synchronized
@@ -301,7 +306,7 @@
 
     override fun getWallpaperInteractor(context: Context): WallpaperInteractor {
         if (getFlags().isMultiCropEnabled() && getFlags().isMultiCropPreviewUiEnabled()) {
-            return injectedWallpaperInteractor
+            return injectedWallpaperInteractor.get()
         }
 
         val appContext = context.applicationContext
@@ -310,12 +315,7 @@
                     repository =
                         WallpaperRepository(
                             scope = getApplicationCoroutineScope(),
-                            client =
-                                WallpaperClientImpl(
-                                    context = appContext,
-                                    wallpaperManager = WallpaperManager.getInstance(appContext),
-                                    wallpaperPreferences = getPreferences(appContext),
-                                ),
+                            client = getWallpaperClient(context),
                             wallpaperPreferences = getPreferences(context = appContext),
                             backgroundDispatcher = bgDispatcher,
                         ),
@@ -323,6 +323,21 @@
                 .also { wallpaperInteractor = it }
     }
 
+    override fun getWallpaperClient(context: Context): WallpaperClient {
+        if (getFlags().isMultiCropEnabled() && getFlags().isMultiCropPreviewUiEnabled()) {
+            return injectedWallpaperClient.get()
+        }
+
+        val appContext = context.applicationContext
+        return wallpaperClient
+            ?: WallpaperClientImpl(
+                    context = appContext,
+                    wallpaperManager = WallpaperManager.getInstance(appContext),
+                    wallpaperPreferences = getPreferences(appContext),
+                )
+                .also { wallpaperClient = it }
+    }
+
     override fun getWallpaperSnapshotRestorer(context: Context): WallpaperSnapshotRestorer {
         return wallpaperSnapshotRestorer
             ?: WallpaperSnapshotRestorer(
@@ -350,7 +365,7 @@
         wallpaperColors: WallpaperColors,
         context: Context
     ): WallpaperColorResources {
-        return WallpaperColorResources(wallpaperColors)
+        return DefaultWallpaperColorResources(wallpaperColors)
     }
 
     override fun getMyPhotosIntentProvider(): MyPhotosStarter.MyPhotosIntentProvider {
diff --git a/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java b/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
index 0982878..20e8dee 100755
--- a/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
+++ b/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
@@ -34,6 +34,8 @@
     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";
 
     /**
      * Preferences with these keys should not be backed up
@@ -76,9 +78,5 @@
         String KEY_PREVIEW_WALLPAPER_COLOR_ID = "preview_wallpaper_color_id";
         String KEY_HOME_WALLPAPER_EFFECTS = "home_wallpaper_effects";
         String KEY_LOCK_WALLPAPER_EFFECTS = "lock_wallpaper_effects";
-        String KEY_CROP_HINT_PORTRAIT = "crop_hint_portrait";
-        String KEY_CROP_HINT_LANDSCAPE = "crop_hint_landscape";
-        String KEY_CROP_HINT_UNFOLDED_PORTRAIT = "crop_hint_unfolded_portrait";
-        String KEY_CROP_HINT_UNFOLDED_LANDSCAPE = "crop_hint_unfolded_landscape";
     }
 }
diff --git a/src/com/android/wallpaper/module/WallpaperPreferences.kt b/src/com/android/wallpaper/module/WallpaperPreferences.kt
index b878c72..6fbb34a 100755
--- a/src/com/android/wallpaper/module/WallpaperPreferences.kt
+++ b/src/com/android/wallpaper/module/WallpaperPreferences.kt
@@ -18,15 +18,17 @@
 import android.app.WallpaperColors
 import android.app.WallpaperManager.SetWallpaperFlags
 import android.graphics.Bitmap
+import android.graphics.Point
 import android.graphics.Rect
 import android.text.TextUtils
 import androidx.annotation.IntDef
 import com.android.wallpaper.model.LiveWallpaperInfo
-import com.android.wallpaper.model.StaticWallpaperMetadata
+import com.android.wallpaper.model.LiveWallpaperPrefMetadata
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel
 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
+import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
+import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 
 /** Interface for persisting and retrieving wallpaper specific preferences. */
 interface WallpaperPreferences {
@@ -62,7 +64,10 @@
     fun clearHomeWallpaperMetadata()
 
     /** Set homescreen static image wallpaper metadata to SharedPreferences. */
-    fun setHomeStaticImageWallpaperMetadata(metadata: StaticWallpaperMetadata)
+    fun setHomeStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata)
+
+    /** Set homescreen live wallpaper metadata to SharedPreferences. */
+    fun setHomeLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata)
 
     /** Returns the home wallpaper's bitmap hash code or 0 if there is none. */
     fun getHomeWallpaperHashCode(): Long
@@ -133,7 +138,10 @@
     fun clearLockWallpaperMetadata()
 
     /** Set lockscreen static image wallpaper metadata to SharedPreferences. */
-    fun setLockStaticImageWallpaperMetadata(metadata: StaticWallpaperMetadata)
+    fun setLockStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata)
+
+    /** Set lockscreen live wallpaper metadata to SharedPreferences. */
+    fun setLockLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata)
 
     /** Returns the lock screen wallpaper's bitmap hash code or 0 if there is none. */
     fun getLockWallpaperHashCode(): Long
@@ -373,7 +381,7 @@
     )
 
     /**
-     * Add a static wallpaper to recent wallpapers as jason array, saved in preferences.
+     * Add a static wallpaper to recent wallpapers as json array, saved in preferences.
      *
      * @param destination destination where the wallpaper is set to
      * @param wallpaperModel static wallpaper model
@@ -382,16 +390,27 @@
      */
     suspend fun addStaticWallpaperToRecentWallpapers(
         destination: WallpaperDestination,
-        wallpaperModel: WallpaperModel.StaticWallpaperModel,
+        wallpaperModel: StaticWallpaperModel,
         bitmap: Bitmap,
-        cropHints: Map<ScreenOrientation, Rect?>,
+        cropHints: Map<Point, Rect>?,
     )
 
-    /** Stores wallpaper crop hints for each dimensions. */
-    fun storeWallpaperCropHints(cropHints: Map<ScreenOrientation, Rect?>)
+    /**
+     * Add a live wallpaper to recent wallpapers as json array, saved in preferences.
+     *
+     * @param destination destination where the wallpaper is set to
+     * @param wallpaperModel live wallpaper model
+     */
+    suspend fun addLiveWallpaperToRecentWallpapers(
+        destination: WallpaperDestination,
+        wallpaperModel: LiveWallpaperModel,
+    )
 
-    /** Gets wallpaper crop hints for each dimensions. */
-    fun getWallpaperCropHints(): Map<ScreenOrientation, Rect?>
+    /** Sets whether the preview tooltip should be shown. */
+    fun setHasPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean)
+
+    /** Gets whether the preview tooltip should be shown. */
+    fun getHasPreviewTooltipBeenShown(): 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/BasePreviewActivity.java b/src/com/android/wallpaper/picker/BasePreviewActivity.java
old mode 100755
new mode 100644
index 0ac4249..2c44430
--- a/src/com/android/wallpaper/picker/BasePreviewActivity.java
+++ b/src/com/android/wallpaper/picker/BasePreviewActivity.java
@@ -37,12 +37,14 @@
             "com.android.wallpaper.picker.view_as_home";
     public static final String IS_ASSET_ID_PRESENT =
             "com.android.wallpaper.picker.asset_id_present";
+    public static final String IS_NEW_TASK =
+            "com.android.wallpaper.picker.new_task";
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Injector injector = InjectorProvider.getInjector();
-        UserEventLogger mUserEventLogger = injector.getUserEventLogger(this);
+        UserEventLogger mUserEventLogger = injector.getUserEventLogger();
         getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
         setTheme(R.style.WallpaperTheme);
         getWindow().setFormat(PixelFormat.TRANSLUCENT);
diff --git a/src/com/android/wallpaper/picker/CategorySelectorFragment.java b/src/com/android/wallpaper/picker/CategorySelectorFragment.java
index 9e10d15..b495197 100644
--- a/src/com/android/wallpaper/picker/CategorySelectorFragment.java
+++ b/src/com/android/wallpaper/picker/CategorySelectorFragment.java
@@ -55,7 +55,6 @@
 import com.android.wallpaper.model.LiveWallpaperInfo;
 import com.android.wallpaper.model.WallpaperInfo;
 import com.android.wallpaper.module.InjectorProvider;
-import com.android.wallpaper.module.logging.UserEventLogger;
 import com.android.wallpaper.util.DeepLinkUtils;
 import com.android.wallpaper.util.DisplayMetricsRetriever;
 import com.android.wallpaper.util.ResourceUtils;
@@ -469,7 +468,8 @@
         Snackbar snackbar = Snackbar.make(getView(), R.string.settings_snackbar_description,
                 Snackbar.LENGTH_LONG);
         Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView();
-        TextView textView = (TextView) layout.findViewById(R.id.snackbar_text);
+        TextView textView = (TextView) layout.findViewById(
+                com.google.android.material.R.id.snackbar_text);
         layout.setBackgroundResource(R.drawable.snackbar_background);
         TypedArray typedArray = getContext().obtainStyledAttributes(
                 new int[]{android.R.attr.textColorPrimary,
@@ -561,8 +561,6 @@
 
         private void onClickListenerForCreativeCategory(int position) {
             Activity activity = getActivity();
-            final UserEventLogger eventLogger =
-                    InjectorProvider.getInjector().getUserEventLogger(activity);
             if (mCategories.get(position).supportsCustomPhotos()) {
                 getCategorySelectorFragmentHost().requestCustomPhotoPicker(
                         new MyPhotosStarter.PermissionChangedListener() {
diff --git a/src/com/android/wallpaper/picker/CustomizationPickerActivity.java b/src/com/android/wallpaper/picker/CustomizationPickerActivity.java
index b50cdb3..9bdc85b 100644
--- a/src/com/android/wallpaper/picker/CustomizationPickerActivity.java
+++ b/src/com/android/wallpaper/picker/CustomizationPickerActivity.java
@@ -87,12 +87,12 @@
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         Injector injector = InjectorProvider.getInjector();
         mDelegate = new WallpaperPickerDelegate(this, this, injector);
-        mUserEventLogger = injector.getUserEventLogger(this);
+        mUserEventLogger = injector.getUserEventLogger();
         mNetworkStatusNotifier = injector.getNetworkStatusNotifier(this);
         mNetworkStatus = mNetworkStatusNotifier.getNetworkStatus();
         mDisplayUtils = injector.getDisplayUtils(this);
 
-        enforceOrientation();
+        enforcePortraitForHandheldAndFoldedDisplay();
 
         // Restore this Activity's state before restoring contained Fragments state.
         super.onCreate(savedInstanceState);
@@ -394,22 +394,21 @@
     @Override
     public void onConfigurationChanged(@NonNull Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        enforceOrientation();
+        enforcePortraitForHandheldAndFoldedDisplay();
     }
 
     /**
-     * Allows any orientation for large screen devices (tablets and unfolded foldables) while
-     * forcing portrait for smaller screens (handheld and folded foldables).
+     * If the display is a handheld display or a folded display from a foldable, we enforce the
+     * activity to be portrait.
      *
      * This method should be called upon initialization of this activity, and whenever there is a
      * configuration change.
      */
     @SuppressLint("SourceLockedOrientationActivity")
-    private void enforceOrientation() {
-        int wantedOrientation =
-                mDisplayUtils.isLargeScreenDevice() && mDisplayUtils.isOnWallpaperDisplay(this)
-                        ? ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
-                        : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+    private void enforcePortraitForHandheldAndFoldedDisplay() {
+        int wantedOrientation = mDisplayUtils.isLargeScreenOrUnfoldedDisplay(this)
+                ? ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+                : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
         if (getRequestedOrientation() != wantedOrientation) {
             setRequestedOrientation(wantedOrientation);
         }
diff --git a/src/com/android/wallpaper/picker/CustomizationPickerFragment.java b/src/com/android/wallpaper/picker/CustomizationPickerFragment.java
index eca2266..1eb34f4 100644
--- a/src/com/android/wallpaper/picker/CustomizationPickerFragment.java
+++ b/src/com/android/wallpaper/picker/CustomizationPickerFragment.java
@@ -109,7 +109,7 @@
                         savedInstanceState,
                         injector.getUndoInteractor(requireContext(), requireActivity()),
                         injector.getWallpaperInteractor(requireContext()),
-                        injector.getUserEventLogger(requireContext()))
+                        injector.getUserEventLogger())
         ).get(CustomizationPickerViewModel.class);
         final Bundle arguments = getArguments();
         mViewModel.setInitialScreen(
diff --git a/src/com/android/wallpaper/picker/DisplayAspectRatioFrameLayout.kt b/src/com/android/wallpaper/picker/DisplayAspectRatioFrameLayout.kt
index a2f1c67..5069b6f 100644
--- a/src/com/android/wallpaper/picker/DisplayAspectRatioFrameLayout.kt
+++ b/src/com/android/wallpaper/picker/DisplayAspectRatioFrameLayout.kt
@@ -39,17 +39,21 @@
         // DisplayAspectRatioFrameLayout is allowed to stretch to fill its parent (for example if
         // the parent is a vertical LinearLayout and the DisplayAspectRatioFrameLayout has a height
         // if 0 and a weight of 1.
+        // However we make sure that the width of the children never exceeds the width of the parent
         //
         // If you need to use this class to force the height dimension based on the width instead,
         // you will need to flip the logic below.
         children.forEach { child ->
+            val childWidth =
+                (child.measuredHeight / screenAspectRatio).toInt().coerceAtMost(measuredWidth)
             child.measure(
+                MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
                 MeasureSpec.makeMeasureSpec(
-                    (child.measuredHeight / screenAspectRatio).toInt(),
-                    MeasureSpec.EXACTLY
-                ),
-                MeasureSpec.makeMeasureSpec(
-                    child.measuredHeight,
+                    if (childWidth < measuredWidth) {
+                        child.measuredHeight
+                    } else {
+                        (childWidth * screenAspectRatio).toInt()
+                    },
                     MeasureSpec.EXACTLY,
                 ),
             )
diff --git a/src/com/android/wallpaper/picker/PreviewActivity.java b/src/com/android/wallpaper/picker/PreviewActivity.java
old mode 100755
new mode 100644
index 9c8a2d0..da0d3e3
--- a/src/com/android/wallpaper/picker/PreviewActivity.java
+++ b/src/com/android/wallpaper/picker/PreviewActivity.java
@@ -132,7 +132,7 @@
 
             if (flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()) {
                 return WallpaperPreviewActivity.Companion.newIntent(appContext,
-                        wallpaper, /* isNewTask= */ isMultiPanel);
+                        wallpaper, isAssetIdPresent, mIsViewAsHome, /* isNewTask= */ isMultiPanel);
             }
 
             // Launch a full preview activity for devices supporting multipanel mode
diff --git a/src/com/android/wallpaper/picker/PreviewFragment.java b/src/com/android/wallpaper/picker/PreviewFragment.java
index e4c274e..53342d4 100755
--- a/src/com/android/wallpaper/picker/PreviewFragment.java
+++ b/src/com/android/wallpaper/picker/PreviewFragment.java
@@ -60,6 +60,7 @@
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
+import androidx.lifecycle.LifecycleOwnerKt;
 import androidx.lifecycle.ViewModelProvider;
 
 import com.android.wallpaper.R;
@@ -81,6 +82,12 @@
 import com.google.android.material.bottomsheet.BottomSheetBehavior;
 import com.google.android.material.transition.MaterialSharedAxis;
 
+import java.util.List;
+
+import kotlinx.coroutines.BuildersKt;
+import kotlinx.coroutines.CoroutineStart;
+import kotlinx.coroutines.Dispatchers;
+
 /**
  * Base Fragment to display the UI for previewing an individual wallpaper.
  */
@@ -223,7 +230,7 @@
         Context appContext = requireContext().getApplicationContext();
         Injector injector = InjectorProvider.getInjector();
 
-        mUserEventLogger = injector.getUserEventLogger(appContext);
+        mUserEventLogger = injector.getUserEventLogger();
         mWallpaperSetter = new WallpaperSetter(injector.getWallpaperPersister(appContext),
                 injector.getPreferences(appContext), mUserEventLogger,
                 injector.getCurrentWallpaperInfoFactory(appContext));
@@ -298,10 +305,15 @@
         mFloatingSheet = view.findViewById(R.id.floating_sheet);
         mHideFloatingSheetTouchLayout = view.findViewById(R.id.hide_floating_sheet_touch_layout);
         mWallpaperControlButtonGroup = view.findViewById(R.id.wallpaper_control_button_group);
-        setUpFloatingSheet(requireContext());
-        mWallpaperControlButtonGroup.showButton(WallpaperControlButtonGroup.INFORMATION,
-                getFloatingSheetControlButtonChangeListener(WallpaperControlButtonGroup.INFORMATION,
-                        INFORMATION));
+        boolean shouldShowInformationFloatingSheet = shouldShowInformationFloatingSheet(mWallpaper);
+        setUpFloatingSheet(requireContext(), shouldShowInformationFloatingSheet);
+        if (shouldShowInformationFloatingSheet) {
+            mWallpaperControlButtonGroup.showButton(
+                    WallpaperControlButtonGroup.INFORMATION,
+                    getFloatingSheetControlButtonChangeListener(
+                            WallpaperControlButtonGroup.INFORMATION,
+                            INFORMATION));
+        }
         mPreviewScrim = view.findViewById(R.id.preview_scrim);
         mExitFullPreviewButton = view.findViewById(R.id.exit_full_preview_button);
         mExitFullPreviewButton.setOnClickListener(v -> toggleWallpaperPreviewControl());
@@ -356,8 +368,22 @@
         mLockSurface.getHolder().addCallback(mLockSurfaceCallback);
     }
 
+    private boolean shouldShowInformationFloatingSheet(WallpaperInfo wallpaperInfo) {
+        List<String> attributions = wallpaperInfo.getAttributions(requireContext());
+        String actionUrl = wallpaperInfo.getActionUrl(requireContext());
+        boolean showAttribution = false;
+        for (String attr : attributions) {
+            if (attr != null && !attr.isEmpty()) {
+                showAttribution = true;
+                break;
+            }
+        }
+        boolean showActionUrl = actionUrl != null && !actionUrl.isEmpty();
+        return showAttribution || showActionUrl;
+    }
+
     @SuppressLint("ClickableViewAccessibility")
-    private void setUpFloatingSheet(Context context) {
+    private void setUpFloatingSheet(Context context, boolean shouldShowInformationFloatingSheet) {
         setHideFloatingSheetLayoutAccessibilityAction();
         mHideFloatingSheetTouchLayout.setContentDescription(
                 getString(R.string.preview_screen_description));
@@ -365,8 +391,10 @@
         mHideFloatingSheetTouchLayout.setVisibility(View.GONE);
         mFloatingSheet.addFloatingSheetCallback(mStandardFloatingSheetCallback);
         mFloatingSheet.addFloatingSheetCallback(mShowOverlayOnHideFloatingSheetCallback);
-        mFloatingSheet.putFloatingSheetContent(INFORMATION,
-                new WallpaperInfoContent(context, mWallpaper));
+        if (shouldShowInformationFloatingSheet) {
+            mFloatingSheet.putFloatingSheetContent(INFORMATION,
+                    new WallpaperInfoContent(context, mWallpaper));
+        }
     }
 
     protected CompoundButton.OnCheckedChangeListener getFloatingSheetControlButtonChangeListener(
@@ -440,20 +468,37 @@
         }
         // Apply the wallpaper color resources to the fragment context. So the views created by
         // the context will apply the given wallpaper color.
-        InjectorProvider.getInjector().getWallpaperColorResources(colors, context).apply(context);
-        mSetWallpaperButton.setBackground(null);
-        mSetWallpaperButton.setBackgroundResource(R.drawable.set_wallpaper_button_background);
-        mExitFullPreviewButton.setForeground(
-                AppCompatResources.getDrawable(context, R.drawable.exit_full_preview_cross));
-        mWallpaperControlButtonGroup.updateBackgroundColor();
-        mOverlayTabs.updateBackgroundColor();
+        BuildersKt.launch(
+                LifecycleOwnerKt.getLifecycleScope(getViewLifecycleOwner()),
+                Dispatchers.getIO(),
+                CoroutineStart.DEFAULT,
+                (coroutineScope, continuation) ->
+                        InjectorProvider.getInjector().getWallpaperColorResources(colors,
+                                context).apply(
+                                    context,
+                                    () -> {
+                                        requireActivity().runOnUiThread(() -> {
+                                            mSetWallpaperButton.setBackground(null);
+                                            mSetWallpaperButton.setBackgroundResource(
+                                                    R.drawable.set_wallpaper_button_background);
+                                            mExitFullPreviewButton.setForeground(
+                                                    AppCompatResources.getDrawable(context,
+                                                            R.drawable.exit_full_preview_cross));
+                                            mWallpaperControlButtonGroup.updateBackgroundColor();
+                                            mOverlayTabs.updateBackgroundColor();
+                                            mFloatingSheet.setColor(context);
+                                        });
+                                        return null;
+                                    }, continuation
+                        )
+        );
+
         // Update the color theme for the home screen overlay
         updateWorkspacePreview(mWorkspaceSurface, mWorkspaceSurfaceCallback, colors,
                 /* hideBottomRow= */ mOverlayTabs.getVisibility() == VISIBLE);
         // Update the color theme for the lock screen overlay
         updateWorkspacePreview(mLockSurface, mLockSurfaceCallback, colors,
                 /* hideBottomRow= */ mOverlayTabs.getVisibility() == VISIBLE);
-        mFloatingSheet.setColor(context);
     }
 
     private void updateScreenPreviewOverlay(@DuoTabs.Tab int tab) {
diff --git a/src/com/android/wallpaper/picker/StandalonePreviewActivity.java b/src/com/android/wallpaper/picker/StandalonePreviewActivity.java
old mode 100755
new mode 100644
index 26d190c..2a9ea51
--- a/src/com/android/wallpaper/picker/StandalonePreviewActivity.java
+++ b/src/com/android/wallpaper/picker/StandalonePreviewActivity.java
@@ -146,7 +146,8 @@
         WallpaperInfo wallpaper = new ImageWallpaperInfo(intent.getData());
         if (flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()) {
             startActivity(WallpaperPreviewActivity.Companion.newIntent(
-                    this.getApplicationContext(), wallpaper, /* isNewTask= */ false));
+                    this.getApplicationContext(), wallpaper, /* isAssetIdPresent= */ false,
+                    /* isViewAsHome= */ true, /* isNewTask= */ false));
             finish();
             return;
         }
diff --git a/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java b/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java
old mode 100755
new mode 100644
index c43ed77..48734a7
--- a/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java
+++ b/src/com/android/wallpaper/picker/ViewOnlyPreviewActivity.java
@@ -111,8 +111,8 @@
             final boolean isMultiPanel = multiPanesChecker.isMultiPanesEnabled(appContext);
             final BaseFlags flags = InjectorProvider.getInjector().getFlags();
             if (flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()) {
-                return WallpaperPreviewActivity.Companion.newIntent(appContext,
-                        wallpaper, /* isNewTask= */ isMultiPanel);
+                return WallpaperPreviewActivity.Companion.newIntent(appContext, wallpaper,
+                        isAssetIdPresent, mIsViewAsHome, /* isNewTask= */ isMultiPanel);
             }
 
             // Launch a full preview activity for devices supporting multipanel mode
diff --git a/src/com/android/wallpaper/picker/broadcast/BroadcastDispatcher.kt b/src/com/android/wallpaper/picker/broadcast/BroadcastDispatcher.kt
new file mode 100644
index 0000000..632682a
--- /dev/null
+++ b/src/com/android/wallpaper/picker/broadcast/BroadcastDispatcher.kt
@@ -0,0 +1,162 @@
+/*
+ * 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.broadcast
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Handler
+import android.os.Looper
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.wallpaper.picker.di.modules.ConcurrencyModule.*
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+
+/**
+ * WallpaperPicker master Broadcast Dispatcher.
+ *
+ * This class allows [BroadcastReceiver] to register and centralizes registrations to [Context] from
+ * WallpaperPicker. That way the number of calls to [BroadcastReceiver.onReceive] can be reduced for
+ * a given broadcast.
+ *
+ * Use only for IntentFilters with actions and optionally categories. It does not support schemes,
+ * data types, data authorities or priority different than 0.
+ *
+ * Cannot be used for getting sticky broadcasts (either as return of registering or as re-delivery).
+ */
+@Singleton
+open class BroadcastDispatcher
+@Inject
+constructor(
+    private val context: Context,
+    @Main private val mainExecutor: Executor,
+    @BroadcastRunning private val broadcastLooper: Looper,
+    @BroadcastRunning private val broadcastExecutor: Executor,
+) {
+    /**
+     * Register a receiver for broadcast with the dispatcher
+     *
+     * @param receiver A receiver to dispatch the [Intent]
+     * @param filter A filter to determine what broadcasts should be dispatched to this receiver. It
+     *   will only take into account actions and categories for filtering. It must have at least one
+     *   action.
+     * @param executor An executor to dispatch [BroadcastReceiver.onReceive].
+     * @param flags Flags to use when registering the receiver. [Context.RECEIVER_EXPORTED] by
+     *   default.
+     * @param permission to enforce security on who can send broadcasts to the receiver.
+     * @throws IllegalArgumentException if the filter has other constraints that are not actions or
+     *   categories or the filter has no actions.
+     */
+    @JvmOverloads
+    open fun registerReceiver(
+        receiver: BroadcastReceiver,
+        filter: IntentFilter,
+        executor: Executor = mainExecutor,
+        @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED,
+        permission: String? = null
+    ) {
+        checkFilter(filter)
+        context.registerReceiver(receiver, filter, permission, Handler(broadcastLooper), flags)
+    }
+
+    /**
+     * Returns a [Flow] that, when collected, emits a new value whenever a broadcast matching
+     * [filter] is received. The value will be computed from the intent and the registered receiver
+     * using [map].
+     *
+     * @see registerReceiver
+     */
+    @JvmOverloads
+    fun <T> broadcastFlow(
+        filter: IntentFilter,
+        @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED,
+        permission: String? = null,
+        map: (Intent, BroadcastReceiver) -> T,
+    ): Flow<T> = callbackFlow {
+        val receiver =
+            object : BroadcastReceiver() {
+                override fun onReceive(context: Context, intent: Intent) {
+                    trySend(map(intent, this))
+                }
+            }
+
+        registerReceiver(
+            receiver,
+            filter,
+            broadcastExecutor,
+            flags,
+            permission,
+        )
+
+        awaitClose { unregisterReceiver(receiver) }
+    }
+
+    /**
+     * Returns a [Flow] that, when collected, emits `Unit` whenever a broadcast matching [filter] is
+     * received.
+     *
+     * @see registerReceiver
+     */
+    @JvmOverloads
+    fun broadcastFlow(
+        filter: IntentFilter,
+        @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED,
+        permission: String? = null,
+    ): Flow<Unit> = broadcastFlow(filter, flags, permission) { _, _ -> Unit }
+
+    private fun checkFilter(filter: IntentFilter) {
+        buildString {
+                if (filter.countActions() == 0) {
+                    append("Filter must contain at least one action. ")
+                }
+                if (filter.countDataAuthorities() != 0) {
+                    append("Filter cannot contain DataAuthorities. ")
+                }
+                if (filter.countDataPaths() != 0) {
+                    append("Filter cannot contain DataPaths. ")
+                }
+                if (filter.countDataSchemes() != 0) {
+                    append("Filter cannot contain DataSchemes. ")
+                }
+                if (filter.countDataTypes() != 0) {
+                    append("Filter cannot contain DataTypes. ")
+                }
+                if (filter.priority != 0) {
+                    append("Filter cannot modify priority. ")
+                }
+            }
+            .let {
+                if (it.isNotEmpty()) {
+                    throw IllegalArgumentException(it)
+                }
+            }
+    }
+
+    /**
+     * Unregister receiver for the current user.
+     *
+     * @param receiver The receiver to unregister.
+     */
+    open fun unregisterReceiver(receiver: BroadcastReceiver) {
+        context.unregisterReceiver(receiver)
+    }
+}
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 41c4b8a..649a140 100644
--- a/src/com/android/wallpaper/picker/customization/data/content/WallpaperClient.kt
+++ b/src/com/android/wallpaper/picker/customization/data/content/WallpaperClient.kt
@@ -17,13 +17,18 @@
 
 package com.android.wallpaper.picker.customization.data.content
 
+import android.app.WallpaperColors
+import android.app.WallpaperManager
 import android.graphics.Bitmap
+import android.graphics.Point
 import android.graphics.Rect
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel.StaticWallpaperModel
 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. */
@@ -43,17 +48,30 @@
      * @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 cropHints The crop hints that indicate how the wallpaper should be cropped and render
-     *   on the designated screen and orientation.
-     * @param onDone A callback to invoke when setting is done.
+     * @param wallpaperSize raw wallpaper size
+     * @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,
-        cropHints: Map<ScreenOrientation, Rect>,
-        onDone: () -> Unit,
+        wallpaperSize: Point,
+        fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
+    )
+
+    /**
+     * Asynchronously sets a live wallpaper.
+     *
+     * @param setWallpaperEntryPoint The entry point where we set the wallpaper from.
+     * @param destination The screen to set the wallpaper on.
+     * @param wallpaperModel The wallpaper model of the wallpaper.
+     */
+    suspend fun setLiveWallpaper(
+        @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
+        destination: WallpaperDestination,
+        wallpaperModel: LiveWallpaperModel,
     )
 
     /**
@@ -77,4 +95,12 @@
 
     /** Returns whether the recent wallpapers provider is available. */
     fun areRecentsAvailable(): Boolean
+
+    fun getCurrentCropHints(
+        displaySizes: List<Point>,
+        @WallpaperManager.SetWallpaperFlags which: Int
+    ): Map<Point, Rect>?
+
+    /** Returns the wallpaper colors for preview a bitmap with a set of crop hints */
+    suspend fun getWallpaperColors(bitmap: Bitmap, cropHints: Map<Point, Rect>?): WallpaperColors?
 }
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 0440bb5..7edc234 100644
--- a/src/com/android/wallpaper/picker/customization/data/content/WallpaperClientImpl.kt
+++ b/src/com/android/wallpaper/picker/customization/data/content/WallpaperClientImpl.kt
@@ -17,7 +17,12 @@
 
 package com.android.wallpaper.picker.customization.data.content
 
+import android.app.WallpaperColors
 import android.app.WallpaperManager
+import android.app.WallpaperManager.FLAG_LOCK
+import android.app.WallpaperManager.FLAG_SYSTEM
+import android.app.WallpaperManager.SetWallpaperFlags
+import android.content.ComponentName
 import android.content.ContentResolver
 import android.content.ContentValues
 import android.content.Context
@@ -25,21 +30,32 @@
 import android.graphics.Bitmap
 import android.graphics.BitmapFactory
 import android.graphics.Color
+import android.graphics.Point
 import android.graphics.Rect
 import android.net.Uri
 import android.os.Looper
 import android.util.Log
+import androidx.collection.ArrayMap
 import com.android.wallpaper.asset.BitmapUtils
-import com.android.wallpaper.model.StaticWallpaperMetadata
+import com.android.wallpaper.model.CreativeCategory
+import com.android.wallpaper.model.LiveWallpaperPrefMetadata
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.module.InjectorProvider
 import com.android.wallpaper.module.WallpaperPreferences
 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.WallpaperDestination.BOTH
+import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination.Companion.toDestinationInt
+import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination.HOME
+import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination.LOCK
 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 com.android.wallpaper.util.WallpaperCropUtils
 import java.io.IOException
+import java.io.InputStream
 import java.util.EnumMap
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
@@ -115,51 +131,257 @@
         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperModel: StaticWallpaperModel,
+        inputStream: InputStream?,
         bitmap: Bitmap,
-        cropHints: Map<ScreenOrientation, Rect>,
-        onDone: () -> Unit
+        wallpaperSize: Point,
+        fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
     ) {
-        // TODO (b/309138446): Use the new multi-crop API from WallpaperManager
-        val wallpaperManagerId =
-            wallpaperManager.setBitmap(
+        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.
+            stopWallpaperRotation()
+        }
+
+        val cropHintsWithParallax =
+            fullPreviewCropModels?.let { cropModels ->
+                cropModels.mapValues { it.value.adjustCropForParallax(wallpaperSize) }
+            }
+                ?: emptyMap()
+        val managerId =
+            wallpaperManager.setStaticWallpaperToSystem(
+                inputStream,
                 bitmap,
-                cropHints[ScreenOrientation.PORTRAIT],
-                true,
-                destination.toFlags()
+                cropHintsWithParallax,
+                destination,
             )
-        // Save wallpaper metadata in the preference for two purposes
-        // 1. Quickly reconstruct the currently-selected wallpaper when opening the app
-        // 2. Snapshot logging
-        val bitmapHash = BitmapUtils.generateHashCode(bitmap)
-        val metadata =
-            StaticWallpaperMetadata(
-                wallpaperModel.commonWallpaperData.attributions,
-                wallpaperModel.commonWallpaperData.exploreActionUrl,
-                wallpaperModel.commonWallpaperData.id.collectionId,
-                bitmapHash,
-                wallpaperManagerId,
-                wallpaperModel.commonWallpaperData.id.uniqueId,
-                // TODO (b/309139122): Introduce crop hints to StaticWallpaperMetadata
-                cropHints = null,
-            )
-        if (destination == WallpaperDestination.HOME || destination == WallpaperDestination.BOTH) {
-            wallpaperPreferences.clearHomeWallpaperMetadata()
-            wallpaperPreferences.setHomeStaticImageWallpaperMetadata(metadata)
-        }
-        if (destination == WallpaperDestination.LOCK || destination == WallpaperDestination.BOTH) {
-            wallpaperPreferences.clearLockWallpaperMetadata()
-            wallpaperPreferences.setLockStaticImageWallpaperMetadata(metadata)
-        }
+
+        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,
-            // TODO (b/309139122): Introduce crop hints to recent wallpapers
-            emptyMap(),
+            cropHintsWithParallax,
         )
     }
 
+    private fun stopWallpaperRotation() {
+        wallpaperPreferences.setWallpaperPresentationMode(
+            WallpaperPreferences.PRESENTATION_MODE_STATIC
+        )
+        wallpaperPreferences.clearDailyRotations()
+    }
+
+    /**
+     * Use [WallpaperManager] to set a static wallpaper to the system.
+     *
+     * @return Wallpaper manager ID
+     */
+    private fun WallpaperManager.setStaticWallpaperToSystem(
+        inputStream: InputStream?,
+        bitmap: Bitmap,
+        cropHints: Map<Point, Rect>,
+        destination: WallpaperDestination,
+    ): Int {
+        return if (inputStream != null) {
+            setStreamWithCrops(
+                inputStream,
+                cropHints,
+                /* allowBackup= */ true,
+                destination.toFlags(),
+            )
+        } else {
+            setBitmapWithCrops(
+                bitmap,
+                cropHints,
+                /* allowBackup= */ true,
+                destination.toFlags(),
+            )
+        }
+    }
+
+    private fun StaticWallpaperModel.getMetadata(
+        bitmap: Bitmap,
+        managerId: Int,
+    ): StaticWallpaperPrefMetadata {
+        val bitmapHash = BitmapUtils.generateHashCode(bitmap)
+        return StaticWallpaperPrefMetadata(
+            commonWallpaperData.attributions,
+            commonWallpaperData.exploreActionUrl,
+            commonWallpaperData.id.collectionId,
+            bitmapHash,
+            managerId,
+            commonWallpaperData.id.uniqueId,
+        )
+    }
+
+    /**
+     * Save wallpaper metadata in the preference for two purposes:
+     * 1. Quickly reconstruct the currently-selected wallpaper when opening the app
+     * 2. Snapshot logging
+     */
+    private fun WallpaperPreferences.setStaticWallpaperMetadata(
+        metadata: StaticWallpaperPrefMetadata,
+        destination: WallpaperDestination
+    ) {
+        when (destination) {
+            HOME -> {
+                clearHomeWallpaperMetadata()
+                setHomeStaticImageWallpaperMetadata(metadata)
+            }
+            LOCK -> {
+                clearLockWallpaperMetadata()
+                setLockStaticImageWallpaperMetadata(metadata)
+            }
+            BOTH -> {
+                clearHomeWallpaperMetadata()
+                setHomeStaticImageWallpaperMetadata(metadata)
+                clearLockWallpaperMetadata()
+                setLockStaticImageWallpaperMetadata(metadata)
+            }
+        }
+    }
+
+    override suspend fun setLiveWallpaper(
+        setWallpaperEntryPoint: Int,
+        destination: WallpaperDestination,
+        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.
+            stopWallpaperRotation()
+        }
+
+        if (wallpaperModel.creativeWallpaperData != null) {
+            saveCreativeWallpaperAtExternal(wallpaperModel, destination)
+        }
+
+        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. */
+    private fun saveCreativeWallpaperAtExternal(
+        wallpaperModel: LiveWallpaperModel,
+        destination: WallpaperDestination,
+    ) {
+        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,
+                    )
+                }
+            } catch (e: Exception) {
+                Log.e(TAG, "Failed updating creative live wallpaper at external.")
+            }
+        }
+    }
+
+    /**
+     * Use [WallpaperManager] to set a live wallpaper to the system.
+     *
+     * @return Wallpaper manager ID
+     */
+    private fun WallpaperManager.setLiveWallpaperToSystem(
+        wallpaperModel: LiveWallpaperModel,
+        destination: WallpaperDestination
+    ): Int {
+        val componentName = wallpaperModel.commonWallpaperData.id.componentName
+        try {
+            // Probe if the function setWallpaperComponentWithFlags exists
+            javaClass.getMethod(
+                "setWallpaperComponentWithFlags",
+                ComponentName::class.java,
+                Int::class.javaPrimitiveType
+            )
+            setWallpaperComponentWithFlags(componentName, destination.toFlags())
+        } catch (e: NoSuchMethodException) {
+            setWallpaperComponent(componentName)
+        }
+
+        // Be careful that WallpaperManager.getWallpaperId can only accept either
+        // WallpaperManager.FLAG_SYSTEM or WallpaperManager.FLAG_LOCK.
+        // If destination is BOTH, either flag should return the same wallpaper manager ID.
+        return getWallpaperId(
+            if (destination == BOTH || destination == HOME) FLAG_SYSTEM else FLAG_LOCK
+        )
+    }
+
+    private fun LiveWallpaperModel.getMetadata(managerId: Int): LiveWallpaperPrefMetadata {
+        return LiveWallpaperPrefMetadata(
+            commonWallpaperData.attributions,
+            liveWallpaperData.systemWallpaperInfo.serviceName,
+            liveWallpaperData.effectNames,
+            commonWallpaperData.id.collectionId,
+            managerId,
+        )
+    }
+
+    /**
+     * Save wallpaper metadata in the preference for two purposes:
+     * 1. Quickly reconstruct the currently-selected wallpaper when opening the app
+     * 2. Snapshot logging
+     */
+    private fun WallpaperPreferences.setLiveWallpaperMetadata(
+        metadata: LiveWallpaperPrefMetadata,
+        destination: WallpaperDestination
+    ) {
+        when (destination) {
+            HOME -> {
+                clearHomeWallpaperMetadata()
+                setHomeLiveWallpaperMetadata(metadata)
+            }
+            LOCK -> {
+                clearLockWallpaperMetadata()
+                setLockLiveWallpaperMetadata(metadata)
+            }
+            BOTH -> {
+                clearHomeWallpaperMetadata()
+                setHomeLiveWallpaperMetadata(metadata)
+                clearLockWallpaperMetadata()
+                setLockLiveWallpaperMetadata(metadata)
+            }
+        }
+    }
+
+    /** Get the URI to call the external app to save the creative wallpaper. */
+    private fun LiveWallpaperModel.getSaveWallpaperUriAndAuthority(
+        destination: WallpaperDestination
+    ): Pair<Uri, String>? {
+        val uriString =
+            liveWallpaperData.systemWallpaperInfo.serviceInfo.metaData.getString(
+                CreativeCategory.KEY_WALLPAPER_SAVE_CREATIVE_CATEGORY_WALLPAPER
+            )
+                ?: return null
+        val uri =
+            Uri.parse(uriString)
+                ?.buildUpon()
+                ?.appendQueryParameter("destination", destination.toDestinationInt().toString())
+                ?.build()
+                ?: return null
+        val authority = uri.authority ?: return null
+        return Pair(uri, authority)
+    }
+
     override suspend fun setRecentWallpaper(
         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
@@ -238,7 +460,7 @@
     ): WallpaperModel {
         val currentWallpapers = getCurrentWallpapers()
         val wallpaper: WallpaperInfo =
-            if (destination == WallpaperDestination.LOCK) {
+            if (destination == LOCK) {
                 currentWallpapers.second ?: currentWallpapers.first
             } else {
                 currentWallpapers.first
@@ -329,22 +551,78 @@
         return recentsContentProviderAvailable == true
     }
 
+    override fun getCurrentCropHints(
+        displaySizes: List<Point>,
+        @SetWallpaperFlags which: Int
+    ): Map<Point, Rect>? {
+        val flags = InjectorProvider.getInjector().getFlags()
+        val isMultiCropEnabled = flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()
+        if (!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
+    }
+
+    override suspend fun getWallpaperColors(
+        bitmap: Bitmap,
+        cropHints: Map<Point, Rect>?
+    ): WallpaperColors? {
+        return wallpaperManager.getWallpaperColors(bitmap, cropHints)
+    }
+
     fun WallpaperDestination.asString(): String {
         return when (this) {
-            WallpaperDestination.BOTH -> SCREEN_ALL
-            WallpaperDestination.HOME -> SCREEN_HOME
-            WallpaperDestination.LOCK -> SCREEN_LOCK
+            BOTH -> SCREEN_ALL
+            HOME -> SCREEN_HOME
+            LOCK -> SCREEN_LOCK
         }
     }
 
     private fun WallpaperDestination.toFlags(): Int {
         return when (this) {
-            WallpaperDestination.BOTH -> WallpaperManager.FLAG_LOCK or WallpaperManager.FLAG_SYSTEM
-            WallpaperDestination.HOME -> WallpaperManager.FLAG_SYSTEM
-            WallpaperDestination.LOCK -> WallpaperManager.FLAG_LOCK
+            BOTH -> FLAG_LOCK or FLAG_SYSTEM
+            HOME -> FLAG_SYSTEM
+            LOCK -> FLAG_LOCK
         }
     }
 
+    /**
+     * Adjusts cropHints for parallax effect.
+     *
+     * [WallpaperCropUtils.calculateCropRect] calculates based on the scaled size, the scale depends
+     * on the view size hosting the preview and the wallpaper zoom of the preview on that view,
+     * whereas the rest of multi-crop is based on full wallpaper size. So scaled back at the end.
+     *
+     * If [CropSizeModel] is null, returns the original cropHint without parallax.
+     *
+     * @param wallpaperSize full wallpaper image size.
+     */
+    private fun FullPreviewCropModel.adjustCropForParallax(
+        wallpaperSize: Point,
+    ): Rect {
+        return cropSizeModel?.let {
+            WallpaperCropUtils.calculateCropRect(
+                    context,
+                    it.hostViewSize,
+                    it.cropSurfaceSize,
+                    wallpaperSize,
+                    cropHint,
+                    it.wallpaperZoom,
+                    /* cropExtraWidth= */ true,
+                )
+                .apply { scale(1f / it.wallpaperZoom) }
+        }
+            ?: cropHint
+    }
+
     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 42df53b..ec3e58c 100644
--- a/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepository.kt
+++ b/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepository.kt
@@ -17,13 +17,20 @@
 
 package com.android.wallpaper.picker.customization.data.repository
 
+import android.app.WallpaperColors
 import android.graphics.Bitmap
+import android.graphics.Point
+import android.graphics.Rect
 import android.util.LruCache
 import com.android.wallpaper.module.WallpaperPreferences
 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
 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.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
@@ -113,8 +120,45 @@
             }
     }
 
+    suspend fun setStaticWallpaper(
+        @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
+        destination: WallpaperDestination,
+        wallpaperModel: StaticWallpaperModel,
+        inputStream: InputStream?,
+        bitmap: Bitmap,
+        wallpaperSize: Point,
+        fullPreviewCropModels: Map<Point, FullPreviewCropModel>? = null,
+    ) {
+        // TODO(b/303317694): provide set wallpaper status as flow
+        withContext(backgroundDispatcher) {
+            client.setStaticWallpaper(
+                setWallpaperEntryPoint,
+                destination,
+                wallpaperModel,
+                inputStream,
+                bitmap,
+                wallpaperSize,
+                fullPreviewCropModels,
+            )
+        }
+    }
+
+    suspend fun setLiveWallpaper(
+        @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
+        destination: WallpaperDestination,
+        wallpaperModel: LiveWallpaperModel,
+    ) {
+        withContext(backgroundDispatcher) {
+            client.setLiveWallpaper(
+                setWallpaperEntryPoint,
+                destination,
+                wallpaperModel,
+            )
+        }
+    }
+
     /** Sets the wallpaper to the one with the given ID. */
-    suspend fun setWallpaper(
+    suspend fun setRecentWallpaper(
         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperId: String,
@@ -133,6 +177,9 @@
         }
     }
 
+    suspend fun getWallpaperColors(bitmap: Bitmap, cropHints: Map<Point, Rect>?): WallpaperColors? =
+        withContext(backgroundDispatcher) { client.getWallpaperColors(bitmap, cropHints) }
+
     companion object {
         const val DEFAULT_KEY = "default_missing_key"
         /** The maximum number of options to show, including the currently-selected one. */
diff --git a/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractor.kt b/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractor.kt
index 016d670..cf645f5 100644
--- a/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractor.kt
+++ b/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractor.kt
@@ -99,12 +99,12 @@
     }
 
     /** Sets the wallpaper to the one with the given ID. */
-    suspend fun setWallpaper(
+    suspend fun setRecentWallpaper(
         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperId: String,
     ) {
-        repository.setWallpaper(
+        repository.setRecentWallpaper(
             setWallpaperEntryPoint = setWallpaperEntryPoint,
             destination = destination,
             wallpaperId = wallpaperId,
diff --git a/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperSnapshotRestorer.kt b/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperSnapshotRestorer.kt
index e3ca17f..ab8e7bd 100644
--- a/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperSnapshotRestorer.kt
+++ b/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperSnapshotRestorer.kt
@@ -51,7 +51,7 @@
     ) {
         val homeWallpaperId = snapshot.args[SELECTED_HOME_SCREEN_WALLPAPER_ID]
         if (!homeWallpaperId.isNullOrEmpty()) {
-            interactor.setWallpaper(
+            interactor.setRecentWallpaper(
                 setWallpaperEntryPoint = SET_WALLPAPER_ENTRY_POINT_RESET,
                 destination = WallpaperDestination.HOME,
                 wallpaperId = homeWallpaperId
@@ -60,7 +60,7 @@
 
         val lockWallpaperId = snapshot.args[SELECTED_LOCK_SCREEN_WALLPAPER_ID]
         if (!lockWallpaperId.isNullOrEmpty()) {
-            interactor.setWallpaper(
+            interactor.setRecentWallpaper(
                 setWallpaperEntryPoint = SET_WALLPAPER_ENTRY_POINT_RESET,
                 destination = WallpaperDestination.LOCK,
                 wallpaperId = lockWallpaperId
diff --git a/src/com/android/wallpaper/picker/customization/shared/model/WallpaperDestination.kt b/src/com/android/wallpaper/picker/customization/shared/model/WallpaperDestination.kt
index 6adbb22..4b8c680 100644
--- a/src/com/android/wallpaper/picker/customization/shared/model/WallpaperDestination.kt
+++ b/src/com/android/wallpaper/picker/customization/shared/model/WallpaperDestination.kt
@@ -20,6 +20,10 @@
 import android.app.WallpaperManager.FLAG_LOCK
 import android.app.WallpaperManager.FLAG_SYSTEM
 import android.app.WallpaperManager.SetWallpaperFlags
+import com.android.wallpaper.module.WallpaperPersister.DEST_BOTH
+import com.android.wallpaper.module.WallpaperPersister.DEST_HOME_SCREEN
+import com.android.wallpaper.module.WallpaperPersister.DEST_LOCK_SCREEN
+import com.android.wallpaper.module.WallpaperPersister.Destination
 
 /** Enumerates all known wallpaper destinations. */
 enum class WallpaperDestination {
@@ -39,5 +43,14 @@
                 else -> throw IllegalArgumentException("Bad @SetWallpaperFlags value $flags")
             }
         }
+
+        @Destination
+        fun WallpaperDestination.toDestinationInt(): Int {
+            return when (this) {
+                BOTH -> DEST_BOTH
+                HOME -> DEST_HOME_SCREEN
+                LOCK -> DEST_LOCK_SCREEN
+            }
+        }
     }
 }
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 34f0770..891177b 100644
--- a/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt
@@ -134,6 +134,7 @@
 
         val flags = BaseFlags.get()
         val isPageTransitionsFeatureEnabled = flags.isPageTransitionsFeatureEnabled(activity)
+        val isMultiCropEnabled = flags.isMultiCropEnabled() && flags.isMultiCropPreviewUiEnabled()
 
         val showLoadingAnimation =
             flags.isPreviewLoadingAnimationEnabled(activity.applicationContext)
@@ -303,7 +304,8 @@
                                     activity = activity,
                                     wallpaperInfo = wallpaperInfo,
                                     surfaceCallback = wallpaperSurfaceCallback,
-                                    offsetToStart = offsetToStart,
+                                    offsetToStart =
+                                        if (isMultiCropEnabled) false else offsetToStart,
                                     onSurfaceViewsReady = surfaceViewsReady,
                                     thumbnailRequested = thumbnailRequested
                                 )
@@ -362,7 +364,7 @@
                     lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                         var initialWallpaperUpdate = true
                         viewModel.shouldReloadWallpaper().collect { shouldReload ->
-                            viewModel.getWallpaperInfo(forceReload = false)
+                            viewModel.getWallpaperInfo(forceReload = shouldReload)
                             // Do not update screen preview on initial update,since the initial
                             // update results from starting or resuming the activity.
                             if (initialWallpaperUpdate) {
@@ -467,7 +469,7 @@
                                 activity = activity,
                                 wallpaperInfo = wallpaperInfo,
                                 surfaceCallback = wallpaperSurfaceCallback,
-                                offsetToStart = offsetToStart,
+                                offsetToStart = if (isMultiCropEnabled) false else offsetToStart,
                                 onSurfaceViewsReady = surfaceViewsReady,
                                 thumbnailRequested = thumbnailRequested
                             )
@@ -611,7 +613,8 @@
                     activity,
                     imageView,
                     ResourceUtils.getColorAttr(activity, android.R.attr.colorSecondary),
-                    /* offsetToStart= */ thumbAsset !is CurrentWallpaperAsset || offsetToStart
+                    /* offsetToStart= */ thumbAsset !is CurrentWallpaperAsset || offsetToStart,
+                    wallpaperInfo.wallpaperCropHints
                 )
             if (wallpaperInfo !is LiveWallpaperInfo) {
                 imageView.addOnLayoutChangeListener(
diff --git a/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchOptionBinder.kt b/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchOptionBinder.kt
index e406c16..8327d9a 100644
--- a/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchOptionBinder.kt
+++ b/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchOptionBinder.kt
@@ -26,6 +26,7 @@
 import androidx.lifecycle.lifecycleScope
 import com.android.wallpaper.R
 import com.android.wallpaper.picker.customization.ui.viewmodel.WallpaperQuickSwitchOptionViewModel
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.launch
 
 /**
@@ -45,18 +46,37 @@
         largeOptionWidthPx: Int,
         isThumbnailFadeAnimationEnabled: Boolean,
         position: Int,
+        titleMap: MutableMap<String, Int>,
     ) {
         val selectionBorder: View = view.requireViewById(R.id.selection_border)
         val selectionIcon: View = view.requireViewById(R.id.selection_icon)
         val thumbnailView: ImageView = view.requireViewById(R.id.thumbnail)
         val placeholder: ImageView = view.requireViewById(R.id.placeholder)
 
-        view.contentDescription =
-            viewModel.title
-                ?: view.resources.getString(R.string.recent_wallpaper_label, "$position")
-
         placeholder.setBackgroundColor(viewModel.placeholderColor)
 
+        if (viewModel.title != null) {
+            viewModel.title
+            val latestIndex = titleMap.getOrDefault(viewModel.title, 0) + 1
+
+            view.contentDescription =
+                view.resources.getString(
+                    R.string.recents_wallpaper_label,
+                    viewModel.title,
+                    latestIndex,
+                )
+            titleMap[viewModel.title] = position + 1
+        } else {
+            // if the content description is missing then the default description will be the
+            // default wallpaper title and its position
+            view.contentDescription =
+                view.resources.getString(
+                    R.string.recents_wallpaper_label,
+                    view.resources.getString(R.string.default_wallpaper_title),
+                    position + 1,
+                )
+        }
+
         lifecycleOwner.lifecycleScope.launch {
             launch {
                 viewModel.onSelected.collect { onSelectedOrNull ->
@@ -84,6 +104,13 @@
             }
 
             launch {
+                viewModel.isSelectionIndicatorVisible.distinctUntilChanged().collect { isSelected ->
+                    // Update the content description to announce the selection status
+                    view.isSelected = isSelected
+                }
+            }
+
+            launch {
                 // We want to skip animating the first update so it doesn't "blink" when the
                 // activity is recreated.
                 var isFirstValue = true
diff --git a/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchSectionBinder.kt b/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchSectionBinder.kt
index 88cc10a..3e0a673 100644
--- a/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchSectionBinder.kt
+++ b/src/com/android/wallpaper/picker/customization/ui/binder/WallpaperQuickSwitchSectionBinder.kt
@@ -86,6 +86,8 @@
             // Calculate the sizes that views should have.
             val (largeOptionWidth, smallOptionWidth) = calculateSizes(parent, options.size)
 
+            val titleMap = mutableMapOf<String, Int>()
+
             // Create, add, and bind a view for each option.
             options.forEachIndexed { index, option ->
                 val optionView =
@@ -100,7 +102,8 @@
                     smallOptionWidthPx = smallOptionWidth,
                     largeOptionWidthPx = largeOptionWidth,
                     isThumbnailFadeAnimationEnabled = isThumbnailFadeAnimationEnabled,
-                    position = index
+                    position = index,
+                    titleMap = titleMap,
                 )
             }
         }
@@ -153,7 +156,7 @@
             )
     }
 
-    /** Compose-inspired cnvenience alias for getting a dimension in pixels. */
+    /** Compose-inspired convenience alias for getting a dimension in pixels. */
     private fun View.dimensionResource(
         @DimenRes res: Int,
     ): Int {
diff --git a/src/com/android/wallpaper/picker/customization/ui/viewmodel/ScreenPreviewViewModel.kt b/src/com/android/wallpaper/picker/customization/ui/viewmodel/ScreenPreviewViewModel.kt
index 7bd8b61..6ec0f3f 100644
--- a/src/com/android/wallpaper/picker/customization/ui/viewmodel/ScreenPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/customization/ui/viewmodel/ScreenPreviewViewModel.kt
@@ -56,8 +56,7 @@
         // TODO(b/281730113) Remove this once better solution is ready.
         return wallpaperUpdateEvents().map { thisWallpaper ->
             val otherWallpaper = wallpaperUpdateEvents(otherScreen()).first()
-            wallpaperInteractor.shouldHandleReload() ||
-                thisWallpaper?.wallpaperId == otherWallpaper?.wallpaperId
+            true
         }
     }
 
diff --git a/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModel.kt b/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModel.kt
index cf945b6..3cc39c6 100644
--- a/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModel.kt
+++ b/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModel.kt
@@ -128,14 +128,10 @@
                                     isSelectedFlow,
                                     isBecomingSelectedFlow,
                                     isSomethingBecomingSelectedFlow,
-                                ) { isSelected, isBeingSelected, isSomethingBecomingSelected,
-                                    ->
-                                    // An option is selectable if it is not itself becoming
-                                    // selected following user click or if nothing else is
-                                    // becoming selected but this option is not the selected
-                                    // one.
-                                    (isSomethingBecomingSelected && !isBeingSelected) ||
-                                        (!isSomethingBecomingSelected && !isSelected)
+                                ) { isSelected, _, isSomethingBecomingSelected ->
+                                    // An option is selectable if either something is not becoming
+                                    // selected and that item is itself not selected.
+                                    !isSomethingBecomingSelected && !isSelected
                                 }
                                 .distinctUntilChanged()
                                 .map { isSelectable ->
@@ -143,7 +139,7 @@
                                         {
                                             // A selectable option can become selected.
                                             coroutineScope.launch {
-                                                interactor.setWallpaper(
+                                                interactor.setRecentWallpaper(
                                                     setWallpaperEntryPoint =
                                                         SET_WALLPAPER_ENTRY_POINT_WALLPAPER_QUICK_SWITCHER,
                                                     destination = destination,
diff --git a/src/com/android/wallpaper/model/wallpaper/ColorInfo.kt b/src/com/android/wallpaper/picker/data/ColorInfo.kt
similarity index 94%
rename from src/com/android/wallpaper/model/wallpaper/ColorInfo.kt
rename to src/com/android/wallpaper/picker/data/ColorInfo.kt
index a83d96c..50b3f37 100644
--- a/src/com/android/wallpaper/model/wallpaper/ColorInfo.kt
+++ b/src/com/android/wallpaper/picker/data/ColorInfo.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import android.app.WallpaperColors
 import android.graphics.Color
diff --git a/src/com/android/wallpaper/model/wallpaper/CommonWallpaperData.kt b/src/com/android/wallpaper/picker/data/CommonWallpaperData.kt
similarity index 90%
rename from src/com/android/wallpaper/model/wallpaper/CommonWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/CommonWallpaperData.kt
index 306e729..13d8d11 100644
--- a/src/com/android/wallpaper/model/wallpaper/CommonWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/CommonWallpaperData.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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import com.android.wallpaper.asset.Asset
 
diff --git a/src/com/android/wallpaper/model/wallpaper/CreativeWallpaperData.kt b/src/com/android/wallpaper/picker/data/CreativeWallpaperData.kt
similarity index 76%
rename from src/com/android/wallpaper/model/wallpaper/CreativeWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/CreativeWallpaperData.kt
index ea1158b..2b50acb 100644
--- a/src/com/android/wallpaper/model/wallpaper/CreativeWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/CreativeWallpaperData.kt
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import android.net.Uri
 
 /** Represents data that is specific to only CreativeWallpapers. */
 data class CreativeWallpaperData(
-    val configPreviewUri: Uri,
-    val cleanPreviewUri: Uri,
-    val deleteUri: Uri,
-    val thumbnailUri: Uri,
-    val shareUri: Uri,
+    val configPreviewUri: Uri?,
+    val cleanPreviewUri: Uri?,
+    val deleteUri: Uri?,
+    val thumbnailUri: Uri?,
+    val shareUri: Uri?,
     val author: String,
     val description: String,
-    val contentDescription: String,
-    val isCurrent: String,
+    val contentDescription: String?,
+    val isCurrent: Boolean,
 )
diff --git a/src/com/android/wallpaper/model/wallpaper/DownloadableWallpaperData.kt b/src/com/android/wallpaper/picker/data/DownloadableWallpaperData.kt
similarity index 95%
rename from src/com/android/wallpaper/model/wallpaper/DownloadableWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/DownloadableWallpaperData.kt
index 04ff8c6..a739ab8 100644
--- a/src/com/android/wallpaper/model/wallpaper/DownloadableWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/DownloadableWallpaperData.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import android.app.WallpaperInfo
 
diff --git a/src/com/android/wallpaper/model/wallpaper/ImageWallpaperData.kt b/src/com/android/wallpaper/picker/data/ImageWallpaperData.kt
similarity index 94%
rename from src/com/android/wallpaper/model/wallpaper/ImageWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/ImageWallpaperData.kt
index b53b7a7..e4b0575 100644
--- a/src/com/android/wallpaper/model/wallpaper/ImageWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/ImageWallpaperData.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import android.net.Uri
 
diff --git a/src/com/android/wallpaper/model/wallpaper/InternalLiveWallpaperData.kt b/src/com/android/wallpaper/picker/data/InternalLiveWallpaperData.kt
similarity index 94%
rename from src/com/android/wallpaper/model/wallpaper/InternalLiveWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/InternalLiveWallpaperData.kt
index ffd3724..7b3eab4 100644
--- a/src/com/android/wallpaper/model/wallpaper/InternalLiveWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/InternalLiveWallpaperData.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 /**
  * Represents set of attributes that are specific to pre-loaded google only downloadable live
diff --git a/src/com/android/wallpaper/model/wallpaper/LiveWallpaperData.kt b/src/com/android/wallpaper/picker/data/LiveWallpaperData.kt
similarity index 94%
rename from src/com/android/wallpaper/model/wallpaper/LiveWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/LiveWallpaperData.kt
index 5a3e7d5..73180f3 100644
--- a/src/com/android/wallpaper/model/wallpaper/LiveWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/LiveWallpaperData.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import android.app.WallpaperInfo
 
diff --git a/src/com/android/wallpaper/model/wallpaper/NetworkWallpaperData.kt b/src/com/android/wallpaper/picker/data/NetworkWallpaperData.kt
similarity index 94%
rename from src/com/android/wallpaper/model/wallpaper/NetworkWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/NetworkWallpaperData.kt
index 278c257..7aa3611 100644
--- a/src/com/android/wallpaper/model/wallpaper/NetworkWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/NetworkWallpaperData.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 /**
  * Represents set of attributes that are needed for a wallpaper downloaded from the background
diff --git a/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt b/src/com/android/wallpaper/picker/data/StaticWallpaperData.kt
similarity index 81%
rename from src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt
rename to src/com/android/wallpaper/picker/data/StaticWallpaperData.kt
index 0eca60f..2b92b4a 100644
--- a/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt
+++ b/src/com/android/wallpaper/picker/data/StaticWallpaperData.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.
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
+import android.graphics.Point
 import android.graphics.Rect
 import com.android.wallpaper.asset.Asset
 
 /** Represents set of attributes that are needed for a static wallpaper. */
 data class StaticWallpaperData(
     val asset: Asset,
-    val cropHints: Map<ScreenOrientation, Rect>? = null,
+    val cropHints: Map<Point, Rect>? = null,
 )
diff --git a/src/com/android/wallpaper/model/wallpaper/WallpaperDestination.kt b/src/com/android/wallpaper/picker/data/WallpaperDestination.kt
similarity index 95%
rename from src/com/android/wallpaper/model/wallpaper/WallpaperDestination.kt
rename to src/com/android/wallpaper/picker/data/WallpaperDestination.kt
index f27cec6..1270a98 100644
--- a/src/com/android/wallpaper/model/wallpaper/WallpaperDestination.kt
+++ b/src/com/android/wallpaper/picker/data/WallpaperDestination.kt
@@ -1,4 +1,4 @@
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import android.app.WallpaperManager.FLAG_LOCK
 import android.app.WallpaperManager.FLAG_SYSTEM
diff --git a/src/com/android/wallpaper/model/wallpaper/WallpaperId.kt b/src/com/android/wallpaper/picker/data/WallpaperId.kt
similarity index 80%
rename from src/com/android/wallpaper/model/wallpaper/WallpaperId.kt
rename to src/com/android/wallpaper/picker/data/WallpaperId.kt
index 2715b45..9eb0e1a 100644
--- a/src/com/android/wallpaper/model/wallpaper/WallpaperId.kt
+++ b/src/com/android/wallpaper/picker/data/WallpaperId.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 import android.content.ComponentName
 
@@ -23,4 +23,8 @@
     val componentName: ComponentName,
     val uniqueId: String,
     val collectionId: String,
-)
+) {
+    /** Gets a unique ID associated with a wallpaper model object. */
+    val wallpaperId: String
+        get() = "$componentName-$uniqueId-$collectionId"
+}
diff --git a/src/com/android/wallpaper/model/wallpaper/WallpaperModel.kt b/src/com/android/wallpaper/picker/data/WallpaperModel.kt
similarity index 94%
rename from src/com/android/wallpaper/model/wallpaper/WallpaperModel.kt
rename to src/com/android/wallpaper/picker/data/WallpaperModel.kt
index ac33dd7..2f62632 100644
--- a/src/com/android/wallpaper/model/wallpaper/WallpaperModel.kt
+++ b/src/com/android/wallpaper/picker/data/WallpaperModel.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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.wallpaper
+package com.android.wallpaper.picker.data
 
 /**
  * Represents the model class that would be used for instantiating any type of wallpaper in the
diff --git a/src/com/android/wallpaper/picker/data/category /CategoryModel.kt b/src/com/android/wallpaper/picker/data/category /CategoryModel.kt
new file mode 100644
index 0000000..5a61770
--- /dev/null
+++ b/src/com/android/wallpaper/picker/data/category /CategoryModel.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.data.category
+
+/**
+ * Represents the model class that would be used for instantiating any type of category in the
+ * picker. Only commonCategory is mandatory while others are optional.
+ */
+class CategoryModel(
+    val commonCategoryData: CommonCategoryData,
+    val thirdPartyCategoryData: ThirdPartyCategoryData? = null,
+    val imageCategoryData: ImageCategoryData? = null,
+    val collectionCategoryData: CollectionCategoryData? = null
+)
diff --git a/src/com/android/wallpaper/model/category /CollectionCategoryData.kt b/src/com/android/wallpaper/picker/data/category /CollectionCategoryData.kt
similarity index 79%
rename from src/com/android/wallpaper/model/category /CollectionCategoryData.kt
rename to src/com/android/wallpaper/picker/data/category /CollectionCategoryData.kt
index 8069d1b..80d9cb3 100644
--- a/src/com/android/wallpaper/model/category /CollectionCategoryData.kt
+++ b/src/com/android/wallpaper/picker/data/category /CollectionCategoryData.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.
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.category
+package com.android.wallpaper.picker.data.category
 
 import com.android.wallpaper.asset.Asset
-import com.android.wallpaper.model.wallpaper.WallpaperModel
+import com.android.wallpaper.picker.data.WallpaperModel
 
 /** Represents set of attributes that depict a collection of wallpapers. */
 data class CollectionCategoryData(
     val wallpaperModels: List<WallpaperModel>,
     val thumbAsset: Asset,
-    val collectionName: String,
-    val rotationEnabled: Boolean,
+    val featuredThumbnailIndex: Int,
     val isSingleWallpaperCategory: Boolean
 )
diff --git a/src/com/android/wallpaper/model/category /CommonCategoryData.kt b/src/com/android/wallpaper/picker/data/category /CommonCategoryData.kt
similarity index 87%
rename from src/com/android/wallpaper/model/category /CommonCategoryData.kt
rename to src/com/android/wallpaper/picker/data/category /CommonCategoryData.kt
index bf28bb6..0385e23 100644
--- a/src/com/android/wallpaper/model/category /CommonCategoryData.kt
+++ b/src/com/android/wallpaper/picker/data/category /CommonCategoryData.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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.category
+package com.android.wallpaper.picker.data.category
 
 /** Represents set of attributes that are common for all categories. */
 data class CommonCategoryData(val title: String, val collectionId: String, val priority: Int)
diff --git a/src/com/android/wallpaper/model/category /ImageCategoryData.kt b/src/com/android/wallpaper/picker/data/category /ImageCategoryData.kt
similarity index 76%
rename from src/com/android/wallpaper/model/category /ImageCategoryData.kt
rename to src/com/android/wallpaper/picker/data/category /ImageCategoryData.kt
index 4d2b7cb..6e904dd 100644
--- a/src/com/android/wallpaper/model/category /ImageCategoryData.kt
+++ b/src/com/android/wallpaper/picker/data/category /ImageCategoryData.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.
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.category
+package com.android.wallpaper.picker.data.category
+
+import android.graphics.drawable.Drawable
 
 /**
  * Represents set of attributes for depicting the block used for accessing personal photos on
  * device.
  */
-data class ImageCategoryData(val overlayIconResId: Int)
+data class ImageCategoryData(val overlayIconDrawable: Drawable?)
diff --git a/src/com/android/wallpaper/model/category /ThirdPartyCategoryData.kt b/src/com/android/wallpaper/picker/data/category /ThirdPartyCategoryData.kt
similarity index 88%
rename from src/com/android/wallpaper/model/category /ThirdPartyCategoryData.kt
rename to src/com/android/wallpaper/picker/data/category /ThirdPartyCategoryData.kt
index 0db6766..4fb160e 100644
--- a/src/com/android/wallpaper/model/category /ThirdPartyCategoryData.kt
+++ b/src/com/android/wallpaper/picker/data/category /ThirdPartyCategoryData.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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaper.model.category
+package com.android.wallpaper.picker.data.category
 
 import android.content.pm.ResolveInfo
 
diff --git a/src/com/android/wallpaper/picker/di/modules/AppModule.kt b/src/com/android/wallpaper/picker/di/modules/AppModule.kt
index 5489907..264868b 100644
--- a/src/com/android/wallpaper/picker/di/modules/AppModule.kt
+++ b/src/com/android/wallpaper/picker/di/modules/AppModule.kt
@@ -18,6 +18,7 @@
 
 import android.app.WallpaperManager
 import android.content.Context
+import android.content.pm.PackageManager
 import dagger.Module
 import dagger.Provides
 import dagger.hilt.InstallIn
@@ -33,4 +34,10 @@
     fun provideWallpaperManager(@ApplicationContext appContext: Context): WallpaperManager {
         return WallpaperManager.getInstance(appContext)
     }
+
+    @Provides
+    @Singleton
+    fun providePackageManager(@ApplicationContext appContext: Context): PackageManager {
+        return appContext.packageManager
+    }
 }
diff --git a/src/com/android/wallpaper/picker/di/modules/ConcurrencyModule.kt b/src/com/android/wallpaper/picker/di/modules/ConcurrencyModule.kt
new file mode 100644
index 0000000..ff2185f
--- /dev/null
+++ b/src/com/android/wallpaper/picker/di/modules/ConcurrencyModule.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.di.modules
+
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.Looper
+import android.os.Process
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import java.util.concurrent.Executor
+import javax.inject.Qualifier
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+class ConcurrencyModule {
+
+    private val BROADCAST_SLOW_DISPATCH_THRESHOLD = 1000L
+    private val BROADCAST_SLOW_DELIVERY_THRESHOLD = 1000L
+
+    @Qualifier
+    @MustBeDocumented
+    @Retention(AnnotationRetention.RUNTIME)
+    annotation class BroadcastRunning
+
+    @Provides
+    @Singleton
+    @BroadcastRunning
+    fun provideBroadcastRunningLooper(): Looper {
+        return HandlerThread(
+                "BroadcastRunning",
+                Process.THREAD_PRIORITY_BACKGROUND,
+            )
+            .apply {
+                start()
+                looper.setSlowLogThresholdMs(
+                    BROADCAST_SLOW_DISPATCH_THRESHOLD,
+                    BROADCAST_SLOW_DELIVERY_THRESHOLD,
+                )
+            }
+            .looper
+    }
+
+    /** Provide a BroadcastRunning Executor (for sending and receiving broadcasts). */
+    @Provides
+    @Singleton
+    @BroadcastRunning
+    fun provideBroadcastRunningExecutor(@BroadcastRunning looper: Looper?): Executor {
+        val handler = Handler(looper ?: Looper.getMainLooper())
+        return Executor { command -> handler.post(command) }
+    }
+}
diff --git a/src/com/android/wallpaper/picker/di/modules/DispatchersModule.kt b/src/com/android/wallpaper/picker/di/modules/DispatchersModule.kt
index e78d085..d43a0b1 100644
--- a/src/com/android/wallpaper/picker/di/modules/DispatchersModule.kt
+++ b/src/com/android/wallpaper/picker/di/modules/DispatchersModule.kt
@@ -43,5 +43,9 @@
 
     @Provides
     @BackgroundDispatcher
+    fun provideBackgroundScope(): CoroutineScope = CoroutineScope(Dispatchers.IO)
+
+    @Provides
+    @BackgroundDispatcher
     fun provideBackgroundDispatcher(): CoroutineDispatcher = Dispatchers.IO
 }
diff --git a/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java b/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java
index 595dc2d..1789db3 100755
--- a/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java
+++ b/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java
@@ -70,7 +70,6 @@
 import com.android.wallpaper.picker.StartRotationDialogFragment;
 import com.android.wallpaper.picker.StartRotationErrorDialogFragment;
 import com.android.wallpaper.util.ActivityUtils;
-import com.android.wallpaper.util.DiskBasedLogger;
 import com.android.wallpaper.util.LaunchUtils;
 import com.android.wallpaper.util.SizeCalculator;
 import com.android.wallpaper.widget.GridPaddingDecoration;
@@ -211,8 +210,6 @@
                 }
                 mCategory = (WallpaperCategory) category;
                 if (mCategory == null) {
-                    DiskBasedLogger.e(TAG, "Failed to find the category.", getContext());
-
                     // The absence of this category in the CategoryProvider indicates a broken
                     // state, see b/38030129. Hence, finish the activity and return.
                     getIndividualPickerFragmentHost().moveToPreviousFragment();
diff --git a/src/com/android/wallpaper/picker/individual/IndividualPickerFragment2.kt b/src/com/android/wallpaper/picker/individual/IndividualPickerFragment2.kt
index f5cf96c..a7d8a6e 100644
--- a/src/com/android/wallpaper/picker/individual/IndividualPickerFragment2.kt
+++ b/src/com/android/wallpaper/picker/individual/IndividualPickerFragment2.kt
@@ -68,7 +68,6 @@
 import com.android.wallpaper.picker.StartRotationDialogFragment
 import com.android.wallpaper.picker.StartRotationErrorDialogFragment
 import com.android.wallpaper.util.ActivityUtils
-import com.android.wallpaper.util.DiskBasedLogger
 import com.android.wallpaper.util.LaunchUtils
 import com.android.wallpaper.util.SizeCalculator
 import com.android.wallpaper.widget.GridPaddingDecoration
@@ -176,8 +175,6 @@
                     }
 
                     if (fetchedCategory == null) {
-                        DiskBasedLogger.e(TAG, "Failed to find the category.", context)
-
                         // The absence of this category in the CategoryProvider indicates a broken
                         // state, see b/38030129. Hence, finish the activity and return.
                         getIndividualPickerFragmentHost().moveToPreviousFragment()
diff --git a/src/com/android/wallpaper/picker/preview/data/repository/EffectsRepository.kt b/src/com/android/wallpaper/picker/preview/data/repository/EffectsRepository.kt
new file mode 100644
index 0000000..0fd887e
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/data/repository/EffectsRepository.kt
@@ -0,0 +1,278 @@
+/*
+ * 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.app.WallpaperInfo
+import android.app.WallpaperManager
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Bundle
+import android.service.wallpaper.WallpaperService
+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.picker.data.LiveWallpaperData
+import com.android.wallpaper.picker.data.WallpaperId
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
+import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2.EffectTextRes
+import dagger.hilt.android.qualifiers.ApplicationContext
+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
+@Inject
+constructor(
+    @ApplicationContext private val context: Context,
+    private val effectsController: EffectsController,
+    @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
+) {
+    enum class EffectStatus {
+        EFFECT_DISABLE,
+        EFFECT_READY,
+        EFFECT_DOWNLOAD_READY,
+        EFFECT_DOWNLOAD_IN_PROGRESS,
+        EFFECT_APPLY_IN_PROGRESS,
+        EFFECT_APPLIED,
+    }
+
+    private val _effectStatus = MutableStateFlow(EffectStatus.EFFECT_DISABLE)
+    val effectStatus = _effectStatus.asStateFlow()
+    val wallpaperEffect = MutableStateFlow<Effect?>(null)
+    // 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
+
+    suspend fun initializeEffect(
+        staticWallpaperModel: StaticWallpaperModel,
+        onWallpaperModelUpdated: (wallpaper: WallpaperModel) -> Unit
+    ) {
+        this.staticWallpaperModel = staticWallpaperModel
+        onWallpaperUpdated = onWallpaperModelUpdated
+        withContext(bgDispatcher) {
+            val listener =
+                EffectsController.EffectsServiceListener {
+                    _,
+                    bundle,
+                    resultCode,
+                    originalStatusCode,
+                    errorMessage ->
+                    when (resultCode) {
+                        EffectsController.RESULT_PROBE_SUCCESS -> {
+                            _effectStatus.value = EffectStatus.EFFECT_READY
+                        }
+                        EffectsController.RESULT_PROBE_ERROR -> {
+                            // Do nothing intended
+                        }
+                        EffectsController.RESULT_ERROR_PROBE_SUPPORT_FOREGROUND -> {
+                            if (BaseFlags.get().isWallpaperEffectModelDownloadEnabled()) {
+                                _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_READY
+                            }
+                        }
+                        EffectsController.RESULT_PROBE_FOREGROUND_DOWNLOADING -> {
+                            _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_IN_PROGRESS
+                        }
+                        EffectsController.RESULT_FOREGROUND_DOWNLOAD_SUCCEEDED -> {
+                            // TODO logger.logEffectForegroundDownload
+                            _effectStatus.value = EffectStatus.EFFECT_READY
+                        }
+                        EffectsController.RESULT_FOREGROUND_DOWNLOAD_FAILED -> {
+                            // TODO logger.logEffectForegroundDownload
+                            _effectStatus.value = EffectStatus.EFFECT_DOWNLOAD_READY
+                        }
+                        EffectsController.RESULT_SUCCESS -> {
+                            _effectStatus.value = EffectStatus.EFFECT_APPLIED
+                            // TODO logger.logEffectApply
+                            bundle.getCinematicWallpaperModel()?.let {
+                                onWallpaperUpdated.invoke(it)
+                            }
+                        }
+                        EffectsController.RESULT_SUCCESS_WITH_GENERATION_ERROR -> {
+                            _effectStatus.value = EffectStatus.EFFECT_APPLIED
+                            // TODO logger.logEffectApply
+                            bundle.getCinematicWallpaperModel()?.let {
+                                onWallpaperUpdated.invoke(it)
+                            }
+                        }
+                        EffectsController.RESULT_SUCCESS_REUSED -> {
+                            _effectStatus.value = EffectStatus.EFFECT_APPLIED
+                            bundle.getCinematicWallpaperModel()?.let {
+                                onWallpaperUpdated.invoke(it)
+                            }
+                        }
+                        else -> {
+                            // TODO onImageEffectFailed
+                            _effectStatus.value = EffectStatus.EFFECT_READY
+                        }
+                    }
+                }
+            // TODO remove listener when destroy
+            effectsController.setListener(listener)
+
+            effectsController.contentUri.let { uri ->
+                if (Uri.EMPTY.equals(uri)) {
+                    return@withContext
+                }
+
+                // Query effect provider
+                context.contentResolver
+                    .query(
+                        uri,
+                        /* projection= */ null,
+                        /* selection= */ null,
+                        /* selectionArgs= */ null,
+                        /* sortOrder= */ null
+                    )
+                    ?.use {
+                        while (it.moveToNext()) {
+                            val titleRow: Int = it.getColumnIndex(EffectContract.KEY_EFFECT_TITLE)
+                            val idRow: Int = it.getColumnIndex(EffectContract.KEY_EFFECT_ID)
+                            wallpaperEffect.value =
+                                Effect(
+                                    it.getInt(idRow),
+                                    it.getString(titleRow),
+                                    effectsController.targetEffect
+                                )
+                        }
+                    }
+            }
+
+            if (effectsController.isEffectTriggered) {
+                _effectStatus.value = EffectStatus.EFFECT_READY
+            } else {
+                effectsController.triggerEffect(context)
+            }
+        }
+    }
+
+    private fun Bundle.getCinematicWallpaperModel(): LiveWallpaperModel? {
+        val componentName =
+            if (containsKey(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT)) {
+                getParcelable<ComponentName>(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT)
+            } else {
+                null
+            }
+                ?: return null
+
+        val assetId =
+            if (containsKey(EffectContract.ASSET_ID)) {
+                getInt(EffectContract.ASSET_ID).toString()
+            } else null
+
+        val resolveInfos =
+            Intent(WallpaperService.SERVICE_INTERFACE)
+                .apply { setClassName(componentName.packageName, componentName.className) }
+                .let {
+                    context.packageManager.queryIntentServices(it, PackageManager.GET_META_DATA)
+                }
+        if (resolveInfos.isEmpty()) {
+            Log.w(TAG, "Couldn't find live wallpaper for " + componentName.className)
+            return null
+        }
+
+        try {
+            val wallpaperInfo = WallpaperInfo(context, resolveInfos[0])
+            val commonWallpaperData =
+                staticWallpaperModel.commonWallpaperData.copy(
+                    id =
+                        WallpaperId(
+                            componentName = componentName,
+                            uniqueId =
+                                if (assetId != null) "${wallpaperInfo.serviceName}_$assetId"
+                                else wallpaperInfo.serviceName,
+                            collectionId = staticWallpaperModel.commonWallpaperData.id.collectionId,
+                        ),
+                )
+            val liveWallpaperData =
+                LiveWallpaperData(
+                    groupName = "",
+                    systemWallpaperInfo = wallpaperInfo,
+                    isTitleVisible = false,
+                    isApplied = false,
+                    effectNames = null,
+                )
+            return LiveWallpaperModel(
+                commonWallpaperData = commonWallpaperData,
+                liveWallpaperData = liveWallpaperData,
+                creativeWallpaperData = null,
+                internalLiveWallpaperData = null,
+            )
+        } catch (e: XmlPullParserException) {
+            Log.w(TAG, "Skipping wallpaper " + resolveInfos[0].serviceInfo, e)
+            return null
+        } catch (e: IOException) {
+            Log.w(TAG, "Skipping wallpaper " + resolveInfos[0].serviceInfo, e)
+            return null
+        }
+    }
+
+    fun enableImageEffect(effect: EffectsController.EffectEnumInterface) {
+        _effectStatus.value = EffectStatus.EFFECT_APPLY_IN_PROGRESS
+        // TODO: Maybe we should call reconnect wallpaper if we have created a LiveWallpaperModel
+        //       if (mLiveWallpaperInfo != null) {
+        //           mCinematicViewModel.reconnectWallpaper()
+        //           return
+        //       }
+        val uri = staticWallpaperModel.imageWallpaperData?.uri ?: return
+        effectsController.generateEffect(effect, uri)
+        // TODO: Implement time out
+    }
+
+    fun disableImageEffect() {
+        // TODO implement disabling effect
+        _effectStatus.value = EffectStatus.EFFECT_READY
+        onWallpaperUpdated.invoke(staticWallpaperModel)
+    }
+
+    fun destroy() {
+        effectsController.removeListener()
+    }
+
+    fun isTargetEffect(effect: EffectsController.EffectEnumInterface): Boolean {
+        return effectsController.isTargetEffect(effect)
+    }
+
+    fun getEffectTextRes(): EffectTextRes {
+        return EffectTextRes(
+            effectsController.effectTitle,
+            effectsController.effectFailedTitle,
+            effectsController.effectSubTitle,
+            effectsController.retryInstruction,
+            effectsController.noEffectInstruction,
+        )
+    }
+
+    companion object {
+        private const val TAG = "EffectsRepository"
+    }
+}
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 e1c5fca..020593c 100644
--- a/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepository.kt
+++ b/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepository.kt
@@ -16,22 +16,55 @@
 
 package com.android.wallpaper.picker.preview.data.repository
 
-import com.android.wallpaper.model.wallpaper.WallpaperModel
+import com.android.wallpaper.module.WallpaperPreferences
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
+import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultCode.SUCCESS
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultModel
 import dagger.hilt.android.scopes.ActivityRetainedScoped
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.withContext
 
 /** This repository class manages the [WallpaperModel] for the preview screen */
 @ActivityRetainedScoped
-class WallpaperPreviewRepository @Inject constructor() {
+class WallpaperPreviewRepository
+@Inject
+constructor(
+    private val liveWallpaperDownloader: LiveWallpaperDownloader,
+    private val preferences: WallpaperPreferences,
+    @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
+) {
     /** This [WallpaperModel] represents the current selected wallpaper */
     private val _wallpaperModel = MutableStateFlow<WallpaperModel?>(null)
     val wallpaperModel: StateFlow<WallpaperModel?> = _wallpaperModel.asStateFlow()
 
-    fun setWallpaperModel(updatedWallpaperModel: WallpaperModel?) {
-        _wallpaperModel.update { updatedWallpaperModel }
+    fun setWallpaperModel(wallpaperModel: WallpaperModel) {
+        _wallpaperModel.value = wallpaperModel
     }
+
+    private val _hasTooltipBeenShown: MutableStateFlow<Boolean> =
+        MutableStateFlow(preferences.getHasPreviewTooltipBeenShown())
+    val hasTooltipBeenShown: StateFlow<Boolean> = _hasTooltipBeenShown.asStateFlow()
+
+    fun dismissTooltip() {
+        _hasTooltipBeenShown.value = true
+        preferences.setHasPreviewTooltipBeenShown(true)
+    }
+
+    suspend fun downloadWallpaper(): LiveWallpaperDownloadResultModel? =
+        withContext(bgDispatcher) {
+            val result = liveWallpaperDownloader.downloadWallpaper()
+            if (result?.code == SUCCESS && result.wallpaperModel != null) {
+                // If download success, update repo's WallpaperModel to render the live wallpaper.
+                _wallpaperModel.value = result.wallpaperModel
+                result
+            } else {
+                result
+            }
+        }
 }
diff --git a/src/com/android/wallpaper/picker/preview/data/util/DefaultLiveWallpaperDownloader.kt b/src/com/android/wallpaper/picker/preview/data/util/DefaultLiveWallpaperDownloader.kt
new file mode 100644
index 0000000..13ce3a0
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/data/util/DefaultLiveWallpaperDownloader.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.data.util
+
+import android.app.Activity
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.IntentSenderRequest
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultModel
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class DefaultLiveWallpaperDownloader @Inject constructor() : LiveWallpaperDownloader {
+
+    override fun initiateDownloadableService(
+        activity: Activity,
+        wallpaperData: WallpaperModel.StaticWallpaperModel,
+        intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
+    ) {}
+
+    override fun cleanup() {}
+
+    override suspend fun downloadWallpaper(): LiveWallpaperDownloadResultModel? {
+        return null
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/data/util/LiveWallpaperDownloader.kt b/src/com/android/wallpaper/picker/preview/data/util/LiveWallpaperDownloader.kt
new file mode 100644
index 0000000..4b1fad6
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/data/util/LiveWallpaperDownloader.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.data.util
+
+import android.app.Activity
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.IntentSenderRequest
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultModel
+
+/**
+ * Handles the download process of a downloadable wallpaper. This downloader should be aware of the
+ * Activity's lifecycle.
+ */
+interface LiveWallpaperDownloader {
+
+    /**
+     * Initializes the downloadable service. This needs to be called when [Activity.onCreate] and
+     * before calling [downloadWallpaper].
+     */
+    fun initiateDownloadableService(
+        activity: Activity,
+        wallpaperData: WallpaperModel.StaticWallpaperModel,
+        intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>,
+    )
+
+    /**
+     * Clean up the underlying downloadable service. This needs to be called when
+     * [Activity.onDestroy].
+     */
+    fun cleanup()
+
+    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 de18603..1b471cd 100644
--- a/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt
+++ b/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt
@@ -16,28 +16,55 @@
 
 package com.android.wallpaper.picker.preview.domain.interactor
 
-import com.android.wallpaper.model.wallpaper.WallpaperModel
-import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
-import com.android.wallpaper.picker.di.modules.MainDispatcher
+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.WallpaperPreviewRepository
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultModel
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
 import dagger.hilt.android.scopes.ActivityRetainedScoped
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 
 /** This class handles the business logic for Preview screen's action buttons */
 @ActivityRetainedScoped
 class PreviewActionsInteractor
 @Inject
 constructor(
-    @MainDispatcher private val mainScope: CoroutineScope,
-    @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
     private val wallpaperPreviewRepository: WallpaperPreviewRepository,
+    private val effectsRepository: EffectsRepository,
 ) {
     val wallpaperModel: StateFlow<WallpaperModel?> = wallpaperPreviewRepository.wallpaperModel
 
-    fun setWallpaperModel(wallpaperModel: WallpaperModel?) {
-        wallpaperPreviewRepository.setWallpaperModel(wallpaperModel)
+    private val _isDownloadingWallpaper = MutableStateFlow<Boolean>(false)
+    val isDownloadingWallpaper: Flow<Boolean> = _isDownloadingWallpaper.asStateFlow()
+
+    val effectsStatus = effectsRepository.effectStatus
+    val effect = effectsRepository.wallpaperEffect
+
+    fun enableImageEffect(effect: EffectEnumInterface) {
+        effectsRepository.enableImageEffect(effect)
+    }
+
+    fun disableImageEffect() {
+        effectsRepository.disableImageEffect()
+    }
+
+    fun isTargetEffect(effect: EffectEnumInterface): Boolean {
+        return effectsRepository.isTargetEffect(effect)
+    }
+
+    fun getEffectTextRes(): WallpaperEffectsView2.EffectTextRes {
+        return effectsRepository.getEffectTextRes()
+    }
+
+    suspend fun downloadWallpaper(): LiveWallpaperDownloadResultModel? {
+        _isDownloadingWallpaper.value = true
+        val wallpaperModel = wallpaperPreviewRepository.downloadWallpaper()
+        _isDownloadingWallpaper.value = false
+        return wallpaperModel
     }
 }
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 31a3b1e..20da4f4 100644
--- a/src/com/android/wallpaper/picker/preview/domain/interactor/WallpaperPreviewInteractor.kt
+++ b/src/com/android/wallpaper/picker/preview/domain/interactor/WallpaperPreviewInteractor.kt
@@ -16,19 +16,66 @@
 
 package com.android.wallpaper.picker.preview.domain.interactor
 
-import com.android.wallpaper.model.wallpaper.WallpaperModel
+import android.app.WallpaperColors
+import android.graphics.Bitmap
+import android.graphics.Point
+import android.graphics.Rect
+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
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
 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.Flow
-import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.StateFlow
 
 @ActivityRetainedScoped
 class WallpaperPreviewInteractor
 @Inject
 constructor(
-    wallpaperPreviewRepository: WallpaperPreviewRepository,
+    private val wallpaperPreviewRepository: WallpaperPreviewRepository,
+    private val wallpaperRepository: WallpaperRepository,
 ) {
-    val wallpaperModel: Flow<WallpaperModel> =
-        wallpaperPreviewRepository.wallpaperModel.filterNotNull()
+    val wallpaperModel: StateFlow<WallpaperModel?> = wallpaperPreviewRepository.wallpaperModel
+
+    val hasTooltipBeenShown: StateFlow<Boolean> = wallpaperPreviewRepository.hasTooltipBeenShown
+    fun dismissTooltip() = wallpaperPreviewRepository.dismissTooltip()
+
+    suspend fun setStaticWallpaper(
+        @UserEventLogger.SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
+        destination: WallpaperDestination,
+        wallpaperModel: StaticWallpaperModel,
+        inputStream: InputStream?,
+        bitmap: Bitmap,
+        wallpaperSize: Point,
+        fullPreviewCropModels: Map<Point, FullPreviewCropModel>? = null,
+    ) {
+        wallpaperRepository.setStaticWallpaper(
+            setWallpaperEntryPoint,
+            destination,
+            wallpaperModel,
+            inputStream,
+            bitmap,
+            wallpaperSize,
+            fullPreviewCropModels,
+        )
+    }
+
+    suspend fun setLiveWallpaper(
+        @UserEventLogger.SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
+        destination: WallpaperDestination,
+        wallpaperModel: WallpaperModel.LiveWallpaperModel,
+    ) {
+        wallpaperRepository.setLiveWallpaper(
+            setWallpaperEntryPoint,
+            destination,
+            wallpaperModel,
+        )
+    }
+
+    suspend fun getWallpaperColors(bitmap: Bitmap, cropHints: Map<Point, Rect>?): WallpaperColors? =
+        wallpaperRepository.getWallpaperColors(bitmap, cropHints)
 }
diff --git a/src/com/android/wallpaper/picker/preview/shared/model/FullPreviewCropModel.kt b/src/com/android/wallpaper/picker/preview/shared/model/FullPreviewCropModel.kt
new file mode 100644
index 0000000..6e83b21
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/shared/model/FullPreviewCropModel.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.picker.preview.shared.model
+
+import android.graphics.Point
+import android.graphics.Rect
+
+/**
+ * Data class represents user's cropHint for a dimension.
+ *
+ * It could be one of below:
+ * 1. A current wallpaper crop.
+ * 2. User's crop via full preview.
+ * 3. Default crop from small preview.
+ *
+ * Only #2 will it contains [cropSizeModel], the other cases parallax (0 for #3) has already
+ * included in [cropHint].
+ */
+data class FullPreviewCropModel(
+    /** The user's crop of wallpaper based on the full wallpaper size. */
+    val cropHint: Rect,
+    /** The data required to compute parallax for this crop, null for no parallax. */
+    val cropSizeModel: CropSizeModel?,
+)
+
+/** Required for computing parallax. */
+data class CropSizeModel(
+    /** The zoom of the wallpaper on its hosting view when user selects the cropHint. */
+    val wallpaperZoom: Float,
+    /** 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,
+)
diff --git a/src/com/android/wallpaper/picker/preview/shared/model/LiveWallpaperDownloadResultModel.kt b/src/com/android/wallpaper/picker/preview/shared/model/LiveWallpaperDownloadResultModel.kt
new file mode 100644
index 0000000..1bf6fe5
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/shared/model/LiveWallpaperDownloadResultModel.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.shared.model
+
+import com.android.wallpaper.picker.data.WallpaperModel
+
+data class LiveWallpaperDownloadResultModel(
+    val code: LiveWallpaperDownloadResultCode,
+    val wallpaperModel: WallpaperModel.LiveWallpaperModel?
+)
+
+enum class LiveWallpaperDownloadResultCode {
+    SUCCESS,
+    FAIL,
+}
diff --git a/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt b/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
index c724b86..74e8eff 100644
--- a/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
@@ -18,46 +18,117 @@
 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.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
 import androidx.activity.viewModels
 import androidx.core.view.WindowCompat
+import androidx.lifecycle.lifecycleScope
+import androidx.navigation.fragment.NavHostFragment
 import com.android.wallpaper.R
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.WallpaperModel
 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.preview.data.repository.WallpaperPreviewRepository
+import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
+import com.android.wallpaper.picker.preview.ui.fragment.SmallPreviewFragment
+import com.android.wallpaper.picker.preview.ui.viewmodel.PreviewActionsViewModel.Companion.getEditActivityIntent
+import com.android.wallpaper.picker.preview.ui.viewmodel.PreviewActionsViewModel.Companion.isNewCreativeWallpaper
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.ActivityUtils
 import com.android.wallpaper.util.DisplayUtils
+import com.android.wallpaper.util.WallpaperConnection
 import com.android.wallpaper.util.converter.WallpaperModelFactory
+import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils
 import dagger.hilt.android.AndroidEntryPoint
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
 
 /** This activity holds the flow for the preview screen. */
 @AndroidEntryPoint(BasePreviewActivity::class)
 class WallpaperPreviewActivity :
     Hilt_WallpaperPreviewActivity(), AppbarFragment.AppbarFragmentHost {
-    private val viewModel: WallpaperPreviewViewModel by viewModels()
     @ApplicationContext @Inject lateinit var appContext: Context
     @Inject lateinit var displayUtils: DisplayUtils
     @Inject lateinit var wallpaperModelFactory: WallpaperModelFactory
     @Inject lateinit var wallpaperPreviewRepository: WallpaperPreviewRepository
+    @Inject lateinit var effectsRepository: EffectsRepository
+    @Inject lateinit var liveWallpaperDownloader: LiveWallpaperDownloader
+
+    private val wallpaperPreviewViewModel: WallpaperPreviewViewModel by viewModels()
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
+        enforcePortraitForHandheldAndFoldedDisplay()
         window.navigationBarColor = Color.TRANSPARENT
         window.statusBarColor = Color.TRANSPARENT
         setContentView(R.layout.activity_wallpaper_preview)
         // 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
+            else WallpaperConnection.WhichPreview.EDIT_CURRENT
+        wallpaperPreviewViewModel.setWhichPreview(whichPreview)
+        if (wallpaper is WallpaperModel.StaticWallpaperModel) {
+            wallpaper.staticWallpaperData.cropHints?.let {
+                wallpaperPreviewViewModel.setCropHints(it)
+            }
+        }
+        if (
+            (wallpaper as? WallpaperModel.StaticWallpaperModel)?.downloadableWallpaperData != null
+        ) {
+            liveWallpaperDownloader.initiateDownloadableService(
+                this,
+                wallpaper,
+                registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {}
+            )
+        }
+
+        if ((wallpaper as? WallpaperModel.StaticWallpaperModel)?.imageWallpaperData != null) {
+            lifecycleScope.launch {
+                effectsRepository.initializeEffect(
+                    staticWallpaperModel = wallpaper,
+                    onWallpaperModelUpdated = { wallpaper ->
+                        wallpaperPreviewRepository.setWallpaperModel(wallpaper)
+                    },
+                )
+            }
+        }
+
+        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() {
@@ -70,15 +141,26 @@
 
     override fun onResume() {
         super.onResume()
-        requestedOrientation =
-            if (displayUtils.isOnWallpaperDisplay(this)) ActivityInfo.SCREEN_ORIENTATION_USER
-            else ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
         if (isInMultiWindowMode) {
             Toast.makeText(this, R.string.wallpaper_exit_split_screen, Toast.LENGTH_SHORT).show()
             onBackPressedDispatcher.onBackPressed()
         }
     }
 
+    override fun onDestroy() {
+        liveWallpaperDownloader.cleanup()
+        (wallpaperPreviewViewModel.wallpaper.value as? WallpaperModel.LiveWallpaperModel)?.let {
+            runBlocking { WallpaperConnectionUtils.disconnect(applicationContext, it) }
+        }
+        effectsRepository.destroy()
+        super.onDestroy()
+    }
+
+    override fun onConfigurationChanged(newConfig: Configuration) {
+        super.onConfigurationChanged(newConfig)
+        enforcePortraitForHandheldAndFoldedDisplay()
+    }
+
     private fun WallpaperInfo.convertToWallpaperModel(): WallpaperModel {
         return wallpaperModelFactory.getWallpaperModel(appContext, this)
     }
@@ -96,16 +178,36 @@
         fun newIntent(
             context: Context,
             wallpaperInfo: WallpaperInfo,
+            isAssetIdPresent: Boolean,
+            isViewAsHome: Boolean = false,
             isNewTask: Boolean = false,
         ): Intent {
             val intent = Intent(context.applicationContext, WallpaperPreviewActivity::class.java)
             if (isNewTask) {
-                // TODO(b/291761856): When going back to main screen, use startActivity instead of
-                //                    onActivityResult, which won't work.
                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
             }
             intent.putExtra(EXTRA_WALLPAPER_INFO, wallpaperInfo)
+            intent.putExtra(IS_ASSET_ID_PRESENT, isAssetIdPresent)
+            intent.putExtra(EXTRA_VIEW_AS_HOME, isViewAsHome)
+            intent.putExtra(IS_NEW_TASK, isNewTask)
             return intent
         }
     }
+
+    /**
+     * If the display is a handheld display or a folded display from a foldable, we enforce the
+     * activity to be portrait.
+     *
+     * This method should be called upon initialization of this activity, and whenever there is a
+     * configuration change.
+     */
+    private fun enforcePortraitForHandheldAndFoldedDisplay() {
+        val wantedOrientation =
+            if (displayUtils.isLargeScreenOrUnfoldedDisplay(this))
+                ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+            else ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+        if (requestedOrientation != wantedOrientation) {
+            requestedOrientation = wantedOrientation
+        }
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/CropWallpaperButtonBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/CropWallpaperButtonBinder.kt
index 4013632..24cf141 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/CropWallpaperButtonBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/CropWallpaperButtonBinder.kt
@@ -32,10 +32,12 @@
     ) {
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
-                viewModel.onCropButtonClick.collect { onCropButtonClick ->
-                    button.setOnClickListener {
-                        onCropButtonClick.invoke()
-                        navigate.invoke()
+                launch {
+                    viewModel.onCropButtonClick.collect { onCropButtonClick ->
+                        button.setOnClickListener {
+                            onCropButtonClick?.invoke()
+                            navigate.invoke()
+                        }
                     }
                 }
             }
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 afe63ea..50f3062 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
@@ -21,7 +21,6 @@
 import com.android.wallpaper.R
 import com.android.wallpaper.model.wallpaper.FoldableDisplay
 import com.android.wallpaper.model.wallpaper.PreviewPagerPage
-import com.android.wallpaper.model.wallpaper.getScreenOrientation
 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
@@ -38,10 +37,18 @@
         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(
+                tooltipStub = view.requireViewById(R.id.tooltip_stub),
+                enableClickToDismiss = false,
+                viewModel = wallpaperPreviewViewModel,
+                lifecycleOwner = viewLifecycleOwner,
+            )
+
             val dualDisplayAspectRatioLayout: DualDisplayAspectRatioLayout =
                 view.requireViewById(R.id.dual_preview)
 
@@ -63,8 +70,9 @@
                         mainScope = mainScope,
                         viewLifecycleOwner = viewLifecycleOwner,
                         screen = PreviewPagerPage.entries[position].screen,
-                        orientation = getScreenOrientation(it, display),
+                        displaySize = it,
                         foldableDisplay = display,
+                        currentNavDestId = currentNavDestId,
                         navigate = navigate,
                     )
                 }
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 6d7c78d..a69f29d 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
@@ -36,6 +36,7 @@
         applicationContext: Context,
         viewLifecycleOwner: LifecycleOwner,
         mainScope: CoroutineScope,
+        currentNavDestId: Int,
         navigate: (View) -> Unit,
     ) {
         // set up tabs view pager
@@ -50,6 +51,7 @@
             applicationContext,
             viewLifecycleOwner,
             mainScope,
+            currentNavDestId,
             navigate,
         )
     }
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 b77ef97..f9179cd 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
@@ -16,7 +16,6 @@
 package com.android.wallpaper.picker.preview.ui.binder
 
 import android.content.Context
-import android.graphics.PointF
 import android.graphics.Rect
 import android.view.LayoutInflater
 import android.view.SurfaceHolder
@@ -28,18 +27,22 @@
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.wallpaper.R
-import com.android.wallpaper.model.wallpaper.WallpaperModel
 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.ui.util.FullResImageViewUtil.getCropRect
+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
 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.view.FullPreviewFrameLayout
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
+import com.android.wallpaper.util.WallpaperCropUtils
 import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils
 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
-import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.OnStateChangedListener
+import java.lang.Integer.min
+import kotlin.math.max
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
@@ -59,7 +62,7 @@
             view.requireViewById(R.id.wallpaper_preview_crop)
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
-                viewModel.fullWallpaper.collect { (_, config) ->
+                viewModel.fullWallpaper.collect { (_, config, _) ->
                     wallpaperPreviewCrop.setCurrentAndTargetDisplaySize(
                         displayUtils.getRealSize(checkNotNull(view.context.display)),
                         config.displaySize,
@@ -75,14 +78,25 @@
         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) ->
+                            viewModel.fullWallpaper.collect {
+                                (wallpaper, config, allowUserCropping, whichPreview) ->
                                 if (wallpaper is WallpaperModel.LiveWallpaperModel) {
                                     WallpaperConnectionUtils.connect(
                                         applicationContext,
                                         mainScope,
-                                        wallpaper.liveWallpaperData.systemWallpaperInfo,
+                                        wallpaper,
+                                        whichPreview,
                                         config.screen.toFlag(),
                                         surfaceView,
                                     )
@@ -91,17 +105,34 @@
                                         initStaticPreviewSurface(
                                             applicationContext,
                                             surfaceView,
-                                            surfaceTouchForwardingLayout,
-                                        ) { rect ->
+                                        ) { crop, zoom ->
                                             viewModel.staticWallpaperPreviewViewModel
-                                                .fullPreviewCrop = rect
+                                                .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.screenOrientation,
+                                        config.displaySize,
                                         lifecycleOwner,
                                     )
                                 }
@@ -111,6 +142,10 @@
 
                 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.
                 }
             }
         )
@@ -120,8 +155,7 @@
     private fun initStaticPreviewSurface(
         applicationContext: Context,
         surfaceView: SurfaceView,
-        surfaceTouchForwardingLayout: TouchForwardingLayout,
-        onNewCrop: (crop: Rect) -> Unit
+        onNewCrop: (crop: Rect, zoom: Float) -> Unit
     ): Pair<ImageView, SubsamplingScaleImageView> {
         val preview =
             LayoutInflater.from(applicationContext)
@@ -129,8 +163,7 @@
         surfaceView.attachView(preview)
         val fullResImageView =
             preview.requireViewById<SubsamplingScaleImageView>(R.id.full_res_image)
-        surfaceTouchForwardingLayout.initTouchForwarding(fullResImageView)
-        fullResImageView.setOnNewCropListener { onNewCrop.invoke(it) }
+        fullResImageView.setOnNewCropListener { crop, zoom -> onNewCrop.invoke(crop, zoom) }
         return Pair(preview.requireViewById(R.id.low_res_image), fullResImageView)
     }
 
@@ -138,18 +171,4 @@
         setForwardingEnabled(true)
         setTargetView(targetView)
     }
-
-    private fun SubsamplingScaleImageView.setOnNewCropListener(onNewCrop: (crop: Rect) -> Unit) {
-        setOnStateChangedListener(
-            object : OnStateChangedListener {
-                override fun onScaleChanged(p0: Float, p1: Int) {
-                    onNewCrop.invoke(getCropRect())
-                }
-
-                override fun onCenterChanged(p0: PointF?, p1: Int) {
-                    onNewCrop.invoke(getCropRect())
-                }
-            }
-        )
-    }
 }
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 a8553dc..d392c66 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt
@@ -16,6 +16,7 @@
 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
@@ -32,7 +33,9 @@
 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.DeleteConfirmationDialogViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.PreviewActionsViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
 import kotlinx.coroutines.launch
@@ -42,15 +45,20 @@
     fun bind(
         actionGroup: PreviewActionGroup,
         floatingSheet: PreviewActionFloatingSheet,
-        viewModel: PreviewActionsViewModel,
+        previewViewModel: WallpaperPreviewViewModel,
+        actionsViewModel: PreviewActionsViewModel,
+        displaySize: Point,
         lifecycleOwner: LifecycleOwner,
         logger: UserEventLogger,
+        onStartEditActivity: (intent: Intent) -> Unit,
+        onStartShareActivity: (intent: Intent) -> Unit,
+        onShowDeleteConfirmationDialog: (videModel: DeleteConfirmationDialogViewModel) -> Unit,
     ) {
         val floatingSheetCallback =
             object : BottomSheetBehavior.BottomSheetCallback() {
                 override fun onStateChanged(view: View, newState: Int) {
                     if (newState == STATE_HIDDEN) {
-                        viewModel.onDialogCollapsed()
+                        actionsViewModel.onFloatingSheetCollapsed()
                     }
                 }
 
@@ -66,94 +74,27 @@
 
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                /** [INFORMATION] */
                 launch {
-                    viewModel.isInformationChecked.collect {
-                        actionGroup.setIsChecked(INFORMATION, it)
-                    }
-                }
-
-                launch {
-                    viewModel.isInformationVisible.collect {
+                    actionsViewModel.isInformationVisible.collect {
                         actionGroup.setIsVisible(INFORMATION, it)
                     }
                 }
 
                 launch {
-                    viewModel.onInformationClicked.collect {
+                    actionsViewModel.isInformationChecked.collect {
+                        actionGroup.setIsChecked(INFORMATION, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.onInformationClicked.collect {
                         actionGroup.setClickListener(INFORMATION, it)
                     }
                 }
 
                 launch {
-                    viewModel.isDownloadChecked.collect { actionGroup.setIsChecked(DOWNLOAD, it) }
-                }
-
-                launch {
-                    viewModel.isDownloadVisible.collect { actionGroup.setIsVisible(DOWNLOAD, it) }
-                }
-
-                launch {
-                    viewModel.onDownloadClicked.collect {
-                        actionGroup.setClickListener(DOWNLOAD, it)
-                    }
-                }
-
-                launch {
-                    viewModel.isDeleteChecked.collect { actionGroup.setIsChecked(DELETE, it) }
-                }
-
-                launch {
-                    viewModel.isDeleteVisible.collect { actionGroup.setIsVisible(DELETE, it) }
-                }
-
-                launch {
-                    viewModel.onDeleteClicked.collect { actionGroup.setClickListener(DELETE, it) }
-                }
-
-                launch { viewModel.isEditChecked.collect { actionGroup.setIsChecked(EDIT, it) } }
-
-                launch { viewModel.isEditVisible.collect { actionGroup.setIsVisible(EDIT, it) } }
-
-                launch {
-                    viewModel.onEditClicked.collect { actionGroup.setClickListener(EDIT, it) }
-                }
-
-                launch {
-                    viewModel.isCustomizeChecked.collect { actionGroup.setIsChecked(CUSTOMIZE, it) }
-                }
-
-                launch {
-                    viewModel.isCustomizeVisible.collect { actionGroup.setIsVisible(CUSTOMIZE, it) }
-                }
-
-                launch {
-                    viewModel.onCustomizeClicked.collect {
-                        actionGroup.setClickListener(CUSTOMIZE, it)
-                    }
-                }
-
-                launch {
-                    viewModel.isEffectsChecked.collect { actionGroup.setIsChecked(EFFECTS, it) }
-                }
-
-                launch {
-                    viewModel.isEffectsVisible.collect { actionGroup.setIsVisible(EFFECTS, it) }
-                }
-
-                launch {
-                    viewModel.onEffectsClicked.collect { actionGroup.setClickListener(EFFECTS, it) }
-                }
-
-                launch { viewModel.isShareChecked.collect { actionGroup.setIsChecked(SHARE, it) } }
-
-                launch { viewModel.isShareVisible.collect { actionGroup.setIsVisible(SHARE, it) } }
-
-                launch {
-                    viewModel.onShareClicked.collect { actionGroup.setClickListener(SHARE, it) }
-                }
-
-                launch {
-                    viewModel.informationFloatingSheetViewModel.collect { viewModel ->
+                    actionsViewModel.informationFloatingSheetViewModel.collect { viewModel ->
                         if (viewModel == null) {
                             floatingSheet.collapse()
                         } else {
@@ -175,6 +116,162 @@
                         }
                     }
                 }
+
+                /** [DOWNLOAD] */
+                launch {
+                    actionsViewModel.isDownloadVisible.collect {
+                        actionGroup.setIsVisible(DOWNLOAD, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.isDownloading.collect { actionGroup.setIsDownloading(it) }
+                }
+
+                launch {
+                    actionsViewModel.isDownloadButtonEnabled.collect {
+                        actionGroup.setClickListener(
+                            DOWNLOAD,
+                            if (it) {
+                                {
+                                    lifecycleOwner.lifecycleScope.launch {
+                                        actionsViewModel.downloadWallpaper()
+                                    }
+                                }
+                            } else null,
+                        )
+                    }
+                }
+
+                /** [DELETE] */
+                launch {
+                    actionsViewModel.isDeleteVisible.collect {
+                        actionGroup.setIsVisible(DELETE, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.isDeleteChecked.collect {
+                        actionGroup.setIsChecked(DELETE, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.onDeleteClicked.collect {
+                        actionGroup.setClickListener(DELETE, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.deleteConfirmationDialogViewModel.collect { viewModel ->
+                        if (viewModel != null) {
+                            onShowDeleteConfirmationDialog.invoke(viewModel)
+                        }
+                    }
+                }
+
+                /** [EDIT] */
+                launch {
+                    actionsViewModel.isEditVisible.collect { actionGroup.setIsVisible(EDIT, it) }
+                }
+
+                launch {
+                    actionsViewModel.isEditChecked.collect { actionGroup.setIsChecked(EDIT, it) }
+                }
+
+                launch {
+                    actionsViewModel.editIntent.collect {
+                        actionGroup.setClickListener(
+                            EDIT,
+                            if (it != null) {
+                                {
+                                    // We need to set default wallpaper preview config view model
+                                    // before entering full screen with edit activity overlay.
+                                    previewViewModel.setDefaultWallpaperPreviewConfigViewModel(
+                                        displaySize
+                                    )
+                                    onStartEditActivity.invoke(it)
+                                }
+                            } else null
+                        )
+                    }
+                }
+
+                /** [CUSTOMIZE] */
+                launch {
+                    actionsViewModel.isCustomizeVisible.collect {
+                        actionGroup.setIsVisible(CUSTOMIZE, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.isCustomizeChecked.collect {
+                        actionGroup.setIsChecked(CUSTOMIZE, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.onCustomizeClicked.collect {
+                        actionGroup.setClickListener(CUSTOMIZE, it)
+                    }
+                }
+
+                /** [EFFECTS] */
+                launch {
+                    actionsViewModel.isEffectsVisible.collect {
+                        actionGroup.setIsVisible(EFFECTS, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.isEffectsChecked.collect {
+                        actionGroup.setIsChecked(EFFECTS, it)
+                    }
+                }
+
+                launch {
+                    actionsViewModel.onEffectsClicked.collect {
+                        actionGroup.setClickListener(EFFECTS, it)
+                    }
+                }
+
+                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) }
+                }
+
+                launch {
+                    actionsViewModel.shareIntent.collect {
+                        actionGroup.setClickListener(
+                            SHARE,
+                            if (it != null) {
+                                { onStartShareActivity.invoke(it) }
+                            } else null
+                        )
+                    }
+                }
             }
         }
     }
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 014fc9a..2e0bf54 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
@@ -20,10 +20,10 @@
 import android.graphics.Point
 import android.view.View
 import androidx.lifecycle.LifecycleOwner
+import androidx.recyclerview.widget.RecyclerView
 import androidx.viewpager2.widget.ViewPager2
 import com.android.wallpaper.R
 import com.android.wallpaper.model.wallpaper.PreviewPagerPage
-import com.android.wallpaper.model.wallpaper.getScreenOrientation
 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
@@ -40,19 +40,28 @@
         previewsViewPager: ViewPager2,
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         previewDisplaySize: Point,
+        currentNavDestId: Int,
         navigate: (View) -> Unit,
     ) {
         previewsViewPager.apply {
             adapter = SinglePreviewPagerAdapter { viewHolder, position ->
+                PreviewTooltipBinder.bind(
+                    tooltipStub = viewHolder.itemView.requireViewById(R.id.tooltip_stub),
+                    enableClickToDismiss = false,
+                    viewModel = wallpaperPreviewViewModel,
+                    lifecycleOwner = viewLifecycleOwner,
+                )
+
                 SmallPreviewBinder.bind(
                     applicationContext = applicationContext,
                     view = viewHolder.itemView.requireViewById(R.id.preview),
                     viewModel = wallpaperPreviewViewModel,
                     screen = PreviewPagerPage.entries[position].screen,
-                    orientation = getScreenOrientation(previewDisplaySize),
+                    displaySize = previewDisplaySize,
                     foldableDisplay = null,
                     mainScope = mainScope,
                     viewLifecycleOwner = viewLifecycleOwner,
+                    currentNavDestId = currentNavDestId,
                     navigate = navigate,
                 )
             }
@@ -61,5 +70,12 @@
             clipToPadding = false
             setPageTransformer(PreviewCardPageTransformer(previewDisplaySize))
         }
+
+        // the over scroll animation needs to be disabled for the RecyclerView that is contained in
+        // the ViewPager2 rather than the ViewPager2 itself
+        val child: View = previewsViewPager.getChildAt(0)
+        if (child is RecyclerView) {
+            child.overScrollMode = View.OVER_SCROLL_NEVER
+        }
     }
 }
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 4b58289..4747e0b 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
@@ -35,6 +35,7 @@
         applicationContext: Context,
         viewLifecycleOwner: LifecycleOwner,
         mainScope: CoroutineScope,
+        currentNavDestId: Int,
         navigate: (View) -> Unit,
     ) {
         // set up tabs view pager
@@ -48,6 +49,7 @@
             previewsViewPager,
             wallpaperPreviewViewModel,
             previewDisplaySize,
+            currentNavDestId,
             navigate,
         )
 
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewTooltipBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewTooltipBinder.kt
new file mode 100644
index 0000000..d116fd5
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewTooltipBinder.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 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.view.View
+import android.view.ViewStub
+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.launch
+
+object PreviewTooltipBinder {
+    fun bind(
+        tooltipStub: ViewStub,
+        enableClickToDismiss: Boolean,
+        viewModel: WallpaperPreviewViewModel,
+        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()
+                            if (enableClickToDismiss) {
+                                tooltip?.setOnClickListener { viewModel.dismissTooltip() }
+                            }
+                        }
+                        // TODO (b/303318205): animate tooltip
+                        // Only show tooltip if it has not been shown before.
+                        tooltip?.isVisible = shouldShowTooltip
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperButtonBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperButtonBinder.kt
index 013ff3a..8965760 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperButtonBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperButtonBinder.kt
@@ -17,14 +17,47 @@
 package com.android.wallpaper.picker.preview.ui.binder
 
 import android.widget.Button
+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.launch
 
 /** Binds the set wallpaper button on small preview. */
 object SetWallpaperButtonBinder {
 
     fun bind(
         button: Button,
+        viewModel: WallpaperPreviewViewModel,
+        lifecycleOwner: LifecycleOwner,
         navigate: () -> Unit,
     ) {
-        button.setOnClickListener { navigate.invoke() }
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                launch { viewModel.isSetWallpaperButtonVisible.collect { button.isVisible = it } }
+
+                launch {
+                    viewModel.onSetWallpaperButtonClicked.collect { onClicked ->
+                        button.setOnClickListener(
+                            if (onClicked != null) {
+                                { onClicked.invoke() }
+                            } else {
+                                null
+                            }
+                        )
+                    }
+                }
+
+                launch {
+                    viewModel.showSetWallpaperDialog.collect {
+                        if (it) {
+                            navigate.invoke()
+                        }
+                    }
+                }
+            }
+        }
     }
 }
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 0bac034..6e35021 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperDialogBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperDialogBinder.kt
@@ -16,22 +16,188 @@
 
 package com.android.wallpaper.picker.preview.ui.binder
 
-import android.app.AlertDialog
-import android.app.Dialog
+import android.graphics.Point
+import android.view.View
+import android.widget.Button
+import android.widget.FrameLayout
+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.R
+import com.android.wallpaper.model.wallpaper.FoldableDisplay
+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
+import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 /** Binds the dialog on small preview confirming and setting wallpaper with destination. */
 object SetWallpaperDialogBinder {
+    private val PreviewScreenIds =
+        mapOf(
+            Screen.LOCK_SCREEN to R.id.lock_preview_selector,
+            Screen.HOME_SCREEN to R.id.home_preview_selector
+        )
 
     fun bind(
-        dialog: AlertDialog,
-        primaryText: String,
-        secondaryText: String,
-        navigate: () -> Unit,
+        dialogContent: View,
+        wallpaperPreviewViewModel: WallpaperPreviewViewModel,
+        isFoldable: Boolean,
+        handheldDisplaySize: Point,
+        lifecycleOwner: LifecycleOwner,
+        mainScope: CoroutineScope,
+        currentNavDestId: Int,
+        onFinishActivity: () -> Unit,
+        onDismissDialog: () -> Unit,
+        navigate: ((View) -> Unit)?,
     ) {
-        // TODO(b/303457019): For the set button, listen to a data flow of onClick listener
-        dialog.apply {
-            setButton(Dialog.BUTTON_POSITIVE, primaryText) { _, _ -> navigate.invoke() }
-            setButton(Dialog.BUTTON_NEGATIVE, secondaryText) { _, _ -> navigate.invoke() }
+        val previewLayout: View =
+            if (isFoldable) dialogContent.requireViewById(R.id.foldable_previews)
+            else dialogContent.requireViewById(R.id.handheld_previews)
+        if (isFoldable)
+            bindFoldablePreview(
+                previewLayout,
+                wallpaperPreviewViewModel,
+                lifecycleOwner,
+                mainScope,
+                currentNavDestId,
+                navigate,
+            )
+        else
+            bindHandheldPreview(
+                previewLayout,
+                wallpaperPreviewViewModel,
+                handheldDisplaySize,
+                lifecycleOwner,
+                mainScope,
+                currentNavDestId,
+                navigate,
+            )
+
+        val cancelButton = dialogContent.requireViewById<Button>(R.id.button_cancel)
+        cancelButton.setOnClickListener { onDismissDialog() }
+
+        val confirmButton = dialogContent.requireViewById<Button>(R.id.button_set)
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                launch {
+                    wallpaperPreviewViewModel.showSetWallpaperDialog.collect { show ->
+                        if (!show) {
+                            onDismissDialog()
+                        }
+                    }
+                }
+
+                launch {
+                    wallpaperPreviewViewModel.setWallpaperDialogOnConfirmButtonClicked.collect {
+                        onClicked ->
+                        confirmButton.setOnClickListener {
+                            mainScope.launch {
+                                onClicked()
+                                onFinishActivity()
+                            }
+                        }
+                    }
+                }
+
+                launch {
+                    wallpaperPreviewViewModel.setWallpaperDialogSelectedScreens.collect {
+                        selectedScreens ->
+                        confirmButton.isEnabled = selectedScreens.isNotEmpty()
+                        PreviewScreenIds.forEach { screenId ->
+                            bindPreviewSelector(
+                                previewLayout.requireViewById(screenId.value),
+                                screenId.key,
+                                selectedScreens,
+                                wallpaperPreviewViewModel,
+                            )
+                        }
+                    }
+                }
+            }
         }
     }
+
+    private fun bindFoldablePreview(
+        previewLayout: View,
+        wallpaperPreviewViewModel: WallpaperPreviewViewModel,
+        lifecycleOwner: LifecycleOwner,
+        mainScope: CoroutineScope,
+        currentNavDestId: Int,
+        navigate: ((View) -> Unit)?,
+    ) {
+        previewLayout.isVisible = true
+        PreviewScreenIds.forEach { screenId ->
+            val dualDisplayAspectRatioLayout: DualDisplayAspectRatioLayout =
+                previewLayout
+                    .requireViewById<FrameLayout>(screenId.value)
+                    .requireViewById(R.id.dual_preview)
+
+            dualDisplayAspectRatioLayout.setDisplaySizes(
+                mapOf(
+                    FoldableDisplay.FOLDED to wallpaperPreviewViewModel.smallerDisplaySize,
+                    FoldableDisplay.UNFOLDED to wallpaperPreviewViewModel.wallpaperDisplaySize,
+                )
+            )
+            FoldableDisplay.entries.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,
+                        currentNavDestId = currentNavDestId,
+                        navigate = navigate,
+                    )
+                }
+            }
+        }
+    }
+
+    private fun bindHandheldPreview(
+        previewLayout: View,
+        wallpaperPreviewViewModel: WallpaperPreviewViewModel,
+        displaySize: Point,
+        lifecycleOwner: LifecycleOwner,
+        mainScope: CoroutineScope,
+        currentNavDestId: Int,
+        navigate: ((View) -> Unit)?,
+    ) {
+        previewLayout.isVisible = true
+        PreviewScreenIds.forEach { screenId ->
+            SmallPreviewBinder.bind(
+                applicationContext = previewLayout.context.applicationContext,
+                view =
+                    previewLayout
+                        .requireViewById<FrameLayout>(screenId.value)
+                        .requireViewById(R.id.preview),
+                viewModel = wallpaperPreviewViewModel,
+                screen = screenId.key,
+                displaySize = displaySize,
+                foldableDisplay = null,
+                mainScope = mainScope,
+                viewLifecycleOwner = lifecycleOwner,
+                currentNavDestId = currentNavDestId,
+                navigate = navigate,
+            )
+        }
+    }
+
+    private fun bindPreviewSelector(
+        selector: View,
+        screen: Screen,
+        selectedScreens: Set<Screen>,
+        dialogViewModel: WallpaperPreviewViewModel,
+    ) {
+        selector.isActivated = selectedScreens.contains(screen)
+        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
new file mode 100644
index 0000000..4d97fb2
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SetWallpaperProgressDialogBinder.kt
@@ -0,0 +1,45 @@
+/*
+ * 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.app.ProgressDialog
+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.launch
+
+/** Binds the set wallpaper progress dialog. */
+object SetWallpaperProgressDialogBinder {
+
+    fun bind(
+        dialog: ProgressDialog,
+        viewModel: WallpaperPreviewViewModel,
+        lifecycleOwner: LifecycleOwner,
+    ) {
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                launch {
+                    viewModel.isSetWallpaperProgressBarVisible.collect {
+                        if (it) dialog.show() else dialog.hide()
+                    }
+                }
+            }
+        }
+    }
+}
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 d3a63ad..36f4d57 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
@@ -16,12 +16,13 @@
 package com.android.wallpaper.picker.preview.ui.binder
 
 import android.content.Context
+import android.graphics.Point
 import android.view.SurfaceView
 import android.view.View
+import androidx.cardview.widget.CardView
 import androidx.lifecycle.LifecycleOwner
 import com.android.wallpaper.R
 import com.android.wallpaper.model.wallpaper.FoldableDisplay
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
 import com.android.wallpaper.module.CustomizationSections.Screen
 import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
@@ -34,31 +35,42 @@
         view: View,
         viewModel: WallpaperPreviewViewModel,
         screen: Screen,
-        orientation: ScreenOrientation,
+        displaySize: Point,
         foldableDisplay: FoldableDisplay?,
         @MainDispatcher mainScope: CoroutineScope,
         viewLifecycleOwner: LifecycleOwner,
+        currentNavDestId: Int,
         navigate: ((View) -> Unit)? = null,
     ) {
+        val previewCard: CardView = view.requireViewById(R.id.preview_card)
         val wallpaperSurface: SurfaceView = view.requireViewById(R.id.wallpaper_surface)
         val workspaceSurface: SurfaceView = view.requireViewById(R.id.workspace_surface)
 
-        view.setOnClickListener {
-            viewModel.onSmallPreviewClicked(screen, orientation, foldableDisplay)
-            navigate?.invoke(wallpaperSurface)
+        if (R.id.smallPreviewFragment == currentNavDestId) {
+            view.setOnClickListener {
+                viewModel.onSmallPreviewClicked(screen, foldableDisplay)
+                navigate?.invoke(previewCard)
+            }
+        } 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)
         WorkspacePreviewBinder.bind(
             workspaceSurface,
             config,
+            viewModel,
+            viewLifecycleOwner,
         )
 
         SmallWallpaperPreviewBinder.bind(
             surface = wallpaperSurface,
             viewModel = viewModel,
             screen = screen,
-            screenOrientation = orientation,
+            displaySize = displaySize,
             applicationContext = applicationContext,
             mainScope = mainScope,
             viewLifecycleOwner = viewLifecycleOwner,
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 d6a70fa..0453495 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
@@ -15,21 +15,24 @@
  */
 package com.android.wallpaper.picker.preview.ui.binder
 
+import android.app.WallpaperColors
 import android.content.Context
+import android.graphics.Point
 import android.view.LayoutInflater
 import android.view.SurfaceHolder
 import android.view.SurfaceView
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import com.android.wallpaper.R
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel
 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.WallpaperEngineConnection.WallpaperEngineConnectionListener
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
@@ -48,7 +51,7 @@
         surface: SurfaceView,
         viewModel: WallpaperPreviewViewModel,
         screen: Screen,
-        screenOrientation: ScreenOrientation,
+        displaySize: Point,
         applicationContext: Context,
         @MainDispatcher mainScope: CoroutineScope,
         viewLifecycleOwner: LifecycleOwner,
@@ -60,14 +63,25 @@
                 override fun surfaceCreated(holder: SurfaceHolder) {
                     job =
                         viewLifecycleOwner.lifecycleScope.launch {
-                            viewModel.wallpaper.collect { wallpaper ->
+                            viewModel.smallWallpaper.collect { (wallpaper, whichPreview) ->
                                 if (wallpaper is WallpaperModel.LiveWallpaperModel) {
                                     WallpaperConnectionUtils.connect(
                                         applicationContext,
                                         mainScope,
-                                        wallpaper.liveWallpaperData.systemWallpaperInfo,
+                                        wallpaper,
+                                        whichPreview,
                                         screen.toFlag(),
                                         surface,
+                                        object : WallpaperEngineConnectionListener {
+                                            override fun onWallpaperColorsChanged(
+                                                colors: WallpaperColors?,
+                                                displayId: Int
+                                            ) {
+                                                viewModel.setWallpaperConnectionColors(
+                                                    WallpaperColorsModel.Loaded(colors)
+                                                )
+                                            }
+                                        }
                                     )
                                 } else if (wallpaper is WallpaperModel.StaticWallpaperModel) {
                                     val staticPreviewView =
@@ -76,11 +90,19 @@
                                     surface.attachView(staticPreviewView)
                                     // Bind static wallpaper
                                     StaticWallpaperPreviewBinder.bind(
-                                        staticPreviewView.requireViewById(R.id.low_res_image),
-                                        staticPreviewView.requireViewById(R.id.full_res_image),
-                                        viewModel.staticWallpaperPreviewViewModel,
-                                        screenOrientation,
-                                        viewLifecycleOwner,
+                                        lowResImageView =
+                                            staticPreviewView.requireViewById(R.id.low_res_image),
+                                        fullResImageView =
+                                            staticPreviewView.requireViewById(R.id.full_res_image),
+                                        viewModel = viewModel.staticWallpaperPreviewViewModel,
+                                        displaySize = displaySize,
+                                        viewLifecycleOwner = viewLifecycleOwner,
+                                        shouldCalibrateWithSystemScale = true,
+                                    )
+                                    // This is to possibly shut down all live wallpaper services
+                                    // if they exist; otherwise static wallpaper can not show up.
+                                    WallpaperConnectionUtils.disconnectAllServices(
+                                        applicationContext
                                     )
                                 }
                             }
@@ -89,6 +111,10 @@
 
                 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.
                 }
             }
         )
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 cf5ff63..c481ea7 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
@@ -17,7 +17,6 @@
 
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
-import android.graphics.Bitmap
 import android.graphics.Point
 import android.graphics.Rect
 import android.graphics.RenderEffect
@@ -30,10 +29,12 @@
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
+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.util.FullResImageViewUtil.getCropRect
+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
 import com.android.wallpaper.util.WallpaperSurfaceCallback.LOW_RES_BITMAP_BLUR_RADIUS
 import com.davemorrissey.labs.subscaleview.ImageSource
 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
@@ -48,8 +49,9 @@
         lowResImageView: ImageView,
         fullResImageView: SubsamplingScaleImageView,
         viewModel: StaticWallpaperPreviewViewModel,
-        screenOrientation: ScreenOrientation,
+        displaySize: Point,
         viewLifecycleOwner: LifecycleOwner,
+        shouldCalibrateWithSystemScale: Boolean = false,
     ) {
         lowResImageView.initLowResImageView()
         fullResImageView.initFullResImageView()
@@ -59,18 +61,34 @@
                 launch { viewModel.lowResBitmap.collect { lowResImageView.setImageBitmap(it) } }
 
                 launch {
-                    viewModel.subsamplingScaleImageViewModel.collect {
-                        val cropHint = it.cropHints?.get(screenOrientation)
+                    viewModel.subsamplingScaleImageViewModel.collect { imageModel ->
+                        val cropHint = imageModel.fullPreviewCropModels?.get(displaySize)?.cropHint
                         fullResImageView.setFullResImage(
-                            it.rawWallpaperBitmap,
-                            it.rawWallpaperSize,
+                            ImageSource.cachedBitmap(imageModel.rawWallpaperBitmap),
+                            imageModel.rawWallpaperSize,
+                            displaySize,
                             cropHint,
+                            RtlUtils.isRtl(lowResImageView.context),
+                            shouldCalibrateWithSystemScale,
                         )
 
-                        // Both small and full previews change fullPreviewCrop but it should track
-                        // only full preview crop, initial value should align with existing crop
-                        // otherwise it's a new preview selection and use current visible crop
-                        viewModel.fullPreviewCrop = cropHint ?: fullResImageView.getCropRect()
+                        // Fill in the default crop region if the displaySize for this preview is
+                        // missing.
+                        viewModel.fullPreviewCropModels.putIfAbsent(
+                            displaySize,
+                            FullPreviewCropModel(
+                                cropHint =
+                                    WallpaperCropUtils.calculateVisibleRect(
+                                        imageModel.rawWallpaperSize,
+                                        Point(
+                                            fullResImageView.measuredWidth,
+                                            fullResImageView.measuredHeight
+                                        )
+                                    ),
+                                cropSizeModel = null,
+                            )
+                        )
+
                         crossFadeInFullResImageView(lowResImageView, fullResImageView)
                     }
                 }
@@ -93,23 +111,41 @@
         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(
-        rawWallpaperBitmap: Bitmap,
+        imageSource: ImageSource,
         rawWallpaperSize: Point,
+        displaySize: Point,
         cropHint: Rect?,
+        isRtl: Boolean,
+        shouldCalibrateWithSystemScale: Boolean = false,
     ) {
         // Set the full res image
-        setImage(ImageSource.bitmap(rawWallpaperBitmap))
+        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
-                setScaleAndCenter(scaleAndCenter.defaultScale, scaleAndCenter.center)
+                val scale =
+                    if (shouldCalibrateWithSystemScale)
+                        WallpaperCropUtils.getSystemWallpaperMaximumScale(
+                            context.applicationContext
+                        )
+                    else 1F
+                setScaleAndCenter(scaleAndCenter.defaultScale * scale, scaleAndCenter.center)
             }
     }
 
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/TabPagerBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/TabPagerBinder.kt
index e23b12e..77cd828 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/TabPagerBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/TabPagerBinder.kt
@@ -18,6 +18,7 @@
 import android.view.View.OVER_SCROLL_NEVER
 import androidx.viewpager.widget.ViewPager
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.TabTextPagerAdapter
+import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.pagetransformers.PreviewSelectedTabTransformer
 
 /** Binds single preview home screen and lock screen tabs. */
 object TabPagerBinder {
@@ -31,6 +32,7 @@
             clipChildren = false
             clipToPadding = false
             overScrollMode = OVER_SCROLL_NEVER
+            setPageTransformer(false, PreviewSelectedTabTransformer())
         }
     }
 }
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 7f7e83f..b629d5b 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/WorkspacePreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/WorkspacePreviewBinder.kt
@@ -15,35 +15,46 @@
  */
 package com.android.wallpaper.picker.preview.ui.binder
 
+import android.app.WallpaperColors
 import android.os.Bundle
+import android.util.Log
 import android.view.SurfaceHolder
 import android.view.SurfaceView
-import android.view.View
 import androidx.core.os.bundleOf
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
+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 kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
 
 object WorkspacePreviewBinder {
     fun bind(
         surface: SurfaceView,
         config: WorkspacePreviewConfigViewModel,
+        viewModel: WallpaperPreviewViewModel,
+        lifecycleOwner: LifecycleOwner,
     ) {
-        surface.visibility = View.VISIBLE
         surface.setZOrderMediaOverlay(true)
         surface.holder.addCallback(
             object : SurfaceViewUtil.SurfaceCallback {
                 override fun surfaceCreated(holder: SurfaceHolder) {
-                    renderWorkspacePreview(
-                        surface = surface,
-                        previewUtils = config.previewUtils,
-                        displayId = config.displayId,
-                    )
+                    lifecycleOwner.lifecycleScope.launch {
+                        viewModel.wallpaperColorsModel.collect {
+                            if (it is WallpaperColorsModel.Loaded) {
+                                renderWorkspacePreview(
+                                    surface = surface,
+                                    previewUtils = config.previewUtils,
+                                    displayId = config.displayId,
+                                    wallpaperColors = it.colors
+                                )
+                            }
+                        }
+                    }
                 }
             }
         )
@@ -56,21 +67,29 @@
     fun bindFullWorkspacePreview(
         surface: SurfaceView,
         viewModel: WallpaperPreviewViewModel,
-        lifecycleOwner: LifecycleOwner
+        lifecycleOwner: LifecycleOwner,
     ) {
-        surface.visibility = View.VISIBLE
         surface.setZOrderMediaOverlay(true)
         surface.holder.addCallback(
             object : SurfaceViewUtil.SurfaceCallback {
                 override fun surfaceCreated(holder: SurfaceHolder) {
                     lifecycleOwner.lifecycleScope.launch {
-                        viewModel.fullWorkspacePreviewConfigViewModel.collect {
-                            renderWorkspacePreview(
-                                surface = surface,
-                                previewUtils = it.previewUtils,
-                                displayId = it.displayId,
-                            )
-                        }
+                        combine(
+                                viewModel.fullWorkspacePreviewConfigViewModel,
+                                viewModel.wallpaperColorsModel
+                            ) { config, colorsModel ->
+                                config to colorsModel
+                            }
+                            .collect { (config, colorsModel) ->
+                                if (colorsModel is WallpaperColorsModel.Loaded) {
+                                    renderWorkspacePreview(
+                                        surface = surface,
+                                        previewUtils = config.previewUtils,
+                                        displayId = config.displayId,
+                                        wallpaperColors = colorsModel.colors
+                                    )
+                                }
+                            }
                     }
                 }
             }
@@ -81,25 +100,42 @@
         surface: SurfaceView,
         previewUtils: PreviewUtils,
         displayId: Int,
+        wallpaperColors: WallpaperColors? = null,
     ) {
         if (previewUtils.supportsPreview()) {
+            val extras = bundleOf(Pair(SurfaceViewUtils.KEY_DISPLAY_ID, displayId))
+            wallpaperColors?.let {
+                extras.putParcelable(SurfaceViewUtils.KEY_WALLPAPER_COLORS, wallpaperColors)
+            }
             val request =
                 SurfaceViewUtils.createSurfaceViewRequest(
                     surface,
-                    bundleOf(Pair(SurfaceViewUtils.KEY_DISPLAY_ID, displayId)),
+                    extras,
                 )
             previewUtils.renderPreview(
                 request,
                 object : PreviewUtils.WorkspacePreviewCallback {
                     override fun onPreviewRendered(resultBundle: Bundle?) {
                         if (resultBundle != null) {
-                            surface.setChildSurfacePackage(
-                                SurfaceViewUtils.getSurfacePackage(resultBundle)
-                            )
+                            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."
+                                    )
+                                }
+                            }
+                        } else {
+                            Log.w(TAG, "Result bundle from rendering preview is null.")
                         }
                     }
                 }
             )
         }
     }
+
+    const val TAG = "WorkspacePreviewBinder"
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeNewPreviewFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeNewPreviewFragment.kt
new file mode 100644
index 0000000..e4f7491
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/CreativeNewPreviewFragment.kt
@@ -0,0 +1,113 @@
+/*
+ * 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 4092fed..1a34086 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
@@ -16,13 +16,19 @@
 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
@@ -31,7 +37,9 @@
 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.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
 import dagger.hilt.android.AndroidEntryPoint
@@ -65,8 +73,37 @@
         val view = inflater.inflate(R.layout.fragment_full_preview, container, false)
         setUpToolbar(view)
 
-        val wallpaperSurface: SurfaceView = view.requireViewById(R.id.wallpaper_surface)
-        ViewCompat.setTransitionName(wallpaperSurface, "full_preview_shared_element")
+        val previewCard: CardView = view.requireViewById(R.id.preview_card)
+        ViewCompat.setTransitionName(
+            previewCard,
+            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,
@@ -91,6 +128,13 @@
             lifecycleOwner = viewLifecycleOwner,
         )
 
+        PreviewTooltipBinder.bind(
+            tooltipStub = view.requireViewById(R.id.tooltip_stub),
+            enableClickToDismiss = true,
+            viewModel = wallpaperPreviewViewModel,
+            lifecycleOwner = viewLifecycleOwner,
+        )
+
         return view
     }
 
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 10e9fa4..24ceaf4 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/SetWallpaperDialogFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/SetWallpaperDialogFragment.kt
@@ -16,25 +16,37 @@
 
 package com.android.wallpaper.picker.preview.ui.fragment
 
+import android.app.Activity
 import android.app.AlertDialog
 import android.app.Dialog
+import android.content.DialogInterface
+import android.content.Intent
 import android.os.Bundle
 import android.view.LayoutInflater
+import android.widget.Toast
 import androidx.fragment.app.DialogFragment
 import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.findNavController
 import com.android.wallpaper.R
+import com.android.wallpaper.picker.TrampolinePickerActivity
+import com.android.wallpaper.picker.di.modules.MainDispatcher
+import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity
 import com.android.wallpaper.picker.preview.ui.binder.SetWallpaperDialogBinder
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
+import com.android.wallpaper.util.LaunchSourceUtils.LAUNCH_SOURCE_LAUNCHER
+import com.android.wallpaper.util.LaunchSourceUtils.LAUNCH_SOURCE_SETTINGS_HOMEPAGE
+import com.android.wallpaper.util.LaunchSourceUtils.WALLPAPER_LAUNCH_SOURCE
 import dagger.hilt.android.AndroidEntryPoint
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
 
 /** Shows LS/HS previews and confirmation to set as wallpaper for HS, LS or both. */
 @AndroidEntryPoint(DialogFragment::class)
 class SetWallpaperDialogFragment : Hilt_SetWallpaperDialogFragment() {
 
     @Inject lateinit var displayUtils: DisplayUtils
+    @Inject @MainDispatcher lateinit var mainScope: CoroutineScope
 
     private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
 
@@ -47,14 +59,55 @@
             AlertDialog.Builder(requireContext(), R.style.SetWallpaperPreviewDialogTheme)
                 .setView(layout)
                 .create()
+
+        /**
+         * We need to keep the reference shortly, because the activity will be forced to restart due
+         * to the theme color update from the system wallpaper change. The activityReference is used
+         * to kill [WallpaperPreviewActivity].
+         */
+        val activityReference = activity
         SetWallpaperDialogBinder.bind(
-            dialog,
-            "Set",
-            "Cancel",
-        ) {
-            findNavController().popBackStack()
-        }
+            layout,
+            wallpaperPreviewViewModel,
+            displayUtils.hasMultiInternalDisplays(),
+            displayUtils.getRealSize(displayUtils.getWallpaperDisplay()),
+            lifecycleOwner = this,
+            mainScope,
+            checkNotNull(findNavController().currentDestination?.id),
+            onFinishActivity = {
+                Toast.makeText(
+                        context,
+                        R.string.wallpaper_set_successfully_message,
+                        Toast.LENGTH_SHORT
+                    )
+                    .show()
+                if (activityReference != null) {
+                    if (wallpaperPreviewViewModel.isNewTask) {
+                        val intent = Intent(activityReference, TrampolinePickerActivity::class.java)
+                        intent.setFlags(
+                            Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
+                        )
+                        intent.putExtra(
+                            WALLPAPER_LAUNCH_SOURCE,
+                            if (wallpaperPreviewViewModel.isViewAsHome) LAUNCH_SOURCE_LAUNCHER
+                            else LAUNCH_SOURCE_SETTINGS_HOMEPAGE
+                        )
+                        activityReference.startActivity(intent)
+                    } else {
+                        activityReference.setResult(Activity.RESULT_OK)
+                        activityReference.finish()
+                    }
+                }
+            },
+            onDismissDialog = { findNavController().popBackStack() },
+            navigate = null,
+        )
 
         return dialog
     }
+
+    override fun onDismiss(dialog: DialogInterface) {
+        super.onDismiss(dialog)
+        wallpaperPreviewViewModel.dismissSetWallpaperDialog()
+    }
 }
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 31a4635..d0ec9e5 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
@@ -15,11 +15,15 @@
  */
 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
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.activity.result.contract.ActivityResultContract
 import androidx.core.content.ContextCompat
 import androidx.core.view.ViewCompat
 import androidx.fragment.app.activityViewModels
@@ -33,8 +37,11 @@
 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.views.TabsPagerContainer
+import com.android.wallpaper.picker.preview.ui.view.PreviewActionGroup
+import com.android.wallpaper.picker.preview.ui.viewmodel.Action
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
 import dagger.hilt.android.AndroidEntryPoint
@@ -55,6 +62,7 @@
     @Inject lateinit var logger: UserEventLogger
 
     private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
+    private lateinit var setWallpaperProgressDialog: ProgressDialog
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -71,12 +79,26 @@
             )
         setUpToolbar(view)
         bindScreenPreview(view)
+        bindPreviewActions(view)
 
         SetWallpaperButtonBinder.bind(
-            view.requireViewById(R.id.button_set_wallpaper),
+            button = view.requireViewById(R.id.button_set_wallpaper),
+            viewModel = wallpaperPreviewViewModel,
+            lifecycleOwner = viewLifecycleOwner,
         ) {
             findNavController().navigate(R.id.action_smallPreviewFragment_to_setWallpaperDialog)
         }
+        setWallpaperProgressDialog =
+            ProgressDialog(context, R.style.LightDialogTheme).apply {
+                setTitle(null)
+                setMessage(context.getString(R.string.set_wallpaper_progress_message))
+                isIndeterminate = true
+            }
+        SetWallpaperProgressDialogBinder.bind(
+            dialog = setWallpaperProgressDialog,
+            viewModel = wallpaperPreviewViewModel,
+            lifecycleOwner = viewLifecycleOwner,
+        )
 
         return view
     }
@@ -94,13 +116,7 @@
     }
 
     private fun bindScreenPreview(view: View) {
-        PreviewActionsBinder.bind(
-            view.requireViewById(R.id.action_button_group),
-            view.requireViewById(R.id.floating_sheet),
-            wallpaperPreviewViewModel.previewActionsViewModel,
-            viewLifecycleOwner,
-            logger,
-        )
+        val currentNavDestId = checkNotNull(findNavController().currentDestination?.id)
         if (displayUtils.hasMultiInternalDisplays()) {
             val dualPreviewView: DualPreviewViewPager =
                 view.requireViewById(R.id.dual_preview_pager)
@@ -113,6 +129,7 @@
                 appContext,
                 viewLifecycleOwner,
                 mainScope,
+                currentNavDestId,
             ) { sharedElement ->
                 ViewCompat.setTransitionName(sharedElement, SMALL_PREVIEW_SHARED_ELEMENT_ID)
                 val extras =
@@ -137,6 +154,7 @@
                 appContext,
                 viewLifecycleOwner,
                 mainScope,
+                currentNavDestId,
             ) { sharedElement ->
                 ViewCompat.setTransitionName(sharedElement, SMALL_PREVIEW_SHARED_ELEMENT_ID)
                 val extras =
@@ -152,8 +170,67 @@
         }
     }
 
+    private fun bindPreviewActions(view: View) {
+        val shareActivityResult =
+            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
+                    }
+                },
+            ) {
+                view
+                    .findViewById<PreviewActionGroup>(R.id.action_button_group)
+                    ?.setIsChecked(Action.SHARE, false)
+            }
+        PreviewActionsBinder.bind(
+            actionGroup = view.requireViewById(R.id.action_button_group),
+            floatingSheet = view.requireViewById(R.id.floating_sheet),
+            previewViewModel = wallpaperPreviewViewModel,
+            actionsViewModel = wallpaperPreviewViewModel.previewActionsViewModel,
+            displaySize = displayUtils.getRealSize(requireActivity().display),
+            lifecycleOwner = viewLifecycleOwner,
+            logger = logger,
+            onStartEditActivity = {
+                findNavController()
+                    .navigate(
+                        resId = R.id.action_smallPreviewFragment_to_fullPreviewFragment,
+                        args = Bundle().apply { putParcelable(ARG_EDIT_INTENT, it) },
+                        navOptions = null,
+                        navigatorExtras = null,
+                    )
+            },
+            onStartShareActivity = { shareActivityResult.launch(it) },
+            onShowDeleteConfirmationDialog = { viewModel ->
+                val context = context ?: return@bind
+                AlertDialog.Builder(context)
+                    .setMessage(R.string.delete_wallpaper_confirmation)
+                    .setOnDismissListener { viewModel.onDismiss.invoke() }
+                    .setPositiveButton(R.string.delete_live_wallpaper) { _, _ ->
+                        if (viewModel.creativeWallpaperDeleteUri != null) {
+                            appContext.contentResolver.delete(
+                                viewModel.creativeWallpaperDeleteUri,
+                                null,
+                                null
+                            )
+                        } else if (viewModel.liveWallpaperDeleteIntent != null) {
+                            appContext.startService(viewModel.liveWallpaperDeleteIntent)
+                        }
+                        activity?.finish()
+                    }
+                    .setNegativeButton(android.R.string.cancel, null)
+                    .show()
+            },
+        )
+    }
+
     companion object {
         const val SMALL_PREVIEW_SHARED_ELEMENT_ID = "small_preview_shared_element"
         const val FULL_PREVIEW_SHARED_ELEMENT_ID = "full_preview_shared_element"
+        const val ARG_EDIT_INTENT = "arg_edit_intent"
     }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/DualPreviewPagerAdapter.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/DualPreviewPagerAdapter.kt
index dab4100..d7bc520 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/DualPreviewPagerAdapter.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/DualPreviewPagerAdapter.kt
@@ -36,7 +36,7 @@
     override fun instantiateItem(container: ViewGroup, position: Int): Any {
         val view =
             LayoutInflater.from(container.context)
-                .inflate(R.layout.preview_foldable_card_view, container, false)
+                .inflate(R.layout.small_preview_foldable_card_view, container, false)
 
         onBindViewHolder.invoke(view, position)
         container.addView(view)
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/SinglePreviewPagerAdapter.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/SinglePreviewPagerAdapter.kt
index ef143b9..d9d83fd 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/SinglePreviewPagerAdapter.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/adapters/SinglePreviewPagerAdapter.kt
@@ -29,7 +29,14 @@
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
         val view =
             LayoutInflater.from(parent.context)
-                .inflate(R.layout.preview_handheld_card_view, parent, false)
+                .inflate(R.layout.small_preview_handheld_card_view, parent, false)
+
+        view.setPadding(
+            0,
+            parent.resources.getDimension(R.dimen.small_preview_preview_top_padding).toInt(),
+            0,
+            parent.resources.getDimension(R.dimen.small_preview_preview_bottom_padding).toInt(),
+        )
         return ViewHolder(view)
     }
 
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 ff92903..6f4e98c 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
@@ -20,6 +20,7 @@
 import android.view.ViewGroup
 import android.widget.TextView
 import androidx.viewpager.widget.PagerAdapter
+import androidx.viewpager.widget.ViewPager
 import com.android.wallpaper.R
 
 /** This class provides the tab views for the tabs in small preview page */
@@ -40,8 +41,18 @@
         val itemView =
             LayoutInflater.from(container.context).inflate(R.layout.item_text, container, false)
 
+        val tabText = container.resources.getString(textPages[position])
+
         val textView = itemView.requireViewById<TextView>(R.id.preview_tab_text)
-        textView.text = container.resources.getString(textPages[position])
+        textView.text = tabText
+
+        val textViewDisabled =
+            itemView.requireViewById<TextView>(R.id.preview_tab_text_overlay_disabled)
+        textViewDisabled.text = tabText
+
+        itemView.setOnClickListener { view ->
+            (container as ViewPager).setCurrentItem(position, true)
+        }
 
         container.addView(itemView)
         return itemView
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/pagetransformers/PreviewSelectedTabTransformer.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/pagetransformers/PreviewSelectedTabTransformer.kt
new file mode 100644
index 0000000..4f0a515
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/pagetransformers/PreviewSelectedTabTransformer.kt
@@ -0,0 +1,38 @@
+/*
+ * 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.fragment.smallpreview.pagetransformers
+
+import android.view.View
+import android.widget.TextView
+import androidx.viewpager.widget.ViewPager
+import com.android.wallpaper.R
+import kotlin.math.abs
+
+/**
+ * Selector api for view pager pages is not correctly setting the state for a page. As a workaround
+ * this transformer manually controls the enable/disable state of the preview tab buttons
+ */
+class PreviewSelectedTabTransformer : ViewPager.PageTransformer {
+    override fun transformPage(page: View, position: Float) {
+        val textView = page.requireViewById<TextView>(R.id.preview_tab_text)
+        val textViewDisabled =
+            page.requireViewById<TextView>(R.id.preview_tab_text_overlay_disabled)
+
+        textViewDisabled.alpha = abs(position)
+        textView.alpha = 1 - abs(position)
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/pagetransformers/PreviewTabsPageTransformer.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/pagetransformers/PreviewTabsPageTransformer.kt
deleted file mode 100644
index 5a6fd16..0000000
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/pagetransformers/PreviewTabsPageTransformer.kt
+++ /dev/null
@@ -1,47 +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.smallpreview.pagetransformers
-
-import android.graphics.Point
-import android.view.View
-import androidx.viewpager.widget.ViewPager
-import com.android.wallpaper.R
-import kotlin.math.abs
-
-/**
- * This class provides the transformations for the tabs in the small preview screen. It enables the
- * behaviour where one out of two tabs cna be focused on and the other is clamped to the side of the
- * left or right of the display
- */
-class PreviewTabsPageTransformer(
-    private val previewDisplaySize: Point,
-) : ViewPager.PageTransformer {
-    override fun transformPage(page: View, position: Float) {
-        // TODO: cache this reference since findViewById is expensive
-        val textView = page.requireViewById<View>(R.id.preview_tab_text)
-
-        val absPosition = Math.abs(position)
-        var textViewWidthOffset: Float = (textView.width / 2 * (absPosition))
-        if (position > 0) {
-            textViewWidthOffset *= -1
-        }
-        page.translationX = -previewDisplaySize.x / 2 * position + textViewWidthOffset
-        val scaleFactor = 0.95f
-        page.scaleX = scaleFactor + (1 - scaleFactor) * (1 - absPosition)
-        page.scaleY = scaleFactor + (1 - scaleFactor) * (1 - absPosition)
-        page.alpha = 0.25f + (1 - abs(position))
-    }
-}
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/views/TabsPagerContainer.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/views/TabsPagerContainer.kt
index 87382db..9acc1dd 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/views/TabsPagerContainer.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/smallpreview/views/TabsPagerContainer.kt
@@ -16,11 +16,16 @@
 package com.android.wallpaper.picker.preview.ui.fragment.smallpreview.views
 
 import android.content.Context
+import android.graphics.Rect
 import android.util.AttributeSet
 import android.view.Gravity
 import android.view.MotionEvent
+import android.view.View
+import android.view.ViewConfiguration
 import android.widget.FrameLayout
+import androidx.core.view.get
 import androidx.viewpager.widget.ViewPager
+import kotlin.math.abs
 
 /** This container view wraps {TabsPager}. This is used to control the touch area of {TabsPager}. */
 class TabsPagerContainer
@@ -47,17 +52,91 @@
         addView(viewPager)
     }
 
-    override fun onTouchEvent(ev: MotionEvent?): Boolean {
+    // x-coordinate of the beginning of a gesture
+    var touchDownX = 0
+
+    // y-coordinate of the beginning of a gesture
+    var touchDownY = 0
+
+    // x-coordinate of the ending of a gesture
+    var touchUpX = 0
+
+    // x-coordinate of the ending of a gesture
+    var touchUpY = 0
+    override fun onTouchEvent(ev: MotionEvent): Boolean {
+        val tab1 = viewPager.get(0)
+        val tab2 = viewPager.get(1)
+        val tab1Rect = tab1.getViewRect()
+        val tab2Rect = tab2.getViewRect()
+        when (ev.action) {
+            MotionEvent.ACTION_DOWN -> {
+                touchDownX = ev.getRawX().toInt()
+                touchDownY = ev.getRawY().toInt()
+
+                // if the touch down event doesn't land in the visible rect of either tab buttons
+                // then we ignore the entirety of the next gesture
+                if (
+                    !tab2Rect.contains(touchDownX, touchDownY) &&
+                        !tab1Rect.contains(touchDownX, touchDownY)
+                ) {
+                    return false
+                }
+            }
+            // Intercepting the touch event here indicates a button has been touched outiside
+            // the bounds of the ViewPager.
+            MotionEvent.ACTION_UP -> {
+
+                // Verify whether the touch up action corresponds to actual tap as opposed to
+                // another gesture
+                if (isClick(touchDownX, touchDownY, ev)) {
+                    if (tab2Rect.contains(touchDownX, touchDownY)) {
+                        // the only time we need to actually scroll to a tab is when the tab which
+                        // was clicked is not the currently centered tab
+                        tab2.callOnClick()
+                    }
+
+                    if (tab1Rect.contains(touchDownX, touchDownY)) {
+                        tab1.callOnClick()
+                    }
+                    return true
+                }
+            }
+        }
         return viewPager.dispatchTouchEvent(ev)
     }
 
-    // TODO: handle click button here and pass click to correct tab
-    override fun performClick(): Boolean {
-        super.performClick()
-        return true
+    // The maximum distance delta in finger position between where the finger first touches the
+    // screen  and when it lifts from the screen to be considered a tap
+    private val CLICK_TOLERANCE = ViewConfiguration.get(context).scaledTouchSlop
+
+    /** Returns whether the given motion event is a tap */
+    private fun isClick(downX: Int, downY: Int, ev: MotionEvent): Boolean {
+        val deltaX = abs(downX - ev.getRawX().toInt())
+        val deltaY = abs(downY - ev.getRawY().toInt())
+
+        val isWithinTimeThreshold = gestureElapsedTime(ev) <= ViewConfiguration.getTapTimeout()
+        val isWithinDistanceThreshold = deltaX <= CLICK_TOLERANCE && deltaY <= CLICK_TOLERANCE
+
+        return isWithinTimeThreshold && isWithinDistanceThreshold
+    }
+
+    /** Returns the elapsed time since the touch gesture the given event is part of has begun. */
+    private fun gestureElapsedTime(event: MotionEvent): Long {
+        return event.eventTime - event.downTime
+    }
+
+    private fun View.getViewRect(): Rect {
+        val returnRect = Rect()
+        this.getGlobalVisibleRect(returnRect)
+        return returnRect
     }
 
     fun getViewPager(): ViewPager {
         return viewPager
     }
+
+    override fun performClick(): Boolean {
+        // returning true to signify that the click was handled by a custom implementation
+        return true
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/util/CropSizeUtil.kt b/src/com/android/wallpaper/picker/preview/ui/util/CropSizeUtil.kt
index f52f1b1..72d1219 100644
--- a/src/com/android/wallpaper/picker/preview/ui/util/CropSizeUtil.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/util/CropSizeUtil.kt
@@ -66,4 +66,13 @@
 
         return PointF(x * ratio, y * ratio)
     }
+
+    fun fitCropRectToLayoutDirection(
+        cropRect: Rect,
+        displaySize: Point,
+        isRtl: Boolean,
+    ): Rect {
+        val parallax = cropRect.width() - displaySize.x * cropRect.height() / displaySize.y
+        return Rect(cropRect).apply { if (isRtl) left += parallax else right -= parallax }
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt b/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt
index d1f9a5b..69790a5 100644
--- a/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt
@@ -18,6 +18,7 @@
 import android.graphics.Point
 import android.graphics.PointF
 import android.graphics.Rect
+import com.android.wallpaper.picker.preview.ui.util.CropSizeUtil.fitCropRectToLayoutDirection
 import com.android.wallpaper.util.WallpaperCropUtils
 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
 
@@ -28,13 +29,17 @@
     fun getScaleAndCenter(
         viewSize: Point,
         rawWallpaperSize: Point,
+        displaySize: Point,
         cropRect: Rect?,
+        isRtl: Boolean,
     ): ScaleAndCenter {
         // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
         // defaultRawWallpaperRect represents a brand new wallpaper preview with no crop hints.
         val defaultRawWallpaperRect =
             WallpaperCropUtils.calculateVisibleRect(rawWallpaperSize, viewSize)
-        val visibleRawWallpaperRect = cropRect ?: defaultRawWallpaperRect
+        val visibleRawWallpaperRect =
+            cropRect?.let { fitCropRectToLayoutDirection(it, displaySize, isRtl) }
+                ?: defaultRawWallpaperRect
         val centerPosition =
             PointF(
                 visibleRawWallpaperRect.centerX().toFloat(),
diff --git a/src/com/android/wallpaper/picker/preview/ui/util/LiveWallpaperDeleteUtil.kt b/src/com/android/wallpaper/picker/preview/ui/util/LiveWallpaperDeleteUtil.kt
new file mode 100644
index 0000000..b60bd9e
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/util/LiveWallpaperDeleteUtil.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.util
+
+import android.app.WallpaperInfo
+import android.app.WallpaperManager
+import android.app.WallpaperManager.FLAG_LOCK
+import android.app.WallpaperManager.FLAG_SYSTEM
+import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.text.TextUtils
+import com.android.wallpaper.picker.LivePreviewFragment
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/** The utility class for live wallpaper that can be deleted */
+@Singleton
+class LiveWallpaperDeleteUtil @Inject constructor(private val wallpaperManager: WallpaperManager) {
+
+    fun getDeleteActionIntent(wallpaperInfo: WallpaperInfo): Intent? {
+        val deleteAction = getDeleteAction(wallpaperInfo)
+        if (TextUtils.isEmpty(deleteAction)) {
+            return null
+        }
+        val deleteActionIntent = Intent(deleteAction)
+        deleteActionIntent.setPackage(wallpaperInfo.packageName)
+        deleteActionIntent.putExtra(LivePreviewFragment.EXTRA_LIVE_WALLPAPER_INFO, wallpaperInfo)
+        return deleteActionIntent
+    }
+
+    private fun getDeleteAction(wallpaperInfo: WallpaperInfo): String? {
+        val currentInfo = wallpaperManager.getWallpaperInfo(FLAG_SYSTEM)
+        val currentLockInfo = wallpaperManager.getWallpaperInfo(FLAG_LOCK)
+        val serviceInfo = wallpaperInfo.serviceInfo
+        val appInfo = serviceInfo.applicationInfo
+        val isPackagePreInstalled =
+            appInfo != null && appInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0
+        if (!isPackagePreInstalled) {
+            // This wallpaper is not installed before
+            return null
+        }
+
+        // A currently set Live wallpaper should not be deleted.
+        val currentService = currentInfo?.serviceInfo
+        if (currentService != null && TextUtils.equals(serviceInfo.name, currentService.name)) {
+            return null
+        }
+        val currentLockService = currentLockInfo?.serviceInfo
+        if (
+            currentLockService != null &&
+                TextUtils.equals(serviceInfo.name, currentLockService.name)
+        ) {
+            return null
+        }
+        val metaData = serviceInfo.metaData
+        return metaData?.getString(LivePreviewFragment.KEY_ACTION_DELETE_LIVE_WALLPAPER)
+    }
+}
diff --git a/src/com/android/wallpaper/picker/preview/ui/util/SubsamplingScaleImageViewUtil.kt b/src/com/android/wallpaper/picker/preview/ui/util/SubsamplingScaleImageViewUtil.kt
new file mode 100644
index 0000000..ae7b3c9
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/util/SubsamplingScaleImageViewUtil.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.util
+
+import android.graphics.PointF
+import android.graphics.Rect
+import com.android.wallpaper.picker.preview.ui.util.FullResImageViewUtil.getCropRect
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
+
+object SubsamplingScaleImageViewUtil {
+
+    fun SubsamplingScaleImageView.setOnNewCropListener(
+        onNewCrop: (crop: Rect, zoom: Float) -> Unit
+    ) {
+        setOnStateChangedListener(
+            object : SubsamplingScaleImageView.OnStateChangedListener {
+                override fun onScaleChanged(p0: Float, p1: Int) {
+                    onNewCrop.invoke(getCropRect(), scale)
+                }
+
+                override fun onCenterChanged(p0: PointF?, p1: Int) {
+                    onNewCrop.invoke(getCropRect(), scale)
+                }
+            }
+        )
+    }
+}
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 bad88fa..376a88b 100644
--- a/src/com/android/wallpaper/picker/preview/ui/view/DualDisplayAspectRatioLayout.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/view/DualDisplayAspectRatioLayout.kt
@@ -18,10 +18,10 @@
 import android.content.Context
 import android.graphics.Point
 import android.util.AttributeSet
-import android.view.LayoutInflater
 import android.widget.LinearLayout
 import com.android.wallpaper.R
 import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import kotlin.math.max
 
 /**
  * This LinearLayout view group implements the dual preview view for the small preview screen for
@@ -34,19 +34,6 @@
 
     private var previewDisplaySizes: Map<FoldableDisplay, Point>? = null
 
-    init {
-        val inflater =
-            getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
-        val foldedPreview = inflater.inflate(R.layout.wallpaper_preview_small, null)
-
-        foldedPreview.id = FoldableDisplay.FOLDED.getViewId()
-        addView(foldedPreview)
-
-        val unfoldedPreview = inflater.inflate(R.layout.wallpaper_preview_small, null)
-        unfoldedPreview.id = FoldableDisplay.UNFOLDED.getViewId()
-        addView(unfoldedPreview)
-    }
-
     /**
      * This measures the desired size of the preview views for both of foldable device's displays.
      * Each preview view respects the aspect ratio of the display it corresponds to while trying to
@@ -69,46 +56,59 @@
         // TODO: This only works for portrait mode currently, need to incorporate landscape
         val parentWidth = this.measuredWidth - totalMarginPixels
 
-        getPreviewDisplaySize(FoldableDisplay.FOLDED)?.let { smallDisplaySize ->
-            getPreviewDisplaySize(FoldableDisplay.UNFOLDED)?.let { largeDisplaySize ->
-                // calculate the aspect ratio (ar) of the folded display
-                val smallDisplayAR = smallDisplaySize.x.toFloat() / smallDisplaySize.y
+        val smallDisplaySize = checkNotNull(getPreviewDisplaySize(FoldableDisplay.FOLDED))
+        val largeDisplaySize = checkNotNull(getPreviewDisplaySize(FoldableDisplay.UNFOLDED))
 
-                // calculate the aspect ratio of the unfolded display
-                val largeDisplayAR = largeDisplaySize.x.toFloat() / largeDisplaySize.y
+        // calculate the aspect ratio (ar) of the folded display
+        val smallDisplayAR = smallDisplaySize.x.toFloat() / smallDisplaySize.y
 
-                val sizeMultiplier = parentWidth / (largeDisplayAR + smallDisplayAR)
-                val widthFolded = (sizeMultiplier * smallDisplayAR).toInt()
-                val heightFolded = (widthFolded / smallDisplayAR).toInt()
+        // calculate the aspect ratio of the unfolded display
+        val largeDisplayAR = largeDisplaySize.x.toFloat() / largeDisplaySize.y
 
-                val widthUnfolded = (sizeMultiplier * largeDisplayAR).toInt()
-                val heightUnfolded = (widthUnfolded / largeDisplayAR).toInt()
+        val sizeMultiplier = parentWidth / (largeDisplayAR + smallDisplayAR)
+        val widthFolded = (sizeMultiplier * smallDisplayAR).toInt()
+        val heightFolded = (widthFolded / smallDisplayAR).toInt()
 
-                val foldedView = getChildAt(0)
-                foldedView.measure(
-                    MeasureSpec.makeMeasureSpec(
-                        widthFolded,
-                        MeasureSpec.EXACTLY,
-                    ),
-                    MeasureSpec.makeMeasureSpec(
-                        heightFolded,
-                        MeasureSpec.EXACTLY,
-                    ),
-                )
+        val widthUnfolded = (sizeMultiplier * largeDisplayAR).toInt()
+        val heightUnfolded = (widthUnfolded / largeDisplayAR).toInt()
 
-                val unfoldedView = getChildAt(1)
-                unfoldedView.measure(
-                    MeasureSpec.makeMeasureSpec(
-                        widthUnfolded,
-                        MeasureSpec.EXACTLY,
-                    ),
-                    MeasureSpec.makeMeasureSpec(
-                        heightUnfolded,
-                        MeasureSpec.EXACTLY,
-                    ),
-                )
-            }
-        }
+        val foldedView = getChildAt(0)
+        foldedView.measure(
+            MeasureSpec.makeMeasureSpec(
+                widthFolded,
+                MeasureSpec.EXACTLY,
+            ),
+            MeasureSpec.makeMeasureSpec(
+                heightFolded,
+                MeasureSpec.EXACTLY,
+            ),
+        )
+
+        val unfoldedView = getChildAt(1)
+        unfoldedView.measure(
+            MeasureSpec.makeMeasureSpec(
+                widthUnfolded,
+                MeasureSpec.EXACTLY,
+            ),
+            MeasureSpec.makeMeasureSpec(
+                heightUnfolded,
+                MeasureSpec.EXACTLY,
+            ),
+        )
+
+        val marginPixels =
+            context.resources.getDimension(R.dimen.small_preview_inter_preview_margin).toInt()
+
+        setMeasuredDimension(
+            MeasureSpec.makeMeasureSpec(
+                widthFolded + widthUnfolded + 2 * marginPixels,
+                MeasureSpec.EXACTLY,
+            ),
+            MeasureSpec.makeMeasureSpec(
+                max(heightFolded, heightUnfolded),
+                MeasureSpec.EXACTLY,
+            )
+        )
     }
 
     override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
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 f3513ba..b5081fe 100644
--- a/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt
@@ -24,7 +24,9 @@
 import android.widget.TextView
 import androidx.core.view.isVisible
 import com.android.wallpaper.R
+import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
 import com.android.wallpaper.util.SizeCalculator
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
 
@@ -48,6 +50,37 @@
         floatingSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
     }
 
+    fun setEffectContent(
+        effect: EffectEnumInterface,
+        myPhotosClickListener: OnClickListener,
+        collapseFloatingSheetListener: OnClickListener,
+        effectSwitchListener: WallpaperEffectsView2.EffectSwitchListener,
+        effectDownloadClickListener: WallpaperEffectsView2.EffectDownloadClickListener,
+        status: WallpaperEffectsView2.Status,
+        resultCode: Int?,
+        errorMessage: String?,
+        title: String,
+        effectTextRes: WallpaperEffectsView2.EffectTextRes,
+    ) {
+        val view =
+            LayoutInflater.from(context).inflate(R.layout.wallpaper_effects_view2, this, false)
+                as WallpaperEffectsView2
+        view.setEffectResources(effectTextRes)
+        view.setMyPhotosClickListener(myPhotosClickListener)
+        view.setCollapseFloatingSheetListener(collapseFloatingSheetListener)
+        view.addEffectSwitchListener(effectSwitchListener)
+        view.setEffectDownloadClickListener(effectDownloadClickListener)
+        view.updateEffectStatus(
+            effect,
+            status,
+            resultCode,
+            errorMessage,
+        )
+        view.updateEffectTitle(title)
+        floatingSheetView.removeAllViews()
+        floatingSheetView.addView(view)
+    }
+
     fun setInformationContent(
         attributions: List<String?>?,
         onExploreButtonClicked: (() -> Unit)?,
diff --git a/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionGroup.kt b/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionGroup.kt
index 7966752..2703188 100644
--- a/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionGroup.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionGroup.kt
@@ -72,6 +72,11 @@
             )
     }
 
+    fun setIsDownloading(isDownloading: Boolean) {
+        downloadButtonProgress.isVisible = isDownloading
+        downloadButtonToggle.isVisible = !isDownloading
+    }
+
     private fun getActionView(action: Action): View {
         return when (action) {
             Action.INFORMATION -> informationButton
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/DeleteConfirmationDialogViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/DeleteConfirmationDialogViewModel.kt
new file mode 100644
index 0000000..1270d14
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/DeleteConfirmationDialogViewModel.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.viewmodel
+
+import android.content.Intent
+import android.net.Uri
+
+class DeleteConfirmationDialogViewModel(
+    val onDismiss: () -> Unit,
+    // Delete intent for general live wallpapers. It is null for creative wallpapers.
+    val liveWallpaperDeleteIntent: Intent?,
+    // Delete URI for creative wallpapers only. It is null for non creative wallpapers.
+    val creativeWallpaperDeleteUri: Uri?,
+)
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 1a921f0..57aba6a 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
@@ -17,11 +17,12 @@
 
 import android.graphics.Bitmap
 import android.graphics.Point
-import android.graphics.Rect
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
+import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
+import java.io.InputStream
 
 data class FullResWallpaperViewModel(
     val rawWallpaperBitmap: Bitmap,
     val rawWallpaperSize: Point,
-    val cropHints: Map<ScreenOrientation, Rect>?,
+    val stream: InputStream?,
+    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
new file mode 100644
index 0000000..7ab1f36
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullWallpaperPreviewViewModel.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.viewmodel
+
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.util.WallpaperConnection.WhichPreview
+
+data class FullWallpaperPreviewViewModel(
+    val wallpaper: WallpaperModel,
+    val config: WallpaperPreviewConfigViewModel,
+    val allowUserCropping: Boolean,
+    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 baff813..463182f 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt
@@ -16,20 +16,31 @@
 
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
-import com.android.wallpaper.model.wallpaper.WallpaperModel
-import com.android.wallpaper.picker.di.modules.MainDispatcher
+import android.content.ClipData
+import android.content.ComponentName
+import android.content.Intent
+import android.net.Uri
+import android.service.wallpaper.WallpaperSettingsActivity
+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.domain.interactor.PreviewActionsInteractor
+import com.android.wallpaper.picker.preview.ui.util.LiveWallpaperDeleteUtil
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.CUSTOMIZE
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.DELETE
-import com.android.wallpaper.picker.preview.ui.viewmodel.Action.DOWNLOAD
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.EDIT
 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.InformationFloatingSheetViewModel
+import com.android.wallpaper.widget.floatingsheetcontent.WallpaperEffectsView2
 import dagger.hilt.android.scopes.ViewModelScoped
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -42,9 +53,10 @@
 class PreviewActionsViewModel
 @Inject
 constructor(
-    interactor: PreviewActionsInteractor,
-    @MainDispatcher private val scope: CoroutineScope,
+    private val interactor: PreviewActionsInteractor,
+    liveWallpaperDeleteUtil: LiveWallpaperDeleteUtil,
 ) {
+    /** [INFORMATION] */
     private val _informationFloatingSheetViewModel: Flow<InformationFloatingSheetViewModel?> =
         interactor.wallpaperModel.map { wallpaperModel ->
             if (wallpaperModel == null || !wallpaperModel.shouldShowInformationFloatingSheet()) {
@@ -57,55 +69,13 @@
             }
         }
 
-    /** Action's isVisible state */
     val isInformationVisible: Flow<Boolean> = _informationFloatingSheetViewModel.map { it != null }
 
-    val isDownloadVisible: Flow<Boolean> =
-        interactor.wallpaperModel.map {
-            (it as? WallpaperModel.StaticWallpaperModel)?.downloadableWallpaperData != null
-        }
-
-    private val _isDeleteVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isDeleteVisible: Flow<Boolean> = _isDeleteVisible.asStateFlow()
-
-    private val _isEditVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isEditVisible: Flow<Boolean> = _isEditVisible.asStateFlow()
-
-    private val _isCustomizeVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isCustomizeVisible: Flow<Boolean> = _isCustomizeVisible.asStateFlow()
-
-    private val _isEffectsVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isEffectsVisible: Flow<Boolean> = _isEffectsVisible.asStateFlow()
-
-    private val _isShareVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isShareVisible: Flow<Boolean> = _isShareVisible.asStateFlow()
-
-    /** Action's isChecked state */
     private val _isInformationChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
     val isInformationChecked: Flow<Boolean> = _isInformationChecked.asStateFlow()
 
-    private val _isDownloadChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isDownloadChecked: Flow<Boolean> = _isDownloadChecked.asStateFlow()
-
-    private val _isDeleteChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isDeleteChecked: Flow<Boolean> = _isDeleteChecked.asStateFlow()
-
-    private val _isEditChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isEditChecked: Flow<Boolean> = _isEditChecked.asStateFlow()
-
-    private val _isCustomizeChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isCustomizeChecked: Flow<Boolean> = _isCustomizeChecked.asStateFlow()
-
-    private val _isEffectsChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isEffectsChecked: Flow<Boolean> = _isEffectsChecked.asStateFlow()
-
-    private val _isShareChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isShareChecked: Flow<Boolean> = _isShareChecked.asStateFlow()
-
-    /**
-     * Floating sheet contents for the bottom sheet dialog. If content is null, the bottom sheet
-     * should collapse, otherwise, expended.
-     */
+    // 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) {
@@ -116,7 +86,6 @@
             }
             .distinctUntilChanged()
 
-    /** Action listeners */
     val onInformationClicked: Flow<(() -> Unit)?> =
         combine(isInformationVisible, isInformationChecked) { show, isChecked ->
             if (show) {
@@ -131,15 +100,65 @@
             }
         }
 
-    val onDownloadClicked: Flow<(() -> Unit)?> =
-        combine(isDownloadVisible, isDownloadChecked) { show, isChecked ->
-            if (show) {
-                {
-                    if (!isChecked) {
-                        uncheckAllOthersExcept(DOWNLOAD)
-                    }
-                    _isDownloadChecked.value = !isChecked
-                }
+    /** [DOWNLOAD] */
+    private val downloadableWallpaperData: Flow<DownloadableWallpaperData?> =
+        interactor.wallpaperModel.map {
+            (it as? WallpaperModel.StaticWallpaperModel)?.downloadableWallpaperData
+        }
+    val isDownloadVisible: Flow<Boolean> = downloadableWallpaperData.map { it != null }
+
+    val isDownloading: Flow<Boolean> = interactor.isDownloadingWallpaper
+
+    val isDownloadButtonEnabled: Flow<Boolean> =
+        combine(downloadableWallpaperData, isDownloading) { downloadableData, isDownloading ->
+            downloadableData != null && !isDownloading
+        }
+
+    suspend fun downloadWallpaper() {
+        interactor.downloadWallpaper()
+    }
+
+    /** [DELETE] */
+    private val liveWallpaperDeleteIntent: Flow<Intent?> =
+        interactor.wallpaperModel.map {
+            if (it is LiveWallpaperModel && it.creativeWallpaperData == null && it.canBeDeleted()) {
+                liveWallpaperDeleteUtil.getDeleteActionIntent(
+                    it.liveWallpaperData.systemWallpaperInfo
+                )
+            } else {
+                null
+            }
+        }
+    private val creativeWallpaperDeleteUri: Flow<Uri?> =
+        interactor.wallpaperModel.map {
+            val deleteUri = (it as? LiveWallpaperModel)?.creativeWallpaperData?.deleteUri
+            if (deleteUri != null && it.canBeDeleted()) {
+                deleteUri
+            } else {
+                null
+            }
+        }
+    val isDeleteVisible: Flow<Boolean> =
+        combine(liveWallpaperDeleteIntent, creativeWallpaperDeleteUri) { intent, uri ->
+            intent != null || uri != null
+        }
+
+    private val _isDeleteChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    val isDeleteChecked: Flow<Boolean> = _isDeleteChecked.asStateFlow()
+
+    // View model for delete confirmation dialog. Note that null means the dialog should show;
+    // otherwise, the dialog should hide.
+    val deleteConfirmationDialogViewModel: Flow<DeleteConfirmationDialogViewModel?> =
+        combine(isDeleteChecked, liveWallpaperDeleteIntent, creativeWallpaperDeleteUri) {
+            isChecked,
+            intent,
+            uri ->
+            if (isChecked && (intent != null || uri != null)) {
+                DeleteConfirmationDialogViewModel(
+                    onDismiss = { _isDeleteChecked.value = false },
+                    liveWallpaperDeleteIntent = intent,
+                    creativeWallpaperDeleteUri = uri,
+                )
             } else {
                 null
             }
@@ -159,19 +178,22 @@
             }
         }
 
-    val onEditClicked: Flow<(() -> Unit)?> =
-        combine(isEditVisible, isEditChecked) { show, isChecked ->
-            if (show) {
-                {
-                    if (!isChecked) {
-                        uncheckAllOthersExcept(EDIT)
-                    }
-                    _isEditChecked.value = !isChecked
-                }
-            } else {
-                null
-            }
+    /** [EDIT] */
+    val editIntent: Flow<Intent?> =
+        interactor.wallpaperModel.map {
+            (it as? WallpaperModel.LiveWallpaperModel)?.liveWallpaperData?.getEditActivityIntent()
         }
+    val isEditVisible: Flow<Boolean> = editIntent.map { it != null }
+
+    private val _isEditChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    val isEditChecked: Flow<Boolean> = _isEditChecked.asStateFlow()
+
+    /** [CUSTOMIZE] */
+    private val _isCustomizeVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    val isCustomizeVisible: Flow<Boolean> = _isCustomizeVisible.asStateFlow()
+
+    private val _isCustomizeChecked: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    val isCustomizeChecked: Flow<Boolean> = _isCustomizeChecked.asStateFlow()
 
     val onCustomizeClicked: Flow<(() -> Unit)?> =
         combine(isCustomizeVisible, isCustomizeChecked) { show, isChecked ->
@@ -187,6 +209,86 @@
             }
         }
 
+    /** [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 fun getEffectFloatingSheetViewModel(
+        status: EffectsRepository.EffectStatus,
+        title: String,
+        effectType: EffectEnumInterface,
+    ): EffectFloatingSheetViewModel {
+        val floatingSheetViewStatus =
+            when (status) {
+                EffectsRepository.EffectStatus.EFFECT_APPLY_IN_PROGRESS ->
+                    WallpaperEffectsView2.Status.PROCESSING
+                EffectsRepository.EffectStatus.EFFECT_APPLIED ->
+                    WallpaperEffectsView2.Status.SUCCESS
+                else -> WallpaperEffectsView2.Status.IDLE
+            }
+        return EffectFloatingSheetViewModel(
+            myPhotosClickListener = {},
+            collapseFloatingSheetListener = {},
+            object : WallpaperEffectsView2.EffectSwitchListener {
+                override fun onEffectSwitchChanged(
+                    effect: EffectEnumInterface,
+                    isChecked: Boolean
+                ) {
+                    if (interactor.isTargetEffect(effect)) {
+                        if (isChecked) {
+                            interactor.enableImageEffect(effect)
+                        } else {
+                            interactor.disableImageEffect()
+                        }
+                    }
+                }
+            },
+            object : WallpaperEffectsView2.EffectDownloadClickListener {
+                override fun onEffectDownloadClick() {
+                    TODO("Not yet implemented")
+                }
+            },
+            floatingSheetViewStatus,
+            resultCode = null,
+            errorMessage = null,
+            title,
+            effectType,
+            interactor.getEffectTextRes(),
+        )
+    }
+
+    val isEffectsVisible: Flow<Boolean> = _effectFloatingSheetViewModel.map { it != 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) {
@@ -201,27 +303,29 @@
             }
         }
 
-    val onShareClicked: Flow<(() -> Unit)?> =
-        combine(isShareVisible, isShareChecked) { show, isChecked ->
-            if (show) {
-                {
-                    if (!isChecked) {
-                        uncheckAllOthersExcept(SHARE)
-                    }
-                    _isShareChecked.value = !isChecked
-                }
-            } else {
-                null
-            }
+    /** [SHARE] */
+    val shareIntent: Flow<Intent?> =
+        interactor.wallpaperModel.map {
+            (it as? LiveWallpaperModel)?.creativeWallpaperData?.getShareIntent()
         }
+    val isShareVisible: Flow<Boolean> = shareIntent.map { it != 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.
+        if (_isInformationChecked.value) {
+            _isInformationChecked.value = false
+        }
+
+        if (_isEffectsChecked.value) {
+            _isEffectsChecked.value = false
+        }
+    }
 
     private fun uncheckAllOthersExcept(action: Action) {
         if (action != INFORMATION) {
             _isInformationChecked.value = false
         }
-        if (action != DOWNLOAD) {
-            _isDownloadChecked.value = false
-        }
         if (action != DELETE) {
             _isDeleteChecked.value = false
         }
@@ -234,36 +338,60 @@
         if (action != EFFECTS) {
             _isEffectsChecked.value = false
         }
-        if (action != SHARE) {
-            _isShareChecked.value = false
-        }
-    }
-
-    fun onDialogCollapsed() {
-        if (_isInformationChecked.value) {
-            _isInformationChecked.value = false
-        }
     }
 
     companion object {
         private fun WallpaperModel.shouldShowInformationFloatingSheet(): Boolean {
-            return if (
-                commonWallpaperData.attributions.isNullOrEmpty() &&
-                    commonWallpaperData.exploreActionUrl.isNullOrEmpty()
-            ) {
-                // If neither of the attributes nor the action url exists, do not show the
-                // information floating sheet.
-                false
-            } else if (
-                this is WallpaperModel.LiveWallpaperModel &&
+            if (
+                this is LiveWallpaperModel &&
                     !liveWallpaperData.systemWallpaperInfo.showMetadataInPreview
             ) {
                 // If the live wallpaper's flag of showMetadataInPreview is false, do not show the
                 // information floating sheet.
-                false
-            } else {
-                true
+                return false
             }
+            val attributions = commonWallpaperData.attributions
+            // Show information floating sheet when any of the following contents exists
+            // 1. Attributions: Any of the list values is not null nor empty
+            // 2. Explore action URL
+            return (!attributions.isNullOrEmpty() && attributions.any { !it.isNullOrEmpty() }) ||
+                !commonWallpaperData.exploreActionUrl.isNullOrEmpty()
+        }
+
+        private fun CreativeWallpaperData.getShareIntent(): Intent {
+            val shareIntent = Intent(Intent.ACTION_SEND)
+            shareIntent.putExtra(Intent.EXTRA_STREAM, shareUri)
+            shareIntent.setType("image/*")
+            shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+            shareIntent.clipData = ClipData.newRawUri(null, shareUri)
+            return Intent.createChooser(shareIntent, null)
+        }
+
+        private fun LiveWallpaperModel.canBeDeleted(): Boolean {
+            return if (creativeWallpaperData != null) {
+                !liveWallpaperData.isApplied &&
+                    !creativeWallpaperData.isCurrent &&
+                    creativeWallpaperData.deleteUri.toString().isNotEmpty()
+            } else {
+                !liveWallpaperData.isApplied
+            }
+        }
+
+        fun LiveWallpaperData.getEditActivityIntent(): Intent? {
+            val settingsActivity = systemWallpaperInfo.settingsActivity
+            if (settingsActivity.isNullOrEmpty()) {
+                return null
+            }
+            val intent =
+                Intent().apply {
+                    component = ComponentName(systemWallpaperInfo.packageName, settingsActivity)
+                    putExtra(WallpaperSettingsActivity.EXTRA_PREVIEW_MODE, true)
+                }
+            return intent
+        }
+
+        fun LiveWallpaperModel.isNewCreativeWallpaper(): Boolean {
+            return creativeWallpaperData?.deleteUri?.toString()?.isEmpty() == true
         }
     }
 }
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 bf56188..15f33b2 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
@@ -23,24 +23,31 @@
 import android.graphics.Point
 import android.graphics.Rect
 import com.android.wallpaper.asset.Asset
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel.StaticWallpaperModel
+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
 import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
 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 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
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.suspendCancellableCoroutine
 
 /** View model for static wallpaper preview used in [WallpaperPreviewActivity] and its fragments */
@@ -52,37 +59,104 @@
     @ApplicationContext private val context: Context,
     private val wallpaperPreferences: WallpaperPreferences,
     @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
+    viewModelScope: CoroutineScope,
 ) {
-    /** The state of static wallpaper crop in full preview, before user confirmation. */
-    var fullPreviewCrop: Rect? = null
+    /**
+     * The state of static wallpaper crop in full preview, before user confirmation.
+     *
+     * The initial value should be the default crop on small preview, which could be the cropHints
+     * for current wallpaper or default crop area for a new wallpaper.
+     */
+    val fullPreviewCropModels: MutableMap<Point, FullPreviewCropModel> = mutableMapOf()
 
-    private val _cropHints: MutableStateFlow<Map<ScreenOrientation, Rect>?> = MutableStateFlow(null)
+    /**
+     * The info picker needs to post process crops for setting static wallpaper.
+     *
+     * It will be filled with current cropHints when previewing current wallpaper, and null when
+     * previewing a new wallpaper, and gets updated through [updateCropHintsInfo] when user picks a
+     * new crop.
+     */
+    private val cropHintsInfo: MutableStateFlow<Map<Point, FullPreviewCropModel>?> =
+        MutableStateFlow(null)
 
-    private val staticWallpaperModel: Flow<StaticWallpaperModel> =
+    private val cropHints: Flow<Map<Point, Rect>?> =
+        cropHintsInfo.map { cropHintsInfoMap ->
+            cropHintsInfoMap?.map { entry -> entry.key to entry.value.cropHint }?.toMap()
+        }
+
+    val staticWallpaperModel: Flow<StaticWallpaperModel> =
         interactor.wallpaperModel.map { it as? StaticWallpaperModel }.filterNotNull()
     val lowResBitmap: Flow<Bitmap> =
         staticWallpaperModel
             .map { it.staticWallpaperData.asset.getLowResBitmap(context) }
             .filterNotNull()
             .flowOn(bgDispatcher)
-    val subsamplingScaleImageViewModel: Flow<FullResWallpaperViewModel> =
-        staticWallpaperModel
-            .map { it.staticWallpaperData.asset }
-            .combine(_cropHints) { asset, cropHints ->
-                val dimensions = asset.decodeRawDimensions()
-                asset.decodeBitmap(dimensions)?.let { bitmap ->
-                    FullResWallpaperViewModel(bitmap, dimensions, cropHints)
+    // Asset detail includes the dimensions, bitmap and input stream decoded from the asset.
+    private val assetDetail: Flow<Triple<Point, Bitmap?, InputStream?>?> =
+        interactor.wallpaperModel
+            .map { (it as? StaticWallpaperModel)?.staticWallpaperData?.asset }
+            .map {
+                if (it == null) {
+                    null
+                } else {
+                    val dimensions = it.decodeRawDimensions()
+                    val bitmap = it.decodeBitmap(dimensions)
+                    val stream = it.getStream()
+                    Triple(dimensions, bitmap, stream)
                 }
             }
-            .filterNotNull()
             .flowOn(bgDispatcher)
-    val wallpaperColors: Flow<WallpaperColors> =
+            // We only want to decode bitmap every time when wallpaper model is updated, instead of
+            // a new subscriber listens to this flow. So we need to use shareIn.
+            .shareIn(viewModelScope, SharingStarted.Lazily, 1)
+
+    val fullResWallpaperViewModel: Flow<FullResWallpaperViewModel?> =
+        combine(assetDetail, cropHintsInfo) { assetDetail, cropHintsInfo ->
+                if (assetDetail == null) {
+                    null
+                } else {
+                    val (dimensions, bitmap, stream) = assetDetail
+                    bitmap?.let {
+                        FullResWallpaperViewModel(bitmap, dimensions, stream, cropHintsInfo)
+                    }
+                }
+            }
+            .flowOn(bgDispatcher)
+    val subsamplingScaleImageViewModel: Flow<FullResWallpaperViewModel> =
+        fullResWallpaperViewModel.filterNotNull()
+    // TODO (b/315856338): cache wallpaper colors in preferences
+    private val storedWallpaperColors: Flow<WallpaperColors?> =
         staticWallpaperModel
             .map { wallpaperPreferences.getWallpaperColors(it.commonWallpaperData.id.uniqueId) }
-            .filterNotNull()
+            .distinctUntilChanged()
+    val wallpaperColors: Flow<WallpaperColorsModel> =
+        combine(storedWallpaperColors, subsamplingScaleImageViewModel, cropHints) {
+            storedColors,
+            wallpaperViewModel,
+            cropHints ->
+            WallpaperColorsModel.Loaded(
+                if (cropHints == null) {
+                    storedColors
+                        ?: interactor.getWallpaperColors(
+                            wallpaperViewModel.rawWallpaperBitmap,
+                            null
+                        )
+                } else {
+                    interactor.getWallpaperColors(wallpaperViewModel.rawWallpaperBitmap, cropHints)
+                }
+            )
+        }
 
-    fun updateCropHints(cropHints: Map<ScreenOrientation, Rect>) {
-        _cropHints.value = _cropHints.value?.plus(cropHints) ?: cropHints
+    /**
+     * Updates new cropHints per displaySize that's been confirmed by the user.
+     *
+     * That's when picker gets current cropHints from [WallpaperManager] or when user crops and
+     * confirms a crop.
+     */
+    fun updateCropHintsInfo(cropHintsInfo: Map<Point, FullPreviewCropModel>) {
+        val newInfo = this.cropHintsInfo.value?.plus(cropHintsInfo) ?: cropHintsInfo
+        this.cropHintsInfo.value = newInfo
+        fullPreviewCropModels.putAll(newInfo)
     }
 
     // TODO b/296288298 Create a util class for Bitmap and Asset
@@ -97,7 +171,16 @@
     private suspend fun Asset.decodeBitmap(dimensions: Point): Bitmap? =
         suspendCancellableCoroutine { k: CancellableContinuation<Bitmap?> ->
             val callback = Asset.BitmapReceiver { k.resumeWith(Result.success(it)) }
-            decodeBitmap(dimensions.x, dimensions.y, callback)
+            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
@@ -121,4 +204,23 @@
         }
         return colors
     }
+
+    class Factory
+    @Inject
+    constructor(
+        private val interactor: WallpaperPreviewInteractor,
+        @ApplicationContext private val context: Context,
+        private val wallpaperPreferences: WallpaperPreferences,
+        @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
+    ) {
+        fun create(viewModelScope: CoroutineScope): StaticWallpaperPreviewViewModel {
+            return StaticWallpaperPreviewViewModel(
+                interactor = interactor,
+                context = context,
+                wallpaperPreferences = wallpaperPreferences,
+                bgDispatcher = bgDispatcher,
+                viewModelScope = viewModelScope,
+            )
+        }
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewConfigViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewConfigViewModel.kt
index 03c5597..4e4707b 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewConfigViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewConfigViewModel.kt
@@ -16,7 +16,6 @@
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
 import android.graphics.Point
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
 import com.android.wallpaper.module.CustomizationSections.Screen
 
 /** Configuration for a wallpaper preview. */
@@ -27,7 +26,4 @@
 
     /** The display size the preview is based on. */
     val displaySize: Point,
-
-    /** The [ScreenOrientation] the preview is based on. */
-    val screenOrientation: ScreenOrientation,
 )
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 6ab61ff..3cd5286 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
@@ -15,53 +15,145 @@
  */
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
+import android.graphics.Point
+import android.graphics.Rect
+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.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel
+import com.android.wallpaper.module.CustomizationSections
 import com.android.wallpaper.module.CustomizationSections.Screen
+import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel
+import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
+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.WallpaperPreviewInteractor
+import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
 import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity
 import com.android.wallpaper.util.DisplayUtils
 import com.android.wallpaper.util.PreviewUtils
+import com.android.wallpaper.util.WallpaperConnection.WhichPreview
 import dagger.hilt.android.lifecycle.HiltViewModel
+import java.util.EnumSet
 import javax.inject.Inject
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.launch
 
 /** Top level [ViewModel] for [WallpaperPreviewActivity] and its fragments */
 @HiltViewModel
 class WallpaperPreviewViewModel
 @Inject
 constructor(
-    interactor: WallpaperPreviewInteractor,
-    val staticWallpaperPreviewViewModel: StaticWallpaperPreviewViewModel,
+    private val interactor: WallpaperPreviewInteractor,
+    staticWallpaperPreviewViewModelFactory: StaticWallpaperPreviewViewModel.Factory,
     val previewActionsViewModel: PreviewActionsViewModel,
     private val displayUtils: DisplayUtils,
     @HomeScreenPreviewUtils private val homePreviewUtils: PreviewUtils,
     @LockScreenPreviewUtils private val lockPreviewUtils: PreviewUtils,
 ) : ViewModel() {
 
+    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: Flow<WallpaperModel> = interactor.wallpaperModel
+    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
+            }
+        }
+
+    fun dismissTooltip() = interactor.dismissTooltip()
+
+    private val _whichPreview = MutableStateFlow<WhichPreview?>(null)
+    private val whichPreview: Flow<WhichPreview> = _whichPreview.asStateFlow().filterNotNull()
+
+    fun setWhichPreview(whichPreview: WhichPreview) {
+        _whichPreview.value = whichPreview
+    }
+
+    fun setCropHints(cropHints: Map<Point, Rect>) {
+        wallpaper.value?.let { model ->
+            if (model is StaticWallpaperModel && !model.isDownloadableWallpaper()) {
+                staticWallpaperPreviewViewModel.updateCropHintsInfo(
+                    cropHints.mapValues {
+                        FullPreviewCropModel(
+                            cropHint = it.value,
+                            cropSizeModel = null,
+                        )
+                    }
+                )
+            }
+        }
+    }
+
+    private val _wallpaperConnectionColors: MutableStateFlow<WallpaperColorsModel> =
+        MutableStateFlow(WallpaperColorsModel.Loading as WallpaperColorsModel).apply {
+            viewModelScope.launch {
+                delay(1000)
+                if (value == WallpaperColorsModel.Loading) {
+                    emit(WallpaperColorsModel.Loaded(null))
+                }
+            }
+        }
+    private val liveWallpaperColors: Flow<WallpaperColorsModel> =
+        wallpaper
+            .filter { it is LiveWallpaperModel }
+            .combine(_wallpaperConnectionColors) { _, wallpaperConnectionColors ->
+                wallpaperConnectionColors
+            }
+    val wallpaperColorsModel: Flow<WallpaperColorsModel> =
+        merge(liveWallpaperColors, staticWallpaperPreviewViewModel.wallpaperColors)
 
     // This is only used for the full screen wallpaper preview.
     private val fullWallpaperPreviewConfigViewModel:
         MutableStateFlow<WallpaperPreviewConfigViewModel?> =
         MutableStateFlow(null)
 
+    // This is only used for the small screen wallpaper preview.
+    val smallWallpaper: Flow<Pair<WallpaperModel, WhichPreview>> =
+        combine(wallpaper.filterNotNull(), whichPreview) { wallpaper, whichPreview ->
+            Pair(wallpaper, whichPreview)
+        }
+
     // This is only used for the full screen wallpaper preview.
-    val fullWallpaper: Flow<Pair<WallpaperModel, WallpaperPreviewConfigViewModel>> =
-        combine(wallpaper, fullWallpaperPreviewConfigViewModel.filterNotNull()) {
-            wallpaper,
-            previewViewModel ->
-            Pair(wallpaper, previewViewModel)
+    val fullWallpaper: Flow<FullWallpaperPreviewViewModel> =
+        combine(
+            wallpaper.filterNotNull(),
+            fullWallpaperPreviewConfigViewModel.filterNotNull(),
+            whichPreview,
+        ) { wallpaper, config, whichPreview ->
+            FullWallpaperPreviewViewModel(
+                wallpaper = wallpaper,
+                config = config,
+                allowUserCropping =
+                    wallpaper is StaticWallpaperModel && !wallpaper.isDownloadableWallpaper(),
+                whichPreview = whichPreview,
+            )
         }
 
     // This is only used for the full screen wallpaper preview.
@@ -73,21 +165,114 @@
     val fullWorkspacePreviewConfigViewModel: Flow<WorkspacePreviewConfigViewModel> =
         _fullWorkspacePreviewConfigViewModel.filterNotNull()
 
-    val onCropButtonClick: Flow<() -> Unit> =
-        combine(wallpaper, fullWallpaperPreviewConfigViewModel.filterNotNull()) {
+    val onCropButtonClick: Flow<(() -> Unit)?> =
+        combine(wallpaper, fullWallpaperPreviewConfigViewModel.filterNotNull()) { wallpaper, _ ->
+            if (wallpaper is StaticWallpaperModel && !wallpaper.isDownloadableWallpaper()) {
+                {
+                    staticWallpaperPreviewViewModel.run {
+                        updateCropHintsInfo(fullPreviewCropModels)
+                    }
+                }
+            } else {
+                null
+            }
+        }
+
+    // Set wallpaper button and set wallpaper dialog
+    val isSetWallpaperButtonVisible: Flow<Boolean> =
+        combine(
             wallpaper,
-            previewViewModel ->
+            staticWallpaperPreviewViewModel.fullResWallpaperViewModel,
+        ) { wallpaper, fullResWallpaperViewModel ->
+            wallpaper != null &&
+                !wallpaper.isDownloadableWallpaper() &&
+                !(wallpaper is StaticWallpaperModel && fullResWallpaperViewModel == null)
+        }
+    val onSetWallpaperButtonClicked: Flow<(() -> Unit)?> =
+        isSetWallpaperButtonVisible.map { visible ->
+            if (visible) {
+                { _showSetWallpaperDialog.value = true }
+            } else null
+        }
+
+    private val _showSetWallpaperDialog = MutableStateFlow(false)
+    val showSetWallpaperDialog = _showSetWallpaperDialog.asStateFlow()
+
+    private val _setWallpaperDialogSelectedScreens: MutableStateFlow<Set<Screen>> =
+        MutableStateFlow(EnumSet.allOf(Screen::class.java))
+    val setWallpaperDialogSelectedScreens: StateFlow<Set<Screen>> =
+        _setWallpaperDialogSelectedScreens.asStateFlow()
+
+    fun onSetWallpaperDialogScreenSelected(screen: Screen) {
+        val previousSelection = _setWallpaperDialogSelectedScreens.value
+        _setWallpaperDialogSelectedScreens.value =
+            if (previousSelection.contains(screen) && previousSelection.size > 1) {
+                previousSelection.minus(screen)
+            } else {
+                previousSelection.plus(screen)
+            }
+    }
+
+    private val _isSetWallpaperProgressBarVisible = MutableStateFlow(false)
+    val isSetWallpaperProgressBarVisible: Flow<Boolean> =
+        _isSetWallpaperProgressBarVisible.asStateFlow()
+
+    val setWallpaperDialogOnConfirmButtonClicked: Flow<suspend () -> Unit> =
+        combine(
+            wallpaper.filterNotNull(),
+            staticWallpaperPreviewViewModel.fullResWallpaperViewModel,
+            setWallpaperDialogSelectedScreens,
+        ) { wallpaper, fullResWallpaperViewModel, selectedScreens ->
             {
-                if (wallpaper is WallpaperModel.StaticWallpaperModel) {
-                    staticWallpaperPreviewViewModel.fullPreviewCrop?.let {
-                        staticWallpaperPreviewViewModel.updateCropHints(
-                            mapOf(previewViewModel.screenOrientation to it)
+                _isSetWallpaperProgressBarVisible.value = true
+                val destination = selectedScreens.getDestination()
+                _showSetWallpaperDialog.value = false
+                when (wallpaper) {
+                    is StaticWallpaperModel ->
+                        fullResWallpaperViewModel?.let {
+                            interactor.setStaticWallpaper(
+                                setWallpaperEntryPoint =
+                                    StyleEnums.SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
+                                destination = destination,
+                                wallpaperModel = wallpaper,
+                                inputStream = it.stream,
+                                bitmap = it.rawWallpaperBitmap,
+                                wallpaperSize = it.rawWallpaperSize,
+                                fullPreviewCropModels = it.fullPreviewCropModels,
+                            )
+                        }
+                    is LiveWallpaperModel -> {
+                        interactor.setLiveWallpaper(
+                            setWallpaperEntryPoint =
+                                StyleEnums.SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
+                            destination = destination,
+                            wallpaperModel = wallpaper,
                         )
                     }
                 }
             }
         }
 
+    private fun Set<Screen>.getDestination(): WallpaperDestination {
+        return if (containsAll(CustomizationSections.Screen.entries)) {
+            WallpaperDestination.BOTH
+        } else if (contains(Screen.HOME_SCREEN)) {
+            WallpaperDestination.HOME
+        } else if (contains(Screen.LOCK_SCREEN)) {
+            WallpaperDestination.LOCK
+        } else {
+            throw IllegalArgumentException("Unknown screens selected: $this")
+        }
+    }
+
+    fun dismissSetWallpaperDialog() {
+        _showSetWallpaperDialog.value = false
+    }
+
+    fun setWallpaperConnectionColors(wallpaperColors: WallpaperColorsModel) {
+        _wallpaperConnectionColors.value = wallpaperColors
+    }
+
     fun getWorkspacePreviewConfig(
         screen: Screen,
         foldableDisplay: FoldableDisplay?,
@@ -121,18 +306,24 @@
 
     fun onSmallPreviewClicked(
         screen: Screen,
-        orientation: ScreenOrientation,
         foldableDisplay: FoldableDisplay?,
     ) {
         fullWallpaperPreviewConfigViewModel.value =
-            getWallpaperPreviewConfig(screen, orientation, foldableDisplay)
+            getWallpaperPreviewConfig(screen, foldableDisplay)
         _fullWorkspacePreviewConfigViewModel.value =
             getWorkspacePreviewConfig(screen, foldableDisplay)
     }
 
+    fun setDefaultWallpaperPreviewConfigViewModel(displaySize: Point) {
+        fullWallpaperPreviewConfigViewModel.value =
+            WallpaperPreviewConfigViewModel(
+                Screen.HOME_SCREEN,
+                displaySize,
+            )
+    }
+
     private fun getWallpaperPreviewConfig(
         screen: Screen,
-        orientation: ScreenOrientation,
         foldableDisplay: FoldableDisplay?,
     ): WallpaperPreviewConfigViewModel {
         val displaySize =
@@ -150,7 +341,12 @@
         return WallpaperPreviewConfigViewModel(
             screen = screen,
             displaySize = displaySize,
-            screenOrientation = orientation,
         )
     }
+
+    companion object {
+        private fun WallpaperModel.isDownloadableWallpaper(): Boolean {
+            return this is StaticWallpaperModel && this.downloadableWallpaperData != null
+        }
+    }
 }
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/EffectFloatingSheetViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/EffectFloatingSheetViewModel.kt
new file mode 100644
index 0000000..3ff26d2
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/EffectFloatingSheetViewModel.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.viewmodel.floatingSheet
+
+import android.view.View
+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(
+    val myPhotosClickListener: View.OnClickListener,
+    val collapseFloatingSheetListener: View.OnClickListener,
+    val effectSwitchListener: WallpaperEffectsView2.EffectSwitchListener,
+    val effectDownloadClickListener: WallpaperEffectsView2.EffectDownloadClickListener,
+    val status: WallpaperEffectsView2.Status,
+    val resultCode: Int?,
+    val errorMessage: String?,
+    val title: String,
+    val effectType: EffectEnumInterface,
+    val effectTextRes: WallpaperEffectsView2.EffectTextRes,
+)
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/InfoFloatingSheetViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/InfoFloatingSheetViewModel.kt
deleted file mode 100644
index 29fa255..0000000
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/InfoFloatingSheetViewModel.kt
+++ /dev/null
@@ -1,40 +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.viewmodel.floatingSheet
-
-import com.android.wallpaper.model.wallpaper.WallpaperModel
-
-/** This data class represents the view data for the info floating sheet */
-data class InfoFloatingSheetViewModel(
-    val actionUrl: String?,
-    val attributions: List<String?>?,
-    val showMetadata: Boolean
-) {
-
-    constructor(
-        wallpaperModel: WallpaperModel
-    ) : this(
-        actionUrl = wallpaperModel.commonWallpaperData.exploreActionUrl,
-        attributions = wallpaperModel.commonWallpaperData.attributions,
-        showMetadata =
-            if (wallpaperModel is WallpaperModel.LiveWallpaperModel) {
-                wallpaperModel.liveWallpaperData.systemWallpaperInfo.showMetadataInPreview
-            } else {
-                true
-            }
-    )
-}
diff --git a/src/com/android/wallpaper/settings/data/repository/SecureSettingsRepository.kt b/src/com/android/wallpaper/settings/data/repository/SecureSettingsRepository.kt
deleted file mode 100644
index db56b67..0000000
--- a/src/com/android/wallpaper/settings/data/repository/SecureSettingsRepository.kt
+++ /dev/null
@@ -1,103 +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.settings.data.repository
-
-import android.content.ContentResolver
-import android.database.ContentObserver
-import android.provider.Settings
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.callbackFlow
-import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.withContext
-
-/** Defines interface for classes that can provide access to data from [Settings.Secure]. */
-interface SecureSettingsRepository {
-
-    /** Returns a [Flow] tracking the value of a setting as an [Int]. */
-    fun intSetting(
-        name: String,
-        defaultValue: Int = 0,
-    ): Flow<Int>
-
-    /** Updates the value of the setting with the given name. */
-    suspend fun set(
-        name: String,
-        value: Int,
-    )
-
-    suspend fun get(
-        name: String,
-        defaultValue: Int = 0,
-    ): Int
-}
-
-class SecureSettingsRepositoryImpl(
-    private val contentResolver: ContentResolver,
-    private val backgroundDispatcher: CoroutineDispatcher,
-) : SecureSettingsRepository {
-
-    override fun intSetting(
-        name: String,
-        defaultValue: Int,
-    ): Flow<Int> {
-        return callbackFlow {
-                val observer =
-                    object : ContentObserver(null) {
-                        override fun onChange(selfChange: Boolean) {
-                            trySend(Unit)
-                        }
-                    }
-
-                contentResolver.registerContentObserver(
-                    Settings.Secure.getUriFor(name),
-                    /* notifyForDescendants= */ false,
-                    observer,
-                )
-                send(Unit)
-
-                awaitClose { contentResolver.unregisterContentObserver(observer) }
-            }
-            .map { Settings.Secure.getInt(contentResolver, name, defaultValue) }
-            // The above work is done on the background thread (which is important for accessing
-            // settings through the content resolver).
-            .flowOn(backgroundDispatcher)
-    }
-
-    override suspend fun set(name: String, value: Int) {
-        withContext(backgroundDispatcher) {
-            Settings.Secure.putInt(
-                contentResolver,
-                name,
-                value,
-            )
-        }
-    }
-
-    override suspend fun get(name: String, defaultValue: Int): Int {
-        return withContext(backgroundDispatcher) {
-            Settings.Secure.getInt(
-                contentResolver,
-                name,
-                defaultValue,
-            )
-        }
-    }
-}
diff --git a/src/com/android/wallpaper/util/DiskBasedLogger.java b/src/com/android/wallpaper/util/DiskBasedLogger.java
deleted file mode 100755
index 350aaff..0000000
--- a/src/com/android/wallpaper/util/DiskBasedLogger.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2017 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 static java.nio.charset.StandardCharsets.UTF_8;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.io.BufferedReader;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Locale;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Logs messages to logcat and for debuggable build types ("eng" or "userdebug") also mirrors logs
- * to a disk-based log buffer.
- */
-public class DiskBasedLogger {
-
-    static final String LOGS_FILE_PATH = "logs.txt";
-    static final SimpleDateFormat DATE_FORMAT =
-            new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS z yyyy", Locale.US);
-
-    private static final String TEMP_LOGS_FILE_PATH = "temp_logs.txt";
-    private static final String TAG = "DiskBasedLogger";
-
-    /**
-     * POJO used to lock thread creation and file read/write operations.
-     */
-    private static final Object S_LOCK = new Object();
-
-    private static final long THREAD_TIMEOUT_MILLIS =
-            TimeUnit.MILLISECONDS.convert(2, TimeUnit.MINUTES);
-    private static Handler sHandler;
-    private static HandlerThread sLoggerThread;
-    private static final Runnable THREAD_CLEANUP_RUNNABLE = new Runnable() {
-        @Override
-        public void run() {
-            if (sLoggerThread != null && sLoggerThread.isAlive()) {
-
-                // HandlerThread#quitSafely was added in JB-MR2, so prefer to use that instead of #quit.
-                boolean isQuitSuccessful =
-                        Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
-                        ? sLoggerThread.quitSafely()
-                        : sLoggerThread.quit();
-
-                if (!isQuitSuccessful) {
-                    Log.e(TAG, "Unable to quit disk-based logger HandlerThread");
-                }
-
-                sLoggerThread = null;
-                sHandler = null;
-            }
-        }
-    };
-
-    /**
-     * Initializes and returns a new dedicated HandlerThread for reading and writing to the disk-based
-     * logs file.
-     */
-    private static void initializeLoggerThread() {
-        sLoggerThread = new HandlerThread("DiskBasedLoggerThread", Process.THREAD_PRIORITY_BACKGROUND);
-        sLoggerThread.start();
-    }
-
-    /**
-     * Returns a Handler that can post messages to the dedicated HandlerThread for reading and writing
-     * to the logs file on disk. Lazy-loads the HandlerThread if it doesn't already exist and delays
-     * its death by a timeout if the thread already exists.
-     */
-    private static Handler getLoggerThreadHandler() {
-        synchronized (S_LOCK) {
-            if (sLoggerThread == null) {
-                initializeLoggerThread();
-
-                // Create a new Handler tied to the new HandlerThread's Looper for processing disk I/O off
-                // the main thread. Starts with a default timeout to quit and remove references to the
-                // thread after a period of inactivity.
-                sHandler = new Handler(sLoggerThread.getLooper());
-            } else {
-                sHandler.removeCallbacks(THREAD_CLEANUP_RUNNABLE);
-            }
-
-            // Delay the logger thread's eventual death.
-            sHandler.postDelayed(THREAD_CLEANUP_RUNNABLE, THREAD_TIMEOUT_MILLIS);
-
-            return sHandler;
-        }
-    }
-
-    /**
-     * Logs an "error" level log to logcat based on the provided tag and message and also duplicates
-     * the log to a file-based log buffer if running on a "userdebug" or "eng" build.
-     */
-    public static void e(String tag, String msg, Context context) {
-        // Pass log tag and message through to logcat regardless of build type.
-        Log.e(tag, msg);
-
-        // Only mirror logs to disk-based log buffer if the build is debuggable.
-        if (!Build.TYPE.equals("eng") && !Build.TYPE.equals("userdebug")) {
-            return;
-        }
-
-        Handler handler = getLoggerThreadHandler();
-        if (handler == null) {
-            Log.e(TAG, "Something went wrong creating the logger thread handler, quitting this logging "
-                    + "operation");
-            return;
-        }
-
-        handler.post(() -> {
-            File logs = new File(context.getFilesDir(), LOGS_FILE_PATH);
-
-            // Construct a log message that we can parse later in order to clean up old logs.
-            String datetime = DATE_FORMAT.format(Calendar.getInstance().getTime());
-            String log = datetime + "/E " + tag + ": " + msg + "\n";
-
-            synchronized (S_LOCK) {
-                FileOutputStream outputStream;
-
-                try {
-                    outputStream = context.openFileOutput(logs.getName(), Context.MODE_APPEND);
-                    outputStream.write(log.getBytes(UTF_8));
-                    outputStream.close();
-                } catch (IOException e) {
-                    Log.e(TAG, "Unable to close output stream for disk-based log buffer", e);
-                }
-            }
-        });
-    }
-
-    /**
-     * Deletes logs in the disk-based log buffer older than 7 days.
-     */
-    public static void clearOldLogs(Context context) {
-        if (!Build.TYPE.equals("eng") && !Build.TYPE.equals("userdebug")) {
-            return;
-        }
-
-        Handler handler = getLoggerThreadHandler();
-        if (handler == null) {
-            Log.e(TAG, "Something went wrong creating the logger thread handler, quitting this logging "
-                    + "operation");
-            return;
-        }
-
-        handler.post(() -> {
-            // Check if the logs file exists first before trying to read from it.
-            File logsFile = new File(context.getFilesDir(), LOGS_FILE_PATH);
-            if (!logsFile.exists()) {
-                Log.w(TAG, "Disk-based log buffer doesn't exist, so there's nothing to clean up.");
-                return;
-            }
-
-            synchronized (S_LOCK) {
-                FileInputStream inputStream;
-                BufferedReader bufferedReader;
-
-                try {
-                    inputStream = context.openFileInput(LOGS_FILE_PATH);
-                    bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF_8));
-                } catch (IOException e) {
-                    Log.e(TAG, "IO exception opening a buffered reader for the existing logs file", e);
-                    return;
-                }
-
-                Date sevenDaysAgo = getSevenDaysAgo();
-
-                File tempLogsFile = new File(context.getFilesDir(), TEMP_LOGS_FILE_PATH);
-                FileOutputStream outputStream;
-
-                try {
-                    outputStream = context.openFileOutput(TEMP_LOGS_FILE_PATH, Context.MODE_APPEND);
-                } catch (IOException e) {
-                    Log.e(TAG, "Unable to close output stream for disk-based log buffer", e);
-                    return;
-                }
-
-                copyLogsNewerThanDate(bufferedReader, outputStream, sevenDaysAgo);
-
-                // Close streams to prevent resource leaks.
-                closeStream(inputStream, "couldn't close input stream for log file");
-                closeStream(outputStream, "couldn't close output stream for temp log file");
-
-                // Rename temp log file (if it exists--which is only when the logs file has logs newer than
-                // 7 days to begin with) to the final logs file.
-                if (tempLogsFile.exists() && !tempLogsFile.renameTo(logsFile)) {
-                    Log.e(TAG, "couldn't rename temp logs file to final logs file");
-                }
-            }
-        });
-    }
-
-    @Nullable
-    @VisibleForTesting
-  /* package */ static Handler getHandler() {
-        return sHandler;
-    }
-
-    /**
-     * Constructs and returns a {@link Date} object representing the time 7 days ago.
-     */
-    private static Date getSevenDaysAgo() {
-        Calendar sevenDaysAgoCalendar = Calendar.getInstance();
-        sevenDaysAgoCalendar.add(Calendar.DAY_OF_MONTH, -7);
-        return sevenDaysAgoCalendar.getTime();
-    }
-
-    /**
-     * Tries to close the provided Closeable stream and logs the error message if the stream couldn't
-     * be closed.
-     */
-    private static void closeStream(Closeable stream, String errorMessage) {
-        try {
-            stream.close();
-        } catch (IOException e) {
-            Log.e(TAG, errorMessage);
-        }
-    }
-
-    /**
-     * Copies all log lines newer than the supplied date from the provided {@link BufferedReader} to
-     * the provided {@OutputStream}.
-     * <p>
-     * The caller of this method is responsible for closing the output stream and input stream
-     * underlying the BufferedReader when all operations have finished.
-     */
-    private static void copyLogsNewerThanDate(BufferedReader reader, OutputStream outputStream,
-                                              Date date) {
-        try {
-            String line = reader.readLine();
-            while (line != null) {
-                // Get the date from the line string.
-                String datetime = line.split("/")[0];
-                Date logDate;
-                try {
-                    logDate = DATE_FORMAT.parse(datetime);
-                } catch (ParseException e) {
-                    Log.e(TAG, "Error parsing date from previous logs", e);
-                    return;
-                }
-
-                // Copy logs newer than the provided date into a temp log file.
-                if (logDate.after(date)) {
-                    outputStream.write(line.getBytes(UTF_8));
-                    outputStream.write("\n".getBytes(UTF_8));
-                }
-
-                line = reader.readLine();
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "IO exception while reading line from buffered reader", e);
-        }
-    }
-}
diff --git a/src/com/android/wallpaper/util/DisplayUtils.kt b/src/com/android/wallpaper/util/DisplayUtils.kt
index 6ea533b..fa1d879 100644
--- a/src/com/android/wallpaper/util/DisplayUtils.kt
+++ b/src/com/android/wallpaper/util/DisplayUtils.kt
@@ -86,6 +86,27 @@
     }
 
     /**
+     * This flag returns true if the display is:
+     * 1. a large screen device display, e.g. tablet
+     * 2. an unfolded display from a foldable device
+     *
+     * This flag returns false the display is:
+     * 1. a handheld device display
+     * 2. a folded display from a foldable device
+     */
+    fun isLargeScreenOrUnfoldedDisplay(activity: Activity): Boolean {
+        // Note that a foldable is a large screen device if the largest display is large screen.
+        // Ths flag is true if it is a large screen device, e.g. tablet, or a foldable device.
+        val isLargeScreenOrFoldable = isLargeScreenDevice()
+        // For a single display device, this flag is always true.
+        // For a multi-display device, it is only true when the current display is the largest
+        // display. For the case of foldable, it is true when the display is the unfolded one, and
+        // false when it is folded.
+        val isSingleDisplayOrUnfolded = isOnWallpaperDisplay(activity)
+        return isLargeScreenOrFoldable && isSingleDisplayOrUnfolded
+    }
+
+    /**
      * Returns true if this device's screen (or largest screen in case of multiple screen devices)
      * is considered a "Large screen"
      */
@@ -127,7 +148,7 @@
      */
     fun getSmallerDisplay(): Display {
         val internalDisplays = getInternalDisplays()
-        var largestDisplay = getWallpaperDisplay()
+        val largestDisplay = getWallpaperDisplay()
         val smallestDisplay = internalDisplays.firstOrNull() { it != largestDisplay }
         return smallestDisplay ?: largestDisplay
     }
@@ -147,4 +168,8 @@
         }
         return allDisplays.filter { it.type == Display.TYPE_INTERNAL }
     }
+
+    fun getInternalDisplaySizes(): List<Point> {
+        return getInternalDisplays().map { getRealSize(it) }
+    }
 }
diff --git a/src/com/android/wallpaper/util/SurfaceViewUtils.java b/src/com/android/wallpaper/util/SurfaceViewUtils.java
index 80dbfee..26bd026 100644
--- a/src/com/android/wallpaper/util/SurfaceViewUtils.java
+++ b/src/com/android/wallpaper/util/SurfaceViewUtils.java
@@ -31,6 +31,7 @@
     public static final String KEY_DISPLAY_ID = "display_id";
     private static final String KEY_SURFACE_PACKAGE = "surface_package";
     private static final String KEY_CALLBACK = "callback";
+    public static final String KEY_WALLPAPER_COLORS = "wallpaper_colors";
 
     /** Create a surface view request. */
     public static Bundle createSurfaceViewRequest(SurfaceView surfaceView) {
@@ -43,7 +44,10 @@
             @Nullable Bundle extras) {
         Bundle bundle = new Bundle();
         bundle.putBinder(KEY_HOST_TOKEN, surfaceView.getHostToken());
-        bundle.putInt(KEY_DISPLAY_ID, surfaceView.getDisplay().getDisplayId());
+        // TODO (b/305258307): Figure out why SurfaceView.getDisplay returns null in small preview
+        if (surfaceView.getDisplay() != null) {
+            bundle.putInt(KEY_DISPLAY_ID, surfaceView.getDisplay().getDisplayId());
+        }
         bundle.putInt(KEY_VIEW_WIDTH, surfaceView.getWidth());
         bundle.putInt(KEY_VIEW_HEIGHT, surfaceView.getHeight());
         if (extras != null) {
diff --git a/src/com/android/wallpaper/util/WallpaperCropUtils.java b/src/com/android/wallpaper/util/WallpaperCropUtils.java
index da44edc..2fcc2fd 100755
--- a/src/com/android/wallpaper/util/WallpaperCropUtils.java
+++ b/src/com/android/wallpaper/util/WallpaperCropUtils.java
@@ -24,6 +24,9 @@
 import android.os.Build.VERSION_CODES;
 import android.view.Display;
 
+import com.android.wallpaper.config.BaseFlags;
+import com.android.wallpaper.module.InjectorProvider;
+
 /**
  * Static utility methods for wallpaper cropping operations.
  */
@@ -191,11 +194,14 @@
     public static Rect calculateCropRect(Context context, float wallpaperZoom, Point wallpaperSize,
             Point defaultCropSurfaceSize, Point targetHostSize, int scrollX, int scrollY,
             boolean cropExtraWidth) {
+        BaseFlags flags = InjectorProvider.getInjector().getFlags();
+        boolean isMultiCropEnabled =
+                flags.isMultiCropPreviewUiEnabled() && 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);
-        Rect rect = new Rect();
-        rect.set(0, 0, scaledWallpaperWidth, scaledWallpaperHeight);
+        Rect scaledWallpaperRect = new Rect();
+        scaledWallpaperRect.set(0, 0, scaledWallpaperWidth, scaledWallpaperHeight);
 
         // Crop rect should start off as the visible screen and then include extra width and height
         // if available within wallpaper at the current zoom.
@@ -209,19 +215,27 @@
             // Try to increase size of screenRect to include extra width depending on the layout
             // direction.
             if (RtlUtils.isRtl(context)) {
-                cropRect.left = Math.max(cropRect.left - extraWidth, rect.left);
+                cropRect.left = Math.max(cropRect.left - extraWidth, scaledWallpaperRect.left);
             } else {
-                cropRect.right = Math.min(cropRect.right + extraWidth, rect.right);
+                cropRect.right = Math.min(cropRect.right + extraWidth, scaledWallpaperRect.right);
             }
         }
 
         // Try to increase the size of the cropRect to to include extra height.
         int availableExtraHeightTop = cropRect.top - Math.max(
-                rect.top,
+                scaledWallpaperRect.top,
                 cropRect.top - extraHeightTopAndBottom);
         int availableExtraHeightBottom = Math.min(
-                rect.bottom,
+                scaledWallpaperRect.bottom,
                 cropRect.bottom + extraHeightTopAndBottom) - cropRect.bottom;
+        if (isMultiCropEnabled) {
+            // availableExtraHeightBottom shouldn't be negative, but it could happen if wallpaper
+            // zoom < 1, in that case it should be zero. Safe guard availableExtraHeightTop as well.
+            // Looks like a bug, but we always have > 1 zoom for existing preview, so flag guard
+            // this block.
+            availableExtraHeightTop = Math.max(availableExtraHeightTop, 0);
+            availableExtraHeightBottom = Math.max(availableExtraHeightBottom, 0);
+        }
 
         int availableExtraHeightTopAndBottom =
                 Math.min(availableExtraHeightTop, availableExtraHeightBottom);
diff --git a/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt b/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt
index b5e2ae4..6245e93 100644
--- a/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt
+++ b/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt
@@ -21,8 +21,8 @@
 import com.android.wallpaper.model.ImageWallpaperInfo
 import com.android.wallpaper.model.LiveWallpaperInfo
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.StaticWallpaperData
-import com.android.wallpaper.model.wallpaper.WallpaperModel
+import com.android.wallpaper.picker.data.StaticWallpaperData
+import com.android.wallpaper.picker.data.WallpaperModel
 import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getCommonWallpaperData
 import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getCreativeWallpaperData
 import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getImageWallpaperData
@@ -45,7 +45,11 @@
         } else {
             WallpaperModel.StaticWallpaperModel(
                 commonWallpaperData = wallpaperInfo.getCommonWallpaperData(context),
-                staticWallpaperData = StaticWallpaperData(asset = wallpaperInfo.getAsset(context)),
+                staticWallpaperData =
+                    StaticWallpaperData(
+                        asset = wallpaperInfo.getAsset(context),
+                        cropHints = wallpaperInfo.wallpaperCropHints
+                    ),
                 imageWallpaperData =
                     (wallpaperInfo as? ImageWallpaperInfo)?.getImageWallpaperData(),
                 networkWallpaperData = null,
diff --git a/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt b/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
index 4c0927d..7bd24e2 100644
--- a/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
+++ b/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
@@ -25,14 +25,14 @@
 import com.android.wallpaper.model.ImageWallpaperInfo
 import com.android.wallpaper.model.LiveWallpaperInfo
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.ColorInfo
-import com.android.wallpaper.model.wallpaper.CommonWallpaperData
-import com.android.wallpaper.model.wallpaper.CreativeWallpaperData
-import com.android.wallpaper.model.wallpaper.Destination
-import com.android.wallpaper.model.wallpaper.ImageWallpaperData
-import com.android.wallpaper.model.wallpaper.LiveWallpaperData
-import com.android.wallpaper.model.wallpaper.WallpaperId
-import com.android.wallpaper.model.wallpaper.WallpaperModel
+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.Destination
+import com.android.wallpaper.picker.data.ImageWallpaperData
+import com.android.wallpaper.picker.data.LiveWallpaperData
+import com.android.wallpaper.picker.data.WallpaperId
+import com.android.wallpaper.picker.data.WallpaperModel
 
 /** This class creates an instance of [WallpaperModel] from a given [WallpaperInfo] object. */
 interface WallpaperModelFactory {
@@ -78,7 +78,10 @@
             val wallpaperId =
                 WallpaperId(
                     componentName = componentName,
-                    uniqueId = wallpaperId,
+                    uniqueId =
+                        if (this is ImageWallpaperInfo && getWallpaperId() == null)
+                            "${uri.hashCode()}"
+                        else wallpaperId,
                     // TODO(b/308800470): Figure out the use of collection ID
                     collectionId = getCollectionId(context) ?: UNKNOWN_COLLECTION_ID,
                 )
@@ -122,7 +125,7 @@
                 author = author ?: "",
                 description = description ?: "",
                 contentDescription = contentDescription,
-                isCurrent = isCurrent.toString() // Convert boolean to String
+                isCurrent = isCurrent,
             )
         }
 
diff --git a/src/com/android/wallpaper/util/converter/category/CategoryFactory.kt b/src/com/android/wallpaper/util/converter/category/CategoryFactory.kt
new file mode 100644
index 0000000..9c55656
--- /dev/null
+++ b/src/com/android/wallpaper/util/converter/category/CategoryFactory.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.converter.category
+
+import android.content.Context
+import android.util.Log
+import com.android.wallpaper.model.Category
+import com.android.wallpaper.model.ImageCategory
+import com.android.wallpaper.model.ThirdPartyAppCategory
+import com.android.wallpaper.model.WallpaperCategory
+import com.android.wallpaper.picker.data.category.CategoryModel
+import com.android.wallpaper.picker.data.category.CollectionCategoryData
+import com.android.wallpaper.picker.data.category.CommonCategoryData
+import com.android.wallpaper.picker.data.category.ImageCategoryData
+import com.android.wallpaper.picker.data.category.ThirdPartyCategoryData
+import com.android.wallpaper.util.converter.WallpaperModelFactory
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/** This class creates an instance of [CategoryModel] from an instance of [Category] object. */
+@Singleton
+class CategoryFactory
+@Inject
+constructor(private val wallpaperModelFactory: WallpaperModelFactory) {
+
+    fun getCategoryModel(context: Context, category: Category): CategoryModel {
+        return CategoryModel(
+            commonCategoryData = getCommonCategoryData(category),
+            collectionCategoryData =
+                (category as? WallpaperCategory)?.getCollectionsCategoryData(context),
+            imageCategoryData = getImageCategoryData(category, context),
+            thirdPartyCategoryData = getThirdPartyCategoryData(category)
+        )
+    }
+
+    private fun getCommonCategoryData(category: Category): CommonCategoryData {
+        return CommonCategoryData(
+            title = category.title,
+            collectionId = category.collectionId,
+            priority = category.priority
+        )
+    }
+
+    private fun WallpaperCategory.getCollectionsCategoryData(
+        context: Context
+    ): CollectionCategoryData? {
+        val wallpaperModelList =
+            wallpapers.map { wallpaperInfo ->
+                wallpaperModelFactory.getWallpaperModel(context, wallpaperInfo)
+            }
+        return CollectionCategoryData(
+            wallpaperModels = wallpaperModelList,
+            thumbAsset = thumbAsset,
+            featuredThumbnailIndex = featuredThumbnailIndex,
+            isSingleWallpaperCategory = isSingleWallpaperCategory,
+        )
+    }
+
+    private fun getImageCategoryData(category: Category, context: Context): ImageCategoryData? {
+        return if (category is ImageCategory) {
+            ImageCategoryData(overlayIconDrawable = category.getOverlayIcon(context))
+        } else {
+            Log.w(TAG, "Passed category is not of type ImageCategory")
+            null
+        }
+    }
+
+    private fun getThirdPartyCategoryData(category: Category): ThirdPartyCategoryData? {
+        return if (category is ThirdPartyAppCategory) {
+            ThirdPartyCategoryData(resolveInfo = category.resolveInfo)
+        } else {
+            Log.w(TAG, "Passed category is not of type ThirdPartyAppCategory")
+            null
+        }
+    }
+
+    companion object {
+        private const val TAG = "DefaultCategoryFactory"
+    }
+}
diff --git a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
index 69a8d06..fc344cb 100644
--- a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
+++ b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
@@ -1,8 +1,10 @@
 package com.android.wallpaper.util.wallpaperconnection
 
 import android.app.WallpaperInfo
+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.os.RemoteException
@@ -14,9 +16,12 @@
 import android.view.SurfaceControl
 import android.view.SurfaceView
 import android.view.View
+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
@@ -27,19 +32,35 @@
 
 object WallpaperConnectionUtils {
 
-    private val engineMap = mutableMapOf<String, Deferred<IWallpaperEngine>>()
+    const val TAG = "WallpaperConnectionUtils"
+
+    // engineMap and surfaceControlMap are used for disconnecting wallpaper services.
+    private val engineMap =
+        mutableMapOf<String, Deferred<Pair<ServiceConnection, WallpaperEngineConnection>>>()
+    // 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>>()
+
     private val mutex = Mutex()
 
     /** Only call this function when the surface view is attached. */
     suspend fun connect(
         context: Context,
         @MainDispatcher mainScope: CoroutineScope,
-        wallpaperInfo: WallpaperInfo,
+        wallpaperModel: LiveWallpaperModel,
+        whichPreview: WhichPreview,
         destinationFlag: Int,
         surfaceView: SurfaceView,
+        listener: WallpaperEngineConnection.WallpaperEngineConnectionListener? = null,
     ) {
-        val displayMetrics = getDisplayMetrics(surfaceView)
+        val wallpaperInfo = wallpaperModel.liveWallpaperData.systemWallpaperInfo
         val engineKey = wallpaperInfo.getKey()
+        val displayMetrics = getDisplayMetrics(surfaceView)
+
+        // 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 {
@@ -48,17 +69,74 @@
                         mainScope.async {
                             initEngine(
                                 context,
-                                wallpaperInfo.getWallpaperIntent(),
+                                wallpaperModel.getWallpaperServiceIntent(),
                                 displayMetrics,
                                 destinationFlag,
+                                whichPreview,
                                 surfaceView,
+                                listener,
                             )
                         }
                 }
             }
         }
 
-        engineMap[engineKey]?.await()?.let { mirrorAndReparent(it, surfaceView, displayMetrics) }
+        engineMap[engineKey]?.await()?.let { (_, engineConnection) ->
+            engineConnection.engine?.let {
+                mirrorAndReparent(engineKey, it, surfaceView, displayMetrics)
+            }
+        }
+    }
+
+    private fun LiveWallpaperModel.getWallpaperServiceIntent(): Intent {
+        return liveWallpaperData.systemWallpaperInfo.let {
+            Intent(WallpaperService.SERVICE_INTERFACE).setClassName(it.packageName, it.serviceName)
+        }
+    }
+
+    suspend fun disconnect(
+        context: Context,
+        wallpaperModel: LiveWallpaperModel,
+    ) {
+        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)
+                }
+            }
+        }
+
+        if (surfaceControlMap.containsKey(engineKey)) {
+            mutex.withLock {
+                surfaceControlMap.remove(engineKey)?.let { surfaceControls ->
+                    surfaceControls.forEach { it.release() }
+                    surfaceControls.clear()
+                }
+            }
+        }
+    }
+
+    /**
+     * Disconnect all live wallpaper services without releasing and clear surface controls. This
+     * function is called before binding static wallpapers. We have cases that user switch between
+     * live wan static wallpapers. When switching from live to static wallpapers, we need to
+     * disconnect the live wallpaper services to have the static wallpapers show up. But we can not
+     * clear the surface controls yet, because we will need them to render the live wallpapers again
+     * when switching from static to live wallpapers again.
+     */
+    suspend fun disconnectAllServices(context: Context) {
+        engineMap.keys.map { key ->
+            mutex.withLock {
+                engineMap.remove(key)?.await()?.let { (serviceConnection, engineConnection) ->
+                    engineConnection.engine?.destroy()
+                    engineConnection.removeListener()
+                    context.unbindService(serviceConnection)
+                }
+            }
+        }
     }
 
     private suspend fun initEngine(
@@ -66,33 +144,37 @@
         wallpaperIntent: Intent,
         displayMetrics: Point,
         destinationFlag: Int,
-        surfaceView: SurfaceView
-    ): IWallpaperEngine {
-        // Bind service
-        val wallpaperService = bindService(context, wallpaperIntent)
+        whichPreview: WhichPreview,
+        surfaceView: SurfaceView,
+        listener: WallpaperEngineConnection.WallpaperEngineConnectionListener?,
+    ): Pair<ServiceConnection, WallpaperEngineConnection> {
+        // Bind service and get service connection and wallpaper service
+        val (serviceConnection, wallpaperService) = bindWallpaperService(context, wallpaperIntent)
+        val engineConnection = WallpaperEngineConnection(displayMetrics, whichPreview)
+        listener?.let { engineConnection.setListener(it) }
         // Attach wallpaper connection to service and get wallpaper engine
-        return WallpaperEngineConnection(displayMetrics)
-            .getEngine(wallpaperService, destinationFlag, surfaceView)
-    }
-
-    private fun WallpaperInfo.getWallpaperIntent(): Intent {
-        return Intent(WallpaperService.SERVICE_INTERFACE)
-            .setClassName(this.packageName, this.serviceName)
+        engineConnection.getEngine(wallpaperService, destinationFlag, surfaceView)
+        return Pair(serviceConnection, engineConnection)
     }
 
     private fun WallpaperInfo.getKey(): String {
         return this.packageName.plus(":").plus(this.serviceName)
     }
 
-    private suspend fun bindService(context: Context, intent: Intent): IWallpaperService =
-        suspendCancellableCoroutine { k: CancellableContinuation<IWallpaperService> ->
+    private suspend fun bindWallpaperService(
+        context: Context,
+        intent: Intent
+    ): Pair<ServiceConnection, IWallpaperService> =
+        suspendCancellableCoroutine {
+            k: CancellableContinuation<Pair<ServiceConnection, IWallpaperService>> ->
             val serviceConnection =
                 WallpaperServiceConnection(
                     object : WallpaperServiceConnection.WallpaperServiceConnectionListener {
                         override fun onWallpaperServiceConnected(
+                            serviceConnection: ServiceConnection,
                             wallpaperService: IWallpaperService
                         ) {
-                            k.resumeWith(Result.success(wallpaperService))
+                            k.resumeWith(Result.success(Pair(serviceConnection, wallpaperService)))
                         }
                     }
                 )
@@ -109,7 +191,8 @@
             }
         }
 
-    private fun mirrorAndReparent(
+    private suspend fun mirrorAndReparent(
+        engineKey: String,
         engine: IWallpaperEngine,
         parentSurface: SurfaceView,
         displayMetrics: Point
@@ -119,19 +202,22 @@
         }
 
         try {
-            val parentSC = parentSurface.surfaceControl
-            val wallpaperMirrorSC = engine.mirrorSurfaceControl() ?: return
+            val parentSurfaceControl = parentSurface.surfaceControl
+            val wallpaperSurfaceControl = engine.mirrorSurfaceControl() ?: return
+            // Add surface control reference for later release when disconnected
+            addSurfaceControlReference(engineKey, wallpaperSurfaceControl)
+
             val values = getScale(parentSurface, displayMetrics)
             SurfaceControl.Transaction().use { t ->
                 t.setMatrix(
-                    wallpaperMirrorSC,
+                    wallpaperSurfaceControl,
                     values[Matrix.MSCALE_X],
                     values[Matrix.MSKEW_Y],
                     values[Matrix.MSKEW_X],
                     values[Matrix.MSCALE_Y]
                 )
-                t.reparent(wallpaperMirrorSC, parentSC)
-                t.show(wallpaperMirrorSC)
+                t.reparent(wallpaperSurfaceControl, parentSurfaceControl)
+                t.show(wallpaperSurfaceControl)
                 t.apply()
             }
         } catch (e: RemoteException) {
@@ -141,6 +227,23 @@
         }
     }
 
+    private suspend fun addSurfaceControlReference(
+        engineKey: String,
+        wallpaperSurfaceControl: SurfaceControl,
+    ) {
+        val surfaceControls = surfaceControlMap[engineKey]
+        if (surfaceControls == null) {
+            mutex.withLock {
+                surfaceControlMap[engineKey] =
+                    (surfaceControlMap[engineKey] ?: mutableListOf()).apply {
+                        add(wallpaperSurfaceControl)
+                    }
+            }
+        } else {
+            surfaceControls.add(wallpaperSurfaceControl)
+        }
+    }
+
     private fun getScale(parentSurface: SurfaceView, displayMetrics: Point): FloatArray {
         val metrics = Matrix()
         val values = FloatArray(9)
diff --git a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperEngineConnection.kt b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperEngineConnection.kt
index 4c70b6e..05f2c92 100644
--- a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperEngineConnection.kt
+++ b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperEngineConnection.kt
@@ -4,13 +4,18 @@
 import android.graphics.Point
 import android.graphics.Rect
 import android.graphics.RectF
+import android.os.Bundle
 import android.os.IBinder
 import android.os.ParcelFileDescriptor
+import android.os.RemoteException
 import android.service.wallpaper.IWallpaperConnection
 import android.service.wallpaper.IWallpaperEngine
 import android.service.wallpaper.IWallpaperService
+import android.util.Log
 import android.view.SurfaceView
 import android.view.WindowManager
+import com.android.wallpaper.util.WallpaperConnection
+import com.android.wallpaper.util.WallpaperConnection.WhichPreview
 import java.lang.reflect.InvocationTargetException
 import java.lang.reflect.Method
 import kotlinx.coroutines.CancellableContinuation
@@ -18,10 +23,12 @@
 
 class WallpaperEngineConnection(
     private val displayMetrics: Point,
+    private val whichPreview: WhichPreview,
 ) : IWallpaperConnection.Stub() {
 
     var engine: IWallpaperEngine? = null
     private var engineContinuation: CancellableContinuation<IWallpaperEngine>? = null
+    private var listener: WallpaperEngineConnectionListener? = null
 
     suspend fun getEngine(
         wallpaperService: IWallpaperService,
@@ -41,15 +48,34 @@
     }
 
     override fun attachEngine(engine: IWallpaperEngine?, displayId: Int) {
+        // Note that the engine in attachEngine callback is different from the one in engineShown
+        // callback, which is called after this attachEngine callback. We use the engine reference
+        // passed in attachEngine callback for WallpaperEngineConnection.
+        this.engine = engine
         engine?.apply {
+            setVisibility(true)
             resizePreview(Rect(0, 0, displayMetrics.x, displayMetrics.y))
             requestWallpaperColors()
         }
     }
 
     override fun engineShown(engine: IWallpaperEngine?) {
-        engine?.let { engineContinuation?.resumeWith(Result.success(it)) }
-        this.engine = engine
+        if (engine != null) {
+            dispatchWallpaperCommand(engine)
+            // Note that the engines from the attachEngine and engineShown callbacks are different
+            // and we only use the reference of engine from the attachEngine callback.
+            this.engine?.let { engineContinuation?.resumeWith(Result.success(it)) }
+        }
+    }
+
+    private fun dispatchWallpaperCommand(engine: IWallpaperEngine) {
+        val bundle = Bundle()
+        bundle.putInt(WHICH_PREVIEW, whichPreview.value)
+        try {
+            engine.dispatchWallpaperCommand(COMMAND_PREVIEW_INFO, 0, 0, 0, bundle)
+        } catch (e: RemoteException) {
+            Log.e(TAG, "Error dispatching wallpaper command: $whichPreview")
+        }
     }
 
     override fun onLocalWallpaperColorsChanged(
@@ -60,15 +86,28 @@
         // Do nothing intended.
     }
 
-    override fun onWallpaperColorsChanged(p0: WallpaperColors?, p1: Int) {
-        // Do nothing intended.
+    override fun onWallpaperColorsChanged(colors: WallpaperColors?, displayId: Int) {
+        listener?.onWallpaperColorsChanged(colors, displayId)
     }
 
-    override fun setWallpaper(p0: String?): ParcelFileDescriptor {
+    override fun setWallpaper(name: String?): ParcelFileDescriptor {
         TODO("Not yet implemented")
     }
 
+    fun setListener(listener: WallpaperEngineConnectionListener) {
+        this.listener = listener
+    }
+
+    fun removeListener() {
+        this.listener = null
+    }
+
     companion object {
+        const val TAG = "WallpaperEngineConnection"
+
+        const val COMMAND_PREVIEW_INFO = "android.wallpaper.previewinfo"
+        const val WHICH_PREVIEW = "which_preview"
+
         /**
          * Before Android U, [IWallpaperService.attach] has no input of destinationFlag. We do
          * method reflection to probe if the service from the external app is using a pre-U API;
@@ -126,4 +165,10 @@
             }
         }
     }
+
+    /** Interface to be notified of connect/disconnect events from [WallpaperConnection] */
+    interface WallpaperEngineConnectionListener {
+        /** Called after the wallpaper color is available or updated. */
+        fun onWallpaperColorsChanged(colors: WallpaperColors?, displayId: Int) {}
+    }
 }
diff --git a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperServiceConnection.kt b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperServiceConnection.kt
index 14f2bc8..1dab628 100644
--- a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperServiceConnection.kt
+++ b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperServiceConnection.kt
@@ -9,15 +9,15 @@
     ServiceConnection {
 
     override fun onServiceConnected(componentName: ComponentName?, service: IBinder?) {
-        listener.onWallpaperServiceConnected(IWallpaperService.Stub.asInterface(service))
+        listener.onWallpaperServiceConnected(this, IWallpaperService.Stub.asInterface(service))
     }
 
-    override fun onServiceDisconnected(componentName: ComponentName?) {
-        // TODO b/300979155(giolin): Recycle resources when onServiceDisconnected
-        // Do nothing intended
-    }
+    override fun onServiceDisconnected(componentName: ComponentName?) {}
 
     interface WallpaperServiceConnectionListener {
-        fun onWallpaperServiceConnected(wallpaperService: IWallpaperService)
+        fun onWallpaperServiceConnected(
+            serviceConnection: ServiceConnection,
+            wallpaperService: IWallpaperService,
+        )
     }
 }
diff --git a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperEffectsView2.kt b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperEffectsView2.kt
new file mode 100644
index 0000000..3dadf54
--- /dev/null
+++ b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperEffectsView2.kt
@@ -0,0 +1,279 @@
+/*
+ * 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.widget.floatingsheetcontent
+
+import android.content.Context
+import android.os.Handler
+import android.util.AttributeSet
+import android.view.View
+import android.widget.Button
+import android.widget.CompoundButton
+import android.widget.LinearLayout
+import android.widget.ProgressBar
+import android.widget.Switch
+import android.widget.TextView
+import androidx.annotation.VisibleForTesting
+import androidx.annotation.VisibleForTesting.Companion.PRIVATE
+import com.android.wallpaper.R
+import com.android.wallpaper.effects.EffectsController
+import com.android.wallpaper.effects.EffectsController.EffectEnumInterface
+
+/** A view for displaying wallpaper info. */
+class WallpaperEffectsView2(context: Context?, attrs: AttributeSet?) :
+    LinearLayout(context, attrs) {
+    private var effectSwitchListener: EffectSwitchListener? = null
+    private var downloadClickListener: EffectDownloadClickListener? = null
+    private var effectSwitch: Switch? = null
+
+    private var effectTextRes: EffectTextRes =
+        EffectTextRes(
+            effectTitle = "",
+            effectFailedTitle = "",
+            effectSubTitle = "",
+            retryInstruction = "",
+            noEffectInstruction = "",
+        )
+
+    @VisibleForTesting(otherwise = PRIVATE) var effectTitle: TextView? = null
+    @VisibleForTesting(otherwise = PRIVATE) var description: TextView? = null
+    @VisibleForTesting(otherwise = PRIVATE) var title: TextView? = null
+    @VisibleForTesting(otherwise = PRIVATE) var myPhotosButton: Button? = null
+    @VisibleForTesting(otherwise = PRIVATE) var continueButton: Button? = null
+    @VisibleForTesting(otherwise = PRIVATE) var tryAgainLaterButton: Button? = null
+    @VisibleForTesting(otherwise = PRIVATE) var switchLayout: View? = null
+    @VisibleForTesting(otherwise = PRIVATE) var container: View? = null
+    @VisibleForTesting(otherwise = PRIVATE) var downloadProgression: ProgressBar? = null
+    @VisibleForTesting(otherwise = PRIVATE) var downloadButton: Button? = null
+    @VisibleForTesting(otherwise = PRIVATE) var downloadButtonLayout: View? = null
+
+    data class EffectTextRes(
+        val effectTitle: String,
+        val effectFailedTitle: String,
+        val effectSubTitle: String,
+        val retryInstruction: String,
+        val noEffectInstruction: String,
+    )
+
+    enum class Status {
+        IDLE,
+        FAILED,
+        SUCCESS,
+        PROCESSING,
+        SHOW_DOWNLOAD_BUTTON,
+        DOWNLOADING,
+    }
+
+    /**
+     * Adds an Effects switch listener.
+     *
+     * @param listener The effects switch listener.
+     */
+    fun addEffectSwitchListener(listener: EffectSwitchListener?) {
+        effectSwitchListener = listener
+    }
+
+    /**
+     * Sets an Effects download button listener.
+     *
+     * @param listener The effects download button listener.
+     */
+    fun setEffectDownloadClickListener(listener: EffectDownloadClickListener?) {
+        downloadClickListener = listener
+    }
+
+    /**
+     * Updates the effect switch status.
+     *
+     * @param checked The status of the switch.
+     */
+    private fun updateEffectSwitchStatus(effect: EffectEnumInterface, checked: Boolean) {
+        effectSwitch?.isChecked = checked
+        effectSwitch?.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
+            switchChanged(effect, isChecked)
+        }
+    }
+
+    /**
+     * Sets click listener to myPhotos button.
+     *
+     * @param clickListener listener for myPhotos.
+     */
+    fun setMyPhotosClickListener(clickListener: OnClickListener?) {
+        myPhotosButton?.setOnClickListener(clickListener)
+    }
+
+    /**
+     * Sets click listener to 'try again' and 'continue' button.
+     *
+     * @param clickListener listener for myPhotos.
+     */
+    fun setCollapseFloatingSheetListener(clickListener: OnClickListener?) {
+        tryAgainLaterButton?.setOnClickListener(clickListener)
+        continueButton?.setOnClickListener(clickListener)
+    }
+
+    fun setEffectResources(effectTextRes: EffectTextRes) {
+        this.effectTextRes = effectTextRes
+        updateDefaultTextIfEmpty(effectTextRes)
+    }
+
+    private fun updateDefaultTextIfEmpty(effectTextRes: EffectTextRes) {
+        tryAgainLaterButton?.updateTextIfEmpty(effectTextRes.noEffectInstruction)
+        title?.updateTextIfEmpty(effectTextRes.effectTitle)
+        description?.updateTextIfEmpty(effectTextRes.effectSubTitle)
+    }
+
+    private fun TextView.updateTextIfEmpty(newText: String) {
+        this.text = this.text.ifEmpty { newText }
+    }
+
+    /**
+     * Updates the wallpaper effect view by status.
+     *
+     * @param status Last status code of wallpaper effect.
+     * @param resultCode the result code to handle different layouts.
+     * @param errorMessage the description of the sheet.
+     */
+    fun updateEffectStatus(
+        effect: EffectEnumInterface,
+        status: Status,
+        resultCode: Int?,
+        errorMessage: String?
+    ) {
+        when (status) {
+            Status.IDLE -> {
+                showBasicLayout()
+                updateEffectSwitchStatus(effect, /* checked = */ false)
+                effectSwitch?.isEnabled = true
+                switchLayout?.visibility = VISIBLE
+                container?.visibility = VISIBLE
+            }
+            Status.SUCCESS -> {
+                showBasicLayout()
+                updateEffectSwitchStatus(effect, /* checked = */ true)
+                Handler().postDelayed({ effectSwitch?.isEnabled = true }, 500)
+                switchLayout?.visibility = VISIBLE
+                container?.visibility = VISIBLE
+            }
+            Status.PROCESSING -> {
+                showBasicLayout()
+                updateEffectSwitchStatus(effect, /* checked = */ true)
+                effectSwitch?.isEnabled = false
+                switchLayout?.visibility = VISIBLE
+                container?.visibility = VISIBLE
+            }
+            Status.FAILED -> showFailedLayout(errorMessage)
+            Status.SHOW_DOWNLOAD_BUTTON -> {
+                description?.text = effectTextRes.effectSubTitle
+                switchLayout?.visibility = INVISIBLE
+                container?.visibility = INVISIBLE
+                downloadButtonLayout?.visibility = VISIBLE
+                downloadProgression?.visibility = INVISIBLE
+            }
+            Status.DOWNLOADING -> {
+                switchLayout?.visibility = INVISIBLE
+                container?.visibility = INVISIBLE
+                downloadButtonLayout?.visibility = INVISIBLE
+                downloadProgression?.visibility = VISIBLE
+            }
+        }
+        controlButtonByCode(
+            myPhotosButton,
+            resultCode,
+            EffectsController.RESULT_ERROR_TRY_ANOTHER_PHOTO
+        )
+        controlButtonByCode(
+            tryAgainLaterButton,
+            resultCode,
+            EffectsController.RESULT_ERROR_TRY_AGAIN_LATER
+        )
+        controlButtonByCode(continueButton, resultCode, EffectsController.RESULT_ERROR_CONTINUE)
+    }
+
+    private fun showBasicLayout() {
+        title?.text = effectTextRes.effectTitle
+        description?.text = effectTextRes.effectSubTitle
+        switchLayout?.visibility = VISIBLE
+        container?.visibility = INVISIBLE
+        downloadProgression?.visibility = INVISIBLE
+        downloadButtonLayout?.visibility = INVISIBLE
+        downloadProgression?.visibility = INVISIBLE
+    }
+
+    private fun showFailedLayout(errorMessage: String?) {
+        switchLayout?.visibility = INVISIBLE
+        title?.text = effectTextRes.effectFailedTitle
+        description?.text = errorMessage
+        container?.visibility = VISIBLE
+        downloadProgression?.visibility = INVISIBLE
+        downloadButtonLayout?.visibility = INVISIBLE
+        downloadProgression?.visibility = INVISIBLE
+    }
+
+    private fun controlButtonByCode(view: View?, resultCode: Int?, mask: Int) {
+        view?.visibility = if (resultCode == null || resultCode and mask == 0) GONE else VISIBLE
+    }
+
+    /**
+     * Updates the wallpaper effect switch title.
+     *
+     * @param title The title of the switch.
+     */
+    fun updateEffectTitle(title: String?) {
+        effectTitle!!.text = title
+    }
+
+    private fun switchChanged(effect: EffectEnumInterface, isChecked: Boolean) {
+        effectSwitchListener?.onEffectSwitchChanged(effect, isChecked)
+    }
+
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        effectSwitch = findViewById(R.id.wallpaper_effect_switch)
+        effectTitle = findViewById(R.id.wallpaper_effect_toggle_title)
+        title = findViewById(R.id.wallpaper_effects_title)
+        description = findViewById(R.id.wallpaper_effects_subtitle)
+        myPhotosButton = findViewById(R.id.open_my_photo_button)
+        tryAgainLaterButton = findViewById(R.id.try_again_button)
+        continueButton = findViewById(R.id.continue_button)
+        container = findViewById(R.id.buttons_container)
+        switchLayout = findViewById(R.id.wallpaper_effect_linear_layout)
+        switchLayout?.setOnClickListener {
+            if (effectSwitch?.isEnabled == true) effectSwitch?.toggle()
+        }
+        downloadButton = findViewById(R.id.download_model_button)
+        downloadButton?.setOnClickListener { downloadClickListener?.onEffectDownloadClick() }
+
+        downloadButtonLayout = findViewById(R.id.button_layout)
+        downloadProgression = findViewById(R.id.action_progress)
+    }
+
+    /** Implements a listener to know when an effect switch has been selected/unselected. */
+    interface EffectSwitchListener {
+        /**
+         * Called when one of the effect switches has change the checked value.
+         *
+         * @param effect The effect connected to the switch.
+         * @param isChecked if the switch is checked.
+         */
+        fun onEffectSwitchChanged(effect: EffectEnumInterface, isChecked: Boolean)
+    }
+
+    /** Implements a listener to know when an effect download button has been click. */
+    interface EffectDownloadClickListener {
+        fun onEffectDownloadClick()
+    }
+}
diff --git a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoContent.kt b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoContent.kt
index 980be4a..24319c7 100644
--- a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoContent.kt
+++ b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoContent.kt
@@ -62,7 +62,7 @@
 
     private fun onExploreClicked() {
         val injector = InjectorProvider.getInjector()
-        injector.getUserEventLogger(context.applicationContext).logWallpaperExploreButtonClicked()
+        injector.getUserEventLogger().logWallpaperExploreButtonClicked()
         context.startActivity(exploreIntent)
     }
 
diff --git a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoView.kt b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoView.kt
index 94ef978..fd6751b 100644
--- a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoView.kt
+++ b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperInfoView.kt
@@ -24,7 +24,6 @@
 import android.widget.TextView
 import com.android.wallpaper.R
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.InfoFloatingSheetViewModel
 import java.util.concurrent.Executors
 
 /** A view for displaying wallpaper info. */
@@ -60,22 +59,6 @@
         )
     }
 
-    fun populateWallpaperInfo(
-        infoFloatingSheetViewModel: InfoFloatingSheetViewModel,
-        actionLabel: CharSequence?,
-        shouldShowExploreButton: Boolean,
-        exploreButtonClickListener: OnClickListener?,
-    ) {
-
-        loadWallpaperInfoData(
-            infoFloatingSheetViewModel.attributions,
-            actionLabel,
-            shouldShowExploreButton,
-            exploreButtonClickListener,
-            infoFloatingSheetViewModel.showMetadata
-        )
-    }
-
     private fun loadWallpaperInfoData(
         attributions: List<String?>?,
         actionLabel: CharSequence?,
diff --git a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperModelInfoContent.kt b/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperModelInfoContent.kt
deleted file mode 100644
index 3bc4307..0000000
--- a/src/com/android/wallpaper/widget/floatingsheetcontent/WallpaperModelInfoContent.kt
+++ /dev/null
@@ -1,88 +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.widget.floatingsheetcontent
-
-import android.content.Context
-import android.content.Intent
-import com.android.wallpaper.R
-import com.android.wallpaper.module.InjectorProvider
-import com.android.wallpaper.picker.WallpaperInfoHelper
-import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.InfoFloatingSheetViewModel
-
-/**
- * This class implements the bottom sheet which holds the wallpaper information for the selected
- * wallpaper
- */
-// TODO(b/310742193): implement this bottom sheet with the modern architecture
-class WallpaperModelInfoContent(
-    private var context: Context,
-    private val infoFloatingSheetViewModel: InfoFloatingSheetViewModel?
-) : FloatingSheetContent<WallpaperInfoView>(context) {
-
-    private var exploreIntent: Intent? = null
-    private var actionLabel: CharSequence? = null
-    private var wallpaperInfoView: WallpaperInfoView? = null
-
-    override val viewId: Int
-        get() = R.layout.floating_sheet_wallpaper_info_view
-
-    /** Gets called when the content view is created or recreated by [FloatingSheetContent] */
-    override fun onViewCreated(view: WallpaperInfoView) {
-        wallpaperInfoView = view
-        context = view.context
-        initializeWallpaperContent()
-    }
-
-    private fun initializeWallpaperContent() {
-        if (infoFloatingSheetViewModel == null) {
-            return
-        }
-        if (actionLabel == null) {
-            setUpExploreIntentAndLabel { populateWallpaperInfo(wallpaperInfoView) }
-        } else {
-            populateWallpaperInfo(wallpaperInfoView)
-        }
-    }
-
-    private fun setUpExploreIntentAndLabel(callback: Runnable?) {
-        WallpaperInfoHelper.loadExploreIntent(context, infoFloatingSheetViewModel?.actionUrl) {
-            actionLabel: CharSequence?,
-            exploreIntent: Intent? ->
-            this.actionLabel = actionLabel
-            this.exploreIntent = exploreIntent
-            callback?.run()
-        }
-    }
-
-    private fun onExploreClicked() {
-        val injector = InjectorProvider.getInjector()
-        injector.getUserEventLogger(context.applicationContext).logWallpaperExploreButtonClicked()
-        context.startActivity(exploreIntent)
-    }
-
-    private fun populateWallpaperInfo(view: WallpaperInfoView?) {
-        view?.let {
-            it.populateWallpaperInfo(
-                infoFloatingSheetViewModel!!,
-                actionLabel,
-                WallpaperInfoHelper.shouldShowExploreButton(context, exploreIntent)
-            ) {
-                onExploreClicked()
-            }
-        }
-    }
-}
diff --git a/src_override/com/android/wallpaper/module/AppModule.kt b/src_override/com/android/wallpaper/module/AppModule.kt
index f992b53..6cd5e4d 100644
--- a/src_override/com/android/wallpaper/module/AppModule.kt
+++ b/src_override/com/android/wallpaper/module/AppModule.kt
@@ -18,6 +18,8 @@
 import android.content.Context
 import com.android.wallpaper.module.logging.NoOpUserEventLogger
 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.util.converter.DefaultWallpaperModelFactory
 import com.android.wallpaper.util.converter.WallpaperModelFactory
 import dagger.Binds
@@ -39,6 +41,12 @@
         impl: DefaultWallpaperModelFactory
     ): WallpaperModelFactory
 
+    @Binds
+    @Singleton
+    abstract fun bindLiveWallpaperDownloader(
+        impl: DefaultLiveWallpaperDownloader
+    ): LiveWallpaperDownloader
+
     companion object {
         @Provides
         @Singleton
diff --git a/src_override/com/android/wallpaper/picker/di/modules/EffectsModule.kt b/src_override/com/android/wallpaper/picker/di/modules/EffectsModule.kt
new file mode 100644
index 0000000..f49a273
--- /dev/null
+++ b/src_override/com/android/wallpaper/picker/di/modules/EffectsModule.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.di.modules
+
+import com.android.wallpaper.effects.DefaultEffectsController
+import com.android.wallpaper.effects.EffectsController
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+/** This class provides the singleton scoped effects controller for wallpaper picker. */
+@InstallIn(SingletonComponent::class)
+@Module
+internal abstract class EffectsModule {
+
+    @Binds
+    @Singleton
+    abstract fun bindEffectsController(impl: DefaultEffectsController): EffectsController
+}
diff --git a/tests/Android.bp b/tests/Android.bp
index 9c681da..1004eae 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -17,6 +17,7 @@
 // Build rule for WallpaperPicker2 tests
 //
 package {
+    default_team: "trendy_team_customization_picker",
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
@@ -41,7 +42,6 @@
         ":WallpaperPicker2Tests_srcs",
         "module/src/com/android/wallpaper/TestModule.kt",
     ],
-    exclude_srcs: [":WallpaperPicker2_src_prod"],
     static_libs: [
         "WallpaperPicker2TestLib",
         "WallpaperPicker2TestRunner",
@@ -58,6 +58,7 @@
         "junit",
         "kotlinx_coroutines_test",
         "truth",
+        "flag-junit",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index d087cbb..68d3caa 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -23,16 +23,14 @@
 android_library {
     name: "WallpaperPicker2TestLib",
 
-    defaults: ["WallpaperPicker2_common_defaults"],
     srcs: [
         "src/**/*.java",
         "src/**/*.kt",
     ],
     static_libs: [
+        "WallpaperPicker2Lib",
         "androidx.annotation_annotation",
         "kotlinx_coroutines_test",
         "truth",
     ],
-
-    platform_apis: true,
 }
diff --git a/tests/common/src/com/android/wallpaper/testing/FakeSecureSettingsRepository.kt b/tests/common/src/com/android/wallpaper/testing/FakeSecureSettingsRepository.kt
index 7855a36..325f9c9 100644
--- a/tests/common/src/com/android/wallpaper/testing/FakeSecureSettingsRepository.kt
+++ b/tests/common/src/com/android/wallpaper/testing/FakeSecureSettingsRepository.kt
@@ -17,7 +17,7 @@
 
 package com.android.wallpaper.testing
 
-import com.android.wallpaper.settings.data.repository.SecureSettingsRepository
+import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.map
@@ -30,11 +30,15 @@
         return settings.map { it.getOrDefault(name, defaultValue.toString()) }.map { it.toInt() }
     }
 
-    override suspend fun set(name: String, value: Int) {
+    override suspend fun setInt(name: String, value: Int) {
         settings.value = settings.value.toMutableMap().apply { this[name] = value.toString() }
     }
 
-    override suspend fun get(name: String, defaultValue: Int): Int {
+    override suspend fun getInt(name: String, defaultValue: Int): Int {
         return settings.value[name]?.toInt() ?: defaultValue
     }
+
+    override suspend fun getString(name: String): String? {
+        return settings.value[name]
+    }
 }
diff --git a/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt b/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt
index 1daa9c5..58d83c6 100644
--- a/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt
+++ b/tests/common/src/com/android/wallpaper/testing/FakeWallpaperClient.kt
@@ -17,14 +17,18 @@
 
 package com.android.wallpaper.testing
 
+import android.app.WallpaperColors
 import android.graphics.Bitmap
+import android.graphics.Point
 import android.graphics.Rect
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel.StaticWallpaperModel
 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
 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 kotlin.math.min
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -85,9 +89,18 @@
         setWallpaperEntryPoint: Int,
         destination: WallpaperDestination,
         wallpaperModel: StaticWallpaperModel,
+        inputStream: InputStream?,
         bitmap: Bitmap,
-        cropHints: Map<ScreenOrientation, Rect>,
-        onDone: () -> Unit
+        wallpaperSize: Point,
+        fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
+    ) {
+        TODO("Not yet implemented")
+    }
+
+    override suspend fun setLiveWallpaper(
+        setWallpaperEntryPoint: Int,
+        destination: WallpaperDestination,
+        wallpaperModel: LiveWallpaperModel,
     ) {
         TODO("Not yet implemented")
     }
@@ -126,6 +139,17 @@
         return true
     }
 
+    override fun getCurrentCropHints(displaySizes: List<Point>, which: Int): Map<Point, Rect>? {
+        return emptyMap()
+    }
+
+    override suspend fun getWallpaperColors(
+        bitmap: Bitmap,
+        cropHints: Map<Point, Rect>?
+    ): WallpaperColors? {
+        return null
+    }
+
     companion object {
         val INITIAL_RECENT_WALLPAPERS =
             listOf(
diff --git a/tests/common/src/com/android/wallpaper/testing/TestInjector.kt b/tests/common/src/com/android/wallpaper/testing/TestInjector.kt
index 704fa68..6e1321d 100644
--- a/tests/common/src/com/android/wallpaper/testing/TestInjector.kt
+++ b/tests/common/src/com/android/wallpaper/testing/TestInjector.kt
@@ -23,6 +23,7 @@
 import androidx.activity.ComponentActivity
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.LifecycleOwner
+import com.android.customization.model.color.DefaultWallpaperColorResources
 import com.android.customization.model.color.WallpaperColorResources
 import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
 import com.android.wallpaper.config.BaseFlags
@@ -209,7 +210,7 @@
         return systemFeatureChecker ?: TestSystemFeatureChecker().also { systemFeatureChecker = it }
     }
 
-    override fun getUserEventLogger(context: Context): UserEventLogger {
+    override fun getUserEventLogger(): UserEventLogger {
         return userEventLogger
     }
 
@@ -274,7 +275,7 @@
                     repository =
                         WallpaperRepository(
                             scope = getApplicationCoroutineScope(),
-                            client = getWallpaperClient(),
+                            client = getWallpaperClient(context),
                             wallpaperPreferences = getPreferences(context = context),
                             backgroundDispatcher = Dispatchers.IO,
                         ),
@@ -295,7 +296,7 @@
         wallpaperColors: WallpaperColors,
         context: Context
     ): WallpaperColorResources {
-        return WallpaperColorResources(wallpaperColors)
+        return DefaultWallpaperColorResources(wallpaperColors)
     }
 
     override fun getWallpaperColorsRepository(): WallpaperColorsRepository {
@@ -325,7 +326,7 @@
             }
     }
 
-    fun getWallpaperClient(): FakeWallpaperClient {
+    override fun getWallpaperClient(context: Context): FakeWallpaperClient {
         return wallpaperClient ?: FakeWallpaperClient().also { wallpaperClient = it }
     }
 
diff --git a/tests/common/src/com/android/wallpaper/testing/TestStaticWallpaperInfo.java b/tests/common/src/com/android/wallpaper/testing/TestStaticWallpaperInfo.java
index 9a040dc..28ef6d5 100644
--- a/tests/common/src/com/android/wallpaper/testing/TestStaticWallpaperInfo.java
+++ b/tests/common/src/com/android/wallpaper/testing/TestStaticWallpaperInfo.java
@@ -33,6 +33,7 @@
  */
 public class TestStaticWallpaperInfo extends WallpaperInfo {
     public static final int COLOR_DEFAULT = 0xff000000;
+    public static final int COLOR_2 = 0xffff0000;
     public static final Parcelable.Creator<TestStaticWallpaperInfo> CREATOR =
             new Parcelable.Creator<TestStaticWallpaperInfo>() {
                 @Override
diff --git a/tests/common/src/com/android/wallpaper/testing/TestWallpaperPersister.java b/tests/common/src/com/android/wallpaper/testing/TestWallpaperPersister.java
index 5c68366..7d36852 100644
--- a/tests/common/src/com/android/wallpaper/testing/TestWallpaperPersister.java
+++ b/tests/common/src/com/android/wallpaper/testing/TestWallpaperPersister.java
@@ -17,12 +17,14 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Point;
 import android.graphics.Rect;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.model.StaticWallpaperMetadata;
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata;
 import com.android.wallpaper.model.WallpaperInfo;
 import com.android.wallpaper.module.InjectorProvider;
 import com.android.wallpaper.module.WallpaperChangedNotifier;
@@ -31,6 +33,7 @@
 
 import java.io.InputStream;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Test double for {@link WallpaperPersister}.
@@ -43,6 +46,7 @@
     private Bitmap mCurrentHomeWallpaper;
     private Bitmap mCurrentLockWallpaper;
     private Bitmap mPendingHomeWallpaper;
+
     private Bitmap mPendingLockWallpaper;
     private List<String> mHomeAttributions;
     private String mHomeActionUrl;
@@ -53,8 +57,8 @@
     private Rect mCropRect;
     private float mScale;
     private WallpaperInfo mWallpaperInfo;
-    private StaticWallpaperMetadata mHomeStaticWallpaperMetadata;
-    private StaticWallpaperMetadata mLockStaticWallpaperMetadata;
+    private StaticWallpaperPrefMetadata mHomeStaticWallpaperPrefMetadata;
+    private StaticWallpaperPrefMetadata mLockStaticWallpaperPrefMetadata;
 
     public TestWallpaperPersister(Context appContext) {
         mAppContext = appContext;
@@ -212,13 +216,13 @@
 
     @Override
     public boolean saveStaticWallpaperToPreferences(int destination,
-            StaticWallpaperMetadata metadata) {
+            StaticWallpaperPrefMetadata metadata) {
         if (destination == DEST_HOME_SCREEN || destination == DEST_BOTH) {
-            mHomeStaticWallpaperMetadata = metadata;
+            mHomeStaticWallpaperPrefMetadata = metadata;
         }
 
         if (destination == DEST_LOCK_SCREEN || destination == DEST_BOTH) {
-            mLockStaticWallpaperMetadata = metadata;
+            mLockStaticWallpaperPrefMetadata = metadata;
         }
         return true;
     }
@@ -239,4 +243,10 @@
             boolean allowBackup, int whichWallpaper) {
         return 1;
     }
+
+    @Override
+    public int setStreamWithCropsToWallpaperManager(InputStream inputStream,
+            @NonNull Map<Point, Rect> cropHints, boolean allowBackup, int whichWallpaper) {
+        return 1;
+    }
 }
diff --git a/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt b/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt
index d82c554..e7480cf 100644
--- a/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt
+++ b/tests/common/src/com/android/wallpaper/testing/TestWallpaperPreferences.kt
@@ -18,19 +18,19 @@
 import android.app.WallpaperColors
 import android.graphics.Bitmap
 import android.graphics.Color
+import android.graphics.Point
 import android.graphics.Rect
 import com.android.wallpaper.model.LiveWallpaperInfo
-import com.android.wallpaper.model.StaticWallpaperMetadata
+import com.android.wallpaper.model.LiveWallpaperPrefMetadata
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata
 import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.ScreenOrientation
-import com.android.wallpaper.model.wallpaper.WallpaperModel
 import com.android.wallpaper.module.WallpaperPersister
 import com.android.wallpaper.module.WallpaperPreferences
 import com.android.wallpaper.module.WallpaperPreferences.PendingDailyWallpaperUpdateStatus
 import com.android.wallpaper.module.WallpaperPreferences.PendingWallpaperSetStatus
 import com.android.wallpaper.module.WallpaperPreferences.PresentationMode
 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
-import com.google.common.collect.ImmutableMap
+import com.android.wallpaper.picker.data.WallpaperModel
 import java.text.SimpleDateFormat
 import java.util.Calendar
 import java.util.Locale
@@ -78,11 +78,13 @@
     private var mNumDaysDailyRotationNotAttempted = 0
     private var mHomeWallpaperEffects: String? = null
     private var mLockWallpaperEffects: String? = null
-    private var mHomeStaticWallpaperMetadata: StaticWallpaperMetadata? = null
-    private var mLockStaticWallpaperMetadata: StaticWallpaperMetadata? = null
+    private var mHomeStaticWallpaperPrefMetadata: StaticWallpaperPrefMetadata? = null
+    private var mLockStaticWallpaperPrefMetadata: StaticWallpaperPrefMetadata? = null
+    private var mHomeLiveWallpaperPrefMetadata: LiveWallpaperPrefMetadata? = null
+    private var mLockLiveWallpaperPrefMetadata: LiveWallpaperPrefMetadata? = null
     private val mWallStoredColor: HashMap<String, String> = HashMap()
 
-    private val wallpaperCropHints: MutableMap<ScreenOrientation, Rect?>
+    private var hasPreviewTooltipBeenShown = true
 
     init {
         wallpaperPresentationMode = WallpaperPreferences.PRESENTATION_MODE_STATIC
@@ -93,7 +95,6 @@
         lastDailyLogTimestamp = -1
         lastDailyWallpaperRotationStatus = -1
         mPendingWallpaperSetStatus = WallpaperPreferences.WALLPAPER_SET_NOT_PENDING
-        wallpaperCropHints = mutableMapOf()
     }
 
     override fun getWallpaperPresentationMode(): Int {
@@ -136,8 +137,12 @@
         homeWallpaperManagerId = 0
     }
 
-    override fun setHomeStaticImageWallpaperMetadata(metadata: StaticWallpaperMetadata) {
-        mHomeStaticWallpaperMetadata = metadata
+    override fun setHomeStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata) {
+        mHomeStaticWallpaperPrefMetadata = metadata
+    }
+
+    override fun setHomeLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata) {
+        mHomeLiveWallpaperPrefMetadata = metadata
     }
 
     override fun getHomeWallpaperHashCode(): Long {
@@ -220,8 +225,12 @@
         lockWallpaperManagerId = 0
     }
 
-    override fun setLockStaticImageWallpaperMetadata(metadata: StaticWallpaperMetadata) {
-        mLockStaticWallpaperMetadata = metadata
+    override fun setLockStaticImageWallpaperMetadata(metadata: StaticWallpaperPrefMetadata) {
+        mLockStaticWallpaperPrefMetadata = metadata
+    }
+
+    override fun setLockLiveWallpaperMetadata(metadata: LiveWallpaperPrefMetadata) {
+        mLockLiveWallpaperPrefMetadata = metadata
     }
 
     override fun getLockWallpaperHashCode(): Long {
@@ -468,15 +477,20 @@
         destination: WallpaperDestination,
         wallpaperModel: WallpaperModel.StaticWallpaperModel,
         bitmap: Bitmap,
-        cropHints: Map<ScreenOrientation, Rect?>
+        cropHints: Map<Point, Rect>?,
     ) {}
 
-    override fun getWallpaperCropHints(): Map<ScreenOrientation, Rect?> {
-        return ImmutableMap.copyOf(wallpaperCropHints)
+    override suspend fun addLiveWallpaperToRecentWallpapers(
+        destination: WallpaperDestination,
+        wallpaperModel: WallpaperModel.LiveWallpaperModel
+    ) {}
+
+    override fun setHasPreviewTooltipBeenShown(hasTooltipBeenShown: Boolean) {
+        this.hasPreviewTooltipBeenShown = hasTooltipBeenShown
     }
 
-    override fun storeWallpaperCropHints(cropHints: Map<ScreenOrientation, Rect?>) {
-        wallpaperCropHints.putAll(cropHints)
+    override fun getHasPreviewTooltipBeenShown(): Boolean {
+        return hasPreviewTooltipBeenShown
     }
 
     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
new file mode 100644
index 0000000..4ec057f
--- /dev/null
+++ b/tests/common/src/com/android/wallpaper/testing/WallpaperModelUtils.kt
@@ -0,0 +1,138 @@
+/*
+ * 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.testing
+
+import android.app.WallpaperColors
+import android.app.WallpaperInfo
+import android.content.ComponentName
+import android.graphics.Color
+import android.net.Uri
+import com.android.wallpaper.asset.Asset
+import com.android.wallpaper.picker.data.ColorInfo
+import com.android.wallpaper.picker.data.CommonWallpaperData
+import com.android.wallpaper.picker.data.Destination
+import com.android.wallpaper.picker.data.ImageWallpaperData
+import com.android.wallpaper.picker.data.LiveWallpaperData
+import com.android.wallpaper.picker.data.StaticWallpaperData
+import com.android.wallpaper.picker.data.WallpaperId
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.util.converter.WallpaperModelFactory
+
+class WallpaperModelUtils {
+    companion object {
+        const val DEFAULT_PLACEHOLDER_COLOR = 1200
+        const val DEFAULT_ACTION_URL = "http://www.bogus.com"
+        val DEFAULT_COLORS =
+            WallpaperColors(
+                Color.valueOf(Color.RED),
+                Color.valueOf(Color.GREEN),
+                Color.valueOf(Color.BLUE)
+            )
+        val DEFAULT_ASSET = TestAsset(TestStaticWallpaperInfo.COLOR_DEFAULT, false)
+        const val DEFAULT_GROUP_NAME = "group name"
+
+        fun getStaticWallpaperModel(
+            wallpaperId: String,
+            collectionId: String,
+            placeholderColor: Int = DEFAULT_PLACEHOLDER_COLOR,
+            attribution: List<String>? = emptyList(),
+            actionUrl: String? = DEFAULT_ACTION_URL,
+            colors: WallpaperColors = DEFAULT_COLORS,
+            asset: Asset = DEFAULT_ASSET,
+        ): WallpaperModel.StaticWallpaperModel {
+            return WallpaperModel.StaticWallpaperModel(
+                commonWallpaperData =
+                    CommonWallpaperData(
+                        id =
+                            WallpaperId(
+                                ComponentName(
+                                    WallpaperModelFactory.STATIC_WALLPAPER_PACKAGE,
+                                    WallpaperModelFactory.STATIC_WALLPAPER_CLASS
+                                ),
+                                wallpaperId,
+                                collectionId,
+                            ),
+                        title = null,
+                        attributions = attribution,
+                        exploreActionUrl = actionUrl,
+                        thumbAsset = asset,
+                        placeholderColorInfo =
+                            ColorInfo(
+                                colors,
+                                placeholderColor,
+                            ),
+                        destination = Destination.NOT_APPLIED,
+                    ),
+                staticWallpaperData =
+                    StaticWallpaperData(
+                        asset,
+                        emptyMap(),
+                    ),
+                imageWallpaperData = ImageWallpaperData(Uri.EMPTY),
+                networkWallpaperData = null,
+                downloadableWallpaperData = null,
+            )
+        }
+
+        fun getLiveWallpaperModel(
+            wallpaperId: String,
+            collectionId: String,
+            placeholderColor: Int = DEFAULT_PLACEHOLDER_COLOR,
+            attribution: List<String>? = emptyList(),
+            actionUrl: String? = DEFAULT_ACTION_URL,
+            colors: WallpaperColors = DEFAULT_COLORS,
+            asset: Asset = DEFAULT_ASSET,
+            groupName: String = DEFAULT_GROUP_NAME,
+            systemWallpaperInfo: WallpaperInfo,
+            isTitleVisible: Boolean = true,
+            isApplied: Boolean = true,
+            effectNames: String? = null,
+        ): WallpaperModel.LiveWallpaperModel {
+            return WallpaperModel.LiveWallpaperModel(
+                commonWallpaperData =
+                    CommonWallpaperData(
+                        id =
+                            WallpaperId(
+                                systemWallpaperInfo.component,
+                                wallpaperId,
+                                collectionId,
+                            ),
+                        title = null,
+                        attributions = attribution,
+                        exploreActionUrl = actionUrl,
+                        thumbAsset = asset,
+                        placeholderColorInfo =
+                            ColorInfo(
+                                colors,
+                                placeholderColor,
+                            ),
+                        destination = Destination.NOT_APPLIED,
+                    ),
+                liveWallpaperData =
+                    LiveWallpaperData(
+                        groupName,
+                        systemWallpaperInfo,
+                        isTitleVisible,
+                        isApplied,
+                        effectNames
+                    ),
+                creativeWallpaperData = null,
+                internalLiveWallpaperData = null,
+            )
+        }
+    }
+}
diff --git a/tests/module/src/com/android/wallpaper/TestModule.kt b/tests/module/src/com/android/wallpaper/TestModule.kt
index d24d02d..18b3a9f 100644
--- a/tests/module/src/com/android/wallpaper/TestModule.kt
+++ b/tests/module/src/com/android/wallpaper/TestModule.kt
@@ -20,6 +20,8 @@
 import com.android.wallpaper.module.WallpaperPreferences
 import com.android.wallpaper.module.logging.TestUserEventLogger
 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.testing.TestInjector
 import com.android.wallpaper.testing.TestWallpaperPreferences
 import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
@@ -46,4 +48,10 @@
     abstract fun bindWallpaperModelFactory(
         impl: DefaultWallpaperModelFactory
     ): WallpaperModelFactory
+
+    @Binds
+    @Singleton
+    abstract fun bindLiveWallpaperDownloader(
+        impl: DefaultLiveWallpaperDownloader
+    ): LiveWallpaperDownloader
 }
diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp
index 3af6979..100cc75 100644
--- a/tests/robotests/Android.bp
+++ b/tests/robotests/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_customization_picker",
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
@@ -7,6 +8,7 @@
     defaults: ["WallpaperPicker2_defaults"],
     platform_apis: true,
     static_libs: [
+        "WallpaperPicker2ApplicationLib",
         "WallpaperPicker2TestLib",
     ],
 }
diff --git a/tests/robotests/config/robolectric.properties b/tests/robotests/config/robolectric.properties
index fab7251..62f25a7 100644
--- a/tests/robotests/config/robolectric.properties
+++ b/tests/robotests/config/robolectric.properties
@@ -1 +1,2 @@
 sdk=NEWEST_SDK
+application = dagger.hilt.android.testing.HiltTestApplication
diff --git a/tests/robotests/module b/tests/robotests/module
new file mode 120000
index 0000000..ad3c990
--- /dev/null
+++ b/tests/robotests/module
@@ -0,0 +1 @@
+../module
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/wallpaper/module/DefaultWallpaperPreferencesTest.kt b/tests/robotests/src/com/android/wallpaper/module/DefaultWallpaperPreferencesTest.kt
index 7e44c35..d825d26 100644
--- a/tests/robotests/src/com/android/wallpaper/module/DefaultWallpaperPreferencesTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/module/DefaultWallpaperPreferencesTest.kt
@@ -17,7 +17,8 @@
 
 import android.content.Context
 import androidx.test.core.app.ApplicationProvider
-import com.android.wallpaper.model.StaticWallpaperMetadata
+import com.android.wallpaper.model.LiveWallpaperPrefMetadata
+import com.android.wallpaper.model.StaticWallpaperPrefMetadata
 import com.android.wallpaper.module.WallpaperPreferenceKeys.NoBackupKeys
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
@@ -33,14 +34,13 @@
     @Test
     fun setHomeStaticImageWallpaperMetadata_metadataShouldBeSavedToPreferences() {
         wallpaperPreferences.setHomeStaticImageWallpaperMetadata(
-            StaticWallpaperMetadata(
+            StaticWallpaperPrefMetadata(
                 attributions = listOf("attr1", "attr2"),
                 actionUrl = "http://www.google.com/",
                 collectionId = "cultural_events",
                 hashCode = 10013L,
                 managerId = 3,
                 remoteId = "ocean",
-                cropHints = null,
             )
         )
 
@@ -74,16 +74,53 @@
     }
 
     @Test
+    fun setHomeLiveWallpaperMetadata_metadataShouldBeSavedToPreferences() {
+        wallpaperPreferences.setHomeLiveWallpaperMetadata(
+            LiveWallpaperPrefMetadata(
+                attributions = listOf("attr1", "attr2"),
+                serviceName =
+                    "com.google.pixel.livewallpaper.dioramas.fiji.wallpapers.FijiWallpaper",
+                effectName = null,
+                collectionId = "living_universe",
+                managerId = 2,
+            )
+        )
+
+        val sharedPref =
+            (ApplicationProvider.getApplicationContext() as Context).getSharedPreferences(
+                DefaultWallpaperPreferences.PREFS_NAME,
+                Context.MODE_PRIVATE
+            )
+        assertThat(sharedPref.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1, null))
+            .isEqualTo("attr1")
+        assertThat(sharedPref.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2, null))
+            .isEqualTo("attr2")
+        assertThat(
+                sharedPref.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_COLLECTION_ID, null)
+            )
+            .isEqualTo("living_universe")
+        val noBackupPref =
+            (ApplicationProvider.getApplicationContext() as Context).getSharedPreferences(
+                DefaultWallpaperPreferences.NO_BACKUP_PREFS_NAME,
+                Context.MODE_PRIVATE
+            )
+        assertThat(noBackupPref.getString(NoBackupKeys.KEY_HOME_WALLPAPER_SERVICE_NAME, null))
+            .isEqualTo("com.google.pixel.livewallpaper.dioramas.fiji.wallpapers.FijiWallpaper")
+        assertThat(noBackupPref.getString(NoBackupKeys.KEY_HOME_WALLPAPER_EFFECTS, null))
+            .isEqualTo(null)
+        assertThat(noBackupPref.getInt(NoBackupKeys.KEY_HOME_WALLPAPER_MANAGER_ID, 0)).isEqualTo(2)
+    }
+
+    @Test
     fun setLockStaticImageWallpaperMetadata_metadataShouldBeSavedToPreferences() {
         wallpaperPreferences.setLockStaticImageWallpaperMetadata(
-            StaticWallpaperMetadata(
+            StaticWallpaperPrefMetadata(
                 attributions = listOf("attr1", "attr2"),
                 actionUrl = "http://www.google.com/",
                 collectionId = "cultural_events",
                 hashCode = 10013L,
                 managerId = 3,
                 remoteId = "ocean",
-                cropHints = null,
             )
         )
 
@@ -115,4 +152,42 @@
         assertThat(noBackupPref.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_REMOTE_ID, null))
             .isEqualTo("ocean")
     }
+
+    @Test
+    fun setLockLiveWallpaperMetadata_metadataShouldBeSavedToPreferences() {
+        wallpaperPreferences.setLockLiveWallpaperMetadata(
+            LiveWallpaperPrefMetadata(
+                attributions = listOf("attr1", "attr2"),
+                serviceName =
+                    "com.google.pixel.livewallpaper.dioramas.fiji.wallpapers.FijiWallpaper",
+                effectName = null,
+                collectionId = "living_universe",
+                managerId = 2,
+            )
+        )
+
+        val sharedPref =
+            (ApplicationProvider.getApplicationContext() as Context).getSharedPreferences(
+                DefaultWallpaperPreferences.PREFS_NAME,
+                Context.MODE_PRIVATE
+            )
+        assertThat(sharedPref.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1, null))
+            .isEqualTo("attr1")
+        assertThat(sharedPref.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2, null))
+            .isEqualTo("attr2")
+        assertThat(
+                sharedPref.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_COLLECTION_ID, null)
+            )
+            .isEqualTo("living_universe")
+        val noBackupPref =
+            (ApplicationProvider.getApplicationContext() as Context).getSharedPreferences(
+                DefaultWallpaperPreferences.NO_BACKUP_PREFS_NAME,
+                Context.MODE_PRIVATE
+            )
+        assertThat(noBackupPref.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_SERVICE_NAME, null))
+            .isEqualTo("com.google.pixel.livewallpaper.dioramas.fiji.wallpapers.FijiWallpaper")
+        assertThat(noBackupPref.getString(NoBackupKeys.KEY_LOCK_WALLPAPER_EFFECTS, null))
+            .isEqualTo(null)
+        assertThat(noBackupPref.getInt(NoBackupKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, 0)).isEqualTo(2)
+    }
 }
diff --git a/tests/robotests/src/com/android/wallpaper/picker/broadcast/BroadcastDispatcherTest.kt b/tests/robotests/src/com/android/wallpaper/picker/broadcast/BroadcastDispatcherTest.kt
new file mode 100644
index 0000000..48b077a
--- /dev/null
+++ b/tests/robotests/src/com/android/wallpaper/picker/broadcast/BroadcastDispatcherTest.kt
@@ -0,0 +1,170 @@
+/*
+ * 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.broadcast
+
+import android.app.Application
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.Looper
+import android.os.Process
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.SmallTest
+import com.android.wallpaper.picker.di.modules.ConcurrencyModule
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.Shadows
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(RobolectricTestRunner::class)
+class BroadcastDispatcherTest {
+
+    private lateinit var mContext: Context
+
+    private lateinit var broadcastReceiver: BroadcastReceiver
+    private lateinit var intentFilter: IntentFilter
+    private lateinit var broadcastDispatcher: BroadcastDispatcher
+
+    private lateinit var mainExecutor: Executor
+
+    @Before
+    fun setUp() {
+        mContext = ApplicationProvider.getApplicationContext()
+        val backgroundRunningLooper = provideBroadcastRunningLooper()
+        mainExecutor = provideBroadcastRunningExecutor(backgroundRunningLooper)
+        broadcastReceiver =
+            object : BroadcastReceiver() {
+                override fun onReceive(context: Context?, intent: Intent?) {}
+            }
+        broadcastDispatcher =
+            BroadcastDispatcher(mContext, mainExecutor, backgroundRunningLooper, mainExecutor)
+    }
+
+    @Test
+    fun testBroadcastFlow_emitsValues() = runTest {
+        intentFilter = IntentFilter("ACTION_TEST")
+        val testIntent = Intent("ACTION_TEST")
+
+        val flow =
+            broadcastDispatcher.broadcastFlow(intentFilter) { intent, receiver ->
+                intent to receiver
+            }
+        val collectedValues = mutableListOf<Pair<Intent, BroadcastReceiver>>()
+        val job = launch { flow.collect { collectedValues.add(it) } }
+
+        // Waits for the flow collection coroutine to start and collect any immediate emissions
+        advanceUntilIdle()
+
+        val shadowApplication =
+            Shadows.shadowOf(ApplicationProvider.getApplicationContext() as Application)
+        val receivers = shadowApplication.registeredReceivers
+        val capturedReceiver = receivers.find { it.broadcastReceiver is BroadcastReceiver }
+        assertThat(capturedReceiver).isNotNull()
+        capturedReceiver?.let { collectedValues.add(testIntent to it.broadcastReceiver) }
+
+        // Processes any additional tasks that may have been scheduled as a result of
+        // adding to collectedValues
+        advanceUntilIdle()
+
+        val expectedValues = listOf(testIntent to capturedReceiver?.broadcastReceiver)
+        assertThat(expectedValues).isEqualTo(collectedValues)
+        job.cancel()
+    }
+
+    @Test
+    fun testRegisterReceiver() {
+        intentFilter = IntentFilter(Intent.ACTION_BOOT_COMPLETED)
+
+        broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter)
+
+        val shadowApplication =
+            Shadows.shadowOf(ApplicationProvider.getApplicationContext() as Application)
+        val receivers = shadowApplication.registeredReceivers
+        val isRegistered = receivers.any { it.broadcastReceiver == broadcastReceiver }
+        assertThat(isRegistered).isEqualTo(true)
+    }
+
+    @Test
+    fun testUnregisterReceiver() {
+        intentFilter = IntentFilter(Intent.ACTION_BOOT_COMPLETED)
+
+        broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter)
+        broadcastDispatcher.unregisterReceiver(broadcastReceiver)
+
+        val shadowApplication =
+            Shadows.shadowOf(ApplicationProvider.getApplicationContext() as Application)
+        val receivers = shadowApplication.registeredReceivers
+        val isUnregistered = receivers.none { it.broadcastReceiver == broadcastReceiver }
+        assertThat(isUnregistered).isEqualTo(true)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun testFilterMustNotContainDataType() {
+        val testFilter = IntentFilter(TEST_ACTION).apply { addDataType(TEST_TYPE) }
+
+        broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun testFilterMustNotSetPriority() {
+        val testFilter =
+            IntentFilter(TEST_ACTION).apply { priority = IntentFilter.SYSTEM_HIGH_PRIORITY }
+
+        broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
+    }
+
+    private fun provideBroadcastRunningLooper(): Looper {
+        return HandlerThread(
+                "BroadcastRunning",
+                Process.THREAD_PRIORITY_BACKGROUND,
+            )
+            .apply {
+                start()
+                looper.setSlowLogThresholdMs(
+                    BROADCAST_SLOW_DISPATCH_THRESHOLD,
+                    BROADCAST_SLOW_DELIVERY_THRESHOLD,
+                )
+            }
+            .looper
+    }
+
+    private fun provideBroadcastRunningExecutor(
+        @ConcurrencyModule.BroadcastRunning looper: Looper?
+    ): Executor {
+        val handler = Handler(looper ?: Looper.getMainLooper())
+        return Executor { command -> handler.post(command) }
+    }
+
+    companion object {
+        private val BROADCAST_SLOW_DISPATCH_THRESHOLD = 1000L
+        private val BROADCAST_SLOW_DELIVERY_THRESHOLD = 1000L
+        const val TEST_ACTION = "TEST_ACTION"
+        const val TEST_TYPE = "test/type"
+    }
+}
diff --git a/tests/robotests/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepositoryTest.kt b/tests/robotests/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepositoryTest.kt
index ef88c27..cda3cc6 100644
--- a/tests/robotests/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepositoryTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/picker/customization/data/repository/WallpaperRepositoryTest.kt
@@ -96,7 +96,7 @@
 
             // Pause the client so we can examine the interim state.
             client.pause()
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.HOME,
                 FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[1].wallpaperId,
@@ -104,7 +104,7 @@
             prefs.setHomeWallpaperRecentsKey(
                 FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[1].wallpaperId
             )
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.LOCK,
                 FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[2].wallpaperId,
@@ -179,12 +179,12 @@
             assertThat(selectedLockWallpaperId())
                 .isEqualTo(FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS.first().wallpaperId)
 
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.HOME,
                 FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[1].wallpaperId,
             )
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.LOCK,
                 FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[2].wallpaperId,
diff --git a/tests/robotests/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractorTest.kt b/tests/robotests/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractorTest.kt
index a472bcf..f818701 100644
--- a/tests/robotests/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractorTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/picker/customization/domain/interactor/WallpaperInteractorTest.kt
@@ -114,12 +114,12 @@
 
             val homeWallpaperId1 = FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[1].wallpaperId
             val lockWallpaperId1 = FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[2].wallpaperId
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.HOME,
                 homeWallpaperId1
             )
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.LOCK,
                 lockWallpaperId1
@@ -131,12 +131,12 @@
 
             val homeWallpaperId2 = FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[2].wallpaperId
             val lockWallpaperId2 = FakeWallpaperClient.INITIAL_RECENT_WALLPAPERS[2].wallpaperId
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.HOME,
                 homeWallpaperId2
             )
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.LOCK,
                 lockWallpaperId2
@@ -183,12 +183,12 @@
 
             // Pause the client so we can examine the interim state.
             client.pause()
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.HOME,
                 homeWallpaperId
             )
-            underTest.setWallpaper(
+            underTest.setRecentWallpaper(
                 SET_WALLPAPER_ENTRY_POINT_WALLPAPER_PREVIEW,
                 WallpaperDestination.LOCK,
                 lockWallpaperId
diff --git a/tests/robotests/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModelTest.kt b/tests/robotests/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModelTest.kt
index 798e204..8a69776 100644
--- a/tests/robotests/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModelTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/picker/customization/ui/viewmodel/WallpaperQuickSwitchViewModelTest.kt
@@ -198,9 +198,7 @@
                 isLarge = isBeingSelected || (nothingBeingSelected && isSelected),
                 isSelectionIndicatorVisible =
                     isBeingSelected || (nothingBeingSelected && isSelected),
-                isSelectable =
-                    (!nothingBeingSelected && !isBeingSelected) ||
-                        (nothingBeingSelected && !isSelected),
+                isSelectable = nothingBeingSelected && !isSelected,
             )
         }
     }
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
new file mode 100644
index 0000000..26e8820
--- /dev/null
+++ b/tests/robotests/src/com/android/wallpaper/picker/preview/data/repository/WallpaperPreviewRepositoryTest.kt
@@ -0,0 +1,204 @@
+/*
+ * 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.data.repository
+
+import android.app.WallpaperInfo
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
+import android.content.pm.ServiceInfo
+import android.graphics.Color
+import androidx.test.core.app.ApplicationProvider
+import com.android.wallpaper.module.WallpaperPreferences
+import com.android.wallpaper.picker.data.ColorInfo
+import com.android.wallpaper.picker.data.CommonWallpaperData
+import com.android.wallpaper.picker.data.Destination
+import com.android.wallpaper.picker.data.LiveWallpaperData
+import com.android.wallpaper.picker.data.WallpaperId
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.preview.data.util.ShadowWallpaperInfo
+import com.android.wallpaper.picker.preview.data.util.TestLiveWallpaperDownloader
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultCode
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultModel
+import com.android.wallpaper.testing.TestAsset
+import com.android.wallpaper.testing.TestWallpaperPreferences
+import com.android.wallpaper.testing.WallpaperModelUtils.Companion.getStaticWallpaperModel
+import com.google.common.truth.Truth.assertThat
+import dagger.hilt.android.testing.HiltTestApplication
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+
+/**
+ * Tests for {@link WallpaperPreviewRepository}.
+ *
+ * WallpaperPreviewRepository cannot be injected in setUp() because it is annotated with scope
+ * ActivityRetainedScoped. We make an instance available via TestActivity, which can inject the SUT
+ * and expose it for testing.
+ */
+@Config(shadows = [ShadowWallpaperInfo::class])
+@RunWith(RobolectricTestRunner::class)
+class WallpaperPreviewRepositoryTest {
+
+    private lateinit var context: Context
+    private lateinit var testDispatcher: CoroutineDispatcher
+    private lateinit var testScope: TestScope
+    private lateinit var underTest: WallpaperPreviewRepository
+    private lateinit var prefs: WallpaperPreferences
+
+    @Before
+    fun setUp() {
+        context = ApplicationProvider.getApplicationContext<HiltTestApplication>()
+        testDispatcher = StandardTestDispatcher()
+        testScope = TestScope(testDispatcher)
+        prefs = TestWallpaperPreferences()
+    }
+
+    @Test
+    fun setWallpaperModel() {
+        underTest =
+            WallpaperPreviewRepository(
+                liveWallpaperDownloader = TestLiveWallpaperDownloader(null),
+                preferences = prefs,
+                bgDispatcher = testDispatcher,
+            )
+
+        val wallpaperModel =
+            getStaticWallpaperModel(
+                wallpaperId = "aaa",
+                collectionId = "testCollection",
+            )
+        assertThat(underTest.wallpaperModel.value).isNull()
+
+        underTest.setWallpaperModel(wallpaperModel)
+
+        assertThat(underTest.wallpaperModel.value).isEqualTo(wallpaperModel)
+    }
+
+    @Test
+    fun dismissTooltip() {
+        prefs.setHasPreviewTooltipBeenShown(false)
+        underTest =
+            WallpaperPreviewRepository(
+                liveWallpaperDownloader = TestLiveWallpaperDownloader(null),
+                preferences = prefs,
+                bgDispatcher = testDispatcher,
+            )
+        assertThat(underTest.hasTooltipBeenShown.value).isFalse()
+
+        underTest.dismissTooltip()
+        assertThat(prefs.getHasPreviewTooltipBeenShown()).isTrue()
+        assertThat(underTest.hasTooltipBeenShown.value).isTrue()
+    }
+
+    @Test
+    fun downloadWallpaper_fails() {
+        underTest =
+            WallpaperPreviewRepository(
+                liveWallpaperDownloader =
+                    TestLiveWallpaperDownloader(
+                        LiveWallpaperDownloadResultModel(LiveWallpaperDownloadResultCode.FAIL, null)
+                    ),
+                preferences = prefs,
+                bgDispatcher = testDispatcher,
+            )
+
+        testScope.runTest {
+            val result = underTest.downloadWallpaper()
+
+            assertThat(result).isNotNull()
+            val (code, wallpaperModel) = result!!
+            assertThat(code).isEqualTo(LiveWallpaperDownloadResultCode.FAIL)
+            assertThat(wallpaperModel).isNull()
+        }
+    }
+
+    @Test
+    fun downloadWallpaper_succeeds() {
+        val resultWallpaper = getTestLiveWallpaperModel()
+        underTest =
+            WallpaperPreviewRepository(
+                liveWallpaperDownloader =
+                    TestLiveWallpaperDownloader(
+                        LiveWallpaperDownloadResultModel(
+                            code = LiveWallpaperDownloadResultCode.SUCCESS,
+                            wallpaperModel = resultWallpaper,
+                        )
+                    ),
+                preferences = prefs,
+                bgDispatcher = testDispatcher,
+            )
+
+        testScope.runTest {
+            val result = underTest.downloadWallpaper()
+
+            assertThat(result).isNotNull()
+            val (code, wallpaperModel) = result!!
+            assertThat(code).isEqualTo(LiveWallpaperDownloadResultCode.SUCCESS)
+            assertThat(wallpaperModel).isEqualTo(resultWallpaper)
+        }
+    }
+
+    private fun getTestLiveWallpaperModel(): WallpaperModel.LiveWallpaperModel {
+        // ShadowWallpaperInfo allows the creation of this object
+        val wallpaperInfo =
+            WallpaperInfo(
+                context,
+                ResolveInfo().apply {
+                    serviceInfo = ServiceInfo()
+                    serviceInfo.packageName = "com.google.android.apps.wallpaper.nexus"
+                    serviceInfo.splitName = "wallpaper_cities_ny"
+                    serviceInfo.name = "NewYorkWallpaper"
+                    serviceInfo.flags = PackageManager.GET_META_DATA
+                }
+            )
+        return WallpaperModel.LiveWallpaperModel(
+            commonWallpaperData =
+                CommonWallpaperData(
+                    id =
+                        WallpaperId(
+                            componentName = ComponentName("package", "class"),
+                            uniqueId = "uniqueId",
+                            collectionId = "collectionId",
+                        ),
+                    title = "title",
+                    attributions = listOf("attr1", "attr2"),
+                    exploreActionUrl = "https://www.google.com/",
+                    thumbAsset = TestAsset(Color.RED, false),
+                    placeholderColorInfo = ColorInfo(null),
+                    destination = Destination.NOT_APPLIED,
+                ),
+            liveWallpaperData =
+                LiveWallpaperData(
+                    groupName = "groupName",
+                    systemWallpaperInfo = wallpaperInfo,
+                    isTitleVisible = false,
+                    isApplied = false,
+                    effectNames = null,
+                ),
+            creativeWallpaperData = null,
+            internalLiveWallpaperData = null,
+        )
+    }
+}
diff --git a/tests/robotests/src/com/android/wallpaper/picker/preview/data/util/ShadowWallpaperInfo.kt b/tests/robotests/src/com/android/wallpaper/picker/preview/data/util/ShadowWallpaperInfo.kt
new file mode 100644
index 0000000..4c7e98e
--- /dev/null
+++ b/tests/robotests/src/com/android/wallpaper/picker/preview/data/util/ShadowWallpaperInfo.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.picker.preview.data.util
+
+import android.app.WallpaperInfo
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.ResolveInfo
+import android.content.pm.ServiceInfo
+import org.robolectric.annotation.Implementation
+import org.robolectric.annotation.Implements
+
+@Implements(WallpaperInfo::class)
+class ShadowWallpaperInfo {
+    private lateinit var context: Context
+    private lateinit var resolveInfo: ResolveInfo
+
+    // CHECKSTYLE:OFF Generated code
+    @Implementation
+    fun __constructor__(context: Context, resolveInfo: ResolveInfo) {
+        this.context = context
+        this.resolveInfo = resolveInfo
+    }
+
+    @Implementation
+    fun getPackageName(): String {
+        return resolveInfo.serviceInfo.packageName
+    }
+
+    @Implementation
+    fun getServiceInfo(): ServiceInfo {
+        return resolveInfo.serviceInfo
+    }
+
+    @Implementation
+    fun getComponent(): ComponentName {
+        return ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name)
+    }
+}
diff --git a/tests/robotests/src/com/android/wallpaper/picker/preview/data/util/TestLiveWallpaperDownloader.kt b/tests/robotests/src/com/android/wallpaper/picker/preview/data/util/TestLiveWallpaperDownloader.kt
new file mode 100644
index 0000000..2eae44e
--- /dev/null
+++ b/tests/robotests/src/com/android/wallpaper/picker/preview/data/util/TestLiveWallpaperDownloader.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.util
+
+import android.app.Activity
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.IntentSenderRequest
+import com.android.wallpaper.picker.data.WallpaperModel
+import com.android.wallpaper.picker.preview.shared.model.LiveWallpaperDownloadResultModel
+
+class TestLiveWallpaperDownloader(
+    private val wallpaperDownloadResult: LiveWallpaperDownloadResultModel?
+) : LiveWallpaperDownloader {
+
+    override fun initiateDownloadableService(
+        activity: Activity,
+        wallpaperData: WallpaperModel.StaticWallpaperModel,
+        intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
+    ) {}
+
+    override fun cleanup() {}
+
+    override suspend fun downloadWallpaper(): LiveWallpaperDownloadResultModel? {
+        return wallpaperDownloadResult
+    }
+}
diff --git a/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt b/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt
index c6cf8d8..ea79287 100644
--- a/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt
@@ -19,9 +19,11 @@
         val wallpaperSize = Point(1080, 1920)
         assertThat(
                 FullResImageViewUtil.getScaleAndCenter(
-                    Point(screenWidth, screenHeight),
-                    wallpaperSize,
+                    viewSize = Point(screenWidth, screenHeight),
+                    rawWallpaperSize = wallpaperSize,
+                    displaySize = Point(screenWidth, screenHeight),
                     cropRect = null,
+                    isRtl = false,
                 )
             )
             .isEqualTo(
@@ -41,9 +43,11 @@
         val wallpaperSize = Point(3840, 3840)
         assertThat(
                 FullResImageViewUtil.getScaleAndCenter(
-                    Point(screenWidth, screenHeight),
-                    wallpaperSize,
+                    viewSize = Point(screenWidth, screenHeight),
+                    rawWallpaperSize = wallpaperSize,
+                    displaySize = Point(screenWidth, screenHeight),
                     cropRect = null,
+                    isRtl = false,
                 )
             )
             .isEqualTo(
@@ -63,9 +67,11 @@
         val wallpaperSize = Point(960, 960)
         assertThat(
                 FullResImageViewUtil.getScaleAndCenter(
-                    Point(screenWidth, screenHeight),
-                    wallpaperSize,
+                    viewSize = Point(screenWidth, screenHeight),
+                    rawWallpaperSize = wallpaperSize,
+                    displaySize = Point(screenWidth, screenHeight),
                     cropRect = null,
+                    isRtl = false,
                 )
             )
             .isEqualTo(
diff --git a/tests/robotests/src/com/android/wallpaper/util/converter/category/CategoryFactoryTest.kt b/tests/robotests/src/com/android/wallpaper/util/converter/category/CategoryFactoryTest.kt
new file mode 100644
index 0000000..fbdfb12
--- /dev/null
+++ b/tests/robotests/src/com/android/wallpaper/util/converter/category/CategoryFactoryTest.kt
@@ -0,0 +1,85 @@
+/*
+ * 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.converter.category
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import com.android.wallpaper.model.ImageCategory
+import com.android.wallpaper.model.PlaceholderCategory
+import com.android.wallpaper.picker.data.category.CategoryModel
+import com.android.wallpaper.util.converter.WallpaperModelFactory
+import dagger.hilt.android.testing.HiltAndroidRule
+import dagger.hilt.android.testing.HiltAndroidTest
+import dagger.hilt.android.testing.HiltTestApplication
+import javax.inject.Inject
+import junit.framework.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@HiltAndroidTest
+@RunWith(RobolectricTestRunner::class)
+class CategoryFactoryTest {
+
+    @get:Rule var hiltRule = HiltAndroidRule(this)
+
+    private lateinit var context: Context
+
+    @Inject lateinit var wallpaperModelFactory: WallpaperModelFactory
+
+    private lateinit var mCategoryFactory: CategoryFactory
+
+    @Before
+    fun setUp() {
+        hiltRule.inject()
+        context = ApplicationProvider.getApplicationContext<HiltTestApplication>()
+        mCategoryFactory = CategoryFactory(wallpaperModelFactory)
+    }
+
+    @Test
+    fun testGetCategoryModel() {
+        val placeholderCategory = PlaceholderCategory(TEST_TITLE, TEST_COLLECTIONID, TEST_PRIORITY)
+
+        val result = mCategoryFactory.getCategoryModel(context, placeholderCategory)
+
+        validateCommonCategoryData(result)
+        assertEquals(result.collectionCategoryData, null)
+        assertEquals(result.imageCategoryData, null)
+        assertEquals(result.thirdPartyCategoryData, null)
+    }
+
+    @Test
+    fun testGetImageCategoryModel() {
+        val imageCategory = ImageCategory(TEST_TITLE, TEST_COLLECTIONID, TEST_PRIORITY)
+        val result = mCategoryFactory.getCategoryModel(context, imageCategory)
+        validateCommonCategoryData(result)
+    }
+
+    private fun validateCommonCategoryData(result: CategoryModel) {
+        assertEquals(TEST_TITLE, result.commonCategoryData.title)
+        assertEquals(TEST_COLLECTIONID, result.commonCategoryData.collectionId)
+        assertEquals(TEST_PRIORITY, result.commonCategoryData.priority)
+    }
+
+    companion object {
+        const val TEST_TITLE = "Test-Title"
+        const val TEST_COLLECTIONID = "Test-Collection-Id"
+        const val TEST_PRIORITY = 1
+    }
+}
diff --git a/tests/src/com/android/wallpaper/picker/PreviewActivityTest.java b/tests/src/com/android/wallpaper/picker/PreviewActivityTest.java
index f89638f..e610dd4 100644
--- a/tests/src/com/android/wallpaper/picker/PreviewActivityTest.java
+++ b/tests/src/com/android/wallpaper/picker/PreviewActivityTest.java
@@ -130,7 +130,7 @@
 
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         mWallpaperPersister = (TestWallpaperPersister) mInjector.getWallpaperPersister(context);
-        mEventLogger = (TestUserEventLogger) mInjector.getUserEventLogger(context);
+        mEventLogger = (TestUserEventLogger) mInjector.getUserEventLogger();
         mExploreIntentChecker = (TestExploreIntentChecker)
                 mInjector.getExploreIntentChecker(context);
         mWallpaperStatusChecker = (TestWallpaperStatusChecker)
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 95c0e5b..7778b91 100644
--- a/tests/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivityTest.kt
+++ b/tests/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivityTest.kt
@@ -15,20 +15,25 @@
  */
 package com.android.wallpaper.picker.preview.ui
 
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
 import androidx.navigation.fragment.NavHostFragment
 import androidx.test.core.app.ActivityScenario
 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
 import com.android.wallpaper.testing.TestStaticWallpaperInfo
+import com.android.window.flags.Flags.FLAG_MULTI_CROP
 import com.google.common.truth.Truth.assertThat
 import dagger.hilt.android.testing.HiltAndroidRule
 import dagger.hilt.android.testing.HiltAndroidTest
 import javax.inject.Inject
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -39,6 +44,8 @@
 class WallpaperPreviewActivityTest {
     @get:Rule var hiltRule = HiltAndroidRule(this)
 
+    @get:Rule val setFlagsRule = SetFlagsRule()
+
     @Inject lateinit var testInjector: TestInjector
 
     private val testStaticWallpaper =
@@ -47,6 +54,8 @@
         WallpaperPreviewActivity.newIntent(
             context = ApplicationProvider.getApplicationContext(),
             wallpaperInfo = testStaticWallpaper,
+            isAssetIdPresent = false,
+            isViewAsHome = false,
             isNewTask = false,
         )
 
@@ -57,6 +66,8 @@
     }
 
     @Test
+    @Ignore("b/327241549")
+    @EnableFlags(FLAG_MULTI_CROP_PREVIEW_UI_FLAG, FLAG_MULTI_CROP)
     fun showsNavHostFragment() {
         val scenario: ActivityScenario<WallpaperPreviewActivity> =
             ActivityScenario.launch(activityStartIntent)