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;
|
int hints = 0;
|
||||||
double meanLuminance = totalLuminance / pixels.length;
|
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;
|
hints |= HINT_SUPPORTS_DARK_TEXT;
|
||||||
}
|
}
|
||||||
if (meanLuminance < DARK_THEME_MEAN_LUMINANCE) {
|
if (meanLuminance < DARK_THEME_MEAN_LUMINANCE) {
|
||||||
|
|||||||
@@ -1680,14 +1680,14 @@ public class WallpaperManager {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,
|
public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,
|
||||||
List<RectF> regions) throws IllegalArgumentException {
|
List<RectF> regions, int which) throws IllegalArgumentException {
|
||||||
for (RectF region : regions) {
|
for (RectF region : regions) {
|
||||||
if (!LOCAL_COLOR_BOUNDS.contains(region)) {
|
if (!LOCAL_COLOR_BOUNDS.contains(region)) {
|
||||||
throw new IllegalArgumentException("Regions must be within bounds "
|
throw new IllegalArgumentException("Regions must be within bounds "
|
||||||
+ LOCAL_COLOR_BOUNDS);
|
+ LOCAL_COLOR_BOUNDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sGlobals.addOnColorsChangedListener(callback, regions, FLAG_SYSTEM,
|
sGlobals.addOnColorsChangedListener(callback, regions, which,
|
||||||
mContext.getUserId(), mContext.getDisplayId());
|
mContext.getUserId(), mContext.getDisplayId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ import android.graphics.Color
|
|||||||
import android.graphics.Point
|
import android.graphics.Point
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import com.android.systemui.shared.navigationbar.RegionSamplingHelper
|
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
|
|
||||||
@@ -31,20 +31,21 @@ import java.util.concurrent.Executor
|
|||||||
open class RegionSampler
|
open class RegionSampler
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(
|
constructor(
|
||||||
val sampledView: View?,
|
val sampledView: View,
|
||||||
mainExecutor: Executor?,
|
mainExecutor: Executor?,
|
||||||
val bgExecutor: Executor?,
|
val bgExecutor: Executor?,
|
||||||
val regionSamplingEnabled: Boolean,
|
val regionSamplingEnabled: Boolean,
|
||||||
|
val isLockscreen: Boolean = false,
|
||||||
|
val wallpaperManager: WallpaperManager? = WallpaperManager.getInstance(sampledView.context),
|
||||||
val updateForegroundColor: UpdateColorCallback,
|
val updateForegroundColor: UpdateColorCallback,
|
||||||
val wallpaperManager: WallpaperManager? = WallpaperManager.getInstance(sampledView?.context)
|
|
||||||
) : WallpaperManager.LocalWallpaperColorConsumer {
|
) : WallpaperManager.LocalWallpaperColorConsumer {
|
||||||
private var regionDarkness = RegionDarkness.DEFAULT
|
private var regionDarkness = RegionDarkness.DEFAULT
|
||||||
private var samplingBounds = Rect()
|
private var samplingBounds = Rect()
|
||||||
private val tmpScreenLocation = IntArray(2)
|
private val tmpScreenLocation = IntArray(2)
|
||||||
@VisibleForTesting var regionSampler: RegionSamplingHelper? = null
|
|
||||||
private var lightForegroundColor = Color.WHITE
|
private var lightForegroundColor = Color.WHITE
|
||||||
private var darkForegroundColor = Color.BLACK
|
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.
|
* Sets the colors to be used for Dark and Light Foreground.
|
||||||
@@ -57,6 +58,36 @@ constructor(
|
|||||||
darkForegroundColor = darkColor
|
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.
|
* Determines which foreground color to use based on region darkness.
|
||||||
*
|
*
|
||||||
@@ -84,40 +115,57 @@ constructor(
|
|||||||
|
|
||||||
/** Start region sampler */
|
/** Start region sampler */
|
||||||
fun startRegionSampler() {
|
fun startRegionSampler() {
|
||||||
if (!regionSamplingEnabled || sampledView == null) {
|
|
||||||
|
if (!regionSamplingEnabled) {
|
||||||
|
if (DEBUG) Log.d(TAG, "startRegionSampler() | RegionSampling flag not enabled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val sampledRegion = calculateSampledRegion(sampledView)
|
sampledView.addOnLayoutChangeListener(layoutChangedListener)
|
||||||
val regions = ArrayList<RectF>()
|
|
||||||
val sampledRegionWithOffset = convertBounds(sampledRegion)
|
|
||||||
|
|
||||||
|
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 (
|
if (
|
||||||
sampledRegionWithOffset.left < 0.0 ||
|
sampledRegionWithOffset.left < 0.0 ||
|
||||||
sampledRegionWithOffset.right > 1.0 ||
|
sampledRegionWithOffset.right > 1.0 ||
|
||||||
sampledRegionWithOffset.top < 0.0 ||
|
sampledRegionWithOffset.top < 0.0 ||
|
||||||
sampledRegionWithOffset.bottom > 1.0
|
sampledRegionWithOffset.bottom > 1.0
|
||||||
) {
|
) {
|
||||||
android.util.Log.e(
|
if (DEBUG)
|
||||||
"RegionSampler",
|
Log.d(
|
||||||
"view out of bounds: $sampledRegion | " +
|
TAG,
|
||||||
|
"startRegionSampler() | view out of bounds: $screenLocationBounds | " +
|
||||||
"screen width: ${displaySize.x}, screen height: ${displaySize.y}",
|
"screen width: ${displaySize.x}, screen height: ${displaySize.y}",
|
||||||
Exception()
|
Exception()
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val regions = ArrayList<RectF>()
|
||||||
regions.add(sampledRegionWithOffset)
|
regions.add(sampledRegionWithOffset)
|
||||||
|
|
||||||
wallpaperManager?.removeOnColorsChangedListener(this)
|
wallpaperManager?.addOnColorsChangedListener(
|
||||||
wallpaperManager?.addOnColorsChangedListener(this, regions)
|
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(
|
bgExecutor?.execute(
|
||||||
Runnable {
|
Runnable {
|
||||||
val initialSampling =
|
initialSampling =
|
||||||
wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)
|
wallpaperManager?.getWallpaperColors(
|
||||||
|
if (isLockscreen) WallpaperManager.FLAG_LOCK
|
||||||
|
else WallpaperManager.FLAG_SYSTEM
|
||||||
|
)
|
||||||
onColorsChanged(sampledRegionWithOffset, initialSampling)
|
onColorsChanged(sampledRegionWithOffset, initialSampling)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -126,6 +174,7 @@ constructor(
|
|||||||
/** Stop region sampler */
|
/** Stop region sampler */
|
||||||
fun stopRegionSampler() {
|
fun stopRegionSampler() {
|
||||||
wallpaperManager?.removeOnColorsChangedListener(this)
|
wallpaperManager?.removeOnColorsChangedListener(this)
|
||||||
|
sampledView.removeOnLayoutChangeListener(layoutChangedListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Dump region sampler */
|
/** Dump region sampler */
|
||||||
@@ -138,22 +187,23 @@ constructor(
|
|||||||
pw.println("passed-in sampledView: $sampledView")
|
pw.println("passed-in sampledView: $sampledView")
|
||||||
pw.println("calculated samplingBounds: $samplingBounds")
|
pw.println("calculated samplingBounds: $samplingBounds")
|
||||||
pw.println(
|
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("screen width: ${displaySize.x}, screen height: ${displaySize.y}")
|
||||||
pw.println(
|
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(
|
pw.println(
|
||||||
"initialSampling for lockscreen: " +
|
"initialSampling for ${if (isLockscreen) "lockscreen" else "homescreen" }" +
|
||||||
"${wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)}"
|
": $initialSampling"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateSampledRegion(sampledView: View): RectF {
|
fun calculateScreenLocation(sampledView: View): RectF? {
|
||||||
|
|
||||||
|
if (!sampledView.isLaidOut) return null
|
||||||
|
|
||||||
val screenLocation = tmpScreenLocation
|
val screenLocation = tmpScreenLocation
|
||||||
/**
|
/**
|
||||||
* The method getLocationOnScreen is used to obtain the view coordinates relative to its
|
* The method getLocationOnScreen is used to obtain the view coordinates relative to its
|
||||||
@@ -181,7 +231,8 @@ constructor(
|
|||||||
*/
|
*/
|
||||||
fun convertBounds(originalBounds: RectF): RectF {
|
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
|
// TODO(b/265968912): remove hard-coded value once LS wallpaper supported
|
||||||
val wallpaperPageNum = 0
|
val wallpaperPageNum = 0
|
||||||
val numScreens = 1
|
val numScreens = 1
|
||||||
@@ -214,6 +265,11 @@ constructor(
|
|||||||
)
|
)
|
||||||
updateForegroundColor()
|
updateForegroundColor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "RegionSampler"
|
||||||
|
private const val DEBUG = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias UpdateColorCallback = () -> Unit
|
typealias UpdateColorCallback = () -> Unit
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Rect
|
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.OnAttachStateChangeListener
|
import android.view.View.OnAttachStateChangeListener
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import android.widget.FrameLayout
|
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
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.BatteryController.BatteryStateChangeCallback
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
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.CoroutineScope
|
||||||
import kotlinx.coroutines.DisposableHandle
|
import kotlinx.coroutines.DisposableHandle
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.launch
|
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
|
* 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)
|
value.initialize(resources, dozeAmount, 0f)
|
||||||
|
|
||||||
if (regionSamplingEnabled) {
|
if (!regionSamplingEnabled) {
|
||||||
clock?.run {
|
|
||||||
smallClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
|
|
||||||
largeClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updateColors()
|
updateColors()
|
||||||
}
|
}
|
||||||
updateFontSizes()
|
updateFontSizes()
|
||||||
@@ -140,44 +133,10 @@ constructor(
|
|||||||
private var disposableHandle: DisposableHandle? = null
|
private var disposableHandle: DisposableHandle? = null
|
||||||
private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING)
|
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() {
|
private fun updateColors() {
|
||||||
val wallpaperManager = WallpaperManager.getInstance(context)
|
val wallpaperManager = WallpaperManager.getInstance(context)
|
||||||
if (regionSamplingEnabled && !wallpaperManager.lockScreenWallpaperExists()) {
|
if (regionSamplingEnabled) {
|
||||||
regionSampler?.let { regionSampler ->
|
regionSampler?.let { regionSampler ->
|
||||||
clock?.let { clock ->
|
clock?.let { clock ->
|
||||||
if (regionSampler.sampledView == clock.smallClock.view) {
|
if (regionSampler.sampledView == clock.smallClock.view) {
|
||||||
@@ -212,6 +171,7 @@ constructor(
|
|||||||
mainExecutor,
|
mainExecutor,
|
||||||
bgExecutor,
|
bgExecutor,
|
||||||
regionSamplingEnabled,
|
regionSamplingEnabled,
|
||||||
|
isLockscreen = true,
|
||||||
::updateColors
|
::updateColors
|
||||||
)
|
)
|
||||||
?.apply { startRegionSampler() }
|
?.apply { startRegionSampler() }
|
||||||
@@ -220,10 +180,11 @@ constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun createRegionSampler(
|
protected open fun createRegionSampler(
|
||||||
sampledView: View?,
|
sampledView: View,
|
||||||
mainExecutor: Executor?,
|
mainExecutor: Executor?,
|
||||||
bgExecutor: Executor?,
|
bgExecutor: Executor?,
|
||||||
regionSamplingEnabled: Boolean,
|
regionSamplingEnabled: Boolean,
|
||||||
|
isLockscreen: Boolean,
|
||||||
updateColors: () -> Unit
|
updateColors: () -> Unit
|
||||||
): RegionSampler? {
|
): RegionSampler? {
|
||||||
return RegionSampler(
|
return RegionSampler(
|
||||||
@@ -231,8 +192,8 @@ constructor(
|
|||||||
mainExecutor,
|
mainExecutor,
|
||||||
bgExecutor,
|
bgExecutor,
|
||||||
regionSamplingEnabled,
|
regionSamplingEnabled,
|
||||||
updateColors
|
isLockscreen,
|
||||||
)
|
) { updateColors() }
|
||||||
}
|
}
|
||||||
|
|
||||||
var regionSampler: RegionSampler? = null
|
var regionSampler: RegionSampler? = null
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.systemui.statusbar.lockscreen
|
package com.android.systemui.statusbar.lockscreen
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.app.WallpaperManager
|
|
||||||
import android.app.smartspace.SmartspaceConfig
|
import android.app.smartspace.SmartspaceConfig
|
||||||
import android.app.smartspace.SmartspaceManager
|
import android.app.smartspace.SmartspaceManager
|
||||||
import android.app.smartspace.SmartspaceSession
|
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.plugins.statusbar.StatusBarStateController
|
||||||
import com.android.systemui.settings.UserTracker
|
import com.android.systemui.settings.UserTracker
|
||||||
import com.android.systemui.shared.regionsampling.RegionSampler
|
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.DATE_SMARTSPACE_DATA_PLUGIN
|
||||||
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
|
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||||
@@ -120,7 +118,7 @@ constructor(
|
|||||||
|
|
||||||
private val regionSamplingEnabled =
|
private val regionSamplingEnabled =
|
||||||
featureFlags.isEnabled(Flags.REGION_SAMPLING)
|
featureFlags.isEnabled(Flags.REGION_SAMPLING)
|
||||||
private var isContentUpdatedOnce = false
|
private var isRegionSamplersCreated = false
|
||||||
private var showNotifications = false
|
private var showNotifications = false
|
||||||
private var showSensitiveContentForCurrentUser = false
|
private var showSensitiveContentForCurrentUser = false
|
||||||
private var showSensitiveContentForManagedUser = 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
|
// 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).
|
// how we test color updates when theme changes (See testThemeChangeUpdatesTextColor).
|
||||||
private val updateFun: UpdateColorCallback = { updateTextColorFromRegionSampler() }
|
|
||||||
|
|
||||||
// TODO: Move logic into SmartspaceView
|
// TODO: Move logic into SmartspaceView
|
||||||
var stateChangeListener = object : View.OnAttachStateChangeListener {
|
var stateChangeListener = object : View.OnAttachStateChangeListener {
|
||||||
@@ -144,6 +141,9 @@ constructor(
|
|||||||
override fun onViewDetachedFromWindow(v: View) {
|
override fun onViewDetachedFromWindow(v: View) {
|
||||||
smartspaceViews.remove(v as SmartspaceView)
|
smartspaceViews.remove(v as SmartspaceView)
|
||||||
|
|
||||||
|
regionSamplers[v]?.stopRegionSampler()
|
||||||
|
regionSamplers.remove(v as SmartspaceView)
|
||||||
|
|
||||||
if (smartspaceViews.isEmpty()) {
|
if (smartspaceViews.isEmpty()) {
|
||||||
disconnect()
|
disconnect()
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ constructor(
|
|||||||
|
|
||||||
val filteredTargets = targets.filter(::filterSmartspaceTarget)
|
val filteredTargets = targets.filter(::filterSmartspaceTarget)
|
||||||
plugin?.onTargetsAvailable(filteredTargets)
|
plugin?.onTargetsAvailable(filteredTargets)
|
||||||
if (!isContentUpdatedOnce) {
|
if (!isRegionSamplersCreated) {
|
||||||
for (v in smartspaceViews) {
|
for (v in smartspaceViews) {
|
||||||
if (regionSamplingEnabled) {
|
if (regionSamplingEnabled) {
|
||||||
var regionSampler = RegionSampler(
|
var regionSampler = RegionSampler(
|
||||||
@@ -178,15 +178,14 @@ constructor(
|
|||||||
uiExecutor,
|
uiExecutor,
|
||||||
bgExecutor,
|
bgExecutor,
|
||||||
regionSamplingEnabled,
|
regionSamplingEnabled,
|
||||||
updateFun
|
isLockscreen = true,
|
||||||
)
|
) { updateTextColorFromRegionSampler() }
|
||||||
initializeTextColors(regionSampler)
|
initializeTextColors(regionSampler)
|
||||||
regionSamplers[v] = regionSampler
|
regionSamplers[v] = regionSampler
|
||||||
regionSampler.startRegionSampler()
|
regionSampler.startRegionSampler()
|
||||||
}
|
}
|
||||||
updateTextColorFromWallpaper()
|
|
||||||
}
|
}
|
||||||
isContentUpdatedOnce = true
|
isRegionSamplersCreated = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,18 +503,16 @@ constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTextColorFromRegionSampler() {
|
private fun updateTextColorFromRegionSampler() {
|
||||||
smartspaceViews.forEach {
|
regionSamplers.forEach { (view, region) ->
|
||||||
val textColor = regionSamplers.get(it)?.currentForegroundColor()
|
val textColor = region.currentForegroundColor()
|
||||||
if (textColor != null) {
|
if (textColor != null) {
|
||||||
it.setPrimaryTextColor(textColor)
|
view.setPrimaryTextColor(textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTextColorFromWallpaper() {
|
private fun updateTextColorFromWallpaper() {
|
||||||
val wallpaperManager = WallpaperManager.getInstance(context)
|
if (!regionSamplingEnabled || regionSamplers.isEmpty()) {
|
||||||
if (!regionSamplingEnabled || wallpaperManager.lockScreenWallpaperExists() ||
|
|
||||||
regionSamplers.isEmpty()) {
|
|
||||||
val wallpaperTextColor =
|
val wallpaperTextColor =
|
||||||
Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor)
|
Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor)
|
||||||
smartspaceViews.forEach { it.setPrimaryTextColor(wallpaperTextColor) }
|
smartspaceViews.forEach { it.setPrimaryTextColor(wallpaperTextColor) }
|
||||||
|
|||||||
@@ -1,17 +1,30 @@
|
|||||||
package com.android.systemui.shared.regionsampling
|
package com.android.systemui.shared.regionsampling
|
||||||
|
|
||||||
|
import android.app.WallpaperColors
|
||||||
import android.app.WallpaperManager
|
import android.app.WallpaperManager
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.RectF
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.SysuiTestCase
|
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.io.PrintWriter
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
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.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.Mockito.`when` as whenever
|
||||||
import org.mockito.junit.MockitoJUnit
|
import org.mockito.junit.MockitoJUnit
|
||||||
|
|
||||||
@@ -26,25 +39,188 @@ class RegionSamplerTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var bgExecutor: Executor
|
@Mock private lateinit var bgExecutor: Executor
|
||||||
@Mock private lateinit var pw: PrintWriter
|
@Mock private lateinit var pw: PrintWriter
|
||||||
@Mock private lateinit var wallpaperManager: WallpaperManager
|
@Mock private lateinit var wallpaperManager: WallpaperManager
|
||||||
|
@Mock private lateinit var updateForegroundColor: UpdateColorCallback
|
||||||
|
|
||||||
private lateinit var mRegionSampler: RegionSampler
|
private lateinit var regionSampler: RegionSampler // lockscreen
|
||||||
private var updateFun: UpdateColorCallback = {}
|
private lateinit var homescreenRegionSampler: RegionSampler
|
||||||
|
|
||||||
|
@Captor
|
||||||
|
private lateinit var colorsChangedListener:
|
||||||
|
ArgumentCaptor<WallpaperManager.LocalWallpaperColorConsumer>
|
||||||
|
|
||||||
|
@Captor private lateinit var layoutChangedListener: ArgumentCaptor<View.OnLayoutChangeListener>
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
whenever(sampledView.isAttachedToWindow).thenReturn(true)
|
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 =
|
||||||
RegionSampler(sampledView, mainExecutor, bgExecutor, true, updateFun, wallpaperManager)
|
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
|
@Test
|
||||||
fun testStartRegionSampler() {
|
fun testCalculatedBounds_inRange() {
|
||||||
mRegionSampler.startRegionSampler()
|
// 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
|
@Test
|
||||||
fun testDump() {
|
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
|
@Test
|
||||||
public void colorHintsTest() {
|
public void whiteSurfaceColorHintsTest() {
|
||||||
Bitmap image = Bitmap.createBitmap(30, 30, Bitmap.Config.ARGB_8888);
|
Bitmap image = Bitmap.createBitmap(30, 30, Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(image);
|
Canvas canvas = new Canvas(image);
|
||||||
|
|
||||||
@@ -59,28 +59,68 @@ public class WallpaperColorsTest {
|
|||||||
int hints = WallpaperColors.fromBitmap(image).getColorHints();
|
int hints = WallpaperColors.fromBitmap(image).getColorHints();
|
||||||
boolean supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0;
|
boolean supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0;
|
||||||
boolean supportsDarkTheme = (hints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 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.assertTrue("White surface should support dark text.", supportsDarkText);
|
||||||
Assert.assertFalse("White surface shouldn't support dark theme.", supportsDarkTheme);
|
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 paint = new Paint();
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Paint.Style.FILL);
|
||||||
paint.setColor(Color.BLACK);
|
paint.setColor(Color.BLACK);
|
||||||
canvas.drawColor(Color.WHITE);
|
|
||||||
canvas.drawRect(0, 0, 8, 8, paint);
|
canvas.drawRect(0, 0, 8, 8, paint);
|
||||||
supportsDarkText = (WallpaperColors.fromBitmap(image)
|
supportsDarkText = (WallpaperColors.fromBitmap(image)
|
||||||
.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0;
|
.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0;
|
||||||
Assert.assertFalse("Light surface shouldn't support dark text "
|
Assert.assertFalse("Light surface shouldn't support dark text "
|
||||||
+ "when it contains dark pixels.", supportsDarkText);
|
+ "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);
|
WallpaperColors colors = new WallpaperColors(Color.valueOf(Color.GREEN), null, null);
|
||||||
fromBitmap = (colors.getColorHints() & WallpaperColors.HINT_FROM_BITMAP) != 0;
|
fromBitmap = (colors.getColorHints() & WallpaperColors.HINT_FROM_BITMAP) != 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user