LS Wallpaper Sampling for Clock

Refactoring RegionSampler implementations (LS clock) to
properly sample from lockscreen wallpaper since it is no longer an image
view.

This also addresses previously known inconsistent behavior when determining color for small clock versus large clock. The small clock only changes visibility while the large clock's view is fully removed and added when active. Because of this, the small clock doesn't trigger our layout change listener like the large clock does, which causes it to not get re-sampled right away. To address this, there is now a special case handling to re-sample when the visibility of the small clock changes.

Flag: region_sampling
Bug: 265968912
Test: manual, atest RegionSamplerTest
Change-Id: I563b32ccfe2e25a2753779bb955171c714c84207
This commit is contained in:
Florence Yang
2023-05-17 01:16:27 +00:00
parent 3259563d30
commit 5f650d4dd0
4 changed files with 70 additions and 40 deletions

View File

@@ -263,6 +263,8 @@ constructor(
(colors?.colorHints?.and(WallpaperColors.HINT_SUPPORTS_DARK_TEXT)) !=
WallpaperColors.HINT_SUPPORTS_DARK_TEXT
)
if (DEBUG)
Log.d(TAG, "onColorsChanged() | region darkness = $regionDarkness for region $area")
updateForegroundColor()
}

View File

@@ -15,18 +15,18 @@
*/
package com.android.keyguard
import android.app.WallpaperManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Resources
import android.text.format.DateFormat
import android.util.TypedValue
import android.util.Log
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
@@ -99,6 +99,28 @@ constructor(
if (!regionSamplingEnabled) {
updateColors()
} else {
clock?.let {
smallRegionSampler = createRegionSampler(
it.smallClock.view,
mainExecutor,
bgExecutor,
regionSamplingEnabled,
isLockscreen = true,
::updateColors
)?.apply { startRegionSampler() }
largeRegionSampler = createRegionSampler(
it.largeClock.view,
mainExecutor,
bgExecutor,
regionSamplingEnabled,
isLockscreen = true,
::updateColors
)?.apply { startRegionSampler() }
updateColors()
}
}
updateFontSizes()
updateTimeListeners()
@@ -110,8 +132,25 @@ constructor(
}
value.smallClock.view.addOnAttachStateChangeListener(
object : OnAttachStateChangeListener {
override fun onViewAttachedToWindow(p0: View?) {
var pastVisibility: Int? = null
override fun onViewAttachedToWindow(view: View?) {
value.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
if (view != null) {
val smallClockFrame = view.parent as FrameLayout
pastVisibility = smallClockFrame.visibility
smallClockFrame.viewTreeObserver.addOnGlobalLayoutListener(
ViewTreeObserver.OnGlobalLayoutListener {
val currentVisibility = smallClockFrame.visibility
if (pastVisibility != currentVisibility) {
pastVisibility = currentVisibility
// when small clock visible, recalculate bounds and sample
if (currentVisibility == View.VISIBLE) {
smallRegionSampler?.stopRegionSampler()
smallRegionSampler?.startRegionSampler()
}
}
})
}
}
override fun onViewDetachedFromWindow(p0: View?) {
@@ -141,21 +180,19 @@ constructor(
private fun updateColors() {
val wallpaperManager = WallpaperManager.getInstance(context)
if (regionSamplingEnabled) {
regionSampler?.let { regionSampler ->
clock?.let { clock ->
if (regionSampler.sampledView == clock.smallClock.view) {
smallClockIsDark = regionSampler.currentRegionDarkness().isDark
clock.smallClock.events.onRegionDarknessChanged(smallClockIsDark)
return@updateColors
} else if (regionSampler.sampledView == clock.largeClock.view) {
largeClockIsDark = regionSampler.currentRegionDarkness().isDark
clock.largeClock.events.onRegionDarknessChanged(largeClockIsDark)
return@updateColors
}
clock?.let { clock ->
smallRegionSampler?.let {
smallClockIsDark = it.currentRegionDarkness().isDark
clock.smallClock.events.onRegionDarknessChanged(smallClockIsDark)
}
largeRegionSampler?.let {
largeClockIsDark = it.currentRegionDarkness().isDark
clock.largeClock.events.onRegionDarknessChanged(largeClockIsDark)
}
}
return
}
val isLightTheme = TypedValue()
@@ -168,23 +205,6 @@ constructor(
largeClock.events.onRegionDarknessChanged(largeClockIsDark)
}
}
private fun updateRegionSampler(sampledRegion: View) {
regionSampler?.stopRegionSampler()
regionSampler =
createRegionSampler(
sampledRegion,
mainExecutor,
bgExecutor,
regionSamplingEnabled,
isLockscreen = true,
::updateColors
)
?.apply { startRegionSampler() }
updateColors()
}
protected open fun createRegionSampler(
sampledView: View,
mainExecutor: Executor?,
@@ -202,7 +222,10 @@ constructor(
) { updateColors() }
}
var regionSampler: RegionSampler? = null
var smallRegionSampler: RegionSampler? = null
private set
var largeRegionSampler: RegionSampler? = null
private set
var smallTimeListener: TimeListener? = null
var largeTimeListener: TimeListener? = null
val shouldTimeListenerRun: Boolean
@@ -319,7 +342,8 @@ constructor(
configurationController.removeCallback(configListener)
batteryController.removeCallback(batteryCallback)
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
regionSampler?.stopRegionSampler()
smallRegionSampler?.stopRegionSampler()
largeRegionSampler?.stopRegionSampler()
smallTimeListener?.stop()
largeTimeListener?.stop()
}

View File

@@ -531,9 +531,13 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
if (clock != null) {
clock.dump(pw);
}
final RegionSampler regionSampler = mClockEventController.getRegionSampler();
if (regionSampler != null) {
regionSampler.dump(pw);
final RegionSampler smallRegionSampler = mClockEventController.getSmallRegionSampler();
if (smallRegionSampler != null) {
smallRegionSampler.dump(pw);
}
final RegionSampler largeRegionSampler = mClockEventController.getLargeRegionSampler();
if (largeRegionSampler != null) {
largeRegionSampler.dump(pw);
}
}

View File

@@ -53,6 +53,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
@@ -155,9 +156,8 @@ class ClockEventControllerTest : SysuiTestCase() {
@Test
fun themeChanged_verifyClockPaletteUpdated() = runBlocking(IMMEDIATE) {
// TODO(b/266103601): delete this test and add more coverage for updateColors()
// verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
// verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
verify(configurationController).addCallback(capture(captor))