1 /*
2  * Copyright (C) 2017 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.wallpaper.module
17 
18 import android.app.WallpaperColors
19 import android.app.WallpaperManager
20 import android.content.Context
21 import android.content.Intent
22 import android.net.Uri
23 import android.os.Bundle
24 import androidx.activity.ComponentActivity
25 import androidx.fragment.app.Fragment
26 import androidx.lifecycle.LifecycleOwner
27 import com.android.customization.model.color.DefaultWallpaperColorResources
28 import com.android.customization.model.color.WallpaperColorResources
29 import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
30 import com.android.systemui.shared.settings.data.repository.SecureSettingsRepositoryImpl
31 import com.android.wallpaper.config.BaseFlags
32 import com.android.wallpaper.effects.EffectsController
33 import com.android.wallpaper.model.CategoryProvider
34 import com.android.wallpaper.model.InlinePreviewIntentFactory
35 import com.android.wallpaper.model.LiveWallpaperInfo
36 import com.android.wallpaper.model.WallpaperInfo
37 import com.android.wallpaper.module.logging.UserEventLogger
38 import com.android.wallpaper.monitor.PerformanceMonitor
39 import com.android.wallpaper.network.Requester
40 import com.android.wallpaper.picker.CustomizationPickerActivity
41 import com.android.wallpaper.picker.ImagePreviewFragment
42 import com.android.wallpaper.picker.LivePreviewFragment
43 import com.android.wallpaper.picker.MyPhotosStarter
44 import com.android.wallpaper.picker.PreviewActivity
45 import com.android.wallpaper.picker.PreviewFragment
46 import com.android.wallpaper.picker.ViewOnlyPreviewActivity
47 import com.android.wallpaper.picker.customization.data.content.WallpaperClient
48 import com.android.wallpaper.picker.customization.data.content.WallpaperClientImpl
49 import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository
50 import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository
51 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
52 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperSnapshotRestorer
53 import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
54 import com.android.wallpaper.picker.di.modules.MainDispatcher
55 import com.android.wallpaper.picker.individual.IndividualPickerFragment
56 import com.android.wallpaper.picker.undo.data.repository.UndoRepository
57 import com.android.wallpaper.picker.undo.domain.interactor.UndoInteractor
58 import com.android.wallpaper.system.UiModeManagerWrapper
59 import com.android.wallpaper.util.DisplayUtils
60 import dagger.Lazy
61 import javax.inject.Inject
62 import javax.inject.Singleton
63 import kotlinx.coroutines.CoroutineDispatcher
64 import kotlinx.coroutines.CoroutineScope
65 
66 @Singleton
67 open class WallpaperPicker2Injector
68 @Inject
69 constructor(
70     @MainDispatcher private val mainScope: CoroutineScope,
71     @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher,
72 ) : Injector {
73     private var alarmManagerWrapper: AlarmManagerWrapper? = null
74     private var bitmapCropper: BitmapCropper? = null
75     private var categoryProvider: CategoryProvider? = null
76     private var currentWallpaperFactory: CurrentWallpaperInfoFactory? = null
77     private var customizationSections: CustomizationSections? = null
78     private var drawableLayerResolver: DrawableLayerResolver? = null
79     private var exploreIntentChecker: ExploreIntentChecker? = null
80     private var liveWallpaperInfoFactory: LiveWallpaperInfoFactory? = null
81     private var packageStatusNotifier: PackageStatusNotifier? = null
82     private var performanceMonitor: PerformanceMonitor? = null
83     private var systemFeatureChecker: SystemFeatureChecker? = null
84     private var wallpaperPersister: WallpaperPersister? = null
85     private var wallpaperRefresher: WallpaperRefresher? = null
86     private var wallpaperStatusChecker: WallpaperStatusChecker? = null
87     private var flags: BaseFlags? = null
88     private var undoInteractor: UndoInteractor? = null
89     private var wallpaperInteractor: WallpaperInteractor? = null
90     private var wallpaperClient: WallpaperClient? = null
91     private var wallpaperSnapshotRestorer: WallpaperSnapshotRestorer? = null
92     private var secureSettingsRepository: SecureSettingsRepository? = null
93     private var wallpaperColorsRepository: WallpaperColorsRepository? = null
94     private var previewActivityIntentFactory: InlinePreviewIntentFactory? = null
95     private var viewOnlyPreviewActivityIntentFactory: InlinePreviewIntentFactory? = null
96 
97     // Injected objects, sorted by alphabetical order on the type of object
98     @Inject lateinit var displayUtils: Lazy<DisplayUtils>
99     @Inject lateinit var requester: Lazy<Requester>
100     @Inject lateinit var networkStatusNotifier: Lazy<NetworkStatusNotifier>
101     @Inject lateinit var partnerProvider: Lazy<PartnerProvider>
102     @Inject lateinit var uiModeManager: Lazy<UiModeManagerWrapper>
103     @Inject lateinit var userEventLogger: Lazy<UserEventLogger>
104     @Inject lateinit var injectedWallpaperClient: Lazy<WallpaperClient>
105     @Inject lateinit var injectedWallpaperInteractor: Lazy<WallpaperInteractor>
106     @Inject lateinit var prefs: Lazy<WallpaperPreferences>
107 
getApplicationCoroutineScopenull108     override fun getApplicationCoroutineScope(): CoroutineScope {
109         return mainScope
110     }
111 
112     @Synchronized
getAlarmManagerWrappernull113     override fun getAlarmManagerWrapper(context: Context): AlarmManagerWrapper {
114         return alarmManagerWrapper
115             ?: DefaultAlarmManagerWrapper(context.applicationContext).also {
116                 alarmManagerWrapper = it
117             }
118     }
119 
120     @Synchronized
getBitmapCroppernull121     override fun getBitmapCropper(): BitmapCropper {
122         return bitmapCropper ?: DefaultBitmapCropper().also { bitmapCropper = it }
123     }
124 
getCategoryProvidernull125     override fun getCategoryProvider(context: Context): CategoryProvider {
126         return categoryProvider
127             ?: DefaultCategoryProvider(context.applicationContext).also { categoryProvider = it }
128     }
129 
130     @Synchronized
getCurrentWallpaperInfoFactorynull131     override fun getCurrentWallpaperInfoFactory(context: Context): CurrentWallpaperInfoFactory {
132         return currentWallpaperFactory
133             ?: DefaultCurrentWallpaperInfoFactory(
134                     getWallpaperRefresher(context.applicationContext),
135                     getLiveWallpaperInfoFactory(context.applicationContext),
136                 )
137                 .also { currentWallpaperFactory = it }
138     }
139 
getCustomizationSectionsnull140     override fun getCustomizationSections(activity: ComponentActivity): CustomizationSections {
141         return customizationSections
142             ?: WallpaperPickerSections().also { customizationSections = it }
143     }
144 
getDeepLinkRedirectIntentnull145     override fun getDeepLinkRedirectIntent(context: Context, uri: Uri): Intent {
146         val intent = Intent()
147         intent.setClass(context, CustomizationPickerActivity::class.java)
148         intent.data = uri
149         intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
150         return intent
151     }
152 
getDisplayUtilsnull153     override fun getDisplayUtils(context: Context): DisplayUtils {
154         return displayUtils.get()
155     }
156 
getDownloadableIntentActionnull157     override fun getDownloadableIntentAction(): String? {
158         return null
159     }
160 
getDrawableLayerResolvernull161     override fun getDrawableLayerResolver(): DrawableLayerResolver {
162         return drawableLayerResolver
163             ?: DefaultDrawableLayerResolver().also { drawableLayerResolver = it }
164     }
165 
getEffectsControllernull166     override fun getEffectsController(
167         context: Context,
168     ): EffectsController? {
169         return null
170     }
171 
172     @Synchronized
getExploreIntentCheckernull173     override fun getExploreIntentChecker(context: Context): ExploreIntentChecker {
174         return exploreIntentChecker
175             ?: DefaultExploreIntentChecker(context.applicationContext).also {
176                 exploreIntentChecker = it
177             }
178     }
179 
getIndividualPickerFragmentnull180     override fun getIndividualPickerFragment(context: Context, collectionId: String): Fragment {
181         return IndividualPickerFragment.newInstance(collectionId)
182     }
183 
getLiveWallpaperInfoFactorynull184     override fun getLiveWallpaperInfoFactory(context: Context): LiveWallpaperInfoFactory {
185         return liveWallpaperInfoFactory
186             ?: DefaultLiveWallpaperInfoFactory().also { liveWallpaperInfoFactory = it }
187     }
188 
189     @Synchronized
getNetworkStatusNotifiernull190     override fun getNetworkStatusNotifier(context: Context): NetworkStatusNotifier {
191         return networkStatusNotifier.get()
192     }
193 
194     @Synchronized
getPackageStatusNotifiernull195     override fun getPackageStatusNotifier(context: Context): PackageStatusNotifier {
196         return packageStatusNotifier
197             ?: DefaultPackageStatusNotifier(context.applicationContext).also {
198                 packageStatusNotifier = it
199             }
200     }
201 
202     @Synchronized
getPartnerProvidernull203     override fun getPartnerProvider(context: Context): PartnerProvider {
204         return partnerProvider.get()
205     }
206 
207     @Synchronized
getPerformanceMonitornull208     override fun getPerformanceMonitor(): PerformanceMonitor? {
209 
210         return performanceMonitor
211             ?: PerformanceMonitor {
212                     /** No Op */
213                 }
214                 .also { performanceMonitor = it }
215     }
216 
getPreviewFragmentnull217     override fun getPreviewFragment(
218         context: Context,
219         wallpaperInfo: WallpaperInfo,
220         viewAsHome: Boolean,
221         isAssetIdPresent: Boolean,
222         isNewTask: Boolean,
223     ): Fragment {
224         val isLiveWallpaper = wallpaperInfo is LiveWallpaperInfo
225         return (if (isLiveWallpaper) LivePreviewFragment() else ImagePreviewFragment()).apply {
226             arguments =
227                 Bundle().apply {
228                     putParcelable(PreviewFragment.ARG_WALLPAPER, wallpaperInfo)
229                     putBoolean(PreviewFragment.ARG_VIEW_AS_HOME, viewAsHome)
230                     putBoolean(PreviewFragment.ARG_IS_ASSET_ID_PRESENT, isAssetIdPresent)
231                     putBoolean(PreviewFragment.ARG_IS_NEW_TASK, isNewTask)
232                 }
233         }
234     }
235 
236     @Synchronized
getRequesternull237     override fun getRequester(context: Context): Requester {
238         return requester.get()
239     }
240 
241     @Synchronized
getSystemFeatureCheckernull242     override fun getSystemFeatureChecker(): SystemFeatureChecker {
243         return systemFeatureChecker
244             ?: DefaultSystemFeatureChecker().also { systemFeatureChecker = it }
245     }
246 
getUserEventLoggernull247     override fun getUserEventLogger(): UserEventLogger {
248         return userEventLogger.get()
249     }
250 
251     @Synchronized
getWallpaperPersisternull252     override fun getWallpaperPersister(context: Context): WallpaperPersister {
253         return wallpaperPersister
254             ?: DefaultWallpaperPersister(
255                     context.applicationContext,
256                     WallpaperManager.getInstance(context.applicationContext),
257                     getPreferences(context),
258                     WallpaperChangedNotifier.getInstance(),
259                     displayUtils.get(),
260                     getBitmapCropper(),
261                     getWallpaperStatusChecker(context),
262                     getCurrentWallpaperInfoFactory(context),
263                     getFlags().isRefactorSettingWallpaper(),
264                 )
265                 .also { wallpaperPersister = it }
266     }
267 
268     @Synchronized
getPreferencesnull269     override fun getPreferences(context: Context): WallpaperPreferences {
270         return prefs.get()
271     }
272 
273     @Synchronized
getWallpaperRefreshernull274     override fun getWallpaperRefresher(context: Context): WallpaperRefresher {
275         return wallpaperRefresher
276             ?: DefaultWallpaperRefresher(context.applicationContext).also {
277                 wallpaperRefresher = it
278             }
279     }
280 
getWallpaperStatusCheckernull281     override fun getWallpaperStatusChecker(context: Context): WallpaperStatusChecker {
282         return wallpaperStatusChecker
283             ?: DefaultWallpaperStatusChecker(
284                     wallpaperManager = WallpaperManager.getInstance(context.applicationContext),
285                 )
286                 .also { wallpaperStatusChecker = it }
287     }
288 
getFlagsnull289     override fun getFlags(): BaseFlags {
290         return flags ?: object : BaseFlags() {}.also { flags = it }
291     }
292 
getUndoInteractornull293     override fun getUndoInteractor(
294         context: Context,
295         lifecycleOwner: LifecycleOwner
296     ): UndoInteractor {
297         return undoInteractor
298             ?: UndoInteractor(
299                     getApplicationCoroutineScope(),
300                     UndoRepository(),
301                     getSnapshotRestorers(context),
302                 )
303                 .also { undoInteractor = it }
304     }
305 
getWallpaperInteractornull306     override fun getWallpaperInteractor(context: Context): WallpaperInteractor {
307         if (getFlags().isMultiCropEnabled()) {
308             return injectedWallpaperInteractor.get()
309         }
310 
311         val appContext = context.applicationContext
312         return wallpaperInteractor
313             ?: WallpaperInteractor(
314                     repository =
315                         WallpaperRepository(
316                             scope = getApplicationCoroutineScope(),
317                             client = getWallpaperClient(context),
318                             wallpaperPreferences = getPreferences(context = appContext),
319                             backgroundDispatcher = bgDispatcher,
320                         ),
321                 )
322                 .also { wallpaperInteractor = it }
323     }
324 
getWallpaperClientnull325     override fun getWallpaperClient(context: Context): WallpaperClient {
326         if (getFlags().isMultiCropEnabled()) {
327             return injectedWallpaperClient.get()
328         }
329 
330         val appContext = context.applicationContext
331         return wallpaperClient
332             ?: WallpaperClientImpl(
333                     context = appContext,
334                     wallpaperManager = WallpaperManager.getInstance(appContext),
335                     wallpaperPreferences = getPreferences(appContext),
336                 )
337                 .also { wallpaperClient = it }
338     }
339 
getWallpaperSnapshotRestorernull340     override fun getWallpaperSnapshotRestorer(context: Context): WallpaperSnapshotRestorer {
341         return wallpaperSnapshotRestorer
342             ?: WallpaperSnapshotRestorer(
343                     scope = getApplicationCoroutineScope(),
344                     interactor = getWallpaperInteractor(context),
345                 )
346                 .also { wallpaperSnapshotRestorer = it }
347     }
348 
getSecureSettingsRepositorynull349     protected fun getSecureSettingsRepository(context: Context): SecureSettingsRepository {
350         return secureSettingsRepository
351             ?: SecureSettingsRepositoryImpl(
352                     contentResolver = context.applicationContext.contentResolver,
353                     backgroundDispatcher = bgDispatcher,
354                 )
355                 .also { secureSettingsRepository = it }
356     }
357 
getWallpaperColorsRepositorynull358     override fun getWallpaperColorsRepository(): WallpaperColorsRepository {
359         return wallpaperColorsRepository
360             ?: WallpaperColorsRepository().also { wallpaperColorsRepository = it }
361     }
362 
getWallpaperColorResourcesnull363     override fun getWallpaperColorResources(
364         wallpaperColors: WallpaperColors,
365         context: Context
366     ): WallpaperColorResources {
367         return DefaultWallpaperColorResources(wallpaperColors)
368     }
369 
getMyPhotosIntentProvidernull370     override fun getMyPhotosIntentProvider(): MyPhotosStarter.MyPhotosIntentProvider {
371         return object : MyPhotosStarter.MyPhotosIntentProvider {}
372     }
373 
isCurrentSelectedColorPresetnull374     override fun isCurrentSelectedColorPreset(context: Context): Boolean {
375         return false
376     }
377 
getPreviewActivityIntentFactorynull378     override fun getPreviewActivityIntentFactory(): InlinePreviewIntentFactory {
379         return previewActivityIntentFactory
380             ?: PreviewActivity.PreviewActivityIntentFactory().also {
381                 previewActivityIntentFactory = it
382             }
383     }
384 
getViewOnlyPreviewActivityIntentFactorynull385     override fun getViewOnlyPreviewActivityIntentFactory(): InlinePreviewIntentFactory {
386         return viewOnlyPreviewActivityIntentFactory
387             ?: ViewOnlyPreviewActivity.ViewOnlyPreviewActivityIntentFactory().also {
388                 viewOnlyPreviewActivityIntentFactory = it
389             }
390     }
391 
392     companion object {
393         /**
394          * When this injector is overridden, this is the minimal value that should be used by
395          * restorers returns in [getSnapshotRestorers].
396          */
397         @JvmStatic protected val MIN_SNAPSHOT_RESTORER_KEY = 0
398     }
399 }
400