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

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23244910

Change-Id: Icf0daad76bc3d48b9b03ec1561820a262f071f79
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Yein Jo
2023-05-17 23:20:51 +00:00
committed by Automerger Merge Worker
4 changed files with 31 additions and 102 deletions

View File

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

View File

@@ -244,9 +244,10 @@ public class MediaControlPanel {
private MultiRippleController mMultiRippleController; private MultiRippleController mMultiRippleController;
private TurbulenceNoiseController mTurbulenceNoiseController; private TurbulenceNoiseController mTurbulenceNoiseController;
private final FeatureFlags mFeatureFlags; 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; private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig;
@VisibleForTesting
MultiRippleController.Companion.RipplesFinishedListener mRipplesFinishedListener;
/** /**
* Initialize a new control panel * Initialize a new control panel
@@ -433,18 +434,6 @@ public class MediaControlPanel {
MultiRippleView multiRippleView = vh.getMultiRippleView(); MultiRippleView multiRippleView = vh.getMultiRippleView();
mMultiRippleController = new MultiRippleController(multiRippleView); mMultiRippleController = new MultiRippleController(multiRippleView);
mTurbulenceNoiseController = new TurbulenceNoiseController(vh.getTurbulenceNoiseView()); 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( mColorSchemeTransition = new ColorSchemeTransition(
mContext, mMediaViewHolder, mMultiRippleController, mTurbulenceNoiseController); mContext, mMediaViewHolder, mMultiRippleController, mTurbulenceNoiseController);
@@ -1150,6 +1139,18 @@ public class MediaControlPanel {
action.run(); action.run();
if (mFeatureFlags.isEnabled(Flags.UMO_SURFACE_RIPPLE)) { if (mFeatureFlags.isEnabled(Flags.UMO_SURFACE_RIPPLE)) {
mMultiRippleController.play(createTouchRippleAnimation(button)); 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) { if (icon instanceof Animatable) {
@@ -1203,10 +1204,8 @@ public class MediaControlPanel {
/* width= */ mMediaViewHolder.getMultiRippleView().getWidth(), /* width= */ mMediaViewHolder.getMultiRippleView().getWidth(),
/* height= */ mMediaViewHolder.getMultiRippleView().getHeight(), /* height= */ mMediaViewHolder.getMultiRippleView().getHeight(),
TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS, TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
/* easeInDuration= */ /* easeInDuration= */ 2500f,
TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS, /* easeOutDuration= */ 2500f,
/* easeOutDuration= */
TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS,
this.getContext().getResources().getDisplayMetrics().density, this.getContext().getResources().getDisplayMetrics().density,
BlendMode.PLUS, BlendMode.PLUS,
/* onAnimationEnd= */ null /* onAnimationEnd= */ null

View File

@@ -2381,36 +2381,28 @@ public class MediaControlPanelTest : SysuiTestCase() {
assertThat(viewHolder.multiRippleView.ripples.size).isEqualTo(0) 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 @Test
fun playTurbulenceNoise_finishesAfterDuration() { fun playTurbulenceNoise_finishesAfterDuration() {
fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true) fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, 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.attachPlayer(viewHolder)
player.bindPlayer(data, KEY)
viewHolder.actionPlayPause.callOnClick()
mainExecutor.execute { mainExecutor.execute {
player.mRipplesFinishedListener.onRipplesFinish()
assertThat(turbulenceNoiseView.visibility).isEqualTo(View.VISIBLE) assertThat(turbulenceNoiseView.visibility).isEqualTo(View.VISIBLE)
clock.advanceTime( clock.advanceTime(

View File

@@ -101,52 +101,4 @@ class MultiRippleControllerTest : SysuiTestCase() {
assertThat(multiRippleView.ripples.size).isEqualTo(0) 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()
}
}
} }