Merge "Turn off WIP small to full preview transition animation" into main
diff --git a/res/drawable/check_circle_full_preview.xml b/res/drawable/check_circle_full_preview.xml
index 09b288a..f716d8f 100644
--- a/res/drawable/check_circle_full_preview.xml
+++ b/res/drawable/check_circle_full_preview.xml
@@ -15,6 +15,6 @@
      limitations under the License.
 -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/wallpaper_control_button_on_background" />
+    <item android:drawable="@drawable/set_crop_button_background" />
     <item android:drawable="@drawable/ic_check_wallpaper" />
 </layer-list>
\ No newline at end of file
diff --git a/res/drawable/ic_check_wallpaper.xml b/res/drawable/ic_check_wallpaper.xml
index a280693..6c2f238 100644
--- a/res/drawable/ic_check_wallpaper.xml
+++ b/res/drawable/ic_check_wallpaper.xml
@@ -20,6 +20,6 @@
     android:viewportWidth="24"
     android:viewportHeight="24">
     <path
-        android:fillColor="@color/text_color_on_accent"
+        android:fillColor="@color/system_on_primary"
         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_crop_button_background.xml b/res/drawable/set_crop_button_background.xml
new file mode 100644
index 0000000..68149ad
--- /dev/null
+++ b/res/drawable/set_crop_button_background.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:colorControlHighlight">
+
+    <item android:id="@android:id/mask">
+        <shape android:shape="oval">
+            <padding
+                android:bottom="@dimen/wallpaper_control_button_padding"
+                android:left="@dimen/wallpaper_control_button_padding"
+                android:right="@dimen/wallpaper_control_button_padding"
+                android:top="@dimen/wallpaper_control_button_padding" />
+            <solid android:color="?android:colorControlHighlight" />
+        </shape>
+    </item>
+
+    <item android:drawable="@drawable/set_crop_button_background_base" />
+</ripple>
\ No newline at end of file
diff --git a/res/drawable/set_crop_button_background_base.xml b/res/drawable/set_crop_button_background_base.xml
new file mode 100644
index 0000000..338fc3f
--- /dev/null
+++ b/res/drawable/set_crop_button_background_base.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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <padding
+        android:left="@dimen/wallpaper_control_button_padding"
+        android:right="@dimen/wallpaper_control_button_padding"
+        android:top="@dimen/wallpaper_control_button_padding"
+        android:bottom="@dimen/wallpaper_control_button_padding"/>
+    <solid android:color="@color/system_primary" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/set_wallpaper_button_background_variant.xml b/res/drawable/set_wallpaper_button_background_variant.xml
new file mode 100644
index 0000000..1f2a746
--- /dev/null
+++ b/res/drawable/set_wallpaper_button_background_variant.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:colorControlHighlight">
+
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/set_wallpaper_button_corner_radius" />
+            <padding
+                android:left="@dimen/set_wallpaper_button_horizontal_padding"
+                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="?android:colorControlHighlight" />
+        </shape>
+    </item>
+
+    <item android:drawable="@drawable/set_wallpaper_button_background_variant_base" />
+</ripple>
\ No newline at end of file
diff --git a/res/drawable/set_wallpaper_button_background_variant_base.xml b/res/drawable/set_wallpaper_button_background_variant_base.xml
new file mode 100644
index 0000000..14e2448
--- /dev/null
+++ b/res/drawable/set_wallpaper_button_background_variant_base.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/set_wallpaper_button_corner_radius" />
+    <padding
+        android:left="@dimen/set_wallpaper_button_horizontal_padding"
+        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_primary" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/set_wallpaper_dialog_positive_button.xml b/res/drawable/set_wallpaper_dialog_positive_button.xml
new file mode 100644
index 0000000..540a8a4
--- /dev/null
+++ b/res/drawable/set_wallpaper_dialog_positive_button.xml
@@ -0,0 +1,33 @@
+<?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.
+  -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:colorControlHighlight">
+
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/set_wallpaper_button_corner_radius" />
+            <padding
+                android:left="@dimen/set_wallpaper_button_horizontal_padding"
+                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="?android:colorControlHighlight" />
+        </shape>
+    </item>
+
+    <item android:drawable="@drawable/set_wallpaper_dialog_positive_button_base" />
+</ripple>
\ No newline at end of file
diff --git a/res/drawable/set_wallpaper_dialog_positive_button_base.xml b/res/drawable/set_wallpaper_dialog_positive_button_base.xml
new file mode 100644
index 0000000..5942cbb
--- /dev/null
+++ b/res/drawable/set_wallpaper_dialog_positive_button_base.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/set_wallpaper_button_corner_radius" />
+    <padding
+        android:left="@dimen/set_wallpaper_button_horizontal_padding"
+        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" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/small_preview_tab_background.xml b/res/drawable/small_preview_tab_background.xml
index 3408f68..ced9242 100644
--- a/res/drawable/small_preview_tab_background.xml
+++ b/res/drawable/small_preview_tab_background.xml
@@ -17,7 +17,7 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="@color/color_accent_secondary" />
+    <solid android:color="@color/system_secondary" />
     <corners android:radius="@dimen/small_preview_button_radius" />
     <padding
         android:top="@dimen/small_preview_button_padding_vertical"
diff --git a/res/layout/floating_sheet2.xml b/res/layout/floating_sheet2.xml
new file mode 100644
index 0000000..c0637f1
--- /dev/null
+++ b/res/layout/floating_sheet2.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright (C) 2022 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.coordinatorlayout.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent">
+    <!-- Bottom Sheet Behavior view should be a child view of CoordinatorLayout -->
+    <FrameLayout
+        android:id="@+id/floating_sheet_container"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:importantForAccessibility="no"
+        app:behavior_hideable="true"
+        app:behavior_peekHeight="0dp"
+        app:behavior_skipCollapsed="true"
+        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
+        <!-- To enable a floating sheet, content and styling are included as child view -->
+        <FrameLayout
+            android:id="@+id/floating_sheet_content"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:padding="@dimen/wallpaper_info_pane_padding"
+            android:layout_marginHorizontal="@dimen/floating_sheet_margin"
+            android:layout_marginBottom="120dp"
+            android:background="@drawable/floating_sheet_background" />
+    </FrameLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/res/layout/fragment_full_preview.xml b/res/layout/fragment_full_preview.xml
index ea50386..d9f59ba 100644
--- a/res/layout/fragment_full_preview.xml
+++ b/res/layout/fragment_full_preview.xml
@@ -51,6 +51,7 @@
             android:elevation="@dimen/wallpaper_preview_buttons_elevation"
             android:layout_marginEnd="@dimen/set_wallpaper_button_margin_end"
             android:contentDescription="@string/show_preview_controls_action"
+            android:textColor="@color/system_on_primary"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintTop_toTopOf="@id/toolbar_container"
             app:layout_constraintBottom_toBottomOf="@id/toolbar_container"/>
diff --git a/res/layout/fragment_small_preview_foldable.xml b/res/layout/fragment_small_preview_foldable.xml
index 6715c22..2ea100b 100644
--- a/res/layout/fragment_small_preview_foldable.xml
+++ b/res/layout/fragment_small_preview_foldable.xml
@@ -38,9 +38,10 @@
         android:layout_height="wrap_content"
         android:elevation="@dimen/wallpaper_preview_buttons_elevation"
         android:layout_marginEnd="@dimen/set_wallpaper_button_margin_end"
-        android:background="@drawable/set_wallpaper_button_background"
+        android:background="@drawable/set_wallpaper_button_background_variant"
         android:text="@string/set_wallpaper_button_text"
-        android:textColor="@color/text_color_on_accent"
+        android:textColor="@color/system_on_primary"
+        android:textAppearance="@style/WallpaperPicker.Preview.TextAppearance.NoAllCaps"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintTop_toTopOf="@id/toolbar_container"
         app:layout_constraintBottom_toBottomOf="@id/toolbar_container"/>
