• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.customization.module
17 
18 import android.app.Activity
19 import android.app.UiModeManager
20 import android.app.WallpaperManager
21 import android.content.Context
22 import android.content.Intent
23 import android.content.res.Resources
24 import android.net.Uri
25 import android.text.TextUtils
26 import androidx.activity.ComponentActivity
27 import androidx.fragment.app.FragmentActivity
28 import androidx.lifecycle.DefaultLifecycleObserver
29 import androidx.lifecycle.LifecycleOwner
30 import androidx.lifecycle.ViewModelProvider
31 import com.android.customization.model.color.ColorCustomizationManager
32 import com.android.customization.model.color.ColorOptionsProvider
33 import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_PRESET
34 import com.android.customization.model.grid.GridOptionsManager
35 import com.android.customization.model.grid.data.repository.GridRepositoryImpl
36 import com.android.customization.model.grid.domain.interactor.GridInteractor
37 import com.android.customization.model.grid.domain.interactor.GridSnapshotRestorer
38 import com.android.customization.model.grid.ui.viewmodel.GridScreenViewModel
39 import com.android.customization.model.mode.DarkModeSnapshotRestorer
40 import com.android.customization.model.theme.OverlayManagerCompat
41 import com.android.customization.model.theme.ThemeBundleProvider
42 import com.android.customization.model.theme.ThemeManager
43 import com.android.customization.model.themedicon.ThemedIconSwitchProvider
44 import com.android.customization.model.themedicon.data.repository.ThemeIconRepository
45 import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor
46 import com.android.customization.model.themedicon.domain.interactor.ThemedIconSnapshotRestorer
47 import com.android.customization.picker.clock.data.repository.ClockPickerRepositoryImpl
48 import com.android.customization.picker.clock.data.repository.ClockRegistryProvider
49 import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
50 import com.android.customization.picker.clock.domain.interactor.ClockPickerSnapshotRestorer
51 import com.android.customization.picker.clock.ui.view.ClockViewFactory
52 import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
53 import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
54 import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
55 import com.android.customization.picker.clock.utils.ClockDescriptionUtils
56 import com.android.customization.picker.clock.utils.ThemePickerClockDescriptionUtils
57 import com.android.customization.picker.color.data.repository.ColorPickerRepositoryImpl
58 import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
59 import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
60 import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
61 import com.android.customization.picker.notifications.data.repository.NotificationsRepository
62 import com.android.customization.picker.notifications.domain.interactor.NotificationsInteractor
63 import com.android.customization.picker.notifications.domain.interactor.NotificationsSnapshotRestorer
64 import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel
65 import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository
66 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
67 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer
68 import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel
69 import com.android.systemui.shared.clocks.ClockRegistry
70 import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
71 import com.android.systemui.shared.customization.data.content.CustomizationProviderClientImpl
72 import com.android.wallpaper.config.BaseFlags
73 import com.android.wallpaper.dispatchers.BackgroundDispatcher
74 import com.android.wallpaper.dispatchers.MainDispatcher
75 import com.android.wallpaper.model.WallpaperColorsViewModel
76 import com.android.wallpaper.module.CustomizationSections
77 import com.android.wallpaper.module.FragmentFactory
78 import com.android.wallpaper.module.UserEventLogger
79 import com.android.wallpaper.module.WallpaperPicker2Injector
80 import com.android.wallpaper.picker.CustomizationPickerActivity
81 import com.android.wallpaper.picker.customization.data.content.WallpaperClientImpl
82 import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository
83 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
84 import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
85 import com.android.wallpaper.util.ScreenSizeCalculator
86 import javax.inject.Inject
87 import javax.inject.Singleton
88 import kotlinx.coroutines.CoroutineDispatcher
89 import kotlinx.coroutines.CoroutineScope
90 
91 @Singleton
92 open class ThemePickerInjector
93 @Inject
94 internal constructor(
95     @MainDispatcher private val mainScope: CoroutineScope,
96     @MainDispatcher private val mainDispatcher: CoroutineDispatcher,
97     @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
98 ) : WallpaperPicker2Injector(mainScope, bgDispatcher), CustomizationInjector {
99     private var customizationSections: CustomizationSections? = null
100     private var userEventLogger: UserEventLogger? = null
101     private var wallpaperInteractor: WallpaperInteractor? = null
102     private var keyguardQuickAffordancePickerInteractor: KeyguardQuickAffordancePickerInteractor? =
103         null
104     private var keyguardQuickAffordancePickerViewModelFactory:
105         KeyguardQuickAffordancePickerViewModel.Factory? =
106         null
107     private var customizationProviderClient: CustomizationProviderClient? = null
108     private var fragmentFactory: FragmentFactory? = null
109     private var keyguardQuickAffordanceSnapshotRestorer: KeyguardQuickAffordanceSnapshotRestorer? =
110         null
111     private var notificationsSnapshotRestorer: NotificationsSnapshotRestorer? = null
112     private var clockPickerInteractor: ClockPickerInteractor? = null
113     private var clockSectionViewModel: ClockSectionViewModel? = null
114     private var clockCarouselViewModelFactory: ClockCarouselViewModel.Factory? = null
115     private var clockViewFactory: ClockViewFactory? = null
116     private var clockPickerSnapshotRestorer: ClockPickerSnapshotRestorer? = null
117     private var notificationsInteractor: NotificationsInteractor? = null
118     private var notificationSectionViewModelFactory: NotificationSectionViewModel.Factory? = null
119     private var colorPickerInteractor: ColorPickerInteractor? = null
120     private var colorPickerViewModelFactory: ColorPickerViewModel.Factory? = null
121     private var colorPickerSnapshotRestorer: ColorPickerSnapshotRestorer? = null
122     private var colorCustomizationManager: ColorCustomizationManager? = null
123     private var darkModeSnapshotRestorer: DarkModeSnapshotRestorer? = null
124     private var themedIconSnapshotRestorer: ThemedIconSnapshotRestorer? = null
125     private var themedIconInteractor: ThemedIconInteractor? = null
126     private var clockSettingsViewModelFactory: ClockSettingsViewModel.Factory? = null
127     private var clockDescriptionUtils: ClockDescriptionUtils? = null
128     private var gridInteractor: GridInteractor? = null
129     private var gridSnapshotRestorer: GridSnapshotRestorer? = null
130     private var gridScreenViewModelFactory: GridScreenViewModel.Factory? = null
131     private var clockRegistryProvider: ClockRegistryProvider? = null
132 
133     override fun getCustomizationSections(activity: ComponentActivity): CustomizationSections {
134         return customizationSections
135             ?: DefaultCustomizationSections(
136                     getColorPickerViewModelFactory(
137                         context = activity,
138                         wallpaperColorsViewModel = getWallpaperColorsViewModel(),
139                     ),
140                     getKeyguardQuickAffordancePickerInteractor(activity),
141                     getKeyguardQuickAffordancePickerViewModelFactory(activity),
142                     NotificationSectionViewModel.Factory(
143                         interactor = getNotificationsInteractor(activity),
144                     ),
145                     getFlags(),
146                     getClockCarouselViewModelFactory(
147                         getClockPickerInteractor(activity.applicationContext),
148                     ),
149                     getClockViewFactory(activity),
150                     getDarkModeSnapshotRestorer(activity),
151                     getThemedIconSnapshotRestorer(activity),
152                     getThemedIconInteractor(),
153                     getColorPickerInteractor(activity, getWallpaperColorsViewModel()),
154                 )
155                 .also { customizationSections = it }
156     }
157 
158     override fun getDeepLinkRedirectIntent(context: Context, uri: Uri): Intent {
159         val intent = Intent()
160         intent.setClass(context, CustomizationPickerActivity::class.java)
161         intent.data = uri
162         intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
163         return intent
164     }
165 
166     override fun getDownloadableIntentAction(): String? {
167         return null
168     }
169 
170     @Synchronized
171     override fun getUserEventLogger(context: Context): ThemesUserEventLogger {
172         return userEventLogger as? ThemesUserEventLogger
173             ?: StatsLogUserEventLogger(
174                     getPreferences(context.applicationContext),
175                     getWallpaperStatusChecker(context.applicationContext),
176                 )
177                 .also { userEventLogger = it }
178     }
179 
180     override fun getFragmentFactory(): FragmentFactory? {
181         return fragmentFactory ?: ThemePickerFragmentFactory().also { fragmentFactory }
182     }
183 
184     override fun getSnapshotRestorers(
185         context: Context,
186     ): Map<Int, SnapshotRestorer> {
187         return super<WallpaperPicker2Injector>.getSnapshotRestorers(context).toMutableMap().apply {
188             this[KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER] =
189                 getKeyguardQuickAffordanceSnapshotRestorer(context)
190             // TODO(b/285047815): Enable after adding wallpaper id for default static wallpaper
191             if (getFlags().isWallpaperRestorerEnabled()) {
192                 this[KEY_WALLPAPER_SNAPSHOT_RESTORER] = getWallpaperSnapshotRestorer(context)
193             }
194             this[KEY_NOTIFICATIONS_SNAPSHOT_RESTORER] = getNotificationsSnapshotRestorer(context)
195             this[KEY_DARK_MODE_SNAPSHOT_RESTORER] = getDarkModeSnapshotRestorer(context)
196             this[KEY_THEMED_ICON_SNAPSHOT_RESTORER] = getThemedIconSnapshotRestorer(context)
197             this[KEY_APP_GRID_SNAPSHOT_RESTORER] = getGridSnapshotRestorer(context)
198             this[KEY_COLOR_PICKER_SNAPSHOT_RESTORER] =
199                 getColorPickerSnapshotRestorer(context, getWallpaperColorsViewModel())
200             this[KEY_CLOCKS_SNAPSHOT_RESTORER] = getClockPickerSnapshotRestorer(context)
201         }
202     }
203 
204     override fun getCustomizationPreferences(context: Context): CustomizationPreferences {
205         return getPreferences(context) as CustomizationPreferences
206     }
207 
208     override fun getThemeManager(
209         provider: ThemeBundleProvider,
210         activity: FragmentActivity,
211         overlayManagerCompat: OverlayManagerCompat,
212         logger: ThemesUserEventLogger
213     ): ThemeManager {
214         return ThemeManager(provider, activity, overlayManagerCompat, logger)
215     }
216 
217     override fun getWallpaperInteractor(context: Context): WallpaperInteractor {
218         val appContext = context.applicationContext
219         return wallpaperInteractor
220             ?: WallpaperInteractor(
221                     repository =
222                         WallpaperRepository(
223                             scope = getApplicationCoroutineScope(),
224                             client =
225                                 WallpaperClientImpl(
226                                     context = appContext,
227                                     infoFactory = getCurrentWallpaperInfoFactory(appContext),
228                                     wallpaperManager = WallpaperManager.getInstance(appContext)
229                                 ),
230                             wallpaperPreferences = getPreferences(context = appContext),
231                             backgroundDispatcher = bgDispatcher,
232                         ),
233                     shouldHandleReload = {
234                         TextUtils.equals(
235                             getColorCustomizationManager(appContext).currentColorSource,
236                             ColorOptionsProvider.COLOR_SOURCE_PRESET
237                         )
238                     }
239                 )
240                 .also { wallpaperInteractor = it }
241     }
242 
243     override fun getKeyguardQuickAffordancePickerInteractor(
244         context: Context
245     ): KeyguardQuickAffordancePickerInteractor {
246         return keyguardQuickAffordancePickerInteractor
247             ?: getKeyguardQuickAffordancePickerInteractorImpl(context).also {
248                 keyguardQuickAffordancePickerInteractor = it
249             }
250     }
251 
252     fun getKeyguardQuickAffordancePickerViewModelFactory(
253         context: Context
254     ): KeyguardQuickAffordancePickerViewModel.Factory {
255         return keyguardQuickAffordancePickerViewModelFactory
256             ?: KeyguardQuickAffordancePickerViewModel.Factory(
257                     context.applicationContext,
258                     getKeyguardQuickAffordancePickerInteractor(context),
259                     getWallpaperInteractor(context),
260                     getCurrentWallpaperInfoFactory(context),
261                 )
262                 .also { keyguardQuickAffordancePickerViewModelFactory = it }
263     }
264 
265     private fun getKeyguardQuickAffordancePickerInteractorImpl(
266         context: Context
267     ): KeyguardQuickAffordancePickerInteractor {
268         val client = getKeyguardQuickAffordancePickerProviderClient(context)
269         val appContext = context.applicationContext
270         return KeyguardQuickAffordancePickerInteractor(
271             KeyguardQuickAffordancePickerRepository(
272                 client,
273                 getApplicationCoroutineScope(),
274                 getFlags(),
275                 appContext
276             ),
277             client
278         ) {
279             getKeyguardQuickAffordanceSnapshotRestorer(appContext)
280         }
281     }
282 
283     private fun getKeyguardQuickAffordancePickerProviderClient(
284         context: Context
285     ): CustomizationProviderClient {
286         return customizationProviderClient
287             ?: CustomizationProviderClientImpl(context.applicationContext, bgDispatcher).also {
288                 customizationProviderClient = it
289             }
290     }
291 
292     private fun getKeyguardQuickAffordanceSnapshotRestorer(
293         context: Context
294     ): KeyguardQuickAffordanceSnapshotRestorer {
295         return keyguardQuickAffordanceSnapshotRestorer
296             ?: KeyguardQuickAffordanceSnapshotRestorer(
297                     getKeyguardQuickAffordancePickerInteractor(context),
298                     getKeyguardQuickAffordancePickerProviderClient(context)
299                 )
300                 .also { keyguardQuickAffordanceSnapshotRestorer = it }
301     }
302 
303     fun getNotificationSectionViewModelFactory(
304         context: Context,
305     ): NotificationSectionViewModel.Factory {
306         return notificationSectionViewModelFactory
307             ?: NotificationSectionViewModel.Factory(
308                     interactor = getNotificationsInteractor(context),
309                 )
310                 .also { notificationSectionViewModelFactory = it }
311     }
312 
313     private fun getNotificationsInteractor(
314         context: Context,
315     ): NotificationsInteractor {
316         val appContext = context.applicationContext
317         return notificationsInteractor
318             ?: NotificationsInteractor(
319                     repository =
320                         NotificationsRepository(
321                             scope = getApplicationCoroutineScope(),
322                             backgroundDispatcher = bgDispatcher,
323                             secureSettingsRepository = getSecureSettingsRepository(context),
324                         ),
325                     snapshotRestorer = { getNotificationsSnapshotRestorer(appContext) },
326                 )
327                 .also { notificationsInteractor = it }
328     }
329 
330     private fun getNotificationsSnapshotRestorer(context: Context): NotificationsSnapshotRestorer {
331         return notificationsSnapshotRestorer
332             ?: NotificationsSnapshotRestorer(
333                     interactor =
334                         getNotificationsInteractor(
335                             context = context,
336                         ),
337                 )
338                 .also { notificationsSnapshotRestorer = it }
339     }
340 
341     override fun getClockRegistry(context: Context): ClockRegistry {
342         return (clockRegistryProvider
343                 ?: ClockRegistryProvider(
344                         context = context.applicationContext,
345                         coroutineScope = getApplicationCoroutineScope(),
346                         mainDispatcher = mainDispatcher,
347                         backgroundDispatcher = bgDispatcher,
348                     )
349                     .also { clockRegistryProvider = it })
350             .get()
351     }
352 
353     override fun getClockPickerInteractor(
354         context: Context,
355     ): ClockPickerInteractor {
356         val appContext = context.applicationContext
357         return clockPickerInteractor
358             ?: ClockPickerInteractor(
359                     repository =
360                         ClockPickerRepositoryImpl(
361                             secureSettingsRepository = getSecureSettingsRepository(appContext),
362                             registry = getClockRegistry(appContext),
363                             scope = getApplicationCoroutineScope(),
364                             mainDispatcher = mainDispatcher,
365                         ),
366                     snapshotRestorer = { getClockPickerSnapshotRestorer(appContext) },
367                 )
368                 .also { clockPickerInteractor = it }
369     }
370 
371     override fun getClockSectionViewModel(
372         context: Context,
373     ): ClockSectionViewModel {
374         return clockSectionViewModel
375             ?: ClockSectionViewModel(
376                     context.applicationContext,
377                     getClockPickerInteractor(context.applicationContext)
378                 )
379                 .also { clockSectionViewModel = it }
380     }
381 
382     override fun getClockCarouselViewModelFactory(
383         interactor: ClockPickerInteractor,
384     ): ClockCarouselViewModel.Factory {
385         return clockCarouselViewModelFactory
386             ?: ClockCarouselViewModel.Factory(interactor, bgDispatcher).also {
387                 clockCarouselViewModelFactory = it
388             }
389     }
390 
391     override fun getClockViewFactory(activity: ComponentActivity): ClockViewFactory {
392         return clockViewFactory
393             ?: ClockViewFactory(
394                     activity.applicationContext,
395                     ScreenSizeCalculator.getInstance()
396                         .getScreenSize(activity.windowManager.defaultDisplay),
397                     WallpaperManager.getInstance(activity.applicationContext),
398                     getClockRegistry(activity.applicationContext),
399                 )
400                 .also {
401                     clockViewFactory = it
402                     activity.lifecycle.addObserver(
403                         object : DefaultLifecycleObserver {
404                             override fun onDestroy(owner: LifecycleOwner) {
405                                 super.onDestroy(owner)
406                                 if ((owner as Activity).isChangingConfigurations()) return
407                                 clockViewFactory?.onDestroy()
408                             }
409                         }
410                     )
411                 }
412     }
413 
414     private fun getClockPickerSnapshotRestorer(
415         context: Context,
416     ): ClockPickerSnapshotRestorer {
417         return clockPickerSnapshotRestorer
418             ?: ClockPickerSnapshotRestorer(getClockPickerInteractor(context)).also {
419                 clockPickerSnapshotRestorer = it
420             }
421     }
422 
423     override fun getColorPickerInteractor(
424         context: Context,
425         wallpaperColorsViewModel: WallpaperColorsViewModel,
426     ): ColorPickerInteractor {
427         val appContext = context.applicationContext
428         return colorPickerInteractor
429             ?: ColorPickerInteractor(
430                     repository =
431                         ColorPickerRepositoryImpl(
432                             wallpaperColorsViewModel,
433                             getColorCustomizationManager(appContext)
434                         ),
435                     snapshotRestorer = {
436                         getColorPickerSnapshotRestorer(appContext, wallpaperColorsViewModel)
437                     }
438                 )
439                 .also { colorPickerInteractor = it }
440     }
441 
442     override fun getColorPickerViewModelFactory(
443         context: Context,
444         wallpaperColorsViewModel: WallpaperColorsViewModel,
445     ): ColorPickerViewModel.Factory {
446         return colorPickerViewModelFactory
447             ?: ColorPickerViewModel.Factory(
448                     context.applicationContext,
449                     getColorPickerInteractor(context, wallpaperColorsViewModel),
450                 )
451                 .also { colorPickerViewModelFactory = it }
452     }
453 
454     private fun getColorPickerSnapshotRestorer(
455         context: Context,
456         wallpaperColorsViewModel: WallpaperColorsViewModel,
457     ): ColorPickerSnapshotRestorer {
458         return colorPickerSnapshotRestorer
459             ?: ColorPickerSnapshotRestorer(
460                     getColorPickerInteractor(context, wallpaperColorsViewModel)
461                 )
462                 .also { colorPickerSnapshotRestorer = it }
463     }
464 
465     private fun getColorCustomizationManager(context: Context): ColorCustomizationManager {
466         return colorCustomizationManager
467             ?: ColorCustomizationManager.getInstance(context, OverlayManagerCompat(context)).also {
468                 colorCustomizationManager = it
469             }
470     }
471 
472     fun getDarkModeSnapshotRestorer(
473         context: Context,
474     ): DarkModeSnapshotRestorer {
475         val appContext = context.applicationContext
476         return darkModeSnapshotRestorer
477             ?: DarkModeSnapshotRestorer(
478                     context = appContext,
479                     manager = appContext.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager,
480                     backgroundDispatcher = bgDispatcher,
481                 )
482                 .also { darkModeSnapshotRestorer = it }
483     }
484 
485     protected fun getThemedIconSnapshotRestorer(
486         context: Context,
487     ): ThemedIconSnapshotRestorer {
488         val optionProvider = ThemedIconSwitchProvider.getInstance(context)
489         return themedIconSnapshotRestorer
490             ?: ThemedIconSnapshotRestorer(
491                     isActivated = { optionProvider.isThemedIconEnabled },
492                     setActivated = { isActivated ->
493                         optionProvider.isThemedIconEnabled = isActivated
494                     },
495                     interactor = getThemedIconInteractor(),
496                 )
497                 .also { themedIconSnapshotRestorer = it }
498     }
499 
500     protected fun getThemedIconInteractor(): ThemedIconInteractor {
501         return themedIconInteractor
502             ?: ThemedIconInteractor(
503                     repository = ThemeIconRepository(),
504                 )
505                 .also { themedIconInteractor = it }
506     }
507 
508     override fun getClockSettingsViewModelFactory(
509         context: Context,
510         wallpaperColorsViewModel: WallpaperColorsViewModel,
511         clockViewFactory: ClockViewFactory,
512     ): ClockSettingsViewModel.Factory {
513         return clockSettingsViewModelFactory
514             ?: ClockSettingsViewModel.Factory(
515                     context.applicationContext,
516                     getClockPickerInteractor(context),
517                     getColorPickerInteractor(
518                         context,
519                         wallpaperColorsViewModel,
520                     ),
521                 ) { clockId ->
522                     clockId?.let { clockViewFactory.getController(clockId).config.isReactiveToTone }
523                         ?: false
524                 }
525                 .also { clockSettingsViewModelFactory = it }
526     }
527 
528     override fun getClockDescriptionUtils(resources: Resources): ClockDescriptionUtils {
529         return clockDescriptionUtils
530             ?: ThemePickerClockDescriptionUtils().also { clockDescriptionUtils = it }
531     }
532 
533     fun getGridScreenViewModelFactory(
534         context: Context,
535     ): ViewModelProvider.Factory {
536         return gridScreenViewModelFactory
537             ?: GridScreenViewModel.Factory(
538                     context = context,
539                     interactor = getGridInteractor(context),
540                 )
541                 .also { gridScreenViewModelFactory = it }
542     }
543 
544     fun getGridInteractor(context: Context): GridInteractor {
545         val appContext = context.applicationContext
546         return gridInteractor
547             ?: GridInteractor(
548                     applicationScope = getApplicationCoroutineScope(),
549                     repository =
550                         GridRepositoryImpl(
551                             applicationScope = getApplicationCoroutineScope(),
552                             manager = GridOptionsManager.getInstance(context),
553                             backgroundDispatcher = bgDispatcher,
554                             isGridApplyButtonEnabled =
555                                 BaseFlags.get().isGridApplyButtonEnabled(appContext),
556                         ),
557                     snapshotRestorer = { getGridSnapshotRestorer(appContext) },
558                 )
559                 .also { gridInteractor = it }
560     }
561 
562     private fun getGridSnapshotRestorer(
563         context: Context,
564     ): GridSnapshotRestorer {
565         return gridSnapshotRestorer
566             ?: GridSnapshotRestorer(
567                     interactor = getGridInteractor(context),
568                 )
569                 .also { gridSnapshotRestorer = it }
570     }
571 
572     override fun isCurrentSelectedColorPreset(context: Context): Boolean {
573         val colorManager =
574             ColorCustomizationManager.getInstance(context, OverlayManagerCompat(context))
575         return COLOR_SOURCE_PRESET == colorManager.currentColorSource
576     }
577 
578     companion object {
579         @JvmStatic
580         private val KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER =
581             WallpaperPicker2Injector.MIN_SNAPSHOT_RESTORER_KEY
582         @JvmStatic
583         private val KEY_WALLPAPER_SNAPSHOT_RESTORER = KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER + 1
584         @JvmStatic
585         private val KEY_NOTIFICATIONS_SNAPSHOT_RESTORER = KEY_WALLPAPER_SNAPSHOT_RESTORER + 1
586         @JvmStatic
587         private val KEY_DARK_MODE_SNAPSHOT_RESTORER = KEY_NOTIFICATIONS_SNAPSHOT_RESTORER + 1
588         @JvmStatic
589         private val KEY_THEMED_ICON_SNAPSHOT_RESTORER = KEY_DARK_MODE_SNAPSHOT_RESTORER + 1
590         @JvmStatic
591         private val KEY_APP_GRID_SNAPSHOT_RESTORER = KEY_THEMED_ICON_SNAPSHOT_RESTORER + 1
592         @JvmStatic
593         private val KEY_COLOR_PICKER_SNAPSHOT_RESTORER = KEY_APP_GRID_SNAPSHOT_RESTORER + 1
594         @JvmStatic private val KEY_CLOCKS_SNAPSHOT_RESTORER = KEY_COLOR_PICKER_SNAPSHOT_RESTORER + 1
595 
596         /**
597          * When this injector is overridden, this is the minimal value that should be used by
598          * restorers returns in [getSnapshotRestorers].
599          *
600          * It should always be greater than the biggest restorer key.
601          */
602         @JvmStatic protected val MIN_SNAPSHOT_RESTORER_KEY = KEY_CLOCKS_SNAPSHOT_RESTORER + 1
603     }
604 }
605