diff options
| -rw-r--r-- | packages/SystemUI/src/com/android/keyguard/ClockEventController.kt | 69 | ||||
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt | 47 |
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 } |