Merge "Fix OOM of metro clock" into udc-qpr-dev

This commit is contained in:
Treehugger Robot
2023-07-07 18:49:56 +00:00
committed by Android (Google) Code Review
2 changed files with 95 additions and 21 deletions

View File

@@ -26,6 +26,7 @@ import android.util.TypedValue
import android.view.View
import android.view.View.OnAttachStateChangeListener
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.widget.FrameLayout
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.Lifecycle
@@ -88,6 +89,15 @@ constructor(
) {
var clock: ClockController? = null
set(value) {
smallClockOnAttachStateChangeListener?.let {
field?.smallClock?.view?.removeOnAttachStateChangeListener(it)
smallClockFrame?.viewTreeObserver
?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
largeClockOnAttachStateChangeListener?.let {
field?.largeClock?.view?.removeOnAttachStateChangeListener(it)
}
field = value
if (value != null) {
smallLogBuffer?.log(TAG, DEBUG, {}, { "New Clock" })
@@ -130,44 +140,62 @@ constructor(
}
value.events.onWeatherDataChanged(it)
}
value.smallClock.view.addOnAttachStateChangeListener(
smallClockOnAttachStateChangeListener =
object : OnAttachStateChangeListener {
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()
smallClockFrame = view.parent as FrameLayout
smallClockFrame?.let {frame ->
pastVisibility = frame.visibility
onGlobalLayoutListener = OnGlobalLayoutListener {
val currentVisibility = frame.visibility
if (pastVisibility != currentVisibility) {
pastVisibility = currentVisibility
// when small clock visible,
// recalculate bounds and sample
if (currentVisibility == View.VISIBLE) {
smallRegionSampler?.stopRegionSampler()
smallRegionSampler?.startRegionSampler()
}
}
}
})
frame.viewTreeObserver
.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
}
}
override fun onViewDetachedFromWindow(p0: View?) {
smallClockFrame?.viewTreeObserver
?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
})
value.largeClock.view.addOnAttachStateChangeListener(
}
value.smallClock.view
.addOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
largeClockOnAttachStateChangeListener =
object : OnAttachStateChangeListener {
override fun onViewAttachedToWindow(p0: View?) {
value.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
}
override fun onViewDetachedFromWindow(p0: View?) {
}
})
}
value.largeClock.view
.addOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
}
}
@VisibleForTesting
var smallClockOnAttachStateChangeListener: OnAttachStateChangeListener? = null
@VisibleForTesting
var largeClockOnAttachStateChangeListener: OnAttachStateChangeListener? = null
private var smallClockFrame: FrameLayout? = null
private var onGlobalLayoutListener: OnGlobalLayoutListener? = null
private var isDozing = false
private set
@@ -307,7 +335,6 @@ constructor(
return
}
isRegistered = true
broadcastDispatcher.registerReceiver(
localeBroadcastReceiver,
IntentFilter(Intent.ACTION_LOCALE_CHANGED)
@@ -346,6 +373,12 @@ constructor(
largeRegionSampler?.stopRegionSampler()
smallTimeListener?.stop()
largeTimeListener?.stop()
clock?.smallClock?.view
?.removeOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
smallClockFrame?.viewTreeObserver
?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
clock?.largeClock?.view
?.removeOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
}
private fun updateTimeListeners() {

View File

@@ -18,7 +18,8 @@ package com.android.keyguard
import android.content.BroadcastReceiver
import android.testing.AndroidTestingRunner
import android.view.View
import android.widget.TextView
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
@@ -83,7 +84,13 @@ class ClockEventControllerTest : SysuiTestCase() {
@Mock private lateinit var bgExecutor: Executor
@Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var smallClockController: ClockFaceController
@Mock private lateinit var smallClockView: View
@Mock private lateinit var smallClockViewTreeObserver: ViewTreeObserver
@Mock private lateinit var smallClockFrame: FrameLayout
@Mock private lateinit var smallClockFrameViewTreeObserver: ViewTreeObserver
@Mock private lateinit var largeClockController: ClockFaceController
@Mock private lateinit var largeClockView: View
@Mock private lateinit var largeClockViewTreeObserver: ViewTreeObserver
@Mock private lateinit var smallClockEvents: ClockFaceEvents
@Mock private lateinit var largeClockEvents: ClockFaceEvents
@Mock private lateinit var parentView: View
@@ -99,8 +106,12 @@ class ClockEventControllerTest : SysuiTestCase() {
fun setUp() {
whenever(clock.smallClock).thenReturn(smallClockController)
whenever(clock.largeClock).thenReturn(largeClockController)
whenever(smallClockController.view).thenReturn(TextView(context))
whenever(largeClockController.view).thenReturn(TextView(context))
whenever(smallClockController.view).thenReturn(smallClockView)
whenever(smallClockView.parent).thenReturn(smallClockFrame)
whenever(smallClockView.viewTreeObserver).thenReturn(smallClockViewTreeObserver)
whenever(smallClockFrame.viewTreeObserver).thenReturn(smallClockFrameViewTreeObserver)
whenever(largeClockController.view).thenReturn(largeClockView)
whenever(largeClockView.viewTreeObserver).thenReturn(largeClockViewTreeObserver)
whenever(smallClockController.events).thenReturn(smallClockEvents)
whenever(largeClockController.events).thenReturn(largeClockEvents)
whenever(clock.events).thenReturn(events)
@@ -302,8 +313,38 @@ class ClockEventControllerTest : SysuiTestCase() {
verify(configurationController).removeCallback(any())
verify(batteryController).removeCallback(any())
verify(keyguardUpdateMonitor).removeCallback(any())
verify(smallClockController.view)
.removeOnAttachStateChangeListener(underTest.smallClockOnAttachStateChangeListener)
verify(largeClockController.view)
.removeOnAttachStateChangeListener(underTest.largeClockOnAttachStateChangeListener)
}
@Test
fun registerOnAttachStateChangeListener_validate() = runBlocking(IMMEDIATE) {
verify(smallClockController.view)
.addOnAttachStateChangeListener(underTest.smallClockOnAttachStateChangeListener)
verify(largeClockController.view)
.addOnAttachStateChangeListener(underTest.largeClockOnAttachStateChangeListener)
}
@Test
fun registerAndRemoveOnGlobalLayoutListener_correctly() = runBlocking(IMMEDIATE) {
underTest.smallClockOnAttachStateChangeListener!!.onViewAttachedToWindow(smallClockView)
verify(smallClockFrame.viewTreeObserver).addOnGlobalLayoutListener(any())
underTest.smallClockOnAttachStateChangeListener!!.onViewDetachedFromWindow(smallClockView)
verify(smallClockFrame.viewTreeObserver).removeOnGlobalLayoutListener(any())
}
@Test
fun registerOnGlobalLayoutListener_RemoveOnAttachStateChangeListener_correctly() =
runBlocking(IMMEDIATE) {
underTest.smallClockOnAttachStateChangeListener!!
.onViewAttachedToWindow(smallClockView)
verify(smallClockFrame.viewTreeObserver).addOnGlobalLayoutListener(any())
underTest.unregisterListeners()
verify(smallClockFrame.viewTreeObserver).removeOnGlobalLayoutListener(any())
}
companion object {
private val IMMEDIATE = Dispatchers.Main.immediate
}