package com.android.systemui.shared.regionsampling import android.app.WallpaperColors import android.app.WallpaperManager import android.graphics.Color import android.graphics.RectF import android.testing.AndroidTestingRunner import android.view.View import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.google.common.truth.Truth.assertThat import java.io.PrintWriter import java.util.concurrent.Executor import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.eq import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit @RunWith(AndroidTestingRunner::class) @SmallTest class RegionSamplerTest : SysuiTestCase() { @JvmField @Rule val mockito = MockitoJUnit.rule() @Mock private lateinit var sampledView: View @Mock private lateinit var mainExecutor: Executor @Mock private lateinit var bgExecutor: Executor @Mock private lateinit var pw: PrintWriter @Mock private lateinit var wallpaperManager: WallpaperManager @Mock private lateinit var updateForegroundColor: UpdateColorCallback private lateinit var regionSampler: RegionSampler // lockscreen private lateinit var homescreenRegionSampler: RegionSampler @Captor private lateinit var colorsChangedListener: ArgumentCaptor @Captor private lateinit var layoutChangedListener: ArgumentCaptor @Before fun setUp() { whenever(sampledView.isAttachedToWindow).thenReturn(true) whenever(sampledView.width).thenReturn(100) whenever(sampledView.height).thenReturn(100) whenever(sampledView.isLaidOut).thenReturn(true) whenever(sampledView.locationOnScreen).thenReturn(intArrayOf(0, 0)) regionSampler = RegionSampler( sampledView, mainExecutor, bgExecutor, regionSamplingEnabled = true, isLockscreen = true, wallpaperManager, updateForegroundColor ) regionSampler.displaySize.set(1080, 2050) // TODO(b/265969235): test sampling on home screen via WallpaperManager.FLAG_SYSTEM homescreenRegionSampler = RegionSampler( sampledView, mainExecutor, bgExecutor, regionSamplingEnabled = true, isLockscreen = false, wallpaperManager, updateForegroundColor ) } @Test fun testCalculatedBounds_inRange() { // test calculations return region within [0,1] sampledView.setLeftTopRightBottom(100, 100, 200, 200) var fractionalBounds = regionSampler.calculateScreenLocation(sampledView)?.let { regionSampler.convertBounds(it) } assertTrue(fractionalBounds?.left!! >= 0.0f) assertTrue(fractionalBounds.right <= 1.0f) assertTrue(fractionalBounds.top >= 0.0f) assertTrue(fractionalBounds.bottom <= 1.0f) } @Test fun testEmptyView_returnsEarly() { sampledView.setLeftTopRightBottom(0, 0, 0, 0) whenever(sampledView.width).thenReturn(0) whenever(sampledView.height).thenReturn(0) regionSampler.startRegionSampler() // returns early so should never call this function verify(wallpaperManager, never()) .addOnColorsChangedListener( any(WallpaperManager.LocalWallpaperColorConsumer::class.java), any(), any() ) } @Test fun testLayoutChange_notifiesListener() { regionSampler.startRegionSampler() // don't count addOnColorsChangedListener() call made in startRegionSampler() clearInvocations(wallpaperManager) verify(sampledView).addOnLayoutChangeListener(capture(layoutChangedListener)) layoutChangedListener.value.onLayoutChange( sampledView, 300, 300, 400, 400, 100, 100, 200, 200 ) verify(sampledView).removeOnLayoutChangeListener(layoutChangedListener.value) verify(wallpaperManager) .removeOnColorsChangedListener( any(WallpaperManager.LocalWallpaperColorConsumer::class.java) ) verify(wallpaperManager) .addOnColorsChangedListener( any(WallpaperManager.LocalWallpaperColorConsumer::class.java), any(), any() ) } @Test fun testColorsChanged_triggersCallback() { regionSampler.startRegionSampler() verify(wallpaperManager) .addOnColorsChangedListener( capture(colorsChangedListener), any(), eq(WallpaperManager.FLAG_LOCK) ) setWhiteWallpaper() verify(updateForegroundColor).invoke() } @Test fun testRegionDarkness() { regionSampler.startRegionSampler() verify(wallpaperManager) .addOnColorsChangedListener( capture(colorsChangedListener), any(), eq(WallpaperManager.FLAG_LOCK) ) // should detect dark region setBlackWallpaper() assertThat(regionSampler.currentRegionDarkness()).isEqualTo(RegionDarkness.DARK) // should detect light region setWhiteWallpaper() assertThat(regionSampler.currentRegionDarkness()).isEqualTo(RegionDarkness.LIGHT) } @Test fun testForegroundColor() { regionSampler.setForegroundColors(Color.WHITE, Color.BLACK) regionSampler.startRegionSampler() verify(wallpaperManager) .addOnColorsChangedListener( capture(colorsChangedListener), any(), eq(WallpaperManager.FLAG_LOCK) ) // dark background, light text setBlackWallpaper() assertThat(regionSampler.currentForegroundColor()).isEqualTo(Color.WHITE) // light background, dark text setWhiteWallpaper() assertThat(regionSampler.currentForegroundColor()).isEqualTo(Color.BLACK) } private fun setBlackWallpaper() { val wallpaperColors = WallpaperColors(Color.valueOf(Color.BLACK), Color.valueOf(Color.BLACK), null) colorsChangedListener.value.onColorsChanged( RectF(100.0f, 100.0f, 200.0f, 200.0f), wallpaperColors ) } private fun setWhiteWallpaper() { val wallpaperColors = WallpaperColors( Color.valueOf(Color.WHITE), Color.valueOf(Color.WHITE), null, WallpaperColors.HINT_SUPPORTS_DARK_TEXT ) colorsChangedListener.value.onColorsChanged( RectF(100.0f, 100.0f, 200.0f, 200.0f), wallpaperColors ) } @Test fun testDump() { regionSampler.dump(pw) homescreenRegionSampler.dump(pw) } }