Fix themed icon preview reload (2/3)

Allow themed icon changes to trigger preview reload.

Bug: 279511950
Test: Manually verified, see bug
Change-Id: I135c22935d9a2bc4d91f0e7deeda84411d6ac907
diff --git a/src/com/android/customization/model/grid/ui/fragment/GridFragment2.kt b/src/com/android/customization/model/grid/ui/fragment/GridFragment2.kt
index 4368c5b..7f890e1 100644
--- a/src/com/android/customization/model/grid/ui/fragment/GridFragment2.kt
+++ b/src/com/android/customization/model/grid/ui/fragment/GridFragment2.kt
@@ -126,7 +126,7 @@
                 ),
             lifecycleOwner = this,
             offsetToStart = false,
-            onPreviewDirty = { activity?.recreate() },
+            onWallpaperPreviewDirty = { activity?.recreate() },
         )
     }
 }
diff --git a/src/com/android/customization/module/DefaultCustomizationSections.java b/src/com/android/customization/module/DefaultCustomizationSections.java
index b8d43ed..b408a89 100644
--- a/src/com/android/customization/module/DefaultCustomizationSections.java
+++ b/src/com/android/customization/module/DefaultCustomizationSections.java
@@ -24,6 +24,7 @@
 import com.android.customization.picker.notifications.ui.section.NotificationSectionController;
 import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel;
 import com.android.customization.picker.preview.ui.section.PreviewWithClockCarouselSectionController;
+import com.android.customization.picker.preview.ui.section.PreviewWithThemeSectionController;
 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor;
 import com.android.customization.picker.quickaffordance.ui.section.KeyguardQuickAffordanceSectionController;
 import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel;
@@ -39,7 +40,6 @@
 import com.android.wallpaper.module.CustomizationSections;
 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor;
 import com.android.wallpaper.picker.customization.ui.section.ConnectedSectionController;
-import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewSectionController;
 import com.android.wallpaper.picker.customization.ui.section.WallpaperQuickSwitchSectionController;
 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationPickerViewModel;
 import com.android.wallpaper.util.DisplayUtils;
@@ -120,9 +120,10 @@
                         wallpaperPreviewNavigator,
                         sectionNavigationController,
                         wallpaperInteractor,
+                        mThemedIconInteractor,
                         wallpaperManager,
                         isTwoPaneAndSmallWidth)
-                        : new ScreenPreviewSectionController(
+                        : new PreviewWithThemeSectionController(
                                 activity,
                                 lifecycleOwner,
                                 screen,
@@ -131,6 +132,7 @@
                                 displayUtils,
                                 wallpaperPreviewNavigator,
                                 wallpaperInteractor,
+                                mThemedIconInteractor,
                                 wallpaperManager,
                                 isTwoPaneAndSmallWidth));
 
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 50840cf..d19b33c 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -112,7 +112,7 @@
                 ),
             lifecycleOwner = this,
             offsetToStart = displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(activity),
-            onPreviewDirty = { activity.recreate() },
+            onWallpaperPreviewDirty = { activity.recreate() },
         )
 
         ClockSettingsBinder.bind(
diff --git a/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt b/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
index ef38f8b..e322eac 100644
--- a/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
+++ b/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
@@ -117,7 +117,7 @@
             lifecycleOwner = this,
             offsetToStart =
                 displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(requireActivity()),
-            onPreviewDirty = { activity?.recreate() },
+            onWallpaperPreviewDirty = { activity?.recreate() },
         )
         ScreenPreviewBinder.bind(
             activity = requireActivity(),
@@ -152,7 +152,7 @@
             lifecycleOwner = this,
             offsetToStart =
                 displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(requireActivity()),
-            onPreviewDirty = { activity?.recreate() },
+            onWallpaperPreviewDirty = { activity?.recreate() },
         )
         val darkModeToggleContainerView: FrameLayout =
             view.requireViewById(R.id.dark_mode_toggle_container)
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 c826dc6..4322009 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -33,6 +33,7 @@
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.get
 import androidx.lifecycle.lifecycleScope
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor
 import com.android.customization.picker.clock.ui.binder.ClockCarouselViewBinder
 import com.android.customization.picker.clock.ui.fragment.ClockSettingsFragment
 import com.android.customization.picker.clock.ui.view.ClockCarouselView
