Merge "Make seekbar static when animations are disabled" into udc-dev

This commit is contained in:
Beth Thibodeau
2023-05-31 21:09:16 +00:00
committed by Android (Google) Code Review
4 changed files with 81 additions and 3 deletions

View File

@@ -56,6 +56,7 @@ open class SeekBarObserver(private val holder: MediaViewHolder) :
R.dimen.qs_media_session_disabled_seekbar_vertical_padding R.dimen.qs_media_session_disabled_seekbar_vertical_padding
) )
var seekBarResetAnimator: Animator? = null var seekBarResetAnimator: Animator? = null
var animationEnabled: Boolean = true
init { init {
val seekBarProgressWavelength = 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.thumb.alpha = if (data.seekAvailable) 255 else 0
holder.seekBar.isEnabled = data.seekAvailable holder.seekBar.isEnabled = data.seekAvailable
progressDrawable?.animate = data.playing && !data.scrubbing progressDrawable?.animate = data.playing && !data.scrubbing && animationEnabled
progressDrawable?.transitionEnabled = !data.seekAvailable progressDrawable?.transitionEnabled = !data.seekAvailable
if (holder.seekBar.maxHeight != seekBarEnabledMaxHeight) { if (holder.seekBar.maxHeight != seekBarEnabledMaxHeight) {

View File

@@ -34,6 +34,7 @@ import android.content.pm.PackageManager;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BlendMode; import android.graphics.BlendMode;
import android.graphics.Color; import android.graphics.Color;
@@ -54,6 +55,7 @@ import android.media.session.MediaSession;
import android.media.session.PlaybackState; import android.media.session.PlaybackState;
import android.os.Process; import android.os.Process;
import android.os.Trace; import android.os.Trace;
import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.Pair; 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.ColorUtilKt;
import com.android.systemui.util.animation.TransitionLayout; import com.android.systemui.util.animation.TransitionLayout;
import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.time.SystemClock; import com.android.systemui.util.time.SystemClock;
import dagger.Lazy; import dagger.Lazy;
@@ -244,11 +247,19 @@ public class MediaControlPanel {
private MultiRippleController mMultiRippleController; private MultiRippleController mMultiRippleController;
private TurbulenceNoiseController mTurbulenceNoiseController; private TurbulenceNoiseController mTurbulenceNoiseController;
private final FeatureFlags mFeatureFlags; private final FeatureFlags mFeatureFlags;
private final GlobalSettings mGlobalSettings;
// TODO(b/281032715): Consider making this as a final variable. For now having a null check // 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) // due to unit test failure. (Perhaps missing some setup)
private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig; private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig;
private ContentObserver mAnimationScaleObserver = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
updateAnimatorDurationScale();
}
};
/** /**
* Initialize a new control panel * Initialize a new control panel
* *
@@ -276,7 +287,8 @@ public class MediaControlPanel {
ActivityIntentHelper activityIntentHelper, ActivityIntentHelper activityIntentHelper,
NotificationLockscreenUserManager lockscreenUserManager, NotificationLockscreenUserManager lockscreenUserManager,
BroadcastDialogController broadcastDialogController, BroadcastDialogController broadcastDialogController,
FeatureFlags featureFlags FeatureFlags featureFlags,
GlobalSettings globalSettings
) { ) {
mContext = context; mContext = context;
mBackgroundExecutor = backgroundExecutor; mBackgroundExecutor = backgroundExecutor;
@@ -305,6 +317,13 @@ public class MediaControlPanel {
}); });
mFeatureFlags = featureFlags; mFeatureFlags = featureFlags;
mGlobalSettings = globalSettings;
mGlobalSettings.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
mAnimationScaleObserver
);
updateAnimatorDurationScale();
} }
/** /**
@@ -387,6 +406,13 @@ public class MediaControlPanel {
updateSeekBarVisibility(); updateSeekBarVisibility();
} }
private void updateAnimatorDurationScale() {
if (mSeekBarObserver != null) {
mSeekBarObserver.setAnimationEnabled(
mGlobalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) > 0f);
}
}
/** /**
* Get the context * Get the context
* *

View File

@@ -234,4 +234,17 @@ class SeekBarObserverTest : SysuiTestCase() {
assertThat(seekBarView.progress).isEqualTo(4000) assertThat(seekBarView.progress).isEqualTo(4000)
verify(mockSeekbarAnimator).start() 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
}
} }

View File

@@ -25,6 +25,7 @@ import android.content.Intent
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.database.ContentObserver
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
@@ -40,6 +41,7 @@ import android.media.MediaMetadata
import android.media.session.MediaSession import android.media.session.MediaSession
import android.media.session.PlaybackState import android.media.session.PlaybackState
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.testing.TestableLooper 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.MediaData
import com.android.systemui.media.controls.models.player.MediaDeviceData 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.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.player.SeekBarViewModel
import com.android.systemui.media.controls.models.recommendation.KEY_SMARTSPACE_APP_NAME import com.android.systemui.media.controls.models.recommendation.KEY_SMARTSPACE_APP_NAME
import com.android.systemui.media.controls.models.recommendation.RecommendationViewHolder 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.argumentCaptor
import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.withArgCaptor import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import dagger.Lazy import dagger.Lazy
@@ -109,6 +113,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyLong import org.mockito.ArgumentMatchers.anyLong
import org.mockito.Captor
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.anyString import org.mockito.Mockito.anyString
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
@@ -233,6 +238,8 @@ public class MediaControlPanelTest : SysuiTestCase() {
this.set(Flags.MEDIA_EXPLICIT_INDICATOR, true) this.set(Flags.MEDIA_EXPLICIT_INDICATOR, true)
this.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, false) 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() @JvmField @Rule val mockito = MockitoJUnit.rule()
@@ -273,7 +280,8 @@ public class MediaControlPanelTest : SysuiTestCase() {
activityIntentHelper, activityIntentHelper,
lockscreenUserManager, lockscreenUserManager,
broadcastDialogController, broadcastDialogController,
fakeFeatureFlag fakeFeatureFlag,
globalSettings,
) { ) {
override fun loadAnimator( override fun loadAnimator(
animId: Int, 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() initGutsViewHolderMocks()
initMediaViewHolderMocks() initMediaViewHolderMocks()
@@ -954,6 +968,30 @@ public class MediaControlPanelTest : SysuiTestCase() {
verify(seekBarViewModel).updateStaticProgress(progress) verify(seekBarViewModel).updateStaticProgress(progress)
} }
@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 @Test
fun bindNotificationActions() { fun bindNotificationActions() {
val icon = context.getDrawable(android.R.drawable.ic_media_play) val icon = context.getDrawable(android.R.drawable.ic_media_play)