Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4953f286 authored by Hao Dong's avatar Hao Dong
Browse files

Show bp without sensor icon before credential view.

Test: atest AuthContainerViewTest
Test: manuall test on test app
Flag: ACONFIG android.hardware.biometrics.custom_biometric_prompt DEVELOPMENT
Bug: 302735104
Change-Id: I1f0f82bdb0c387a7cc3755fe83b977b1666a7f3b
parent 4cc0c937
Loading
Loading
Loading
Loading
+42 −32
Original line number Diff line number Diff line
@@ -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;
@@ -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,
@@ -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() {
@@ -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 */);
+13 −7
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
+19 −2
Original line number Diff line number Diff line
@@ -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
@@ -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. */
@@ -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) ->
@@ -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
@@ -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
                            }
@@ -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 {
+20 −2
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
@@ -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 =
@@ -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)