From affa8137c1f08a9a04fbef8595ff180d74db1d61 Mon Sep 17 00:00:00 2001 From: Grace Cheng Date: Mon, 14 Aug 2023 21:19:04 +0000 Subject: Fix missing BP icon Bind SFPS BiometricPrompt iconView to ViewModel, introduce BiometricSensorPropertiesInteractor for accessing FingerprintPropertyRepository, fix initial BiometricState and state after device rotation, and rename ViewModel and ViewBinder files to match BP refactor Fixes: 286983554 Test: (manual) Observe BP icon is visible and plays animation upon opening and after device rotations Test: atest AuthContainerViewTest Test: atest AuthControllerTest Test: atest PromptFingerprintIconViewModelTest Test: atest PromptViewModelTest Change-Id: Id51e8bfa15b2db929499a46437d0a8c77405435f --- .../systemui/biometrics/AuthContainerView.java | 21 +---- .../systemui/biometrics/AuthController.java | 11 +-- .../domain/interactor/PromptSelectorInteractor.kt | 10 +++ .../AuthBiometricFingerprintIconViewBinder.kt | 47 ----------- .../binder/AuthBiometricFingerprintViewBinder.kt | 34 -------- .../biometrics/ui/binder/BiometricViewBinder.kt | 3 + .../ui/binder/PromptFingerprintIconViewBinder.kt | 50 +++++++++++ .../viewmodel/AuthBiometricFingerprintViewModel.kt | 84 ------------------- .../ui/viewmodel/PromptFingerprintIconViewModel.kt | 96 ++++++++++++++++++++++ .../biometrics/ui/viewmodel/PromptViewModel.kt | 39 ++++++--- .../systemui/biometrics/AuthContainerViewTest.kt | 17 ++-- .../systemui/biometrics/AuthControllerTest.java | 12 +-- .../interactor/PromptSelectorInteractorImplTest.kt | 5 +- .../AuthBiometricFingerprintViewModelTest.kt | 70 ---------------- .../PromptFingerprintIconViewModelTest.kt | 94 +++++++++++++++++++++ .../biometrics/ui/viewmodel/PromptViewModelTest.kt | 23 +++++- 16 files changed, 323 insertions(+), 293 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintIconViewBinder.kt delete mode 100644 packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt create mode 100644 packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptFingerprintIconViewBinder.kt delete mode 100644 packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModel.kt create mode 100644 packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 58c8000a2328..802a550c4d29 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -73,9 +73,7 @@ import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteracto import com.android.systemui.biometrics.domain.model.BiometricModalities; import com.android.systemui.biometrics.ui.BiometricPromptLayout; import com.android.systemui.biometrics.ui.CredentialView; -import com.android.systemui.biometrics.ui.binder.AuthBiometricFingerprintViewBinder; import com.android.systemui.biometrics.ui.binder.BiometricViewBinder; -import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel; import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel; import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel; import com.android.systemui.dagger.qualifiers.Background; @@ -142,8 +140,6 @@ public class AuthContainerView extends LinearLayout // TODO: these should be migrated out once ready private final Provider mPromptCredentialInteractor; - private final Provider - mAuthBiometricFingerprintViewModelProvider; private final @NonNull Provider mPromptSelectorInteractorProvider; // TODO(b/251476085): these should be migrated out of the view private final Provider mCredentialViewModelProvider; @@ -283,8 +279,6 @@ public class AuthContainerView extends LinearLayout @NonNull UserManager userManager, @NonNull LockPatternUtils lockPatternUtils, @NonNull InteractionJankMonitor jankMonitor, - @NonNull Provider - authBiometricFingerprintViewModelProvider, @NonNull Provider promptCredentialInteractor, @NonNull Provider promptSelectorInteractor, @NonNull PromptViewModel promptViewModel, @@ -293,9 +287,9 @@ public class AuthContainerView extends LinearLayout @NonNull VibratorHelper vibratorHelper) { this(config, featureFlags, applicationCoroutineScope, fpProps, faceProps, wakefulnessLifecycle, panelInteractionDetector, userManager, lockPatternUtils, - jankMonitor, authBiometricFingerprintViewModelProvider, promptSelectorInteractor, - promptCredentialInteractor, promptViewModel, credentialViewModelProvider, - new Handler(Looper.getMainLooper()), bgExecutor, vibratorHelper); + jankMonitor, promptSelectorInteractor, promptCredentialInteractor, promptViewModel, + credentialViewModelProvider, new Handler(Looper.getMainLooper()), bgExecutor, + vibratorHelper); } @VisibleForTesting @@ -309,8 +303,6 @@ public class AuthContainerView extends LinearLayout @NonNull UserManager userManager, @NonNull LockPatternUtils lockPatternUtils, @NonNull InteractionJankMonitor jankMonitor, - @NonNull Provider - authBiometricFingerprintViewModelProvider, @NonNull Provider promptSelectorInteractorProvider, @NonNull Provider credentialInteractor, @NonNull PromptViewModel promptViewModel, @@ -359,7 +351,6 @@ public class AuthContainerView extends LinearLayout mBackgroundExecutor = bgExecutor; mInteractionJankMonitor = jankMonitor; mPromptCredentialInteractor = credentialInteractor; - mAuthBiometricFingerprintViewModelProvider = authBiometricFingerprintViewModelProvider; mPromptSelectorInteractorProvider = promptSelectorInteractorProvider; mCredentialViewModelProvider = credentialViewModelProvider; mPromptViewModel = promptViewModel; @@ -442,9 +433,6 @@ public class AuthContainerView extends LinearLayout fingerprintAndFaceView.updateOverrideIconLayoutParamsSize(); fingerprintAndFaceView.setFaceClass3( faceProperties.sensorStrength == STRENGTH_STRONG); - final AuthBiometricFingerprintViewModel fpAndFaceViewModel = - mAuthBiometricFingerprintViewModelProvider.get(); - AuthBiometricFingerprintViewBinder.bind(fingerprintAndFaceView, fpAndFaceViewModel); mBiometricView = fingerprintAndFaceView; } else if (fpProperties != null) { final AuthBiometricFingerprintView fpView = @@ -453,9 +441,6 @@ public class AuthContainerView extends LinearLayout fpView.setSensorProperties(fpProperties); fpView.setScaleFactorProvider(config.mScaleProvider); fpView.updateOverrideIconLayoutParamsSize(); - final AuthBiometricFingerprintViewModel fpViewModel = - mAuthBiometricFingerprintViewModelProvider.get(); - AuthBiometricFingerprintViewBinder.bind(fpView, fpViewModel); mBiometricView = fpView; } else if (faceProperties != null) { mBiometricView = (AuthBiometricFaceView) layoutInflater.inflate( diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 7b288a8d49f1..d5289a49be51 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -73,7 +73,6 @@ import com.android.systemui.CoreStartable; import com.android.systemui.biometrics.domain.interactor.LogContextInteractor; import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor; import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor; -import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel; import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel; import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel; import com.android.systemui.dagger.SysUISingleton; @@ -134,8 +133,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, private final CoroutineScope mApplicationCoroutineScope; // TODO: these should be migrated out once ready - @NonNull private final Provider - mAuthBiometricFingerprintViewModelProvider; @NonNull private final Provider mPromptCredentialInteractor; @NonNull private final Provider mPromptSelectorInteractor; @NonNull private final Provider mCredentialViewModelProvider; @@ -765,8 +762,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, @NonNull LockPatternUtils lockPatternUtils, @NonNull UdfpsLogger udfpsLogger, @NonNull LogContextInteractor logContextInteractor, - @NonNull Provider - authBiometricFingerprintViewModelProvider, @NonNull Provider promptCredentialInteractorProvider, @NonNull Provider promptSelectorInteractorProvider, @NonNull Provider credentialViewModelProvider, @@ -801,7 +796,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, mVibratorHelper = vibratorHelper; mLogContextInteractor = logContextInteractor; - mAuthBiometricFingerprintViewModelProvider = authBiometricFingerprintViewModelProvider; mPromptSelectorInteractor = promptSelectorInteractorProvider; mPromptCredentialInteractor = promptCredentialInteractorProvider; mPromptViewModelProvider = promptViewModelProvider; @@ -1344,9 +1338,8 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, config.mScaleProvider = this::getScaleFactor; return new AuthContainerView(config, mFeatureFlags, mApplicationCoroutineScope, mFpProps, mFaceProps, wakefulnessLifecycle, panelInteractionDetector, userManager, lockPatternUtils, - mInteractionJankMonitor, mAuthBiometricFingerprintViewModelProvider, - mPromptCredentialInteractor, mPromptSelectorInteractor, viewModel, - mCredentialViewModelProvider, bgExecutor, mVibratorHelper); + mInteractionJankMonitor, mPromptCredentialInteractor, mPromptSelectorInteractor, + viewModel, mCredentialViewModelProvider, bgExecutor, mVibratorHelper); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt index bb87dca1cdc4..5badcaf06003 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt @@ -21,15 +21,18 @@ import com.android.internal.widget.LockPatternUtils import com.android.systemui.biometrics.Utils import com.android.systemui.biometrics.Utils.getCredentialType import com.android.systemui.biometrics.Utils.isDeviceCredentialAllowed +import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.PromptRepository import com.android.systemui.biometrics.domain.model.BiometricModalities import com.android.systemui.biometrics.domain.model.BiometricOperationInfo import com.android.systemui.biometrics.domain.model.BiometricPromptRequest import com.android.systemui.biometrics.shared.model.BiometricUserInfo +import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.PromptKind import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map @@ -65,6 +68,9 @@ interface PromptSelectorInteractor { */ val isConfirmationRequired: Flow + /** Fingerprint sensor type */ + val sensorType: StateFlow + /** Use biometrics for authentication. */ fun useBiometricsForAuthentication( promptInfo: PromptInfo, @@ -89,6 +95,7 @@ interface PromptSelectorInteractor { class PromptSelectorInteractorImpl @Inject constructor( + private val fingerprintPropertyRepository: FingerprintPropertyRepository, private val promptRepository: PromptRepository, lockPatternUtils: LockPatternUtils, ) : PromptSelectorInteractor { @@ -140,6 +147,9 @@ constructor( } } + override val sensorType: StateFlow = + fingerprintPropertyRepository.sensorType + override fun useBiometricsForAuthentication( promptInfo: PromptInfo, userId: Int, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintIconViewBinder.kt deleted file mode 100644 index bd0907e588ca..000000000000 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintIconViewBinder.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2023 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.biometrics.ui.binder - -import android.view.DisplayInfo -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.repeatOnLifecycle -import com.airbnb.lottie.LottieAnimationView -import com.android.systemui.biometrics.AuthBiometricFingerprintView -import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel -import com.android.systemui.lifecycle.repeatWhenAttached -import kotlinx.coroutines.launch - -/** Sub-binder for [AuthBiometricFingerprintView.mIconView]. */ -object AuthBiometricFingerprintIconViewBinder { - - /** - * Binds a [AuthBiometricFingerprintView.mIconView] to a [AuthBiometricFingerprintViewModel]. - */ - @JvmStatic - fun bind(view: LottieAnimationView, viewModel: AuthBiometricFingerprintViewModel) { - view.repeatWhenAttached { - repeatOnLifecycle(Lifecycle.State.STARTED) { - val displayInfo = DisplayInfo() - view.context.display?.getDisplayInfo(displayInfo) - viewModel.setRotation(displayInfo.rotation) - viewModel.onConfigurationChanged(view.context.resources.configuration) - launch { viewModel.iconAsset.collect { iconAsset -> view.setAnimation(iconAsset) } } - } - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt deleted file mode 100644 index 9c1bcec2f396..000000000000 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2023 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.biometrics.ui.binder - -import com.android.systemui.biometrics.AuthBiometricFingerprintView -import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel - -object AuthBiometricFingerprintViewBinder { - - /** - * Binds a [AuthBiometricFingerprintView.mIconView] to a [AuthBiometricFingerprintViewModel]. - */ - @JvmStatic - fun bind(view: AuthBiometricFingerprintView, viewModel: AuthBiometricFingerprintViewModel) { - if (view.isSfps) { - AuthBiometricFingerprintIconViewBinder.bind(view.getIconView(), viewModel) - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt index d054751b760b..b1439fd7421d 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt @@ -108,6 +108,9 @@ object BiometricViewBinder { val iconViewOverlay = view.requireViewById(R.id.biometric_icon_overlay) val iconView = view.requireViewById(R.id.biometric_icon) + + PromptFingerprintIconViewBinder.bind(iconView, viewModel.fingerprintIconViewModel) + val indicatorMessageView = view.requireViewById(R.id.indicator) // Negative-side (left) buttons diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptFingerprintIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptFingerprintIconViewBinder.kt new file mode 100644 index 000000000000..188c82b52374 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptFingerprintIconViewBinder.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2023 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.biometrics.ui.binder + +import android.view.DisplayInfo +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.repeatOnLifecycle +import com.airbnb.lottie.LottieAnimationView +import com.android.systemui.biometrics.ui.viewmodel.PromptFingerprintIconViewModel +import com.android.systemui.lifecycle.repeatWhenAttached +import kotlinx.coroutines.launch + +/** Sub-binder for [BiometricPromptLayout.iconView]. */ +object PromptFingerprintIconViewBinder { + + /** Binds [BiometricPromptLayout.iconView] to [PromptFingerprintIconViewModel]. */ + @JvmStatic + fun bind(view: LottieAnimationView, viewModel: PromptFingerprintIconViewModel) { + view.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.STARTED) { + val displayInfo = DisplayInfo() + view.context.display?.getDisplayInfo(displayInfo) + viewModel.setRotation(displayInfo.rotation) + viewModel.onConfigurationChanged(view.context.resources.configuration) + launch { + viewModel.iconAsset.collect { iconAsset -> + if (iconAsset != -1) { + view.setAnimation(iconAsset) + } + } + } + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModel.kt deleted file mode 100644 index 617d80cee09d..000000000000 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModel.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2023 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.biometrics.ui.viewmodel - -import android.annotation.RawRes -import android.content.res.Configuration -import android.view.Surface -import com.android.systemui.R -import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine - -/** Models UI of AuthBiometricFingerprintView to support rear display state changes. */ -class AuthBiometricFingerprintViewModel -@Inject -constructor(private val interactor: DisplayStateInteractor) { - /** Current device rotation. */ - private var rotation: Int = Surface.ROTATION_0 - - /** Current AuthBiometricFingerprintView asset. */ - val iconAsset: Flow = - combine(interactor.isFolded, interactor.isInRearDisplayMode) { - isFolded: Boolean, - isInRearDisplayMode: Boolean -> - getSideFpsAnimationAsset(isFolded, isInRearDisplayMode) - } - - @RawRes - private fun getSideFpsAnimationAsset( - isDeviceFolded: Boolean, - isInRearDisplayMode: Boolean, - ): Int = - when (rotation) { - Surface.ROTATION_90 -> - if (isInRearDisplayMode) { - R.raw.biometricprompt_rear_portrait_reverse_base - } else if (isDeviceFolded) { - R.raw.biometricprompt_folded_base_topleft - } else { - R.raw.biometricprompt_portrait_base_topleft - } - Surface.ROTATION_270 -> - if (isInRearDisplayMode) { - R.raw.biometricprompt_rear_portrait_base - } else if (isDeviceFolded) { - R.raw.biometricprompt_folded_base_bottomright - } else { - R.raw.biometricprompt_portrait_base_bottomright - } - else -> - if (isInRearDisplayMode) { - R.raw.biometricprompt_rear_landscape_base - } else if (isDeviceFolded) { - R.raw.biometricprompt_folded_base_default - } else { - R.raw.biometricprompt_landscape_base - } - } - - /** Called on configuration changes */ - fun onConfigurationChanged(newConfig: Configuration) { - interactor.onConfigurationChanged(newConfig) - } - - fun setRotation(newRotation: Int) { - rotation = newRotation - } -} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt new file mode 100644 index 000000000000..9b30acb84428 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2023 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.biometrics.ui.viewmodel + +import android.annotation.RawRes +import android.content.res.Configuration +import android.view.Surface +import com.android.systemui.R +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor +import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor +import com.android.systemui.biometrics.shared.model.FingerprintSensorType +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine + +/** Models UI of [BiometricPromptLayout.iconView] */ +class PromptFingerprintIconViewModel +@Inject +constructor( + private val displayStateInteractor: DisplayStateInteractor, + private val promptSelectorInteractor: PromptSelectorInteractor, +) { + /** Current device rotation. */ + private var rotation: Int = Surface.ROTATION_0 + + /** Current BiometricPromptLayout.iconView asset. */ + val iconAsset: Flow = + combine( + displayStateInteractor.isFolded, + displayStateInteractor.isInRearDisplayMode, + promptSelectorInteractor.sensorType, + ) { isFolded: Boolean, isInRearDisplayMode: Boolean, sensorType: FingerprintSensorType -> + when (sensorType) { + FingerprintSensorType.POWER_BUTTON -> + getSideFpsAnimationAsset(isFolded, isInRearDisplayMode) + // Replace below when non-SFPS iconAsset logic is migrated to this ViewModel + else -> -1 + } + } + + @RawRes + private fun getSideFpsAnimationAsset( + isDeviceFolded: Boolean, + isInRearDisplayMode: Boolean, + ): Int = + when (rotation) { + Surface.ROTATION_90 -> + if (isInRearDisplayMode) { + R.raw.biometricprompt_rear_portrait_reverse_base + } else if (isDeviceFolded) { + R.raw.biometricprompt_folded_base_topleft + } else { + R.raw.biometricprompt_portrait_base_topleft + } + Surface.ROTATION_270 -> + if (isInRearDisplayMode) { + R.raw.biometricprompt_rear_portrait_base + } else if (isDeviceFolded) { + R.raw.biometricprompt_folded_base_bottomright + } else { + R.raw.biometricprompt_portrait_base_bottomright + } + else -> + if (isInRearDisplayMode) { + R.raw.biometricprompt_rear_landscape_base + } else if (isDeviceFolded) { + R.raw.biometricprompt_folded_base_default + } else { + R.raw.biometricprompt_landscape_base + } + } + + /** Called on configuration changes */ + fun onConfigurationChanged(newConfig: Configuration) { + displayStateInteractor.onConfigurationChanged(newConfig) + } + + fun setRotation(newRotation: Int) { + rotation = newRotation + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt index 89561a5a212b..4dc7720ef447 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt @@ -20,6 +20,7 @@ import android.util.Log import android.view.HapticFeedbackConstants import android.view.MotionEvent import com.android.systemui.biometrics.AuthBiometricView +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor import com.android.systemui.biometrics.domain.model.BiometricModalities import com.android.systemui.biometrics.shared.model.BiometricModality @@ -45,16 +46,23 @@ import kotlinx.coroutines.launch class PromptViewModel @Inject constructor( - private val interactor: PromptSelectorInteractor, + private val displayStateInteractor: DisplayStateInteractor, + private val promptSelectorInteractor: PromptSelectorInteractor, private val vibrator: VibratorHelper, private val featureFlags: FeatureFlags, ) { + /** Models UI of [BiometricPromptLayout.iconView] */ + val fingerprintIconViewModel: PromptFingerprintIconViewModel = + PromptFingerprintIconViewModel(displayStateInteractor, promptSelectorInteractor) + /** The set of modalities available for this prompt */ val modalities: Flow = - interactor.prompt.map { it?.modalities ?: BiometricModalities() }.distinctUntilChanged() + promptSelectorInteractor.prompt + .map { it?.modalities ?: BiometricModalities() } + .distinctUntilChanged() // TODO(b/251476085): remove after icon controllers are migrated - do not keep this state - private var _legacyState = MutableStateFlow(AuthBiometricView.STATE_AUTHENTICATING_ANIMATING_IN) + private var _legacyState = MutableStateFlow(AuthBiometricView.STATE_IDLE) val legacyState: StateFlow = _legacyState.asStateFlow() private val _isAuthenticating: MutableStateFlow = MutableStateFlow(false) @@ -75,17 +83,18 @@ constructor( * successful authentication. */ val isConfirmationRequired: Flow = - combine(_isOverlayTouched, interactor.isConfirmationRequired) { + combine(_isOverlayTouched, promptSelectorInteractor.isConfirmationRequired) { isOverlayTouched, isConfirmationRequired -> !isOverlayTouched && isConfirmationRequired } /** The kind of credential the user has. */ - val credentialKind: Flow = interactor.credentialKind + val credentialKind: Flow = promptSelectorInteractor.credentialKind /** The label to use for the cancel button. */ - val negativeButtonText: Flow = interactor.prompt.map { it?.negativeButtonText ?: "" } + val negativeButtonText: Flow = + promptSelectorInteractor.prompt.map { it?.negativeButtonText ?: "" } private val _message: MutableStateFlow = MutableStateFlow(PromptMessage.Empty) @@ -113,7 +122,7 @@ constructor( _forceLargeSize, _forceMediumSize, modalities, - interactor.isConfirmationRequired, + promptSelectorInteractor.isConfirmationRequired, fingerprintStartMode, ) { forceLarge, forceMedium, modalities, confirmationRequired, fpStartMode -> when { @@ -129,14 +138,16 @@ constructor( .distinctUntilChanged() /** Title for the prompt. */ - val title: Flow = interactor.prompt.map { it?.title ?: "" }.distinctUntilChanged() + val title: Flow = + promptSelectorInteractor.prompt.map { it?.title ?: "" }.distinctUntilChanged() /** Subtitle for the prompt. */ - val subtitle: Flow = interactor.prompt.map { it?.subtitle ?: "" }.distinctUntilChanged() + val subtitle: Flow = + promptSelectorInteractor.prompt.map { it?.subtitle ?: "" }.distinctUntilChanged() /** Description for the prompt. */ val description: Flow = - interactor.prompt.map { it?.description ?: "" }.distinctUntilChanged() + promptSelectorInteractor.prompt.map { it?.description ?: "" }.distinctUntilChanged() /** If the indicator (help, error) message should be shown. */ val isIndicatorMessageVisible: Flow = @@ -160,7 +171,9 @@ constructor( /** If the icon can be used as a confirmation button. */ val isIconConfirmButton: Flow = - combine(size, interactor.isConfirmationRequired) { size, isConfirmationRequired -> + combine(size, promptSelectorInteractor.isConfirmationRequired) { + size, + isConfirmationRequired -> size.isNotSmall && isConfirmationRequired } @@ -169,7 +182,7 @@ constructor( combine( size, isAuthenticated, - interactor.isCredentialAllowed, + promptSelectorInteractor.isCredentialAllowed, ) { size, authState, credentialAllowed -> size.isNotSmall && authState.isNotAuthenticated && !credentialAllowed } @@ -221,7 +234,7 @@ constructor( combine( size, isAuthenticated, - interactor.isCredentialAllowed, + promptSelectorInteractor.isCredentialAllowed, ) { size, authState, credentialAllowed -> size.isNotSmall && authState.isNotAuthenticated && credentialAllowed } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt index 4e52e64a8af1..9584d888b01f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt @@ -39,13 +39,13 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.internal.widget.LockPatternUtils import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl import com.android.systemui.biometrics.domain.interactor.FakeCredentialInteractor import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl -import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel import com.android.systemui.flags.FakeFeatureFlags @@ -109,6 +109,7 @@ open class AuthContainerViewTest : SysuiTestCase() { private val testScope = TestScope(StandardTestDispatcher()) private val fakeExecutor = FakeExecutor(FakeSystemClock()) private val biometricPromptRepository = FakePromptRepository() + private val fingerprintRepository = FakeFingerprintPropertyRepository() private val rearDisplayStateRepository = FakeRearDisplayStateRepository() private val credentialInteractor = FakeCredentialInteractor() private val bpCredentialInteractor = PromptCredentialInteractor( @@ -118,10 +119,12 @@ open class AuthContainerViewTest : SysuiTestCase() { ) private val promptSelectorInteractor by lazy { PromptSelectorInteractorImpl( + fingerprintRepository, biometricPromptRepository, lockPatternUtils, ) } + private val displayStateInteractor = DisplayStateInteractorImpl( testScope.backgroundScope, mContext, @@ -129,9 +132,7 @@ open class AuthContainerViewTest : SysuiTestCase() { rearDisplayStateRepository ) - private val authBiometricFingerprintViewModel = AuthBiometricFingerprintViewModel( - displayStateInteractor - ) + private val credentialViewModel = CredentialViewModel(mContext, bpCredentialInteractor) private var authContainer: TestAuthContainerView? = null @@ -524,10 +525,14 @@ open class AuthContainerViewTest : SysuiTestCase() { userManager, lockPatternUtils, interactionJankMonitor, - { authBiometricFingerprintViewModel }, { promptSelectorInteractor }, { bpCredentialInteractor }, - PromptViewModel(promptSelectorInteractor, vibrator, featureFlags), + PromptViewModel( + displayStateInteractor, + promptSelectorInteractor, + vibrator, + featureFlags + ), { credentialViewModel }, Handler(TestableLooper.get(this).looper), fakeExecutor, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index 48e513140c3a..6d71dd5cd8ba 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -92,7 +92,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.domain.interactor.LogContextInteractor; import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor; import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor; -import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel; import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel; import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel; import com.android.systemui.flags.FakeFeatureFlags; @@ -177,8 +176,6 @@ public class AuthControllerTest extends SysuiTestCase { @Mock private PromptSelectorInteractor mPromptSelectionInteractor; @Mock - private AuthBiometricFingerprintViewModel mAuthBiometricFingerprintViewModel; - @Mock private CredentialViewModel mCredentialViewModel; @Mock private PromptViewModel mPromptViewModel; @@ -1095,11 +1092,10 @@ public class AuthControllerTest extends SysuiTestCase { mFingerprintManager, mFaceManager, () -> mUdfpsController, () -> mSideFpsController, mDisplayManager, mWakefulnessLifecycle, mPanelInteractionDetector, mUserManager, mLockPatternUtils, mUdfpsLogger, - mLogContextInteractor, () -> mAuthBiometricFingerprintViewModel, - () -> mBiometricPromptCredentialInteractor, () -> mPromptSelectionInteractor, - () -> mCredentialViewModel, () -> mPromptViewModel, - mInteractionJankMonitor, mHandler, - mBackgroundExecutor, mUdfpsUtils, mVibratorHelper); + mLogContextInteractor, () -> mBiometricPromptCredentialInteractor, + () -> mPromptSelectionInteractor, () -> mCredentialViewModel, + () -> mPromptViewModel, mInteractionJankMonitor, mHandler, mBackgroundExecutor, + mUdfpsUtils, mVibratorHelper); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt index 81cbaeab2a32..4d5e1b7de60f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt @@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest import com.android.internal.widget.LockPatternUtils import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.Utils +import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository import com.android.systemui.biometrics.domain.model.BiometricModalities import com.android.systemui.biometrics.faceSensorPropertiesInternal @@ -61,13 +62,15 @@ class PromptSelectorInteractorImplTest : SysuiTestCase() { @Mock private lateinit var lockPatternUtils: LockPatternUtils private val testScope = TestScope() + private val fingerprintRepository = FakeFingerprintPropertyRepository() private val promptRepository = FakePromptRepository() private lateinit var interactor: PromptSelectorInteractor @Before fun setup() { - interactor = PromptSelectorInteractorImpl(promptRepository, lockPatternUtils) + interactor = + PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt deleted file mode 100644 index 785f1be89986..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.android.systemui.biometrics.ui.viewmodel - -import android.content.res.Configuration -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository -import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor -import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl -import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.util.concurrency.FakeExecutor -import com.android.systemui.util.time.FakeSystemClock -import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.TestScope -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.junit.runners.JUnit4 - -@OptIn(ExperimentalCoroutinesApi::class) -@SmallTest -@RunWith(JUnit4::class) -class AuthBiometricFingerprintViewModelTest : SysuiTestCase() { - - private val rearDisplayStateRepository = FakeRearDisplayStateRepository() - private val testScope = TestScope(StandardTestDispatcher()) - private val fakeExecutor = FakeExecutor(FakeSystemClock()) - - private lateinit var interactor: DisplayStateInteractor - private lateinit var viewModel: AuthBiometricFingerprintViewModel - - @Before - fun setup() { - interactor = - DisplayStateInteractorImpl( - testScope.backgroundScope, - mContext, - fakeExecutor, - rearDisplayStateRepository - ) - viewModel = AuthBiometricFingerprintViewModel(interactor) - } - - @Test - fun iconUpdates_onConfigurationChanged() { - testScope.runTest { - runCurrent() - - val testConfig = Configuration() - val folded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP - 1 - val unfolded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP + 1 - val currentIcon = collectLastValue(viewModel.iconAsset) - - testConfig.smallestScreenWidthDp = folded - viewModel.onConfigurationChanged(testConfig) - val foldedIcon = currentIcon() - - testConfig.smallestScreenWidthDp = unfolded - viewModel.onConfigurationChanged(testConfig) - val unfoldedIcon = currentIcon() - - assertThat(foldedIcon).isNotEqualTo(unfoldedIcon) - } - } -} - -internal const val INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP = 600 diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt new file mode 100644 index 000000000000..7697c098ed3d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt @@ -0,0 +1,94 @@ +package com.android.systemui.biometrics.ui.viewmodel + +import android.content.res.Configuration +import androidx.test.filters.SmallTest +import com.android.internal.widget.LockPatternUtils +import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository +import com.android.systemui.biometrics.data.repository.FakePromptRepository +import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl +import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor +import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl +import com.android.systemui.biometrics.shared.model.FingerprintSensorType +import com.android.systemui.biometrics.shared.model.SensorStrength +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(JUnit4::class) +class PromptFingerprintIconViewModelTest : SysuiTestCase() { + + @JvmField @Rule var mockitoRule = MockitoJUnit.rule() + + @Mock private lateinit var lockPatternUtils: LockPatternUtils + + private val fingerprintRepository = FakeFingerprintPropertyRepository() + private val promptRepository = FakePromptRepository() + private val rearDisplayStateRepository = FakeRearDisplayStateRepository() + + private val testScope = TestScope(StandardTestDispatcher()) + private val fakeExecutor = FakeExecutor(FakeSystemClock()) + + private lateinit var promptSelectorInteractor: PromptSelectorInteractor + private lateinit var displayStateInteractor: DisplayStateInteractor + private lateinit var viewModel: PromptFingerprintIconViewModel + + @Before + fun setup() { + promptSelectorInteractor = + PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils) + displayStateInteractor = + DisplayStateInteractorImpl( + testScope.backgroundScope, + mContext, + fakeExecutor, + rearDisplayStateRepository + ) + viewModel = PromptFingerprintIconViewModel(displayStateInteractor, promptSelectorInteractor) + } + + @Test + fun sfpsIconUpdates_onConfigurationChanged() { + testScope.runTest { + runCurrent() + configureFingerprintPropertyRepository(FingerprintSensorType.POWER_BUTTON) + val testConfig = Configuration() + val folded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP - 1 + val unfolded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP + 1 + val currentIcon = collectLastValue(viewModel.iconAsset) + + testConfig.smallestScreenWidthDp = folded + viewModel.onConfigurationChanged(testConfig) + val foldedIcon = currentIcon() + + testConfig.smallestScreenWidthDp = unfolded + viewModel.onConfigurationChanged(testConfig) + val unfoldedIcon = currentIcon() + + assertThat(foldedIcon).isNotEqualTo(unfoldedIcon) + } + } + + private fun configureFingerprintPropertyRepository(sensorType: FingerprintSensorType) { + fingerprintRepository.setProperties(0, SensorStrength.STRONG, sensorType, mapOf()) + } +} + +internal const val INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP = 600 diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt index 4d19543d41ff..11b0b0798ebc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt @@ -24,7 +24,10 @@ import androidx.test.filters.SmallTest import com.android.internal.widget.LockPatternUtils import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.AuthBiometricView +import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository +import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl import com.android.systemui.biometrics.domain.model.BiometricModalities @@ -37,7 +40,9 @@ import com.android.systemui.coroutines.collectValues import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION import com.android.systemui.statusbar.VibratorHelper +import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any +import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first @@ -69,8 +74,19 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa @Mock private lateinit var lockPatternUtils: LockPatternUtils @Mock private lateinit var vibrator: VibratorHelper + private val fakeExecutor = FakeExecutor(FakeSystemClock()) private val testScope = TestScope() + private val fingerprintRepository = FakeFingerprintPropertyRepository() private val promptRepository = FakePromptRepository() + private val rearDisplayStateRepository = FakeRearDisplayStateRepository() + + private val displayStateInteractor = + DisplayStateInteractorImpl( + testScope.backgroundScope, + mContext, + fakeExecutor, + rearDisplayStateRepository + ) private lateinit var selector: PromptSelectorInteractor private lateinit var viewModel: PromptViewModel @@ -78,10 +94,11 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa @Before fun setup() { - selector = PromptSelectorInteractorImpl(promptRepository, lockPatternUtils) + selector = + PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils) selector.resetPrompt() - viewModel = PromptViewModel(selector, vibrator, featureFlags) + viewModel = PromptViewModel(displayStateInteractor, selector, vibrator, featureFlags) featureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, false) } @@ -105,7 +122,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa } assertThat(message).isEqualTo(PromptMessage.Empty) assertThat(size).isEqualTo(expectedSize) - assertThat(legacyState).isEqualTo(AuthBiometricView.STATE_AUTHENTICATING_ANIMATING_IN) + assertThat(legacyState).isEqualTo(AuthBiometricView.STATE_IDLE) val startMessage = "here we go" viewModel.showAuthenticating(startMessage, isRetry = false) -- cgit v1.2.3-59-g8ed1b