diff options
| author | 2024-01-30 13:29:39 +0000 | |
|---|---|---|
| committer | 2024-01-30 13:29:39 +0000 | |
| commit | 3cec4a195ff54c4ca115b4cf2edd41be7a417676 (patch) | |
| tree | 26bb857b19ab6c8e645ac3932e2220c80e535d7f | |
| parent | 9d6a9b7fea8d29dd59794e8c04d0357d08b90db1 (diff) | |
| parent | c82878ee820ef4b538195d97e8711813dc0aba2e (diff) | |
Merge "Only register for face auth lift gesture when device is interactive" into main
15 files changed, 488 insertions, 153 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/binder/LiftToRunFaceAuthBinderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/binder/LiftToRunFaceAuthBinderTest.kt new file mode 100644 index 000000000000..e9e85c9f210b --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/binder/LiftToRunFaceAuthBinderTest.kt @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2024 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.deviceentry.domain.ui.binder + +import android.content.packageManager +import android.content.pm.PackageManager +import android.hardware.Sensor +import android.hardware.TriggerEventListener +import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository +import com.android.systemui.deviceentry.ui.binder.liftToRunFaceAuthBinder +import com.android.systemui.keyguard.data.repository.biometricSettingsRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository +import com.android.systemui.kosmos.testScope +import com.android.systemui.power.data.repository.fakePowerRepository +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.capture +import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.sensors.asyncSensorManager +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.clearInvocations +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@ExperimentalCoroutinesApi +@SmallTest +@RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class LiftToRunFaceAuthBinderTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val sensorManager = kosmos.asyncSensorManager + private val powerRepository = kosmos.fakePowerRepository + private val keyguardRepository = kosmos.fakeKeyguardRepository + private val bouncerRepository = kosmos.keyguardBouncerRepository + private val biometricSettingsRepository = kosmos.biometricSettingsRepository + private val packageManager = kosmos.packageManager + + @Captor private lateinit var triggerEventListenerCaptor: ArgumentCaptor<TriggerEventListener> + @Mock private lateinit var mockSensor: Sensor + + private val underTest = kosmos.liftToRunFaceAuthBinder + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true) + whenever(sensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)).thenReturn(mockSensor) + } + + @Test + fun doNotListenForGesture() = + testScope.runTest { + start() + verifyNeverRequestsTriggerSensor() + } + + @Test + fun awakeKeyguard_listenForGesture() = + testScope.runTest { + start() + givenAwakeKeyguard(true) + runCurrent() + verifyRequestTriggerSensor() + } + + @Test + fun faceNotEnrolled_listenForGesture() = + testScope.runTest { + start() + givenAwakeKeyguard(true) + biometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(false) + runCurrent() + verifyNeverRequestsTriggerSensor() + } + + @Test + fun notInteractive_doNotListenForGesture() = + testScope.runTest { + start() + givenAwakeKeyguard(true) + powerRepository.setInteractive(false) + runCurrent() + verifyNeverRequestsTriggerSensor() + } + + @Test + fun primaryBouncer_listenForGesture() = + testScope.runTest { + start() + givenAwakeKeyguard(false) + givenPrimaryBouncerShowing() + runCurrent() + verifyRequestTriggerSensor() + } + + @Test + fun alternateBouncer_listenForGesture() = + testScope.runTest { + start() + givenAwakeKeyguard(false) + givenAlternateBouncerShowing() + runCurrent() + verifyRequestTriggerSensor() + } + + @Test + fun restartListeningForGestureAfterSensorTrigger() = + testScope.runTest { + start() + givenAwakeKeyguard(true) + runCurrent() + verifyRequestTriggerSensor() + clearInvocations(sensorManager) + + triggerEventListenerCaptor.value.onTrigger(null) + runCurrent() + verifyRequestTriggerSensor() + } + + @Test + fun cancelTriggerSensor_keyguardNotAwakeAnymore() = + testScope.runTest { + start() + givenAwakeKeyguard(true) + runCurrent() + verifyRequestTriggerSensor() + + givenAwakeKeyguard(false) + runCurrent() + verifyCancelTriggerSensor() + } + + private fun start() { + underTest.start() + biometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true) + givenAwakeKeyguard(false) + givenBouncerNotShowing() + } + + private fun givenAwakeKeyguard(isAwake: Boolean) { + powerRepository.setInteractive(isAwake) + keyguardRepository.setKeyguardShowing(isAwake) + keyguardRepository.setKeyguardOccluded(false) + } + + private fun givenPrimaryBouncerShowing() { + bouncerRepository.setPrimaryShow(true) + bouncerRepository.setAlternateVisible(false) + } + + private fun givenBouncerNotShowing() { + bouncerRepository.setPrimaryShow(false) + bouncerRepository.setAlternateVisible(false) + } + + private fun givenAlternateBouncerShowing() { + bouncerRepository.setPrimaryShow(false) + bouncerRepository.setAlternateVisible(true) + } + + private fun verifyRequestTriggerSensor() { + verify(sensorManager).requestTriggerSensor(capture(triggerEventListenerCaptor), any()) + } + + private fun verifyNeverRequestsTriggerSensor() { + verify(sensorManager, never()).requestTriggerSensor(any(), any()) + } + + private fun verifyCancelTriggerSensor() { + verify(sensorManager).cancelTriggerSensor(any(), any()) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt index 30ac34402ffd..6fc5be1e376d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt @@ -19,7 +19,7 @@ package com.android.systemui.keyguard.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor import com.android.systemui.coroutines.collectValues import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic @@ -52,11 +52,9 @@ class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() { val testScope = kosmos.testScope val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository - val primaryBouncerInteractor = kosmos.primaryBouncerInteractor + val primaryBouncerInteractor = kosmos.mockPrimaryBouncerInteractor val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController - val underTest by lazy { - kosmos.primaryBouncerToGoneTransitionViewModel - } + val underTest by lazy { kosmos.primaryBouncerToGoneTransitionViewModel } @Before fun setUp() { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt index 817087955971..9504cfcdbe3c 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt @@ -51,7 +51,6 @@ import com.android.systemui.shortcut.ShortcutKeyDispatcher import com.android.systemui.statusbar.ImmersiveModeConfirmation import com.android.systemui.statusbar.gesture.GesturePointerEventListener import com.android.systemui.statusbar.notification.InstantAppNotifier -import com.android.systemui.statusbar.phone.KeyguardLiftController import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.phone.StatusBarHeadsUpChangeListener import com.android.systemui.stylus.StylusUsiPowerStartable @@ -225,12 +224,6 @@ abstract class SystemUICoreStartableModule { @ClassKey(WMShell::class) abstract fun bindWMShell(sysui: WMShell): CoreStartable - /** Inject into KeyguardLiftController. */ - @Binds - @IntoMap - @ClassKey(KeyguardLiftController::class) - abstract fun bindKeyguardLiftController(sysui: KeyguardLiftController): CoreStartable - /** Inject into MediaTttSenderCoordinator. */ @Binds @IntoMap diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/LiftToRunFaceAuthBinder.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/LiftToRunFaceAuthBinder.kt new file mode 100644 index 000000000000..1fd7d009cee4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/LiftToRunFaceAuthBinder.kt @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2024 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.deviceentry.ui.binder + +import android.content.pm.PackageManager +import android.hardware.Sensor +import android.hardware.TriggerEvent +import android.hardware.TriggerEventListener +import com.android.keyguard.ActiveUnlockConfig +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.CoreStartable +import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.util.Assert +import com.android.systemui.util.sensors.AsyncSensorManager +import java.io.PrintWriter +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filterNot +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch + +/** + * Triggers face auth and active unlock on lift when the device is showing the lock screen or + * bouncer. Only initialized if face auth is supported on the device. Not to be confused with the + * lift to wake gesture which is handled by {@link com.android.server.policy.PhoneWindowManager}. + */ +@SysUISingleton +class LiftToRunFaceAuthBinder +@Inject +constructor( + @Application private val scope: CoroutineScope, + private val packageManager: PackageManager, + private val asyncSensorManager: AsyncSensorManager, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + keyguardInteractor: KeyguardInteractor, + primaryBouncerInteractor: PrimaryBouncerInteractor, + alternateBouncerInteractor: AlternateBouncerInteractor, + private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor, + powerInteractor: PowerInteractor, +) : CoreStartable { + + private var pickupSensor: Sensor? = null + private val isListening: MutableStateFlow<Boolean> = MutableStateFlow(false) + private val stoppedListening: Flow<Unit> = isListening.filterNot { it }.map {} // map to Unit + + private val onAwakeKeyguard: Flow<Boolean> = + combine( + powerInteractor.isInteractive, + keyguardInteractor.isKeyguardVisible, + ) { isInteractive, isKeyguardVisible -> + isInteractive && isKeyguardVisible + } + private val bouncerShowing: Flow<Boolean> = + combine( + primaryBouncerInteractor.isShowing, + alternateBouncerInteractor.isVisible, + ) { primaryBouncerShowing, alternateBouncerShowing -> + primaryBouncerShowing || alternateBouncerShowing + } + private val listenForPickupSensor: Flow<Boolean> = + combine( + stoppedListening, + bouncerShowing, + onAwakeKeyguard, + ) { _, bouncerShowing, onAwakeKeyguard -> + (onAwakeKeyguard || bouncerShowing) && + deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled() + } + + override fun start() { + if (packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) { + init() + } + } + + private fun init() { + pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE) + scope.launch { + listenForPickupSensor.collect { listenForPickupSensor -> + updateListeningState(listenForPickupSensor) + } + } + } + + private val listener: TriggerEventListener = + object : TriggerEventListener() { + override fun onTrigger(event: TriggerEvent?) { + Assert.isMainThread() + deviceEntryFaceAuthInteractor.onDeviceLifted() + keyguardUpdateMonitor.requestActiveUnlock( + ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE, + "KeyguardLiftController" + ) + + // Not listening anymore since trigger events unregister themselves + isListening.value = false + } + } + + override fun dump(pw: PrintWriter, args: Array<out String>) { + pw.println("LiftToRunFaceAuthBinder:") + pw.println(" pickupSensor: $pickupSensor") + pw.println(" isListening: ${isListening.value}") + } + + private fun updateListeningState(shouldListen: Boolean) { + if (pickupSensor == null) { + return + } + if (shouldListen != isListening.value) { + isListening.value = shouldListen + + if (shouldListen) { + asyncSensorManager.requestTriggerSensor(listener, pickupSensor) + } else { + asyncSensorManager.cancelTriggerSensor(listener, pickupSensor) + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index 13e38358477a..e16f8dcbb00e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -51,7 +51,7 @@ import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.WindowManagerLockscreenVisibilityManager; import com.android.systemui.keyguard.data.quickaffordance.KeyguardDataQuickAffordanceModule; -import com.android.systemui.keyguard.data.repository.KeyguardFaceAuthModule; +import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthModule; import com.android.systemui.keyguard.data.repository.KeyguardRepositoryModule; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule; @@ -104,7 +104,7 @@ import kotlinx.coroutines.CoroutineDispatcher; FalsingModule.class, KeyguardDataQuickAffordanceModule.class, KeyguardRepositoryModule.class, - KeyguardFaceAuthModule.class, + DeviceEntryFaceAuthModule.class, KeyguardDisplayModule.class, StartKeyguardTransitionModule.class, ResourceTrimmerModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt index fede47957a7b..4cd544ff658e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt @@ -23,6 +23,7 @@ import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepos import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepositoryImpl import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor +import com.android.systemui.deviceentry.ui.binder.LiftToRunFaceAuthBinder import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory import dagger.Binds @@ -32,7 +33,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -interface KeyguardFaceAuthModule { +interface DeviceEntryFaceAuthModule { @Binds fun deviceEntryFaceAuthRepository( impl: DeviceEntryFaceAuthRepositoryImpl @@ -41,13 +42,20 @@ interface KeyguardFaceAuthModule { @Binds @IntoMap @ClassKey(SystemUIDeviceEntryFaceAuthInteractor::class) - fun bind(impl: SystemUIDeviceEntryFaceAuthInteractor): CoreStartable + fun bindSystemUIDeviceEntryFaceAuthInteractor( + impl: SystemUIDeviceEntryFaceAuthInteractor + ): CoreStartable @Binds fun keyguardFaceAuthInteractor( impl: SystemUIDeviceEntryFaceAuthInteractor ): DeviceEntryFaceAuthInteractor + @Binds + @IntoMap + @ClassKey(LiftToRunFaceAuthBinder::class) + fun bindLiftToRunFaceAuthBinder(impl: LiftToRunFaceAuthBinder): CoreStartable + companion object { @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt deleted file mode 100644 index 9f0863385ca1..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2019 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.phone - -import android.content.Context -import android.content.pm.PackageManager -import android.hardware.Sensor -import android.hardware.TriggerEvent -import android.hardware.TriggerEventListener -import com.android.keyguard.ActiveUnlockConfig -import com.android.keyguard.KeyguardUpdateMonitor -import com.android.keyguard.KeyguardUpdateMonitorCallback -import com.android.systemui.CoreStartable -import com.android.systemui.Dumpable -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dump.DumpManager -import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor -import com.android.systemui.plugins.statusbar.StatusBarStateController -import com.android.systemui.user.domain.interactor.SelectedUserInteractor -import com.android.systemui.util.Assert -import com.android.systemui.util.sensors.AsyncSensorManager -import java.io.PrintWriter -import javax.inject.Inject - -/** - * Triggers face auth on lift when the device is showing the lock screen. Only initialized - * if face auth is supported on the device. Not to be confused with the lift to wake gesture - * which is handled by {@link com.android.server.policy.PhoneWindowManager}. - */ -@SysUISingleton -class KeyguardLiftController @Inject constructor( - private val context: Context, - private val statusBarStateController: StatusBarStateController, - private val asyncSensorManager: AsyncSensorManager, - private val keyguardUpdateMonitor: KeyguardUpdateMonitor, - private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor, - private val dumpManager: DumpManager, - private val selectedUserInteractor: SelectedUserInteractor, -) : Dumpable, CoreStartable { - - private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE) - private var isListening = false - private var bouncerVisible = false - - override fun start() { - if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) { - init() - } - } - - private fun init() { - dumpManager.registerDumpable(this) - statusBarStateController.addCallback(statusBarStateListener) - keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) - updateListeningState() - } - - private val listener: TriggerEventListener = object : TriggerEventListener() { - override fun onTrigger(event: TriggerEvent?) { - Assert.isMainThread() - // Not listening anymore since trigger events unregister themselves - isListening = false - updateListeningState() - deviceEntryFaceAuthInteractor.onDeviceLifted() - keyguardUpdateMonitor.requestActiveUnlock( - ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE, - "KeyguardLiftController") - } - } - - private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { - override fun onKeyguardBouncerFullyShowingChanged(bouncer: Boolean) { - bouncerVisible = bouncer - updateListeningState() - } - - override fun onKeyguardVisibilityChanged(visible: Boolean) { - updateListeningState() - } - } - - private val statusBarStateListener = object : StatusBarStateController.StateListener { - override fun onDozingChanged(isDozing: Boolean) { - updateListeningState() - } - } - - override fun dump(pw: PrintWriter, args: Array<out String>) { - pw.println("KeyguardLiftController:") - pw.println(" pickupSensor: $pickupSensor") - pw.println(" isListening: $isListening") - pw.println(" bouncerVisible: $bouncerVisible") - } - - private fun updateListeningState() { - if (pickupSensor == null) { - return - } - val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible && - !statusBarStateController.isDozing - - val isFaceEnabled = deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled() - val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled - if (shouldListen != isListening) { - isListening = shouldListen - - if (shouldListen) { - asyncSensorManager.requestTriggerSensor(listener, pickupSensor) - } else { - asyncSensorManager.cancelTriggerSensor(listener, pickupSensor) - } - } - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt index 75994da6c934..ad2ae8b41af9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt @@ -19,7 +19,7 @@ package com.android.systemui.keyguard.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor import com.android.systemui.coroutines.collectValues import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic @@ -65,7 +65,7 @@ class BouncerToGoneFlowsTest : SysuiTestCase() { private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository private val shadeRepository = kosmos.shadeRepository private val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController - private val primaryBouncerInteractor = kosmos.primaryBouncerInteractor + private val primaryBouncerInteractor = kosmos.mockPrimaryBouncerInteractor private val underTest = kosmos.bouncerToGoneFlows @Before diff --git a/packages/SystemUI/tests/utils/src/android/content/PackageManagerKosmos.kt b/packages/SystemUI/tests/utils/src/android/content/PackageManagerKosmos.kt new file mode 100644 index 000000000000..8901314d8e76 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/android/content/PackageManagerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 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 android.content + +import android.content.pm.PackageManager +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +val Kosmos.packageManager by Kosmos.Fixture { mock<PackageManager>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorKosmos.kt index 06b6cda62806..244ef8d81ebd 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorKosmos.kt @@ -16,7 +16,40 @@ package com.android.systemui.bouncer.domain.interactor +import android.content.applicationContext +import com.android.keyguard.keyguardSecurityModel +import com.android.keyguard.keyguardUpdateMonitor +import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository +import com.android.systemui.bouncer.ui.BouncerView +import com.android.systemui.classifier.falsingCollector +import com.android.systemui.concurrency.fakeExecutor +import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor +import com.android.systemui.keyguard.DismissCallbackRegistry +import com.android.systemui.keyguard.data.repository.trustRepository import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.statusbar.policy.KeyguardStateControllerImpl +import com.android.systemui.user.domain.interactor.selectedUserInteractor +import com.android.systemui.util.concurrency.mockExecutorHandler import com.android.systemui.util.mockito.mock -var Kosmos.primaryBouncerInteractor by Kosmos.Fixture { mock<PrimaryBouncerInteractor>() } +var Kosmos.mockPrimaryBouncerInteractor by Kosmos.Fixture { mock<PrimaryBouncerInteractor>() } +var Kosmos.primaryBouncerInteractor by + Kosmos.Fixture { + PrimaryBouncerInteractor( + repository = keyguardBouncerRepository, + primaryBouncerView = mock<BouncerView>(), + mainHandler = mockExecutorHandler(executor = fakeExecutor), + keyguardStateController = mock<KeyguardStateControllerImpl>(), + keyguardSecurityModel = keyguardSecurityModel, + primaryBouncerCallbackInteractor = mock<PrimaryBouncerCallbackInteractor>(), + falsingCollector = falsingCollector, + dismissCallbackRegistry = mock<DismissCallbackRegistry>(), + context = applicationContext, + keyguardUpdateMonitor = keyguardUpdateMonitor, + trustRepository = trustRepository, + applicationScope = applicationCoroutineScope, + selectedUserInteractor = selectedUserInteractor, + deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt index 0b1fb4074226..5575b05b3874 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt @@ -23,7 +23,7 @@ import com.android.keyguard.keyguardUpdateMonitor import com.android.keyguard.trustManager import com.android.systemui.biometrics.data.repository.facePropertyRepository import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor -import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor import com.android.systemui.deviceentry.data.repository.faceWakeUpTriggersConfig import com.android.systemui.keyguard.data.repository.biometricSettingsRepository import com.android.systemui.keyguard.data.repository.deviceEntryFaceAuthRepository @@ -46,7 +46,7 @@ val Kosmos.deviceEntryFaceAuthInteractor by applicationScope = applicationCoroutineScope, mainDispatcher = testDispatcher, repository = deviceEntryFaceAuthRepository, - primaryBouncerInteractor = { primaryBouncerInteractor }, + primaryBouncerInteractor = { mockPrimaryBouncerInteractor }, alternateBouncerInteractor = alternateBouncerInteractor, keyguardTransitionInteractor = keyguardTransitionInteractor, faceAuthenticationLogger = faceAuthLogger, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/ui/binder/LiftToRunFaceAuthBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/ui/binder/LiftToRunFaceAuthBinderKosmos.kt new file mode 100644 index 000000000000..2fead91b430a --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/ui/binder/LiftToRunFaceAuthBinderKosmos.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 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.deviceentry.ui.binder + +import android.content.packageManager +import com.android.keyguard.keyguardUpdateMonitor +import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.util.sensors.asyncSensorManager +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.liftToRunFaceAuthBinder by + Kosmos.Fixture { + LiftToRunFaceAuthBinder( + scope = applicationCoroutineScope, + packageManager = packageManager, + asyncSensorManager = asyncSensorManager, + keyguardUpdateMonitor = keyguardUpdateMonitor, + keyguardInteractor = keyguardInteractor, + primaryBouncerInteractor = primaryBouncerInteractor, + alternateBouncerInteractor = alternateBouncerInteractor, + deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor, + powerInteractor = powerInteractor, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt index c71c1c3ea5f0..ffa4133c7269 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt @@ -18,7 +18,7 @@ package com.android.systemui.keyguard.ui.viewmodel -import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos @@ -31,7 +31,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.bouncerToGoneFlows by Fixture { BouncerToGoneFlows( statusBarStateController = sysuiStatusBarStateController, - primaryBouncerInteractor = primaryBouncerInteractor, + primaryBouncerInteractor = mockPrimaryBouncerInteractor, keyguardDismissActionInteractor = mock(), featureFlags = featureFlagsClassic, shadeInteractor = shadeInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt index ab28d0d670ef..4ecff73f71ed 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt @@ -18,7 +18,7 @@ package com.android.systemui.keyguard.ui.viewmodel -import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos @@ -30,7 +30,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.primaryBouncerToGoneTransitionViewModel by Fixture { PrimaryBouncerToGoneTransitionViewModel( statusBarStateController = sysuiStatusBarStateController, - primaryBouncerInteractor = primaryBouncerInteractor, + primaryBouncerInteractor = mockPrimaryBouncerInteractor, keyguardDismissActionInteractor = mock(), featureFlags = featureFlagsClassic, bouncerToGoneFlows = bouncerToGoneFlows, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/sensors/AsyncSensorManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/sensors/AsyncSensorManagerKosmos.kt new file mode 100644 index 000000000000..117ae8c46d3c --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/sensors/AsyncSensorManagerKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 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.util.sensors + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +val Kosmos.asyncSensorManager by Kosmos.Fixture { mock<AsyncSensorManager>() } |