Merge "Revert "Polish weather clock Move adding weather placeholder to ..."" into udc-dev
diff --git a/res/drawable/carousel_item_card_background.xml b/res/drawable/carousel_item_card_background.xml
new file mode 100644
index 0000000..946d279
--- /dev/null
+++ b/res/drawable/carousel_item_card_background.xml
@@ -0,0 +1,21 @@
+<?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">
+    <solid android:color="@color/color_surface" />
+    <corners android:radius="16dp" />
+</shape>
\ No newline at end of file
diff --git a/res/layout/clock_carousel.xml b/res/layout/clock_carousel.xml
index dbeb4dd..f6c408b 100644
--- a/res/layout/clock_carousel.xml
+++ b/res/layout/clock_carousel.xml
@@ -22,7 +22,7 @@
     android:layout_height="match_parent"
     app:layoutDescription="@xml/carousel_scene">
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+    <FrameLayout
         android:id="@+id/item_view_0"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
@@ -30,14 +30,28 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toStartOf="@+id/item_view_1"
         app:layout_constraintTop_toTopOf="parent">
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false" />
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_0"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_0"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_0"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false" />
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_1"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
@@ -45,14 +59,28 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toStartOf="@+id/item_view_2"
         app:layout_constraintTop_toTopOf="parent" >
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false"/>
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_1"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_1"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_1"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false"/>
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_2"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
@@ -61,42 +89,84 @@
         app:layout_constraintHorizontal_bias="0.5"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent">
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false"/>
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_2"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_2"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_2"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false"/>
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_3"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
         android:layout_marginStart="@dimen/clock_carousel_item_margin"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toEndOf="@+id/item_view_2"
-        app:layout_constraintTop_toTopOf="parent" >
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false"/>
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+        app:layout_constraintTop_toTopOf="parent">
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_3"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_3"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_3"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false"/>
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_4"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
         android:layout_marginStart="@dimen/clock_carousel_item_margin"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toEndOf="@+id/item_view_3"
-        app:layout_constraintTop_toTopOf="parent" >
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <View
+            android:id="@+id/item_card_4"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
             android:layout_gravity="center"
-            android:clipChildren="false" />
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_4"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_4"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false" />
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
 
     <androidx.constraintlayout.helper.widget.Carousel
         android:id="@+id/carousel"
diff --git a/res/layout/grid_preview_card.xml b/res/layout/grid_preview_card.xml
index 6df8508..a2691df 100644
--- a/res/layout/grid_preview_card.xml
+++ b/res/layout/grid_preview_card.xml
@@ -39,7 +39,7 @@
         android:layout_height="match_parent"
         android:importantForAccessibility="noHideDescendants" />
 
-    <View
+    <ImageView
         android:id="@+id/grid_fadein_scrim"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index cb4876a..9bcdd56 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -160,10 +160,8 @@
     <dimen name="clock_carousel_item_height">380dp</dimen>
     <dimen name="clock_carousel_item_margin">16dp</dimen>
     <dimen name="clock_carousel_guideline_margin">140dp</dimen>
-    <!-- Scale of the carousel items that are not selected and at the side -->
-    <dimen name="clock_carousel_scale" format="float">0.5</dimen>
-    <!-- Alpha of the carousel items that are not selected and at the side -->
-    <dimen name="clock_carousel_alpha" format="float">0.4</dimen>
+    <dimen name="clock_carousel_item_card_width">100dp</dimen>
+    <dimen name="clock_carousel_item_card_height">108dp</dimen>
 
     <!-- Clock color and size button -->
     <dimen name="clock_color_size_button_min_height">32dp</dimen>
diff --git a/res/xml/carousel_scene.xml b/res/xml/carousel_scene.xml
index e26ee14..267f0a1 100644
--- a/res/xml/carousel_scene.xml
+++ b/res/xml/carousel_scene.xml
@@ -42,12 +42,10 @@
             android:id="@+id/item_view_0"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_1"
             android:layout_width="@dimen/clock_carousel_item_width"
@@ -58,13 +56,11 @@
             motion:layout_constraintEnd_toEndOf="parent"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -73,9 +69,6 @@
             android:id="@+id/item_view_3"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toEndOf="@+id/item_view_2"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -86,9 +79,6 @@
             android:id="@+id/item_view_0"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@+id/item_view_1"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -97,12 +87,10 @@
             android:id="@+id/item_view_1"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
