[DO NOT MERGE] Bouncer - Intercept touch events when not visible

There is a moment, when swiping on the lockscreen, that the bouncer
showing state is set to true but it isn't quite visible. In this
state, it is possible to interact with it.

Only allow interaction if the bouncer is at least 90% visible.

Also, refactor bouncer repository to an interface and add a
FakeKeyguardBouncerRepository so it can be tested with coroutines.

Test: atest PrimaryBouncerInteractorTest
PrimaryBouncerInteractorWithCoroutinesTest
Fixes: 260820843

Change-Id: I78cdf14521cc8cd02b6f2ab06e7ca518c92718c0
This commit is contained in:
Matt Pietal
2022-12-22 17:40:12 +00:00
parent d2fe4b9e81
commit 96cdb8a262
14 changed files with 421 additions and 82 deletions

View File

@@ -19,6 +19,7 @@ package com.android.keyguard;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout; import android.widget.FrameLayout;
/** /**
@@ -33,7 +34,7 @@ import android.widget.FrameLayout;
public class KeyguardHostView extends FrameLayout { public class KeyguardHostView extends FrameLayout {
protected ViewMediatorCallback mViewMediatorCallback; protected ViewMediatorCallback mViewMediatorCallback;
private boolean mIsInteractable;
public KeyguardHostView(Context context) { public KeyguardHostView(Context context) {
this(context, null); this(context, null);
@@ -54,4 +55,24 @@ public class KeyguardHostView extends FrameLayout {
public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) { public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
mViewMediatorCallback = viewMediatorCallback; mViewMediatorCallback = viewMediatorCallback;
} }
/** Set true if the view can be interacted with */
public void setInteractable(boolean isInteractable) {
mIsInteractable = isInteractable;
}
/**
* Make sure to disallow touches while transitioning the bouncer, otherwise
* it can remain interactable even when barely visible.
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return !mIsInteractable;
}
/** True to consume any events that are sent to it */
@Override
public boolean onTouchEvent(MotionEvent ev) {
return true;
}
} }

View File

@@ -527,4 +527,9 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
mKeyguardSecurityContainerController.updateKeyguardPosition(x); mKeyguardSecurityContainerController.updateKeyguardPosition(x);
} }
} }
/** Set true if the view can be interacted with */
public void setInteractable(boolean isInteractable) {
mView.setInteractable(isInteractable);
}
} }

View File

