From dc859eae82767598c43bbb182e81228be55f030b Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 9 Oct 2023 22:49:41 -0700 Subject: [PATCH] Fix the resumption of playback when suitable device is connected. With this change the playback will resume as soon as the suitable device is connected and suppression reason is cleared (within set time out). #minor-release PiperOrigin-RevId: 572140309 --- ...utPlaybackSuppressionResolverListener.java | 2 +- ...aybackSuppressionResolverListenerTest.java | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/libraries/ui/src/main/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListener.java b/libraries/ui/src/main/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListener.java index b96476da18..b06397eb36 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListener.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListener.java @@ -157,9 +157,9 @@ public final class WearUnsuitableOutputPlaybackSuppressionResolverListener && player.getPlaybackSuppressionReason() == Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_OUTPUT) { player.pause(); + unsuitableOutputPlaybackSuppressionStartRealtimeMs = clock.elapsedRealtime(); if (events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED)) { launchSystemMediaOutputSwitcherUi(applicationContext); - unsuitableOutputPlaybackSuppressionStartRealtimeMs = clock.elapsedRealtime(); } } else if (events.contains(Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED) && player.getPlaybackSuppressionReason() == Player.PLAYBACK_SUPPRESSION_REASON_NONE diff --git a/libraries/ui/src/test/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListenerTest.java b/libraries/ui/src/test/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListenerTest.java index d7e4f86de0..e8f10d5e4d 100644 --- a/libraries/ui/src/test/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListenerTest.java +++ b/libraries/ui/src/test/java/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListenerTest.java @@ -488,6 +488,75 @@ public class WearUnsuitableOutputPlaybackSuppressionResolverListenerTest { assertThat(isPlaybackPaused.get()).isTrue(); } + /** + * Test for automatic resumption of the ongoing playback when it is transferred from one suitable + * device to another within set time out. + */ + @Test + public void + transferOnGoingPlaybackFromOneSuitableDeviceToAnotherWithinSetTimeOut_shouldContinuePlayback() + throws TimeoutException { + shadowPackageManager.setSystemFeature(PackageManager.FEATURE_WATCH, /* supported= */ true); + setupConnectedAudioOutput( + AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, AudioDeviceInfo.TYPE_BLUETOOTH_A2DP); + testPlayer.addListener( + new WearUnsuitableOutputPlaybackSuppressionResolverListener( + ApplicationProvider.getApplicationContext())); + testPlayer.setMediaItem( + MediaItem.fromUri("asset:///media/mp4/sample_with_increasing_timestamps_360p.mp4")); + testPlayer.prepare(); + testPlayer.play(); + runUntilPlaybackState(testPlayer, Player.STATE_READY); + + removeConnectedAudioOutput(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP); + runUntilPlayWhenReady(testPlayer, /* expectedPlayWhenReady= */ false); + + addConnectedAudioOutput( + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, /* notifyAudioDeviceCallbacks= */ true); + runUntilPlayWhenReady(testPlayer, /* expectedPlayWhenReady= */ true); + + assertThat(testPlayer.isPlaying()).isTrue(); + } + + /** + * Test for automatic pause of the ongoing playback when it is transferred from one suitable + * device to another and the time difference between switching is more than default time out + */ + @Test + public void + transferOnGoingPlaybackFromOneSuitableDeviceToAnotherAfterTimeOut_shouldNotContinuePlayback() + throws TimeoutException { + shadowPackageManager.setSystemFeature(PackageManager.FEATURE_WATCH, /* supported= */ true); + setupConnectedAudioOutput( + AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, AudioDeviceInfo.TYPE_BLUETOOTH_A2DP); + FakeClock fakeClock = new FakeClock(/* isAutoAdvancing= */ true); + testPlayer.addListener( + new WearUnsuitableOutputPlaybackSuppressionResolverListener( + ApplicationProvider.getApplicationContext(), + WearUnsuitableOutputPlaybackSuppressionResolverListener + .DEFAULT_PLAYBACK_SUPPRESSION_AUTO_RESUME_TIMEOUT_MS, + fakeClock)); + testPlayer.setMediaItem( + MediaItem.fromUri("asset:///media/mp4/sample_with_increasing_timestamps_360p.mp4")); + testPlayer.prepare(); + testPlayer.play(); + runUntilPlaybackState(testPlayer, Player.STATE_READY); + + removeConnectedAudioOutput(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP); + runUntilPlayWhenReady(testPlayer, /* expectedPlayWhenReady= */ false); + + fakeClock.advanceTime( + WearUnsuitableOutputPlaybackSuppressionResolverListener + .DEFAULT_PLAYBACK_SUPPRESSION_AUTO_RESUME_TIMEOUT_MS + * 2); + + addConnectedAudioOutput( + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, /* notifyAudioDeviceCallbacks= */ true); + runUntilPlayWhenReady(testPlayer, /* expectedPlayWhenReady= */ false); + + assertThat(testPlayer.isPlaying()).isFalse(); + } + /** * Test for no pause on the Player when the playback is not suppressed due to unsuitable output. */