@@ -113,13 +101,11 @@
             motion:layout_constraintEnd_toEndOf="parent"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_3"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -128,9 +114,6 @@
             android:id="@+id/item_view_4"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toEndOf="@+id/item_view_3"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -141,9 +124,6 @@
             android:id="@+id/item_view_1"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@+id/item_view_2"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -152,12 +132,10 @@
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_3"
             android:layout_width="@dimen/clock_carousel_item_width"
@@ -168,16 +146,13 @@
             motion:layout_constraintEnd_toEndOf="parent"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_4"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
     </ConstraintSet>
-
 </MotionScene>
\ No newline at end of file
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index 306ef04..479bca2 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -70,5 +70,6 @@
     fun getClockSettingsViewModelFactory(
         context: Context,
         wallpaperColorsViewModel: WallpaperColorsViewModel,
+        clockViewFactory: ClockViewFactory,
     ): ClockSettingsViewModel.Factory
 }
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index b35de75..da11d51 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -460,6 +460,7 @@
     override fun getClockSettingsViewModelFactory(
         context: Context,
         wallpaperColorsViewModel: WallpaperColorsViewModel,
+        clockViewFactory: ClockViewFactory,
     ): ClockSettingsViewModel.Factory {
         return clockSettingsViewModelFactory
             ?: ClockSettingsViewModel.Factory(
@@ -469,7 +470,10 @@
                         context,
                         wallpaperColorsViewModel,
                     ),
-                )
+                ) { clockId ->
+                    clockId?.let { clockViewFactory.getController(clockId).config.isReactiveToTone }
+                        ?: false
+                }
                 .also { clockSettingsViewModelFactory = it }
     }
 
diff --git a/src/com/android/customization/picker/WallpaperPreviewer.java b/src/com/android/customization/picker/WallpaperPreviewer.java
index ef16895..1b9ea9f 100644
--- a/src/com/android/customization/picker/WallpaperPreviewer.java
+++ b/src/com/android/customization/picker/WallpaperPreviewer.java
@@ -19,6 +19,8 @@
 import android.app.WallpaperColors;
 import android.content.Intent;
 import android.graphics.Rect;
+import android.graphics.RenderEffect;
+import android.graphics.Shader.TileMode;
 import android.service.wallpaper.WallpaperService;
 import android.view.Surface;
 import android.view.SurfaceView;
@@ -54,7 +56,7 @@
     private final Activity mActivity;
     private final ImageView mHomePreview;
     private final SurfaceView mWallpaperSurface;
-    @Nullable private final View mFadeInScrim;
+    @Nullable private final ImageView mFadeInScrim;
 
     private WallpaperSurfaceCallback mWallpaperSurfaceCallback;
     private WallpaperInfo mWallpaper;
@@ -73,7 +75,7 @@
     }
 
     public WallpaperPreviewer(Lifecycle lifecycle, Activity activity, ImageView homePreview,
-                              SurfaceView wallpaperSurface, @Nullable View fadeInScrim) {
+                              SurfaceView wallpaperSurface, @Nullable ImageView fadeInScrim) {
         lifecycle.addObserver(this);
 
         mActivity = activity;
@@ -170,10 +172,16 @@
                                         mActivity, android.R.attr.colorSecondary),
                                 /* offsetToStart= */ true);
                 if (mWallpaper instanceof LiveWallpaperInfo) {
+                    ImageView preview = homeImageWallpaper;
+                    if (VideoWallpaperUtils.needsFadeIn(mWallpaper) && mFadeInScrim != null) {
+                        preview = mFadeInScrim;
+                        preview.setRenderEffect(
+                                RenderEffect.createBlurEffect(150f, 150f, TileMode.CLAMP));
+                    }
                     mWallpaper.getThumbAsset(mActivity.getApplicationContext())
                             .loadPreviewImage(
                                     mActivity,
-                                    homeImageWallpaper,
+                                    preview,
                                     ResourceUtils.getColorAttr(
                                             mActivity, android.R.attr.colorSecondary),
                                     /* offsetToStart= */ true);
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
index 880a00b..9537365 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -137,6 +137,7 @@
         secureSettingsRepository
             .intSetting(
                 name = Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
+                defaultValue = DEFAULT_CLOCK_SIZE,
             )
             .map { setting -> setting == 1 }
             .map { isDynamic -> if (isDynamic) ClockSize.DYNAMIC else ClockSize.SMALL }
@@ -189,5 +190,8 @@
 
         // The color tone to apply to the selected color
         private const val KEY_METADATA_COLOR_TONE_PROGRESS = "metadataColorToneProgress"
+
+        // The default clock size is 1, which means dynamic
+        private const val DEFAULT_CLOCK_SIZE = 1
     }
 }
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
index cf80dc1..925e293 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
@@ -30,14 +30,6 @@
 import kotlinx.coroutines.launch
 
 object ClockCarouselViewBinder {
-    /**
-     * The binding is used by the view where there is an action executed from another view, e.g.
-     * toggling show/hide of the view that the binder is holding.
-     */
-    interface Binding {
-        fun show()
-        fun hide()
-    }
 
     @JvmStatic
     fun bind(
@@ -46,7 +38,7 @@
         viewModel: ClockCarouselViewModel,
         clockViewFactory: ClockViewFactory,
         lifecycleOwner: LifecycleOwner,
-    ): Binding {
+    ) {
         val singleClockHostView =
             singleClockView.requireViewById<FrameLayout>(R.id.single_clock_host_view)
         lifecycleOwner.lifecycleScope.launch {
@@ -106,15 +98,5 @@
                 }
             }
         )
