diff options
4 files changed, 77 insertions, 2 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt index b7658a9f178d..51c157a56560 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt @@ -61,6 +61,7 @@ class SeekBarObserver(view: View) : Observer<SeekBarViewModel.Progress> { if (!data.enabled) { seekBarView.setEnabled(false) seekBarView.getThumb().setAlpha(0) + seekBarView.setProgress(0) elapsedTimeView.setText("") totalTimeView.setText("") return diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt index dd83e42cde2d..142510030a5f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt @@ -77,13 +77,25 @@ class SeekBarViewModel(val bgExecutor: DelayableExecutor) { val seekAvailable = ((playbackState?.actions ?: 0L) and PlaybackState.ACTION_SEEK_TO) != 0L val position = playbackState?.position?.toInt() val duration = mediaMetadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.toInt() - val enabled = if (duration != null && duration <= 0) false else true + val enabled = if (playbackState == null || + playbackState?.getState() == PlaybackState.STATE_NONE || + (duration != null && duration <= 0)) false else true _data = Progress(enabled, seekAvailable, position, duration, color) if (shouldPollPlaybackPosition()) { checkPlaybackPosition() } } + /** + * Puts the seek bar into a resumption state. + * + * This should be called when the media session behind the controller has been destroyed. + */ + @AnyThread + fun clearController() = bgExecutor.execute { + _data = _data.copy(enabled = false) + } + @AnyThread private fun checkPlaybackPosition(): Runnable = bgExecutor.executeDelayed({ val currentPosition = controller?.playbackState?.position?.toInt() diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java index e636707a9722..dcb0f883b016 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java @@ -171,6 +171,8 @@ public class QSMediaPlayer extends MediaControlPanel { public void clearControls() { super.clearControls(); + mSeekBarViewModel.clearController(); + View guts = mMediaNotifView.findViewById(R.id.media_guts); View options = mMediaNotifView.findViewById(R.id.qs_media_controls_options); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt index f316d0480fac..28a3d6a32a61 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt @@ -86,7 +86,7 @@ public class SeekBarViewModelTest : SysuiTestCase() { } @Test - fun updateDuration() { + fun updateDurationWithPlayback() { // GIVEN that the duration is contained within the metadata val duration = 12000L val metadata = MediaMetadata.Builder().run { @@ -94,6 +94,12 @@ public class SeekBarViewModelTest : SysuiTestCase() { build() } whenever(mockController.getMetadata()).thenReturn(metadata) + // AND a valid playback state (ie. media session is not destroyed) + val state = PlaybackState.Builder().run { + setState(PlaybackState.STATE_PLAYING, 200L, 1f) + build() + } + whenever(mockController.getPlaybackState()).thenReturn(state) // WHEN the controller is updated viewModel.updateController(mockController, Color.RED) // THEN the duration is extracted @@ -102,6 +108,22 @@ public class SeekBarViewModelTest : SysuiTestCase() { } @Test + fun updateDurationWithoutPlayback() { + // GIVEN that the duration is contained within the metadata + val duration = 12000L + val metadata = MediaMetadata.Builder().run { + putLong(MediaMetadata.METADATA_KEY_DURATION, duration) + build() + } + whenever(mockController.getMetadata()).thenReturn(metadata) + // WHEN the controller is updated + viewModel.updateController(mockController, Color.RED) + // THEN the duration is extracted + assertThat(viewModel.progress.value!!.duration).isEqualTo(duration) + assertThat(viewModel.progress.value!!.enabled).isFalse() + } + + @Test fun updateDurationNegative() { // GIVEN that the duration is negative val duration = -1L @@ -110,6 +132,12 @@ public class SeekBarViewModelTest : SysuiTestCase() { build() } whenever(mockController.getMetadata()).thenReturn(metadata) + // AND a valid playback state (ie. media session is not destroyed) + val state = PlaybackState.Builder().run { + setState(PlaybackState.STATE_PLAYING, 200L, 1f) + build() + } + whenever(mockController.getPlaybackState()).thenReturn(state) // WHEN the controller is updated viewModel.updateController(mockController, Color.RED) // THEN the seek bar is disabled @@ -125,6 +153,12 @@ public class SeekBarViewModelTest : SysuiTestCase() { build() } whenever(mockController.getMetadata()).thenReturn(metadata) + // AND a valid playback state (ie. media session is not destroyed) + val state = PlaybackState.Builder().run { + setState(PlaybackState.STATE_PLAYING, 200L, 1f) + build() + } + whenever(mockController.getPlaybackState()).thenReturn(state) // WHEN the controller is updated viewModel.updateController(mockController, Color.RED) // THEN the seek bar is disabled @@ -372,4 +406,30 @@ public class SeekBarViewModelTest : SysuiTestCase() { // THEN an update task is queued assertThat(fakeExecutor.numPending()).isEqualTo(1) } + + @Test + fun clearSeekBar() { + // GIVEN that the duration is contained within the metadata + val metadata = MediaMetadata.Builder().run { + putLong(MediaMetadata.METADATA_KEY_DURATION, 12000L) + build() + } + whenever(mockController.getMetadata()).thenReturn(metadata) + // AND a valid playback state (ie. media session is not destroyed) + val state = PlaybackState.Builder().run { + setState(PlaybackState.STATE_PLAYING, 200L, 1f) + build() + } + whenever(mockController.getPlaybackState()).thenReturn(state) + // AND the controller has been updated + viewModel.updateController(mockController, Color.RED) + // WHEN the controller is cleared on the event when the session is destroyed + viewModel.clearController() + with(fakeExecutor) { + advanceClockToNext() + runAllReady() + } + // THEN the seek bar is disabled + assertThat(viewModel.progress.value!!.enabled).isFalse() + } } |