Merge "LS Wallpaper Sampling for LS Smartspace" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
77c206e386
@@ -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) {
|
||||
|
||||
@@ -1680,14 +1680,14 @@ public class WallpaperManager {
|
||||
* @hide
|
||||
*/
|
||||
public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,
|
||||
List<RectF> regions) throws IllegalArgumentException {
|
||||
List<RectF> 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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<RectF>()
|
||||
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<RectF>()
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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<WallpaperManager.LocalWallpaperColorConsumer>
|
||||
|
||||
@Captor private lateinit var layoutChangedListener: ArgumentCaptor<View.OnLayoutChangeListener>
|
||||
|
||||
@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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user