From cba65c8c61122c5f0a41bd95a767002e11a1bae4 Mon Sep 17 00:00:00 2001 From: ibaker Date: Thu, 17 Nov 2022 17:41:02 +0000 Subject: [PATCH] Throw exception if a released player is passed to TestPlayerRunHelper I considered moving this enforcement inside the ExoPlayerImpl implementation, but it might lead to app crashes in cases that apps (incorrectly) call a released player, but it wasn't actually causing a problem. PiperOrigin-RevId: 489233917 --- .../robolectric/TestPlayerRunHelper.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java index 658e9f56be..54d62208ef 100644 --- a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java +++ b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java @@ -17,6 +17,7 @@ package androidx.media3.test.utils.robolectric; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.test.utils.robolectric.RobolectricUtil.runMainLooperUntil; import android.os.Looper; @@ -55,6 +56,9 @@ public class TestPlayerRunHelper { public static void runUntilPlaybackState(Player player, @Player.State int expectedState) throws TimeoutException { verifyMainTestThread(player); + if (player instanceof ExoPlayer) { + verifyPlaybackThreadIsAlive((ExoPlayer) player); + } runMainLooperUntil( () -> player.getPlaybackState() == expectedState || player.getPlayerError() != null); if (player.getPlayerError() != null) { @@ -76,6 +80,9 @@ public class TestPlayerRunHelper { public static void runUntilPlayWhenReady(Player player, boolean expectedPlayWhenReady) throws TimeoutException { verifyMainTestThread(player); + if (player instanceof ExoPlayer) { + verifyPlaybackThreadIsAlive((ExoPlayer) player); + } runMainLooperUntil( () -> player.getPlayWhenReady() == expectedPlayWhenReady || player.getPlayerError() != null); @@ -98,6 +105,9 @@ public class TestPlayerRunHelper { public static void runUntilTimelineChanged(Player player, Timeline expectedTimeline) throws TimeoutException { verifyMainTestThread(player); + if (player instanceof ExoPlayer) { + verifyPlaybackThreadIsAlive((ExoPlayer) player); + } runMainLooperUntil( () -> expectedTimeline.equals(player.getCurrentTimeline()) @@ -151,6 +161,9 @@ public class TestPlayerRunHelper { public static void runUntilPositionDiscontinuity( Player player, @Player.DiscontinuityReason int expectedReason) throws TimeoutException { verifyMainTestThread(player); + if (player instanceof ExoPlayer) { + verifyPlaybackThreadIsAlive((ExoPlayer) player); + } AtomicBoolean receivedCallback = new AtomicBoolean(false); Player.Listener listener = new Player.Listener() { @@ -180,6 +193,8 @@ public class TestPlayerRunHelper { */ public static ExoPlaybackException runUntilError(ExoPlayer player) throws TimeoutException { verifyMainTestThread(player); + verifyPlaybackThreadIsAlive(player); + runMainLooperUntil(() -> player.getPlayerError() != null); return checkNotNull(player.getPlayerError()); } @@ -199,6 +214,8 @@ public class TestPlayerRunHelper { public static void runUntilSleepingForOffload(ExoPlayer player, boolean expectedSleepForOffload) throws TimeoutException { verifyMainTestThread(player); + verifyPlaybackThreadIsAlive(player); + AtomicBoolean receiverCallback = new AtomicBoolean(false); ExoPlayer.AudioOffloadListener listener = new ExoPlayer.AudioOffloadListener() { @@ -228,6 +245,8 @@ public class TestPlayerRunHelper { */ public static void runUntilRenderedFirstFrame(ExoPlayer player) throws TimeoutException { verifyMainTestThread(player); + verifyPlaybackThreadIsAlive(player); + AtomicBoolean receivedCallback = new AtomicBoolean(false); Player.Listener listener = new Player.Listener() { @@ -259,6 +278,7 @@ public class TestPlayerRunHelper { public static void playUntilPosition(ExoPlayer player, int mediaItemIndex, long positionMs) throws TimeoutException { verifyMainTestThread(player); + verifyPlaybackThreadIsAlive(player); Looper applicationLooper = Util.getCurrentOrMainLooper(); AtomicBoolean messageHandled = new AtomicBoolean(false); player @@ -319,6 +339,8 @@ public class TestPlayerRunHelper { public static void runUntilPendingCommandsAreFullyHandled(ExoPlayer player) throws TimeoutException { verifyMainTestThread(player); + verifyPlaybackThreadIsAlive(player); + // Send message to player that will arrive after all other pending commands. Thus, the message // execution on the app thread will also happen after all other pending command // acknowledgements have arrived back on the app thread. @@ -336,4 +358,10 @@ public class TestPlayerRunHelper { throw new IllegalStateException(); } } + + private static void verifyPlaybackThreadIsAlive(ExoPlayer player) { + checkState( + player.getPlaybackLooper().getThread().isAlive(), + "Playback thread is not alive, has the player been released?"); + } }