-
-        return object : Binding {
-            override fun show() {
-                viewModel.showClockCarousel(true)
-            }
-
-            override fun hide() {
-                viewModel.showClockCarousel(false)
-            }
-        }
     }
 }
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
index 1bbb965..b358873 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
@@ -43,6 +43,9 @@
 
 /** Bind between the clock settings screen and its view model. */
 object ClockSettingsBinder {
+    private const val SLIDER_ENABLED_ALPHA = 1f
+    private const val SLIDER_DISABLED_ALPHA = .3f
+
     fun bind(
         view: View,
         viewModel: ClockSettingsViewModel,
@@ -176,7 +179,11 @@
                 }
 
                 launch {
-                    viewModel.isSliderEnabled.collect { isEnabled -> slider.isEnabled = isEnabled }
+                    viewModel.isSliderEnabled.collect { isEnabled ->
+                        slider.isEnabled = isEnabled
+                        slider.alpha =
+                            if (isEnabled) SLIDER_ENABLED_ALPHA else SLIDER_DISABLED_ALPHA
+                    }
                 }
             }
         }
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
index c5cde53..dd4c968 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -66,59 +66,59 @@
         val colorViewModel = injector.getWallpaperColorsViewModel()
         val displayUtils = injector.getDisplayUtils(context)
         ScreenPreviewBinder.bind(
-                activity = activity,
-                previewView = lockScreenView,
-                viewModel =
-                    ScreenPreviewViewModel(
-                        previewUtils =
-                            PreviewUtils(
-                                context = context,
-                                authority =
-                                    resources.getString(
-                                        R.string.lock_screen_preview_provider_authority,
-                                    ),
-                            ),
-                        wallpaperInfoProvider = {
-                            suspendCancellableCoroutine { continuation ->
-                                injector
-                                    .getCurrentWallpaperInfoFactory(context)
-                                    .createCurrentWallpaperInfos(
-                                        { homeWallpaper, lockWallpaper, _ ->
-                                            continuation.resume(
-                                                homeWallpaper ?: lockWallpaper,
-                                                null,
-                                            )
-                                        },
-                                        /* forceRefresh= */ true,
-                                    )
-                            }
-                        },
-                        onWallpaperColorChanged = { colors ->
-                            colorViewModel.setLockWallpaperColors(colors)
-                        },
-                        initialExtrasProvider = {
-                            Bundle().apply {
-                                // Hide the clock from the system UI rendered preview so we can
-                                // place the carousel on top of it.
-                                putBoolean(
-                                    ClockPreviewConstants.KEY_HIDE_CLOCK,
-                                    true,
+            activity = activity,
+            previewView = lockScreenView,
+            viewModel =
+                ScreenPreviewViewModel(
+                    previewUtils =
+                        PreviewUtils(
+                            context = context,
+                            authority =
+                                resources.getString(
+                                    R.string.lock_screen_preview_provider_authority,
+                                ),
+                        ),
+                    wallpaperInfoProvider = {
+                        suspendCancellableCoroutine { continuation ->
+                            injector
+                                .getCurrentWallpaperInfoFactory(context)
+                                .createCurrentWallpaperInfos(
+                                    { homeWallpaper, lockWallpaper, _ ->
+                                        continuation.resume(
+                                            homeWallpaper ?: lockWallpaper,
+                                            null,
+                                        )
+                                    },
+                                    /* forceRefresh= */ true,
                                 )
-                            }
-                        },
-                    ),
-                lifecycleOwner = this,
-                offsetToStart = displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(activity),
-            )
-            .show()
+                        }
+                    },
+                    onWallpaperColorChanged = { colors ->
+                        colorViewModel.setLockWallpaperColors(colors)
+                    },
+                    initialExtrasProvider = {
+                        Bundle().apply {
+                            // Hide the clock from the system UI rendered preview so we can
+                            // place the carousel on top of it.
+                            putBoolean(
+                                ClockPreviewConstants.KEY_HIDE_CLOCK,
+                                true,
+                            )
+                        }
+                    },
+                ),
+            lifecycleOwner = this,
+            offsetToStart = displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(activity),
+        )
 
         ClockSettingsBinder.bind(
             view,
             ViewModelProvider(
-                    requireActivity(),
+                    activity,
                     injector.getClockSettingsViewModelFactory(
                         context,
                         injector.getWallpaperColorsViewModel(),
+                        injector.getClockViewFactory(activity),
                     ),
                 )
                 .get(),
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
index 3eae7aa..48d3de3 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -17,15 +17,16 @@
 
 import android.content.Context
 import android.util.AttributeSet
+import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.FrameLayout
 import androidx.constraintlayout.helper.widget.Carousel
 import androidx.constraintlayout.motion.widget.MotionLayout
-import androidx.core.view.get
 import com.android.systemui.plugins.ClockController
 import com.android.wallpaper.R
+import java.lang.Float.max
 
 class ClockCarouselView(
     context: Context,
@@ -39,8 +40,12 @@
     private val carousel: Carousel
     private val motionLayout: MotionLayout
     private lateinit var adapter: ClockCarouselAdapter
-    private lateinit var scalingUpClock: ClockController
-    private lateinit var scalingDownClock: ClockController
+    private lateinit var scalingUpClockController: ClockController
+    private lateinit var scalingDownClockController: ClockController
+    private var scalingUpClockView: View? = null
+    private var scalingDownClockView: View? = null
+    private var showingCardView: View? = null
+    private var hidingCardView: View? = null
 
     init {
         val clockCarousel = LayoutInflater.from(context).inflate(R.layout.clock_carousel, this)
@@ -65,13 +70,25 @@
                     startId: Int,
                     endId: Int
                 ) {
+                    Log.d("mmpud", "onTransitionStarted")
                     val scalingDownClockId = adapter.clockIds[carousel.currentIndex]
                     val scalingUpIdx =
                         if (endId == R.id.next) (carousel.currentIndex + 1) % adapter.count()
                         else (carousel.currentIndex - 1 + adapter.count()) % adapter.count()
                     val scalingUpClockId = adapter.clockIds[scalingUpIdx]
-                    scalingDownClock = adapter.onGetClockController(scalingDownClockId)
-                    scalingUpClock = adapter.onGetClockController(scalingUpClockId)
+                    scalingDownClockController = adapter.onGetClockController(scalingDownClockId)
+                    scalingUpClockController = adapter.onGetClockController(scalingUpClockId)
+                    scalingDownClockView = motionLayout?.findViewById(R.id.clock_scale_view_2)
+                    scalingUpClockView =
+                        motionLayout?.findViewById(
+                            if (endId == R.id.next) R.id.clock_scale_view_3
+                            else R.id.clock_scale_view_1
+                        )
+                    showingCardView = motionLayout?.findViewById(R.id.item_card_2)
+                    hidingCardView =
+                        motionLayout?.findViewById(
+                            if (endId == R.id.next) R.id.item_card_3 else R.id.item_card_1
+                        )
                 }
 
                 override fun onTransitionChange(
@@ -80,11 +97,22 @@
                     endId: Int,
                     progress: Float
                 ) {
-                    scalingDownClock.animations.onPickerCarouselSwiping(
+                    scalingDownClockController.animations.onPickerCarouselSwiping(
                         1 - progress,
                         getPreviewRatio()
                     )
-                    scalingUpClock.animations.onPickerCarouselSwiping(progress, getPreviewRatio())
+                    scalingUpClockController.animations.onPickerCarouselSwiping(
+                        progress,
+                        getPreviewRatio()
+                    )
+                    val scalingUpScale = getScalingUpScale(progress)
+                    val scalingDownScale = getScalingDownScale(progress)
+                    scalingUpClockView?.scaleX = scalingUpScale
+                    scalingUpClockView?.scaleY = scalingUpScale
+                    scalingDownClockView?.scaleX = scalingDownScale
+                    scalingDownClockView?.scaleY = scalingDownScale
+                    showingCardView?.alpha = getShowingAlpha(progress)
+                    hidingCardView?.alpha = getHidingAlpha(progress)
                 }
 
                 override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {}
@@ -117,8 +145,17 @@
         }
 
         override fun populate(view: View?, index: Int) {
-            val viewRoot = view as ViewGroup
-            val clockHostView = viewRoot[0] as ViewGroup
+            val viewRoot = view as? ViewGroup ?: return
+            val cardView =
+                getClockCardViewId(viewRoot.id)?.let { viewRoot.findViewById(it) as? View }
+                    ?: return
+            val clockScaleView =
+                getClockScaleViewId(viewRoot.id)?.let { viewRoot.findViewById(it) as? View }
+                    ?: return
+            val clockHostView =
+                getClockHostViewId(viewRoot.id)?.let { viewRoot.findViewById(it) as? ViewGroup }
+                    ?: return
+
             clockHostView.removeAllViews()
             val clockView = onGetClockController(clockIds[index]).largeClock.view
             // The clock view might still be attached to an existing parent. Detach before adding to
@@ -126,11 +163,17 @@
             (clockView.parent as? ViewGroup)?.removeView(clockView)
             clockHostView.addView(clockView)
             // initialize scaling state for all clocks
-            if (view.id != MIDDLE_VIEW_IN_START_STATE) {
+            if (!isMiddleView(viewRoot.id)) {
+                cardView.alpha = 1f
+                clockScaleView.scaleX = CLOCK_CAROUSEL_VIEW_SCALE
+                clockScaleView.scaleY = CLOCK_CAROUSEL_VIEW_SCALE
                 onGetClockController(clockIds[index])
                     .animations
                     .onPickerCarouselSwiping(0F, getPreviewRatio())
             } else {
+                cardView.alpha = 0f
+                clockScaleView.scaleX = 1f
+                clockScaleView.scaleY = 1f
                 onGetClockController(clockIds[index])
                     .animations
                     .onPickerCarouselSwiping(1F, getPreviewRatio())
@@ -143,6 +186,56 @@
     }
 
     companion object {
-        const val MIDDLE_VIEW_IN_START_STATE = R.id.item_view_2
+        const val CLOCK_CAROUSEL_VIEW_SCALE = 0.5f
+
+        fun getScalingUpScale(progress: Float) =
+            CLOCK_CAROUSEL_VIEW_SCALE + progress * (1f - CLOCK_CAROUSEL_VIEW_SCALE)
+
+        fun getScalingDownScale(progress: Float) = 1f - progress * (1f - CLOCK_CAROUSEL_VIEW_SCALE)
+
+        // This makes the card only starts to reveal in the last quarter of the trip so
+        // the card won't overlap the preview.
+        fun getShowingAlpha(progress: Float) = max(progress - 0.75f, 0f) * 4
+
+        // This makes the card starts to hide in the first quarter of the trip so the
+        // card won't overlap the preview.
+        fun getHidingAlpha(progress: Float) = max(1f - progress * 4, 0f)
+
+        fun getClockHostViewId(rootViewId: Int): Int? {
+            return when (rootViewId) {
+                R.id.item_view_0 -> R.id.clock_host_view_0
+                R.id.item_view_1 -> R.id.clock_host_view_1
+                R.id.item_view_2 -> R.id.clock_host_view_2
+                R.id.item_view_3 -> R.id.clock_host_view_3
+                R.id.item_view_4 -> R.id.clock_host_view_4
+                else -> null
+            }
+        }
+
+        fun getClockScaleViewId(rootViewId: Int): Int? {
+            return when (rootViewId) {
+                R.id.item_view_0 -> R.id.clock_scale_view_0
+                R.id.item_view_1 -> R.id.clock_scale_view_1
+                R.id.item_view_2 -> R.id.clock_scale_view_2
+                R.id.item_view_3 -> R.id.clock_scale_view_3
+                R.id.item_view_4 -> R.id.clock_scale_view_4
+                else -> null
+            }
+        }
+
+        fun getClockCardViewId(rootViewId: Int): Int? {
+            return when (rootViewId) {
+                R.id.item_view_0 -> R.id.item_card_0
+                R.id.item_view_1 -> R.id.item_card_1
+                R.id.item_view_2 -> R.id.item_card_2
+                R.id.item_view_3 -> R.id.item_card_3
+                R.id.item_view_4 -> R.id.item_card_4
+                else -> null
+            }
+        }
+
+        fun isMiddleView(rootViewId: Int): Boolean {
+            return rootViewId == R.id.item_view_2
+        }
     }
 }
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
index 60a9e85..c01f56a 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -19,8 +19,6 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.map
@@ -44,14 +42,7 @@
 
     val seedColor: Flow<Int?> = interactor.seedColor
 
-    private val shouldShowCarousel = MutableStateFlow(false)
-    val isCarouselVisible: Flow<Boolean> =
-        combine(allClockIds.map { it.size > 1 }.distinctUntilChanged(), shouldShowCarousel) {
-                hasMoreThanOneClock,
-                shouldShowCarousel ->
-                hasMoreThanOneClock && shouldShowCarousel
-            }
-            .distinctUntilChanged()
+    val isCarouselVisible: Flow<Boolean> = allClockIds.map { it.size > 1 }.distinctUntilChanged()
 
     @OptIn(ExperimentalCoroutinesApi::class)
     val selectedIndex: Flow<Int> =
@@ -69,14 +60,8 @@
             .mapNotNull { it }
 
     // Handle the case when there is only one clock in the carousel
-    private val shouldShowSingleClock = MutableStateFlow(false)
     val isSingleClockViewVisible: Flow<Boolean> =
-        combine(allClockIds.map { it.size == 1 }.distinctUntilChanged(), shouldShowSingleClock) {
-                hasOneClock,
-                shouldShowSingleClock ->
-                hasOneClock && shouldShowSingleClock
-            }
-            .distinctUntilChanged()
+        allClockIds.map { it.size == 1 }.distinctUntilChanged()
 
     val clockId: Flow<String> =
         allClockIds
@@ -87,11 +72,6 @@
         interactor.setSelectedClock(clockId)
     }
 
-    fun showClockCarousel(shouldShow: Boolean) {
-        shouldShowCarousel.value = shouldShow
-        shouldShowSingleClock.value = shouldShow
-    }
-
     companion object {
         const val CLOCKS_EVENT_UPDATE_DELAY_MILLIS: Long = 100
     }
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
index 1514f1b..b66f977 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
@@ -53,6 +53,7 @@
     context: Context,
     private val clockPickerInteractor: ClockPickerInteractor,
     private val colorPickerInteractor: ColorPickerInteractor,
+    private val getIsReactiveToTone: (clockId: String?) -> Boolean,
 ) : ViewModel() {
 
     enum class Tab {
@@ -60,20 +61,27 @@
         SIZE,
     }
 
-    val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+    private val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
 
     val selectedClockId: StateFlow<String?> =
         clockPickerInteractor.selectedClockId
             .distinctUntilChanged()
             .stateIn(viewModelScope, SharingStarted.Eagerly, null)
 
-    val selectedColorId: StateFlow<String?> =
+    private val selectedColorId: StateFlow<String?> =
         clockPickerInteractor.selectedColorId.stateIn(viewModelScope, SharingStarted.Eagerly, null)
 
     private val sliderColorToneProgress =
         MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
     val isSliderEnabled: Flow<Boolean> =
-        clockPickerInteractor.selectedColorId.map { it != null }.distinctUntilChanged()
+        combine(selectedClockId, clockPickerInteractor.selectedColorId) { clockId, colorId ->
+                if (colorId == null) {
+                    false
+                } else {
+                    getIsReactiveToTone(clockId)
+                }
+            }
+            .distinctUntilChanged()
     val sliderProgress: Flow<Int> =
         merge(clockPickerInteractor.colorToneProgress, sliderColorToneProgress)
 
@@ -286,6 +294,7 @@
         private val context: Context,
         private val clockPickerInteractor: ClockPickerInteractor,
         private val colorPickerInteractor: ColorPickerInteractor,
+        private val getIsReactiveToTone: (clockId: String?) -> Boolean,
     ) : ViewModelProvider.Factory {
         override fun <T : ViewModel> create(modelClass: Class<T>): T {
             @Suppress("UNCHECKED_CAST")
@@ -293,6 +302,7 @@
                 context = context,
                 clockPickerInteractor = clockPickerInteractor,
                 colorPickerInteractor = colorPickerInteractor,
+                getIsReactiveToTone = getIsReactiveToTone,
             )
                 as T
         }
diff --git a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
index 0303b41..43fb85b 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -22,7 +22,6 @@
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewStub
-import androidx.core.view.isVisible
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import com.android.customization.picker.clock.ui.binder.ClockCarouselViewBinder
@@ -46,7 +45,7 @@
 class PreviewWithClockCarouselSectionController(
     activity: Activity,
     private val lifecycleOwner: LifecycleOwner,
-    private val initialScreen: CustomizationSections.Screen,
+    private val screen: CustomizationSections.Screen,
     wallpaperInfoFactory: CurrentWallpaperInfoFactory,
     colorViewModel: WallpaperColorsViewModel,
     displayUtils: DisplayUtils,
@@ -59,7 +58,7 @@
     ScreenPreviewSectionController(
         activity,
         lifecycleOwner,
-        initialScreen,
+        screen,
         wallpaperInfoFactory,
         colorViewModel,
         displayUtils,
@@ -67,32 +66,31 @@
         wallpaperInteractor,
     ) {
 
-    private var clockCarouselBinding: ClockCarouselViewBinder.Binding? = null
     private var clockColorAndSizeButton: View? = null
 
     override val hideLockScreenClockPreview = true
 
     override fun createView(context: Context): ScreenPreviewView {
         val view = super.createView(context)
+        if (screen == CustomizationSections.Screen.LOCK_SCREEN) {
+            val clockColorAndSizeButtonStub: ViewStub =
+                view.requireViewById(R.id.clock_color_and_size_button)
+            clockColorAndSizeButtonStub.layoutResource = R.layout.clock_color_and_size_button
+            clockColorAndSizeButton = clockColorAndSizeButtonStub.inflate() as View
+            clockColorAndSizeButton?.setOnClickListener {
+                navigationController.navigateTo(ClockSettingsFragment())
+            }
 
-        val clockColorAndSizeButtonStub: ViewStub =
-            view.requireViewById(R.id.clock_color_and_size_button)
-        clockColorAndSizeButtonStub.layoutResource = R.layout.clock_color_and_size_button
-        clockColorAndSizeButton = clockColorAndSizeButtonStub.inflate() as View
-        clockColorAndSizeButton?.setOnClickListener {
-            navigationController.navigateTo(ClockSettingsFragment())
-        }
+            val carouselViewStub: ViewStub = view.requireViewById(R.id.clock_carousel_view_stub)
+            carouselViewStub.layoutResource = R.layout.clock_carousel_view
+            val carouselView = carouselViewStub.inflate() as ClockCarouselView
 
-        val carouselViewStub: ViewStub = view.requireViewById(R.id.clock_carousel_view_stub)
-        carouselViewStub.layoutResource = R.layout.clock_carousel_view
-        val carouselView = carouselViewStub.inflate() as ClockCarouselView
-
-        // TODO (b/270716937) We should handle the single clock case in the clock carousel itself
-        val singleClockViewStub: ViewStub = view.requireViewById(R.id.single_clock_view_stub)
-        singleClockViewStub.layoutResource = R.layout.single_clock_view
-        val singleClockView = singleClockViewStub.inflate() as ViewGroup
-        lifecycleOwner.lifecycleScope.launch {
-            clockCarouselBinding =
+            // TODO (b/270716937) We should handle the single clock case in the clock carousel
+            // itself
+            val singleClockViewStub: ViewStub = view.requireViewById(R.id.single_clock_view_stub)
+            singleClockViewStub.layoutResource = R.layout.single_clock_view
+            val singleClockView = singleClockViewStub.inflate() as ViewGroup
+            lifecycleOwner.lifecycleScope.launch {
                 ClockCarouselViewBinder.bind(
                     carouselView = carouselView,
                     singleClockView = singleClockView,
@@ -100,20 +98,9 @@
                     clockViewFactory = clockViewFactory,
                     lifecycleOwner = lifecycleOwner,
                 )
-            onScreenSwitched(
-                isOnLockScreen = initialScreen == CustomizationSections.Screen.LOCK_SCREEN
-            )
+            }
         }
-        return view
-    }
 
-    override fun onScreenSwitched(isOnLockScreen: Boolean) {
-        super.onScreenSwitched(isOnLockScreen)
-        clockColorAndSizeButton?.isVisible = isOnLockScreen
-        if (isOnLockScreen) {
-            clockCarouselBinding?.show()
-        } else {
-            clockCarouselBinding?.hide()
-        }
+        return view
     }
 }
diff --git a/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
index 2ef4e97..2b0b47f 100644
--- a/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
+++ b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -75,12 +75,16 @@
     }
 
     companion object {
+        const val CLOCK_ID_0 = "clock0"
+        const val CLOCK_ID_1 = "clock1"
+        const val CLOCK_ID_2 = "clock2"
+        const val CLOCK_ID_3 = "clock3"
         val fakeClocks =
             listOf(
-                ClockMetadataModel("clock0", "clock0", null, 50, null),
-                ClockMetadataModel("clock1", "clock1", null, 50, null),
-                ClockMetadataModel("clock2", "clock2", null, 50, null),
-                ClockMetadataModel("clock3", "clock3", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_0, "clock0", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_1, "clock1", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_2, "clock2", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_3, "clock3", null, 50, null),
             )
         const val CLOCK_COLOR_ID = "RED"
         const val CLOCK_COLOR_TONE_PROGRESS = 87
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
index 63f77bd..5bc7461 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -75,46 +75,22 @@
     }
 
     @Test
-    fun setShouldShowCarousel() = runTest {
+    fun multipleClockCase() = runTest {
         underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithMultipleClocks))
         val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
+        val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
         advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsCarouselVisible()).isFalse()
-        underTest.showClockCarousel(true)
         assertThat(observedIsCarouselVisible()).isTrue()
+        assertThat(observedIsSingleClockViewVisible()).isFalse()
     }
 
     @Test
