Merge "SessionPlaylistAgent: Handle setDataSource" into pi-dev
diff --git a/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java b/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
index 693e137..dfbe56a 100644
--- a/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
+++ b/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
@@ -23,6 +23,7 @@
import android.media.MediaItem2;
import android.media.MediaMetadata2;
import android.media.MediaPlayerBase;
+import android.media.MediaPlayerBase.PlayerEventCallback;
import android.media.MediaPlaylistAgent;
import android.media.MediaSession2.OnDataSourceMissingHelper;
import android.util.ArrayMap;
@@ -47,8 +48,8 @@
private final Object mLock = new Object();
private final MediaSession2Impl mSessionImpl;
+ private final MyPlayerEventCallback mPlayerCallback;
- // TODO: Set data sources properly into mPlayer (b/74090741)
@GuardedBy("mLock")
private MediaPlayerBase mPlayer;
@GuardedBy("mLock")
@@ -69,6 +70,22 @@
@GuardedBy("mLock")
private PlayItem mCurrent;
+ // Called on session callback executor.
+ private class MyPlayerEventCallback extends PlayerEventCallback {
+ public void onCurrentDataSourceChanged(@NonNull MediaPlayerBase mpb,
+ @Nullable DataSourceDesc dsd) {
+ if (mPlayer != mpb) {
+ return;
+ }
+ synchronized (mLock) {
+ if (dsd == null && mCurrent != null) {
+ mCurrent = getNextValidPlayItemLocked(mCurrent.shuffledIdx, 1);
+ updateCurrentIfNeededLocked();
+ }
+ }
+ }
+ }
+
private class PlayItem {
int shuffledIdx;
DataSourceDesc dsd;
@@ -127,14 +144,23 @@
}
mSessionImpl = sessionImpl;
mPlayer = player;
+ mPlayerCallback = new MyPlayerEventCallback();
+ mPlayer.registerPlayerEventCallback(mSessionImpl.getCallbackExecutor(), mPlayerCallback);
}
- public void setPlayer(MediaPlayerBase player) {
+ public void setPlayer(@NonNull MediaPlayerBase player) {
if (player == null) {
throw new IllegalArgumentException("player shouldn't be null");
}
synchronized (mLock) {
+ if (player == mPlayer) {
+ return;
+ }
+ mPlayer.unregisterPlayerEventCallback(mPlayerCallback);
mPlayer = player;
+ mPlayer.registerPlayerEventCallback(
+ mSessionImpl.getCallbackExecutor(), mPlayerCallback);
+ updatePlayerDataSourceLocked();
}
}
@@ -172,6 +198,7 @@
mMetadata = metadata;
mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1);
+ updatePlayerDataSourceLocked();
}
notifyPlaylistChanged();
}
@@ -210,6 +237,7 @@
}
if (!hasValidItem()) {
mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1);
+ updatePlayerDataSourceLocked();
} else {
updateCurrentIfNeededLocked();
}
@@ -249,6 +277,7 @@
mPlaylist.set(index, item);
if (!hasValidItem()) {
mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1);
+ updatePlayerDataSourceLocked();
} else {
updateCurrentIfNeededLocked();
}
@@ -291,7 +320,7 @@
@Override
public void skipToNextItem() {
synchronized (mLock) {
- if (!hasValidItem()) {
+ if (!hasValidItem() || mCurrent == mEopPlayItem) {
return;
}
PlayItem next = getNextValidPlayItemLocked(mCurrent.shuffledIdx, 1);
@@ -318,6 +347,23 @@
return;
}
mRepeatMode = repeatMode;
+ switch (repeatMode) {
+ case MediaPlaylistAgent.REPEAT_MODE_ONE:
+ if (mCurrent != null && mCurrent != mEopPlayItem) {
+ mPlayer.loopCurrent(true);
+ }
+ break;
+ case MediaPlaylistAgent.REPEAT_MODE_ALL:
+ case MediaPlaylistAgent.REPEAT_MODE_GROUP:
+ if (mCurrent == mEopPlayItem) {
+ mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1);
+ updatePlayerDataSourceLocked();
+ }
+ // pass through
+ case MediaPlaylistAgent.REPEAT_MODE_NONE:
+ mPlayer.loopCurrent(false);
+ break;
+ }
}
notifyRepeatModeChanged();
}
@@ -339,6 +385,7 @@
}
mShuffleMode = shuffleMode;
applyShuffleModeLocked();
+ updateCurrentIfNeededLocked();
}
notifyShuffleModeChanged();
}
@@ -373,6 +420,7 @@
return dsd;
}
+ // TODO: consider to call updateCurrentIfNeededLocked inside (b/74090741)
private PlayItem getNextValidPlayItemLocked(int curShuffledIdx, int direction) {
int size = mPlaylist.size();
if (curShuffledIdx == END_OF_PLAYLIST) {
@@ -414,9 +462,21 @@
mCurrent = getNextValidPlayItemLocked(mCurrent.shuffledIdx, 1);
}
}
+ updatePlayerDataSourceLocked();
return;
}
+ private void updatePlayerDataSourceLocked() {
+ if (mCurrent == null || mCurrent == mEopPlayItem) {
+ return;
+ }
+ if (mPlayer.getCurrentDataSource() != mCurrent.dsd) {
+ mPlayer.setDataSource(mCurrent.dsd);
+ mPlayer.loopCurrent(mRepeatMode == MediaPlaylistAgent.REPEAT_MODE_ONE);
+ }
+ // TODO: Call setNextDataSource (b/74090741)
+ }
+
private void applyShuffleModeLocked() {
mShuffledList.clear();
mShuffledList.addAll(mPlaylist);
diff --git a/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java b/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
index ca941ab..55a34fd 100644
--- a/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
+++ b/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
@@ -24,6 +24,7 @@
import android.media.MediaItem2;
import android.media.MediaMetadata2;
import android.media.MediaPlayerBase;
+import android.media.MediaPlayerBase.PlayerEventCallback;
import android.media.MediaPlaylistAgent;
import android.media.MediaSession2;
import android.media.MediaSession2.OnDataSourceMissingHelper;
@@ -35,6 +36,7 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Matchers;
import java.util.ArrayList;
import java.util.List;
@@ -56,6 +58,7 @@
private Context mContext;
private MediaSession2Impl mSessionImpl;
private MediaPlayerBase mPlayer;
+ private PlayerEventCallback mPlayerEventCallback;
private SessionPlaylistAgent mAgent;
private OnDataSourceMissingHelper mDataSourceHelper;
private MyPlaylistEventCallback mEventCallback;
@@ -229,6 +232,12 @@
};
mPlayer = mock(MockPlayer.class);
+ doAnswer(invocation -> {
+ Object[] args = invocation.getArguments();
+ mPlayerEventCallback = (PlayerEventCallback) args[1];
+ return null;
+ }).when(mPlayer).registerPlayerEventCallback(Matchers.any(), Matchers.any());
+
mSessionImpl = mock(MediaSession2Impl.class);
mDataSourceHelper = new MyDataSourceHelper();
mAgent = new SessionPlaylistAgent(mContext, mSessionImpl, mPlayer);
@@ -567,6 +576,33 @@
assertEquals(SessionPlaylistAgent.END_OF_PLAYLIST, mAgent.getCurShuffledIndex());
}
+ @Test
+ public void testPlaylistAfterOnCurrentDataSourceChanged() throws Exception {
+ int listSize = 2;
+ verify(mPlayer).registerPlayerEventCallback(Matchers.any(), Matchers.any());
+
+ createAndSetPlaylist(listSize);
+ assertEquals(0, mAgent.getCurShuffledIndex());
+
+ mPlayerEventCallback.onCurrentDataSourceChanged(mPlayer, null);
+ assertEquals(1, mAgent.getCurShuffledIndex());
+ mPlayerEventCallback.onCurrentDataSourceChanged(mPlayer, null);
+ assertEquals(SessionPlaylistAgent.END_OF_PLAYLIST, mAgent.getCurShuffledIndex());
+
+ mAgent.skipToNextItem();
+ assertEquals(SessionPlaylistAgent.END_OF_PLAYLIST, mAgent.getCurShuffledIndex());
+
+ mAgent.setRepeatMode(MediaPlaylistAgent.REPEAT_MODE_ONE);
+ assertEquals(SessionPlaylistAgent.END_OF_PLAYLIST, mAgent.getCurShuffledIndex());
+
+ mAgent.setRepeatMode(MediaPlaylistAgent.REPEAT_MODE_ALL);
+ assertEquals(0, mAgent.getCurShuffledIndex());
+ mPlayerEventCallback.onCurrentDataSourceChanged(mPlayer, null);
+ assertEquals(1, mAgent.getCurShuffledIndex());
+ mPlayerEventCallback.onCurrentDataSourceChanged(mPlayer, null);
+ assertEquals(0, mAgent.getCurShuffledIndex());
+ }
+
private List<MediaItem2> createAndSetPlaylist(int listSize) throws Exception {
List<MediaItem2> items = new ArrayList<>();
for (int i = 0; i < listSize; ++i) {