@@ -51,7 +52,10 @@
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
 
-/** Controls the screen preview section. */
+/**
+ * A ThemePicker version of the [ScreenPreviewSectionController] that adjusts the preview for the
+ * clock carousel, and also updates the preview on theme changes.
+ */
 class PreviewWithClockCarouselSectionController(
     activity: ComponentActivity,
     private val lifecycleOwner: LifecycleOwner,
@@ -64,10 +68,11 @@
     wallpaperPreviewNavigator: WallpaperPreviewNavigator,
     private val navigationController: CustomizationSectionNavigationController,
     wallpaperInteractor: WallpaperInteractor,
+    themedIconInteractor: ThemedIconInteractor,
     wallpaperManager: WallpaperManager,
     private val isTwoPaneAndSmallWidth: Boolean,
 ) :
-    ScreenPreviewSectionController(
+    PreviewWithThemeSectionController(
         activity,
         lifecycleOwner,
         screen,
@@ -76,6 +81,7 @@
         displayUtils,
         wallpaperPreviewNavigator,
         wallpaperInteractor,
+        themedIconInteractor,
         wallpaperManager,
         isTwoPaneAndSmallWidth,
     ) {
diff --git a/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt b/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
new file mode 100644
index 0000000..56c6c30
--- /dev/null
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.customization.picker.preview.ui.section
+
+import android.app.Activity
+import android.app.WallpaperManager
+import android.content.Context
+import androidx.lifecycle.LifecycleOwner
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor
+import com.android.customization.picker.preview.ui.viewmodel.PreviewWithThemeViewModel
+import com.android.wallpaper.R
+import com.android.wallpaper.model.WallpaperColorsViewModel
+import com.android.wallpaper.model.WallpaperPreviewNavigator
+import com.android.wallpaper.module.CurrentWallpaperInfoFactory
+import com.android.wallpaper.module.CustomizationSections
+import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
+import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewSectionController
+import com.android.wallpaper.picker.customization.ui.viewmodel.ScreenPreviewViewModel
+import com.android.wallpaper.util.DisplayUtils
+import com.android.wallpaper.util.PreviewUtils
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+/**
+ * A ThemePicker version of the [ScreenPreviewSectionController] that binds the preview view with
+ * the [PreviewWithThemeViewModel] to allow preview updates on theme changes.
+ */
+open class PreviewWithThemeSectionController(
+    activity: Activity,
+    lifecycleOwner: LifecycleOwner,
+    private val screen: CustomizationSections.Screen,
+    private val wallpaperInfoFactory: CurrentWallpaperInfoFactory,
+    private val colorViewModel: WallpaperColorsViewModel,
+    displayUtils: DisplayUtils,
+    wallpaperPreviewNavigator: WallpaperPreviewNavigator,
+    private val wallpaperInteractor: WallpaperInteractor,
+    private val themedIconInteractor: ThemedIconInteractor,
+    wallpaperManager: WallpaperManager,
+    isTwoPaneAndSmallWidth: Boolean,
+) :
+    ScreenPreviewSectionController(
+        activity,
+        lifecycleOwner,
+        screen,
+        wallpaperInfoFactory,
+        colorViewModel,
+        displayUtils,
+        wallpaperPreviewNavigator,
+        wallpaperInteractor,
+        wallpaperManager,
+        isTwoPaneAndSmallWidth
+    ) {
+    override fun createScreenPreviewViewModel(context: Context): ScreenPreviewViewModel {
+        return PreviewWithThemeViewModel(
+            previewUtils =
+                if (isOnLockScreen) {
+                    PreviewUtils(
+                        context = context,
+                        authority =
+                            context.getString(
+                                R.string.lock_screen_preview_provider_authority,
+                            ),
+                    )
+                } else {
+                    PreviewUtils(
+                        context = context,
+                        authorityMetadataKey =
+                            context.getString(
+                                R.string.grid_control_metadata_name,
+                            ),
+                    )
+                },
+            wallpaperInfoProvider = { forceReload ->
+                suspendCancellableCoroutine { continuation ->
+                    wallpaperInfoFactory.createCurrentWallpaperInfos(
+                        { homeWallpaper, lockWallpaper, _ ->
+                            val wallpaper =
+                                if (isOnLockScreen) {
+                                    lockWallpaper ?: homeWallpaper
+                                } else {
+                                    homeWallpaper ?: lockWallpaper
+                                }
+                            loadInitialColors(
+                                context = context,
+                                screen = screen,
+                            )
+                            continuation.resume(wallpaper, null)
+                        },
+                        forceReload,
+                    )
+                }
+            },
+            onWallpaperColorChanged = { colors ->
+                if (isOnLockScreen) {
+                    colorViewModel.setLockWallpaperColors(colors)
+                } else {
+                    colorViewModel.setHomeWallpaperColors(colors)
+                }
+            },
+            initialExtrasProvider = { getInitialExtras(isOnLockScreen) },
+            wallpaperInteractor = wallpaperInteractor,
+            themedIconInteractor = themedIconInteractor,
+            screen = screen,
+        )
+    }
+}
diff --git a/src/com/android/customization/picker/preview/ui/viewmodel/PreviewWithThemeViewModel.kt b/src/com/android/customization/picker/preview/ui/viewmodel/PreviewWithThemeViewModel.kt
new file mode 100644
index 0000000..435878d
--- /dev/null
+++ b/src/com/android/customization/picker/preview/ui/viewmodel/PreviewWithThemeViewModel.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.customization.picker.preview.ui.viewmodel
+
+import android.app.WallpaperColors
+import android.os.Bundle
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor
+import com.android.wallpaper.model.WallpaperInfo
+import com.android.wallpaper.module.CustomizationSections
+import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
+import com.android.wallpaper.picker.customization.ui.viewmodel.ScreenPreviewViewModel
+import com.android.wallpaper.util.PreviewUtils
+import kotlinx.coroutines.flow.Flow
+
+/** A ThemePicker version of the [ScreenPreviewViewModel] */
+class PreviewWithThemeViewModel(
+    previewUtils: PreviewUtils,
+    initialExtrasProvider: () -> Bundle? = { null },
+    wallpaperInfoProvider: suspend (forceReload: Boolean) -> WallpaperInfo?,
+    onWallpaperColorChanged: (WallpaperColors?) -> Unit = {},
+    wallpaperInteractor: WallpaperInteractor,
+    private val themedIconInteractor: ThemedIconInteractor? = null,
+    screen: CustomizationSections.Screen,
+) :
+    ScreenPreviewViewModel(
+        previewUtils,
+        initialExtrasProvider,
+        wallpaperInfoProvider,
+        onWallpaperColorChanged,
+        wallpaperInteractor,
+        screen,
+    ) {
+    override fun workspaceUpdateEvents(): Flow<Boolean>? = themedIconInteractor?.isActivated
+}
diff --git a/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePreviewBinder.kt b/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePreviewBinder.kt
index f63f666..5b6d353 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePreviewBinder.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePreviewBinder.kt
@@ -49,7 +49,7 @@
                 lifecycleOwner = lifecycleOwner,
                 offsetToStart = offsetToStart,
                 dimWallpaper = true,
-                onPreviewDirty = { activity.recreate() },
+                onWallpaperPreviewDirty = { activity.recreate() },
             )
 
         previewView.contentDescription =