Loading packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java +63 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.media.DataSourceDesc; 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; Loading @@ -47,8 +48,8 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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") Loading @@ -69,6 +70,22 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { @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; Loading Loading @@ -127,14 +144,23 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { } 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(); } } Loading Loading @@ -172,6 +198,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { mMetadata = metadata; mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1); updatePlayerDataSourceLocked(); } notifyPlaylistChanged(); } Loading Loading @@ -210,6 +237,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { } if (!hasValidItem()) { mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1); updatePlayerDataSourceLocked(); } else { updateCurrentIfNeededLocked(); } Loading Loading @@ -249,6 +277,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { mPlaylist.set(index, item); if (!hasValidItem()) { mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1); updatePlayerDataSourceLocked(); } else { updateCurrentIfNeededLocked(); } Loading Loading @@ -291,7 +320,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { @Override public void skipToNextItem() { synchronized (mLock) { if (!hasValidItem()) { if (!hasValidItem() || mCurrent == mEopPlayItem) { return; } PlayItem next = getNextValidPlayItemLocked(mCurrent.shuffledIdx, 1); Loading @@ -318,6 +347,23 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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(); } Loading @@ -339,6 +385,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { } mShuffleMode = shuffleMode; applyShuffleModeLocked(); updateCurrentIfNeededLocked(); } notifyShuffleModeChanged(); } Loading Loading @@ -373,6 +420,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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) { Loading Loading @@ -414,9 +462,21 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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); Loading packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.media.DataSourceDesc; 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; Loading @@ -35,6 +36,7 @@ import android.test.AndroidTestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Matchers; import java.util.ArrayList; import java.util.List; Loading @@ -56,6 +58,7 @@ public class SessionPlaylistAgentTest extends AndroidTestCase { private Context mContext; private MediaSession2Impl mSessionImpl; private MediaPlayerBase mPlayer; private PlayerEventCallback mPlayerEventCallback; private SessionPlaylistAgent mAgent; private OnDataSourceMissingHelper mDataSourceHelper; private MyPlaylistEventCallback mEventCallback; Loading Loading @@ -229,6 +232,12 @@ public class SessionPlaylistAgentTest extends AndroidTestCase { }; 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); Loading Loading @@ -567,6 +576,33 @@ public class SessionPlaylistAgentTest extends AndroidTestCase { 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) { Loading Loading
packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java +63 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.media.DataSourceDesc; 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; Loading @@ -47,8 +48,8 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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") Loading @@ -69,6 +70,22 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { @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; Loading Loading @@ -127,14 +144,23 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { } 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(); } } Loading Loading @@ -172,6 +198,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { mMetadata = metadata; mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1); updatePlayerDataSourceLocked(); } notifyPlaylistChanged(); } Loading Loading @@ -210,6 +237,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { } if (!hasValidItem()) { mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1); updatePlayerDataSourceLocked(); } else { updateCurrentIfNeededLocked(); } Loading Loading @@ -249,6 +277,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { mPlaylist.set(index, item); if (!hasValidItem()) { mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1); updatePlayerDataSourceLocked(); } else { updateCurrentIfNeededLocked(); } Loading Loading @@ -291,7 +320,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { @Override public void skipToNextItem() { synchronized (mLock) { if (!hasValidItem()) { if (!hasValidItem() || mCurrent == mEopPlayItem) { return; } PlayItem next = getNextValidPlayItemLocked(mCurrent.shuffledIdx, 1); Loading @@ -318,6 +347,23 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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(); } Loading @@ -339,6 +385,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { } mShuffleMode = shuffleMode; applyShuffleModeLocked(); updateCurrentIfNeededLocked(); } notifyShuffleModeChanged(); } Loading Loading @@ -373,6 +420,7 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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) { Loading Loading @@ -414,9 +462,21 @@ public class SessionPlaylistAgent extends MediaPlaylistAgent { 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); Loading
packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.media.DataSourceDesc; 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; Loading @@ -35,6 +36,7 @@ import android.test.AndroidTestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Matchers; import java.util.ArrayList; import java.util.List; Loading @@ -56,6 +58,7 @@ public class SessionPlaylistAgentTest extends AndroidTestCase { private Context mContext; private MediaSession2Impl mSessionImpl; private MediaPlayerBase mPlayer; private PlayerEventCallback mPlayerEventCallback; private SessionPlaylistAgent mAgent; private OnDataSourceMissingHelper mDataSourceHelper; private MyPlaylistEventCallback mEventCallback; Loading Loading @@ -229,6 +232,12 @@ public class SessionPlaylistAgentTest extends AndroidTestCase { }; 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); Loading Loading @@ -567,6 +576,33 @@ public class SessionPlaylistAgentTest extends AndroidTestCase { 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) { Loading