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

Commit e52858e5 authored by Daniel Chapin's avatar Daniel Chapin Committed by Android (Google) Code Review
Browse files

Merge "Revert "Update face authenticating asset"" into 24D1-dev

parents f4781550 a886be55
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@

<resources>
    <!-- Dynamic colors-->
    <color name="settingslib_color_blue700">#0B57D0</color>
    <color name="settingslib_color_blue600">#1a73e8</color>
    <color name="settingslib_color_blue400">#669df6</color>
    <color name="settingslib_color_blue300">#8ab4f8</color>
+0 −3
Original line number Diff line number Diff line
@@ -55,9 +55,6 @@ public class LottieColorUtils {
        map.put(
                ".black",
                android.R.color.white);
        map.put(
                ".blue200",
                R.color.settingslib_color_blue700);
        map.put(
                ".blue400",
                R.color.settingslib_color_blue600);
+0 −1
Original line number Diff line number Diff line
{"v":"5.7.13","fr":60,"ip":0,"op":61,"w":64,"h":64,"nm":"face_scanning 3","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,32,0],"ix":2,"l":2},"a":{"a":0,"k":[27.25,27.25,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":30,"s":[95,95,100]},{"t":60,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-1.243],[-1.244,0],[0,1.243],[1.242,0]],"o":[[0,1.243],[1.242,0],[0,-1.243],[-1.244,0]],"v":[[-2.249,0.001],[0.001,2.251],[2.249,0.001],[0.001,-2.251]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.658823529412,0.780392216701,0.980392216701,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[60]},{"t":60,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[15.1,20.495],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-1.243],[-1.242,0],[0,1.243],[1.242,0]],"o":[[0,1.243],[1.242,0],[0,-1.243],[-1.242,0]],"v":[[-2.249,0],[0.001,2.25],[2.249,0],[0.001,-2.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.658823529412,0.780392216701,0.980392216701,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[60]},{"t":60,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[39.4,20.495],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[2.814,3.523],[-2.814,3.523],[-2.814,1.363],[0.652,1.363],[0.652,-3.523],[2.814,-3.523]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.658823529412,0.780392216701,0.980392216701,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[60]},{"t":60,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[27.791,28.479],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.154,0.15],[0,0],[0.117,-0.095],[0,0],[0.228,-0.121],[0.358,-0.103],[0.922,0.261],[0.3,0.16],[0.24,0.185],[0.14,0.139],[0.178,0.261],[0.143,0.451],[0,0],[0,0.494],[0,0],[-0.214,-0.676],[-0.392,-0.572],[-0.323,-0.317],[-0.228,-0.177],[-0.333,-0.179],[-0.503,-0.145],[-0.662,0],[-0.653,0.184],[-0.437,0.233],[-0.336,0.258],[0,0],[0,0]],"o":[[0,0],[-0.107,0.106],[0,0],[-0.24,0.185],[-0.301,0.16],[-0.92,0.261],[-0.357,-0.103],[-0.228,-0.121],[-0.158,-0.122],[-0.225,-0.221],[-0.272,-0.393],[0,0],[-0.147,-0.466],[0,0],[0,0.716],[0.206,0.656],[0.256,0.372],[0.204,0.201],[0.336,0.258],[0.436,0.233],[0.655,0.184],[0.662,0],[0.503,-0.145],[0.332,-0.179],[0,0],[0,0],[0.165,-0.136]],"v":[[6.094,1.465],[4.579,-0.076],[4.242,0.225],[4.124,0.315],[3.43,0.771],[2.439,1.165],[-0.342,1.165],[-1.331,0.771],[-2.027,0.315],[-2.48,-0.075],[-3.087,-0.801],[-3.712,-2.075],[-3.712,-2.075],[-3.934,-3.523],[-6.094,-3.523],[-5.771,-1.424],[-4.868,0.424],[-3.995,1.465],[-3.344,2.027],[-2.35,2.676],[-0.934,3.243],[1.049,3.523],[3.031,3.243],[4.449,2.676],[5.441,2.027],[5.482,1.997],[5.615,1.895]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.658823529412,0.780392216701,0.980392216701,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[60]},{"t":60,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[26.201,40.411],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-13.398,0],[0,-13.4],[13.398,0],[0,13.4]],"o":[[13.398,0],[0,13.4],[-13.398,0],[0,-13.4]],"v":[[0,-24.3],[24.3,0],[0,24.3],[-24.3,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[14.904,0],[0,-14.904],[-14.904,0],[0,14.904]],"o":[[-14.904,0],[0,14.904],[14.904,0],[0,-14.904]],"v":[[0,-27],[-27,0],[0,27],[27,0]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.658823529412,0.780392216701,0.980392216701,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[60]},{"t":60,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[27.25,27.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":4,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"bm":0}],"markers":[]}
 No newline at end of file
+53 −39
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@
package com.android.systemui.biometrics.ui.binder

import android.graphics.Rect
import android.graphics.drawable.Animatable2
import android.graphics.drawable.AnimatedVectorDrawable
import android.graphics.drawable.Drawable
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
@@ -30,8 +32,8 @@ import com.android.systemui.biometrics.ui.viewmodel.PromptIconViewModel
import com.android.systemui.biometrics.ui.viewmodel.PromptIconViewModel.AuthType
import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.Utils.Companion.toQuad
import com.android.systemui.util.kotlin.Utils.Companion.toQuint
import com.android.systemui.util.kotlin.Utils.Companion.toTriple
import com.android.systemui.util.kotlin.sample
import kotlinx.coroutines.flow.combine
@@ -61,11 +63,29 @@ object PromptIconViewBinder {

                    iconOverlayView.layoutParams.width = iconViewLayoutParamSizeOverride.first
                    iconOverlayView.layoutParams.height = iconViewLayoutParamSizeOverride.second
                } else {
                    iconView.layoutParams.width = viewModel.fingerprintIconWidth.first()
                    iconView.layoutParams.height = viewModel.fingerprintIconWidth.first()

                    iconOverlayView.layoutParams.width = viewModel.fingerprintIconWidth.first()
                    iconOverlayView.layoutParams.height = viewModel.fingerprintIconWidth.first()
                }

                var faceIcon: AnimatedVectorDrawable? = null
                val faceIconCallback =
                    object : Animatable2.AnimationCallback() {
                        override fun onAnimationStart(drawable: Drawable) {
                            viewModel.onAnimationStart()
                        }

                        override fun onAnimationEnd(drawable: Drawable) {
                            viewModel.onAnimationEnd()
                        }
                    }

                launch {
                    var width = 0
                    var height = 0
                    combine(promptViewModel.size, viewModel.activeAuthType, ::Pair).collect {
                        (_, activeAuthType) ->
                        // Every time after bp shows, [isIconViewLoaded] is set to false in
@@ -75,17 +95,6 @@ object PromptIconViewBinder {
                        when (activeAuthType) {
                            AuthType.Fingerprint,
                            AuthType.Coex -> {
                                if (iconViewLayoutParamSizeOverride == null) {
                                    iconView.layoutParams.width =
                                        viewModel.fingerprintIconWidth.first()
                                    iconView.layoutParams.height =
                                        viewModel.fingerprintIconHeight.first()

                                    iconOverlayView.layoutParams.width =
                                        viewModel.fingerprintIconWidth.first()
                                    iconOverlayView.layoutParams.height =
                                        viewModel.fingerprintIconHeight.first()
                                }
                                /**
                                 * View is only set visible in BiometricViewSizeBinder once
                                 * PromptSize is determined that accounts for iconView size, to
@@ -100,10 +109,8 @@ object PromptIconViewBinder {
                                }
                            }
                            AuthType.Face -> {
                                if (iconViewLayoutParamSizeOverride == null) {
                                    iconView.layoutParams.width = viewModel.faceIconWidth
                                    iconView.layoutParams.height = viewModel.faceIconHeight
                                }
                                width = viewModel.faceIconWidth
                                height = viewModel.faceIconHeight
                                /**
                                 * Set to true by default since face icon is a drawable, which
                                 * doesn't have a LottieOnCompositionLoadedListener equivalent.
@@ -114,6 +121,13 @@ object PromptIconViewBinder {
                                promptViewModel.setIsIconViewLoaded(true)
                            }
                        }

                        if (width != 0 && height != 0) {
                            iconView.layoutParams.width = width
                            iconView.layoutParams.height = height
                            iconOverlayView.layoutParams.width = width
                            iconOverlayView.layoutParams.height = height
                        }
                    }
                }

@@ -141,13 +155,19 @@ object PromptIconViewBinder {
                            combine(
                                viewModel.activeAuthType,
                                viewModel.shouldAnimateIconView,
                                viewModel.shouldRepeatAnimation,
                                viewModel.showingError,
                                ::Triple
                            ),
                                ::toQuad
                            ),
                            ::toQuint
                        )
                        .collect { (iconAsset, activeAuthType, shouldAnimateIconView, showingError)
                            ->
                        .collect {
                            (
                                iconAsset,
                                activeAuthType,
                                shouldAnimateIconView,
                                shouldRepeatAnimation,
                                showingError) ->
                            if (iconAsset != -1) {
                                when (activeAuthType) {
                                    AuthType.Fingerprint,
@@ -160,18 +180,10 @@ object PromptIconViewBinder {
                                        }
                                    }
                                    AuthType.Face -> {
                                        // TODO(b/318569643): Consolidate logic once all face auth
                                        // assets are migrated from drawable to json
                                        if (iconAsset == R.raw.face_dialog_authenticating) {
                                            iconView.setAnimation(iconAsset)
                                            iconView.frame = 0

                                            if (shouldAnimateIconView) {
                                                iconView.playAnimation()
                                                iconView.loop(true)
                                        faceIcon?.apply {
                                            unregisterAnimationCallback(faceIconCallback)
                                            stop()
                                        }
                                        } else {
                                            faceIcon?.apply { stop() }
                                        faceIcon =
                                            iconView.context.getDrawable(iconAsset)
                                                as AnimatedVectorDrawable
@@ -179,8 +191,10 @@ object PromptIconViewBinder {
                                            iconView.setImageDrawable(this)
                                            if (shouldAnimateIconView) {
                                                forceAnimationOnUI()
                                                    start()
                                                if (shouldRepeatAnimation) {
                                                    registerAnimationCallback(faceIconCallback)
                                                }
                                                start()
                                            }
                                        }
                                    }
+77 −19
Original line number Diff line number Diff line
@@ -31,10 +31,12 @@ import com.android.systemui.res.R
import com.android.systemui.util.kotlin.combine
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map

/**
 * Models UI of [BiometricPromptLayout.iconView] and [BiometricPromptLayout.biometric_icon_overlay]
@@ -55,8 +57,11 @@ constructor(
    }

    /**
     * Indicates what auth type the UI currently displays. Fingerprint-only auth -> Fingerprint
     * Face-only auth -> Face Co-ex auth, implicit flow -> Face Co-ex auth, explicit flow -> Coex
     * Indicates what auth type the UI currently displays.
     * Fingerprint-only auth -> Fingerprint
     * Face-only auth -> Face
     * Co-ex auth, implicit flow -> Face
     * Co-ex auth, explicit flow -> Coex
     */
    val activeAuthType: Flow<AuthType> =
        combine(
@@ -124,6 +129,35 @@ constructor(
        _previousIconOverlayWasError.value = previousIconOverlayWasError
    }

    /** Called when iconView begins animating. */
    fun onAnimationStart() {
        _animationEnded.value = false
    }

    /** Called when iconView ends animating. */
    fun onAnimationEnd() {
        _animationEnded.value = true
    }

    private val _animationEnded: MutableStateFlow<Boolean> = MutableStateFlow(false)

    /**
     * Whether a face iconView should pulse (i.e. while isAuthenticating and previous animation
     * ended).
     */
    val shouldPulseAnimation: Flow<Boolean> =
        combine(_animationEnded, promptViewModel.isAuthenticating) {
                animationEnded,
                isAuthenticating ->
                animationEnded && isAuthenticating
            }
            .distinctUntilChanged()

    private val _lastPulseLightToDark: MutableStateFlow<Boolean> = MutableStateFlow(false)

    /** Tracks whether a face iconView last pulsed light to dark (vs. dark to light) */
    val lastPulseLightToDark: Flow<Boolean> = _lastPulseLightToDark.asStateFlow()

    /** Layout params for fingerprint iconView */
    val fingerprintIconWidth: Flow<Int> = promptViewModel.fingerprintSensorDiameter
    val fingerprintIconHeight: Flow<Int> = promptViewModel.fingerprintSensorDiameter
@@ -165,6 +199,17 @@ constructor(
                        }
                    }
                AuthType.Face ->
                    shouldPulseAnimation.flatMapLatest { shouldPulseAnimation: Boolean ->
                        if (shouldPulseAnimation) {
                            val iconAsset =
                                if (_lastPulseLightToDark.value) {
                                    R.drawable.face_dialog_pulse_dark_to_light
                                } else {
                                    R.drawable.face_dialog_pulse_light_to_dark
                                }
                            _lastPulseLightToDark.value = !_lastPulseLightToDark.value
                            flowOf(iconAsset)
                        } else {
                            combine(
                                promptViewModel.isAuthenticated.distinctUntilChanged(),
                                promptViewModel.isAuthenticating.distinctUntilChanged(),
@@ -182,6 +227,8 @@ constructor(
                                    showingError
                                )
                            }
                        }
                    }
                AuthType.Coex ->
                    combine(
                        displayStateInteractor.currentRotation,
@@ -284,7 +331,8 @@ constructor(
        } else if (authState.isAuthenticated) {
            R.drawable.face_dialog_dark_to_checkmark
        } else if (isAuthenticating) {
            R.raw.face_dialog_authenticating
            _lastPulseLightToDark.value = false
            R.drawable.face_dialog_pulse_dark_to_light
        } else if (showingError) {
            R.drawable.face_dialog_dark_to_error
        } else if (_previousIconWasError.value) {
@@ -659,6 +707,16 @@ constructor(
            }
        }

    /** Whether the current BiometricPromptLayout.iconView asset animation should be repeated. */
    val shouldRepeatAnimation: Flow<Boolean> =
        activeAuthType.flatMapLatest { activeAuthType: AuthType ->
            when (activeAuthType) {
                AuthType.Fingerprint,
                AuthType.Coex -> flowOf(false)
                AuthType.Face -> promptViewModel.isAuthenticating.map { it }
            }
        }

    /** Called on configuration changes */
    fun onConfigurationChanged(newConfig: Configuration) {
        displayStateInteractor.onConfigurationChanged(newConfig)
Loading