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 Merged-In: Id51e8bfa15b2db929499a46437d0a8c77405435f
This commit is contained in:
@@ -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<PromptCredentialInteractor> mPromptCredentialInteractor;
|
||||
private final Provider<AuthBiometricFingerprintViewModel>
|
||||
mAuthBiometricFingerprintViewModelProvider;
|
||||
private final @NonNull Provider<PromptSelectorInteractor> mPromptSelectorInteractorProvider;
|
||||
// TODO(b/251476085): these should be migrated out of the view
|
||||
private final Provider<CredentialViewModel> mCredentialViewModelProvider;
|
||||
@@ -283,8 +279,6 @@ public class AuthContainerView extends LinearLayout
|
||||
@NonNull UserManager userManager,
|
||||
@NonNull LockPatternUtils lockPatternUtils,
|
||||
@NonNull InteractionJankMonitor jankMonitor,
|
||||
@NonNull Provider<AuthBiometricFingerprintViewModel>
|
||||
authBiometricFingerprintViewModelProvider,
|
||||
@NonNull Provider<PromptCredentialInteractor> promptCredentialInteractor,
|
||||
@NonNull Provider<PromptSelectorInteractor> 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<AuthBiometricFingerprintViewModel>
|
||||
authBiometricFingerprintViewModelProvider,
|
||||
@NonNull Provider<PromptSelectorInteractor> promptSelectorInteractorProvider,
|
||||
@NonNull Provider<PromptCredentialInteractor> 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(
|
||||
|
||||
@@ -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<AuthBiometricFingerprintViewModel>
|
||||
mAuthBiometricFingerprintViewModelProvider;
|
||||
@NonNull private final Provider<PromptCredentialInteractor> mPromptCredentialInteractor;
|
||||
@NonNull private final Provider<PromptSelectorInteractor> mPromptSelectorInteractor;
|
||||
@NonNull private final Provider<CredentialViewModel> mCredentialViewModelProvider;
|
||||
@@ -765,8 +762,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
@NonNull LockPatternUtils lockPatternUtils,
|
||||
@NonNull UdfpsLogger udfpsLogger,
|
||||
@NonNull LogContextInteractor logContextInteractor,
|
||||
@NonNull Provider<AuthBiometricFingerprintViewModel>
|
||||
authBiometricFingerprintViewModelProvider,
|
||||
@NonNull Provider<PromptCredentialInteractor> promptCredentialInteractorProvider,
|
||||
@NonNull Provider<PromptSelectorInteractor> promptSelectorInteractorProvider,
|
||||
@NonNull Provider<CredentialViewModel> 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
|
||||
|
||||
@@ -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<Boolean>
|
||||
|
||||
/** Fingerprint sensor type */
|
||||
val sensorType: StateFlow<FingerprintSensorType>
|
||||
|
||||
/** 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<FingerprintSensorType> =
|
||||
fingerprintPropertyRepository.sensorType
|
||||
|
||||
override fun useBiometricsForAuthentication(
|
||||
promptInfo: PromptInfo,
|
||||
userId: Int,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,9 @@ object BiometricViewBinder {
|
||||
|
||||
val iconViewOverlay = view.requireViewById<LottieAnimationView>(R.id.biometric_icon_overlay)
|
||||
val iconView = view.requireViewById<LottieAnimationView>(R.id.biometric_icon)
|
||||
|
||||
PromptFingerprintIconViewBinder.bind(iconView, viewModel.fingerprintIconViewModel)
|
||||
|
||||
val indicatorMessageView = view.requireViewById<TextView>(R.id.indicator)
|
||||
|
||||
// Negative-side (left) buttons
|
||||
|
||||
@@ -21,26 +21,29 @@ 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.biometrics.ui.viewmodel.PromptFingerprintIconViewModel
|
||||
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/** Sub-binder for [AuthBiometricFingerprintView.mIconView]. */
|
||||
object AuthBiometricFingerprintIconViewBinder {
|
||||
/** Sub-binder for [BiometricPromptLayout.iconView]. */
|
||||
object PromptFingerprintIconViewBinder {
|
||||
|
||||
/**
|
||||
* Binds a [AuthBiometricFingerprintView.mIconView] to a [AuthBiometricFingerprintViewModel].
|
||||
*/
|
||||
/** Binds [BiometricPromptLayout.iconView] to [PromptFingerprintIconViewModel]. */
|
||||
@JvmStatic
|
||||
fun bind(view: LottieAnimationView, viewModel: AuthBiometricFingerprintViewModel) {
|
||||
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 -> view.setAnimation(iconAsset) } }
|
||||
launch {
|
||||
viewModel.iconAsset.collect { iconAsset ->
|
||||
if (iconAsset != -1) {
|
||||
view.setAnimation(iconAsset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,23 +22,35 @@ 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 AuthBiometricFingerprintView to support rear display state changes. */
|
||||
class AuthBiometricFingerprintViewModel
|
||||
/** Models UI of [BiometricPromptLayout.iconView] */
|
||||
class PromptFingerprintIconViewModel
|
||||
@Inject
|
||||
constructor(private val interactor: DisplayStateInteractor) {
|
||||
constructor(
|
||||
private val displayStateInteractor: DisplayStateInteractor,
|
||||
private val promptSelectorInteractor: PromptSelectorInteractor,
|
||||
) {
|
||||
/** Current device rotation. */
|
||||
private var rotation: Int = Surface.ROTATION_0
|
||||
|
||||
/** Current AuthBiometricFingerprintView asset. */
|
||||
/** Current BiometricPromptLayout.iconView asset. */
|
||||
val iconAsset: Flow<Int> =
|
||||
combine(interactor.isFolded, interactor.isInRearDisplayMode) {
|
||||
isFolded: Boolean,
|
||||
isInRearDisplayMode: Boolean ->
|
||||
getSideFpsAnimationAsset(isFolded, isInRearDisplayMode)
|
||||
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
|
||||
@@ -75,7 +87,7 @@ constructor(private val interactor: DisplayStateInteractor) {
|
||||
|
||||
/** Called on configuration changes */
|
||||
fun onConfigurationChanged(newConfig: Configuration) {
|
||||
interactor.onConfigurationChanged(newConfig)
|
||||
displayStateInteractor.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
fun setRotation(newRotation: Int) {
|
||||
@@ -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<BiometricModalities> =
|
||||
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<Int> = _legacyState.asStateFlow()
|
||||
|
||||
private val _isAuthenticating: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||
@@ -75,17 +83,18 @@ constructor(
|
||||
* successful authentication.
|
||||
*/
|
||||
val isConfirmationRequired: Flow<Boolean> =
|
||||
combine(_isOverlayTouched, interactor.isConfirmationRequired) {
|
||||
combine(_isOverlayTouched, promptSelectorInteractor.isConfirmationRequired) {
|
||||
isOverlayTouched,
|
||||
isConfirmationRequired ->
|
||||
!isOverlayTouched && isConfirmationRequired
|
||||
}
|
||||
|
||||
/** The kind of credential the user has. */
|
||||
val credentialKind: Flow<PromptKind> = interactor.credentialKind
|
||||
val credentialKind: Flow<PromptKind> = promptSelectorInteractor.credentialKind
|
||||
|
||||
/** The label to use for the cancel button. */
|
||||
val negativeButtonText: Flow<String> = interactor.prompt.map { it?.negativeButtonText ?: "" }
|
||||
val negativeButtonText: Flow<String> =
|
||||
promptSelectorInteractor.prompt.map { it?.negativeButtonText ?: "" }
|
||||
|
||||
private val _message: MutableStateFlow<PromptMessage> = 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<String> = interactor.prompt.map { it?.title ?: "" }.distinctUntilChanged()
|
||||
val title: Flow<String> =
|
||||
promptSelectorInteractor.prompt.map { it?.title ?: "" }.distinctUntilChanged()
|
||||
|
||||
/** Subtitle for the prompt. */
|
||||
val subtitle: Flow<String> = interactor.prompt.map { it?.subtitle ?: "" }.distinctUntilChanged()
|
||||
val subtitle: Flow<String> =
|
||||
promptSelectorInteractor.prompt.map { it?.subtitle ?: "" }.distinctUntilChanged()
|
||||
|
||||
/** Description for the prompt. */
|
||||
val description: Flow<String> =
|
||||
interactor.prompt.map { it?.description ?: "" }.distinctUntilChanged()
|
||||
promptSelectorInteractor.prompt.map { it?.description ?: "" }.distinctUntilChanged()
|
||||
|
||||
/** If the indicator (help, error) message should be shown. */
|
||||
val isIndicatorMessageVisible: Flow<Boolean> =
|
||||
@@ -160,7 +171,9 @@ constructor(
|
||||
|
||||
/** If the icon can be used as a confirmation button. */
|
||||
val isIconConfirmButton: Flow<Boolean> =
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,10 +2,17 @@ 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
|
||||
@@ -16,38 +23,52 @@ 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 AuthBiometricFingerprintViewModelTest : SysuiTestCase() {
|
||||
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 interactor: DisplayStateInteractor
|
||||
private lateinit var viewModel: AuthBiometricFingerprintViewModel
|
||||
private lateinit var promptSelectorInteractor: PromptSelectorInteractor
|
||||
private lateinit var displayStateInteractor: DisplayStateInteractor
|
||||
private lateinit var viewModel: PromptFingerprintIconViewModel
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
interactor =
|
||||
promptSelectorInteractor =
|
||||
PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils)
|
||||
displayStateInteractor =
|
||||
DisplayStateInteractorImpl(
|
||||
testScope.backgroundScope,
|
||||
mContext,
|
||||
fakeExecutor,
|
||||
rearDisplayStateRepository
|
||||
)
|
||||
viewModel = AuthBiometricFingerprintViewModel(interactor)
|
||||
viewModel = PromptFingerprintIconViewModel(displayStateInteractor, promptSelectorInteractor)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun iconUpdates_onConfigurationChanged() {
|
||||
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
|
||||
@@ -64,6 +85,10 @@ class AuthBiometricFingerprintViewModelTest : SysuiTestCase() {
|
||||
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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user