summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java86
-rw-r--r--src/instrumentationTest/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java1170
2 files changed, 1219 insertions, 37 deletions
diff --git a/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java b/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java
index 7333a4919..b5c78b77b 100644
--- a/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java
+++ b/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java
@@ -129,7 +129,7 @@ public class PlaybackServiceMediaPlayer {
*
* @see #playMediaObject(de.danoeh.antennapod.util.playback.Playable, boolean, boolean, boolean)
*/
- public void playMediaObject(final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
+ private void playMediaObject(final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
if (playable == null)
throw new IllegalArgumentException("playable = null");
if (!playerLock.isHeldByCurrentThread())
@@ -149,22 +149,22 @@ public class PlaybackServiceMediaPlayer {
}
}
createMediaPlayer();
- media = playable;
+ this.media = playable;
+ this.stream = stream;
PlaybackServiceMediaPlayer.this.startWhenPrepared.set(startWhenPrepared);
setPlayerStatus(PlayerStatus.INITIALIZING, media);
try {
media.loadMetadata();
if (stream) {
- mediaPlayer.setDataSource(playable.getStreamUrl());
+ mediaPlayer.setDataSource(media.getStreamUrl());
} else {
- mediaPlayer.setDataSource(playable.getLocalMediaUrl());
+ mediaPlayer.setDataSource(media.getLocalMediaUrl());
}
setPlayerStatus(PlayerStatus.INITIALIZED, media);
if (prepareImmediately) {
setPlayerStatus(PlayerStatus.PREPARING, media);
mediaPlayer.prepare();
- setPlayerStatus(PlayerStatus.PREPARED, media);
onPrepared(startWhenPrepared);
}
@@ -192,42 +192,45 @@ public class PlaybackServiceMediaPlayer {
@Override
public void run() {
playerLock.lock();
- if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) {
- int focusGained = audioManager.requestAudioFocus(
- audioFocusChangeListener, AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
-
- setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed()));
- mediaPlayer.start();
- if (playerStatus == PlayerStatus.PREPARED) {
- mediaPlayer.seekTo(media.getPosition());
- }
- setPlayerStatus(PlayerStatus.PLAYING, media);
- pausedBecauseOfTransientAudiofocusLoss = false;
- if (android.os.Build.VERSION.SDK_INT >= 14) {
- RemoteControlClient remoteControlClient = callback.getRemoteControlClient();
- if (remoteControlClient != null) {
- audioManager
- .registerRemoteControlClient(remoteControlClient);
- }
- }
- audioManager
- .registerMediaButtonEventReceiver(new ComponentName(context.getPackageName(),
- MediaButtonReceiver.class.getName()));
- media.onPlaybackStart();
+ resumeSync();
+ playerLock.unlock();
+ }
+ });
+ }
- } else {
- if (AppConfig.DEBUG) Log.e(TAG, "Failed to request audio focus");
+ private void resumeSync() {
+ if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) {
+ int focusGained = audioManager.requestAudioFocus(
+ audioFocusChangeListener, AudioManager.STREAM_MUSIC,
+ AudioManager.AUDIOFOCUS_GAIN);
+ if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+
+ setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed()));
+ mediaPlayer.start();
+ if (playerStatus == PlayerStatus.PREPARED) {
+ mediaPlayer.seekTo(media.getPosition());
+ }
+ setPlayerStatus(PlayerStatus.PLAYING, media);
+ pausedBecauseOfTransientAudiofocusLoss = false;
+ if (android.os.Build.VERSION.SDK_INT >= 14) {
+ RemoteControlClient remoteControlClient = callback.getRemoteControlClient();
+ if (remoteControlClient != null) {
+ audioManager
+ .registerRemoteControlClient(remoteControlClient);
}
- } else {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Call to resume() was ignored because current state of PSMP object is " + playerStatus);
}
+ audioManager
+ .registerMediaButtonEventReceiver(new ComponentName(context.getPackageName(),
+ MediaButtonReceiver.class.getName()));
+ media.onPlaybackStart();
- playerLock.unlock();
+ } else {
+ if (AppConfig.DEBUG) Log.e(TAG, "Failed to request audio focus");
}
- });
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Call to resume() was ignored because current state of PSMP object is " + playerStatus);
+ }
}
@@ -260,6 +263,8 @@ public class PlaybackServiceMediaPlayer {
if (stream && reinit) {
reinit();
}
+ } else {
+ if (AppConfig.DEBUG) Log.d(TAG, "Ignoring call to pause: Player is in " + playerStatus + " state");
}
playerLock.unlock();
@@ -318,7 +323,7 @@ public class PlaybackServiceMediaPlayer {
setPlayerStatus(PlayerStatus.PREPARED, media);
if (startWhenPrepared) {
- resume();
+ resumeSync();
}
playerLock.unlock();
@@ -466,6 +471,10 @@ public class PlaybackServiceMediaPlayer {
return retVal;
}
+ public boolean isStartWhenPrepared() {
+ return startWhenPrepared.get();
+ }
+
/**
* Returns true if the playback speed can be adjusted. This method can also return false if the PSMP object's
* internal MediaPlayer cannot be accessed at the moment.
@@ -550,6 +559,8 @@ public class PlaybackServiceMediaPlayer {
private synchronized void setPlayerStatus(PlayerStatus newStatus, Playable newMedia) {
if (newStatus == null)
throw new IllegalArgumentException("newStatus = null");
+ if (AppConfig.DEBUG) Log.d(TAG, "Setting player status to " + newStatus);
+
this.playerStatus = newStatus;
this.media = newMedia;
callback.statusChanged(new PSMPInfo(playerStatus, media));
@@ -564,6 +575,7 @@ public class PlaybackServiceMediaPlayer {
} else {
mediaPlayer = new AudioPlayer(context);
}
+ mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
return setMediaPlayerListeners(mediaPlayer);
}
diff --git a/src/instrumentationTest/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/src/instrumentationTest/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
new file mode 100644
index 000000000..9ba95568b
--- /dev/null
+++ b/src/instrumentationTest/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
@@ -0,0 +1,1170 @@
+package instrumentationTest.de.test.antennapod.service.playback;
+
+import android.content.Context;
+import android.media.RemoteControlClient;
+import android.test.InstrumentationTestCase;
+import de.danoeh.antennapod.feed.Feed;
+import de.danoeh.antennapod.feed.FeedItem;
+import de.danoeh.antennapod.feed.FeedMedia;
+import de.danoeh.antennapod.service.playback.PlaybackServiceMediaPlayer;
+import de.danoeh.antennapod.service.playback.PlayerStatus;
+import de.danoeh.antennapod.storage.PodDBAdapter;
+import de.danoeh.antennapod.util.playback.Playable;
+import junit.framework.AssertionFailedError;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test class for PlaybackServiceMediaPlayer
+ */
+public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
+ private static final String TAG = "PlaybackServiceMediaPlayerTest";
+
+ private static final String PLAYABLE_FILE_URL = "http://hpr.dogphilosophy.net/test/mp3.mp3";
+ private static final String PLAYABLE_DEST_URL = "psmptestfile.wav";
+ private String PLAYABLE_LOCAL_URL = null;
+ private static final int LATCH_TIMEOUT_SECONDS = 10;
+
+ private volatile AssertionFailedError assertionError;
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ PodDBAdapter.deleteDatabase(getInstrumentation().getTargetContext());
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ assertionError = null;
+
+ final Context context = getInstrumentation().getTargetContext();
+ context.deleteDatabase(PodDBAdapter.DATABASE_NAME);
+ // make sure database is created
+ PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ adapter.close();
+ File cacheDir = context.getExternalFilesDir("testFiles");
+ if (cacheDir == null)
+ cacheDir = context.getExternalFilesDir("testFiles");
+ File dest = new File(cacheDir, PLAYABLE_DEST_URL);
+
+ assertNotNull(cacheDir);
+ assertTrue(cacheDir.canWrite());
+ assertTrue(cacheDir.canRead());
+ if (!dest.exists()) {
+ InputStream i = new URL(PLAYABLE_FILE_URL).openStream();
+ OutputStream o = new FileOutputStream(new File(cacheDir, PLAYABLE_DEST_URL));
+ IOUtils.copy(i, o);
+ o.flush();
+ o.close();
+ i.close();
+ }
+ PLAYABLE_LOCAL_URL = "file://" + dest.getAbsolutePath();
+ }
+
+ private void checkPSMPInfo(PlaybackServiceMediaPlayer.PSMPInfo info) {
+ try {
+ switch (info.playerStatus) {
+ case PLAYING:
+ case PAUSED:
+ case PREPARED:
+ case PREPARING:
+ case INITIALIZED:
+ case INITIALIZING:
+ case SEEKING:
+ case AWAITING_VIDEO_SURFACE:
+ assertNotNull(info.playable);
+ break;
+ case STOPPED:
+ assertNull(info.playable);
+ break;
+ case ERROR:
+ assertNull(info.playable);
+ }
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ public void testInit() {
+ final Context c = getInstrumentation().getTargetContext();
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, defaultCallback);
+ psmp.shutdown();
+ }
+
+ private Playable writeTestPlayable(String downloadUrl, String fileUrl) {
+ final Context c = getInstrumentation().getTargetContext();
+ Feed f = new Feed(0, new Date(), "f", "l", "d", null, null, null, null, "i", null, null, "l", false);
+ f.setItems(new ArrayList<FeedItem>());
+ FeedItem i = new FeedItem(0, "t", "i", "l", new Date(), false, f);
+ f.getItems().add(i);
+ FeedMedia media = new FeedMedia(0, i, 0, 0, 0, "audio/wav", fileUrl, downloadUrl, fileUrl != null, null);
+ i.setMedia(media);
+ PodDBAdapter adapter = new PodDBAdapter(c);
+ adapter.open();
+ adapter.setCompleteFeed(f);
+ assertTrue(media.getId() != 0);
+ adapter.close();
+ return media;
+ }
+
+
+ public void testPlayMediaObjectStreamNoStartNoPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(2);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ countDownLatch.countDown();
+ } else {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ countDownLatch.countDown();
+ }
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
+ psmp.playMediaObject(p, true, false, false);
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertFalse(psmp.isStartWhenPrepared());
+ psmp.shutdown();
+ }
+
+ public void testPlayMediaObjectStreamStartNoPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(2);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ countDownLatch.countDown();
+ } else {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ countDownLatch.countDown();
+ }
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
+ psmp.playMediaObject(p, true, true, false);
+
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertTrue(psmp.isStartWhenPrepared());
+ psmp.shutdown();
+ }
+
+ public void testPlayMediaObjectStreamNoStartPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(4);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+ } else if (countDownLatch.getCount() == 4) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 3) {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 1) {
+ assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus);
+ }
+ countDownLatch.countDown();
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
+ psmp.playMediaObject(p, true, false, true);
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PREPARED);
+
+ psmp.shutdown();
+ }
+
+ public void testPlayMediaObjectStreamStartPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(5);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+
+ } else if (countDownLatch.getCount() == 5) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 4) {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 3) {
+ assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 1) {
+ assertEquals(PlayerStatus.PLAYING, newInfo.playerStatus);
+ }
+ countDownLatch.countDown();
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
+ psmp.playMediaObject(p, true, true, true);
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PLAYING);
+ psmp.shutdown();
+ }
+
+ public void testPlayMediaObjectLocalNoStartNoPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(2);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ countDownLatch.countDown();
+ } else {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ countDownLatch.countDown();
+ }
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
+ psmp.playMediaObject(p, false, false, false);
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertFalse(psmp.isStartWhenPrepared());
+ psmp.shutdown();
+ }
+
+ public void testPlayMediaObjectLocalStartNoPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(2);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ countDownLatch.countDown();
+ } else {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ countDownLatch.countDown();
+ }
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
+ psmp.playMediaObject(p, false, true, false);
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.INITIALIZED);
+ assertTrue(psmp.isStartWhenPrepared());
+ psmp.shutdown();
+ }
+
+ public void testPlayMediaObjectLocalNoStartPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(4);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+ } else if (countDownLatch.getCount() == 4) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 3) {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 1) {
+ assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus);
+ }
+ countDownLatch.countDown();
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
+ psmp.playMediaObject(p, false, false, true);
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PREPARED);
+ psmp.shutdown();
+ }
+
+ public void testPlayMediaObjectLocalStartPrepare() throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final CountDownLatch countDownLatch = new CountDownLatch(5);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ try {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR)
+ throw new IllegalStateException("MediaPlayer error");
+ if (countDownLatch.getCount() == 0) {
+ fail();
+ } else if (countDownLatch.getCount() == 5) {
+ assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 4) {
+ assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 3) {
+ assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 2) {
+ assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus);
+ } else if (countDownLatch.getCount() == 1) {
+ assertEquals(PlayerStatus.PLAYING, newInfo.playerStatus);
+ }
+
+ } catch (AssertionFailedError e) {
+ if (assertionError == null)
+ assertionError = e;
+ } finally {
+ countDownLatch.countDown();
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
+ psmp.playMediaObject(p, false, true, true);
+ boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ assertTrue(psmp.getPSMPInfo().playerStatus == PlayerStatus.PLAYING);
+ psmp.shutdown();
+ }
+
+
+ private final PlaybackServiceMediaPlayer.PSMPCallback defaultCallback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ checkPSMPInfo(newInfo);
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+
+ private void pauseTestSkeleton(final PlayerStatus initialState, final boolean stream, final boolean abandonAudioFocus, final boolean reinit, long timeoutSeconds) throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final int latchCount = (stream && reinit) ? 2 : 1;
+ final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
+
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR) {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ } else if (initialState != PlayerStatus.PLAYING) {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ } else {
+ switch (newInfo.playerStatus) {
+ case PAUSED:
+ if (latchCount == countDownLatch.getCount())
+ countDownLatch.countDown();
+ else {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ }
+ break;
+ case INITIALIZED:
+ if (stream && reinit && countDownLatch.getCount() < latchCount) {
+ countDownLatch.countDown();
+ } else if (countDownLatch.getCount() < latchCount) {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ }
+ break;
+ }
+ }
+
+ }
+
+ @Override
+ public void shouldStop() {
+ if (assertionError == null)
+ assertionError = new AssertionFailedError("Unexpected call to shouldStop");
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ if (assertionError == null)
+ assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError");
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
+ if (initialState == PlayerStatus.PLAYING) {
+ psmp.playMediaObject(p, stream, true, true);
+ }
+ psmp.pause(abandonAudioFocus, reinit);
+ boolean res = countDownLatch.await(timeoutSeconds, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res || initialState != PlayerStatus.PLAYING);
+ psmp.shutdown();
+ }
+
+ public void testPauseDefaultState() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.STOPPED, false, false, false, 1);
+ }
+
+ public void testPausePlayingStateNoAbandonNoReinitNoStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, false, false, false, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPausePlayingStateNoAbandonNoReinitStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, true, false, false, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPausePlayingStateAbandonNoReinitNoStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, false, true, false, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPausePlayingStateAbandonNoReinitStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, true, true, false, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPausePlayingStateNoAbandonReinitNoStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, false, false, true, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPausePlayingStateNoAbandonReinitStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, true, false, true, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPausePlayingStateAbandonReinitNoStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, false, true, true, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPausePlayingStateAbandonReinitStream() throws InterruptedException {
+ pauseTestSkeleton(PlayerStatus.PLAYING, true, true, true, LATCH_TIMEOUT_SECONDS);
+ }
+
+ private void resumeTestSkeleton(final PlayerStatus initialState, long timeoutSeconds) throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final int latchCount = (initialState == PlayerStatus.PAUSED || initialState == PlayerStatus.PLAYING) ? 2 :
+ (initialState == PlayerStatus.PREPARED) ? 1 : 0;
+ final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
+
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR) {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ } else if (newInfo.playerStatus == PlayerStatus.PLAYING) {
+ if (countDownLatch.getCount() == 0) {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ } else {
+ countDownLatch.countDown();
+ }
+ }
+
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ if (assertionError == null) {
+ assertionError = new AssertionFailedError("Unexpected call of onMediaPlayerError");
+ }
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ if (initialState == PlayerStatus.PREPARED || initialState == PlayerStatus.PLAYING || initialState == PlayerStatus.PAUSED) {
+ boolean startWhenPrepared = (initialState != PlayerStatus.PREPARED);
+ psmp.playMediaObject(writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL), false, startWhenPrepared, true);
+ }
+ if (initialState == PlayerStatus.PAUSED) {
+ psmp.pause(false, false);
+ }
+ psmp.resume();
+ boolean res = countDownLatch.await(timeoutSeconds, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res || (initialState != PlayerStatus.PAUSED && initialState != PlayerStatus.PREPARED));
+ psmp.shutdown();
+ }
+
+ public void testResumePausedState() throws InterruptedException {
+ resumeTestSkeleton(PlayerStatus.PAUSED, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testResumePreparedState() throws InterruptedException {
+ resumeTestSkeleton(PlayerStatus.PREPARED, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testResumePlayingState() throws InterruptedException {
+ resumeTestSkeleton(PlayerStatus.PLAYING, 1);
+ }
+
+ private void prepareTestSkeleton(final PlayerStatus initialState, long timeoutSeconds) throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final int latchCount = 1;
+ final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR) {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ } else {
+ if (initialState == PlayerStatus.INITIALIZED && newInfo.playerStatus == PlayerStatus.PREPARED) {
+ countDownLatch.countDown();
+ } else if (initialState != PlayerStatus.INITIALIZED && initialState == newInfo.playerStatus) {
+ countDownLatch.countDown();
+ }
+ }
+
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ if (assertionError == null)
+ assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError");
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
+ if (initialState == PlayerStatus.INITIALIZED
+ || initialState == PlayerStatus.PLAYING
+ || initialState == PlayerStatus.PREPARED
+ || initialState == PlayerStatus.PAUSED) {
+ boolean prepareImmediately = (initialState != PlayerStatus.INITIALIZED);
+ boolean startWhenPrepared = (initialState != PlayerStatus.PREPARED);
+ psmp.playMediaObject(p, false, startWhenPrepared, prepareImmediately);
+ if (initialState == PlayerStatus.PAUSED) {
+ psmp.pause(false, false);
+ }
+ psmp.prepare();
+ }
+
+ boolean res = countDownLatch.await(timeoutSeconds, TimeUnit.SECONDS);
+ if (initialState != PlayerStatus.INITIALIZED) {
+ assertEquals(initialState, psmp.getPSMPInfo().playerStatus);
+ }
+
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ psmp.shutdown();
+ }
+
+ public void testPrepareInitializedState() throws InterruptedException {
+ prepareTestSkeleton(PlayerStatus.INITIALIZED, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPreparePlayingState() throws InterruptedException {
+ prepareTestSkeleton(PlayerStatus.PLAYING, 1);
+ }
+
+ public void testPreparePausedState() throws InterruptedException {
+ prepareTestSkeleton(PlayerStatus.PAUSED, 1);
+ }
+
+ public void testPreparePreparedState() throws InterruptedException {
+ prepareTestSkeleton(PlayerStatus.PREPARED, 1);
+ }
+
+ private void reinitTestSkeleton(final PlayerStatus initialState, final long timeoutSeconds) throws InterruptedException {
+ final Context c = getInstrumentation().getTargetContext();
+ final int latchCount = 2;
+ final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
+ PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
+ @Override
+ public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ checkPSMPInfo(newInfo);
+ if (newInfo.playerStatus == PlayerStatus.ERROR) {
+ if (assertionError == null)
+ assertionError = new UnexpectedStateChange(newInfo.playerStatus);
+ } else {
+ if (newInfo.playerStatus == initialState) {
+ countDownLatch.countDown();
+ } else if (countDownLatch.getCount() < latchCount && newInfo.playerStatus == PlayerStatus.INITIALIZED) {
+ countDownLatch.countDown();
+ }
+ }
+ }
+
+ @Override
+ public void shouldStop() {
+
+ }
+
+ @Override
+ public void playbackSpeedChanged(float s) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public boolean onMediaPlayerInfo(int code) {
+ return false;
+ }
+
+ @Override
+ public boolean onMediaPlayerError(Object inObj, int what, int extra) {
+ if (assertionError == null)
+ assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError");
+ return false;
+ }
+
+ @Override
+ public boolean endPlayback(boolean playNextEpisode) {
+ return false;
+ }
+
+ @Override
+ public RemoteControlClient getRemoteControlClient() {
+ return null;
+ }
+ };
+ PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
+ boolean prepareImmediately = initialState != PlayerStatus.INITIALIZED;
+ boolean startImmediately = initialState != PlayerStatus.PREPARED;
+ psmp.playMediaObject(p, false, startImmediately, prepareImmediately);
+ if (initialState == PlayerStatus.PAUSED) {
+ psmp.pause(false, false);
+ }
+ psmp.reinit();
+ boolean res = countDownLatch.await(timeoutSeconds, TimeUnit.SECONDS);
+ if (assertionError != null)
+ throw assertionError;
+ assertTrue(res);
+ psmp.shutdown();
+ }
+
+ public void testReinitPlayingState() throws InterruptedException {
+ reinitTestSkeleton(PlayerStatus.PLAYING, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testReinitPausedState() throws InterruptedException {
+ reinitTestSkeleton(PlayerStatus.PAUSED, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testPreparedPlayingState() throws InterruptedException {
+ reinitTestSkeleton(PlayerStatus.PREPARED, LATCH_TIMEOUT_SECONDS);
+ }
+
+ public void testReinitInitializedState() throws InterruptedException {
+ reinitTestSkeleton(PlayerStatus.INITIALIZED, LATCH_TIMEOUT_SECONDS);
+ }
+
+ private static class UnexpectedStateChange extends AssertionFailedError {
+ public UnexpectedStateChange(PlayerStatus status) {
+ super("Unexpected state change: " + status);
+ }
+ }
+}