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

Commit 20775fc7 authored by Hao Dong's avatar Hao Dong
Browse files

Show two step credential only for custom bp.

1. Add method and flow shouldShowBpWithoutIconForCredential to make the
   check more clear and accurate.
2. Fix when configuration changes, credential view is not showing
   properly.

Test: atest PromptRepositoryImplTest
Test: atest AuthContainerViewTest
Flag: ACONFIG android.hardware.biometrics.custom_biometric_prompt DEVELOPMENT
Bug: 302735104
Change-Id: I036584c6b5da4598d6cf271ee5210bbe6c1faea9
parent b6a7c55f
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
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;
@@ -33,6 +32,7 @@ import android.graphics.PixelFormat;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.Flags;
import android.hardware.biometrics.PromptInfo;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -402,7 +402,12 @@ public class AuthContainerView extends LinearLayout
            @Nullable FaceSensorPropertiesInternal faceProps,
            @NonNull VibratorHelper vibratorHelper
    ) {
        if (Utils.isBiometricAllowed(config.mPromptInfo) || customBiometricPrompt()) {
        // Set this value before showing either of the prompt.
        mPromptSelectorInteractorProvider.get().setShouldShowBpWithoutIconForCredential(
                config.mPromptInfo);

        if (Utils.isBiometricAllowed(config.mPromptInfo)
                || mPromptViewModel.getShowBpWithoutIconForCredential().getValue()) {
            addBiometricView(config, layoutInflater, viewModel, fpProps, faceProps, vibratorHelper);
        } else if (constraintBp() && Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) {
            addCredentialView(true, false);
@@ -411,7 +416,6 @@ public class AuthContainerView extends LinearLayout
        }
    }


    private void addBiometricView(@NonNull Config config, @NonNull LayoutInflater layoutInflater,
            @NonNull PromptViewModel viewModel,
            @Nullable FingerprintSensorPropertiesInternal fpProps,
@@ -534,7 +538,8 @@ public class AuthContainerView extends LinearLayout
                () -> animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED));
        if (constraintBp()) {
            // Do nothing on attachment with constraintLayout
        } else if (Utils.isBiometricAllowed(mConfig.mPromptInfo) || customBiometricPrompt()) {
        } else if (Utils.isBiometricAllowed(mConfig.mPromptInfo)
                || mPromptViewModel.getShowBpWithoutIconForCredential().getValue()) {
            mBiometricScrollView.addView(mBiometricView.asView());
        } else if (Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) {
            addCredentialView(true /* animatePanel */, false /* animateContents */);
@@ -819,6 +824,9 @@ public class AuthContainerView extends LinearLayout

        final Runnable endActionRunnable = () -> {
            setVisibility(View.INVISIBLE);
            if (Flags.customBiometricPrompt()) {
                mPromptSelectorInteractorProvider.get().resetPrompt();
            }
            removeWindowIfAttached();
        };

+28 −0
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package com.android.systemui.biometrics.data.repository

import android.hardware.biometrics.Flags
import android.hardware.biometrics.PromptInfo
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.Utils
import com.android.systemui.biometrics.Utils.isDeviceCredentialAllowed
import com.android.systemui.biometrics.shared.model.PromptKind
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -65,6 +68,18 @@ interface PromptRepository {
     */
    val isConfirmationRequired: Flow<Boolean>

    /**
     * If biometric prompt without icon needs to show for displaying content prior to credential
     * view.
     */
    val showBpWithoutIconForCredential: StateFlow<Boolean>

    /**
     * Update whether biometric prompt without icon needs to show for displaying content prior to
     * credential view, which should be set before [setPrompt].
     */
    fun setShouldShowBpWithoutIconForCredential(promptInfo: PromptInfo)

    /** Update the prompt configuration, which should be set before [isShowing]. */
    fun setPrompt(
        promptInfo: PromptInfo,
@@ -129,6 +144,19 @@ constructor(
            }
            .distinctUntilChanged()

    private val _showBpWithoutIconForCredential: MutableStateFlow<Boolean> = MutableStateFlow(false)
    override val showBpWithoutIconForCredential = _showBpWithoutIconForCredential.asStateFlow()

    override fun setShouldShowBpWithoutIconForCredential(promptInfo: PromptInfo) {
        val hasCredentialViewShown = kind.value !is PromptKind.Biometric
        val showBpForCredential =
            Flags.customBiometricPrompt() &&
                !Utils.isBiometricAllowed(promptInfo) &&
                isDeviceCredentialAllowed(promptInfo) &&
                promptInfo.contentView != null
        _showBpWithoutIconForCredential.value = showBpForCredential && !hasCredentialViewShown
    }

    override fun setPrompt(
        promptInfo: PromptInfo,
        userId: Int,
+8 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -59,6 +60,13 @@ constructor(
    /** If the prompt is currently showing. */
    val isShowing: Flow<Boolean> = biometricPromptRepository.isShowing

    /**
     * If biometric prompt without icon needs to show for displaying content prior to credential
     * view.
     */
    val showBpWithoutIconForCredential: StateFlow<Boolean> =
        biometricPromptRepository.showBpWithoutIconForCredential

    /** Metadata about the current credential prompt, including app-supplied preferences. */
    val prompt: Flow<BiometricPromptRequest.Credential?> =
        combine(
+19 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ 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
@@ -70,6 +71,18 @@ interface PromptSelectorInteractor {
    /** Fingerprint sensor type */
    val sensorType: Flow<FingerprintSensorType>

    /**
     * If biometric prompt without icon needs to show for displaying content prior to credential
     * view.
     */
    val showBpWithoutIconForCredential: StateFlow<Boolean>

    /**
     * Update whether biometric prompt without icon needs to show for displaying content prior to
     * credential view, which should be set before [PromptRepository.setPrompt].
     */
    fun setShouldShowBpWithoutIconForCredential(promptInfo: PromptInfo)

    /** Use biometrics for authentication. */
    fun useBiometricsForAuthentication(
        promptInfo: PromptInfo,
@@ -154,6 +167,12 @@ constructor(

    override val sensorType: Flow<FingerprintSensorType> = fingerprintPropertyRepository.sensorType

    override val showBpWithoutIconForCredential = promptRepository.showBpWithoutIconForCredential

    override fun setShouldShowBpWithoutIconForCredential(promptInfo: PromptInfo) {
        promptRepository.setShouldShowBpWithoutIconForCredential(promptInfo)
    }

    override fun useBiometricsForAuthentication(
        promptInfo: PromptInfo,
        userId: Int,
+3 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ sealed class BiometricPromptRequest(
    val title: String,
    val subtitle: String,
    val description: String,
    val contentView: PromptContentView?,
    val userInfo: BiometricUserInfo,
    val operationInfo: BiometricOperationInfo,
    val showEmergencyCallButton: Boolean,
@@ -33,11 +34,11 @@ sealed class BiometricPromptRequest(
            title = info.title?.toString() ?: "",
            subtitle = info.subtitle?.toString() ?: "",
            description = info.description?.toString() ?: "",
            contentView = info.contentView,
            userInfo = userInfo,
            operationInfo = operationInfo,
            showEmergencyCallButton = info.isShowEmergencyCallButton
        ) {
        val contentView: PromptContentView? = info.contentView
        val logoRes: Int = info.logoRes
        val logoBitmap: Bitmap? = info.logoBitmap
        val logoDescription: String? = info.logoDescription
@@ -54,6 +55,7 @@ sealed class BiometricPromptRequest(
            title = (info.deviceCredentialTitle ?: info.title)?.toString() ?: "",
            subtitle = (info.deviceCredentialSubtitle ?: info.subtitle)?.toString() ?: "",
            description = (info.deviceCredentialDescription ?: info.description)?.toString() ?: "",
            contentView = info.contentView,
            userInfo = userInfo,
            operationInfo = operationInfo,
            showEmergencyCallButton = info.isShowEmergencyCallButton
Loading