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

Commit ef8cae9e authored by Ale Nijamkin's avatar Ale Nijamkin Committed by Android (Google) Code Review
Browse files

Merge "[flexiglass] Adds support for "enhanced PIN privacy"" into main

parents f5adf3e9 9d8f520b
Loading
Loading
Loading
Loading
+20 −12
Original line number Original line Diff line number Diff line
@@ -76,6 +76,8 @@ fun PinPad(
    val backspaceButtonAppearance by viewModel.backspaceButtonAppearance.collectAsState()
    val backspaceButtonAppearance by viewModel.backspaceButtonAppearance.collectAsState()
    val confirmButtonAppearance by viewModel.confirmButtonAppearance.collectAsState()
    val confirmButtonAppearance by viewModel.confirmButtonAppearance.collectAsState()
    val animateFailure: Boolean by viewModel.animateFailure.collectAsState()
    val animateFailure: Boolean by viewModel.animateFailure.collectAsState()
    val isDigitButtonAnimationEnabled: Boolean by
        viewModel.isDigitButtonAnimationEnabled.collectAsState()


    val buttonScaleAnimatables = remember { List(12) { Animatable(1f) } }
    val buttonScaleAnimatables = remember { List(12) { Animatable(1f) } }
    LaunchedEffect(animateFailure) {
    LaunchedEffect(animateFailure) {
@@ -94,10 +96,11 @@ fun PinPad(
    ) {
    ) {
        repeat(9) { index ->
        repeat(9) { index ->
            DigitButton(
            DigitButton(
                index + 1,
                digit = index + 1,
                isInputEnabled,
                isInputEnabled = isInputEnabled,
                viewModel::onPinButtonClicked,
                onClicked = viewModel::onPinButtonClicked,
                buttonScaleAnimatables[index]::value,
                scaling = buttonScaleAnimatables[index]::value,
                isAnimationEnabled = isDigitButtonAnimationEnabled,
            )
            )
        }
        }


@@ -116,10 +119,11 @@ fun PinPad(
        )
        )


        DigitButton(
        DigitButton(
            0,
            digit = 0,
            isInputEnabled,
            isInputEnabled = isInputEnabled,
            viewModel::onPinButtonClicked,
            onClicked = viewModel::onPinButtonClicked,
            buttonScaleAnimatables[10]::value,
            scaling = buttonScaleAnimatables[10]::value,
            isAnimationEnabled = isDigitButtonAnimationEnabled,
        )
        )


        ActionButton(
        ActionButton(
@@ -143,15 +147,17 @@ private fun DigitButton(
    isInputEnabled: Boolean,
    isInputEnabled: Boolean,
    onClicked: (Int) -> Unit,
    onClicked: (Int) -> Unit,
    scaling: () -> Float,
    scaling: () -> Float,
    isAnimationEnabled: Boolean,
) {
) {
    PinPadButton(
    PinPadButton(
        onClicked = { onClicked(digit) },
        onClicked = { onClicked(digit) },
        isEnabled = isInputEnabled,
        isEnabled = isInputEnabled,
        backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
        backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
        foregroundColor = MaterialTheme.colorScheme.onSurfaceVariant,
        foregroundColor = MaterialTheme.colorScheme.onSurfaceVariant,
        isAnimationEnabled = isAnimationEnabled,
        modifier =
        modifier =
            Modifier.graphicsLayer {
            Modifier.graphicsLayer {
                val scale = scaling()
                val scale = if (isAnimationEnabled) scaling() else 1f
                scaleX = scale
                scaleX = scale
                scaleY = scale
                scaleY = scale
            }
            }
@@ -195,6 +201,7 @@ private fun ActionButton(
        isEnabled = isInputEnabled && !isHidden,
        isEnabled = isInputEnabled && !isHidden,
        backgroundColor = backgroundColor,
        backgroundColor = backgroundColor,
        foregroundColor = foregroundColor,
        foregroundColor = foregroundColor,
        isAnimationEnabled = true,
        modifier =
        modifier =
            Modifier.graphicsLayer {
            Modifier.graphicsLayer {
                alpha = hiddenAlpha
                alpha = hiddenAlpha
@@ -216,6 +223,7 @@ private fun PinPadButton(
    isEnabled: Boolean,
    isEnabled: Boolean,
    backgroundColor: Color,
    backgroundColor: Color,
    foregroundColor: Color,
    foregroundColor: Color,
    isAnimationEnabled: Boolean,
    modifier: Modifier = Modifier,
    modifier: Modifier = Modifier,
    onLongPressed: (() -> Unit)? = null,
    onLongPressed: (() -> Unit)? = null,
    content: @Composable (contentColor: () -> Color) -> Unit,
    content: @Composable (contentColor: () -> Color) -> Unit,
@@ -243,7 +251,7 @@ private fun PinPadButton(


    val cornerRadius: Dp by
    val cornerRadius: Dp by
        animateDpAsState(
        animateDpAsState(
            if (isPressed) 24.dp else pinButtonSize / 2,
            if (isAnimationEnabled && isPressed) 24.dp else pinButtonSize / 2,
            label = "PinButton round corners",
            label = "PinButton round corners",
            animationSpec = tween(animDurationMillis, easing = animEasing)
            animationSpec = tween(animDurationMillis, easing = animEasing)
        )
        )
@@ -251,7 +259,7 @@ private fun PinPadButton(
    val containerColor: Color by
    val containerColor: Color by
        animateColorAsState(
        animateColorAsState(
            when {
            when {
                isPressed -> MaterialTheme.colorScheme.primary
                isAnimationEnabled && isPressed -> MaterialTheme.colorScheme.primary
                else -> backgroundColor
                else -> backgroundColor
            },
            },
            label = "Pin button container color",
            label = "Pin button container color",
@@ -260,7 +268,7 @@ private fun PinPadButton(
    val contentColor =
    val contentColor =
        animateColorAsState(
        animateColorAsState(
            when {
            when {
                isPressed -> MaterialTheme.colorScheme.onPrimary
                isAnimationEnabled && isPressed -> MaterialTheme.colorScheme.onPrimary
                else -> foregroundColor
                else -> foregroundColor
            },
            },
            label = "Pin button container color",
            label = "Pin button container color",
+9 −0
Original line number Original line Diff line number Diff line
@@ -108,6 +108,9 @@ interface AuthenticationRepository {
    /** The minimal length of a pattern. */
    /** The minimal length of a pattern. */
    val minPatternLength: Int
    val minPatternLength: Int


    /** Whether the "enhanced PIN privacy" setting is enabled for the current user. */
    val isPinEnhancedPrivacyEnabled: StateFlow<Boolean>

    /**
    /**
     * Returns the currently-configured authentication method. This determines how the
     * Returns the currently-configured authentication method. This determines how the
     * authentication challenge needs to be completed in order to unlock an otherwise locked device.
     * authentication challenge needs to be completed in order to unlock an otherwise locked device.
@@ -212,6 +215,12 @@ constructor(


    override val minPatternLength: Int = LockPatternUtils.MIN_LOCK_PATTERN_SIZE
    override val minPatternLength: Int = LockPatternUtils.MIN_LOCK_PATTERN_SIZE


    override val isPinEnhancedPrivacyEnabled: StateFlow<Boolean> =
        refreshingFlow(
            initialValue = true,
            getFreshValue = { userId -> lockPatternUtils.isPinEnhancedPrivacyEnabled(userId) },
        )

    override suspend fun getAuthenticationMethod(): AuthenticationMethodModel {
    override suspend fun getAuthenticationMethod(): AuthenticationMethodModel {
        return withContext(backgroundDispatcher) {
        return withContext(backgroundDispatcher) {
            blockingAuthenticationMethodInternal(userRepository.selectedUserId)
            blockingAuthenticationMethodInternal(userRepository.selectedUserId)
+3 −0
Original line number Original line Diff line number Diff line
@@ -145,6 +145,9 @@ constructor(
    val authenticationChallengeResult: SharedFlow<Boolean> =
    val authenticationChallengeResult: SharedFlow<Boolean> =
        repository.authenticationChallengeResult
        repository.authenticationChallengeResult


    /** Whether the "enhanced PIN privacy" setting is enabled for the current user. */
    val isPinEnhancedPrivacyEnabled: StateFlow<Boolean> = repository.isPinEnhancedPrivacyEnabled

    private var throttlingCountdownJob: Job? = null
    private var throttlingCountdownJob: Job? = null


    init {
    init {
+4 −0
Original line number Original line Diff line number Diff line
@@ -92,6 +92,10 @@ constructor(
    /** Whether the pattern should be visible for the currently-selected user. */
    /** Whether the pattern should be visible for the currently-selected user. */
    val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible
    val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible


    /** Whether the "enhanced PIN privacy" setting is enabled for the current user. */
    val isPinEnhancedPrivacyEnabled: StateFlow<Boolean> =
        authenticationInteractor.isPinEnhancedPrivacyEnabled

    /** Whether the user switcher should be displayed within the bouncer UI on large screens. */
    /** Whether the user switcher should be displayed within the bouncer UI on large screens. */
    val isUserSwitcherVisible: Boolean
    val isUserSwitcherVisible: Boolean
        get() = repository.isUserSwitcherVisible
        get() = repository.isUserSwitcherVisible
+13 −0
Original line number Original line Diff line number Diff line
@@ -84,6 +84,19 @@ class PinBouncerViewModel(


    override val throttlingMessageId = R.string.kg_too_many_failed_pin_attempts_dialog_message
    override val throttlingMessageId = R.string.kg_too_many_failed_pin_attempts_dialog_message


    /**
     * Whether the digit buttons should be animated when touched. Note that this doesn't affect the
     * delete or enter buttons; those should always animate.
     */
    val isDigitButtonAnimationEnabled: StateFlow<Boolean> =
        interactor.isPinEnhancedPrivacyEnabled
            .map { !it }
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = !interactor.isPinEnhancedPrivacyEnabled.value,
            )

    /** Notifies that the user clicked on a PIN button with the given digit value. */
    /** Notifies that the user clicked on a PIN button with the given digit value. */
    fun onPinButtonClicked(input: Int) {
    fun onPinButtonClicked(input: Int) {
        val pinInput = mutablePinInput.value
        val pinInput = mutablePinInput.value
Loading