Rewire dozing for clock events
Continuing exploration of moving all doze events to flowables, including both isDozing and the dozeAmount animations. At the moment, the source of these events still comes from StatusBarStateController, which informs the KeyguardRepository. Next up is to create a parallel way to drive these animations that is solely based on repository information. Bug: 242853098 Test: atest ClockEventControllerTest KeyguardClockSwitchControllerTest Change-Id: I8c40076ad7e716093f602e5bbf5d9f03871ac679
This commit is contained in:
@@ -23,12 +23,17 @@ import android.content.res.Resources
|
||||
import android.text.format.DateFormat
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.plugins.ClockController
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.flags.Flags.REGION_SAMPLING
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
||||
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.shared.regionsampling.RegionSamplingInstance
|
||||
import com.android.systemui.statusbar.policy.BatteryController
|
||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
|
||||
@@ -38,13 +43,19 @@ import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.DisposableHandle
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
|
||||
* [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
|
||||
*/
|
||||
open class ClockEventController @Inject constructor(
|
||||
private val statusBarStateController: StatusBarStateController,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val broadcastDispatcher: BroadcastDispatcher,
|
||||
private val batteryController: BatteryController,
|
||||
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||
@@ -53,7 +64,7 @@ open class ClockEventController @Inject constructor(
|
||||
private val context: Context,
|
||||
@Main private val mainExecutor: Executor,
|
||||
@Background private val bgExecutor: Executor,
|
||||
private val featureFlags: FeatureFlags,
|
||||
private val featureFlags: FeatureFlags
|
||||
) {
|
||||
var clock: ClockController? = null
|
||||
set(value) {
|
||||
@@ -70,9 +81,9 @@ open class ClockEventController @Inject constructor(
|
||||
private var isCharging = false
|
||||
private var dozeAmount = 0f
|
||||
private var isKeyguardVisible = false
|
||||
|
||||
private val regionSamplingEnabled =
|
||||
featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING)
|
||||
private var isRegistered = false
|
||||
private var disposableHandle: DisposableHandle? = null
|
||||
private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING)
|
||||
|
||||
private fun updateColors() {
|
||||
if (regionSamplingEnabled && smallRegionSampler != null && largeRegionSampler != null) {
|
||||
@@ -165,15 +176,6 @@ open class ClockEventController @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val statusBarStateListener = object : StatusBarStateController.StateListener {
|
||||
override fun onDozeAmountChanged(linear: Float, eased: Float) {
|
||||
clock?.animations?.doze(linear)
|
||||
|
||||
isDozing = linear > dozeAmount
|
||||
dozeAmount = linear
|
||||
}
|
||||
}
|
||||
|
||||
private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
|
||||
override fun onKeyguardVisibilityChanged(visible: Boolean) {
|
||||
isKeyguardVisible = visible
|
||||
@@ -195,13 +197,11 @@ open class ClockEventController @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
isDozing = statusBarStateController.isDozing
|
||||
}
|
||||
|
||||
fun registerListeners() {
|
||||
dozeAmount = statusBarStateController.dozeAmount
|
||||
isDozing = statusBarStateController.isDozing || dozeAmount != 0f
|
||||
fun registerListeners(parent: View) {
|
||||
if (isRegistered) {
|
||||
return
|
||||
}
|
||||
isRegistered = true
|
||||
|
||||
broadcastDispatcher.registerReceiver(
|
||||
localeBroadcastReceiver,
|
||||
@@ -210,17 +210,27 @@ open class ClockEventController @Inject constructor(
|
||||
configurationController.addCallback(configListener)
|
||||
batteryController.addCallback(batteryCallback)
|
||||
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
|
||||
statusBarStateController.addCallback(statusBarStateListener)
|
||||
smallRegionSampler?.startRegionSampler()
|
||||
largeRegionSampler?.startRegionSampler()
|
||||
disposableHandle = parent.repeatWhenAttached {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
listenForDozing(this)
|
||||
listenForDozeAmount(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun unregisterListeners() {
|
||||
if (!isRegistered) {
|
||||
return
|
||||
}
|
||||
isRegistered = false
|
||||
|
||||
disposableHandle?.dispose()
|
||||
broadcastDispatcher.unregisterReceiver(localeBroadcastReceiver)
|
||||
configurationController.removeCallback(configListener)
|
||||
batteryController.removeCallback(batteryCallback)
|
||||
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
|
||||
statusBarStateController.removeCallback(statusBarStateListener)
|
||||
smallRegionSampler?.stopRegionSampler()
|
||||
largeRegionSampler?.stopRegionSampler()
|
||||
}
|
||||
@@ -235,8 +245,28 @@ open class ClockEventController @Inject constructor(
|
||||
largeRegionSampler?.dump(pw)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = ClockEventController::class.simpleName
|
||||
private const val FORMAT_NUMBER = 1234567890
|
||||
@VisibleForTesting
|
||||
internal suspend fun listenForDozeAmount(scope: CoroutineScope): Job {
|
||||
return scope.launch {
|
||||
keyguardInteractor.dozeAmount.collect {
|
||||
dozeAmount = it
|
||||
clock?.animations?.doze(dozeAmount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal suspend fun listenForDozing(scope: CoroutineScope): Job {
|
||||
return scope.launch {
|
||||
combine (
|
||||
keyguardInteractor.dozeAmount,
|
||||
keyguardInteractor.isDozing,
|
||||
) { localDozeAmount, localIsDozing ->
|
||||
localDozeAmount > dozeAmount || localIsDozing
|
||||
}
|
||||
.collect { localIsDozing ->
|
||||
isDozing = localIsDozing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
protected void onViewAttached() {
|
||||
mClockRegistry.registerClockChangeListener(mClockChangedListener);
|
||||
setClock(mClockRegistry.createCurrentClock());
|
||||
mClockEventController.registerListeners();
|
||||
mClockEventController.registerListeners(mView);
|
||||
mKeyguardClockTopMargin =
|
||||
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@ package com.android.keyguard
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
||||
import com.android.systemui.plugins.ClockAnimations
|
||||
import com.android.systemui.plugins.ClockController
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
@@ -37,6 +40,9 @@ import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import java.util.TimeZone
|
||||
import java.util.concurrent.Executor
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.yield
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@@ -57,7 +63,7 @@ import org.mockito.junit.MockitoJUnit
|
||||
class ClockEventControllerTest : SysuiTestCase() {
|
||||
|
||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||
@Mock private lateinit var statusBarStateController: StatusBarStateController
|
||||
@Mock private lateinit var keyguardInteractor: KeyguardInteractor
|
||||
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
|
||||
@Mock private lateinit var batteryController: BatteryController
|
||||
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||
@@ -72,8 +78,10 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
@Mock private lateinit var largeClockController: ClockFaceController
|
||||
@Mock private lateinit var smallClockEvents: ClockFaceEvents
|
||||
@Mock private lateinit var largeClockEvents: ClockFaceEvents
|
||||
@Mock private lateinit var parentView: View
|
||||
private lateinit var repository: FakeKeyguardRepository
|
||||
|
||||
private lateinit var clockEventController: ClockEventController
|
||||
private lateinit var underTest: ClockEventController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
@@ -86,8 +94,10 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
whenever(clock.events).thenReturn(events)
|
||||
whenever(clock.animations).thenReturn(animations)
|
||||
|
||||
clockEventController = ClockEventController(
|
||||
statusBarStateController,
|
||||
repository = FakeKeyguardRepository()
|
||||
|
||||
underTest = ClockEventController(
|
||||
KeyguardInteractor(repository = repository),
|
||||
broadcastDispatcher,
|
||||
batteryController,
|
||||
keyguardUpdateMonitor,
|
||||
@@ -98,31 +108,34 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
bgExecutor,
|
||||
featureFlags
|
||||
)
|
||||
underTest.clock = clock
|
||||
|
||||
runBlocking(IMMEDIATE) {
|
||||
underTest.registerListeners(parentView)
|
||||
|
||||
repository.setDozing(true)
|
||||
repository.setDozeAmount(1f)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clockSet_validateInitialization() {
|
||||
clockEventController.clock = clock
|
||||
|
||||
verify(clock).initialize(any(), anyFloat(), anyFloat())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clockUnset_validateState() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.clock = null
|
||||
underTest.clock = null
|
||||
|
||||
assertEquals(clockEventController.clock, null)
|
||||
assertEquals(underTest.clock, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun themeChanged_verifyClockPaletteUpdated() {
|
||||
fun themeChanged_verifyClockPaletteUpdated() = runBlocking(IMMEDIATE) {
|
||||
clockEventController.clock = clock
|
||||
verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
|
||||
verify(configurationController).addCallback(capture(captor))
|
||||
captor.value.onThemeChanged()
|
||||
@@ -131,13 +144,11 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fontChanged_verifyFontSizeUpdated() {
|
||||
fun fontChanged_verifyFontSizeUpdated() = runBlocking(IMMEDIATE) {
|
||||
clockEventController.clock = clock
|
||||
verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
|
||||
verify(configurationController).addCallback(capture(captor))
|
||||
captor.value.onDensityOrFontScaleChanged()
|
||||
@@ -146,10 +157,7 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() = runBlocking(IMMEDIATE) {
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
@@ -161,26 +169,21 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardShowingCharging_Duplicate_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
fun batteryCallback_keyguardShowingCharging_Duplicate_verifyChargeAnimation() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
|
||||
verify(animations, times(1)).charge()
|
||||
}
|
||||
verify(animations, times(1)).charge()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardHiddenCharging_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
fun batteryCallback_keyguardHiddenCharging_verifyChargeAnimation() = runBlocking(IMMEDIATE) {
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
@@ -192,25 +195,20 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardShowingNotCharging_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
fun batteryCallback_keyguardShowingNotCharging_verifyChargeAnimation() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, false)
|
||||
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, false)
|
||||
|
||||
verify(animations, never()).charge()
|
||||
}
|
||||
verify(animations, never()).charge()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun localeCallback_verifyClockNotified() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
fun localeCallback_verifyClockNotified() = runBlocking(IMMEDIATE) {
|
||||
val captor = argumentCaptor<BroadcastReceiver>()
|
||||
verify(broadcastDispatcher).registerReceiver(
|
||||
capture(captor), any(), eq(null), eq(null), anyInt(), eq(null)
|
||||
@@ -221,10 +219,7 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_visibilityChanged_clockDozeCalled() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
fun keyguardCallback_visibilityChanged_clockDozeCalled() = runBlocking(IMMEDIATE) {
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
|
||||
@@ -236,10 +231,7 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_timeFormat_clockNotified() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
fun keyguardCallback_timeFormat_clockNotified() = runBlocking(IMMEDIATE) {
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
captor.value.onTimeFormatChanged("12h")
|
||||
@@ -248,11 +240,8 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_timezoneChanged_clockNotified() {
|
||||
fun keyguardCallback_timezoneChanged_clockNotified() = runBlocking(IMMEDIATE) {
|
||||
val mockTimeZone = mock<TimeZone>()
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
captor.value.onTimeZoneChanged(mockTimeZone)
|
||||
@@ -261,10 +250,7 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_userSwitched_clockNotified() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
fun keyguardCallback_userSwitched_clockNotified() = runBlocking(IMMEDIATE) {
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
captor.value.onUserSwitchComplete(10)
|
||||
@@ -273,25 +259,27 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_verifyKeyguardChanged() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
fun keyguardCallback_verifyKeyguardChanged() = runBlocking(IMMEDIATE) {
|
||||
val job = underTest.listenForDozeAmount(this)
|
||||
repository.setDozeAmount(0.4f)
|
||||
|
||||
val captor = argumentCaptor<StatusBarStateController.StateListener>()
|
||||
verify(statusBarStateController).addCallback(capture(captor))
|
||||
captor.value.onDozeAmountChanged(0.4f, 0.6f)
|
||||
yield()
|
||||
|
||||
verify(animations).doze(0.4f)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unregisterListeners_validate() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.unregisterListeners()
|
||||
fun unregisterListeners_validate() = runBlocking(IMMEDIATE) {
|
||||
underTest.unregisterListeners()
|
||||
verify(broadcastDispatcher).unregisterReceiver(any())
|
||||
verify(configurationController).removeCallback(any())
|
||||
verify(batteryController).removeCallback(any())
|
||||
verify(keyguardUpdateMonitor).removeCallback(any())
|
||||
verify(statusBarStateController).removeCallback(any())
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,6 +265,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
private void verifyAttachment(VerificationMode times) {
|
||||
verify(mClockRegistry, times).registerClockChangeListener(
|
||||
any(ClockRegistry.ClockChangeListener.class));
|
||||
verify(mClockEventController, times).registerListeners();
|
||||
verify(mClockEventController, times).registerListeners(mView);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user