diff options
4 files changed, 81 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt index e38abc2228c4..6eaff3fcb929 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt @@ -56,6 +56,7 @@ open class SeekBarObserver(private val holder: MediaViewHolder) : R.dimen.qs_media_session_disabled_seekbar_vertical_padding ) var seekBarResetAnimator: Animator? = null + var animationEnabled: Boolean = true init { val seekBarProgressWavelength = @@ -104,7 +105,7 @@ open class SeekBarObserver(private val holder: MediaViewHolder) : holder.seekBar.thumb.alpha = if (data.seekAvailable) 255 else 0 holder.seekBar.isEnabled = data.seekAvailable - progressDrawable?.animate = data.playing && !data.scrubbing + progressDrawable?.animate = data.playing && !data.scrubbing && animationEnabled progressDrawable?.transitionEnabled = !data.seekAvailable if (holder.seekBar.maxHeight != seekBarEnabledMaxHeight) { diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java index 32a793556681..516fbf5ca12c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java @@ -34,6 +34,7 @@ import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; +import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.BlendMode; import android.graphics.Color; @@ -54,6 +55,7 @@ import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Process; import android.os.Trace; +import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -121,6 +123,7 @@ import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseContro import com.android.systemui.util.ColorUtilKt; import com.android.systemui.util.animation.TransitionLayout; import com.android.systemui.util.concurrency.DelayableExecutor; +import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.time.SystemClock; import dagger.Lazy; @@ -244,11 +247,19 @@ public class MediaControlPanel { private MultiRippleController mMultiRippleController; private TurbulenceNoiseController mTurbulenceNoiseController; private final FeatureFlags mFeatureFlags; + private final GlobalSettings mGlobalSettings; // 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 ContentObserver mAnimationScaleObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + updateAnimatorDurationScale(); + } + }; + /** * Initialize a new control panel * @@ -276,7 +287,8 @@ public class MediaControlPanel { ActivityIntentHelper activityIntentHelper, NotificationLockscreenUserManager lockscreenUserManager, BroadcastDialogController broadcastDialogController, - FeatureFlags featureFlags + FeatureFlags featureFlags, + GlobalSettings globalSettings ) { mContext = context; mBackgroundExecutor = backgroundExecutor; @@ -305,6 +317,13 @@ public class MediaControlPanel { }); mFeatureFlags = featureFlags; + + mGlobalSettings = globalSettings; + mGlobalSettings.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE), + mAnimationScaleObserver + ); + updateAnimatorDurationScale(); } /** @@ -387,6 +406,13 @@ public class MediaControlPanel { updateSeekBarVisibility(); } + private void updateAnimatorDurationScale() { + if (mSeekBarObserver != null) { + mSeekBarObserver.setAnimationEnabled( + mGlobalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) > 0f); + } + } + /** * Get the context * diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarObserverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarObserverTest.kt index 97b18e214550..d6ceea11b801 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarObserverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarObserverTest.kt @@ -234,4 +234,17 @@ class SeekBarObserverTest : SysuiTestCase() { assertThat(seekBarView.progress).isEqualTo(4000) verify(mockSeekbarAnimator).start() } + + @Test + fun seekbarActive_animationsDisabled() { + // WHEN playing, but animations have been disabled + observer.animationEnabled = false + val isPlaying = true + val isScrubbing = false + val data = SeekBarViewModel.Progress(true, true, isPlaying, isScrubbing, 3000, 120000) + observer.onChanged(data) + + // THEN progress drawable does not animate + verify(mockSquigglyProgress).animate = false + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt index f030a03be80f..7b673bc2b31e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt @@ -25,6 +25,7 @@ import android.content.Intent import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.content.res.Configuration +import android.database.ContentObserver import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color @@ -40,6 +41,7 @@ import android.media.MediaMetadata import android.media.session.MediaSession import android.media.session.PlaybackState import android.os.Bundle +import android.provider.Settings import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -73,6 +75,7 @@ import com.android.systemui.media.controls.models.player.MediaButton import com.android.systemui.media.controls.models.player.MediaData import com.android.systemui.media.controls.models.player.MediaDeviceData import com.android.systemui.media.controls.models.player.MediaViewHolder +import com.android.systemui.media.controls.models.player.SeekBarObserver import com.android.systemui.media.controls.models.player.SeekBarViewModel import com.android.systemui.media.controls.models.recommendation.KEY_SMARTSPACE_APP_NAME import com.android.systemui.media.controls.models.recommendation.RecommendationViewHolder @@ -97,6 +100,7 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.withArgCaptor +import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import dagger.Lazy @@ -109,6 +113,7 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyLong +import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.anyString import org.mockito.Mockito.mock @@ -233,6 +238,8 @@ public class MediaControlPanelTest : SysuiTestCase() { this.set(Flags.MEDIA_EXPLICIT_INDICATOR, true) this.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, false) } + @Mock private lateinit var globalSettings: GlobalSettings + @Captor private lateinit var settingsObserverCaptor: ArgumentCaptor<ContentObserver> @JvmField @Rule val mockito = MockitoJUnit.rule() @@ -273,7 +280,8 @@ public class MediaControlPanelTest : SysuiTestCase() { activityIntentHelper, lockscreenUserManager, broadcastDialogController, - fakeFeatureFlag + fakeFeatureFlag, + globalSettings, ) { override fun loadAnimator( animId: Int, @@ -284,6 +292,12 @@ public class MediaControlPanelTest : SysuiTestCase() { } } + verify(globalSettings) + .registerContentObserver( + eq(Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE)), + settingsObserverCaptor.capture() + ) + initGutsViewHolderMocks() initMediaViewHolderMocks() @@ -955,6 +969,30 @@ public class MediaControlPanelTest : SysuiTestCase() { } @Test + fun animationSettingChange_updateSeekbar() { + // When animations are enabled + globalSettings.putFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) + val progress = 0.5 + val state = mediaData.copy(resumption = true, resumeProgress = progress) + player.attachPlayer(viewHolder) + player.bindPlayer(state, PACKAGE) + + val captor = argumentCaptor<SeekBarObserver>() + verify(seekBarData).observeForever(captor.capture()) + val seekBarObserver = captor.value!! + + // Then the seekbar is set to animate + assertThat(seekBarObserver.animationEnabled).isTrue() + + // When the setting changes, + globalSettings.putFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 0f) + settingsObserverCaptor.value!!.onChange(false) + + // Then the seekbar is set to not animate + assertThat(seekBarObserver.animationEnabled).isFalse() + } + + @Test fun bindNotificationActions() { val icon = context.getDrawable(android.R.drawable.ic_media_play) val bg = context.getDrawable(R.drawable.qs_media_round_button_background) |