summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt69
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt47
2 files changed, 95 insertions, 21 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 4e0e8d0dbcd7..4a6e53d304f4 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -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() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 231898884adf..b67f2805f2bb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -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
}