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

Commit 86b8eb03 authored by Grace Cheng's avatar Grace Cheng Committed by Android (Google) Code Review
Browse files

Merge "SysUI arch updates for SL composable" into main

parents fadc085a e1a40c80
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -293,9 +293,10 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
                    && keyguardInputView instanceof KeyguardSecureLockDeviceBiometricAuthView) {
                return new KeyguardSecureLockDeviceBiometricAuthViewController(
                        (KeyguardSecureLockDeviceBiometricAuthView) keyguardInputView,
                        mSecureLockDeviceViewModelFactory, mSelectedUserInteractor,
                        securityMode, keyguardSecurityCallback, emergencyButtonController,
                        mMessageAreaControllerFactory, mFeatureFlags, mBouncerHapticPlayer);
                        mSecureLockDeviceViewModelFactory, mSecureLockDeviceInteractor,
                        mSelectedUserInteractor, securityMode, keyguardSecurityCallback,
                        emergencyButtonController, mMessageAreaControllerFactory, mFeatureFlags,
                        mBouncerHapticPlayer);
            }
            if (keyguardInputView instanceof KeyguardPatternView) {
                return new KeyguardPatternViewController((KeyguardPatternView) keyguardInputView,
+8 −14
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ import com.android.systemui.flags.FeatureFlags
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.securelockdevice.ui.SecureLockDeviceContent
import com.android.systemui.securelockdevice.domain.interactor.SecureLockDeviceInteractor
import com.android.systemui.securelockdevice.ui.composable.SecureLockDeviceContent
import com.android.systemui.securelockdevice.ui.viewmodel.SecureLockDeviceBiometricAuthContentViewModel
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import kotlinx.coroutines.launch
@@ -36,7 +37,9 @@ import kotlinx.coroutines.launch
 */
class KeyguardSecureLockDeviceBiometricAuthViewController(
    private val view: KeyguardSecureLockDeviceBiometricAuthView,
    secureLockDeviceViewModelFactory: SecureLockDeviceBiometricAuthContentViewModel.Factory,
    private val secureLockDeviceViewModelFactory:
        SecureLockDeviceBiometricAuthContentViewModel.Factory,
    private val secureLockDeviceInteractor: SecureLockDeviceInteractor,
    selectedUserInteractor: SelectedUserInteractor,
    securityMode: KeyguardSecurityModel.SecurityMode?,
    keyguardSecurityCallback: KeyguardSecurityCallback?,
@@ -56,9 +59,6 @@ class KeyguardSecureLockDeviceBiometricAuthViewController(
        bouncerHapticPlayer,
    ) {

    private val secureLockDeviceViewModel: SecureLockDeviceBiometricAuthContentViewModel =
        secureLockDeviceViewModelFactory.create()

    public override fun onInit() {
        if (SceneContainerFlag.isEnabled) {
            return
@@ -71,17 +71,12 @@ class KeyguardSecureLockDeviceBiometricAuthViewController(
                id = R.id.secure_lock_device_biometric_auth_content
                setContent {
                    SecureLockDeviceContent(
                        secureLockDeviceViewModel = secureLockDeviceViewModel,
                        secureLockDeviceViewModelFactory = secureLockDeviceViewModelFactory,
                        modifier = Modifier.fillMaxSize(),
                    )
                }
            }
        view.repeatWhenAttached {
            lifecycleScope.launch {
                view.addView(composeView)
                secureLockDeviceViewModel.activate()
            }
        }
        view.repeatWhenAttached { lifecycleScope.launch { view.addView(composeView) } }
    }

    override fun updateMessageAreaVisibility() {}
@@ -95,12 +90,11 @@ class KeyguardSecureLockDeviceBiometricAuthViewController(
    override fun needsInput(): Boolean = false

    override fun startAppearAnimation() {
        secureLockDeviceViewModel.startAppearAnimation()
        super.startAppearAnimation()
    }

    override fun startDisappearAnimation(finishRunnable: Runnable?): Boolean {
        secureLockDeviceViewModel.setDisappearAnimationFinishedRunnable(finishRunnable)
        secureLockDeviceInteractor.setDisappearAnimationFinishedRunnable(finishRunnable)
        return true
    }

+61 −18
Original line number Diff line number Diff line
@@ -25,13 +25,14 @@ import android.graphics.Rect
import android.hardware.biometrics.Flags
import android.security.Flags.secureLockDevice
import android.util.RotationUtils
import androidx.compose.runtime.getValue
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
import com.android.systemui.biometrics.ui.PromptIconState
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.display.domain.interactor.DisplayStateInteractor
import com.android.systemui.display.shared.model.DisplayRotation
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.HydratedActivatable
import com.android.systemui.res.R
import com.android.systemui.securelockdevice.ui.viewmodel.SecureLockDeviceBiometricAuthContentViewModel
import com.android.systemui.util.kotlin.Quad
@@ -64,7 +65,7 @@ constructor(
    @Application private val applicationContext: Context,
    private val displayStateInteractor: DisplayStateInteractor,
    udfpsOverlayInteractor: UdfpsOverlayInteractor,
) : ExclusiveActivatable() {
) : HydratedActivatable() {

    /** Biometric auth modalities for the UI to display */
    enum class BiometricAuthModalities {
@@ -110,22 +111,27 @@ constructor(
        }

    private val hasSfps: Flow<Boolean> =
        if (promptViewModel != null) {
            promptViewModel.modalities.map { it.hasSfps }
        } else if (secureLockDevice() && secureLockDeviceViewModel != null) {
        promptViewModel?.modalities?.map { it.hasSfps }
            ?: if (secureLockDevice() && secureLockDeviceViewModel != null) {
                secureLockDeviceViewModel.enrolledStrongBiometrics.map { it.hasSfps }
            } else {
                flowOf(false)
            }

    /** Whether UDFPS is available on the biometric prompt. */
    val hasUdfps: Flow<Boolean> =
        if (promptViewModel != null) {
            promptViewModel.modalities.map { it.hasUdfps }
        } else if (secureLockDevice() && secureLockDeviceViewModel != null) {
        promptViewModel?.modalities?.map { it.hasUdfps }
            ?: if (secureLockDevice() && secureLockDeviceViewModel != null) {
                secureLockDeviceViewModel.enrolledStrongBiometrics.map { it.hasUdfps }
            } else {
                flowOf(false)
            }
    /**
     * Hydrated state version of [hasUdfps] for use in composables. Should replace [hasUdfps] when
     * legacy icon view / view-binder are fully migrated to compose.
     */
    val hasUdfpsState: Boolean by
        hasUdfps.hydratedStateOf(traceName = "hasUdfps", initialValue = false)

    /** If the user is currently authenticating (i.e. at least one biometric is scanning). */
    val isAuthenticating: Flow<Boolean> =
@@ -136,6 +142,12 @@ constructor(
    /** Whether an error message is currently being shown. */
    val showingError: Flow<Boolean> =
        promptViewModel?.showingError ?: secureLockDeviceViewModel?.showingError ?: emptyFlow()
    /**
     * Hydrated state version of [showingError] for use in composables. Should replace
     * [showingError] when legacy icon view / view-binder are fully migrated to compose.
     */
    val showingErrorState: Boolean by
        showingError.hydratedStateOf(traceName = "showingError", initialValue = false)

    /** Whether the previous icon shown displayed an error. */
    internal val previousIconWasError: MutableStateFlow<Boolean> = MutableStateFlow(false)
@@ -151,10 +163,15 @@ constructor(
            ?: emptyFlow()

    /** If the auth is pending confirmation. */
    val isPendingConfirmation: Flow<Boolean> =
    private val isPendingConfirmation: Flow<Boolean> =
        isAuthenticated.map { authState ->
            authState.isAuthenticated && authState.needsUserConfirmation
        }
    val isPendingConfirmationState: Boolean by
        isPendingConfirmation.hydratedStateOf(
            traceName = "isPendingConfirmation",
            initialValue = false,
        )

    /** Current biometric icon asset. */
    val iconAsset: Flow<Int> =
@@ -340,6 +357,13 @@ constructor(
            }
        }

    /**
     * Hydrated state version of [iconSize] for use in composables. Should replace [iconSize] when
     * legacy icon view / view-binder are fully migrated to compose.
     */
    val iconSizeState: Pair<Int, Int> by
        iconSize.hydratedStateOf(traceName = "iconSize", initialValue = Pair(0, 0))

    /** Content description for iconView */
    val contentDescriptionId: Flow<Int> =
        activeBiometricAuthType.flatMapLatest { modalities ->
@@ -507,6 +531,24 @@ constructor(
                )
            }
            .distinctUntilChanged()
    /**
     * Hydrated state version of [iconState] for use in composables. Should replace [iconState] when
     * legacy icon view / view-binder are fully migrated to compose.
     */
    val hydratedIconState: PromptIconState by
        iconState.hydratedStateOf(
            traceName = "iconState",
            initialValue =
                PromptIconState(
                    asset = -1,
                    shouldAnimate = false,
                    shouldLoop = false,
                    contentDescriptionId = -1,
                    rotation = 0f,
                    activeBiometricAuthType = BiometricAuthModalities.None,
                    showingError = false,
                ),
        )

    fun onConfigurationChanged(newConfig: Configuration) {
        displayStateInteractor.onConfigurationChanged(newConfig)
@@ -702,7 +744,8 @@ constructor(
        when {
            authState.isAuthenticatedAndExplicitlyConfirmed ->
                R.string.biometric_dialog_face_icon_description_confirmed
            authState.isAuthenticated -> R.string.biometric_dialog_face_icon_description_authenticated
            authState.isAuthenticated ->
                R.string.biometric_dialog_face_icon_description_authenticated
            isAuthenticating -> R.string.biometric_dialog_face_icon_description_authenticating
            showingError -> R.string.keyguard_face_failed
            else -> R.string.biometric_dialog_face_icon_description_idle
+30 −4
Original line number Diff line number Diff line
@@ -25,17 +25,31 @@ import com.android.systemui.biometrics.ui.PromptPosition
import com.android.systemui.biometrics.ui.isMedium
import com.android.systemui.biometrics.ui.isSmall
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.res.R
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged

/** Models UI of [BiometricPromptLayout.iconView] */
class PromptIconViewModel(
    promptViewModel: PromptViewModel,
class PromptIconViewModel
@AssistedInject
constructor(
    @Assisted private val promptViewModel: PromptViewModel,
    @Assisted private val biometricAuthIconViewModelFactory: BiometricAuthIconViewModel.Factory,
    @Application private val context: Context,
    val internal: BiometricAuthIconViewModel,
) {
) : ExclusiveActivatable() {
    val internal: BiometricAuthIconViewModel =
        biometricAuthIconViewModelFactory.create(
            promptViewModel = promptViewModel,
            secureLockDeviceViewModel = null,
        )

    /** Padding for placing icons */
    val portraitSmallBottomPadding =
        context.resources.getDimensionPixelSize(
@@ -151,4 +165,16 @@ class PromptIconViewModel(
    fun onConfigurationChanged(newConfig: Configuration) {
        internal.onConfigurationChanged(newConfig)
    }

    @AssistedFactory
    interface Factory {
        fun create(
            promptViewModel: PromptViewModel,
            biometricAuthIconViewModelFactory: BiometricAuthIconViewModel.Factory,
        ): PromptIconViewModel
    }

    override suspend fun onActivated(): Nothing {
        coroutineScope { awaitCancellation() }
    }
}
+7 −9
Original line number Diff line number Diff line
@@ -102,8 +102,9 @@ constructor(
    accessibilityManager: AccessibilityManager,
    promptFallbackViewModelFactory: PromptFallbackViewModel.Factory,
    shadeInteractor: ShadeInteractor,
    promptIconViewModelFactory: PromptIconViewModel.Factory,
    biometricAuthIconViewModelFactory: BiometricAuthIconViewModel.Factory,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
) {
    /** Viewmodel for the fallback view */
    val promptFallbackViewModel = promptFallbackViewModelFactory.create()
@@ -400,15 +401,12 @@ constructor(
        promptSelectorInteractor.prompt.map { it?.contentView }.distinctUntilChanged()

    /** ViewModel for the biometric icon in the prompt. */
    val iconViewModel =
        PromptIconViewModel(
            this,
            context,
            biometricAuthIconViewModelFactory.create(
    val iconViewModel: PromptIconViewModel by lazy {
        promptIconViewModelFactory.create(
            promptViewModel = this,
                secureLockDeviceViewModel = null,
            ),
            biometricAuthIconViewModelFactory = biometricAuthIconViewModelFactory,
        )
    }

    private val originalDescription =
        promptSelectorInteractor.prompt.map { it?.description ?: "" }.distinctUntilChanged()
Loading