-    fun shouldNotShowCarouselWhenSingleClock() = runTest {
+    fun singleClockCase() = runTest {
         underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithSingleClock))
         val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
-        advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsCarouselVisible()).isFalse()
-        underTest.showClockCarousel(true)
-        assertThat(observedIsCarouselVisible()).isFalse()
-    }
-
-    @Test
-    fun setShouldShowSingleClock() = runTest {
-        underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithSingleClock))
         val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
         advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsSingleClockViewVisible()).isFalse()
-        underTest.showClockCarousel(true)
+        assertThat(observedIsCarouselVisible()).isFalse()
         assertThat(observedIsSingleClockViewVisible()).isTrue()
     }
-
-    @Test
-    fun shouldNotShowSingleClockWhenMultipleClocks() = runTest {
-        underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithMultipleClocks))
-        val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
-        advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsSingleClockViewVisible()).isFalse()
-        underTest.showClockCarousel(true)
-        assertThat(observedIsSingleClockViewVisible()).isFalse()
-    }
 }
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
index a959a46..92059e3 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
@@ -34,14 +34,26 @@
 
     private lateinit var context: Context
     private lateinit var colorPickerInteractor: ColorPickerInteractor
+    private lateinit var clockPickerInteractor: ClockPickerInteractor
     private lateinit var underTest: ClockSettingsViewModel
     private lateinit var colorMap: Map<String, ClockColorViewModel>
