Merge "Fix missing BP icon" into udc-qpr-dev

This commit is contained in:
Grace Cheng
2023-08-21 20:27:16 +00:00
committed by Android (Google) Code Review
13 changed files with 147 additions and 116 deletions

View File

@@ -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(

View File

@@ -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

View File

@@ -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,

View File

@@ -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)
}
}
}

View File

@@ -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

View File

@@ -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)
}
}
}
}
}
}

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)