package de.test.antennapod.service.playback;
import android.content.Context;
import android.test.InstrumentationTestCase;
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.util.ArrayList;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.test.antennapod.util.service.download.HTTPBin;
/**
* Test class for LocalPSMP
*/
public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
private static final String TAG = "PlaybackServiceMediaPlayerTest";
private static final String PLAYABLE_FILE_URL = "http://127.0.0.1:" + HTTPBin.PORT + "/files/0";
private static final String PLAYABLE_DEST_URL = "psmptestfile.mp3";
private String PLAYABLE_LOCAL_URL = null;
private static final int LATCH_TIMEOUT_SECONDS = 10;
private HTTPBin httpServer;
private volatile AssertionFailedError assertionError;
@Override
protected void tearDown() throws Exception {
super.tearDown();
PodDBAdapter.deleteDatabase();
httpServer.stop();
}
@Override
protected void setUp() throws Exception {
super.setUp();
assertionError = null;
final Context context = getInstrumentation().getTargetContext();
// create new database
PodDBAdapter.init(context);
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.close();
httpServer = new HTTPBin();
httpServer.start();
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 = getInstrumentation().getContext().getAssets().open("testfile.mp3");
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();
assertEquals(0, httpServer.serveFile(dest));
}
private void checkPSMPInfo(LocalPSMP.PSMPInfo info) {
try {
switch (info.playerStatus) {
case PLAYING:
case PAUSED:
case PREPARED:
case PREPARING:
case INITIALIZED:
case INITIALIZING:
case SEEKING:
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 LocalPSMP(c, defaultCallback);
psmp.shutdown();
}
private Playable writeTestPlayable(String downloadUrl, String fileUrl) {
final Context c = getInstrumentation().getTargetContext();
Feed f = new Feed(0, null, "f", "l", "d", null, null, null, null, "i", null, null, "l", false);
FeedPreferences prefs = new FeedPreferences(f.getId(), false, FeedPreferences.AutoDeleteAction.NO, null, null);
f.setPreferences(prefs);
f.setItems(new ArrayList<>());
FeedItem i = new FeedItem(0, "t", "i", "l", new Date(), FeedItem.UNPLAYED, f);
f.getItems().add(i);
FeedMedia media = new FeedMedia(0, i, 0, 0, 0, "audio/wav", fileUrl, downloadUrl, fileUrl != null, null, 0, 0);
i.setMedia(media);
PodDBAdapter adapter = PodDBAdapter.getInstance();
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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
}
@Override
public void shouldStop() {
}
@Override
public void playbackSpeedChanged(float s) {
}
@Override
public void setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) { return false; }
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
return false;
}
@Override
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
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(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
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(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
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(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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(LocalPSMP.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 setSpeedAbilityChanged() {
}
@Override
public void onMediaChanged(boolean reloadUI) {
}
@Override
public void onBufferingUpdate(int percent) {
}
@Override
public boolean onMediaPlayerInfo(int code, int resourceId) {
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(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new LocalPSMP(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);
}
}
}