@@ -66,7 +67,12 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"/>
 
-    <com.android.wallpaper.widget.WallpaperControlButtonGroup
+    <com.android.wallpaper.picker.preview.ui.view.PreviewActionFloatingSheet
+        android:id="@+id/floating_sheet"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent" />
+
+    <com.android.wallpaper.picker.preview.ui.view.PreviewActionGroup
         android:id="@+id/action_button_group"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -75,9 +81,4 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"/>
 
-    <com.android.wallpaper.widget.FloatingSheet
-        android:id="@+id/floating_sheet"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent" />
-
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/res/layout/fragment_small_preview_handheld.xml b/res/layout/fragment_small_preview_handheld.xml
index 070dc88..a255ace 100644
--- a/res/layout/fragment_small_preview_handheld.xml
+++ b/res/layout/fragment_small_preview_handheld.xml
@@ -39,9 +39,10 @@
         android:layout_height="wrap_content"
         android:elevation="@dimen/wallpaper_preview_buttons_elevation"
         android:layout_marginEnd="@dimen/set_wallpaper_button_margin_end"
-        android:background="@drawable/set_wallpaper_button_background"
+        android:background="@drawable/set_wallpaper_button_background_variant"
         android:text="@string/set_wallpaper_button_text"
-        android:textColor="@color/text_color_on_accent"
+        android:textColor="@color/system_on_primary"
+        android:textAppearance="@style/WallpaperPicker.Preview.TextAppearance.NoAllCaps"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintTop_toTopOf="@id/toolbar_container"
         app:layout_constraintBottom_toBottomOf="@id/toolbar_container"/>
@@ -65,6 +66,11 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent" />
 
+    <com.android.wallpaper.picker.preview.ui.view.PreviewActionFloatingSheet
+        android:id="@+id/floating_sheet"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent" />
+
     <com.android.wallpaper.picker.preview.ui.view.PreviewActionGroup
         android:id="@+id/action_button_group"
         android:layout_width="wrap_content"
@@ -74,9 +80,4 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"/>
 
-    <com.android.wallpaper.widget.FloatingSheet
-        android:id="@+id/floating_sheet"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent" />
-
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/item_text.xml b/res/layout/item_text.xml
index 9b411f3..97fe155 100644
--- a/res/layout/item_text.xml
+++ b/res/layout/item_text.xml
@@ -25,5 +25,5 @@
         android:background="@drawable/small_preview_tab_background"
         android:layout_gravity="center"
         android:textAppearance="@style/WallpaperPicker.Preview.TextAppearance.NoAllCaps"
-        android:textSize="16sp"/>
+        android:textColor="@color/system_on_primary" />
 </FrameLayout>
diff --git a/res/layout/set_wallpaper_dialog.xml b/res/layout/set_wallpaper_dialog.xml
index 72c2356..7e5e75c 100644
--- a/res/layout/set_wallpaper_dialog.xml
+++ b/res/layout/set_wallpaper_dialog.xml
@@ -52,16 +52,16 @@
             android:id="@+id/button_cancel"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:background="@drawable/set_wallpaper_button_background"
-            android:textColor="@color/text_color_on_accent"
+            android:background="@drawable/set_wallpaper_dialog_positive_button"
+            android:textColor="@color/system_on_primary"
             android:text="Cancel" />
 
         <Button
             android:id="@+id/button_set"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:background="@drawable/set_wallpaper_button_background"
-            android:textColor="@color/text_color_on_accent"
+            android:background="@drawable/set_wallpaper_dialog_positive_button"
+            android:textColor="@color/system_on_primary"
             android:text="Set" />
     </LinearLayout>
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/res/layout/wallpaper_info_view2.xml b/res/layout/wallpaper_info_view2.xml
new file mode 100644
index 0000000..737a822
--- /dev/null
+++ b/res/layout/wallpaper_info_view2.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:divider="@drawable/horizontal_divider_8dp"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/wallpaper_info_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="20sp"
+        android:textColor="@color/text_color_primary"
+        android:visibility="gone"/>
+
+    <TextView
+        android:id="@+id/wallpaper_info_subtitle1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textColor="@color/text_color_secondary"
+        android:textSize="14sp"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@+id/wallpaper_info_subtitle2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textColor="@color/text_color_secondary"
+        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:text="@string/explore"
+        android:visibility="gone" />
+</LinearLayout>
diff --git a/src/com/android/wallpaper/model/wallpaper/DownloadableWallpaperData.kt b/src/com/android/wallpaper/model/wallpaper/DownloadableWallpaperData.kt
new file mode 100644
index 0000000..04ff8c6
--- /dev/null
+++ b/src/com/android/wallpaper/model/wallpaper/DownloadableWallpaperData.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.app.WallpaperInfo
+
+/** Represents set of attributes that are needed for a wallpaper that is downloadable. */
+data class DownloadableWallpaperData(
+    val groupName: String,
+    val systemWallpaperInfo: WallpaperInfo,
+    val isTitleVisible: Boolean,
+    val isApplied: Boolean,
+    val effectNames: String?,
+)
diff --git a/src/com/android/wallpaper/model/wallpaper/LiveWallpaperData.kt b/src/com/android/wallpaper/model/wallpaper/LiveWallpaperData.kt
index 832bff5..5a3e7d5 100644
--- a/src/com/android/wallpaper/model/wallpaper/LiveWallpaperData.kt
+++ b/src/com/android/wallpaper/model/wallpaper/LiveWallpaperData.kt
@@ -21,7 +21,6 @@
 /** Represents set of attributes that are specific to live wallpapers. */
 data class LiveWallpaperData(
     val groupName: String,
-    val isDownloadable: Boolean,
     val systemWallpaperInfo: WallpaperInfo,
     val isTitleVisible: Boolean,
     val isApplied: Boolean,
diff --git a/src/com/android/wallpaper/model/wallpaper/WallpaperModel.kt b/src/com/android/wallpaper/model/wallpaper/WallpaperModel.kt
index 2d09da3..ac33dd7 100644
--- a/src/com/android/wallpaper/model/wallpaper/WallpaperModel.kt
+++ b/src/com/android/wallpaper/model/wallpaper/WallpaperModel.kt
@@ -40,6 +40,7 @@
         override val commonWallpaperData: CommonWallpaperData,
         val staticWallpaperData: StaticWallpaperData,
         val imageWallpaperData: ImageWallpaperData?,
-        val networkWallpaperData: NetworkWallpaperData?
+        val networkWallpaperData: NetworkWallpaperData?,
+        val downloadableWallpaperData: DownloadableWallpaperData?,
     ) : WallpaperModel()
 }
diff --git a/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt b/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
index 552bfc5..d135020 100755
--- a/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
+++ b/src/com/android/wallpaper/module/WallpaperPicker2Injector.kt
@@ -26,8 +26,6 @@
 import androidx.lifecycle.LifecycleOwner
 import com.android.customization.model.color.WallpaperColorResources
 import com.android.wallpaper.config.BaseFlags
-import com.android.wallpaper.dispatchers.BackgroundDispatcher
-import com.android.wallpaper.dispatchers.MainDispatcher
 import com.android.wallpaper.effects.EffectsController
 import com.android.wallpaper.model.CategoryProvider
 import com.android.wallpaper.model.InlinePreviewIntentFactory
@@ -49,6 +47,8 @@
 import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository
 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperSnapshotRestorer
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
+import com.android.wallpaper.picker.di.modules.MainDispatcher
 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
