diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java index be1d8b8ad7d3f..b710644a308cf 100644 --- a/core/java/android/app/WallpaperColors.java +++ b/core/java/android/app/WallpaperColors.java @@ -588,7 +588,7 @@ public final class WallpaperColors implements Parcelable { int hints = 0; double meanLuminance = totalLuminance / pixels.length; - if (meanLuminance > BRIGHT_IMAGE_MEAN_LUMINANCE && darkPixels < maxDarkPixels) { + if (meanLuminance > BRIGHT_IMAGE_MEAN_LUMINANCE && darkPixels <= maxDarkPixels) { hints |= HINT_SUPPORTS_DARK_TEXT; } if (meanLuminance < DARK_THEME_MEAN_LUMINANCE) { diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index be067921a8b10..57935e3bd5b11 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1680,14 +1680,14 @@ public class WallpaperManager { * @hide */ public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback, - List regions) throws IllegalArgumentException { + List regions, int which) throws IllegalArgumentException { for (RectF region : regions) { if (!LOCAL_COLOR_BOUNDS.contains(region)) { throw new IllegalArgumentException("Regions must be within bounds " + LOCAL_COLOR_BOUNDS); } } - sGlobals.addOnColorsChangedListener(callback, regions, FLAG_SYSTEM, + sGlobals.addOnColorsChangedListener(callback, regions, which, mContext.getUserId(), mContext.getDisplayId()); } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt index 482158e80d0fd..9a00447615049 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt @@ -21,9 +21,9 @@ import android.graphics.Color import android.graphics.Point import android.graphics.Rect import android.graphics.RectF +import android.util.Log import android.view.View import androidx.annotation.VisibleForTesting -import com.android.systemui.shared.navigationbar.RegionSamplingHelper import java.io.PrintWriter import java.util.concurrent.Executor @@ -31,20 +31,21 @@ import java.util.concurrent.Executor open class RegionSampler @JvmOverloads constructor( - val sampledView: View?, + val sampledView: View, mainExecutor: Executor?, val bgExecutor: Executor?, val regionSamplingEnabled: Boolean, + val isLockscreen: Boolean = false, + val wallpaperManager: WallpaperManager? = WallpaperManager.getInstance(sampledView.context), val updateForegroundColor: UpdateColorCallback, - val wallpaperManager: WallpaperManager? = WallpaperManager.getInstance(sampledView?.context) ) : WallpaperManager.LocalWallpaperColorConsumer { private var regionDarkness = RegionDarkness.DEFAULT private var samplingBounds = Rect() private val tmpScreenLocation = IntArray(2) - @VisibleForTesting var regionSampler: RegionSamplingHelper? = null private var lightForegroundColor = Color.WHITE private var darkForegroundColor = Color.BLACK - private val displaySize = Point() + @VisibleForTesting val displaySize = Point() + private var initialSampling: WallpaperColors? = null /** * Sets the colors to be used for Dark and Light Foreground. @@ -57,6 +58,36 @@ constructor( darkForegroundColor = darkColor } + private val layoutChangedListener = + object : View.OnLayoutChangeListener { + + override fun onLayoutChange( + view: View?, + left: Int, + top: Int, + right: Int, + bottom: Int, + oldLeft: Int, + oldTop: Int, + oldRight: Int, + oldBottom: Int + ) { + + // don't pass in negative bounds when region is in transition state + if (sampledView.locationOnScreen[0] < 0 || sampledView.locationOnScreen[1] < 0) { + return + } + + val currentViewRect = Rect(left, top, right, bottom) + val oldViewRect = Rect(oldLeft, oldTop, oldRight, oldBottom) + + if (currentViewRect != oldViewRect) { + stopRegionSampler() + startRegionSampler() + } + } + } + /** * Determines which foreground color to use based on region darkness. * @@ -84,40 +115,57 @@ constructor( /** Start region sampler */ fun startRegionSampler() { - if (!regionSamplingEnabled || sampledView == null) { + + if (!regionSamplingEnabled) { + if (DEBUG) Log.d(TAG, "startRegionSampler() | RegionSampling flag not enabled") return } - val sampledRegion = calculateSampledRegion(sampledView) - val regions = ArrayList() - val sampledRegionWithOffset = convertBounds(sampledRegion) + sampledView.addOnLayoutChangeListener(layoutChangedListener) + val screenLocationBounds = calculateScreenLocation(sampledView) + if (screenLocationBounds == null) { + if (DEBUG) Log.d(TAG, "startRegionSampler() | passed in null region") + return + } + if (screenLocationBounds.isEmpty) { + if (DEBUG) Log.d(TAG, "startRegionSampler() | passed in empty region") + return + } + + val sampledRegionWithOffset = convertBounds(screenLocationBounds) if ( sampledRegionWithOffset.left < 0.0 || sampledRegionWithOffset.right > 1.0 || sampledRegionWithOffset.top < 0.0 || sampledRegionWithOffset.bottom > 1.0 ) { - android.util.Log.e( - "RegionSampler", - "view out of bounds: $sampledRegion | " + - "screen width: ${displaySize.x}, screen height: ${displaySize.y}", - Exception() - ) + if (DEBUG) + Log.d( + TAG, + "startRegionSampler() | view out of bounds: $screenLocationBounds | " + + "screen width: ${displaySize.x}, screen height: ${displaySize.y}", + Exception() + ) return } + val regions = ArrayList() regions.add(sampledRegionWithOffset) - wallpaperManager?.removeOnColorsChangedListener(this) - wallpaperManager?.addOnColorsChangedListener(this, regions) + wallpaperManager?.addOnColorsChangedListener( + this, + regions, + if (isLockscreen) WallpaperManager.FLAG_LOCK else WallpaperManager.FLAG_SYSTEM + ) - // TODO(b/265969235): conditionally set FLAG_LOCK or FLAG_SYSTEM once HS smartspace - // implemented bgExecutor?.execute( Runnable { - val initialSampling = - wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK) + initialSampling = + wallpaperManager?.getWallpaperColors( + if (isLockscreen) WallpaperManager.FLAG_LOCK + else WallpaperManager.FLAG_SYSTEM + ) onColorsChanged(sampledRegionWithOffset, initialSampling) } ) @@ -126,6 +174,7 @@ constructor( /** Stop region sampler */ fun stopRegionSampler() { wallpaperManager?.removeOnColorsChangedListener(this) + sampledView.removeOnLayoutChangeListener(layoutChangedListener) } /** Dump region sampler */ @@ -138,22 +187,23 @@ constructor( pw.println("passed-in sampledView: $sampledView") pw.println("calculated samplingBounds: $samplingBounds") pw.println( - "sampledView width: ${sampledView?.width}, sampledView height: ${sampledView?.height}" + "sampledView width: ${sampledView.width}, sampledView height: ${sampledView.height}" ) pw.println("screen width: ${displaySize.x}, screen height: ${displaySize.y}") pw.println( - "sampledRegionWithOffset: ${convertBounds(calculateSampledRegion(sampledView!!))}" + "sampledRegionWithOffset: ${convertBounds( + calculateScreenLocation(sampledView) ?: RectF())}" ) - // TODO(b/265969235): mock initialSampling based on if component is on HS or LS wallpaper - // HS Smartspace - wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_SYSTEM) - // LS Smartspace, clock - wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK) pw.println( - "initialSampling for lockscreen: " + - "${wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)}" + "initialSampling for ${if (isLockscreen) "lockscreen" else "homescreen" }" + + ": $initialSampling" ) } - fun calculateSampledRegion(sampledView: View): RectF { + fun calculateScreenLocation(sampledView: View): RectF? { + + if (!sampledView.isLaidOut) return null + val screenLocation = tmpScreenLocation /** * The method getLocationOnScreen is used to obtain the view coordinates relative to its @@ -181,7 +231,8 @@ constructor( */ fun convertBounds(originalBounds: RectF): RectF { - // TODO(b/265969235): GRAB # PAGES + CURRENT WALLPAPER PAGE # FROM LAUNCHER + // TODO(b/265969235): GRAB # PAGES + CURRENT WALLPAPER PAGE # FROM LAUNCHER (--> HS + // Smartspace always on 1st page) // TODO(b/265968912): remove hard-coded value once LS wallpaper supported val wallpaperPageNum = 0 val numScreens = 1 @@ -214,6 +265,11 @@ constructor( ) updateForegroundColor() } + + companion object { + private const val TAG = "RegionSampler" + private const val DEBUG = false + } } typealias UpdateColorCallback = () -> Unit diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index c5b14e3c8722a..a8f2804291053 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -21,13 +21,11 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.res.Resources -import android.graphics.Rect import android.text.format.DateFormat import android.util.TypedValue import android.view.View import android.view.View.OnAttachStateChangeListener import android.view.ViewTreeObserver -import android.widget.FrameLayout import androidx.annotation.VisibleForTesting import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle @@ -55,16 +53,16 @@ import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor -import java.util.Locale -import java.util.TimeZone -import java.util.concurrent.Executor -import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch +import java.util.Locale +import java.util.TimeZone +import java.util.concurrent.Executor +import javax.inject.Inject /** * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by @@ -98,12 +96,7 @@ constructor( value.initialize(resources, dozeAmount, 0f) - if (regionSamplingEnabled) { - clock?.run { - smallClock.view.addOnLayoutChangeListener(mLayoutChangedListener) - largeClock.view.addOnLayoutChangeListener(mLayoutChangedListener) - } - } else { + if (!regionSamplingEnabled) { updateColors() } updateFontSizes() @@ -140,44 +133,10 @@ constructor( private var disposableHandle: DisposableHandle? = null private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING) - private val mLayoutChangedListener = - object : View.OnLayoutChangeListener { - - override fun onLayoutChange( - view: View?, - left: Int, - top: Int, - right: Int, - bottom: Int, - oldLeft: Int, - oldTop: Int, - oldRight: Int, - oldBottom: Int - ) { - view?.removeOnLayoutChangeListener(this) - - val parent = (view?.parent) as FrameLayout - - // don't pass in negative bounds when clocks are in transition state - if (view.locationOnScreen[0] < 0 || view.locationOnScreen[1] < 0) { - return - } - - val currentViewRect = Rect(left, top, right, bottom) - val oldViewRect = Rect(oldLeft, oldTop, oldRight, oldBottom) - - if ( - currentViewRect.width() != oldViewRect.width() || - currentViewRect.height() != oldViewRect.height() - ) { - updateRegionSampler(view) - } - } - } private fun updateColors() { val wallpaperManager = WallpaperManager.getInstance(context) - if (regionSamplingEnabled && !wallpaperManager.lockScreenWallpaperExists()) { + if (regionSamplingEnabled) { regionSampler?.let { regionSampler -> clock?.let { clock -> if (regionSampler.sampledView == clock.smallClock.view) { @@ -212,6 +171,7 @@ constructor( mainExecutor, bgExecutor, regionSamplingEnabled, + isLockscreen = true, ::updateColors ) ?.apply { startRegionSampler() } @@ -220,10 +180,11 @@ constructor( } protected open fun createRegionSampler( - sampledView: View?, + sampledView: View, mainExecutor: Executor?, bgExecutor: Executor?, regionSamplingEnabled: Boolean, + isLockscreen: Boolean, updateColors: () -> Unit ): RegionSampler? { return RegionSampler( @@ -231,8 +192,8 @@ constructor( mainExecutor, bgExecutor, regionSamplingEnabled, - updateColors - ) + isLockscreen, + ) { updateColors() } } var regionSampler: RegionSampler? = null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt index 950dbd9300b32..7cc917f3b0b86 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.lockscreen import android.app.PendingIntent -import android.app.WallpaperManager import android.app.smartspace.SmartspaceConfig import android.app.smartspace.SmartspaceManager import android.app.smartspace.SmartspaceSession @@ -56,7 +55,6 @@ import com.android.systemui.plugins.WeatherData import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.settings.UserTracker import com.android.systemui.shared.regionsampling.RegionSampler -import com.android.systemui.shared.regionsampling.UpdateColorCallback import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DATE_SMARTSPACE_DATA_PLUGIN import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN import com.android.systemui.statusbar.phone.KeyguardBypassController @@ -120,7 +118,7 @@ constructor( private val regionSamplingEnabled = featureFlags.isEnabled(Flags.REGION_SAMPLING) - private var isContentUpdatedOnce = false + private var isRegionSamplersCreated = false private var showNotifications = false private var showSensitiveContentForCurrentUser = false private var showSensitiveContentForManagedUser = false @@ -128,7 +126,6 @@ constructor( // TODO(b/202758428): refactor so that we can test color updates via region samping, similar to // how we test color updates when theme changes (See testThemeChangeUpdatesTextColor). - private val updateFun: UpdateColorCallback = { updateTextColorFromRegionSampler() } // TODO: Move logic into SmartspaceView var stateChangeListener = object : View.OnAttachStateChangeListener { @@ -144,6 +141,9 @@ constructor( override fun onViewDetachedFromWindow(v: View) { smartspaceViews.remove(v as SmartspaceView) + regionSamplers[v]?.stopRegionSampler() + regionSamplers.remove(v as SmartspaceView) + if (smartspaceViews.isEmpty()) { disconnect() } @@ -170,7 +170,7 @@ constructor( val filteredTargets = targets.filter(::filterSmartspaceTarget) plugin?.onTargetsAvailable(filteredTargets) - if (!isContentUpdatedOnce) { + if (!isRegionSamplersCreated) { for (v in smartspaceViews) { if (regionSamplingEnabled) { var regionSampler = RegionSampler( @@ -178,15 +178,14 @@ constructor( uiExecutor, bgExecutor, regionSamplingEnabled, - updateFun - ) + isLockscreen = true, + ) { updateTextColorFromRegionSampler() } initializeTextColors(regionSampler) regionSamplers[v] = regionSampler regionSampler.startRegionSampler() } - updateTextColorFromWallpaper() } - isContentUpdatedOnce = true + isRegionSamplersCreated = true } } @@ -504,18 +503,16 @@ constructor( } private fun updateTextColorFromRegionSampler() { - smartspaceViews.forEach { - val textColor = regionSamplers.get(it)?.currentForegroundColor() + regionSamplers.forEach { (view, region) -> + val textColor = region.currentForegroundColor() if (textColor != null) { - it.setPrimaryTextColor(textColor) + view.setPrimaryTextColor(textColor) } } } private fun updateTextColorFromWallpaper() { - val wallpaperManager = WallpaperManager.getInstance(context) - if (!regionSamplingEnabled || wallpaperManager.lockScreenWallpaperExists() || - regionSamplers.isEmpty()) { + if (!regionSamplingEnabled || regionSamplers.isEmpty()) { val wallpaperTextColor = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor) smartspaceViews.forEach { it.setPrimaryTextColor(wallpaperTextColor) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt index ae1c8cbe2a656..1031621e2e7e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt @@ -1,17 +1,30 @@ 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 @@ -26,25 +39,188 @@ class RegionSamplerTest : SysuiTestCase() { @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 mRegionSampler: RegionSampler - private var updateFun: 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)) - mRegionSampler = - RegionSampler(sampledView, mainExecutor, bgExecutor, true, updateFun, wallpaperManager) + 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 testStartRegionSampler() { - mRegionSampler.startRegionSampler() + 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() { - mRegionSampler.dump(pw) + regionSampler.dump(pw) + homescreenRegionSampler.dump(pw) } } diff --git a/tests/Internal/src/android/app/WallpaperColorsTest.java b/tests/Internal/src/android/app/WallpaperColorsTest.java index 9ffb236d3f59c..70660a0a117e6 100644 --- a/tests/Internal/src/android/app/WallpaperColorsTest.java +++ b/tests/Internal/src/android/app/WallpaperColorsTest.java @@ -48,10 +48,10 @@ public class WallpaperColorsTest { } /** - * Check that white supports dark text and black doesn't + * Check that white surface supports dark text */ @Test - public void colorHintsTest() { + public void whiteSurfaceColorHintsTest() { Bitmap image = Bitmap.createBitmap(30, 30, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(image); @@ -59,28 +59,68 @@ public class WallpaperColorsTest { int hints = WallpaperColors.fromBitmap(image).getColorHints(); boolean supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; boolean supportsDarkTheme = (hints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; - boolean fromBitmap = (hints & WallpaperColors.HINT_FROM_BITMAP) != 0; Assert.assertTrue("White surface should support dark text.", supportsDarkText); Assert.assertFalse("White surface shouldn't support dark theme.", supportsDarkTheme); - Assert.assertTrue("From bitmap should be true if object was created " - + "using WallpaperColors#fromBitmap.", fromBitmap); - - canvas.drawColor(Color.BLACK); - hints = WallpaperColors.fromBitmap(image).getColorHints(); - supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; - supportsDarkTheme = (hints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; - Assert.assertFalse("Black surface shouldn't support dark text.", supportsDarkText); - Assert.assertTrue("Black surface should support dark theme.", supportsDarkTheme); Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.BLACK); - canvas.drawColor(Color.WHITE); canvas.drawRect(0, 0, 8, 8, paint); supportsDarkText = (WallpaperColors.fromBitmap(image) .getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; Assert.assertFalse("Light surface shouldn't support dark text " + "when it contains dark pixels.", supportsDarkText); + } + + /** + * Check that x-small white region supports dark text when max number of dark pixels = 0 + */ + @Test + public void xSmallWhiteSurfaceColorHintsTest() { + Bitmap xsmall_image = Bitmap.createBitmap(1, 5, Bitmap.Config.ARGB_8888); + Canvas xsmall_canvas = new Canvas(xsmall_image); + + xsmall_canvas.drawColor(Color.WHITE); + int hints = WallpaperColors.fromBitmap(xsmall_image).getColorHints(); + boolean supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; + boolean supportsDarkTheme = (hints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; + Assert.assertTrue("X-small white surface should support dark text.", + supportsDarkText); + Assert.assertFalse("X-small white surface shouldn't support dark theme.", + supportsDarkTheme); + } + + /** + * Check that black surface doesn't support dark text + */ + @Test + public void blackSurfaceColorHintsTest() { + Bitmap image = Bitmap.createBitmap(30, 30, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(image); + + canvas.drawColor(Color.BLACK); + int hints = WallpaperColors.fromBitmap(image).getColorHints(); + boolean supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; + boolean supportsDarkTheme = (hints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; + Assert.assertFalse("Black surface shouldn't support dark text.", supportsDarkText); + Assert.assertTrue("Black surface should support dark theme.", supportsDarkTheme); + } + + /** + * Check that bitmap hint properly indicates when object created via WallpaperColors#fromBitmap + * versus WallpaperColors() public constructor + */ + @Test + public void bitmapHintsTest() { + Bitmap image = Bitmap.createBitmap(30, 30, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(image); + + canvas.drawColor(Color.WHITE); + int hints = WallpaperColors.fromBitmap(image).getColorHints(); + + boolean fromBitmap = (hints & WallpaperColors.HINT_FROM_BITMAP) != 0; + Assert.assertTrue("From bitmap should be true if object was created " + + "using WallpaperColors#fromBitmap.", fromBitmap); WallpaperColors colors = new WallpaperColors(Color.valueOf(Color.GREEN), null, null); fromBitmap = (colors.getColorHints() & WallpaperColors.HINT_FROM_BITMAP) != 0;