1 /*
<lambda>null2  * Copyright (C) 2023 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  */
17 
18 package com.android.wallpaper.testing
19 
20 import android.app.WallpaperColors
21 import android.graphics.Bitmap
22 import android.graphics.Point
23 import android.graphics.Rect
24 import com.android.wallpaper.asset.Asset
25 import com.android.wallpaper.model.Screen
26 import com.android.wallpaper.model.WallpaperModelsPair
27 import com.android.wallpaper.module.logging.UserEventLogger.SetWallpaperEntryPoint
28 import com.android.wallpaper.picker.customization.data.content.WallpaperClient
29 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
30 import com.android.wallpaper.picker.customization.shared.model.WallpaperModel
31 import com.android.wallpaper.picker.data.WallpaperModel.LiveWallpaperModel
32 import com.android.wallpaper.picker.data.WallpaperModel.StaticWallpaperModel
33 import com.android.wallpaper.picker.preview.shared.model.FullPreviewCropModel
34 import javax.inject.Inject
35 import javax.inject.Singleton
36 import kotlin.math.min
37 import kotlinx.coroutines.flow.Flow
38 import kotlinx.coroutines.flow.MutableStateFlow
39 import kotlinx.coroutines.flow.map
40 
41 @Singleton
42 class FakeWallpaperClient @Inject constructor() : WallpaperClient {
43     val wallpapersSet =
44         mutableMapOf(
45             WallpaperDestination.HOME to null as com.android.wallpaper.picker.data.WallpaperModel?,
46             WallpaperDestination.LOCK to null as com.android.wallpaper.picker.data.WallpaperModel?,
47         )
48     private var wallpaperColors: WallpaperColors? = null
49 
50     private val _recentWallpapers =
51         MutableStateFlow(
52             buildMap {
53                 WallpaperDestination.values()
54                     .filter { it != WallpaperDestination.BOTH }
55                     .forEach { screen -> put(screen, INITIAL_RECENT_WALLPAPERS) }
56             }
57         )
58     private var isPaused = false
59     private var deferred = mutableListOf<(suspend () -> Unit)>()
60 
61     fun setRecentWallpapers(
62         recentWallpapersByDestination: Map<WallpaperDestination, List<WallpaperModel>>
63     ) {
64         _recentWallpapers.value = recentWallpapersByDestination
65     }
66 
67     fun pause() {
68         isPaused = true
69     }
70 
71     suspend fun unpause() {
72         isPaused = false
73         deferred.forEach { it.invoke() }
74         deferred.clear()
75     }
76 
77     override fun recentWallpapers(
78         destination: WallpaperDestination,
79         limit: Int,
80     ): Flow<List<WallpaperModel>> {
81         return _recentWallpapers.map { wallpapersByScreen ->
82             val wallpapers =
83                 wallpapersByScreen[destination] ?: error("No wallpapers for screen $destination")
84             if (wallpapers.size > limit) {
85                 wallpapers.subList(0, min(limit, wallpapers.size))
86             } else {
87                 wallpapers
88             }
89         }
90     }
91 
92     fun getCurrentWallpaper(destination: WallpaperDestination): WallpaperModel {
93         return _recentWallpapers.value[destination]?.get(0)
94             ?: error("No wallpapers for screen $destination")
95     }
96 
97     override suspend fun setStaticWallpaper(
98         setWallpaperEntryPoint: Int,
99         destination: WallpaperDestination,
100         wallpaperModel: StaticWallpaperModel,
101         bitmap: Bitmap,
102         wallpaperSize: Point,
103         asset: Asset,
104         fullPreviewCropModels: Map<Point, FullPreviewCropModel>?,
105     ) {
106         addToWallpapersSet(wallpaperModel, destination)
107     }
108 
109     override suspend fun setLiveWallpaper(
110         setWallpaperEntryPoint: Int,
111         destination: WallpaperDestination,
112         wallpaperModel: LiveWallpaperModel,
113     ) {
114         addToWallpapersSet(wallpaperModel, destination)
115     }
116 
117     private fun addToWallpapersSet(
118         wallpaperModel: com.android.wallpaper.picker.data.WallpaperModel,
119         destination: WallpaperDestination,
120     ) {
121         wallpapersSet[destination] = wallpaperModel
122     }
123 
124     override suspend fun setRecentWallpaper(
125         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
126         destination: WallpaperDestination,
127         wallpaperId: String,
128         onDone: () -> Unit,
129     ) {
130         if (isPaused) {
131             deferred.add {
132                 setRecentWallpaper(setWallpaperEntryPoint, destination, wallpaperId, onDone)
133             }
134         } else {
135             _recentWallpapers.value =
136                 _recentWallpapers.value.toMutableMap().apply {
137                     this[destination] =
138                         _recentWallpapers.value[destination]?.sortedBy {
139                             it.wallpaperId != wallpaperId
140                         } ?: error("No wallpapers for screen $destination")
141                 }
142             onDone.invoke()
143         }
144     }
145 
146     override suspend fun loadThumbnail(
147         wallpaperId: String,
148         destination: WallpaperDestination,
149     ): Bitmap? {
150         return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
151     }
152 
153     override fun areRecentsAvailable(): Boolean {
154         return true
155     }
156 
157     override fun getCurrentCropHints(displaySizes: List<Point>, which: Int): Map<Point, Rect>? {
158         return emptyMap()
159     }
160 
161     fun setWallpaperColors(wallpaperColors: WallpaperColors) {
162         this.wallpaperColors = wallpaperColors
163     }
164 
165     override suspend fun getWallpaperColors(
166         bitmap: Bitmap,
167         cropHints: Map<Point, Rect>?,
168     ): WallpaperColors? {
169         return wallpaperColors
170     }
171 
172     override fun getWallpaperColors(screen: Screen): WallpaperColors? {
173         return wallpaperColors
174     }
175 
176     fun setCurrentWallpaperModels(
177         homeWallpaper: com.android.wallpaper.picker.data.WallpaperModel,
178         lockWallpaper: com.android.wallpaper.picker.data.WallpaperModel?,
179     ) {
180         wallpapersSet[WallpaperDestination.HOME] = homeWallpaper
181         wallpapersSet[WallpaperDestination.LOCK] = lockWallpaper
182     }
183 
184     // Getting current home wallpaper should always return non-null value
185     override suspend fun getCurrentWallpaperModels(): WallpaperModelsPair {
186         return WallpaperModelsPair(
187             wallpapersSet[WallpaperDestination.HOME]
188                 ?: (WallpaperModelUtils.getStaticWallpaperModel(
189                         wallpaperId = "defaultWallpaperId",
190                         collectionId = "defaultCollection",
191                     )
192                     .also { wallpapersSet[WallpaperDestination.HOME] = it }),
193             wallpapersSet[WallpaperDestination.LOCK],
194         )
195     }
196 
197     companion object {
198         val INITIAL_RECENT_WALLPAPERS =
199             listOf(
200                 WallpaperModel(wallpaperId = "zero", placeholderColor = 0, title = "title1"),
201                 WallpaperModel(wallpaperId = "one", placeholderColor = 1, title = "title2"),
202                 WallpaperModel(wallpaperId = "two", placeholderColor = 2, title = "title3"),
203             )
204     }
205 }
206