@@ -41,31 +41,96 @@ import kotlinx.coroutines.flow.map
* *
* Make sure to add newly added flows to the logger. * Make sure to add newly added flows to the logger.
*/ */
interface KeyguardBouncerRepository {
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
val primaryBouncerVisible: StateFlow<Boolean>
val primaryBouncerShow: StateFlow<KeyguardBouncerModel?>
val primaryBouncerShowingSoon: StateFlow<Boolean>
val primaryBouncerHide: StateFlow<Boolean>
val primaryBouncerStartingToHide: StateFlow<Boolean>
val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
/** Determines if we want to instantaneously show the primary bouncer instead of translating. */
val primaryBouncerScrimmed: StateFlow<Boolean>
/**
* Set how much of the notification panel is showing on the screen.
* ```
* 0f = panel fully hidden = bouncer fully showing
* 1f = panel fully showing = bouncer fully hidden
* ```
*/
val panelExpansionAmount: StateFlow<Float>
val keyguardPosition: StateFlow<Float>
val onScreenTurnedOff: StateFlow<Boolean>
val isBackButtonEnabled: StateFlow<Boolean?>
/** Determines if user is already unlocked */
val keyguardAuthenticated: StateFlow<Boolean?>
val showMessage: StateFlow<BouncerShowMessageModel?>
val resourceUpdateRequests: StateFlow<Boolean>
val bouncerPromptReason: Int
val bouncerErrorMessage: CharSequence?
val isAlternateBouncerVisible: StateFlow<Boolean>
val isAlternateBouncerUIAvailable: StateFlow<Boolean>
var lastAlternateBouncerVisibleTime: Long
fun setPrimaryScrimmed(isScrimmed: Boolean)
fun setPrimaryVisible(isVisible: Boolean)
fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?)
fun setPrimaryShowingSoon(showingSoon: Boolean)
fun setPrimaryHide(hide: Boolean)
fun setPrimaryStartingToHide(startingToHide: Boolean)
fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
fun setPanelExpansion(panelExpansion: Float)
fun setKeyguardPosition(keyguardPosition: Float)
fun setResourceUpdateRequests(willUpdateResources: Boolean)
fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?)
fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?)
fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean)
fun setAlternateVisible(isVisible: Boolean)
fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
}
@SysUISingleton @SysUISingleton
class KeyguardBouncerRepository class KeyguardBouncerRepositoryImpl
@Inject @Inject
constructor( constructor(
private val viewMediatorCallback: ViewMediatorCallback, private val viewMediatorCallback: ViewMediatorCallback,
private val clock: SystemClock, private val clock: SystemClock,
@Application private val applicationScope: CoroutineScope, @Application private val applicationScope: CoroutineScope,
@BouncerLog private val buffer: TableLogBuffer, @BouncerLog private val buffer: TableLogBuffer,
) { ) : KeyguardBouncerRepository {
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */ /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
private val _primaryBouncerVisible = MutableStateFlow(false) private val _primaryBouncerVisible = MutableStateFlow(false)
val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow() override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null) private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
val primaryBouncerShow = _primaryBouncerShow.asStateFlow() override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
private val _primaryBouncerShowingSoon = MutableStateFlow(false) private val _primaryBouncerShowingSoon = MutableStateFlow(false)
val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow() override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
private val _primaryBouncerHide = MutableStateFlow(false) private val _primaryBouncerHide = MutableStateFlow(false)
val primaryBouncerHide = _primaryBouncerHide.asStateFlow() override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
private val _primaryBouncerStartingToHide = MutableStateFlow(false) private val _primaryBouncerStartingToHide = MutableStateFlow(false)
val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow() override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null) private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
val primaryBouncerStartingDisappearAnimation = _primaryBouncerDisappearAnimation.asStateFlow() override val primaryBouncerStartingDisappearAnimation =
_primaryBouncerDisappearAnimation.asStateFlow()
/** Determines if we want to instantaneously show the primary bouncer instead of translating. */ /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
private val _primaryBouncerScrimmed = MutableStateFlow(false) private val _primaryBouncerScrimmed = MutableStateFlow(false)
val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow() override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
/** /**
* Set how much of the notification panel is showing on the screen. * Set how much of the notification panel is showing on the screen.
* ``` * ```
@@ -74,23 +139,23 @@ constructor(
* ``` * ```
*/ */
private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN) private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
val panelExpansionAmount = _panelExpansionAmount.asStateFlow() override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f) private val _keyguardPosition = MutableStateFlow(0f)
val keyguardPosition = _keyguardPosition.asStateFlow() override val keyguardPosition = _keyguardPosition.asStateFlow()
private val _onScreenTurnedOff = MutableStateFlow(false) private val _onScreenTurnedOff = MutableStateFlow(false)
val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow() override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null) private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow() override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null) private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
/** Determines if user is already unlocked */ /** Determines if user is already unlocked */
val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow() override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null) private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
val showMessage = _showMessage.asStateFlow() override val showMessage = _showMessage.asStateFlow()
private val _resourceUpdateRequests = MutableStateFlow(false) private val _resourceUpdateRequests = MutableStateFlow(false)
val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow() override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
val bouncerPromptReason: Int override val bouncerPromptReason: Int
get() = viewMediatorCallback.bouncerPromptReason get() = viewMediatorCallback.bouncerPromptReason
val bouncerErrorMessage: CharSequence? override val bouncerErrorMessage: CharSequence?
get() = viewMediatorCallback.consumeCustomMessage() get() = viewMediatorCallback.consumeCustomMessage()
init { init {
@@ -99,21 +164,21 @@ constructor(
/** Values associated with the AlternateBouncer */ /** Values associated with the AlternateBouncer */
private val _isAlternateBouncerVisible = MutableStateFlow(false) private val _isAlternateBouncerVisible = MutableStateFlow(false)
val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow() override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false) private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
val isAlternateBouncerUIAvailable: StateFlow<Boolean> = override val isAlternateBouncerUIAvailable: StateFlow<Boolean> =
_isAlternateBouncerUIAvailable.asStateFlow() _isAlternateBouncerUIAvailable.asStateFlow()
fun setPrimaryScrimmed(isScrimmed: Boolean) { override fun setPrimaryScrimmed(isScrimmed: Boolean) {
_primaryBouncerScrimmed.value = isScrimmed _primaryBouncerScrimmed.value = isScrimmed
} }
fun setPrimaryVisible(isVisible: Boolean) { override fun setPrimaryVisible(isVisible: Boolean) {
_primaryBouncerVisible.value = isVisible _primaryBouncerVisible.value = isVisible
} }
fun setAlternateVisible(isVisible: Boolean) { override fun setAlternateVisible(isVisible: Boolean) {
if (isVisible && !_isAlternateBouncerVisible.value) { if (isVisible && !_isAlternateBouncerVisible.value) {
lastAlternateBouncerVisibleTime = clock.uptimeMillis() lastAlternateBouncerVisibleTime = clock.uptimeMillis()
} else if (!isVisible) { } else if (!isVisible) {
@@ -122,55 +187,55 @@ constructor(
_isAlternateBouncerVisible.value = isVisible _isAlternateBouncerVisible.value = isVisible
} }
fun setAlternateBouncerUIAvailable(isAvailable: Boolean) { override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
_isAlternateBouncerUIAvailable.value = isAvailable _isAlternateBouncerUIAvailable.value = isAvailable
} }
fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) { override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
_primaryBouncerShow.value = keyguardBouncerModel _primaryBouncerShow.value = keyguardBouncerModel
} }
fun setPrimaryShowingSoon(showingSoon: Boolean) { override fun setPrimaryShowingSoon(showingSoon: Boolean) {
_primaryBouncerShowingSoon.value = showingSoon _primaryBouncerShowingSoon.value = showingSoon
} }
fun setPrimaryHide(hide: Boolean) { override fun setPrimaryHide(hide: Boolean) {
_primaryBouncerHide.value = hide _primaryBouncerHide.value = hide
} }
fun setPrimaryStartingToHide(startingToHide: Boolean) { override fun setPrimaryStartingToHide(startingToHide: Boolean) {
_primaryBouncerStartingToHide.value = startingToHide _primaryBouncerStartingToHide.value = startingToHide
} }
fun setPrimaryStartDisappearAnimation(runnable: Runnable?) { override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
_primaryBouncerDisappearAnimation.value = runnable _primaryBouncerDisappearAnimation.value = runnable
} }
fun setPanelExpansion(panelExpansion: Float) { override fun setPanelExpansion(panelExpansion: Float) {
_panelExpansionAmount.value = panelExpansion _panelExpansionAmount.value = panelExpansion
} }
fun setKeyguardPosition(keyguardPosition: Float) { override fun setKeyguardPosition(keyguardPosition: Float) {
_keyguardPosition.value = keyguardPosition _keyguardPosition.value = keyguardPosition
} }
fun setResourceUpdateRequests(willUpdateResources: Boolean) { override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
_resourceUpdateRequests.value = willUpdateResources _resourceUpdateRequests.value = willUpdateResources
} }
fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) { override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
_showMessage.value = bouncerShowMessageModel _showMessage.value = bouncerShowMessageModel
} }
fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) { override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
_keyguardAuthenticated.value = keyguardAuthenticated _keyguardAuthenticated.value = keyguardAuthenticated
} }
fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) { override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
_isBackButtonEnabled.value = isBackButtonEnabled _isBackButtonEnabled.value = isBackButtonEnabled
} }
fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) { override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
_onScreenTurnedOff.value = onScreenTurnedOff _onScreenTurnedOff.value = onScreenTurnedOff
} }