+    // We make the condition that CLOCK_ID_3 is not reactive to tone
+    private val getIsReactiveToTone: (clockId: String?) -> Boolean = { clockId ->
+        when (clockId) {
+            FakeClockPickerRepository.CLOCK_ID_0 -> true
+            FakeClockPickerRepository.CLOCK_ID_1 -> true
+            FakeClockPickerRepository.CLOCK_ID_2 -> true
+            FakeClockPickerRepository.CLOCK_ID_3 -> false
+            else -> false
+        }
+    }
 
     @Before
     fun setUp() {
         val testDispatcher = StandardTestDispatcher()
         Dispatchers.setMain(testDispatcher)
         context = InstrumentationRegistry.getInstrumentation().targetContext
+        clockPickerInteractor = ClockPickerInteractor(FakeClockPickerRepository())
         colorPickerInteractor =
             ColorPickerInteractor(
                 repository = FakeColorPickerRepository(context = context),
@@ -54,11 +66,14 @@
         underTest =
             ClockSettingsViewModel.Factory(
                     context = context,
-                    clockPickerInteractor = ClockPickerInteractor(FakeClockPickerRepository()),
+                    clockPickerInteractor = clockPickerInteractor,
                     colorPickerInteractor = colorPickerInteractor,
+                    getIsReactiveToTone = getIsReactiveToTone,
                 )
                 .create(ClockSettingsViewModel::class.java)
         colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+
+        clockPickerInteractor.setSelectedClock(FakeClockPickerRepository.CLOCK_ID_0)
     }
 
     @After
@@ -160,4 +175,21 @@
         underTest.setClockSize(ClockSize.SMALL)
         assertThat(observedClockSize()).isEqualTo(ClockSize.SMALL)
     }
+
+    @Test
+    fun getIsReactiveToTone() = runTest {
+        val observedClockColorOptions = collectLastValue(underTest.colorOptions)
+        val isSliderEnabled = collectLastValue(underTest.isSliderEnabled)
+        // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
+        advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
+        val option1OnClicked = collectLastValue(observedClockColorOptions()!![1].onClicked)
+        option1OnClicked()?.invoke()
+
+        clockPickerInteractor.setSelectedClock(FakeClockPickerRepository.CLOCK_ID_0)
+        assertThat(isSliderEnabled()).isTrue()
+
+        // We make the condition that CLOCK_ID_0 is not reactive to tone
+        clockPickerInteractor.setSelectedClock(FakeClockPickerRepository.CLOCK_ID_3)
+        assertThat(isSliderEnabled()).isFalse()
+    }
 }