diff --git a/src/com/android/wallpaper/picker/LivePreviewFragment.java b/src/com/android/wallpaper/picker/LivePreviewFragment.java
index 2d7b13b..4c09e6f 100644
--- a/src/com/android/wallpaper/picker/LivePreviewFragment.java
+++ b/src/com/android/wallpaper/picker/LivePreviewFragment.java
@@ -604,8 +604,8 @@
                     mWallpaperSurface,
                     null,
                     mIsViewAsHome ? FLAG_SYSTEM : FLAG_LOCK,
-                    mIsAssetIdPresent ? WallpaperConnection.WHICH_PREVIEW.EDIT_NON_CURRENT
-                            : WallpaperConnection.WHICH_PREVIEW.EDIT_CURRENT);
+                    mIsAssetIdPresent ? WallpaperConnection.WhichPreview.EDIT_NON_CURRENT
+                            : WallpaperConnection.WhichPreview.EDIT_CURRENT);
             mWallpaperConnection.setVisibility(true);
         } else {
             WallpaperColorsLoader.getWallpaperColors(
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 ebb9ec0..46b2c1a 100644
--- a/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/customization/ui/binder/ScreenPreviewBinder.kt
@@ -563,7 +563,7 @@
             wallpaperSurface,
             mirrorSurface,
             screen.toFlag(),
-            WallpaperConnection.WHICH_PREVIEW.PREVIEW_CURRENT
+            WallpaperConnection.WhichPreview.PREVIEW_CURRENT
         )
 
     private fun removeAndReadd(view: View) {
diff --git a/src/com/android/wallpaper/dispatchers/DispatchersModule.kt b/src/com/android/wallpaper/picker/di/modules/DispatchersModule.kt
similarity index 96%
rename from src/com/android/wallpaper/dispatchers/DispatchersModule.kt
rename to src/com/android/wallpaper/picker/di/modules/DispatchersModule.kt
index 2bdfd71..e78d085 100644
--- a/src/com/android/wallpaper/dispatchers/DispatchersModule.kt
+++ b/src/com/android/wallpaper/picker/di/modules/DispatchersModule.kt
@@ -12,10 +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.
- *
  */
 
-package com.android.wallpaper.dispatchers
+package com.android.wallpaper.picker.di.modules
 
 import dagger.Module
 import dagger.Provides
diff --git a/src/com/android/wallpaper/picker/di/modules/RepositoryModule.kt b/src/com/android/wallpaper/picker/di/modules/RepositoryModule.kt
index 1b30b0d..25a6697 100644
--- a/src/com/android/wallpaper/picker/di/modules/RepositoryModule.kt
+++ b/src/com/android/wallpaper/picker/di/modules/RepositoryModule.kt
@@ -17,8 +17,6 @@
 
 import android.app.WallpaperManager
 import android.content.Context
-import com.android.wallpaper.dispatchers.BackgroundDispatcher
-import com.android.wallpaper.dispatchers.MainDispatcher
 import com.android.wallpaper.module.WallpaperPreferences
 import com.android.wallpaper.picker.customization.data.content.WallpaperClient
 import com.android.wallpaper.picker.customization.data.content.WallpaperClientImpl
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 30a2de3..de18603 100644
--- a/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt
+++ b/src/com/android/wallpaper/picker/preview/domain/interactor/PreviewActionsInteractor.kt
@@ -16,9 +16,9 @@
 
 package com.android.wallpaper.picker.preview.domain.interactor
 
-import com.android.wallpaper.dispatchers.BackgroundDispatcher
-import com.android.wallpaper.dispatchers.MainDispatcher
 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.picker.preview.data.repository.WallpaperPreviewRepository
 import dagger.hilt.android.scopes.ActivityRetainedScoped
 import javax.inject.Inject
diff --git a/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt b/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
index c11657c..c724b86 100644
--- a/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/WallpaperPreviewActivity.kt
@@ -24,7 +24,6 @@
 import androidx.activity.viewModels
 import androidx.core.view.WindowCompat
 import com.android.wallpaper.R
-import com.android.wallpaper.model.LiveWallpaperInfo
 import com.android.wallpaper.model.WallpaperInfo
 import com.android.wallpaper.model.wallpaper.WallpaperModel
 import com.android.wallpaper.picker.AppbarFragment
@@ -33,7 +32,7 @@
 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.converter.DefaultWallpaperModelFactory
+import com.android.wallpaper.util.converter.WallpaperModelFactory
 import dagger.hilt.android.AndroidEntryPoint
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
@@ -45,7 +44,7 @@
     private val viewModel: WallpaperPreviewViewModel by viewModels()
     @ApplicationContext @Inject lateinit var appContext: Context
     @Inject lateinit var displayUtils: DisplayUtils
-    @Inject lateinit var wallpaperModelFactory: DefaultWallpaperModelFactory
+    @Inject lateinit var wallpaperModelFactory: WallpaperModelFactory
     @Inject lateinit var wallpaperPreviewRepository: WallpaperPreviewRepository
 
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -57,7 +56,8 @@
         WindowCompat.setDecorFitsSystemWindows(window, ActivityUtils.isSUWMode(this))
         val wallpaper =
             checkNotNull(intent.getParcelableExtra(EXTRA_WALLPAPER_INFO, WallpaperInfo::class.java))
-        wallpaperPreviewRepository.setWallpaperModel(wallpaper.convertToWallpaperModel())
+                .convertToWallpaperModel()
+        wallpaperPreviewRepository.setWallpaperModel(wallpaper)
     }
 
     override fun onUpArrowPressed() {
@@ -80,11 +80,7 @@
     }
 
     private fun WallpaperInfo.convertToWallpaperModel(): WallpaperModel {
-        return if (this is LiveWallpaperInfo) {
-            wallpaperModelFactory.getWallpaperModel(appContext, this)
-        } else {
-            wallpaperModelFactory.getWallpaperModel(appContext, this)
-        }
+        return wallpaperModelFactory.getWallpaperModel(appContext, this)
     }
 
     companion object {
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 dfed897..b77ef97 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
@@ -28,9 +28,9 @@
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.wallpaper.R
-import com.android.wallpaper.dispatchers.MainDispatcher
 import com.android.wallpaper.model.wallpaper.WallpaperModel
 import com.android.wallpaper.picker.TouchForwardingLayout
+import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.util.FullResImageViewUtil.getCropRect
 import com.android.wallpaper.picker.preview.ui.util.SurfaceViewUtil
 import com.android.wallpaper.picker.preview.ui.util.SurfaceViewUtil.attachView
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 a360de4..a8553dc 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewActionsBinder.kt
@@ -15,10 +15,15 @@
  */
 package com.android.wallpaper.picker.preview.ui.binder
 
+import android.content.Intent
+import android.net.Uri
+import android.view.View
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.wallpaper.module.logging.UserEventLogger
+import com.android.wallpaper.picker.preview.ui.view.PreviewActionFloatingSheet
 import com.android.wallpaper.picker.preview.ui.view.PreviewActionGroup
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.CUSTOMIZE
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.DELETE
@@ -28,70 +33,148 @@
 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.PreviewActionsViewModel
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
 import kotlinx.coroutines.launch
 
 /** Binds the action buttons and bottom sheet to [PreviewActionsViewModel] */
 object PreviewActionsBinder {
     fun bind(
-        view: PreviewActionGroup,
+        actionGroup: PreviewActionGroup,
+        floatingSheet: PreviewActionFloatingSheet,
         viewModel: PreviewActionsViewModel,
         lifecycleOwner: LifecycleOwner,
+        logger: UserEventLogger,
     ) {
+        val floatingSheetCallback =
+            object : BottomSheetBehavior.BottomSheetCallback() {
+                override fun onStateChanged(view: View, newState: Int) {
+                    if (newState == STATE_HIDDEN) {
+                        viewModel.onDialogCollapsed()
+                    }
+                }
+
+                override fun onSlide(p0: View, p1: Float) {}
+            }
+        floatingSheet.addFloatingSheetCallback(floatingSheetCallback)
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
+                floatingSheet.addFloatingSheetCallback(floatingSheetCallback)
+            }
+            floatingSheet.removeFloatingSheetCallback(floatingSheetCallback)
+        }
+
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                 launch {
-                    viewModel.isInformationChecked.collect { view.setIsChecked(INFORMATION, it) }
+                    viewModel.isInformationChecked.collect {
+                        actionGroup.setIsChecked(INFORMATION, it)
+                    }
                 }
 
                 launch {
-                    viewModel.isInformationVisible.collect { view.setIsVisible(INFORMATION, it) }
+                    viewModel.isInformationVisible.collect {
+                        actionGroup.setIsVisible(INFORMATION, it)
+                    }
                 }
 
                 launch {
                     viewModel.onInformationClicked.collect {
-                        view.setClickListener(INFORMATION, it)
+                        actionGroup.setClickListener(INFORMATION, it)
                     }
                 }
 
-                launch { viewModel.isDownloadChecked.collect { view.setIsChecked(DOWNLOAD, it) } }
-
-                launch { viewModel.isDownloadVisible.collect { view.setIsVisible(DOWNLOAD, it) } }
-
                 launch {
-                    viewModel.onDownloadClicked.collect { view.setClickListener(DOWNLOAD, it) }
+                    viewModel.isDownloadChecked.collect { actionGroup.setIsChecked(DOWNLOAD, it) }
                 }
 
-                launch { viewModel.isDeleteChecked.collect { view.setIsChecked(DELETE, it) } }
-
-                launch { viewModel.isDeleteVisible.collect { view.setIsVisible(DELETE, it) } }
-
-                launch { viewModel.onDeleteClicked.collect { view.setClickListener(DELETE, it) } }
-
-                launch { viewModel.isEditChecked.collect { view.setIsChecked(EDIT, it) } }
-
-                launch { viewModel.isEditVisible.collect { view.setIsVisible(EDIT, it) } }
-
-                launch { viewModel.onEditClicked.collect { view.setClickListener(EDIT, it) } }
-
-                launch { viewModel.isCustomizeChecked.collect { view.setIsChecked(CUSTOMIZE, it) } }
-
-                launch { viewModel.isCustomizeVisible.collect { view.setIsVisible(CUSTOMIZE, it) } }
-
                 launch {
-                    viewModel.onCustomizeClicked.collect { view.setClickListener(CUSTOMIZE, it) }
+                    viewModel.isDownloadVisible.collect { actionGroup.setIsVisible(DOWNLOAD, it) }
                 }
 
-                launch { viewModel.isEffectsChecked.collect { view.setIsChecked(EFFECTS, it) } }
+                launch {
+                    viewModel.onDownloadClicked.collect {
+                        actionGroup.setClickListener(DOWNLOAD, it)
+                    }
+                }
 
-                launch { viewModel.isEffectsVisible.collect { view.setIsVisible(EFFECTS, it) } }
+                launch {
+                    viewModel.isDeleteChecked.collect { actionGroup.setIsChecked(DELETE, it) }
+                }
 
-                launch { viewModel.onEffectsClicked.collect { view.setClickListener(EFFECTS, it) } }
+                launch {
+                    viewModel.isDeleteVisible.collect { actionGroup.setIsVisible(DELETE, it) }
+                }
 
-                launch { viewModel.isShareChecked.collect { view.setIsChecked(SHARE, it) } }
+                launch {
+                    viewModel.onDeleteClicked.collect { actionGroup.setClickListener(DELETE, it) }
+                }
 
-                launch { viewModel.isShareVisible.collect { view.setIsVisible(SHARE, it) } }
+                launch { viewModel.isEditChecked.collect { actionGroup.setIsChecked(EDIT, it) } }
 
-                launch { viewModel.onShareClicked.collect { view.setClickListener(SHARE, 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 ->
+                        if (viewModel == null) {
+                            floatingSheet.collapse()
+                        } else {
+                            val onExploreButtonClicked =
+                                viewModel.exploreActionUrl?.let { url ->
+                                    {
+                                        logger.logWallpaperExploreButtonClicked()
+                                        val appContext = floatingSheet.context.applicationContext
+                                        appContext.startActivity(
+                                            Intent(Intent.ACTION_VIEW, Uri.parse(url))
+                                        )
+                                    }
+                                }
+                            floatingSheet.setInformationContent(
+                                viewModel.attributions,
+                                onExploreButtonClicked
+                            )
+                            floatingSheet.expand()
+                        }
+                    }
+                }
             }
         }
     }
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 828f83e..d3a63ad 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
@@ -20,10 +20,10 @@
 import android.view.View
 import androidx.lifecycle.LifecycleOwner
 import com.android.wallpaper.R
