summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt60
4 files changed, 52 insertions, 63 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index d9ee8f3f06b4..7697421256fa 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -48,7 +48,6 @@ import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.animation.Interpolator;
import android.widget.ImageButton;
import android.widget.ImageView;
@@ -552,30 +551,6 @@ public class MediaControlPanel {
// refreshState is required here to resize the text views (and prevent ellipsis)
mMediaViewController.refreshState();
-
- // Use OnPreDrawListeners to enforce zero alpha on these views for a frame.
- // TransitionLayout insists on resetting the alpha of these views to 1 when onLayout
- // is called which causes the animation to look bad. These suppress that behavior.
- titleText.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- titleText.setAlpha(0);
- titleText.getViewTreeObserver().removeOnPreDrawListener(this);
- return true;
- }
- });
-
- artistText.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- artistText.setAlpha(0);
- artistText.getViewTreeObserver().removeOnPreDrawListener(this);
- return true;
- }
- });
-
return Unit.INSTANCE;
},
() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt b/packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt
index 9a1a6d35e3e3..48f4a16cc538 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt
@@ -18,8 +18,6 @@ package com.android.systemui.media
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
-import android.animation.AnimatorSet
-import com.android.internal.annotations.VisibleForTesting
/**
* MetadataAnimationHandler controls the current state of the MediaControlPanel's transition motion.
@@ -33,37 +31,37 @@ internal open class MetadataAnimationHandler(
private val enterAnimator: Animator
) : AnimatorListenerAdapter() {
- private val animator: AnimatorSet
private var postExitUpdate: (() -> Unit)? = null
private var postEnterUpdate: (() -> Unit)? = null
private var targetData: Any? = null
val isRunning: Boolean
- get() = animator.isRunning
+ get() = enterAnimator.isRunning || exitAnimator.isRunning
fun setNext(targetData: Any, postExit: () -> Unit, postEnter: () -> Unit): Boolean {
if (targetData != this.targetData) {
this.targetData = targetData
postExitUpdate = postExit
postEnterUpdate = postEnter
- if (!animator.isRunning) {
- animator.start()
+ if (!isRunning) {
+ exitAnimator.start()
}
return true
}
return false
}
- override fun onAnimationEnd(animator: Animator) {
- if (animator === exitAnimator) {
+ override fun onAnimationEnd(anim: Animator) {
+ if (anim === exitAnimator) {
postExitUpdate?.let { it() }
postExitUpdate = null
+ enterAnimator.start()
}
- if (animator === enterAnimator) {
+ if (anim === enterAnimator) {
// Another new update appeared while entering
if (postExitUpdate != null) {
- this.animator.start()
+ exitAnimator.start()
} else {
postEnterUpdate?.let { it() }
postEnterUpdate = null
@@ -74,13 +72,5 @@ internal open class MetadataAnimationHandler(
init {
exitAnimator.addListener(this)
enterAnimator.addListener(this)
- animator = buildAnimatorSet(exitAnimator, enterAnimator)
- }
-
- @VisibleForTesting
- protected open fun buildAnimatorSet(exit: Animator, enter: Animator): AnimatorSet {
- val result = AnimatorSet()
- result.playSequentially(exitAnimator, enterAnimator)
- return result
}
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index b8c85bb41726..f4dba7bc41a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -951,7 +951,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
// Rebinding should not trigger animation
player.bindPlayer(mediaData, PACKAGE)
- verify(mockAnimator, times(1)).start()
+ verify(mockAnimator, times(2)).start()
}
@Test
@@ -973,7 +973,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
// Bind trigges new animation
player.bindPlayer(data1, PACKAGE)
- verify(mockAnimator, times(2)).start()
+ verify(mockAnimator, times(3)).start()
whenever(mockAnimator.isRunning()).thenReturn(true)
// Rebind before animation end binds corrct data
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt
index 52cb902a4f38..311aa9649911 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt
@@ -18,7 +18,6 @@ package com.android.systemui.media
import org.mockito.Mockito.`when` as whenever
import android.animation.Animator
-import android.animation.AnimatorSet
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
@@ -44,7 +43,6 @@ class MetadataAnimationHandlerTest : SysuiTestCase() {
private interface Callback : () -> Unit
private lateinit var handler: MetadataAnimationHandler
- @Mock private lateinit var animatorSet: AnimatorSet
@Mock private lateinit var enterAnimator: Animator
@Mock private lateinit var exitAnimator: Animator
@Mock private lateinit var postExitCB: Callback
@@ -54,11 +52,7 @@ class MetadataAnimationHandlerTest : SysuiTestCase() {
@Before
fun setUp() {
- handler = object : MetadataAnimationHandler(exitAnimator, enterAnimator) {
- override fun buildAnimatorSet(exit: Animator, enter: Animator): AnimatorSet {
- return animatorSet
- }
- }
+ handler = MetadataAnimationHandler(exitAnimator, enterAnimator)
}
@After
@@ -69,22 +63,31 @@ class MetadataAnimationHandlerTest : SysuiTestCase() {
val cb = { fail("Unexpected callback") }
handler.setNext("data-1", cb, cb)
- verify(animatorSet).start()
+ verify(exitAnimator).start()
}
@Test
fun executeAnimationEnd_runsCallacks() {
+ // We expect this first call to only start the exit animator
handler.setNext("data-1", postExitCB, postEnterCB)
- verify(animatorSet, times(1)).start()
+ verify(exitAnimator, times(1)).start()
+ verify(enterAnimator, never()).start()
verify(postExitCB, never()).invoke()
+ verify(postEnterCB, never()).invoke()
+ // After the exit animator completes,
+ // the exit cb should run, and enter animation should start
handler.onAnimationEnd(exitAnimator)
- verify(animatorSet, times(1)).start()
+ verify(exitAnimator, times(1)).start()
+ verify(enterAnimator, times(1)).start()
verify(postExitCB, times(1)).invoke()
verify(postEnterCB, never()).invoke()
+ // After the exit animator completes,
+ // the enter cb should run without other state changes
handler.onAnimationEnd(enterAnimator)
- verify(animatorSet, times(1)).start()
+ verify(exitAnimator, times(1)).start()
+ verify(enterAnimator, times(1)).start()
verify(postExitCB, times(1)).invoke()
verify(postEnterCB, times(1)).invoke()
}
@@ -120,38 +123,58 @@ class MetadataAnimationHandlerTest : SysuiTestCase() {
val postExitCB2 = mock(Callback::class.java)
val postEnterCB2 = mock(Callback::class.java)
+ // We expect this first call to only start the exit animator
handler.setNext("data-1", postExitCB, postEnterCB)
- verify(animatorSet, times(1)).start()
+ verify(exitAnimator, times(1)).start()
+ verify(enterAnimator, never()).start()
verify(postExitCB, never()).invoke()
verify(postExitCB2, never()).invoke()
verify(postEnterCB, never()).invoke()
verify(postEnterCB2, never()).invoke()
- whenever(animatorSet.isRunning()).thenReturn(true)
+ // After the exit animator completes,
+ // the exit cb should run, and enter animation should start
+ whenever(exitAnimator.isRunning()).thenReturn(true)
+ whenever(enterAnimator.isRunning()).thenReturn(false)
handler.onAnimationEnd(exitAnimator)
- verify(animatorSet, times(1)).start()
+ verify(exitAnimator, times(1)).start()
+ verify(enterAnimator, times(1)).start()
verify(postExitCB, times(1)).invoke()
verify(postExitCB2, never()).invoke()
verify(postEnterCB, never()).invoke()
verify(postEnterCB2, never()).invoke()
+ // Setting new data before the enter animator completes should not trigger
+ // the exit animator an additional time (since it's already running)
+ whenever(exitAnimator.isRunning()).thenReturn(false)
+ whenever(enterAnimator.isRunning()).thenReturn(true)
handler.setNext("data-2", postExitCB2, postEnterCB2)
+ verify(exitAnimator, times(1)).start()
+
+ // Finishing the enterAnimator should cause the exitAnimator to fire again
+ // since the data change and additional time. No enterCB should be executed.
handler.onAnimationEnd(enterAnimator)
- verify(animatorSet, times(2)).start()
+ verify(exitAnimator, times(2)).start()
+ verify(enterAnimator, times(1)).start()
verify(postExitCB, times(1)).invoke()
verify(postExitCB2, never()).invoke()
verify(postEnterCB, never()).invoke()
verify(postEnterCB2, never()).invoke()
+ // Continuing the sequence, this triggers the enter animator an additional time
handler.onAnimationEnd(exitAnimator)
- verify(animatorSet, times(2)).start()
+ verify(exitAnimator, times(2)).start()
+ verify(enterAnimator, times(2)).start()
verify(postExitCB, times(1)).invoke()
verify(postExitCB2, times(1)).invoke()
verify(postEnterCB, never()).invoke()
verify(postEnterCB2, never()).invoke()
+ // And finally the enter animator completes,
+ // triggering the correct postEnterCallback to fire
handler.onAnimationEnd(enterAnimator)
- verify(animatorSet, times(2)).start()
+ verify(exitAnimator, times(2)).start()
+ verify(enterAnimator, times(2)).start()
verify(postExitCB, times(1)).invoke()
verify(postExitCB2, times(1)).invoke()
verify(postEnterCB, never()).invoke()
@@ -172,6 +195,7 @@ class MetadataAnimationHandlerTest : SysuiTestCase() {
fun enterAnimatorEndsWithoutCallback_noAnimatiorStart() {
handler.onAnimationEnd(enterAnimator)
- verify(animatorSet, never()).start()
+ verify(exitAnimator, never()).start()
+ verify(enterAnimator, never()).start()
}
}