Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +42 −32 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.Flags.customBiometricPrompt; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION; Loading Loading @@ -401,7 +402,21 @@ public class AuthContainerView extends LinearLayout @Nullable FaceSensorPropertiesInternal faceProps, @NonNull VibratorHelper vibratorHelper ) { if (Utils.isBiometricAllowed(config.mPromptInfo)) { if (Utils.isBiometricAllowed(config.mPromptInfo) || customBiometricPrompt()) { addBiometricView(config, layoutInflater, viewModel, fpProps, faceProps, vibratorHelper); } else if (constraintBp() && Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) { addCredentialView(true, false); } else { mPromptSelectorInteractorProvider.get().resetPrompt(); } } private void addBiometricView(@NonNull Config config, @NonNull LayoutInflater layoutInflater, @NonNull PromptViewModel viewModel, @Nullable FingerprintSensorPropertiesInternal fpProps, @Nullable FaceSensorPropertiesInternal faceProps, @NonNull VibratorHelper vibratorHelper) { mPromptSelectorInteractorProvider.get().useBiometricsForAuthentication( config.mPromptInfo, config.mUserId, Loading Loading @@ -432,11 +447,6 @@ public class AuthContainerView extends LinearLayout config.mScaleProvider); } } } else if (constraintBp() && Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) { addCredentialView(true, false); } else { mPromptSelectorInteractorProvider.get().resetPrompt(); } } private void onBackInvoked() { Loading Loading @@ -524,7 +534,7 @@ public class AuthContainerView extends LinearLayout () -> animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED)); if (constraintBp()) { // Do nothing on attachment with constraintLayout } else if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) { } else if (Utils.isBiometricAllowed(mConfig.mPromptInfo) || customBiometricPrompt()) { mBiometricScrollView.addView(mBiometricView.asView()); } else if (Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) { addCredentialView(true /* animatePanel */, false /* animateContents */); Loading packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +13 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context import android.hardware.biometrics.BiometricAuthenticator import android.hardware.biometrics.BiometricConstants import android.hardware.biometrics.BiometricPrompt import android.hardware.biometrics.Flags.customBiometricPrompt import android.hardware.face.FaceManager import android.text.method.ScrollingMovementMethod import android.util.Log Loading Loading @@ -123,13 +124,6 @@ object BiometricViewBinder { (view as BiometricPromptLayout).updatedFingerprintAffordanceSize } PromptIconViewBinder.bind( iconView, iconOverlayView, iconSizeOverride, viewModel, ) val indicatorMessageView = view.requireViewById<TextView>(R.id.indicator) // Negative-side (left) buttons Loading @@ -156,6 +150,18 @@ object BiometricViewBinder { view.repeatWhenAttached { // these do not change and need to be set before any size transitions val modalities = viewModel.modalities.first() // If there is no biometrics available, biometric prompt is showing just for displaying // content, no authentication needed. if (!(customBiometricPrompt() && modalities.isEmpty)) { PromptIconViewBinder.bind( iconView, iconOverlayView, iconSizeOverride, viewModel, ) } if (modalities.hasFingerprint) { /** * Load the given [rawResources] immediately so they are cached for use in the Loading packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt +19 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.animation.AnimatorSet import android.animation.ValueAnimator import android.graphics.Outline import android.graphics.Rect import android.hardware.biometrics.Flags import android.transition.AutoTransition import android.transition.TransitionManager import android.view.Surface Loading Loading @@ -59,6 +60,7 @@ import com.android.systemui.res.R import kotlin.math.abs import kotlin.math.min import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch /** Helper for [BiometricViewBinder] to handle resize transitions. */ Loading Loading @@ -219,6 +221,18 @@ object BiometricViewSizeBinder { view.repeatWhenAttached { var currentSize: PromptSize? = null val modalities = viewModel.modalities.first() // TODO(b/288175072): Move all visibility settings together. // If there is no biometrics available, biometric prompt is showing just for // displaying content, no authentication needed. if (Flags.customBiometricPrompt() && modalities.isEmpty) { smallConstraintSet.setVisibility(iconHolderView.id, View.GONE) smallConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE) smallConstraintSet.setVisibility(R.id.indicator, View.GONE) mediumConstraintSet.setVisibility(iconHolderView.id, View.GONE) mediumConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE) mediumConstraintSet.setVisibility(R.id.indicator, View.GONE) } lifecycleScope.launch { combine(viewModel.position, viewModel.size, ::Pair).collect { (position, size) -> Loading Loading @@ -299,6 +313,7 @@ object BiometricViewSizeBinder { // TODO(b/251476085): migrate the legacy panel controller and simplify this view.repeatWhenAttached { var currentSize: PromptSize? = null val modalities = viewModel.modalities.first() lifecycleScope.launch { /** * View is only set visible in BiometricViewSizeBinder once PromptSize is Loading @@ -318,6 +333,9 @@ object BiometricViewSizeBinder { for (v in viewsToHideWhenSmall) { v.showContentOrHide(forceHide = size.isSmall) } if (Flags.customBiometricPrompt() && modalities.isEmpty) { iconHolderView.visibility = View.GONE } if (currentSize == null && size.isSmall) { iconHolderView.alpha = 0f } Loading @@ -328,8 +346,7 @@ object BiometricViewSizeBinder { // TODO(b/302735104): Fix wrong height due to the delay of // PromptContentView. addOnLayoutChangeListener() will cause crash when // showing credential view, since |PromptIconViewModel| won't release // the // flow. // the flow. // propagate size changes to legacy panel controller and animate // transitions view.doOnLayout { Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +20 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.pm.PackageManager import android.hardware.biometrics.BiometricAuthenticator import android.hardware.biometrics.BiometricConstants import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT import android.hardware.biometrics.Flags.customBiometricPrompt import android.hardware.biometrics.PromptInfo import android.hardware.face.FaceSensorPropertiesInternal import android.hardware.fingerprint.FingerprintSensorPropertiesInternal Loading @@ -38,11 +40,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.jank.InteractionJankMonitor import com.android.internal.widget.LockPatternUtils import com.android.systemui.res.R import com.android.systemui.Flags.FLAG_CONSTRAINT_BP import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl import com.android.systemui.biometrics.domain.interactor.FakeCredentialInteractor Loading @@ -53,6 +55,7 @@ import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel import com.android.systemui.display.data.repository.FakeDisplayRepository import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.res.R import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.events.ANIMATING_OUT import com.android.systemui.user.domain.interactor.SelectedUserInteractor Loading Loading @@ -145,6 +148,8 @@ open class AuthContainerViewTest : SysuiTestCase() { @Before fun setup() { mSetFlagsRule.disableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT) mSetFlagsRule.disableFlags(FLAG_CONSTRAINT_BP) displayRepository = FakeDisplayRepository() displayStateInteractor = Loading Loading @@ -393,6 +398,19 @@ open class AuthContainerViewTest : SysuiTestCase() { assertThat(container.hasBiometricPrompt()).isFalse() } @Test fun testShowBiometricUIWhenCustomBpEnabledAndNoSensors() { mSetFlagsRule.enableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT) val container = initializeFingerprintContainer( authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL ) waitForIdleSync() assertThat(customBiometricPrompt()).isTrue() assertThat(container.hasBiometricPrompt()).isTrue() assertThat(container.hasCredentialView()).isFalse() } @Test fun testCredentialViewUsesEffectiveUserId() { whenever(userManager.getCredentialOwnerProfile(anyInt())).thenReturn(200) Loading Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +42 −32 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.Flags.customBiometricPrompt; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION; Loading Loading @@ -401,7 +402,21 @@ public class AuthContainerView extends LinearLayout @Nullable FaceSensorPropertiesInternal faceProps, @NonNull VibratorHelper vibratorHelper ) { if (Utils.isBiometricAllowed(config.mPromptInfo)) { if (Utils.isBiometricAllowed(config.mPromptInfo) || customBiometricPrompt()) { addBiometricView(config, layoutInflater, viewModel, fpProps, faceProps, vibratorHelper); } else if (constraintBp() && Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) { addCredentialView(true, false); } else { mPromptSelectorInteractorProvider.get().resetPrompt(); } } private void addBiometricView(@NonNull Config config, @NonNull LayoutInflater layoutInflater, @NonNull PromptViewModel viewModel, @Nullable FingerprintSensorPropertiesInternal fpProps, @Nullable FaceSensorPropertiesInternal faceProps, @NonNull VibratorHelper vibratorHelper) { mPromptSelectorInteractorProvider.get().useBiometricsForAuthentication( config.mPromptInfo, config.mUserId, Loading Loading @@ -432,11 +447,6 @@ public class AuthContainerView extends LinearLayout config.mScaleProvider); } } } else if (constraintBp() && Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) { addCredentialView(true, false); } else { mPromptSelectorInteractorProvider.get().resetPrompt(); } } private void onBackInvoked() { Loading Loading @@ -524,7 +534,7 @@ public class AuthContainerView extends LinearLayout () -> animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED)); if (constraintBp()) { // Do nothing on attachment with constraintLayout } else if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) { } else if (Utils.isBiometricAllowed(mConfig.mPromptInfo) || customBiometricPrompt()) { mBiometricScrollView.addView(mBiometricView.asView()); } else if (Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) { addCredentialView(true /* animatePanel */, false /* animateContents */); Loading
packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +13 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context import android.hardware.biometrics.BiometricAuthenticator import android.hardware.biometrics.BiometricConstants import android.hardware.biometrics.BiometricPrompt import android.hardware.biometrics.Flags.customBiometricPrompt import android.hardware.face.FaceManager import android.text.method.ScrollingMovementMethod import android.util.Log Loading Loading @@ -123,13 +124,6 @@ object BiometricViewBinder { (view as BiometricPromptLayout).updatedFingerprintAffordanceSize } PromptIconViewBinder.bind( iconView, iconOverlayView, iconSizeOverride, viewModel, ) val indicatorMessageView = view.requireViewById<TextView>(R.id.indicator) // Negative-side (left) buttons Loading @@ -156,6 +150,18 @@ object BiometricViewBinder { view.repeatWhenAttached { // these do not change and need to be set before any size transitions val modalities = viewModel.modalities.first() // If there is no biometrics available, biometric prompt is showing just for displaying // content, no authentication needed. if (!(customBiometricPrompt() && modalities.isEmpty)) { PromptIconViewBinder.bind( iconView, iconOverlayView, iconSizeOverride, viewModel, ) } if (modalities.hasFingerprint) { /** * Load the given [rawResources] immediately so they are cached for use in the Loading
packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt +19 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.animation.AnimatorSet import android.animation.ValueAnimator import android.graphics.Outline import android.graphics.Rect import android.hardware.biometrics.Flags import android.transition.AutoTransition import android.transition.TransitionManager import android.view.Surface Loading Loading @@ -59,6 +60,7 @@ import com.android.systemui.res.R import kotlin.math.abs import kotlin.math.min import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch /** Helper for [BiometricViewBinder] to handle resize transitions. */ Loading Loading @@ -219,6 +221,18 @@ object BiometricViewSizeBinder { view.repeatWhenAttached { var currentSize: PromptSize? = null val modalities = viewModel.modalities.first() // TODO(b/288175072): Move all visibility settings together. // If there is no biometrics available, biometric prompt is showing just for // displaying content, no authentication needed. if (Flags.customBiometricPrompt() && modalities.isEmpty) { smallConstraintSet.setVisibility(iconHolderView.id, View.GONE) smallConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE) smallConstraintSet.setVisibility(R.id.indicator, View.GONE) mediumConstraintSet.setVisibility(iconHolderView.id, View.GONE) mediumConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE) mediumConstraintSet.setVisibility(R.id.indicator, View.GONE) } lifecycleScope.launch { combine(viewModel.position, viewModel.size, ::Pair).collect { (position, size) -> Loading Loading @@ -299,6 +313,7 @@ object BiometricViewSizeBinder { // TODO(b/251476085): migrate the legacy panel controller and simplify this view.repeatWhenAttached { var currentSize: PromptSize? = null val modalities = viewModel.modalities.first() lifecycleScope.launch { /** * View is only set visible in BiometricViewSizeBinder once PromptSize is Loading @@ -318,6 +333,9 @@ object BiometricViewSizeBinder { for (v in viewsToHideWhenSmall) { v.showContentOrHide(forceHide = size.isSmall) } if (Flags.customBiometricPrompt() && modalities.isEmpty) { iconHolderView.visibility = View.GONE } if (currentSize == null && size.isSmall) { iconHolderView.alpha = 0f } Loading @@ -328,8 +346,7 @@ object BiometricViewSizeBinder { // TODO(b/302735104): Fix wrong height due to the delay of // PromptContentView. addOnLayoutChangeListener() will cause crash when // showing credential view, since |PromptIconViewModel| won't release // the // flow. // the flow. // propagate size changes to legacy panel controller and animate // transitions view.doOnLayout { Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +20 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.pm.PackageManager import android.hardware.biometrics.BiometricAuthenticator import android.hardware.biometrics.BiometricConstants import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT import android.hardware.biometrics.Flags.customBiometricPrompt import android.hardware.biometrics.PromptInfo import android.hardware.face.FaceSensorPropertiesInternal import android.hardware.fingerprint.FingerprintSensorPropertiesInternal Loading @@ -38,11 +40,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.jank.InteractionJankMonitor import com.android.internal.widget.LockPatternUtils import com.android.systemui.res.R import com.android.systemui.Flags.FLAG_CONSTRAINT_BP import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.data.repository.FakePromptRepository import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl import com.android.systemui.biometrics.domain.interactor.FakeCredentialInteractor Loading @@ -53,6 +55,7 @@ import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel import com.android.systemui.display.data.repository.FakeDisplayRepository import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.res.R import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.events.ANIMATING_OUT import com.android.systemui.user.domain.interactor.SelectedUserInteractor Loading Loading @@ -145,6 +148,8 @@ open class AuthContainerViewTest : SysuiTestCase() { @Before fun setup() { mSetFlagsRule.disableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT) mSetFlagsRule.disableFlags(FLAG_CONSTRAINT_BP) displayRepository = FakeDisplayRepository() displayStateInteractor = Loading Loading @@ -393,6 +398,19 @@ open class AuthContainerViewTest : SysuiTestCase() { assertThat(container.hasBiometricPrompt()).isFalse() } @Test fun testShowBiometricUIWhenCustomBpEnabledAndNoSensors() { mSetFlagsRule.enableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT) val container = initializeFingerprintContainer( authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL ) waitForIdleSync() assertThat(customBiometricPrompt()).isTrue() assertThat(container.hasBiometricPrompt()).isTrue() assertThat(container.hasCredentialView()).isFalse() } @Test fun testCredentialViewUsesEffectiveUserId() { whenever(userManager.getCredentialOwnerProfile(anyInt())).thenReturn(200) Loading