View File

@@ -37,4 +37,7 @@ interface KeyguardRepositoryModule {
fun deviceEntryFingerprintAuthRepository( fun deviceEntryFingerprintAuthRepository(
impl: DeviceEntryFingerprintAuthRepositoryImpl impl: DeviceEntryFingerprintAuthRepositoryImpl
): DeviceEntryFingerprintAuthRepository ): DeviceEntryFingerprintAuthRepository
@Binds
fun keyguardBouncerRepository(impl: KeyguardBouncerRepositoryImpl): KeyguardBouncerRepository
} }

View File

@@ -113,6 +113,8 @@ constructor(
0f 0f
} }
} }
/** Allow for interaction when just about fully visible */
val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
// TODO(b/243685699): Move isScrimmed logic to data layer. // TODO(b/243685699): Move isScrimmed logic to data layer.
// TODO(b/243695312): Encapsulate all of the show logic for the bouncer. // TODO(b/243695312): Encapsulate all of the show logic for the bouncer.

View File

@@ -160,6 +160,12 @@ object KeyguardBouncerViewBinder {
} }
} }
launch {
viewModel.isInteractable.collect { isInteractable ->
hostViewController.setInteractable(isInteractable)
}
}
launch { launch {
viewModel.isBouncerVisible viewModel.isBouncerVisible
.filter { !it } .filter { !it }

View File

@@ -41,6 +41,9 @@ constructor(
/** Observe on bouncer visibility. */ /** Observe on bouncer visibility. */
val isBouncerVisible: Flow<Boolean> = interactor.isVisible val isBouncerVisible: Flow<Boolean> = interactor.isVisible
/** Can the user interact with the view? */
val isInteractable: Flow<Boolean> = interactor.isInteractable
/** Observe whether bouncer is showing. */ /** Observe whether bouncer is showing. */
val show: Flow<KeyguardBouncerModel> = interactor.show val show: Flow<KeyguardBouncerModel> = interactor.show

View File

@@ -52,7 +52,6 @@ import android.view.WindowMetrics
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.airbnb.lottie.LottieAnimationView import com.airbnb.lottie.LottieAnimationView
import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext import com.android.systemui.SysuiTestableContext
@@ -61,9 +60,8 @@ import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.MODERN_ALTERNATE_BOUNCER import com.android.systemui.flags.Flags.MODERN_ALTERNATE_BOUNCER
import com.android.systemui.keyguard.data.repository.FakeBiometricRepository import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.recents.OverviewProxyService import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.util.time.FakeSystemClock
@@ -111,7 +109,7 @@ class SideFpsControllerTest : SysuiTestCase() {
@Captor lateinit var overlayCaptor: ArgumentCaptor<View> @Captor lateinit var overlayCaptor: ArgumentCaptor<View>
@Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams> @Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
private lateinit var keyguardBouncerRepository: KeyguardBouncerRepository private lateinit var keyguardBouncerRepository: FakeKeyguardBouncerRepository
private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
private val featureFlags = FakeFeatureFlags() private val featureFlags = FakeFeatureFlags()
private val executor = FakeExecutor(FakeSystemClock()) private val executor = FakeExecutor(FakeSystemClock())
@@ -135,13 +133,7 @@ class SideFpsControllerTest : SysuiTestCase() {
@Before @Before
fun setup() { fun setup() {
featureFlags.set(MODERN_ALTERNATE_BOUNCER, true) featureFlags.set(MODERN_ALTERNATE_BOUNCER, true)
keyguardBouncerRepository = keyguardBouncerRepository = FakeKeyguardBouncerRepository()
KeyguardBouncerRepository(
mock(ViewMediatorCallback::class.java),
FakeSystemClock(),
TestCoroutineScope(),
mock(TableLogBuffer::class.java),
)
alternateBouncerInteractor = alternateBouncerInteractor =
AlternateBouncerInteractor( AlternateBouncerInteractor(
keyguardBouncerRepository, keyguardBouncerRepository,

View File

@@ -29,6 +29,7 @@ import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.BiometricRepository import com.android.systemui.keyguard.data.repository.BiometricRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
@@ -65,7 +66,7 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
allowTestableLooperAsMainThread() // repeatWhenAttached requires the main thread allowTestableLooperAsMainThread() // repeatWhenAttached requires the main thread
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
keyguardBouncerRepository = keyguardBouncerRepository =
KeyguardBouncerRepository( KeyguardBouncerRepositoryImpl(
mock(com.android.keyguard.ViewMediatorCallback::class.java), mock(com.android.keyguard.ViewMediatorCallback::class.java),
FakeSystemClock(), FakeSystemClock(),
TestCoroutineScope(), TestCoroutineScope(),

View File

@@ -45,7 +45,7 @@ class KeyguardBouncerRepositoryTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
val testCoroutineScope = TestCoroutineScope() val testCoroutineScope = TestCoroutineScope()
underTest = underTest =
KeyguardBouncerRepository( KeyguardBouncerRepositoryImpl(
viewMediatorCallback, viewMediatorCallback,
systemClock, systemClock,
testCoroutineScope, testCoroutineScope,

View File

@@ -25,6 +25,7 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeBiometricRepository import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock import com.android.systemui.util.time.SystemClock
@@ -58,7 +59,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
fun setup() { fun setup() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
bouncerRepository = bouncerRepository =
KeyguardBouncerRepository( KeyguardBouncerRepositoryImpl(
mock(ViewMediatorCallback::class.java), mock(ViewMediatorCallback::class.java),
FakeSystemClock(), FakeSystemClock(),
TestCoroutineScope(), TestCoroutineScope(),

View File

@@ -68,13 +68,13 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Mock private lateinit var keyguardBypassController: KeyguardBypassController @Mock private lateinit var keyguardBypassController: KeyguardBypassController
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private val mainHandler = FakeHandler(Looper.getMainLooper()) private val mainHandler = FakeHandler(Looper.getMainLooper())
private lateinit var mPrimaryBouncerInteractor: PrimaryBouncerInteractor private lateinit var underTest: PrimaryBouncerInteractor
@Before @Before
fun setUp() { fun setUp() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
DejankUtils.setImmediate(true) DejankUtils.setImmediate(true)
mPrimaryBouncerInteractor = underTest =
PrimaryBouncerInteractor( PrimaryBouncerInteractor(
repository, repository,
bouncerView, bouncerView,
@@ -94,7 +94,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test @Test
fun testShow_isScrimmed() { fun testShow_isScrimmed() {
mPrimaryBouncerInteractor.show(true) underTest.show(true)
verify(repository).setOnScreenTurnedOff(false) verify(repository).setOnScreenTurnedOff(false)
verify(repository).setKeyguardAuthenticated(null) verify(repository).setKeyguardAuthenticated(null)
verify(repository).setPrimaryHide(false) verify(repository).setPrimaryHide(false)
@@ -124,7 +124,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test @Test
fun testHide() { fun testHide() {
mPrimaryBouncerInteractor.hide() underTest.hide()
verify(falsingCollector).onBouncerHidden() verify(falsingCollector).onBouncerHidden()
verify(keyguardStateController).notifyBouncerShowing(false) verify(keyguardStateController).notifyBouncerShowing(false)
verify(repository).setPrimaryShowingSoon(false) verify(repository).setPrimaryShowingSoon(false)
@@ -137,7 +137,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test @Test
fun testExpansion() { fun testExpansion() {
`when`(repository.panelExpansionAmount.value).thenReturn(0.5f) `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
mPrimaryBouncerInteractor.setPanelExpansion(0.6f) underTest.setPanelExpansion(0.6f)
verify(repository).setPanelExpansion(0.6f) verify(repository).setPanelExpansion(0.6f)
verify(mPrimaryBouncerCallbackInteractor).dispatchExpansionChanged(0.6f) verify(mPrimaryBouncerCallbackInteractor).dispatchExpansionChanged(0.6f)
} }
@@ -146,7 +146,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
fun testExpansion_fullyShown() { fun testExpansion_fullyShown() {
`when`(repository.panelExpansionAmount.value).thenReturn(0.5f) `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null) `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_VISIBLE) underTest.setPanelExpansion(EXPANSION_VISIBLE)
verify(falsingCollector).onBouncerShown() verify(falsingCollector).onBouncerShown()
verify(mPrimaryBouncerCallbackInteractor).dispatchFullyShown() verify(mPrimaryBouncerCallbackInteractor).dispatchFullyShown()
} }
@@ -155,7 +155,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
fun testExpansion_fullyHidden() { fun testExpansion_fullyHidden() {
`when`(repository.panelExpansionAmount.value).thenReturn(0.5f) `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null) `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_HIDDEN) underTest.setPanelExpansion(EXPANSION_HIDDEN)
verify(repository).setPrimaryVisible(false) verify(repository).setPrimaryVisible(false)
verify(repository).setPrimaryShow(null) verify(repository).setPrimaryShow(null)
verify(repository).setPrimaryHide(true) verify(repository).setPrimaryHide(true)
@@ -167,7 +167,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test @Test
fun testExpansion_startingToHide() { fun testExpansion_startingToHide() {
`when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE) `when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
mPrimaryBouncerInteractor.setPanelExpansion(0.1f) underTest.setPanelExpansion(0.1f)
verify(repository).setPrimaryStartingToHide(true) verify(repository).setPrimaryStartingToHide(true)
verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToHide() verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToHide()
} }
@@ -175,7 +175,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Test @Test
fun testShowMessage() { fun testShowMessage() {
val argCaptor = ArgumentCaptor.forClass(BouncerShowMessageModel::class.java) val argCaptor = ArgumentCaptor.forClass(BouncerShowMessageModel::class.java)
mPrimaryBouncerInteractor.showMessage("abc", null) underTest.showMessage("abc", null)
verify(repository).setShowMessage(argCaptor.capture()) verify(repository).setShowMessage(argCaptor.capture())
assertThat(argCaptor.value.message).isEqualTo("abc") assertThat(argCaptor.value.message).isEqualTo("abc")
} }
@@ -184,62 +184,62 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
fun testDismissAction() { fun testDismissAction() {
val onDismissAction = mock(ActivityStarter.OnDismissAction::class.java) val onDismissAction = mock(ActivityStarter.OnDismissAction::class.java)
val cancelAction = mock(Runnable::class.java) val cancelAction = mock(Runnable::class.java)
mPrimaryBouncerInteractor.setDismissAction(onDismissAction, cancelAction) underTest.setDismissAction(onDismissAction, cancelAction)
verify(bouncerViewDelegate).setDismissAction(onDismissAction, cancelAction) verify(bouncerViewDelegate).setDismissAction(onDismissAction, cancelAction)
} }
@Test @Test
fun testUpdateResources() { fun testUpdateResources() {
mPrimaryBouncerInteractor.updateResources() underTest.updateResources()
verify(repository).setResourceUpdateRequests(true) verify(repository).setResourceUpdateRequests(true)
} }
@Test @Test
fun testNotifyKeyguardAuthenticated() { fun testNotifyKeyguardAuthenticated() {
mPrimaryBouncerInteractor.notifyKeyguardAuthenticated(true) underTest.notifyKeyguardAuthenticated(true)
verify(repository).setKeyguardAuthenticated(true) verify(repository).setKeyguardAuthenticated(true)
} }
@Test @Test
fun testNotifyShowedMessage() { fun testNotifyShowedMessage() {
mPrimaryBouncerInteractor.onMessageShown() underTest.onMessageShown()
verify(repository).setShowMessage(null) verify(repository).setShowMessage(null)
} }
@Test @Test
fun testOnScreenTurnedOff() { fun testOnScreenTurnedOff() {
mPrimaryBouncerInteractor.onScreenTurnedOff() underTest.onScreenTurnedOff()
verify(repository).setOnScreenTurnedOff(true) verify(repository).setOnScreenTurnedOff(true)
} }
@Test @Test
fun testSetKeyguardPosition() { fun testSetKeyguardPosition() {
mPrimaryBouncerInteractor.setKeyguardPosition(0f) underTest.setKeyguardPosition(0f)
verify(repository).setKeyguardPosition(0f) verify(repository).setKeyguardPosition(0f)
} }
@Test @Test
fun testNotifyKeyguardAuthenticatedHandled() { fun testNotifyKeyguardAuthenticatedHandled() {
mPrimaryBouncerInteractor.notifyKeyguardAuthenticatedHandled() underTest.notifyKeyguardAuthenticatedHandled()
verify(repository).setKeyguardAuthenticated(null) verify(repository).setKeyguardAuthenticated(null)
} }
@Test @Test
fun testNotifyUpdatedResources() { fun testNotifyUpdatedResources() {
mPrimaryBouncerInteractor.notifyUpdatedResources() underTest.notifyUpdatedResources()
verify(repository).setResourceUpdateRequests(false) verify(repository).setResourceUpdateRequests(false)
} }
@Test @Test
fun testSetBackButtonEnabled() { fun testSetBackButtonEnabled() {
mPrimaryBouncerInteractor.setBackButtonEnabled(true) underTest.setBackButtonEnabled(true)
verify(repository).setIsBackButtonEnabled(true) verify(repository).setIsBackButtonEnabled(true)
} }
@Test @Test
fun testStartDisappearAnimation() { fun testStartDisappearAnimation() {
val runnable = mock(Runnable::class.java) val runnable = mock(Runnable::class.java)
mPrimaryBouncerInteractor.startDisappearAnimation(runnable) underTest.startDisappearAnimation(runnable)
verify(repository).setPrimaryStartDisappearAnimation(any(Runnable::class.java)) verify(repository).setPrimaryStartDisappearAnimation(any(Runnable::class.java))
} }
@@ -248,42 +248,42 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
`when`(repository.primaryBouncerVisible.value).thenReturn(true) `when`(repository.primaryBouncerVisible.value).thenReturn(true)
`when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE) `when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null) `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
assertThat(mPrimaryBouncerInteractor.isFullyShowing()).isTrue() assertThat(underTest.isFullyShowing()).isTrue()
`when`(repository.primaryBouncerVisible.value).thenReturn(false) `when`(repository.primaryBouncerVisible.value).thenReturn(false)
assertThat(mPrimaryBouncerInteractor.isFullyShowing()).isFalse() assertThat(underTest.isFullyShowing()).isFalse()
} }
@Test @Test
fun testIsScrimmed() { fun testIsScrimmed() {
`when`(repository.primaryBouncerScrimmed.value).thenReturn(true) `when`(repository.primaryBouncerScrimmed.value).thenReturn(true)
assertThat(mPrimaryBouncerInteractor.isScrimmed()).isTrue() assertThat(underTest.isScrimmed()).isTrue()
`when`(repository.primaryBouncerScrimmed.value).thenReturn(false) `when`(repository.primaryBouncerScrimmed.value).thenReturn(false)
assertThat(mPrimaryBouncerInteractor.isScrimmed()).isFalse() assertThat(underTest.isScrimmed()).isFalse()
} }
@Test @Test
fun testIsInTransit() { fun testIsInTransit() {
`when`(repository.primaryBouncerShowingSoon.value).thenReturn(true) `when`(repository.primaryBouncerShowingSoon.value).thenReturn(true)
assertThat(mPrimaryBouncerInteractor.isInTransit()).isTrue() assertThat(underTest.isInTransit()).isTrue()
`when`(repository.primaryBouncerShowingSoon.value).thenReturn(false) `when`(repository.primaryBouncerShowingSoon.value).thenReturn(false)
assertThat(mPrimaryBouncerInteractor.isInTransit()).isFalse() assertThat(underTest.isInTransit()).isFalse()
`when`(repository.panelExpansionAmount.value).thenReturn(0.5f) `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
assertThat(mPrimaryBouncerInteractor.isInTransit()).isTrue() assertThat(underTest.isInTransit()).isTrue()
} }
@Test @Test
fun testIsAnimatingAway() { fun testIsAnimatingAway() {
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(Runnable {}) `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(Runnable {})
assertThat(mPrimaryBouncerInteractor.isAnimatingAway()).isTrue() assertThat(underTest.isAnimatingAway()).isTrue()
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null) `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
assertThat(mPrimaryBouncerInteractor.isAnimatingAway()).isFalse() assertThat(underTest.isAnimatingAway()).isFalse()
} }
@Test @Test
fun testWillDismissWithAction() { fun testWillDismissWithAction() {
`when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(true) `when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(true)
assertThat(mPrimaryBouncerInteractor.willDismissWithAction()).isTrue() assertThat(underTest.willDismissWithAction()).isTrue()
`when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(false) `when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(false)
assertThat(mPrimaryBouncerInteractor.willDismissWithAction()).isFalse() assertThat(underTest.willDismissWithAction()).isFalse()
} }
} }

View File

@@ -0,0 +1,112 @@
/*
* 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.interactor
import android.os.Looper
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(JUnit4::class)
class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
private lateinit var repository: FakeKeyguardBouncerRepository
@Mock private lateinit var bouncerView: BouncerView
@Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
@Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
@Mock private lateinit var falsingCollector: FalsingCollector
@Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
@Mock private lateinit var keyguardBypassController: KeyguardBypassController
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private val mainHandler = FakeHandler(Looper.getMainLooper())
private lateinit var underTest: PrimaryBouncerInteractor
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
repository = FakeKeyguardBouncerRepository()
underTest =
PrimaryBouncerInteractor(
repository,
bouncerView,
mainHandler,
keyguardStateController,
keyguardSecurityModel,
primaryBouncerCallbackInteractor,
falsingCollector,
dismissCallbackRegistry,
keyguardBypassController,
keyguardUpdateMonitor,
)
}
@Test
fun notInteractableWhenExpansionIsBelow90Percent() = runTest {
val isInteractable = collectLastValue(underTest.isInteractable)
repository.setPrimaryVisible(true)
repository.setPanelExpansion(0.15f)
assertThat(isInteractable()).isFalse()
}
@Test
fun notInteractableWhenExpansionAbove90PercentButNotVisible() = runTest {
val isInteractable = collectLastValue(underTest.isInteractable)
repository.setPrimaryVisible(false)
repository.setPanelExpansion(0.05f)
assertThat(isInteractable()).isFalse()
}
@Test
fun isInteractableWhenExpansionAbove90PercentAndVisible() = runTest {
var isInteractable = collectLastValue(underTest.isInteractable)
repository.setPrimaryVisible(true)
repository.setPanelExpansion(0.09f)
assertThat(isInteractable()).isTrue()
repository.setPanelExpansion(0.12f)
assertThat(isInteractable()).isFalse()
repository.setPanelExpansion(0f)
assertThat(isInteractable()).isTrue()
}
}

View File

@@ -0,0 +1,128 @@
/*
* 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.data.repository
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Fake implementation of [KeyguardRepository] */
class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
private val _primaryBouncerVisible = MutableStateFlow(false)
override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
private val _primaryBouncerShowingSoon = MutableStateFlow(false)
override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
private val _primaryBouncerHide = MutableStateFlow(false)
override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
private val _primaryBouncerStartingToHide = MutableStateFlow(false)
override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
override val primaryBouncerStartingDisappearAnimation =
_primaryBouncerDisappearAnimation.asStateFlow()
private val _primaryBouncerScrimmed = MutableStateFlow(false)
override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
override val keyguardPosition = _keyguardPosition.asStateFlow()
private val _onScreenTurnedOff = MutableStateFlow(false)
override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
override val showMessage = _showMessage.asStateFlow()
private val _resourceUpdateRequests = MutableStateFlow(false)
override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
override val bouncerPromptReason = 0
override val bouncerErrorMessage: CharSequence? = null
private val _isAlternateBouncerVisible = MutableStateFlow(false)
override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
override var lastAlternateBouncerVisibleTime: Long = 0L
private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
override val isAlternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
override fun setPrimaryScrimmed(isScrimmed: Boolean) {
_primaryBouncerScrimmed.value = isScrimmed
}
override fun setPrimaryVisible(isVisible: Boolean) {
_primaryBouncerVisible.value = isVisible
}
override fun setAlternateVisible(isVisible: Boolean) {
_isAlternateBouncerVisible.value = isVisible
}
override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
_isAlternateBouncerUIAvailable.value = isAvailable
}
override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
_primaryBouncerShow.value = keyguardBouncerModel
}
override fun setPrimaryShowingSoon(showingSoon: Boolean) {
_primaryBouncerShowingSoon.value = showingSoon
}
override fun setPrimaryHide(hide: Boolean) {
_primaryBouncerHide.value = hide
}
override fun setPrimaryStartingToHide(startingToHide: Boolean) {
_primaryBouncerStartingToHide.value = startingToHide
}
override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
_primaryBouncerDisappearAnimation.value = runnable
}
override fun setPanelExpansion(panelExpansion: Float) {
_panelExpansionAmount.value = panelExpansion
}
override fun setKeyguardPosition(keyguardPosition: Float) {
_keyguardPosition.value = keyguardPosition
}
override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
_resourceUpdateRequests.value = willUpdateResources
}
override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
_showMessage.value = bouncerShowMessageModel
}
override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
_keyguardAuthenticated.value = keyguardAuthenticated
}
override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
_isBackButtonEnabled.value = isBackButtonEnabled
}
override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
_onScreenTurnedOff.value = onScreenTurnedOff
}
}