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

Commit 4865cbfa authored by Sherry Zhou's avatar Sherry Zhou
Browse files

Migrate stepping animation to blueprint for default clock

Flag: ACONFIG com.android.systemui.migrate_clocks_to_blueprint
DEVELOPMENT
Bug: 315167622
Test: manually test stepping animation with flag on and off

Change-Id: Ieb697646fb3a4ada3c2cdac505f941dfea5e04db
parent 182ae92f
Loading
Loading
Loading
Loading
+10 −3
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;


import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.systemui.Flags.migrateClocksToBlueprint;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;


import android.animation.Animator;
import android.animation.Animator;
@@ -492,7 +493,12 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
            boolean splitShadeEnabled,
            boolean splitShadeEnabled,
            boolean shouldBeCentered,
            boolean shouldBeCentered,
            boolean animate) {
            boolean animate) {
        mKeyguardClockSwitchController.setSplitShadeCentered(splitShadeEnabled && shouldBeCentered);
        if (migrateClocksToBlueprint()) {
            mKeyguardInteractor.setClockShouldBeCentered(mSplitShadeEnabled && shouldBeCentered);
        } else {
            mKeyguardClockSwitchController.setSplitShadeCentered(
                    splitShadeEnabled && shouldBeCentered);
        }
        if (mStatusViewCentered == shouldBeCentered) {
        if (mStatusViewCentered == shouldBeCentered) {
            return;
            return;
        }
        }
@@ -548,8 +554,9 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
        ClockController clock = mKeyguardClockSwitchController.getClock();
        ClockController clock = mKeyguardClockSwitchController.getClock();
        boolean customClockAnimation = clock != null
        boolean customClockAnimation = clock != null
                && clock.getLargeClock().getConfig().getHasCustomPositionUpdatedAnimation();
                && clock.getLargeClock().getConfig().getHasCustomPositionUpdatedAnimation();

        // When migrateClocksToBlueprint is on, customized clock animation is conducted in
        if (customClockAnimation) {
        // KeyguardClockViewBinder
        if (customClockAnimation && !migrateClocksToBlueprint()) {
            // Find the clock, so we can exclude it from this transition.
            // Find the clock, so we can exclude it from this transition.
            FrameLayout clockContainerView = mView.findViewById(R.id.lockscreen_clock_view_large);
            FrameLayout clockContainerView = mView.findViewById(R.id.lockscreen_clock_view_large);


+89 −2
Original line number Original line Diff line number Diff line
@@ -16,13 +16,20 @@


package com.android.systemui.keyguard.ui.binder
package com.android.systemui.keyguard.ui.binder


import android.animation.Animator
import android.animation.ValueAnimator
import android.transition.Transition
import android.transition.TransitionManager
import android.transition.TransitionManager
import android.transition.TransitionSet
import android.transition.TransitionValues
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.helper.widget.Layer
import androidx.constraintlayout.helper.widget.Layer
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.animation.Interpolators
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
@@ -32,6 +39,8 @@ import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.res.R
import com.android.systemui.res.R
import kotlinx.coroutines.launch
import kotlinx.coroutines.launch


private const val KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION_MS = 1000L

object KeyguardClockViewBinder {
object KeyguardClockViewBinder {
    @JvmStatic
    @JvmStatic
    fun bind(
    fun bind(
@@ -69,12 +78,18 @@ object KeyguardClockViewBinder {
                launch {
                launch {
                    if (!migrateClocksToBlueprint()) return@launch
                    if (!migrateClocksToBlueprint()) return@launch
                    viewModel.clockShouldBeCentered.collect {
                    viewModel.clockShouldBeCentered.collect {
                        viewModel.clock?.let {
                            if (it.largeClock.config.hasCustomPositionUpdatedAnimation) {
                                playClockCenteringAnimation(clockSection, keyguardRootView, it)
                            } else {
                                applyConstraints(clockSection, keyguardRootView, true)
                                applyConstraints(clockSection, keyguardRootView, true)
                            }
                            }
                        }
                        }
                    }
                    }
                }
                }
            }
            }
        }
    }


    private fun cleanupClockViews(
    private fun cleanupClockViews(
        clockController: ClockController?,
        clockController: ClockController?,
@@ -125,12 +140,84 @@ object KeyguardClockViewBinder {
        clockSection: ClockSection,
        clockSection: ClockSection,
        rootView: ConstraintLayout,
        rootView: ConstraintLayout,
        animated: Boolean,
        animated: Boolean,
        set: TransitionSet? = null,
    ) {
    ) {
        val constraintSet = ConstraintSet().apply { clone(rootView) }
        val constraintSet = ConstraintSet().apply { clone(rootView) }
        clockSection.applyConstraints(constraintSet)
        clockSection.applyConstraints(constraintSet)
        if (animated) {
        if (animated) {
            TransitionManager.beginDelayedTransition(rootView)
            set?.let { TransitionManager.beginDelayedTransition(rootView, it) }
                ?: run { TransitionManager.beginDelayedTransition(rootView) }
        }
        }
        constraintSet.applyTo(rootView)
        constraintSet.applyTo(rootView)
    }
    }

    private fun playClockCenteringAnimation(
        clockSection: ClockSection,
        keyguardRootView: ConstraintLayout,
        clock: ClockController,
    ) {
        // Find the clock, so we can exclude it from this transition.
        val clockView = clock.largeClock.view
        val set = TransitionSet()
        val adapter = SplitShadeTransitionAdapter(clock)
        adapter.setInterpolator(Interpolators.LINEAR)
        adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION_MS)
        adapter.addTarget(clockView)
        set.addTransition(adapter)
        applyConstraints(clockSection, keyguardRootView, true, set)
    }

    internal class SplitShadeTransitionAdapter
    @VisibleForTesting
    constructor(private val clock: ClockController) : Transition() {
        private fun captureValues(transitionValues: TransitionValues) {
            transitionValues.values[PROP_BOUNDS_LEFT] = transitionValues.view.left
            val locationInWindowTmp = IntArray(2)
            transitionValues.view.getLocationInWindow(locationInWindowTmp)
            transitionValues.values[PROP_X_IN_WINDOW] = locationInWindowTmp[0]
        }

        override fun captureEndValues(transitionValues: TransitionValues) {
            captureValues(transitionValues)
        }

        override fun captureStartValues(transitionValues: TransitionValues) {
            captureValues(transitionValues)
        }

        override fun createAnimator(
            sceneRoot: ViewGroup,
            startValues: TransitionValues?,
            endValues: TransitionValues?
        ): Animator? {
            if (startValues == null || endValues == null) {
                return null
            }
            val anim = ValueAnimator.ofFloat(0f, 1f)
            val fromLeft = startValues.values[PROP_BOUNDS_LEFT] as Int
            val fromWindowX = startValues.values[PROP_X_IN_WINDOW] as Int
            val toWindowX = endValues.values[PROP_X_IN_WINDOW] as Int
            // Using windowX, to determine direction, instead of left, as in RTL the difference of
            // toLeft - fromLeft is always positive, even when moving left.
            val direction = if (toWindowX - fromWindowX > 0) 1 else -1
            anim.addUpdateListener { animation: ValueAnimator ->
                clock.largeClock.animations.onPositionUpdated(
                    fromLeft,
                    direction,
                    animation.animatedFraction
                )
            }
            return anim
        }

        override fun getTransitionProperties(): Array<String> {
            return TRANSITION_PROPERTIES
        }

        companion object {
            private const val PROP_BOUNDS_LEFT = "splitShadeTransitionAdapter:boundsLeft"
            private const val PROP_X_IN_WINDOW = "splitShadeTransitionAdapter:xInWindow"
            private val TRANSITION_PROPERTIES = arrayOf(PROP_BOUNDS_LEFT, PROP_X_IN_WINDOW)
        }
    }
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
@@ -42,6 +43,7 @@ object KeyguardSmartspaceViewBinder {
        keyguardRootView.repeatWhenAttached {
        keyguardRootView.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                launch {
                    if (!migrateClocksToBlueprint()) return@launch
                    clockViewModel.hasCustomWeatherDataDisplay.collect { hasCustomWeatherDataDisplay
                    clockViewModel.hasCustomWeatherDataDisplay.collect { hasCustomWeatherDataDisplay
                        ->
                        ->
                        if (hasCustomWeatherDataDisplay) {
                        if (hasCustomWeatherDataDisplay) {
+5 −1
Original line number Original line Diff line number Diff line
@@ -29,4 +29,8 @@ class KeyguardRootView(
    ConstraintLayout(
    ConstraintLayout(
        context,
        context,
        attrs,
        attrs,
    )
    ) {
    init {
        clipChildren = false
    }
}
+3 −8
Original line number Original line Diff line number Diff line
@@ -1751,15 +1751,10 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
        } else {
        } else {
            layout = mNotificationContainerParent;
            layout = mNotificationContainerParent;
        }
        }

        if (migrateClocksToBlueprint()) {
            mKeyguardInteractor.setClockShouldBeCentered(mSplitShadeEnabled && shouldBeCentered);
        } else {
        mKeyguardStatusViewController.updateAlignment(
        mKeyguardStatusViewController.updateAlignment(
                layout, mSplitShadeEnabled, shouldBeCentered, animate);
                layout, mSplitShadeEnabled, shouldBeCentered, animate);
        mKeyguardUnfoldTransition.ifPresent(t -> t.setStatusViewCentered(shouldBeCentered));
        mKeyguardUnfoldTransition.ifPresent(t -> t.setStatusViewCentered(shouldBeCentered));
    }
    }
    }


    private boolean shouldKeyguardStatusViewBeCentered() {
    private boolean shouldKeyguardStatusViewBeCentered() {
        if (mSplitShadeEnabled) {
        if (mSplitShadeEnabled) {