diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt index 758e4114c77eb..ea6497ebcf3a9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt @@ -17,14 +17,12 @@ package com.android.systemui.keyguard.data.quickaffordance -import android.content.Context import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.containeddrawable.ContainedDrawable import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.qrcodescanner.controller.QRCodeScannerController import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose @@ -35,12 +33,9 @@ import kotlinx.coroutines.flow.Flow class QrCodeScannerKeyguardQuickAffordanceConfig @Inject constructor( - @Application context: Context, private val controller: QRCodeScannerController, ) : KeyguardQuickAffordanceConfig { - private val appContext = context.applicationContext - override val state: Flow = conflatedCallbackFlow { val callback = object : QRCodeScannerController.Callback { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt index c686e27adb2ac..cc5a9972af933 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt @@ -29,32 +29,59 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall import com.android.systemui.containeddrawable.ContainedDrawable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.statusbar.policy.KeyguardStateController -import com.android.systemui.statusbar.policy.KeyguardStateControllerExt.isKeyguardShowing import com.android.systemui.wallet.controller.QuickAccessWalletController import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flowOf /** Quick access wallet quick affordance data source. */ @SysUISingleton class QuickAccessWalletKeyguardQuickAffordanceConfig @Inject constructor( - private val keyguardStateController: KeyguardStateController, private val walletController: QuickAccessWalletController, private val activityStarter: ActivityStarter, ) : KeyguardQuickAffordanceConfig { - override val state: Flow = - keyguardStateController - .isKeyguardShowing(TAG) - .flatMapLatest { isKeyguardShowing -> - stateInternal(isKeyguardShowing) + override val state: Flow = conflatedCallbackFlow { + val callback = + object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback { + override fun onWalletCardsRetrieved(response: GetWalletCardsResponse?) { + trySendWithFailureLogging( + state( + isFeatureEnabled = walletController.isWalletEnabled, + hasCard = response?.walletCards?.isNotEmpty() == true, + tileIcon = walletController.walletClient.tileIcon, + ), + TAG, + ) + } + + override fun onWalletCardRetrievalError(error: GetWalletCardsError?) { + Log.e(TAG, "Wallet card retrieval error, message: \"${error?.message}\"") + trySendWithFailureLogging( + KeyguardQuickAffordanceConfig.State.Hidden, + TAG, + ) + } } + walletController.setupWalletChangeObservers( + callback, + QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE, + QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE + ) + walletController.updateWalletPreference() + walletController.queryWalletCards(callback) + + awaitClose { + walletController.unregisterWalletChangeObservers( + QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE, + QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE + ) + } + } + override fun onQuickAffordanceClicked( animationController: ActivityLaunchAnimator.Controller?, ): KeyguardQuickAffordanceConfig.OnClickedResult { @@ -66,53 +93,6 @@ constructor( return KeyguardQuickAffordanceConfig.OnClickedResult.Handled } - private fun stateInternal( - isKeyguardShowing: Boolean - ): Flow { - if (!isKeyguardShowing) { - return flowOf(KeyguardQuickAffordanceConfig.State.Hidden) - } - - return conflatedCallbackFlow { - val callback = - object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback { - override fun onWalletCardsRetrieved(response: GetWalletCardsResponse?) { - trySendWithFailureLogging( - state( - isFeatureEnabled = walletController.isWalletEnabled, - hasCard = response?.walletCards?.isNotEmpty() == true, - tileIcon = walletController.walletClient.tileIcon, - ), - TAG, - ) - } - - override fun onWalletCardRetrievalError(error: GetWalletCardsError?) { - Log.e(TAG, "Wallet card retrieval error, message: \"${error?.message}\"") - trySendWithFailureLogging( - KeyguardQuickAffordanceConfig.State.Hidden, - TAG, - ) - } - } - - walletController.setupWalletChangeObservers( - callback, - QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE, - QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE - ) - walletController.updateWalletPreference() - walletController.queryWalletCards(callback) - - awaitClose { - walletController.unregisterWalletChangeObservers( - QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE, - QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE - ) - } - } - } - private fun state( isFeatureEnabled: Boolean, hasCard: Boolean, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt index be91e51f85508..62cf1a624d9b8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt @@ -21,6 +21,7 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall import com.android.systemui.common.data.model.Position import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.policy.KeyguardStateController import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow @@ -49,6 +50,15 @@ interface KeyguardRepository { */ val clockPosition: StateFlow + /** + * Observable for whether the keyguard is showing. + * + * Note: this is also `true` when the lock-screen is occluded with an `Activity` "above" it in + * the z-order (which is not really above the system UI window, but rather - the lock-screen + * becomes invisible to reveal the "occluding activity"). + */ + val isKeyguardShowing: Flow + /** * Observable for whether we are in doze state. * @@ -91,6 +101,7 @@ class KeyguardRepositoryImpl @Inject constructor( statusBarStateController: StatusBarStateController, + keyguardStateController: KeyguardStateController, ) : KeyguardRepository { private val _animateBottomAreaDozingTransitions = MutableStateFlow(false) override val animateBottomAreaDozingTransitions = @@ -102,6 +113,29 @@ constructor( private val _clockPosition = MutableStateFlow(Position(0, 0)) override val clockPosition = _clockPosition.asStateFlow() + override val isKeyguardShowing: Flow = conflatedCallbackFlow { + val callback = + object : KeyguardStateController.Callback { + override fun onKeyguardShowingChanged() { + trySendWithFailureLogging( + keyguardStateController.isShowing, + TAG, + "updated isKeyguardShowing" + ) + } + } + + keyguardStateController.addCallback(callback) + // Adding the callback does not send an initial update. + trySendWithFailureLogging( + keyguardStateController.isShowing, + TAG, + "initial isKeyguardShowing" + ) + + awaitClose { keyguardStateController.removeCallback(callback) } + } + override val isDozing: Flow = conflatedCallbackFlow { val callback = object : StatusBarStateController.StateListener { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt index d2ab3e9b0f879..1a5670c7e8077 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt @@ -30,7 +30,8 @@ interface KeyguardRepositoryModule { impl: KeyguardQuickAffordanceRepositoryImpl ): KeyguardQuickAffordanceRepository - @Binds fun keyguardQuickAffordanceConfigs( + @Binds + fun keyguardQuickAffordanceConfigs( impl: KeyguardQuickAffordanceConfigsImpl ): KeyguardQuickAffordanceConfigs } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/usecase/ObserveIsKeyguardShowingUseCase.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/usecase/ObserveIsKeyguardShowingUseCase.kt new file mode 100644 index 0000000000000..11af123c1650e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/usecase/ObserveIsKeyguardShowingUseCase.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.systemui.keyguard.domain.usecase + +import com.android.systemui.keyguard.data.repository.KeyguardRepository +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow + +/** + * Use-case for observing whether the keyguard is currently being shown. + * + * Note: this is also `true` when the lock-screen is occluded with an `Activity` "above" it in the + * z-order (which is not really above the system UI window, but rather - the lock-screen becomes + * invisible to reveal the "occluding activity"). + */ +class ObserveIsKeyguardShowingUseCase +@Inject +constructor( + private val repository: KeyguardRepository, +) { + operator fun invoke(): Flow { + return repository.isKeyguardShowing + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCase.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCase.kt index aac3d752ce706..eef8ec3e68f56 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCase.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCase.kt @@ -29,7 +29,7 @@ class ObserveKeyguardQuickAffordanceUseCase constructor( private val repository: KeyguardQuickAffordanceRepository, private val isDozingUseCase: ObserveIsDozingUseCase, - private val dozeAmountUseCase: ObserveDozeAmountUseCase, + private val isKeyguardShowingUseCase: ObserveIsKeyguardShowingUseCase, ) { operator fun invoke( position: KeyguardQuickAffordancePosition @@ -37,9 +37,9 @@ constructor( return combine( repository.affordance(position), isDozingUseCase(), - dozeAmountUseCase(), - ) { affordance, isDozing, dozeAmount -> - if (!isDozing && dozeAmount == 0f) { + isKeyguardShowingUseCase(), + ) { affordance, isDozing, isKeyguardShowing -> + if (!isDozing && isKeyguardShowing) { affordance } else { KeyguardQuickAffordanceModel.Hidden diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerExt.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerExt.kt deleted file mode 100644 index b3f1eebb420b0..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerExt.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.android.systemui.statusbar.policy - -import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging -import com.android.systemui.common.coroutine.ConflatedCallbackFlow -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow - -object KeyguardStateControllerExt { - /** - * Returns an observable for whether the keyguard is currently shown or not. - */ - fun KeyguardStateController.isKeyguardShowing(loggingTag: String): Flow { - return ConflatedCallbackFlow.conflatedCallbackFlow { - val callback = - object : KeyguardStateController.Callback { - override fun onKeyguardShowingChanged() { - trySendWithFailureLogging( - isShowing, loggingTag, "updated isKeyguardShowing") - } - } - - addCallback(callback) - // Adding the callback does not send an initial update. - trySendWithFailureLogging(isShowing, loggingTag, "initial isKeyguardShowing") - - awaitClose { removeCallback(callback) } - } - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardQuickAffordanceRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardQuickAffordanceRepository.kt index 7d1cccb8a0a80..10d2e4de631d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardQuickAffordanceRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardQuickAffordanceRepository.kt @@ -27,7 +27,7 @@ class FakeKeyguardQuickAffordanceRepository : KeyguardQuickAffordanceRepository private val modelByPosition = mutableMapOf< - KeyguardQuickAffordancePosition, MutableStateFlow>() + KeyguardQuickAffordancePosition, MutableStateFlow>() init { KeyguardQuickAffordancePosition.values().forEach { value -> diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt index c82803af4f377..d40b985f64dea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt @@ -17,9 +17,7 @@ package com.android.systemui.keyguard.data.repository import com.android.systemui.common.data.model.Position -import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -36,18 +34,13 @@ class FakeKeyguardRepository : KeyguardRepository { private val _clockPosition = MutableStateFlow(Position(0, 0)) override val clockPosition: StateFlow = _clockPosition - private val _isDozing = - MutableSharedFlow( - replay = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST, - ) + private val _isKeyguardShowing = MutableStateFlow(false) + override val isKeyguardShowing: Flow = _isKeyguardShowing + + private val _isDozing = MutableStateFlow(false) override val isDozing: Flow = _isDozing - private val _dozeAmount = - MutableSharedFlow( - replay = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST, - ) + private val _dozeAmount = MutableStateFlow(0f) override val dozeAmount: Flow = _dozeAmount init { @@ -67,11 +60,15 @@ class FakeKeyguardRepository : KeyguardRepository { _clockPosition.value = Position(x, y) } + fun setKeyguardShowing(isShowing: Boolean) { + _isKeyguardShowing.value = isShowing + } + fun setDozing(isDozing: Boolean) { - _isDozing.tryEmit(isDozing) + _isDozing.value = isDozing } fun setDozeAmount(dozeAmount: Float) { - _dozeAmount.tryEmit(dozeAmount) + _dozeAmount.value = dozeAmount } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt index 2ee80349ff4cb..3d2c51a449c7f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt @@ -20,6 +20,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.data.model.Position import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.argumentCaptor import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.launchIn @@ -31,6 +32,7 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.mockito.Mock import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest @@ -38,6 +40,7 @@ import org.mockito.MockitoAnnotations class KeyguardRepositoryImplTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateController + @Mock private lateinit var keyguardStateController: KeyguardStateController private lateinit var underTest: KeyguardRepositoryImpl @@ -45,7 +48,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - underTest = KeyguardRepositoryImpl(statusBarStateController) + underTest = KeyguardRepositoryImpl(statusBarStateController, keyguardStateController) } @Test @@ -99,6 +102,28 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { assertThat(underTest.clockPosition.value).isEqualTo(Position(3, 1)) } + @Test + fun isKeyguardShowing() = runBlockingTest { + whenever(keyguardStateController.isShowing).thenReturn(false) + var latest: Boolean? = null + val job = underTest.isKeyguardShowing.onEach { latest = it }.launchIn(this) + + assertThat(latest).isFalse() + + val captor = argumentCaptor() + verify(keyguardStateController).addCallback(captor.capture()) + + whenever(keyguardStateController.isShowing).thenReturn(true) + captor.value.onKeyguardShowingChanged() + assertThat(latest).isTrue() + + whenever(keyguardStateController.isShowing).thenReturn(false) + captor.value.onKeyguardShowingChanged() + assertThat(latest).isFalse() + + job.cancel() + } + @Test fun isDozing() = runBlockingTest { var latest: Boolean? = null diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt index 4bef00a13a073..6e0da1b3fce15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt @@ -51,7 +51,7 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) whenever(controller.intent).thenReturn(INTENT_1) - underTest = QrCodeScannerKeyguardQuickAffordanceConfig(context, controller) + underTest = QrCodeScannerKeyguardQuickAffordanceConfig(controller) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt index ee1d4d895e59d..79949721a8135 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt @@ -26,7 +26,6 @@ import com.android.systemui.containeddrawable.ContainedDrawable import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig import com.android.systemui.keyguard.data.quickaffordance.QuickAccessWalletKeyguardQuickAffordanceConfig import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.wallet.controller.QuickAccessWalletController @@ -48,7 +47,6 @@ import org.mockito.MockitoAnnotations class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { @Mock private lateinit var walletController: QuickAccessWalletController - @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var activityStarter: ActivityStarter private lateinit var underTest: QuickAccessWalletKeyguardQuickAffordanceConfig @@ -59,7 +57,6 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { underTest = QuickAccessWalletKeyguardQuickAffordanceConfig( - keyguardStateController, walletController, activityStarter, ) @@ -67,7 +64,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { @Test fun `affordance - keyguard showing - has wallet card - visible model`() = runBlockingTest { - val callback = setUpState() + setUpState() var latest: KeyguardQuickAffordanceConfig.State? = null val job = underTest.state.onEach { latest = it }.launchIn(this) @@ -76,25 +73,11 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { assertThat(visibleModel.icon).isEqualTo(ContainedDrawable.WithDrawable(ICON)) assertThat(visibleModel.contentDescriptionResourceId).isNotNull() job.cancel() - callback?.let { verify(keyguardStateController).removeCallback(it) } - } - - @Test - fun `affordance - keyguard not showing - model is none`() = runBlockingTest { - val callback = setUpState(isKeyguardShowing = false) - var latest: KeyguardQuickAffordanceConfig.State? = null - - val job = underTest.state.onEach { latest = it }.launchIn(this) - - assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.State.Hidden) - - job.cancel() - callback?.let { verify(keyguardStateController).removeCallback(it) } } @Test fun `affordance - wallet not enabled - model is none`() = runBlockingTest { - val callback = setUpState(isWalletEnabled = false) + setUpState(isWalletEnabled = false) var latest: KeyguardQuickAffordanceConfig.State? = null val job = underTest.state.onEach { latest = it }.launchIn(this) @@ -102,12 +85,11 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.State.Hidden) job.cancel() - callback?.let { verify(keyguardStateController).removeCallback(it) } } @Test fun `affordance - query not successful - model is none`() = runBlockingTest { - val callback = setUpState(isWalletQuerySuccessful = false) + setUpState(isWalletQuerySuccessful = false) var latest: KeyguardQuickAffordanceConfig.State? = null val job = underTest.state.onEach { latest = it }.launchIn(this) @@ -115,12 +97,11 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.State.Hidden) job.cancel() - callback?.let { verify(keyguardStateController).removeCallback(it) } } @Test fun `affordance - missing icon - model is none`() = runBlockingTest { - val callback = setUpState(hasWalletIcon = false) + setUpState(hasWalletIcon = false) var latest: KeyguardQuickAffordanceConfig.State? = null val job = underTest.state.onEach { latest = it }.launchIn(this) @@ -128,12 +109,11 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.State.Hidden) job.cancel() - callback?.let { verify(keyguardStateController).removeCallback(it) } } @Test fun `affordance - no selected card - model is none`() = runBlockingTest { - val callback = setUpState(hasWalletIcon = false) + setUpState(hasWalletIcon = false) var latest: KeyguardQuickAffordanceConfig.State? = null val job = underTest.state.onEach { latest = it }.launchIn(this) @@ -141,7 +121,6 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.State.Hidden) job.cancel() - callback?.let { verify(keyguardStateController).removeCallback(it) } } @Test @@ -159,21 +138,11 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } private fun setUpState( - isKeyguardShowing: Boolean = true, isWalletEnabled: Boolean = true, isWalletQuerySuccessful: Boolean = true, hasWalletIcon: Boolean = true, hasSelectedCard: Boolean = true, - ): KeyguardStateController.Callback? { - var returnedCallback: KeyguardStateController.Callback? = null - whenever(keyguardStateController.isShowing).thenReturn(isKeyguardShowing) - whenever(keyguardStateController.addCallback(any())).thenAnswer { invocation -> - with(invocation.arguments[0] as KeyguardStateController.Callback) { - returnedCallback = this - onKeyguardShowingChanged() - } - } - + ) { whenever(walletController.isWalletEnabled).thenReturn(isWalletEnabled) val walletClient: QuickAccessWalletClient = mock() @@ -203,8 +172,6 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } } } - - return returnedCallback } companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCaseTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCaseTest.kt index a60657c594c96..b90400be16d8f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCaseTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/ObserveKeyguardQuickAffordanceUseCaseTest.kt @@ -43,20 +43,21 @@ class ObserveKeyguardQuickAffordanceUseCaseTest : SysuiTestCase() { private lateinit var repository: FakeKeyguardRepository private lateinit var quickAffordanceRepository: FakeKeyguardQuickAffordanceRepository private lateinit var isDozingUseCase: ObserveIsDozingUseCase - private lateinit var dozeAmountUseCase: ObserveDozeAmountUseCase + private lateinit var isKeyguardShowingUseCase: ObserveIsKeyguardShowingUseCase @Before fun setUp() { repository = FakeKeyguardRepository() + repository.setKeyguardShowing(true) isDozingUseCase = ObserveIsDozingUseCase(repository) - dozeAmountUseCase = ObserveDozeAmountUseCase(repository) + isKeyguardShowingUseCase = ObserveIsKeyguardShowingUseCase(repository) quickAffordanceRepository = FakeKeyguardQuickAffordanceRepository() underTest = ObserveKeyguardQuickAffordanceUseCase( repository = quickAffordanceRepository, isDozingUseCase = isDozingUseCase, - dozeAmountUseCase = dozeAmountUseCase, + isKeyguardShowingUseCase = isKeyguardShowingUseCase, ) } @@ -75,9 +76,10 @@ class ObserveKeyguardQuickAffordanceUseCaseTest : SysuiTestCase() { ) var latest: KeyguardQuickAffordanceModel? = null - val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_END) - .onEach { latest = it } - .launchIn(this) + val job = + underTest(KeyguardQuickAffordancePosition.BOTTOM_END) + .onEach { latest = it } + .launchIn(this) assertThat(latest).isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) val visibleModel = latest as KeyguardQuickAffordanceModel.Visible @@ -104,16 +106,17 @@ class ObserveKeyguardQuickAffordanceUseCaseTest : SysuiTestCase() { ) var latest: KeyguardQuickAffordanceModel? = null - val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_END) - .onEach { latest = it } - .launchIn(this) + val job = + underTest(KeyguardQuickAffordancePosition.BOTTOM_END) + .onEach { latest = it } + .launchIn(this) assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden) job.cancel() } @Test - fun `invoke - affordance not visible doze amount is not 0`() = runBlockingTest { - repository.setDozeAmount(0.3f) + fun `invoke - affordance not visible when lockscreen is not showing`() = runBlockingTest { + repository.setKeyguardShowing(false) val configKey = HomeControlsKeyguardQuickAffordanceConfig::class val model = KeyguardQuickAffordanceModel.Visible( @@ -127,9 +130,10 @@ class ObserveKeyguardQuickAffordanceUseCaseTest : SysuiTestCase() { ) var latest: KeyguardQuickAffordanceModel? = null - val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_END) - .onEach { latest = it } - .launchIn(this) + val job = + underTest(KeyguardQuickAffordancePosition.BOTTOM_END) + .onEach { latest = it } + .launchIn(this) assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden) job.cancel() } @@ -142,9 +146,10 @@ class ObserveKeyguardQuickAffordanceUseCaseTest : SysuiTestCase() { ) var latest: KeyguardQuickAffordanceModel? = null - val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_START) - .onEach { latest = it } - .launchIn(this) + val job = + underTest(KeyguardQuickAffordancePosition.BOTTOM_START) + .onEach { latest = it } + .launchIn(this) assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden) job.cancel() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt index cb9cbbaa169ff..00dd58e191421 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt @@ -33,6 +33,7 @@ import com.android.systemui.keyguard.domain.usecase.ObserveBottomAreaAlphaUseCas import com.android.systemui.keyguard.domain.usecase.ObserveClockPositionUseCase import com.android.systemui.keyguard.domain.usecase.ObserveDozeAmountUseCase import com.android.systemui.keyguard.domain.usecase.ObserveIsDozingUseCase +import com.android.systemui.keyguard.domain.usecase.ObserveIsKeyguardShowingUseCase import com.android.systemui.keyguard.domain.usecase.ObserveKeyguardQuickAffordanceUseCase import com.android.systemui.keyguard.domain.usecase.OnKeyguardQuickAffordanceClickedUseCase import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordanceModel @@ -65,7 +66,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { private lateinit var affordanceRepository: FakeKeyguardQuickAffordanceRepository private lateinit var repository: FakeKeyguardRepository private lateinit var isDozingUseCase: ObserveIsDozingUseCase - private lateinit var dozeAmountUseCase: ObserveDozeAmountUseCase + private lateinit var isKeyguardShowingUseCase: ObserveIsKeyguardShowingUseCase private lateinit var launchQuickAffordanceUseCase: FakeLaunchKeyguardQuickAffordanceUseCase private lateinit var homeControlsQuickAffordanceConfig: FakeKeyguardQuickAffordanceConfig private lateinit var quickAccessWalletAffordanceConfig: FakeKeyguardQuickAffordanceConfig @@ -83,8 +84,8 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { ObserveIsDozingUseCase( repository = repository, ) - dozeAmountUseCase = - ObserveDozeAmountUseCase( + isKeyguardShowingUseCase = + ObserveIsKeyguardShowingUseCase( repository = repository, ) launchQuickAffordanceUseCase = FakeLaunchKeyguardQuickAffordanceUseCase() @@ -98,7 +99,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { ObserveKeyguardQuickAffordanceUseCase( repository = affordanceRepository, isDozingUseCase = isDozingUseCase, - dozeAmountUseCase = dozeAmountUseCase, + isKeyguardShowingUseCase = isKeyguardShowingUseCase, ), onQuickAffordanceClickedUseCase = OnKeyguardQuickAffordanceClickedUseCase( @@ -140,12 +141,13 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { } @Test - fun `startButton - present and not dozing - visible model - starts activity on click`() = + fun `startButton - present - not dozing - lockscreen showing - visible model - starts activity on click`() = // ktlint-disable max-line-length runBlockingTest { var latest: KeyguardQuickAffordanceViewModel? = null val job = underTest.startButton.onEach { latest = it }.launchIn(this) repository.setDozing(false) + repository.setKeyguardShowing(true) val testConfig = TestConfig( isVisible = true, @@ -168,12 +170,13 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { } @Test - fun `endButton - present and not dozing - visible model - do nothing on click`() = + fun `endButton - present - not dozing - lockscreen showing - visible model - do nothing on click`() = // ktlint-disable max-line-length runBlockingTest { var latest: KeyguardQuickAffordanceViewModel? = null val job = underTest.endButton.onEach { latest = it }.launchIn(this) repository.setDozing(false) + repository.setKeyguardShowing(true) val config = TestConfig( isVisible = true, @@ -197,35 +200,38 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { } @Test - fun `startButton - not present and not dozing - model is none`() = runBlockingTest { - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.startButton.onEach { latest = it }.launchIn(this) + fun `startButton - not present - not dozing - lockscreen showing - model is none`() = + runBlockingTest { + var latest: KeyguardQuickAffordanceViewModel? = null + val job = underTest.startButton.onEach { latest = it }.launchIn(this) - repository.setDozing(false) - val config = - TestConfig( - isVisible = false, - ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, + repository.setDozing(false) + repository.setKeyguardShowing(true) + val config = + TestConfig( + isVisible = false, + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = config, + ) + + assertQuickAffordanceViewModel( + viewModel = latest, testConfig = config, + configKey = configKey, ) - - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = config, - configKey = configKey, - ) - job.cancel() - } + job.cancel() + } @Test - fun `startButton - present but dozing - model is none`() = runBlockingTest { + fun `startButton - present - dozing - lockscreen showing - model is none`() = runBlockingTest { var latest: KeyguardQuickAffordanceViewModel? = null val job = underTest.startButton.onEach { latest = it }.launchIn(this) repository.setDozing(true) + repository.setKeyguardShowing(true) val config = TestConfig( isVisible = true, @@ -247,6 +253,35 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { job.cancel() } + @Test + fun `startButton - present - not dozing - lockscreen not showing - model is none`() = + runBlockingTest { + var latest: KeyguardQuickAffordanceViewModel? = null + val job = underTest.startButton.onEach { latest = it }.launchIn(this) + + repository.setDozing(false) + repository.setKeyguardShowing(false) + val config = + TestConfig( + isVisible = true, + icon = mock(), + canShowWhileLocked = false, + intent = Intent("action"), + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = config, + ) + + assertQuickAffordanceViewModel( + viewModel = latest, + testConfig = TestConfig(isVisible = false), + configKey = configKey, + ) + job.cancel() + } + @Test fun animateButtonReveal() = runBlockingTest { val values = mutableListOf() @@ -287,6 +322,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { @Test fun isIndicationAreaPadded() = runBlockingTest { + repository.setKeyguardShowing(true) val values = mutableListOf() val job = underTest.isIndicationAreaPadded.onEach(values::add).launchIn(this)