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

Commit 2d7be5f4 authored by Selim Cinek's avatar Selim Cinek
Browse files

Made the animation logic more stable

We're now using the most recent state of the last attached location
for the animation start, since otherwise this could be flickering.
The animation could detoriate if the view wasn't attached
to the screen anymore as a result, which is fixed as well.

Bug: 154137987
Test: add media notification, observe
Change-Id: I1a6dfa651d676b3d620577fbd6c9e6a5d833dc0c
parent 54809628
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
package com.android.systemui.media

import android.view.View
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.MediaHeaderView
import com.android.systemui.statusbar.phone.KeyguardBypassController
import javax.inject.Inject
@@ -29,8 +32,17 @@ import javax.inject.Singleton
@Singleton
class KeyguardMediaController @Inject constructor(
    private val mediaHost: MediaHost,
    private val bypassController: KeyguardBypassController
    private val bypassController: KeyguardBypassController,
    private val statusBarStateController: SysuiStatusBarStateController
) {

    init {
        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
            override fun onStateChanged(newState: Int) {
                updateVisibility()
            }
        })
    }
    private var view: MediaHeaderView? = null

    /**
@@ -38,18 +50,21 @@ class KeyguardMediaController @Inject constructor(
     */
    fun attach(mediaView: MediaHeaderView) {
        view = mediaView
        mediaHost.visibleChangedListener = ::updateVisibility
        // First let's set the desired state that we want for this host
        mediaHost.visibleChangedListener = { updateVisibility() }
        mediaHost.expansion = 0.0f
        mediaHost.showsOnlyActiveMedia = true

        // Let's now initialize this view, which also creates the host view for us.
        mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
        mediaView.setMediaHost(mediaHost.hostView)
    /**
     * Attach this controller to a media view, initializing its state
     */
        mediaView.setContentView(mediaHost.hostView)
    }

    private fun updateVisibility(isVisible: Boolean) {
        val shouldBeVisible = isVisible && !bypassController.bypassEnabled
    private fun updateVisibility() {
        val shouldBeVisible = mediaHost.visible
                && !bypassController.bypassEnabled
                && (statusBarStateController.state == StatusBarState.KEYGUARD ||
                        statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
        view?.visibility = if (shouldBeVisible) View.VISIBLE else View.GONE
    }
}
+25 −7
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ class MediaHierarchyManager @Inject constructor(
    private val mediaCarousel
        get() =  mediaViewManager.mediaCarousel
    private var animationStartState: MediaState? = null
    private var statusbarState: Int = statusBarStateController.state
    private var animator = ValueAnimator.ofFloat(0.0f, 1.0f).apply {
        interpolator = Interpolators.FAST_OUT_SLOW_IN
        addUpdateListener {
@@ -96,9 +97,16 @@ class MediaHierarchyManager @Inject constructor(

    init {
        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
            override fun onStateChanged(newState: Int) {
            override fun onStatePreChange(oldState: Int, newState: Int) {
                // We're updating the location before the state change happens, since we want the
                // location of the previous state to still be up to date when the animation starts
                statusbarState = newState
                updateDesiredLocation()
            }

            override fun onStateChanged(newState: Int) {
                updateTargetState()
            }
        })
    }

@@ -168,14 +176,24 @@ class MediaHierarchyManager @Inject constructor(
        val previousHost = getHost(previousLocation)
        if (currentHost == null || previousHost == null) {
            cancelAnimationAndApplyDesiredState()
            return
        }
        updateTargetState()
        if (isCurrentlyInGuidedTransformation()) {
            applyTargetStateIfNotAnimating()
        } else if (animate) {
            animator.cancel()
            if (currentAttachmentLocation == IN_OVERLAY
                    || !previousHost.hostView.isAttachedToWindow) {
                // Let's animate to the new position, starting from the current position
                // We also go in here in case the view was detached, since the bounds wouldn't
                // be correct anymore
                animationStartState = currentState.copy()
            } else {
                // otherwise, let's take the freshest state, since the current one could
                // be outdated
                animationStartState = previousHost.currentState.copy()
            }
            adjustAnimatorForTransition(desiredLocation, previousLocation)
            animator.start()
        } else {
@@ -190,7 +208,7 @@ class MediaHierarchyManager @Inject constructor(
        if (currentLocation == LOCATION_QQS
                && previousLocation == LOCATION_LOCKSCREEN
                && (statusBarStateController.leaveOpenOnKeyguardHide()
                        || statusBarStateController.state == StatusBarState.SHADE_LOCKED)) {
                        || statusbarState == StatusBarState.SHADE_LOCKED)) {
            // Usually listening to the isShown is enough to determine this, but there is some
            // non-trivial reattaching logic happening that will make the view not-shown earlier
            return true
@@ -212,7 +230,7 @@ class MediaHierarchyManager @Inject constructor(
        var delay = 0L
        if (previousLocation == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QQS) {
            // Going to the full shade, let's adjust the animation duration
            if (statusBarStateController.state == StatusBarState.SHADE
            if (statusbarState == StatusBarState.SHADE
                    && keyguardStateController.isKeyguardFadingAway) {
                delay = keyguardStateController.keyguardFadingAwayDelay
            }
@@ -330,8 +348,8 @@ class MediaHierarchyManager @Inject constructor(
    @MediaLocation
    private fun calculateLocation() : Int {
        val onLockscreen = (!bypassController.bypassEnabled
                && (statusBarStateController.state == StatusBarState.KEYGUARD
                || statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER))
                && (statusbarState == StatusBarState.KEYGUARD
                || statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER))
        return when {
            qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
            qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
+4 −1
Original line number Diff line number Diff line
@@ -59,7 +59,10 @@ class MediaHost @Inject constructor(
    }

    /**
     * Initialize this MediaObject and create a host view
     * Initialize this MediaObject and create a host view.
     *
     * @param location the location this host name has. Used to identify the host during
     *                 transitions.
     */
    fun init(@MediaLocation location: Int) {
        this.location = location;
+4 −4
Original line number Diff line number Diff line
@@ -53,10 +53,10 @@ public class MediaHeaderView extends ActivatableNotificationView {
        setTintColor(color);
    }

    public void setMediaHost(ViewGroup mediaHost) {
        mContentView = mediaHost;
        addView(mediaHost);
        ViewGroup.LayoutParams layoutParams = mediaHost.getLayoutParams();
    public void setContentView(ViewGroup contentView) {
        mContentView = contentView;
        addView(contentView);
        ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
        layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
    }
+1 −2
Original line number Diff line number Diff line
@@ -266,7 +266,6 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section

        final boolean showHeaders = mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
        final boolean usingPeopleFiltering = mSectionsFeatureManager.isFilteringEnabled();
        final boolean isKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
        final boolean usingMediaControls = mSectionsFeatureManager.isMediaControlsEnabled();

        boolean peopleNotifsPresent = false;
@@ -274,7 +273,7 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
        int currentMediaControlsIdx = -1;
        // Currently, just putting media controls in the front and incrementing the position based
        // on the number of heads-up notifs.
        int mediaControlsTarget = isKeyguard && usingMediaControls ? 0 : -1;
        int mediaControlsTarget = usingMediaControls ? 0 : -1;
        int currentIncomingHeaderIdx = -1;
        int incomingHeaderTarget = -1;
        int currentPeopleHeaderIdx = -1;
Loading