1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.support.v4.media.session;
17
18import static android.support.test.InstrumentationRegistry.getContext;
19import static android.support.test.InstrumentationRegistry.getInstrumentation;
20
21import static org.junit.Assert.assertEquals;
22import static org.junit.Assert.assertNotNull;
23import static org.junit.Assert.assertTrue;
24import static org.junit.Assert.fail;
25
26import android.media.AudioManager;
27import android.media.session.MediaController;
28import android.media.session.MediaSession;
29import android.media.session.PlaybackState;
30import android.net.Uri;
31import android.os.Build;
32import android.os.Bundle;
33import android.os.Handler;
34import android.os.Looper;
35import android.os.ResultReceiver;
36import android.os.SystemClock;
37import android.support.test.filters.SmallTest;
38import android.support.test.runner.AndroidJUnit4;
39import android.support.v4.media.MediaDescriptionCompat;
40import android.support.v4.media.RatingCompat;
41import android.support.v4.media.VolumeProviderCompat;
42
43import org.junit.After;
44import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
47
48import java.util.ArrayList;
49import java.util.List;
50
51/**
52 * Test {@link MediaControllerCompat}.
53 */
54@RunWith(AndroidJUnit4.class)
55public class MediaControllerCompatTest {
56    // The maximum time to wait for an operation.
57    private static final long TIME_OUT_MS = 3000L;
58    private static final String SESSION_TAG = "test-session";
59    private static final String EXTRAS_KEY = "test-key";
60    private static final String EXTRAS_VALUE = "test-val";
61    private static final float DELTA = 1e-4f;
62    private static final boolean ENABLED = true;
63    private static final boolean DISABLED = false;
64    private static final long TEST_POSITION = 1000000L;
65    private static final float TEST_PLAYBACK_SPEED = 3.0f;
66
67
68    private final Object mWaitLock = new Object();
69    private Handler mHandler = new Handler(Looper.getMainLooper());
70    private MediaSessionCompat mSession;
71    private MediaSessionCallback mCallback = new MediaSessionCallback();
72    private MediaControllerCompat mController;
73
74    @Before
75    public void setUp() throws Exception {
76        getInstrumentation().runOnMainSync(new Runnable() {
77            @Override
78            public void run() {
79                mSession = new MediaSessionCompat(getContext(), SESSION_TAG);
80                mSession.setCallback(mCallback, mHandler);
81                mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
82                mController = mSession.getController();
83            }
84        });
85    }
86
87    @After
88    public void tearDown() throws Exception {
89        mSession.release();
90    }
91
92    @Test
93    @SmallTest
94    public void testGetPackageName() {
95        assertEquals(getContext().getPackageName(), mController.getPackageName());
96    }
97
98    @Test
99    @SmallTest
100    public void testGetRatingType() {
101        assertEquals("Default rating type of a session must be RatingCompat.RATING_NONE",
102                RatingCompat.RATING_NONE, mController.getRatingType());
103
104        mSession.setRatingType(RatingCompat.RATING_5_STARS);
105        assertEquals(RatingCompat.RATING_5_STARS, mController.getRatingType());
106    }
107
108    @Test
109    @SmallTest
110    public void testGetSessionToken() throws Exception {
111        assertEquals(mSession.getSessionToken(), mController.getSessionToken());
112    }
113
114    @Test
115    @SmallTest
116    public void testSendCommand() throws Exception {
117        synchronized (mWaitLock) {
118            mCallback.reset();
119            final String command = "test-command";
120            final Bundle extras = new Bundle();
121            extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
122            mController.sendCommand(command, extras, new ResultReceiver(null));
123            mWaitLock.wait(TIME_OUT_MS);
124            assertTrue(mCallback.mOnCommandCalled);
125            assertNotNull(mCallback.mCommandCallback);
126            assertEquals(command, mCallback.mCommand);
127            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
128        }
129    }
130
131    @Test
132    @SmallTest
133    public void testAddRemoveQueueItems() throws Exception {
134        final String mediaId1 = "media_id_1";
135        final String mediaTitle1 = "media_title_1";
136        MediaDescriptionCompat itemDescription1 = new MediaDescriptionCompat.Builder()
137                .setMediaId(mediaId1).setTitle(mediaTitle1).build();
138
139        final String mediaId2 = "media_id_2";
140        final String mediaTitle2 = "media_title_2";
141        MediaDescriptionCompat itemDescription2 = new MediaDescriptionCompat.Builder()
142                .setMediaId(mediaId2).setTitle(mediaTitle2).build();
143
144        synchronized (mWaitLock) {
145            mCallback.reset();
146            mController.addQueueItem(itemDescription1);
147            mWaitLock.wait(TIME_OUT_MS);
148            assertTrue(mCallback.mOnAddQueueItemCalled);
149            assertEquals(-1, mCallback.mQueueIndex);
150            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
151            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
152
153            mCallback.reset();
154            mController.addQueueItem(itemDescription2, 0);
155            mWaitLock.wait(TIME_OUT_MS);
156            assertTrue(mCallback.mOnAddQueueItemAtCalled);
157            assertEquals(0, mCallback.mQueueIndex);
158            assertEquals(mediaId2, mCallback.mQueueDescription.getMediaId());
159            assertEquals(mediaTitle2, mCallback.mQueueDescription.getTitle());
160
161            mCallback.reset();
162            mController.removeQueueItemAt(0);
163            mWaitLock.wait(TIME_OUT_MS);
164            assertTrue(mCallback.mOnRemoveQueueItemCalled);
165            assertEquals(mediaId2, mCallback.mQueueDescription.getMediaId());
166            assertEquals(mediaTitle2, mCallback.mQueueDescription.getTitle());
167
168            mCallback.reset();
169            mController.removeQueueItem(itemDescription1);
170            mWaitLock.wait(TIME_OUT_MS);
171            assertTrue(mCallback.mOnRemoveQueueItemCalled);
172            assertEquals(mediaId1, mCallback.mQueueDescription.getMediaId());
173            assertEquals(mediaTitle1, mCallback.mQueueDescription.getTitle());
174
175            // Try to modify the queue when the session does not support queue management.
176            mSession.setFlags(0);
177            try {
178                mController.addQueueItem(itemDescription1);
179                fail();
180            } catch (UnsupportedOperationException e) {
181                // Expected.
182            }
183        }
184    }
185
186    // TODO: Uncomment after fixing this test. This test causes an Exception on System UI.
187    // @Test
188    // @SmallTest
189    public void testVolumeControl() throws Exception {
190        VolumeProviderCompat vp =
191                new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
192            @Override
193            public void onSetVolumeTo(int volume) {
194                synchronized (mWaitLock) {
195                    setCurrentVolume(volume);
196                    mWaitLock.notify();
197                }
198            }
199
200            @Override
201            public void onAdjustVolume(int direction) {
202                synchronized (mWaitLock) {
203                    switch (direction) {
204                        case AudioManager.ADJUST_LOWER:
205                            setCurrentVolume(getCurrentVolume() - 1);
206                            break;
207                        case AudioManager.ADJUST_RAISE:
208                            setCurrentVolume(getCurrentVolume() + 1);
209                            break;
210                    }
211                    mWaitLock.notify();
212                }
213            }
214        };
215        mSession.setPlaybackToRemote(vp);
216
217        synchronized (mWaitLock) {
218            // test setVolumeTo
219            mController.setVolumeTo(7, 0);
220            mWaitLock.wait(TIME_OUT_MS);
221            assertEquals(7, vp.getCurrentVolume());
222
223            // test adjustVolume
224            mController.adjustVolume(AudioManager.ADJUST_LOWER, 0);
225            mWaitLock.wait(TIME_OUT_MS);
226            assertEquals(6, vp.getCurrentVolume());
227
228            mController.adjustVolume(AudioManager.ADJUST_RAISE, 0);
229            mWaitLock.wait(TIME_OUT_MS);
230            assertEquals(7, vp.getCurrentVolume());
231        }
232    }
233
234    @Test
235    @SmallTest
236    public void testTransportControlsAndMediaSessionCallback() throws Exception {
237        MediaControllerCompat.TransportControls controls = mController.getTransportControls();
238        synchronized (mWaitLock) {
239            mCallback.reset();
240            controls.play();
241            mWaitLock.wait(TIME_OUT_MS);
242            assertTrue(mCallback.mOnPlayCalled);
243
244            mCallback.reset();
245            controls.pause();
246            mWaitLock.wait(TIME_OUT_MS);
247            assertTrue(mCallback.mOnPauseCalled);
248
249            mCallback.reset();
250            controls.stop();
251            mWaitLock.wait(TIME_OUT_MS);
252            assertTrue(mCallback.mOnStopCalled);
253
254            mCallback.reset();
255            controls.fastForward();
256            mWaitLock.wait(TIME_OUT_MS);
257            assertTrue(mCallback.mOnFastForwardCalled);
258
259            mCallback.reset();
260            controls.rewind();
261            mWaitLock.wait(TIME_OUT_MS);
262            assertTrue(mCallback.mOnRewindCalled);
263
264            mCallback.reset();
265            controls.skipToPrevious();
266            mWaitLock.wait(TIME_OUT_MS);
267            assertTrue(mCallback.mOnSkipToPreviousCalled);
268
269            mCallback.reset();
270            controls.skipToNext();
271            mWaitLock.wait(TIME_OUT_MS);
272            assertTrue(mCallback.mOnSkipToNextCalled);
273
274            mCallback.reset();
275            final long seekPosition = 1000;
276            controls.seekTo(seekPosition);
277            mWaitLock.wait(TIME_OUT_MS);
278            assertTrue(mCallback.mOnSeekToCalled);
279            assertEquals(seekPosition, mCallback.mSeekPosition);
280
281            mCallback.reset();
282            final RatingCompat rating =
283                    RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 3f);
284            controls.setRating(rating);
285            mWaitLock.wait(TIME_OUT_MS);
286            assertTrue(mCallback.mOnSetRatingCalled);
287            assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
288            assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
289
290            mCallback.reset();
291            final String mediaId = "test-media-id";
292            final Bundle extras = new Bundle();
293            extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
294            controls.playFromMediaId(mediaId, extras);
295            mWaitLock.wait(TIME_OUT_MS);
296            assertTrue(mCallback.mOnPlayFromMediaIdCalled);
297            assertEquals(mediaId, mCallback.mMediaId);
298            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
299
300            mCallback.reset();
301            final String query = "test-query";
302            controls.playFromSearch(query, extras);
303            mWaitLock.wait(TIME_OUT_MS);
304            assertTrue(mCallback.mOnPlayFromSearchCalled);
305            assertEquals(query, mCallback.mQuery);
306            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
307
308            mCallback.reset();
309            final Uri uri = Uri.parse("content://test/popcorn.mod");
310            controls.playFromUri(uri, extras);
311            mWaitLock.wait(TIME_OUT_MS);
312            assertTrue(mCallback.mOnPlayFromUriCalled);
313            assertEquals(uri, mCallback.mUri);
314            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
315
316            mCallback.reset();
317            final String action = "test-action";
318            controls.sendCustomAction(action, extras);
319            mWaitLock.wait(TIME_OUT_MS);
320            assertTrue(mCallback.mOnCustomActionCalled);
321            assertEquals(action, mCallback.mAction);
322            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
323
324            mCallback.reset();
325            mCallback.mOnCustomActionCalled = false;
326            final PlaybackStateCompat.CustomAction customAction =
327                    new PlaybackStateCompat.CustomAction.Builder(action, action, -1)
328                            .setExtras(extras)
329                            .build();
330            controls.sendCustomAction(customAction, extras);
331            mWaitLock.wait(TIME_OUT_MS);
332            assertTrue(mCallback.mOnCustomActionCalled);
333            assertEquals(action, mCallback.mAction);
334            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
335
336            mCallback.reset();
337            final long queueItemId = 1000;
338            controls.skipToQueueItem(queueItemId);
339            mWaitLock.wait(TIME_OUT_MS);
340            assertTrue(mCallback.mOnSkipToQueueItemCalled);
341            assertEquals(queueItemId, mCallback.mQueueItemId);
342
343            mCallback.reset();
344            controls.prepare();
345            mWaitLock.wait(TIME_OUT_MS);
346            assertTrue(mCallback.mOnPrepareCalled);
347
348            mCallback.reset();
349            controls.prepareFromMediaId(mediaId, extras);
350            mWaitLock.wait(TIME_OUT_MS);
351            assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
352            assertEquals(mediaId, mCallback.mMediaId);
353            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
354
355            mCallback.reset();
356            controls.prepareFromSearch(query, extras);
357            mWaitLock.wait(TIME_OUT_MS);
358            assertTrue(mCallback.mOnPrepareFromSearchCalled);
359            assertEquals(query, mCallback.mQuery);
360            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
361
362            mCallback.reset();
363            controls.prepareFromUri(uri, extras);
364            mWaitLock.wait(TIME_OUT_MS);
365            assertTrue(mCallback.mOnPrepareFromUriCalled);
366            assertEquals(uri, mCallback.mUri);
367            assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
368
369            mCallback.reset();
370            controls.setCaptioningEnabled(ENABLED);
371            mWaitLock.wait(TIME_OUT_MS);
372            assertTrue(mCallback.mOnSetCaptioningEnabledCalled);
373            assertEquals(ENABLED, mCallback.mCaptioningEnabled);
374
375            mCallback.reset();
376            final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
377            controls.setRepeatMode(repeatMode);
378            mWaitLock.wait(TIME_OUT_MS);
379            assertTrue(mCallback.mOnSetRepeatModeCalled);
380            assertEquals(repeatMode, mCallback.mRepeatMode);
381
382            mCallback.reset();
383            controls.setShuffleModeEnabled(ENABLED);
384            mWaitLock.wait(TIME_OUT_MS);
385            assertTrue(mCallback.mOnSetShuffleModeEnabledCalled);
386            assertEquals(ENABLED, mCallback.mShuffleModeEnabled);
387
388            mCallback.reset();
389            controls.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_ALL);
390            mWaitLock.wait(TIME_OUT_MS);
391            assertTrue(mCallback.mOnSetShuffleModeCalled);
392            assertEquals(PlaybackStateCompat.SHUFFLE_MODE_ALL, mCallback.mShuffleMode);
393        }
394    }
395
396    @Test
397    @SmallTest
398    public void testPlaybackInfo() {
399        final int playbackType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
400        final int volumeControl = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
401        final int maxVolume = 10;
402        final int currentVolume = 3;
403
404        int audioStream = 77;
405        MediaControllerCompat.PlaybackInfo info = new MediaControllerCompat.PlaybackInfo(
406                playbackType, audioStream, volumeControl, maxVolume, currentVolume);
407
408        assertEquals(playbackType, info.getPlaybackType());
409        assertEquals(audioStream, info.getAudioStream());
410        assertEquals(volumeControl, info.getVolumeControl());
411        assertEquals(maxVolume, info.getMaxVolume());
412        assertEquals(currentVolume, info.getCurrentVolume());
413    }
414
415    @Test
416    @SmallTest
417    public void testGetPlaybackStateWithPositionUpdate() throws InterruptedException {
418        final long stateSetTime = SystemClock.elapsedRealtime();
419        PlaybackStateCompat stateIn = new PlaybackStateCompat.Builder()
420                .setState(PlaybackStateCompat.STATE_PLAYING, TEST_POSITION, TEST_PLAYBACK_SPEED,
421                        stateSetTime)
422                .build();
423        mSession.setPlaybackState(stateIn);
424
425        final long waitDuration = 100L;
426        Thread.sleep(waitDuration);
427
428        final long expectedUpdateTime = waitDuration + stateSetTime;
429        final long expectedPosition = (long) (TEST_PLAYBACK_SPEED * waitDuration) + TEST_POSITION;
430
431        final double updateTimeTolerance = 30L;
432        final double positionTolerance = updateTimeTolerance * TEST_PLAYBACK_SPEED;
433
434        PlaybackStateCompat stateOut = mSession.getController().getPlaybackState();
435        assertEquals(expectedUpdateTime, stateOut.getLastPositionUpdateTime(), updateTimeTolerance);
436        assertEquals(expectedPosition, stateOut.getPosition(), positionTolerance);
437
438        // Compare the result with MediaController.getPlaybackState().
439        if (Build.VERSION.SDK_INT >= 21) {
440            MediaController controller = new MediaController(
441                    getContext(), (MediaSession.Token) mSession.getSessionToken().getToken());
442            PlaybackState state = controller.getPlaybackState();
443            assertEquals(state.getLastPositionUpdateTime(), stateOut.getLastPositionUpdateTime(),
444                    updateTimeTolerance);
445            assertEquals(state.getPosition(), stateOut.getPosition(), positionTolerance);
446        }
447    }
448
449    private class MediaSessionCallback extends MediaSessionCompat.Callback {
450        private long mSeekPosition;
451        private long mQueueItemId;
452        private RatingCompat mRating;
453        private String mMediaId;
454        private String mQuery;
455        private Uri mUri;
456        private String mAction;
457        private String mCommand;
458        private Bundle mExtras;
459        private ResultReceiver mCommandCallback;
460        private boolean mCaptioningEnabled;
461        private int mRepeatMode;
462        private boolean mShuffleModeEnabled;
463        private int mShuffleMode;
464        private int mQueueIndex;
465        private MediaDescriptionCompat mQueueDescription;
466        private List<MediaSessionCompat.QueueItem> mQueue = new ArrayList<>();
467
468        private boolean mOnPlayCalled;
469        private boolean mOnPauseCalled;
470        private boolean mOnStopCalled;
471        private boolean mOnFastForwardCalled;
472        private boolean mOnRewindCalled;
473        private boolean mOnSkipToPreviousCalled;
474        private boolean mOnSkipToNextCalled;
475        private boolean mOnSeekToCalled;
476        private boolean mOnSkipToQueueItemCalled;
477        private boolean mOnSetRatingCalled;
478        private boolean mOnPlayFromMediaIdCalled;
479        private boolean mOnPlayFromSearchCalled;
480        private boolean mOnPlayFromUriCalled;
481        private boolean mOnCustomActionCalled;
482        private boolean mOnCommandCalled;
483        private boolean mOnPrepareCalled;
484        private boolean mOnPrepareFromMediaIdCalled;
485        private boolean mOnPrepareFromSearchCalled;
486        private boolean mOnPrepareFromUriCalled;
487        private boolean mOnSetCaptioningEnabledCalled;
488        private boolean mOnSetRepeatModeCalled;
489        private boolean mOnSetShuffleModeEnabledCalled;
490        private boolean mOnSetShuffleModeCalled;
491        private boolean mOnAddQueueItemCalled;
492        private boolean mOnAddQueueItemAtCalled;
493        private boolean mOnRemoveQueueItemCalled;
494
495        public void reset() {
496            mSeekPosition = -1;
497            mQueueItemId = -1;
498            mRating = null;
499            mMediaId = null;
500            mQuery = null;
501            mUri = null;
502            mAction = null;
503            mExtras = null;
504            mCommand = null;
505            mCommandCallback = null;
506            mCaptioningEnabled = false;
507            mShuffleModeEnabled = false;
508            mRepeatMode = PlaybackStateCompat.REPEAT_MODE_NONE;
509            mShuffleMode = PlaybackStateCompat.SHUFFLE_MODE_NONE;
510            mQueueIndex = -1;
511            mQueueDescription = null;
512
513            mOnPlayCalled = false;
514            mOnPauseCalled = false;
515            mOnStopCalled = false;
516            mOnFastForwardCalled = false;
517            mOnRewindCalled = false;
518            mOnSkipToPreviousCalled = false;
519            mOnSkipToNextCalled = false;
520            mOnSkipToQueueItemCalled = false;
521            mOnSeekToCalled = false;
522            mOnSetRatingCalled = false;
523            mOnPlayFromMediaIdCalled = false;
524            mOnPlayFromSearchCalled = false;
525            mOnPlayFromUriCalled = false;
526            mOnCustomActionCalled = false;
527            mOnCommandCalled = false;
528            mOnPrepareCalled = false;
529            mOnPrepareFromMediaIdCalled = false;
530            mOnPrepareFromSearchCalled = false;
531            mOnPrepareFromUriCalled = false;
532            mOnSetCaptioningEnabledCalled = false;
533            mOnSetRepeatModeCalled = false;
534            mOnSetShuffleModeEnabledCalled = false;
535            mOnSetShuffleModeCalled = false;
536            mOnAddQueueItemCalled = false;
537            mOnAddQueueItemAtCalled = false;
538            mOnRemoveQueueItemCalled = false;
539        }
540
541        @Override
542        public void onPlay() {
543            synchronized (mWaitLock) {
544                mOnPlayCalled = true;
545                mWaitLock.notify();
546            }
547        }
548
549        @Override
550        public void onPause() {
551            synchronized (mWaitLock) {
552                mOnPauseCalled = true;
553                mWaitLock.notify();
554            }
555        }
556
557        @Override
558        public void onStop() {
559            synchronized (mWaitLock) {
560                mOnStopCalled = true;
561                mWaitLock.notify();
562            }
563        }
564
565        @Override
566        public void onFastForward() {
567            synchronized (mWaitLock) {
568                mOnFastForwardCalled = true;
569                mWaitLock.notify();
570            }
571        }
572
573        @Override
574        public void onRewind() {
575            synchronized (mWaitLock) {
576                mOnRewindCalled = true;
577                mWaitLock.notify();
578            }
579        }
580
581        @Override
582        public void onSkipToPrevious() {
583            synchronized (mWaitLock) {
584                mOnSkipToPreviousCalled = true;
585                mWaitLock.notify();
586            }
587        }
588
589        @Override
590        public void onSkipToNext() {
591            synchronized (mWaitLock) {
592                mOnSkipToNextCalled = true;
593                mWaitLock.notify();
594            }
595        }
596
597        @Override
598        public void onSeekTo(long pos) {
599            synchronized (mWaitLock) {
600                mOnSeekToCalled = true;
601                mSeekPosition = pos;
602                mWaitLock.notify();
603            }
604        }
605
606        @Override
607        public void onSetRating(RatingCompat rating) {
608            synchronized (mWaitLock) {
609                mOnSetRatingCalled = true;
610                mRating = rating;
611                mWaitLock.notify();
612            }
613        }
614
615        @Override
616        public void onPlayFromMediaId(String mediaId, Bundle extras) {
617            synchronized (mWaitLock) {
618                mOnPlayFromMediaIdCalled = true;
619                mMediaId = mediaId;
620                mExtras = extras;
621                mWaitLock.notify();
622            }
623        }
624
625        @Override
626        public void onPlayFromSearch(String query, Bundle extras) {
627            synchronized (mWaitLock) {
628                mOnPlayFromSearchCalled = true;
629                mQuery = query;
630                mExtras = extras;
631                mWaitLock.notify();
632            }
633        }
634
635        @Override
636        public void onPlayFromUri(Uri uri, Bundle extras) {
637            synchronized (mWaitLock) {
638                mOnPlayFromUriCalled = true;
639                mUri = uri;
640                mExtras = extras;
641                mWaitLock.notify();
642            }
643        }
644
645        @Override
646        public void onCustomAction(String action, Bundle extras) {
647            synchronized (mWaitLock) {
648                mOnCustomActionCalled = true;
649                mAction = action;
650                mExtras = extras;
651                mWaitLock.notify();
652            }
653        }
654
655        @Override
656        public void onSkipToQueueItem(long id) {
657            synchronized (mWaitLock) {
658                mOnSkipToQueueItemCalled = true;
659                mQueueItemId = id;
660                mWaitLock.notify();
661            }
662        }
663
664        @Override
665        public void onCommand(String command, Bundle extras, ResultReceiver cb) {
666            synchronized (mWaitLock) {
667                mOnCommandCalled = true;
668                mCommand = command;
669                mExtras = extras;
670                mCommandCallback = cb;
671                mWaitLock.notify();
672            }
673        }
674
675        @Override
676        public void onPrepare() {
677            synchronized (mWaitLock) {
678                mOnPrepareCalled = true;
679                mWaitLock.notify();
680            }
681        }
682
683        @Override
684        public void onPrepareFromMediaId(String mediaId, Bundle extras) {
685            synchronized (mWaitLock) {
686                mOnPrepareFromMediaIdCalled = true;
687                mMediaId = mediaId;
688                mExtras = extras;
689                mWaitLock.notify();
690            }
691        }
692
693        @Override
694        public void onPrepareFromSearch(String query, Bundle extras) {
695            synchronized (mWaitLock) {
696                mOnPrepareFromSearchCalled = true;
697                mQuery = query;
698                mExtras = extras;
699                mWaitLock.notify();
700            }
701        }
702
703        @Override
704        public void onPrepareFromUri(Uri uri, Bundle extras) {
705            synchronized (mWaitLock) {
706                mOnPrepareFromUriCalled = true;
707                mUri = uri;
708                mExtras = extras;
709                mWaitLock.notify();
710            }
711        }
712
713        @Override
714        public void onSetRepeatMode(int repeatMode) {
715            synchronized (mWaitLock) {
716                mOnSetRepeatModeCalled = true;
717                mRepeatMode = repeatMode;
718                mWaitLock.notify();
719            }
720        }
721
722        @Override
723        public void onAddQueueItem(MediaDescriptionCompat description) {
724            synchronized (mWaitLock) {
725                mOnAddQueueItemCalled = true;
726                mQueueDescription = description;
727                mQueue.add(new MediaSessionCompat.QueueItem(description, mQueue.size()));
728                mSession.setQueue(mQueue);
729                mWaitLock.notify();
730            }
731        }
732
733        @Override
734        public void onAddQueueItem(MediaDescriptionCompat description, int index) {
735            synchronized (mWaitLock) {
736                mOnAddQueueItemAtCalled = true;
737                mQueueIndex = index;
738                mQueueDescription = description;
739                mQueue.add(index, new MediaSessionCompat.QueueItem(description, mQueue.size()));
740                mSession.setQueue(mQueue);
741                mWaitLock.notify();
742            }
743        }
744
745        @Override
746        public void onRemoveQueueItem(MediaDescriptionCompat description) {
747            synchronized (mWaitLock) {
748                mOnRemoveQueueItemCalled = true;
749                String mediaId = description.getMediaId();
750                for (int i = mQueue.size() - 1; i >= 0; --i) {
751                    if (mediaId.equals(mQueue.get(i).getDescription().getMediaId())) {
752                        mQueueDescription = mQueue.remove(i).getDescription();
753                        mSession.setQueue(mQueue);
754                        break;
755                    }
756                }
757                mWaitLock.notify();
758            }
759        }
760
761        @Override
762        public void onSetCaptioningEnabled(boolean enabled) {
763            synchronized (mWaitLock) {
764                mOnSetCaptioningEnabledCalled = true;
765                mCaptioningEnabled = enabled;
766                mWaitLock.notify();
767            }
768        }
769
770        @Override
771        public void onSetShuffleModeEnabled(boolean enabled) {
772            synchronized (mWaitLock) {
773                mOnSetShuffleModeEnabledCalled = true;
774                mShuffleModeEnabled = enabled;
775                mWaitLock.notify();
776            }
777        }
778
779        @Override
780        public void onSetShuffleMode(int shuffleMode) {
781            synchronized (mWaitLock) {
782                mOnSetShuffleModeCalled = true;
783                mShuffleMode = shuffleMode;
784                mWaitLock.notify();
785            }
786        }
787    }
788}
789