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

Commit 2641ab1c authored by Beverly's avatar Beverly
Browse files

Update DeviceEntryViewModel transition source to transitionValue

- Only update deviceEntryIcon burnIn when AOD transitions update
by calling transitionInteractor.transitionValue.
- This CL also adds coroutine tracing for better traces.

Bug: 335673842
Flag: ACONFIG com.android.systemui.device_entry_udfps_refactor NEXTFOOD
Test: Check CoroutineContinuations in the perfetto trace for
DeviceEntryIconViewBinder#viewModel.burnInOffsets - there are a lot less
now when the device isn't transitioning to AOD.

Change-Id: Id202f6f517d2a3ac96d4e4a2b6bbf6dfa50956e8
parent 12753147
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.view.View
import androidx.core.view.isInvisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.tracing.coroutines.launch
import com.android.systemui.common.ui.view.LongPressHandlingView
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
@@ -40,6 +41,7 @@ import kotlinx.coroutines.launch

@ExperimentalCoroutinesApi
object DeviceEntryIconViewBinder {
    private const val TAG = "DeviceEntryIconViewBinder"

    /**
     * Updates UI for:
@@ -82,22 +84,22 @@ object DeviceEntryIconViewBinder {
            // GONE => AOD transition (even though the view may not be visible until the middle
            // of the transition.
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                launch {
                launch("$TAG#viewModel.isVisible") {
                    viewModel.isVisible.collect { isVisible ->
                        longPressHandlingView.isInvisible = !isVisible
                    }
                }
                launch {
                launch("$TAG#viewModel.isLongPressEnabled") {
                    viewModel.isLongPressEnabled.collect { isEnabled ->
                        longPressHandlingView.setLongPressHandlingEnabled(isEnabled)
                    }
                }
                launch {
                launch("$TAG#viewModel.accessibilityDelegateHint") {
                    viewModel.accessibilityDelegateHint.collect { hint ->
                        view.accessibilityHintType = hint
                    }
                }
                launch {
                launch("$TAG#viewModel.useBackgroundProtection") {
                    viewModel.useBackgroundProtection.collect { useBackgroundProtection ->
                        if (useBackgroundProtection) {
                            bgView.visibility = View.VISIBLE
@@ -106,7 +108,7 @@ object DeviceEntryIconViewBinder {
                        }
                    }
                }
                launch {
                launch("$TAG#viewModel.burnInOffsets") {
                    viewModel.burnInOffsets.collect { burnInOffsets ->
                        view.translationX = burnInOffsets.x.toFloat()
                        view.translationY = burnInOffsets.y.toFloat()
@@ -114,7 +116,9 @@ object DeviceEntryIconViewBinder {
                    }
                }

                launch { viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha } }
                launch("$TAG#viewModel.deviceEntryViewAlpha") {
                    viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha }
                }
            }
        }

@@ -122,7 +126,7 @@ object DeviceEntryIconViewBinder {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                // Start with an empty state
                fgIconView.setImageState(StateSet.NOTHING, /* merge */ false)
                launch {
                launch("$TAG#fpIconView.viewModel") {
                    fgViewModel.viewModel.collect { viewModel ->
                        fgIconView.setImageState(
                            view.getIconState(viewModel.type, viewModel.useAodVariant),
@@ -144,8 +148,10 @@ object DeviceEntryIconViewBinder {

        bgView.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                launch { bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha } }
                launch {
                launch("$TAG#bgViewModel.alpha") {
                    bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha }
                }
                launch("$TAG#bgViewModel.color") {
                    bgViewModel.color.collect { color ->
                        bgView.imageTintList = ColorStateList.valueOf(color)
                    }
+46 −62
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn

/** Models the UI state for the containing device entry icon & long-press handling view. */
@ExperimentalCoroutinesApi
@@ -110,27 +111,7 @@ constructor(
            )
        }

    private val dozeAmount: Flow<Float> =
        combine(
            transitionInteractor.startedKeyguardTransitionStep,
            merge(
                transitionInteractor.transitionStepsFromState(KeyguardState.AOD).map {
                    1f - it.value
                },
                transitionInteractor.transitionStepsToState(KeyguardState.AOD).map { it.value }
            ),
        ) { startedKeyguardTransitionStep, aodTransitionAmount ->
            if (
                startedKeyguardTransitionStep.to == KeyguardState.AOD ||
                    startedKeyguardTransitionStep.from == KeyguardState.AOD
            ) {
                aodTransitionAmount
            } else {
                // in case a new transition (ie: to occluded) cancels a transition to or from
                // aod, then we want to make sure the doze amount is still updated to 0
                0f
            }
        }
    private val dozeAmount: Flow<Float> = transitionInteractor.transitionValue(KeyguardState.AOD)
    // Burn-in offsets that animate based on the transition amount to AOD
    private val animatedBurnInOffsets: Flow<BurnInOffsets> =
        combine(nonAnimatedBurnInOffsets, dozeAmount) { burnInOffsets, dozeAmount ->
@@ -141,16 +122,18 @@ constructor(
            )
        }

    val deviceEntryViewAlpha: Flow<Float> =
    val deviceEntryViewAlpha: StateFlow<Float> =
        combine(
                transitionAlpha,
                alphaMultiplierFromShadeExpansion,
            ) { alpha, alphaMultiplier ->
                alpha * alphaMultiplier
            }
            .stateIn(scope = scope, started = SharingStarted.WhileSubscribed(), initialValue = 0f)
    val useBackgroundProtection: StateFlow<Boolean> = isUdfpsSupported
    val burnInOffsets: Flow<BurnInOffsets> =
        deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { udfpsEnrolled ->
        deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled
            .flatMapLatest { udfpsEnrolled ->
                if (udfpsEnrolled) {
                    combine(
                        transitionInteractor.startedKeyguardTransitionStep.sample(
@@ -189,6 +172,7 @@ constructor(
                    flowOf(BurnInOffsets(x = 0, y = 0, progress = 0f))
                }
            }
            .distinctUntilChanged()

    private val isUnlocked: Flow<Boolean> =
        keyguardInteractor.isKeyguardDismissible.flatMapLatest { isUnlocked ->