-import com.android.wallpaper.dispatchers.MainDispatcher
 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
 import kotlinx.coroutines.CoroutineScope
 
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 2b941f9..d6a70fa 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
@@ -22,10 +22,10 @@
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import com.android.wallpaper.R
-import com.android.wallpaper.dispatchers.MainDispatcher
 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.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
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 0020a44..4092fed 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
@@ -27,8 +27,8 @@
 import androidx.navigation.fragment.findNavController
 import androidx.transition.TransitionInflater
 import com.android.wallpaper.R
-import com.android.wallpaper.dispatchers.MainDispatcher
 import com.android.wallpaper.picker.AppbarFragment
+import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.binder.CropWallpaperButtonBinder
 import com.android.wallpaper.picker.preview.ui.binder.FullWallpaperPreviewBinder
 import com.android.wallpaper.picker.preview.ui.binder.WorkspacePreviewBinder
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 108dffb..31a4635 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
@@ -26,8 +26,9 @@
 import androidx.navigation.fragment.FragmentNavigatorExtras
 import androidx.navigation.fragment.findNavController
 import com.android.wallpaper.R
-import com.android.wallpaper.dispatchers.MainDispatcher
+import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.picker.AppbarFragment
+import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.ui.binder.DualPreviewSelectorBinder
 import com.android.wallpaper.picker.preview.ui.binder.PreviewActionsBinder
 import com.android.wallpaper.picker.preview.ui.binder.PreviewSelectorBinder
@@ -51,6 +52,7 @@
     @Inject @ApplicationContext lateinit var appContext: Context
     @Inject lateinit var displayUtils: DisplayUtils
     @Inject @MainDispatcher lateinit var mainScope: CoroutineScope
+    @Inject lateinit var logger: UserEventLogger
 
     private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>()
 
