blob: 2598bef48de7dc001ecd7789e7aec7d4290717ca [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.v4.media.session;
import static android.support.test.InstrumentationRegistry.getContext;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.ResultReceiver;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.v4.media.MediaDescriptionCompat;
import android.support.v4.media.PollingCheck;
import android.support.v4.media.RatingCompat;
import android.support.v4.media.VolumeProviderCompat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test {@link MediaControllerCompat}.
*/
@RunWith(AndroidJUnit4.class)
public class MediaControllerCompatTest {
// The maximum time to wait for an operation.
private static final long TIME_OUT_MS = 3000L;
private static final String SESSION_TAG = "test-session";
private static final String EXTRAS_KEY = "test-key";
private static final String EXTRAS_VALUE = "test-val";
private static final float DELTA = 1e-4f;
private final Object mWaitLock = new Object();
private Handler mHandler = new Handler(Looper.getMainLooper());
private MediaSessionCompat mSession;
private MediaSessionCallback mCallback = new MediaSessionCallback();
private MediaControllerCompat mController;
@Before
public void setUp() throws Exception {
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
mSession = new MediaSessionCompat(getContext(), SESSION_TAG);
mSession.setCallback(mCallback, mHandler);
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
mController = mSession.getController();
}
});
}
@After
public void tearDown() throws Exception {
mSession.release();
}
@Test
@SmallTest
public void testGetPackageName() {
assertEquals(getContext().getPackageName(), mController.getPackageName());
}
@Test
@SmallTest
public void testGetRatingType() {
assertEquals("Default rating type of a session must be RatingCompat.RATING_NONE",
RatingCompat.RATING_NONE, mController.getRatingType());
mSession.setRatingType(RatingCompat.RATING_5_STARS);
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
// Wait until the extra binder is ready.
new PollingCheck(TIME_OUT_MS) {
@Override
protected boolean check() {
return mController.getRatingType() != RatingCompat.RATING_NONE;
}
}.run();
}
assertEquals(RatingCompat.RATING_5_STARS, mController.getRatingType());
}
@Test
@SmallTest
public void testGetSessionToken() throws Exception {
assertEquals(mSession.getSessionToken(), mController.getSessionToken());
}
@Test
@SmallTest
public void testSendCommand() throws Exception {
synchronized (mWaitLock) {
mCallback.reset();
final String command = "test-command";
final Bundle extras = new Bundle();
extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
mController.sendCommand(command, extras, new ResultReceiver(null));
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnCommandCalled);
assertNotNull(mCallback.mCommandCallback);
assertEquals(command, mCallback.mCommand);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
}
}
@Test
@SmallTest
public void testAddRemoveQueueItems() throws Exception {
final String mediaId = "media_id";
final String mediaTitle = "media_title";
MediaDescriptionCompat itemDescription = new MediaDescriptionCompat.Builder()
.setMediaId(mediaId).setTitle(mediaTitle).build();
synchronized (mWaitLock) {
mCallback.reset();
mController.addQueueItem(itemDescription);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnAddQueueItemCalled);
assertEquals(-1, mCallback.mQueueIndex);
assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
mCallback.reset();
mController.addQueueItem(itemDescription, 0);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnAddQueueItemAtCalled);
assertEquals(0, mCallback.mQueueIndex);
assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
mCallback.reset();
mController.removeQueueItemAt(0);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnRemoveQueueItemAtCalled);
assertEquals(0, mCallback.mQueueIndex);
mCallback.reset();
mController.removeQueueItem(itemDescription);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnRemoveQueueItemCalled);
assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
}
}
// TODO: Uncomment after fixing this test. This test causes an Exception on System UI.
// @Test
// @SmallTest
public void testVolumeControl() throws Exception {
VolumeProviderCompat vp =
new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
@Override
public void onSetVolumeTo(int volume) {
synchronized (mWaitLock) {
setCurrentVolume(volume);
mWaitLock.notify();
}
}
@Override
public void onAdjustVolume(int direction) {
synchronized (mWaitLock) {
switch (direction) {
case AudioManager.ADJUST_LOWER:
setCurrentVolume(getCurrentVolume() - 1);
break;
case AudioManager.ADJUST_RAISE:
setCurrentVolume(getCurrentVolume() + 1);
break;
}
mWaitLock.notify();
}
}
};
mSession.setPlaybackToRemote(vp);
synchronized (mWaitLock) {
// test setVolumeTo
mController.setVolumeTo(7, 0);
mWaitLock.wait(TIME_OUT_MS);
assertEquals(7, vp.getCurrentVolume());
// test adjustVolume
mController.adjustVolume(AudioManager.ADJUST_LOWER, 0);
mWaitLock.wait(TIME_OUT_MS);
assertEquals(6, vp.getCurrentVolume());
mController.adjustVolume(AudioManager.ADJUST_RAISE, 0);
mWaitLock.wait(TIME_OUT_MS);
assertEquals(7, vp.getCurrentVolume());
}
}
@Test
@SmallTest
public void testTransportControlsAndMediaSessionCallback() throws Exception {
MediaControllerCompat.TransportControls controls = mController.getTransportControls();
synchronized (mWaitLock) {
mCallback.reset();
controls.play();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPlayCalled);
mCallback.reset();
controls.pause();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPauseCalled);
mCallback.reset();
controls.stop();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnStopCalled);
mCallback.reset();
controls.fastForward();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnFastForwardCalled);
mCallback.reset();
controls.rewind();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnRewindCalled);
mCallback.reset();
controls.skipToPrevious();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnSkipToPreviousCalled);
mCallback.reset();
controls.skipToNext();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnSkipToNextCalled);
mCallback.reset();
final long seekPosition = 1000;
controls.seekTo(seekPosition);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnSeekToCalled);
assertEquals(seekPosition, mCallback.mSeekPosition);
mCallback.reset();
final RatingCompat rating =
RatingCompat.newStarRating(RatingCompat.RATING_5_STARS, 3f);
controls.setRating(rating);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnSetRatingCalled);
assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating(), DELTA);
mCallback.reset();
final String mediaId = "test-media-id";
final Bundle extras = new Bundle();
extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
controls.playFromMediaId(mediaId, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPlayFromMediaIdCalled);
assertEquals(mediaId, mCallback.mMediaId);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
final String query = "test-query";
controls.playFromSearch(query, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPlayFromSearchCalled);
assertEquals(query, mCallback.mQuery);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
final Uri uri = Uri.parse("content://test/popcorn.mod");
controls.playFromUri(uri, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPlayFromUriCalled);
assertEquals(uri, mCallback.mUri);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
final String action = "test-action";
controls.sendCustomAction(action, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnCustomActionCalled);
assertEquals(action, mCallback.mAction);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
mCallback.mOnCustomActionCalled = false;
final PlaybackStateCompat.CustomAction customAction =
new PlaybackStateCompat.CustomAction.Builder(action, action, -1)
.setExtras(extras)
.build();
controls.sendCustomAction(customAction, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnCustomActionCalled);
assertEquals(action, mCallback.mAction);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
final long queueItemId = 1000;
controls.skipToQueueItem(queueItemId);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnSkipToQueueItemCalled);
assertEquals(queueItemId, mCallback.mQueueItemId);
mCallback.reset();
controls.prepare();
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPrepareCalled);
mCallback.reset();
controls.prepareFromMediaId(mediaId, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
assertEquals(mediaId, mCallback.mMediaId);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
controls.prepareFromSearch(query, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPrepareFromSearchCalled);
assertEquals(query, mCallback.mQuery);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
controls.prepareFromUri(uri, extras);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnPrepareFromUriCalled);
assertEquals(uri, mCallback.mUri);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
mCallback.reset();
final int repeatMode = PlaybackStateCompat.REPEAT_MODE_ALL;
controls.setRepeatMode(repeatMode);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnSetRepeatModeCalled);
assertEquals(repeatMode, mCallback.mRepeatMode);
mCallback.reset();
final boolean shuffleModeEnabled = true;
controls.setShuffleModeEnabled(shuffleModeEnabled);
mWaitLock.wait(TIME_OUT_MS);
assertTrue(mCallback.mOnSetShuffleModeEnabledCalled);
assertEquals(shuffleModeEnabled, mCallback.mShuffleModeEnabled);
}
}
@Test
@SmallTest
public void testPlaybackInfo() {
final int playbackType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
final int volumeControl = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
final int maxVolume = 10;
final int currentVolume = 3;
int audioStream = 77;
MediaControllerCompat.PlaybackInfo info = new MediaControllerCompat.PlaybackInfo(
playbackType, audioStream, volumeControl, maxVolume, currentVolume);
assertEquals(playbackType, info.getPlaybackType());
assertEquals(audioStream, info.getAudioStream());
assertEquals(volumeControl, info.getVolumeControl());
assertEquals(maxVolume, info.getMaxVolume());
assertEquals(currentVolume, info.getCurrentVolume());
}
private class MediaSessionCallback extends MediaSessionCompat.Callback {
private long mSeekPosition;
private long mQueueItemId;
private RatingCompat mRating;
private String mMediaId;
private String mQuery;
private Uri mUri;
private String mAction;
private String mCommand;
private Bundle mExtras;
private ResultReceiver mCommandCallback;
private int mRepeatMode;
private boolean mShuffleModeEnabled;
private int mQueueIndex;
private MediaDescriptionCompat mQueueDescription;
private boolean mOnPlayCalled;
private boolean mOnPauseCalled;
private boolean mOnStopCalled;
private boolean mOnFastForwardCalled;
private boolean mOnRewindCalled;
private boolean mOnSkipToPreviousCalled;
private boolean mOnSkipToNextCalled;
private boolean mOnSeekToCalled;
private boolean mOnSkipToQueueItemCalled;
private boolean mOnSetRatingCalled;
private boolean mOnPlayFromMediaIdCalled;
private boolean mOnPlayFromSearchCalled;
private boolean mOnPlayFromUriCalled;
private boolean mOnCustomActionCalled;
private boolean mOnCommandCalled;
private boolean mOnPrepareCalled;
private boolean mOnPrepareFromMediaIdCalled;
private boolean mOnPrepareFromSearchCalled;
private boolean mOnPrepareFromUriCalled;
private boolean mOnSetRepeatModeCalled;
private boolean mOnSetShuffleModeEnabledCalled;
private boolean mOnAddQueueItemCalled;
private boolean mOnAddQueueItemAtCalled;
private boolean mOnRemoveQueueItemCalled;
private boolean mOnRemoveQueueItemAtCalled;
public void reset() {
mSeekPosition = -1;
mQueueItemId = -1;
mRating = null;
mMediaId = null;
mQuery = null;
mUri = null;
mAction = null;
mExtras = null;
mCommand = null;
mCommandCallback = null;
mShuffleModeEnabled = false;
mRepeatMode = PlaybackStateCompat.REPEAT_MODE_NONE;
mQueueIndex = -1;
mQueueDescription = null;
mOnPlayCalled = false;
mOnPauseCalled = false;
mOnStopCalled = false;
mOnFastForwardCalled = false;
mOnRewindCalled = false;
mOnSkipToPreviousCalled = false;
mOnSkipToNextCalled = false;
mOnSkipToQueueItemCalled = false;
mOnSeekToCalled = false;
mOnSetRatingCalled = false;
mOnPlayFromMediaIdCalled = false;
mOnPlayFromSearchCalled = false;
mOnPlayFromUriCalled = false;
mOnCustomActionCalled = false;
mOnCommandCalled = false;
mOnPrepareCalled = false;
mOnPrepareFromMediaIdCalled = false;
mOnPrepareFromSearchCalled = false;
mOnPrepareFromUriCalled = false;
mOnSetRepeatModeCalled = false;
mOnSetShuffleModeEnabledCalled = false;
mOnAddQueueItemCalled = false;
mOnAddQueueItemAtCalled = false;
mOnRemoveQueueItemCalled = false;
mOnRemoveQueueItemAtCalled = false;
}
@Override
public void onPlay() {
synchronized (mWaitLock) {
mOnPlayCalled = true;
mWaitLock.notify();
}
}
@Override
public void onPause() {
synchronized (mWaitLock) {
mOnPauseCalled = true;
mWaitLock.notify();
}
}
@Override
public void onStop() {
synchronized (mWaitLock) {
mOnStopCalled = true;
mWaitLock.notify();
}
}
@Override
public void onFastForward() {
synchronized (mWaitLock) {
mOnFastForwardCalled = true;
mWaitLock.notify();
}
}
@Override
public void onRewind() {
synchronized (mWaitLock) {
mOnRewindCalled = true;
mWaitLock.notify();
}
}
@Override
public void onSkipToPrevious() {
synchronized (mWaitLock) {
mOnSkipToPreviousCalled = true;
mWaitLock.notify();
}
}
@Override
public void onSkipToNext() {
synchronized (mWaitLock) {
mOnSkipToNextCalled = true;
mWaitLock.notify();
}
}
@Override
public void onSeekTo(long pos) {
synchronized (mWaitLock) {
mOnSeekToCalled = true;
mSeekPosition = pos;
mWaitLock.notify();
}
}
@Override
public void onSetRating(RatingCompat rating) {
synchronized (mWaitLock) {
mOnSetRatingCalled = true;
mRating = rating;
mWaitLock.notify();
}
}
@Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
synchronized (mWaitLock) {
mOnPlayFromMediaIdCalled = true;
mMediaId = mediaId;
mExtras = extras;
mWaitLock.notify();
}
}
@Override
public void onPlayFromSearch(String query, Bundle extras) {
synchronized (mWaitLock) {
mOnPlayFromSearchCalled = true;
mQuery = query;
mExtras = extras;
mWaitLock.notify();
}
}
@Override
public void onPlayFromUri(Uri uri, Bundle extras) {
synchronized (mWaitLock) {
mOnPlayFromUriCalled = true;
mUri = uri;
mExtras = extras;
mWaitLock.notify();
}
}
@Override
public void onCustomAction(String action, Bundle extras) {
synchronized (mWaitLock) {
mOnCustomActionCalled = true;
mAction = action;
mExtras = extras;
mWaitLock.notify();
}
}
@Override
public void onSkipToQueueItem(long id) {
synchronized (mWaitLock) {
mOnSkipToQueueItemCalled = true;
mQueueItemId = id;
mWaitLock.notify();
}
}
@Override
public void onCommand(String command, Bundle extras, ResultReceiver cb) {
synchronized (mWaitLock) {
mOnCommandCalled = true;
mCommand = command;
mExtras = extras;
mCommandCallback = cb;
mWaitLock.notify();
}
}
@Override
public void onPrepare() {
synchronized (mWaitLock) {
mOnPrepareCalled = true;
mWaitLock.notify();
}
}
@Override
public void onPrepareFromMediaId(String mediaId, Bundle extras) {
synchronized (mWaitLock) {
mOnPrepareFromMediaIdCalled = true;
mMediaId = mediaId;
mExtras = extras;
mWaitLock.notify();
}
}
@Override
public void onPrepareFromSearch(String query, Bundle extras) {
synchronized (mWaitLock) {
mOnPrepareFromSearchCalled = true;
mQuery = query;
mExtras = extras;
mWaitLock.notify();
}
}
@Override
public void onPrepareFromUri(Uri uri, Bundle extras) {
synchronized (mWaitLock) {
mOnPrepareFromUriCalled = true;
mUri = uri;
mExtras = extras;
mWaitLock.notify();
}
}
@Override
public void onSetRepeatMode(int repeatMode) {
synchronized (mWaitLock) {
mOnSetRepeatModeCalled = true;
mRepeatMode = repeatMode;
mWaitLock.notify();
}
}
@Override
public void onAddQueueItem(MediaDescriptionCompat description) {
synchronized (mWaitLock) {
mOnAddQueueItemCalled = true;
mQueueDescription = description;
mWaitLock.notify();
}
}
@Override
public void onAddQueueItem(MediaDescriptionCompat description, int index) {
synchronized (mWaitLock) {
mOnAddQueueItemAtCalled = true;
mQueueIndex = index;
mQueueDescription = description;
mWaitLock.notify();
}
}
@Override
public void onRemoveQueueItem(MediaDescriptionCompat description) {
synchronized (mWaitLock) {
mOnRemoveQueueItemCalled = true;
mQueueDescription = description;
mWaitLock.notify();
}
}
@Override
public void onSetShuffleModeEnabled(boolean enabled) {
synchronized (mWaitLock) {
mOnSetShuffleModeEnabledCalled = true;
mShuffleModeEnabled = enabled;
mWaitLock.notify();
}
}
@Override
public void onRemoveQueueItemAt(int index) {
synchronized (mWaitLock) {
mOnRemoveQueueItemAtCalled = true;
mQueueIndex = index;
mWaitLock.notify();
}
}
}
}