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 Original line Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.biometrics;
package com.android.systemui.biometrics;


import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
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 android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;


import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION;
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.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.Flags;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.PromptInfo;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -402,7 +402,12 @@ public class AuthContainerView extends LinearLayout
            @Nullable FaceSensorPropertiesInternal faceProps,
            @Nullable FaceSensorPropertiesInternal faceProps,
            @NonNull VibratorHelper vibratorHelper
            @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);
            addBiometricView(config, layoutInflater, viewModel, fpProps, faceProps, vibratorHelper);
        } else if (constraintBp() && Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) {
        } else if (constraintBp() && Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo)) {
            addCredentialView(true, false);
            addCredentialView(true, false);
@@ -411,7 +416,6 @@ public class AuthContainerView extends LinearLayout
        }
        }
    }
    }



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


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


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


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


import android.hardware.biometrics.Flags
import android.hardware.biometrics.PromptInfo
import android.hardware.biometrics.PromptInfo
import com.android.systemui.biometrics.AuthController
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.biometrics.shared.model.PromptKind
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -65,6 +68,18 @@ interface PromptRepository {
     */
     */
    val isConfirmationRequired: Flow<Boolean>
    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]. */
    /** Update the prompt configuration, which should be set before [isShowing]. */
    fun setPrompt(
    fun setPrompt(
        promptInfo: PromptInfo,
        promptInfo: PromptInfo,
@@ -129,6 +144,19 @@ constructor(
            }
            }
            .distinctUntilChanged()
            .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(
    override fun setPrompt(
        promptInfo: PromptInfo,
        promptInfo: PromptInfo,
        userId: Int,
        userId: Int,
+8 −0
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -59,6 +60,13 @@ constructor(
    /** If the prompt is currently showing. */
    /** If the prompt is currently showing. */
    val isShowing: Flow<Boolean> = biometricPromptRepository.isShowing
    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. */
    /** Metadata about the current credential prompt, including app-supplied preferences. */
    val prompt: Flow<BiometricPromptRequest.Credential?> =
    val prompt: Flow<BiometricPromptRequest.Credential?> =
        combine(
        combine(
+19 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.systemui.biometrics.shared.model.PromptKind
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
@@ -70,6 +71,18 @@ interface PromptSelectorInteractor {
    /** Fingerprint sensor type */
    /** Fingerprint sensor type */
    val sensorType: Flow<FingerprintSensorType>
    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. */
    /** Use biometrics for authentication. */
    fun useBiometricsForAuthentication(
    fun useBiometricsForAuthentication(
        promptInfo: PromptInfo,
        promptInfo: PromptInfo,
@@ -154,6 +167,12 @@ constructor(


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


    override val showBpWithoutIconForCredential = promptRepository.showBpWithoutIconForCredential

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

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