@@ -94,8 +96,10 @@
     private fun bindScreenPreview(view: View) {
         PreviewActionsBinder.bind(
             view.requireViewById(R.id.action_button_group),
+            view.requireViewById(R.id.floating_sheet),
             wallpaperPreviewViewModel.previewActionsViewModel,
             viewLifecycleOwner,
+            logger,
         )
         if (displayUtils.hasMultiInternalDisplays()) {
             val dualPreviewView: DualPreviewViewPager =
diff --git a/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt b/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt
new file mode 100644
index 0000000..f3513ba
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/view/PreviewActionFloatingSheet.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.FrameLayout
+import android.widget.TextView
+import androidx.core.view.isVisible
+import com.android.wallpaper.R
+import com.android.wallpaper.util.SizeCalculator
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
+
+/**
+ * UI that hosts the content of the floating sheet dialog sliding from the bottom when a
+ * correspondent preview action is toggled on.
+ */
+class PreviewActionFloatingSheet(context: Context, attrs: AttributeSet?) :
+    FrameLayout(context, attrs) {
+
+    private val floatingSheetView: ViewGroup
+    private val floatingSheetContainer: ViewGroup
+    private val floatingSheetBehavior: BottomSheetBehavior<ViewGroup>
+
+    init {
+        LayoutInflater.from(context).inflate(R.layout.floating_sheet2, this, true)
+        floatingSheetView = requireViewById(R.id.floating_sheet_content)
+        SizeCalculator.adjustBackgroundCornerRadius(floatingSheetView)
+        floatingSheetContainer = requireViewById(R.id.floating_sheet_container)
+        floatingSheetBehavior = BottomSheetBehavior.from(floatingSheetContainer)
+        floatingSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+    }
+
+    fun setInformationContent(
+        attributions: List<String?>?,
+        onExploreButtonClicked: (() -> Unit)?,
+    ) {
+        val view = LayoutInflater.from(context).inflate(R.layout.wallpaper_info_view2, this, false)
+        val title: TextView = view.requireViewById(R.id.wallpaper_info_title)
+        val subtitle1: TextView = view.requireViewById(R.id.wallpaper_info_subtitle1)
+        val subtitle2: TextView = view.requireViewById(R.id.wallpaper_info_subtitle2)
+        val exploreButton: Button = view.requireViewById(R.id.wallpaper_info_explore_button)
+        attributions?.forEachIndexed { index, text ->
+            when (index) {
+                0 -> {
+                    if (!text.isNullOrEmpty()) {
+                        title.text = text
+                        title.isVisible = true
+                    }
+                }
+                1 -> {
+                    if (!text.isNullOrEmpty()) {
+                        subtitle1.text = text
+                        subtitle1.isVisible = true
+                    }
+                }
+                2 -> {
+                    if (!text.isNullOrEmpty()) {
+                        subtitle2.text = text
+                        subtitle2.isVisible = true
+                    }
+                }
+            }
+            if (onExploreButtonClicked != null) {
+                exploreButton.isVisible = true
+                exploreButton.setOnClickListener { onExploreButtonClicked.invoke() }
+            }
+        }
+        floatingSheetView.removeAllViews()
+        floatingSheetView.addView(view)
+    }
+
+    fun expand() {
+        floatingSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
+    }
+
+    fun collapse() {
+        floatingSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+    }
+
+    /**
+     * Adds Floating Sheet Callback to connected [BottomSheetBehavior].
+     *
+     * @param callback the callback for floating sheet state changes, has to be in the type of
+     *   [BottomSheetBehavior.BottomSheetCallback] since the floating sheet behavior is currently
+     *   based on [BottomSheetBehavior]
+     */
+    fun addFloatingSheetCallback(callback: BottomSheetCallback) {
+        floatingSheetBehavior.addBottomSheetCallback(callback)
+    }
+
+    fun removeFloatingSheetCallback(callback: BottomSheetCallback) {
+        floatingSheetBehavior.removeBottomSheetCallback(callback)
+    }
+}
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 c665146..baff813 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewActionsViewModel.kt
@@ -16,6 +16,8 @@
 
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
+import com.android.wallpaper.model.wallpaper.WallpaperModel
+import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.picker.preview.domain.interactor.PreviewActionsInteractor
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.CUSTOMIZE
 import com.android.wallpaper.picker.preview.ui.viewmodel.Action.DELETE
@@ -24,14 +26,15 @@
 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.InfoFloatingSheetViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.floatingSheet.InformationFloatingSheetViewModel
 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
 import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 
 /** View model for the preview action buttons */
@@ -40,13 +43,27 @@
 @Inject
 constructor(
     interactor: PreviewActionsInteractor,
+    @MainDispatcher private val scope: CoroutineScope,
 ) {
-    /** Action's isVisible state */
-    private val _isInformationVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isInformationVisible: Flow<Boolean> = _isInformationVisible.asStateFlow()
+    private val _informationFloatingSheetViewModel: Flow<InformationFloatingSheetViewModel?> =
+        interactor.wallpaperModel.map { wallpaperModel ->
+            if (wallpaperModel == null || !wallpaperModel.shouldShowInformationFloatingSheet()) {
+                null
+            } else {
+                InformationFloatingSheetViewModel(
+                    wallpaperModel.commonWallpaperData.attributions,
+                    wallpaperModel.commonWallpaperData.exploreActionUrl,
+                )
+            }
+        }
 
-    private val _isDownloadVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    val isDownloadVisible: Flow<Boolean> = _isDownloadVisible.asStateFlow()
+    /** 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()
@@ -85,6 +102,20 @@
     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.
+     */
+    val informationFloatingSheetViewModel: Flow<InformationFloatingSheetViewModel?> =
+        combine(isInformationChecked, _informationFloatingSheetViewModel) { checked, viewModel ->
+                if (checked && viewModel != null) {
+                    viewModel
+                } else {
+                    null
+                }
+            }
+            .distinctUntilChanged()
+
     /** Action listeners */
     val onInformationClicked: Flow<(() -> Unit)?> =
         combine(isInformationVisible, isInformationChecked) { show, isChecked ->
@@ -208,15 +239,33 @@
         }
     }
 
-    /** This flow emits the view data for the info button bottom sheet */
-    val infoButtonAndFloatingSheetViewModel: Flow<InfoFloatingSheetViewModel> =
-        interactor.wallpaperModel.filterNotNull().map { wallpaperModel ->
-            InfoFloatingSheetViewModel(wallpaperModel)
+    fun onDialogCollapsed() {
+        if (_isInformationChecked.value) {
+            _isInformationChecked.value = false
         }
+    }
 
-    /** This flow expresses the visibility state of the info button */
-    val showInfoButton: Flow<Boolean> =
-        interactor.wallpaperModel.map { wallpaperModel -> wallpaperModel != null }
+    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 &&
+                    !liveWallpaperData.systemWallpaperInfo.showMetadataInPreview
+            ) {
+                // If the live wallpaper's flag of showMetadataInPreview is false, do not show the
+                // information floating sheet.
+                false
+            } else {
+                true
+            }
+        }
+    }
 }
 
 enum class Action {
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 e2467e4..bf56188 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
@@ -23,10 +23,10 @@
 import android.graphics.Point
 import android.graphics.Rect
 import com.android.wallpaper.asset.Asset
-import com.android.wallpaper.dispatchers.BackgroundDispatcher
 import com.android.wallpaper.model.wallpaper.ScreenOrientation
 import com.android.wallpaper.model.wallpaper.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.module.WallpaperPreferences
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
 import com.android.wallpaper.picker.preview.domain.interactor.WallpaperPreviewInteractor
 import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity
 import dagger.hilt.android.qualifiers.ApplicationContext
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/InformationFloatingSheetViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/InformationFloatingSheetViewModel.kt
new file mode 100644
index 0000000..c14bd79
--- /dev/null
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/floatingSheet/InformationFloatingSheetViewModel.kt
@@ -0,0 +1,23 @@
+/*
+ * 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
+
+/** This data class represents the view data for the info floating sheet */
+data class InformationFloatingSheetViewModel(
+    val attributions: List<String?>?,
+    val exploreActionUrl: String?,
+)
diff --git a/src/com/android/wallpaper/util/WallpaperConnection.java b/src/com/android/wallpaper/util/WallpaperConnection.java
index ca3febf..d3150bb 100644
--- a/src/com/android/wallpaper/util/WallpaperConnection.java
+++ b/src/com/android/wallpaper/util/WallpaperConnection.java
@@ -62,11 +62,10 @@
 public class WallpaperConnection extends IWallpaperConnection.Stub implements ServiceConnection {
 
     /**
-     * Defines the different possible scenarios for which we need to dispatch a command
-     * from picker to the wallpaper.
+     * Defines different possible scenarios for which we need to dispatch a command from picker to
+     * the wallpaper.
      */
-
-    public enum WHICH_PREVIEW {
+    public enum WhichPreview {
         /**
          * Represents the case when we preview a currently applied wallpaper (home/lock) simply
          * by tapping on it.
@@ -83,7 +82,7 @@
 
         private final int mValue;
 
-        WHICH_PREVIEW(int value) {
+        WhichPreview(int value) {
             this.mValue = value;
         }
 
@@ -120,7 +119,7 @@
     private boolean mEngineReady;
     private boolean mDestroyed;
     private int mDestinationFlag;
-    private WHICH_PREVIEW mWhichPreview;
+    private WhichPreview mWhichPreview;
 
     /**
      * @param intent used to bind the wallpaper service
@@ -130,7 +129,7 @@
      */
     public WallpaperConnection(Intent intent, Context context,
             @Nullable WallpaperConnectionListener listener, @NonNull SurfaceView containerView,
-            WHICH_PREVIEW preview) {
+            WhichPreview preview) {
         this(intent, context, listener, containerView, null, null,
                 preview);
     }
@@ -150,7 +149,7 @@
             @Nullable WallpaperConnectionListener listener, @NonNull SurfaceView containerView,
             @Nullable SurfaceView secondaryContainerView,
             @Nullable @WallpaperManager.SetWallpaperFlags Integer destinationFlag,
-            WHICH_PREVIEW preview) {
+            WhichPreview preview) {
         mContext = context.getApplicationContext();
         mIntent = intent;
         mListener = listener;
diff --git a/src/com/android/wallpaper/util/converter/CommonWallpaperDataFactory.kt b/src/com/android/wallpaper/util/converter/CommonWallpaperDataFactory.kt
deleted file mode 100644
index 6c5cc0e..0000000
--- a/src/com/android/wallpaper/util/converter/CommonWallpaperDataFactory.kt
+++ /dev/null
@@ -1,106 +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.util.converter
-
-import android.app.WallpaperManager
-import android.content.ComponentName
-import android.content.Context
-import android.util.Log
-import com.android.wallpaper.model.CurrentWallpaperInfo
-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.Destination
-import com.android.wallpaper.model.wallpaper.WallpaperId
-
-/**
- * This class is responsible for creating CommonWallpaperData object. It achieves this in two ways:
- *
- * A. By utilizing instances of wallpaperInfo class, which provide attributes common to both new and
- * old classes.
- *
- * B. By directly passing the other attributes required to construct the CommonWallpaperData object.
- */
-class CommonWallpaperDataFactory {
-
-    companion object {
-        private const val TAG = "CommonWallpaperDataFactory"
-
-        const val STATIC_WALLPAPER_PACKAGE = "StaticWallpaperPackage"
-        const val STATIC_WALLPAPER_CLASS = "StaticWallpaperClass"
-        private const val UNKNOWN_COLLECTION_ID = "unknown_collection_id"
-
-        fun getCommonWallpaperData(
-            wallpaperInfo: WallpaperInfo,
-            context: Context
-        ): CommonWallpaperData {
-
-            var wallpaperDestination = Destination.NOT_APPLIED
-            if (wallpaperInfo is CurrentWallpaperInfo) {
-                wallpaperDestination =
-                    when (wallpaperInfo.wallpaperManagerFlag) {
-                        WallpaperManager.FLAG_SYSTEM -> Destination.APPLIED_TO_SYSTEM
-                        WallpaperManager.FLAG_LOCK -> Destination.APPLIED_TO_LOCK
-                        WallpaperManager.FLAG_LOCK and WallpaperManager.FLAG_SYSTEM ->
-                            Destination.APPLIED_TO_SYSTEM_LOCK
-                        else -> {
-                            Log.w(
-                                TAG,
-                                "Invalid value for wallpaperManagerFlag: " +
-                                    wallpaperInfo.wallpaperManagerFlag
-                            )
-                            Destination.NOT_APPLIED
-                        }
-                    }
-            }
-
-            // componentName is a valid value for liveWallpapers, for other types of wallpapers
-            // (which are static) we can have a constant value
-            val componentName =
-                if (wallpaperInfo is LiveWallpaperInfo) {
-                    wallpaperInfo.wallpaperComponent.component
-                } else {
-                    ComponentName(STATIC_WALLPAPER_PACKAGE, STATIC_WALLPAPER_CLASS)
-                }
-
-            val wallpaperId =
-                WallpaperId(
-                    componentName = componentName,
-                    uniqueId = wallpaperInfo.wallpaperId,
-                    // TODO(b/308800470): Figure out the use of collection ID
-                    collectionId = wallpaperInfo.getCollectionId(context) ?: UNKNOWN_COLLECTION_ID,
-                )
-
-            val colorInfoOfWallpaper =
-                ColorInfo(
-                    wallpaperInfo.colorInfo.wallpaperColors,
-                    wallpaperInfo.colorInfo.placeholderColor
-                )
-
-            return CommonWallpaperData(
-                id = wallpaperId,
-                title = wallpaperInfo.getTitle(context),
-                attributions = wallpaperInfo.getAttributions(context),
-                exploreActionUrl = wallpaperInfo.getActionUrl(context),
-                thumbAsset = wallpaperInfo.getThumbAsset(context),
-                placeholderColorInfo = colorInfoOfWallpaper,
-                destination = wallpaperDestination,
-            )
-        }
-    }
-}
diff --git a/src/com/android/wallpaper/util/converter/DefaultLiveWallpaperDataFactory.kt b/src/com/android/wallpaper/util/converter/DefaultLiveWallpaperDataFactory.kt
deleted file mode 100644
index 447e75c..0000000
--- a/src/com/android/wallpaper/util/converter/DefaultLiveWallpaperDataFactory.kt
+++ /dev/null
@@ -1,86 +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.util.converter
-
-import android.app.WallpaperManager
-import android.app.WallpaperManager.FLAG_LOCK
-import android.app.WallpaperManager.FLAG_SYSTEM
-import android.content.Context
-import com.android.wallpaper.model.CreativeWallpaperInfo
-import com.android.wallpaper.model.LiveWallpaperInfo
-import com.android.wallpaper.model.wallpaper.CreativeWallpaperData
-import com.android.wallpaper.model.wallpaper.LiveWallpaperData
-
-/**
- * This class is responsible for creating various data classes for LiveWallpaperModel. It achieves
- * this in two ways:
- *
- * A. By utilizing instances of different types of WallpaperInfo classes, which provide attributes
- * common to both new and old classes.
- *
- * B. By directly passing the necessary attributes required to construct the objects.
- *
- * The methods in this class should only be used to create an instance of LiveWallpaperModel.
- */
-open class DefaultLiveWallpaperDataFactory {
-
-    /**
-     * Creates an instance of CreativeWallpaperData object.
-     *
-     * @param wallpaperInfo reference to object of CreativeWallpaperInfo that is used for attributes
-     *   common to the old and new model class.
-     */
-    fun getCreativeWallpaperData(wallpaperInfo: LiveWallpaperInfo): CreativeWallpaperData? {
-        return (wallpaperInfo as? CreativeWallpaperInfo)?.let {
-            CreativeWallpaperData(
-                configPreviewUri = it.configPreviewUri,
-                cleanPreviewUri = it.cleanPreviewUri,
-                deleteUri = it.deleteUri,
-                thumbnailUri = it.thumbnailUri,
-                shareUri = it.shareUri,
-                author = it.author ?: "",
-                description = it.description ?: "",
-                contentDescription = it.contentDescription,
-                isCurrent = it.isCurrent.toString() // Convert boolean to String
-            )
-        }
-    }
-
-    /**
-     * Creates an instance of LiveWallpaperData object.
-     *
-     * @param wallpaperInfo: Reference to object of LiveWallpaperInfo that is used for attributes
-     *   common to the old and new model class.
-     */
-    open fun getLiveWallpaperData(
-        wallpaperInfo: LiveWallpaperInfo,
-        context: Context
-    ): LiveWallpaperData {
-        val groupNameOfWallpaper = (wallpaperInfo as? CreativeWallpaperInfo)?.groupName ?: ""
-        val wallpaperManager = WallpaperManager.getInstance(context)
-        val currentHomeWallpaper = wallpaperManager.getWallpaperInfo(FLAG_SYSTEM)
-        val currentLockWallpaper = wallpaperManager.getWallpaperInfo(FLAG_LOCK)
-        return LiveWallpaperData(
-            groupName = groupNameOfWallpaper,
-            isDownloadable = false,
-            systemWallpaperInfo = wallpaperInfo.info,
-            isTitleVisible = wallpaperInfo.isVisibleTitle,
-            isApplied = wallpaperInfo.isApplied(currentHomeWallpaper, currentLockWallpaper),
-            effectNames = wallpaperInfo.effectNames,
-        )
-    }
-}
diff --git a/src/com/android/wallpaper/util/converter/DefaultStaticWallpaperDataFactory.kt b/src/com/android/wallpaper/util/converter/DefaultStaticWallpaperDataFactory.kt
deleted file mode 100644
index 6109a92..0000000
--- a/src/com/android/wallpaper/util/converter/DefaultStaticWallpaperDataFactory.kt
+++ /dev/null
@@ -1,69 +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.util.converter
-
-import android.content.Context
-import com.android.wallpaper.model.ImageWallpaperInfo
-import com.android.wallpaper.model.LiveWallpaperInfo
-import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.model.wallpaper.ImageWallpaperData
-import com.android.wallpaper.model.wallpaper.StaticWallpaperData
-
-/**
- * This class is responsible for creating various data classes for LiveWallpaperModel. It achieves
- * this in two ways:
- *
- * A. By utilizing instances of different types of WallpaperInfo classes, which provide attributes
- * common to both new and old classes.
- *
- * B. By directly passing the necessary attributes required to construct the objects.
- *
- * The methods in this class should only be used to create an instance of StaticWallpaperModel.
- */
-open class DefaultStaticWallpaperDataFactory {
-
-    /**
-     * Creates an instance of StaticWallpaperData.
-     *
-     * @param wallpaperAsset: Refers to the asset that the static wallpaper data class would
-     *   contain.
-     */
-    open fun getStaticWallpaperData(
-        wallpaperInfo: WallpaperInfo,
-        context: Context
-    ): StaticWallpaperData {
-        return if (wallpaperInfo !is LiveWallpaperInfo) {
-            StaticWallpaperData(asset = wallpaperInfo.getAsset(context))
-        } else {
-            throw IllegalArgumentException(
-                "Invalid wallpaperInfo type: ${wallpaperInfo::class.simpleName}"
-            )
-        }
-    }
-
-    /**
-     * Creates an instance of ImageWallpaperData.
-     *
-     * @param wallpaperInfo: Refers to the object of ImageWallpaperInfo that is used for creating an
-     *   object of type ImageWallpaperData.
-     */
-    fun getImageWallpaperData(wallpaperInfo: WallpaperInfo): ImageWallpaperData? {
-        return if (wallpaperInfo is ImageWallpaperInfo) {
-            ImageWallpaperData(wallpaperInfo.uri)
-        } else null
-    }
-}
diff --git a/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt b/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt
index 9dd2207..b5e2ae4 100644
--- a/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt
+++ b/src/com/android/wallpaper/util/converter/DefaultWallpaperModelFactory.kt
@@ -17,61 +17,40 @@
 package com.android.wallpaper.util.converter
 
 import android.content.Context
+import com.android.wallpaper.model.CreativeWallpaperInfo
+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.util.converter.WallpaperModelFactory.Companion.getCommonWallpaperData
+import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getCreativeWallpaperData
+import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getImageWallpaperData
+import com.android.wallpaper.util.converter.WallpaperModelFactory.Companion.getLiveWallpaperData
+import javax.inject.Inject
+import javax.inject.Singleton
 
-/**
- * This class is responsible for creating an instance of Live/Static WallpaperModel from the given
- * wallpaperInfo object.
- */
-open class DefaultWallpaperModelFactory {
+@Singleton
+class DefaultWallpaperModelFactory @Inject constructor() : WallpaperModelFactory {
 
-    private val defaultLiveWallpaperDataFactory = DefaultLiveWallpaperDataFactory()
-    private val defaultStaticWallpaperDataFactory = DefaultStaticWallpaperDataFactory()
-
-    /**
-     * Composes an instance of LiveWallpaperModel depending on the type of WallpaperInfo object.
-     *
-     * @param context: context of the application
-     * @param wallpaperInfo: wallpaperInfo object for the wallpaper being converted to the new model
-     *   class
-     */
-    open fun getWallpaperModel(
-        context: Context,
-        wallpaperInfo: LiveWallpaperInfo
-    ): WallpaperModel.LiveWallpaperModel {
-        return WallpaperModel.LiveWallpaperModel(
-            commonWallpaperData =
-                CommonWallpaperDataFactory.getCommonWallpaperData(wallpaperInfo, context),
-            liveWallpaperData =
-                defaultLiveWallpaperDataFactory.getLiveWallpaperData(wallpaperInfo, context),
-            creativeWallpaperData =
-                defaultLiveWallpaperDataFactory.getCreativeWallpaperData(wallpaperInfo),
-            internalLiveWallpaperData = null
-        )
-    }
-
-    /**
-     * Composes an instance of StaticWallpaperModel depending the type of WallpaperInfo object. This
-     * will throw an exception in case you pass any type of LiveWallpaperInfo object to this method.
-     *
-     * @param context: context of the application
-     * @param wallpaperInfo: wallpaperInfo object for the wallpaper being converted to the new model
-     *   class
-     */
-    open fun getWallpaperModel(
-        context: Context,
-        wallpaperInfo: WallpaperInfo
-    ): WallpaperModel.StaticWallpaperModel {
-        return WallpaperModel.StaticWallpaperModel(
-            commonWallpaperData =
-                CommonWallpaperDataFactory.getCommonWallpaperData(wallpaperInfo, context),
-            staticWallpaperData =
-                defaultStaticWallpaperDataFactory.getStaticWallpaperData(wallpaperInfo, context),
-            imageWallpaperData =
-                defaultStaticWallpaperDataFactory.getImageWallpaperData(wallpaperInfo),
-            networkWallpaperData = null
-        )
+    override fun getWallpaperModel(context: Context, wallpaperInfo: WallpaperInfo): WallpaperModel {
+        return if (wallpaperInfo is LiveWallpaperInfo) {
+            WallpaperModel.LiveWallpaperModel(
+                commonWallpaperData = wallpaperInfo.getCommonWallpaperData(context),
+                liveWallpaperData = wallpaperInfo.getLiveWallpaperData(context),
+                creativeWallpaperData =
+                    (wallpaperInfo as? CreativeWallpaperInfo)?.getCreativeWallpaperData(),
+                internalLiveWallpaperData = null,
+            )
+        } else {
+            WallpaperModel.StaticWallpaperModel(
+                commonWallpaperData = wallpaperInfo.getCommonWallpaperData(context),
+                staticWallpaperData = StaticWallpaperData(asset = wallpaperInfo.getAsset(context)),
+                imageWallpaperData =
+                    (wallpaperInfo as? ImageWallpaperInfo)?.getImageWallpaperData(),
+                networkWallpaperData = null,
+                downloadableWallpaperData = null,
+            )
+        }
     }
 }
diff --git a/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt b/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
new file mode 100644
index 0000000..4c0927d
--- /dev/null
+++ b/src/com/android/wallpaper/util/converter/WallpaperModelFactory.kt
@@ -0,0 +1,133 @@
+/*
+ * 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.util.converter
+
+import android.app.WallpaperManager
+import android.content.ComponentName
+import android.content.Context
+import android.util.Log
+import com.android.wallpaper.model.CreativeWallpaperInfo
+import com.android.wallpaper.model.CurrentWallpaperInfo
+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
+
+/** This class creates an instance of [WallpaperModel] from a given [WallpaperInfo] object. */
+interface WallpaperModelFactory {
+
+    fun getWallpaperModel(context: Context, wallpaperInfo: WallpaperInfo): WallpaperModel
+
+    companion object {
+
+        const val STATIC_WALLPAPER_PACKAGE = "StaticWallpaperPackage"
+        const val STATIC_WALLPAPER_CLASS = "StaticWallpaperClass"
+
+        private const val TAG = "WallpaperModelFactory"
+        private const val UNKNOWN_COLLECTION_ID = "unknown_collection_id"
+
+        fun WallpaperInfo.getCommonWallpaperData(context: Context): CommonWallpaperData {
+            var wallpaperDestination = Destination.NOT_APPLIED
+            if (this is CurrentWallpaperInfo) {
+                wallpaperDestination =
+                    when (wallpaperManagerFlag) {
+                        WallpaperManager.FLAG_SYSTEM -> Destination.APPLIED_TO_SYSTEM
+                        WallpaperManager.FLAG_LOCK -> Destination.APPLIED_TO_LOCK
+                        WallpaperManager.FLAG_LOCK and WallpaperManager.FLAG_SYSTEM ->
+                            Destination.APPLIED_TO_SYSTEM_LOCK
+                        else -> {
+                            Log.w(
+                                TAG,
+                                "Invalid value for wallpaperManagerFlag: $wallpaperManagerFlag"
+                            )
+                            Destination.NOT_APPLIED
+                        }
+                    }
+            }
+
+            // componentName is a valid value for liveWallpapers, for other types of wallpapers
+            // (which are static) we can have a constant value
+            val componentName =
+                if (this is LiveWallpaperInfo) {
+                    wallpaperComponent.component
+                } else {
+                    ComponentName(STATIC_WALLPAPER_PACKAGE, STATIC_WALLPAPER_CLASS)
+                }
+
+            val wallpaperId =
+                WallpaperId(
+                    componentName = componentName,
+                    uniqueId = wallpaperId,
+                    // TODO(b/308800470): Figure out the use of collection ID
+                    collectionId = getCollectionId(context) ?: UNKNOWN_COLLECTION_ID,
+                )
+
+            val colorInfoOfWallpaper =
+                ColorInfo(colorInfo.wallpaperColors, colorInfo.placeholderColor)
+
+            return CommonWallpaperData(
+                id = wallpaperId,
+                title = getTitle(context),
+                attributions = getAttributions(context),
+                exploreActionUrl = getActionUrl(context),
+                thumbAsset = getThumbAsset(context),
+                placeholderColorInfo = colorInfoOfWallpaper,
+                destination = wallpaperDestination,
+            )
+        }
+
+        fun LiveWallpaperInfo.getLiveWallpaperData(context: Context): LiveWallpaperData {
+            val groupNameOfWallpaper = (this as? CreativeWallpaperInfo)?.groupName ?: ""
+            val wallpaperManager = WallpaperManager.getInstance(context)
+            val currentHomeWallpaper =
+                wallpaperManager.getWallpaperInfo(WallpaperManager.FLAG_SYSTEM)
+            val currentLockWallpaper = wallpaperManager.getWallpaperInfo(WallpaperManager.FLAG_LOCK)
+            return LiveWallpaperData(
+                groupName = groupNameOfWallpaper,
+                systemWallpaperInfo = info,
+                isTitleVisible = isVisibleTitle,
+                isApplied = isApplied(currentHomeWallpaper, currentLockWallpaper),
+                effectNames = effectNames,
+            )
+        }
+
+        fun CreativeWallpaperInfo.getCreativeWallpaperData(): CreativeWallpaperData {
+            return CreativeWallpaperData(
+                configPreviewUri = configPreviewUri,
+                cleanPreviewUri = cleanPreviewUri,
+                deleteUri = deleteUri,
+                thumbnailUri = thumbnailUri,
+                shareUri = shareUri,
+                author = author ?: "",
+                description = description ?: "",
+                contentDescription = contentDescription,
+                isCurrent = isCurrent.toString() // Convert boolean to String
+            )
+        }
+
+        fun ImageWallpaperInfo.getImageWallpaperData(): ImageWallpaperData {
+            return ImageWallpaperData(uri)
+        }
+    }
+}
diff --git a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
index e2cc150..69a8d06 100644
--- a/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
+++ b/src/com/android/wallpaper/util/wallpaperconnection/WallpaperConnectionUtils.kt
@@ -14,7 +14,7 @@
 import android.view.SurfaceControl
 import android.view.SurfaceView
 import android.view.View
-import com.android.wallpaper.dispatchers.MainDispatcher
+import com.android.wallpaper.picker.di.modules.MainDispatcher
 import com.android.wallpaper.util.ScreenSizeCalculator
 import com.android.wallpaper.util.WallpaperConnection
 import kotlinx.coroutines.CancellableContinuation
diff --git a/src_override/com/android/wallpaper/module/AppModule.kt b/src_override/com/android/wallpaper/module/AppModule.kt
index 6fcf837..f992b53 100644
--- a/src_override/com/android/wallpaper/module/AppModule.kt
+++ b/src_override/com/android/wallpaper/module/AppModule.kt
@@ -19,6 +19,7 @@
 import com.android.wallpaper.module.logging.NoOpUserEventLogger
 import com.android.wallpaper.module.logging.UserEventLogger
 import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
+import com.android.wallpaper.util.converter.WallpaperModelFactory
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
@@ -32,6 +33,12 @@
 abstract class AppModule {
     @Binds @Singleton abstract fun bindInjector(impl: WallpaperPicker2Injector): Injector
 
+    @Binds
+    @Singleton
+    abstract fun bindWallpaperModelFactory(
+        impl: DefaultWallpaperModelFactory
+    ): WallpaperModelFactory
+
     companion object {
         @Provides
         @Singleton
@@ -46,11 +53,5 @@
         fun provideUserEventLogger(): UserEventLogger {
             return NoOpUserEventLogger()
         }
-
-        @Provides
-        @Singleton
-        fun provideDefaultWallpaperModelFactory(): DefaultWallpaperModelFactory {
-            return DefaultWallpaperModelFactory()
-        }
     }
 }
diff --git a/tests/module/src/com/android/wallpaper/TestModule.kt b/tests/module/src/com/android/wallpaper/TestModule.kt
index de407ba..d24d02d 100644
--- a/tests/module/src/com/android/wallpaper/TestModule.kt
+++ b/tests/module/src/com/android/wallpaper/TestModule.kt
@@ -23,9 +23,9 @@
 import com.android.wallpaper.testing.TestInjector
 import com.android.wallpaper.testing.TestWallpaperPreferences
 import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
+import com.android.wallpaper.util.converter.WallpaperModelFactory
 import dagger.Binds
 import dagger.Module
-import dagger.Provides
 import dagger.hilt.components.SingletonComponent
 import dagger.hilt.testing.TestInstallIn
 import javax.inject.Singleton
@@ -41,11 +41,9 @@
     @Singleton
     abstract fun bindWallpaperPreferences(impl: TestWallpaperPreferences): WallpaperPreferences
 
-    companion object {
-        @Provides
-        @Singleton
-        fun provideDefaultWallpaperModelFactory(): DefaultWallpaperModelFactory {
-            return DefaultWallpaperModelFactory()
-        }
-    }
+    @Binds
+    @Singleton
+    abstract fun bindWallpaperModelFactory(
+        impl: DefaultWallpaperModelFactory
+    ): WallpaperModelFactory
 }