Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 414ef561 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Sungsoo Lim
Browse files

MediaSession impl update for MediaPlayerBase

Update the MediaSession implementation after MediaPlayerBase
  API update.

Bug: 64098437
Test: MediaSession CTS
Change-Id: I3d1e25ea3d00e77a90f0b9bcd14ac0a2c9e3ddd1
parent b97f6a97
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -492,6 +492,11 @@ public class MediaController2Impl implements MediaController2Provider {
        // TODO(jaewan): Implement
    }

    @Override
    public void replacePlaylistItem_impl(int index, MediaItem2 item) {
        // TODO: Implement this
    }

    @Override
    public PlaylistParams getPlaylistParams_impl() {
        synchronized (mLock) {
+84 −25
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ import android.media.MediaItem2;
import android.media.MediaLibraryService2;
import android.media.MediaMetadata2;
import android.media.MediaPlayerBase;
import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaPlayerBase.PlayerEventCallback;
import android.media.MediaSession2;
import android.media.MediaSession2.Builder;
import android.media.MediaSession2.Command;
@@ -85,7 +85,7 @@ public class MediaSession2Impl implements MediaSession2Provider {
    private final MediaSession2Stub mSessionStub;
    private final SessionToken2 mSessionToken;
    private final AudioManager mAudioManager;
    private final ArrayMap<EventCallback, Executor> mCallbacks = new ArrayMap<>();
    private final ArrayMap<PlayerEventCallback, Executor> mCallbacks = new ArrayMap<>();
    private final PendingIntent mSessionActivity;

    // mPlayer is set to null when the session is closed, and we shouldn't throw an exception
@@ -228,11 +228,11 @@ public class MediaSession2Impl implements MediaSession2Provider {
        synchronized (mLock) {
            if (mPlayer != null && mEventCallback != null) {
                // This might not work for a poorly implemented player.
                mPlayer.unregisterEventCallback(mEventCallback);
                mPlayer.unregisterPlayerEventCallback(mEventCallback);
            }
            mPlayer = player;
            mEventCallback = new MyEventCallback(this, player);
            player.registerEventCallback(mCallbackExecutor, mEventCallback);
            player.registerPlayerEventCallback(mCallbackExecutor, mEventCallback);
            mVolumeProvider = volumeProvider;
            mPlaybackInfo = info;
        }
@@ -293,7 +293,7 @@ public class MediaSession2Impl implements MediaSession2Provider {
        synchronized (mLock) {
            if (mPlayer != null) {
                // close can be called multiple times
                mPlayer.unregisterEventCallback(mEventCallback);
                mPlayer.unregisterPlayerEventCallback(mEventCallback);
                mPlayer = null;
            }
        }
@@ -347,7 +347,9 @@ public class MediaSession2Impl implements MediaSession2Provider {
        ensureCallingThread();
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            player.stop();
            // TODO: Uncomment or remove
            //player.stop();
            player.pause();
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
@@ -356,12 +358,16 @@ public class MediaSession2Impl implements MediaSession2Provider {
    @Override
    public void skipToPrevious_impl() {
        ensureCallingThread();
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            player.skipToPrevious();
            // TODO implement
            //player.skipToPrevious();
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
    }

    @Override
@@ -393,23 +399,32 @@ public class MediaSession2Impl implements MediaSession2Provider {
            throw new IllegalArgumentException("params shouldn't be null");
        }
        ensureCallingThread();
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            player.setPlaylistParams(params);
            // TODO implement
            //player.setPlaylistParams(params);
            mSessionStub.notifyPlaylistParamsChanged(params);
        }
        */
    }

    @Override
    public PlaylistParams getPlaylistParams_impl() {
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            // TODO(jaewan): Is it safe to be called on any thread?
            //               Otherwise MediaSession2 should cache parameter of setPlaylistParams.
            return player.getPlaylistParams();
            // TODO implement
            //return player.getPlaylistParams();
            return null;
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
        return null;
    }

@@ -439,13 +454,17 @@ public class MediaSession2Impl implements MediaSession2Provider {
            throw new IllegalArgumentException("playlist shouldn't be null");
        }
        ensureCallingThread();
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            player.setPlaylist(playlist);
            // TODO implement, use the SessionPlaylistController itf
            //player.setPlaylist(playlist);
            mSessionStub.notifyPlaylistChanged(playlist);
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
    }

    @Override
@@ -463,16 +482,26 @@ public class MediaSession2Impl implements MediaSession2Provider {
        // TODO(jaewan): Implement
    }

    @Override
    public void replacePlaylistItem_impl(int index, MediaItem2 item) {
        // TODO(jaewan): Implement
    }

    @Override
    public List<MediaItem2> getPlaylist_impl() {
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            // TODO(jaewan): Is it safe to be called on any thread?
            //               Otherwise MediaSession2 should cache parameter of setPlaylist.
            return player.getPlaylist();
            // TODO implement
            //return player.getPlaylist();
            return null;
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
        return null;
    }

@@ -496,23 +525,31 @@ public class MediaSession2Impl implements MediaSession2Provider {
    @Override
    public void fastForward_impl() {
        ensureCallingThread();
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            player.fastForward();
            // TODO implement
            //player.fastForward();
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
    }

    @Override
    public void rewind_impl() {
        ensureCallingThread();
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            player.rewind();
            // TODO implement
            //player.rewind();
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
    }

    @Override
@@ -529,16 +566,20 @@ public class MediaSession2Impl implements MediaSession2Provider {
    @Override
    public void skipToPlaylistItem_impl(MediaItem2 item) {
        ensureCallingThread();
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
            player.setCurrentPlaylistItem(item);
            // TODO implement
            //player.setCurrentPlaylistItem(item);
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
    }

    @Override
    public void registerPlayerEventCallback_impl(Executor executor, EventCallback callback) {
    public void registerPlayerEventCallback_impl(Executor executor, PlayerEventCallback callback) {
        if (executor == null) {
            throw new IllegalArgumentException("executor shouldn't be null");
        }
@@ -551,13 +592,16 @@ public class MediaSession2Impl implements MediaSession2Provider {
            return;
        }
        mCallbacks.put(callback, executor);
        // TODO: Uncomment or remove
        /*
        // TODO(jaewan): Double check if we need this.
        final PlaybackState2 state = getInstance().getPlaybackState();
        executor.execute(() -> callback.onPlaybackStateChanged(state));
        */
    }

    @Override
    public void unregisterPlayerEventCallback_impl(EventCallback callback) {
    public void unregisterPlayerEventCallback_impl(PlayerEventCallback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("callback shouldn't be null");
        }
@@ -568,14 +612,19 @@ public class MediaSession2Impl implements MediaSession2Provider {
    @Override
    public PlaybackState2 getPlaybackState_impl() {
        ensureCallingThread();
        // TODO: Uncomment or remove
        /*
        final MediaPlayerBase player = mPlayer;
        if (player != null) {
           // TODO(jaewan): Is it safe to be called on any thread?
            //               Otherwise MediaSession2 should cache the result from listener.
            return player.getPlaybackState();
            // TODO implement
            //return player.getPlaybackState();
            return null;
        } else if (DEBUG) {
            Log.d(TAG, "API calls after the close()", new IllegalStateException());
        }
        */
        return null;
    }

@@ -609,30 +658,32 @@ public class MediaSession2Impl implements MediaSession2Provider {
    }

    private void notifyPlaybackStateChangedNotLocked(final PlaybackState2 state) {
        ArrayMap<EventCallback, Executor> callbacks = new ArrayMap<>();
        ArrayMap<PlayerEventCallback, Executor> callbacks = new ArrayMap<>();
        synchronized (mLock) {
            callbacks.putAll(mCallbacks);
        }
        // Notify to callbacks added directly to this session
        for (int i = 0; i < callbacks.size(); i++) {
            final EventCallback callback = callbacks.keyAt(i);
            final PlayerEventCallback callback = callbacks.keyAt(i);
            final Executor executor = callbacks.valueAt(i);
            executor.execute(() -> callback.onPlaybackStateChanged(state));
            // TODO: Uncomment or remove
            //executor.execute(() -> callback.onPlaybackStateChanged(state));
        }
        // Notify to controllers as well.
        mSessionStub.notifyPlaybackStateChangedNotLocked(state);
    }

    private void notifyErrorNotLocked(String mediaId, int what, int extra) {
        ArrayMap<EventCallback, Executor> callbacks = new ArrayMap<>();
        ArrayMap<PlayerEventCallback, Executor> callbacks = new ArrayMap<>();
        synchronized (mLock) {
            callbacks.putAll(mCallbacks);
        }
        // Notify to callbacks added directly to this session
        for (int i = 0; i < callbacks.size(); i++) {
            final EventCallback callback = callbacks.keyAt(i);
            final PlayerEventCallback callback = callbacks.keyAt(i);
            final Executor executor = callbacks.valueAt(i);
            executor.execute(() -> callback.onError(mediaId, what, extra));
            // TODO: Uncomment or remove
            //executor.execute(() -> callback.onError(mediaId, what, extra));
        }
        // TODO(jaewan): Notify to controllers as well.
    }
@@ -675,7 +726,7 @@ public class MediaSession2Impl implements MediaSession2Provider {
        return mSessionActivity;
    }

    private static class MyEventCallback extends EventCallback {
    private static class MyEventCallback extends PlayerEventCallback {
        private final WeakReference<MediaSession2Impl> mSession;
        private final MediaPlayerBase mPlayer;

@@ -684,6 +735,8 @@ public class MediaSession2Impl implements MediaSession2Provider {
            mPlayer = player;
        }

        // TODO: Uncomment or remove
        /*
        @Override
        public void onPlaybackStateChanged(PlaybackState2 state) {
            MediaSession2Impl session = mSession.get();
@@ -697,7 +750,10 @@ public class MediaSession2Impl implements MediaSession2Provider {
            }
            session.notifyPlaybackStateChangedNotLocked(state);
        }
        */

        // TODO: Uncomment or remove
        /*
        @Override
        public void onError(String mediaId, int what, int extra) {
            MediaSession2Impl session = mSession.get();
@@ -712,6 +768,9 @@ public class MediaSession2Impl implements MediaSession2Provider {
            }
            session.notifyErrorNotLocked(mediaId, what, extra);
        }
        */

        //TODO implement the real PlayerEventCallback methods
    }

    public static final class CommandImpl implements CommandProvider {
+16 −10
Original line number Diff line number Diff line
@@ -22,7 +22,8 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaPlayerBase;
import android.media.MediaPlayerBase.PlayerEventCallback;
import android.media.MediaSession2;
import android.media.MediaSessionService2;
import android.media.MediaSessionService2.MediaNotification;
@@ -42,7 +43,7 @@ public class MediaSessionService2Impl implements MediaSessionService2Provider {
    private static final boolean DEBUG = true; // TODO(jaewan): Change this.

    private final MediaSessionService2 mInstance;
    private final EventCallback mCallback = new SessionServiceEventCallback();
    private final PlayerEventCallback mCallback = new SessionServiceEventCallback();

    private final Object mLock = new Object();
    @GuardedBy("mLock")
@@ -135,16 +136,21 @@ public class MediaSessionService2Impl implements MediaSessionService2Provider {
                mediaNotification.getNotification());
    }

    private class SessionServiceEventCallback extends EventCallback {
    private class SessionServiceEventCallback extends PlayerEventCallback {
        @Override
        public void onPlaybackStateChanged(PlaybackState2 state) {
            if (state == null) {
                Log.w(TAG, "Ignoring null playback state");
        public void onPlayerStateChanged(MediaPlayerBase mpb, int state) {
            // TODO: Implement this
            return;
        }
            MediaSession2Impl impl = (MediaSession2Impl) mSession.getProvider();
            updateNotification(impl.getInstance().getPlaybackState());
        }
        // TODO: Uncomment or remove
        //public void onPlaybackStateChanged(PlaybackState2 state) {
        //    if (state == null) {
        //        Log.w(TAG, "Ignoring null playback state");
        //        return;
        //    }
        //    MediaSession2Impl impl = (MediaSession2Impl) mSession.getProvider();
        //    updateNotification(impl.getInstance().getPlaybackState());
        //}
    }

    public static class MediaNotificationImpl implements MediaNotificationProvider {
+3 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.support.annotation.NonNull;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

@@ -227,6 +228,7 @@ public class MediaBrowser2Test extends MediaController2Test {
        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
    }

    @Ignore
    @Test
    public void testSearch() throws InterruptedException {
        final String query = MockMediaLibraryService2.SEARCH_QUERY;
@@ -352,6 +354,7 @@ public class MediaBrowser2Test extends MediaController2Test {
        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
    }

    @Ignore
    @Test
    public void testUnsubscribe() throws InterruptedException {
        final String testParentId = "testUnsubscribeId";
+14 −2
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package android.media;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaPlayerBase.PlayerEventCallback;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
@@ -116,6 +116,7 @@ public class MediaController2Test extends MediaSession2TestBase {
        assertTrue(mPlayer.mPauseCalled);
    }

    @Ignore
    @Test
    public void testSkipToPrevious() throws InterruptedException {
        mController.skipToPrevious();
@@ -138,6 +139,7 @@ public class MediaController2Test extends MediaSession2TestBase {
        assertTrue(mPlayer.mSkipToNextCalled);
    }

    @Ignore
    @Test
    public void testStop() throws InterruptedException {
        mController.stop();
@@ -160,6 +162,7 @@ public class MediaController2Test extends MediaSession2TestBase {
        assertTrue(mPlayer.mPrepareCalled);
    }

    @Ignore
    @Test
    public void testFastForward() throws InterruptedException {
        mController.fastForward();
@@ -171,6 +174,7 @@ public class MediaController2Test extends MediaSession2TestBase {
        assertTrue(mPlayer.mFastForwardCalled);
    }

    @Ignore
    @Test
    public void testRewind() throws InterruptedException {
        mController.rewind();
@@ -219,6 +223,7 @@ public class MediaController2Test extends MediaSession2TestBase {
        assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
    }

    @Ignore
    @Test
    public void testGetSetPlaylistParams() throws Exception {
        final PlaylistParams params = new PlaylistParams(mContext,
@@ -285,6 +290,7 @@ public class MediaController2Test extends MediaSession2TestBase {
    }

    // This also tests getPlaybackState().
    @Ignore
    @Test
    public void testControllerCallback_onPlaybackStateChanged() throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(1);
@@ -649,6 +655,7 @@ public class MediaController2Test extends MediaSession2TestBase {
        testConnectToService(MockMediaSessionService2.ID);
    }

    @Ignore
    @Test
    public void testConnectToService_libraryService() throws InterruptedException {
        testConnectToService(MockMediaLibraryService2.ID);
@@ -696,6 +703,7 @@ public class MediaController2Test extends MediaSession2TestBase {
        testControllerAfterSessionIsGone(mSession.getToken().getId());
    }

    @Ignore
    @Test
    public void testControllerAfterSessionIsGone_sessionService() throws InterruptedException {
        connectToService(TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID));
@@ -780,14 +788,18 @@ public class MediaController2Test extends MediaSession2TestBase {
    }

    private void testNoInteraction() throws InterruptedException {
        // TODO: Uncomment
        /*
        final CountDownLatch latch = new CountDownLatch(1);
        final EventCallback callback = new EventCallback() {
        final PlayerEventCallback callback = new PlayerEventCallback() {
            @Override
            public void onPlaybackStateChanged(PlaybackState2 state) {
                fail("Controller shouldn't be notified about change in session after the close.");
                latch.countDown();
            }
        };
        */

        // TODO(jaewan): Add equivalent tests again
        /*
        mController.registerPlayerEventCallback(playbackListener, sHandler);
Loading