Merge "Have turbulence noise play together with ripple on UMO button click." into udc-dev

This commit is contained in:
Yein Jo
2023-05-17 22:56:10 +00:00
committed by Android (Google) Code Review
4 changed files with 31 additions and 102 deletions

View File

@@ -21,20 +21,9 @@ import androidx.annotation.VisibleForTesting
/** Controller that handles playing [RippleAnimation]. */
class MultiRippleController(private val multipleRippleView: MultiRippleView) {
private val ripplesFinishedListeners = ArrayList<RipplesFinishedListener>()
companion object {
/** Max number of ripple animations at a time. */
@VisibleForTesting const val MAX_RIPPLE_NUMBER = 10
interface RipplesFinishedListener {
/** Triggered when all the ripples finish running. */
fun onRipplesFinish()
}
}
fun addRipplesFinishedListener(listener: RipplesFinishedListener) {
ripplesFinishedListeners.add(listener)
}
/** Updates all the ripple colors during the animation. */
@@ -52,9 +41,6 @@ class MultiRippleController(private val multipleRippleView: MultiRippleView) {
rippleAnimation.play {
// Remove ripple once the animation is done
multipleRippleView.ripples.remove(rippleAnimation)
if (multipleRippleView.ripples.isEmpty()) {
ripplesFinishedListeners.forEach { listener -> listener.onRipplesFinish() }
}
}
// Trigger drawing

View File

@@ -244,9 +244,10 @@ public class MediaControlPanel {
private MultiRippleController mMultiRippleController;
private TurbulenceNoiseController mTurbulenceNoiseController;
private final FeatureFlags mFeatureFlags;
// TODO(b/281032715): Consider making this as a final variable. For now having a null check
// due to unit test failure. (Perhaps missing some setup)
private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig;
@VisibleForTesting
MultiRippleController.Companion.RipplesFinishedListener mRipplesFinishedListener;
/**
* Initialize a new control panel
@@ -433,18 +434,6 @@ public class MediaControlPanel {
MultiRippleView multiRippleView = vh.getMultiRippleView();
mMultiRippleController = new MultiRippleController(multiRippleView);
mTurbulenceNoiseController = new TurbulenceNoiseController(vh.getTurbulenceNoiseView());
if (mFeatureFlags.isEnabled(Flags.UMO_TURBULENCE_NOISE)) {
mRipplesFinishedListener = () -> {
if (mTurbulenceNoiseAnimationConfig == null) {
mTurbulenceNoiseAnimationConfig = createTurbulenceNoiseAnimation();
}
// Color will be correctly updated in ColorSchemeTransition.
mTurbulenceNoiseController.play(mTurbulenceNoiseAnimationConfig);
mMainExecutor.executeDelayed(
mTurbulenceNoiseController::finish, TURBULENCE_NOISE_PLAY_DURATION);
};
mMultiRippleController.addRipplesFinishedListener(mRipplesFinishedListener);
}
mColorSchemeTransition = new ColorSchemeTransition(
mContext, mMediaViewHolder, mMultiRippleController, mTurbulenceNoiseController);
@@ -1150,6 +1139,18 @@ public class MediaControlPanel {
action.run();
if (mFeatureFlags.isEnabled(Flags.UMO_SURFACE_RIPPLE)) {
mMultiRippleController.play(createTouchRippleAnimation(button));
if (mFeatureFlags.isEnabled(Flags.UMO_TURBULENCE_NOISE)) {
if (mTurbulenceNoiseAnimationConfig == null) {
mTurbulenceNoiseAnimationConfig =
createTurbulenceNoiseAnimation();
}
// Color will be correctly updated in ColorSchemeTransition.
mTurbulenceNoiseController.play(mTurbulenceNoiseAnimationConfig);
mMainExecutor.executeDelayed(
mTurbulenceNoiseController::finish,
TURBULENCE_NOISE_PLAY_DURATION
);
}
}
if (icon instanceof Animatable) {
@@ -1203,10 +1204,8 @@ public class MediaControlPanel {
/* width= */ mMediaViewHolder.getMultiRippleView().getWidth(),
/* height= */ mMediaViewHolder.getMultiRippleView().getHeight(),
TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
/* easeInDuration= */
TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS,
/* easeOutDuration= */
TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS,
/* easeInDuration= */ 2500f,
/* easeOutDuration= */ 2500f,
this.getContext().getResources().getDisplayMetrics().density,
BlendMode.PLUS,
/* onAnimationEnd= */ null

View File

@@ -2381,36 +2381,28 @@ public class MediaControlPanelTest : SysuiTestCase() {
assertThat(viewHolder.multiRippleView.ripples.size).isEqualTo(0)
}
@Test
fun onButtonClick_turbulenceNoiseFlagEnabled_createsRipplesFinishedListener() {
fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, true)
player.attachPlayer(viewHolder)
assertThat(player.mRipplesFinishedListener).isNotNull()
}
@Test
fun onButtonClick_turbulenceNoiseFlagDisabled_doesNotCreateRipplesFinishedListener() {
fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, false)
player.attachPlayer(viewHolder)
assertThat(player.mRipplesFinishedListener).isNull()
}
@Test
fun playTurbulenceNoise_finishesAfterDuration() {
fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, true)
val semanticActions =
MediaButton(
playOrPause =
MediaAction(
icon = null,
action = {},
contentDescription = "play",
background = null
)
)
val data = mediaData.copy(semanticActions = semanticActions)
player.attachPlayer(viewHolder)
player.bindPlayer(data, KEY)
viewHolder.actionPlayPause.callOnClick()
mainExecutor.execute {
player.mRipplesFinishedListener.onRipplesFinish()
assertThat(turbulenceNoiseView.visibility).isEqualTo(View.VISIBLE)
clock.advanceTime(

View File

@@ -101,52 +101,4 @@ class MultiRippleControllerTest : SysuiTestCase() {
assertThat(multiRippleView.ripples.size).isEqualTo(0)
}
}
@Test
fun play_onFinishesAllRipples_triggersRipplesFinished() {
var isTriggered = false
val listener =
object : MultiRippleController.Companion.RipplesFinishedListener {
override fun onRipplesFinish() {
isTriggered = true
}
}
multiRippleController.addRipplesFinishedListener(listener)
fakeExecutor.execute {
multiRippleController.play(RippleAnimation(RippleAnimationConfig(duration = 1000)))
multiRippleController.play(RippleAnimation(RippleAnimationConfig(duration = 2000)))
assertThat(multiRippleView.ripples.size).isEqualTo(2)
fakeSystemClock.advanceTime(2000L)
assertThat(multiRippleView.ripples.size).isEqualTo(0)
assertThat(isTriggered).isTrue()
}
}
@Test
fun play_notAllRipplesFinished_doesNotTriggerRipplesFinished() {
var isTriggered = false
val listener =
object : MultiRippleController.Companion.RipplesFinishedListener {
override fun onRipplesFinish() {
isTriggered = true
}
}
multiRippleController.addRipplesFinishedListener(listener)
fakeExecutor.execute {
multiRippleController.play(RippleAnimation(RippleAnimationConfig(duration = 1000)))
multiRippleController.play(RippleAnimation(RippleAnimationConfig(duration = 2000)))
assertThat(multiRippleView.ripples.size).isEqualTo(2)
fakeSystemClock.advanceTime(1000L)
assertThat(multiRippleView.ripples.size).isEqualTo(1)
assertThat(isTriggered).isFalse()
}
}
}