1 package com.android.systemui.shared.regionsampling
2 
3 import android.app.WallpaperColors
4 import android.app.WallpaperManager
5 import android.graphics.Color
6 import android.graphics.RectF
7 import android.view.View
8 import androidx.test.ext.junit.runners.AndroidJUnit4
9 import androidx.test.filters.SmallTest
10 import com.android.systemui.SysuiTestCase
11 import com.android.systemui.util.mockito.any
12 import com.android.systemui.util.mockito.capture
13 import com.google.common.truth.Truth.assertThat
14 import java.io.PrintWriter
15 import java.util.concurrent.Executor
16 import org.junit.Assert.assertTrue
17 import org.junit.Before
18 import org.junit.Rule
19 import org.junit.Test
20 import org.junit.runner.RunWith
21 import org.mockito.ArgumentCaptor
22 import org.mockito.ArgumentMatchers.eq
23 import org.mockito.Captor
24 import org.mockito.Mock
25 import org.mockito.Mockito.clearInvocations
26 import org.mockito.Mockito.never
27 import org.mockito.Mockito.verify
28 import org.mockito.Mockito.`when` as whenever
29 import org.mockito.junit.MockitoJUnit
30 
31 @RunWith(AndroidJUnit4::class)
32 @SmallTest
33 class RegionSamplerTest : SysuiTestCase() {
34 
35     @JvmField @Rule val mockito = MockitoJUnit.rule()
36 
37     @Mock private lateinit var sampledView: View
38     @Mock private lateinit var mainExecutor: Executor
39     @Mock private lateinit var bgExecutor: Executor
40     @Mock private lateinit var pw: PrintWriter
41     @Mock private lateinit var wallpaperManager: WallpaperManager
42     @Mock private lateinit var updateForegroundColor: UpdateColorCallback
43 
44     private lateinit var regionSampler: RegionSampler // lockscreen
45     private lateinit var homescreenRegionSampler: RegionSampler
46 
47     @Captor
48     private lateinit var colorsChangedListener:
49         ArgumentCaptor<WallpaperManager.LocalWallpaperColorConsumer>
50 
51     @Captor private lateinit var layoutChangedListener: ArgumentCaptor<View.OnLayoutChangeListener>
52 
53     @Before
setUpnull54     fun setUp() {
55         whenever(sampledView.isAttachedToWindow).thenReturn(true)
56         whenever(sampledView.width).thenReturn(100)
57         whenever(sampledView.height).thenReturn(100)
58         whenever(sampledView.isLaidOut).thenReturn(true)
59         whenever(sampledView.locationOnScreen).thenReturn(intArrayOf(0, 0))
60 
61         regionSampler =
62             RegionSampler(
63                 sampledView,
64                 mainExecutor,
65                 bgExecutor,
66                 regionSamplingEnabled = true,
67                 isLockscreen = true,
68                 wallpaperManager,
69                 updateForegroundColor
70             )
71         regionSampler.displaySize.set(1080, 2050)
72 
73         // TODO(b/265969235): test sampling on home screen via WallpaperManager.FLAG_SYSTEM
74         homescreenRegionSampler =
75             RegionSampler(
76                 sampledView,
77                 mainExecutor,
78                 bgExecutor,
79                 regionSamplingEnabled = true,
80                 isLockscreen = false,
81                 wallpaperManager,
82                 updateForegroundColor
83             )
84     }
85 
86     @Test
testCalculatedBounds_inRangenull87     fun testCalculatedBounds_inRange() {
88         // test calculations return region within [0,1]
89         sampledView.setLeftTopRightBottom(100, 100, 200, 200)
90         var fractionalBounds =
91             regionSampler.calculateScreenLocation(sampledView)?.let {
92                 regionSampler.convertBounds(it)
93             }
94 
95         assertTrue(fractionalBounds?.left!! >= 0.0f)
96         assertTrue(fractionalBounds.right <= 1.0f)
97         assertTrue(fractionalBounds.top >= 0.0f)
98         assertTrue(fractionalBounds.bottom <= 1.0f)
99     }
100 
101     @Test
testEmptyView_returnsEarlynull102     fun testEmptyView_returnsEarly() {
103         sampledView.setLeftTopRightBottom(0, 0, 0, 0)
104         whenever(sampledView.width).thenReturn(0)
105         whenever(sampledView.height).thenReturn(0)
106         regionSampler.startRegionSampler()
107         // returns early so should never call this function
108         verify(wallpaperManager, never())
109             .addOnColorsChangedListener(
110                 any(WallpaperManager.LocalWallpaperColorConsumer::class.java),
111                 any(),
112                 any()
113             )
114     }
115 
116     @Test
testLayoutChange_notifiesListenernull117     fun testLayoutChange_notifiesListener() {
118         regionSampler.startRegionSampler()
119         // don't count addOnColorsChangedListener() call made in startRegionSampler()
120         clearInvocations(wallpaperManager)
121 
122         verify(sampledView).addOnLayoutChangeListener(capture(layoutChangedListener))
123         layoutChangedListener.value.onLayoutChange(
124             sampledView,
125             300,
126             300,
127             400,
128             400,
129             100,
130             100,
131             200,
132             200
133         )
134         verify(sampledView).removeOnLayoutChangeListener(layoutChangedListener.value)
135         verify(wallpaperManager)
136             .removeOnColorsChangedListener(
137                 any(WallpaperManager.LocalWallpaperColorConsumer::class.java)
138             )
139         verify(wallpaperManager)
140             .addOnColorsChangedListener(
141                 any(WallpaperManager.LocalWallpaperColorConsumer::class.java),
142                 any(),
143                 any()
144             )
145     }
146 
147     @Test
testColorsChanged_triggersCallbacknull148     fun testColorsChanged_triggersCallback() {
149         regionSampler.startRegionSampler()
150         verify(wallpaperManager)
151             .addOnColorsChangedListener(
152                 capture(colorsChangedListener),
153                 any(),
154                 eq(WallpaperManager.FLAG_LOCK)
155             )
156         setWhiteWallpaper()
157         verify(updateForegroundColor).invoke()
158     }
159 
160     @Test
testRegionDarknessnull161     fun testRegionDarkness() {
162         regionSampler.startRegionSampler()
163         verify(wallpaperManager)
164             .addOnColorsChangedListener(
165                 capture(colorsChangedListener),
166                 any(),
167                 eq(WallpaperManager.FLAG_LOCK)
168             )
169 
170         // should detect dark region
171         setBlackWallpaper()
172         assertThat(regionSampler.currentRegionDarkness()).isEqualTo(RegionDarkness.DARK)
173 
174         // should detect light region
175         setWhiteWallpaper()
176         assertThat(regionSampler.currentRegionDarkness()).isEqualTo(RegionDarkness.LIGHT)
177     }
178 
179     @Test
testForegroundColornull180     fun testForegroundColor() {
181         regionSampler.setForegroundColors(Color.WHITE, Color.BLACK)
182         regionSampler.startRegionSampler()
183         verify(wallpaperManager)
184             .addOnColorsChangedListener(
185                 capture(colorsChangedListener),
186                 any(),
187                 eq(WallpaperManager.FLAG_LOCK)
188             )
189 
190         // dark background, light text
191         setBlackWallpaper()
192         assertThat(regionSampler.currentForegroundColor()).isEqualTo(Color.WHITE)
193 
194         // light background, dark text
195         setWhiteWallpaper()
196         assertThat(regionSampler.currentForegroundColor()).isEqualTo(Color.BLACK)
197     }
198 
setBlackWallpapernull199     private fun setBlackWallpaper() {
200         val wallpaperColors =
201             WallpaperColors(Color.valueOf(Color.BLACK), Color.valueOf(Color.BLACK), null)
202         colorsChangedListener.value.onColorsChanged(
203             RectF(100.0f, 100.0f, 200.0f, 200.0f),
204             wallpaperColors
205         )
206     }
setWhiteWallpapernull207     private fun setWhiteWallpaper() {
208         val wallpaperColors =
209             WallpaperColors(
210                 Color.valueOf(Color.WHITE),
211                 Color.valueOf(Color.WHITE),
212                 null,
213                 WallpaperColors.HINT_SUPPORTS_DARK_TEXT
214             )
215         colorsChangedListener.value.onColorsChanged(
216             RectF(100.0f, 100.0f, 200.0f, 200.0f),
217             wallpaperColors
218         )
219     }
220 
221     @Test
testDumpnull222     fun testDump() {
223         regionSampler.dump(pw)
224         homescreenRegionSampler.dump(pw)
225     }
226 }
227