[go: nahoru, domu]

blob: 62a867fe57bba8af863f63bd42a06edcd08841a0 [file] [log] [blame]
/*
* Copyright 2019 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 androidx.media2.widget;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup;
import static androidx.test.espresso.matcher.ViewMatchers.isClickable;
import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import android.net.Uri;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Test {@link MediaControlView} with a {@link androidx.media2.common.SessionPlayer} or a {@link
* androidx.media2.session.MediaController}.
*/
@SuppressWarnings("deprecation")
@RunWith(Parameterized.class)
@LargeTest
public class MediaControlView_WithPlayerTest extends MediaWidgetTestBase {
@Parameterized.Parameters(name = "PlayerType={0}")
public static List<String> getPlayerTypes() {
return Arrays.asList(PLAYER_TYPE_MEDIA_CONTROLLER, PLAYER_TYPE_MEDIA_PLAYER);
}
private static final long FFWD_MS = 30000L;
private static final long REW_MS = 10000L;
private String mPlayerType;
private MediaControlViewTestActivity mActivity;
private MediaControlView mMediaControlView;
private androidx.media2.common.MediaItem mFileSchemeMediaItem;
@SuppressWarnings("deprecation")
@Rule
public androidx.test.rule.ActivityTestRule<MediaControlViewTestActivity> mActivityRule =
new androidx.test.rule.ActivityTestRule<>(MediaControlViewTestActivity.class);
public MediaControlView_WithPlayerTest(String playerType) {
mPlayerType = playerType;
}
@Before
public void setup() throws Throwable {
// Ignore all tests, b/202710013
assumeTrue(false);
mActivity = mActivityRule.getActivity();
mMediaControlView = mActivity.findViewById(
androidx.media2.widget.test.R.id.mediacontrolview);
Uri fileSchemeUri = getResourceUri(
androidx.media2.widget.test.R.raw.test_file_scheme_video);
mFileSchemeMediaItem = createTestMediaItem(fileSchemeUri);
checkAttachedToWindow(mMediaControlView);
}
@After
public void tearDown() throws Throwable {
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
closeAll();
}
});
}
/**
* It also tests clicking play button
*/
@Test
public void setPlayerOrController_PausedState() throws Throwable {
final CountDownLatch latchForPausedState = new CountDownLatch(1);
final CountDownLatch latchForPlayingState = new CountDownLatch(1);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
@Override
public void onPlayerStateChanged(
@NonNull PlayerWrapper player, int state) {
if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PAUSED) {
latchForPausedState.countDown();
} else if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PLAYING) {
latchForPlayingState.countDown();
}
}
},
mFileSchemeMediaItem,
null);
setPlayerWrapper(playerWrapper);
assertTrue(latchForPausedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(allOf(withId(R.id.pause), isCompletelyDisplayed()))
.check(matches(withContentDescription(R.string.mcv2_play_button_desc)))
.perform(click());
assertTrue(latchForPlayingState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(allOf(withId(R.id.pause), isCompletelyDisplayed()))
.check(matches(withContentDescription(R.string.mcv2_pause_button_desc)));
}
/**
* It also tests clicking pause button
*/
@Test
public void setPlayerOrController_PlayingState() throws Throwable {
final CountDownLatch latchForPreparedState = new CountDownLatch(1);
final CountDownLatch latchForPausedState = new CountDownLatch(1);
final CountDownLatch latchForPlayingState = new CountDownLatch(1);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
private int mState =
androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE;
@Override
public void onPlayerStateChanged(
@NonNull PlayerWrapper player, int state) {
if (mState == androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE
&& state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PAUSED) {
latchForPreparedState.countDown();
}
if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PLAYING) {
latchForPlayingState.countDown();
}
if (mState
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PLAYING
&& state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PAUSED) {
latchForPausedState.countDown();
}
mState = state;
}
},
mFileSchemeMediaItem,
null);
assertTrue(latchForPreparedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
playerWrapper.play();
assertTrue(latchForPlayingState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
setPlayerWrapper(playerWrapper);
onView(allOf(withId(R.id.pause), isCompletelyDisplayed()))
.check(matches(withContentDescription(R.string.mcv2_pause_button_desc)))
.perform(click());
assertTrue(latchForPausedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(allOf(withId(R.id.pause), isCompletelyDisplayed()))
.check(matches(withContentDescription(R.string.mcv2_play_button_desc)));
}
@Test
public void setPlayerAndController_MultipleTimes() throws Throwable {
DefaultPlayerCallback callback1 = new DefaultPlayerCallback();
PlayerWrapper wrapper1 = createPlayerWrapper(callback1, mFileSchemeMediaItem, null);
assertTrue(callback1.mPausedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
DefaultPlayerCallback callback2 = new DefaultPlayerCallback();
PlayerWrapper wrapper2 = createPlayerWrapperOfPlayer(callback2, mFileSchemeMediaItem, null);
assertTrue(callback2.mPausedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
DefaultPlayerCallback callback3 = new DefaultPlayerCallback();
PlayerWrapper wrapper3 = createPlayerWrapperOfController(callback3, mFileSchemeMediaItem,
null);
assertTrue(callback3.mPausedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
DefaultPlayerCallback callback4 = new DefaultPlayerCallback();
PlayerWrapper wrapper4 = createPlayerWrapper(callback4, mFileSchemeMediaItem, null);
assertTrue(callback4.mPausedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
setPlayerWrapper(wrapper1);
onView(allOf(withId(R.id.pause), isCompletelyDisplayed())).perform(click());
assertTrue(callback1.mPlayingLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(1, callback2.mPlayingLatch.getCount());
assertEquals(1, callback3.mPlayingLatch.getCount());
assertEquals(1, callback4.mPlayingLatch.getCount());
callback1.mPlayingLatch = new CountDownLatch(1);
setPlayerWrapper(wrapper2);
onView(allOf(withId(R.id.pause), isCompletelyDisplayed())).perform(click());
assertTrue(callback2.mPlayingLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(1, callback1.mPlayingLatch.getCount());
assertEquals(1, callback3.mPlayingLatch.getCount());
assertEquals(1, callback4.mPlayingLatch.getCount());
callback2.mPlayingLatch = new CountDownLatch(1);
setPlayerWrapper(wrapper3);
onView(allOf(withId(R.id.pause), isCompletelyDisplayed())).perform(click());
assertTrue(callback3.mPlayingLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(1, callback1.mPlayingLatch.getCount());
assertEquals(1, callback2.mPlayingLatch.getCount());
assertEquals(1, callback4.mPlayingLatch.getCount());
callback3.mPlayingLatch = new CountDownLatch(1);
setPlayerWrapper(wrapper4);
onView(allOf(withId(R.id.pause), isCompletelyDisplayed())).perform(click());
assertTrue(callback4.mPlayingLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(1, callback1.mPlayingLatch.getCount());
assertEquals(1, callback2.mPlayingLatch.getCount());
assertEquals(1, callback3.mPlayingLatch.getCount());
}
@Test
public void ffwdButtonClick() throws Throwable {
final CountDownLatch latchForPausedState = new CountDownLatch(1);
final CountDownLatch latchForFfwd = new CountDownLatch(1);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
@Override
public void onSeekCompleted(
@NonNull PlayerWrapper player, long position) {
if (position >= FFWD_MS) {
latchForFfwd.countDown();
}
}
@Override
public void onPlayerStateChanged(
@NonNull PlayerWrapper player, int state) {
if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PAUSED) {
latchForPausedState.countDown();
}
}
},
mFileSchemeMediaItem,
null);
setPlayerWrapper(playerWrapper);
assertTrue(latchForPausedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(allOf(withId(R.id.ffwd), isCompletelyDisplayed())).perform(click());
assertTrue(latchForFfwd.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
}
@Test
public void rewButtonClick() throws Throwable {
final CountDownLatch latchForFfwd = new CountDownLatch(1);
final CountDownLatch latchForRew = new CountDownLatch(1);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
long mExpectedPosition = FFWD_MS;
final long mDelta = 1000L;
@Override
public void onPlayerStateChanged(
@NonNull PlayerWrapper player, int state) {
if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PAUSED) {
mExpectedPosition = FFWD_MS;
player.seekTo(mExpectedPosition);
}
}
@Override
public void onSeekCompleted(
@NonNull PlayerWrapper player, long position) {
// Ignore the initial seek. Internal MediaPlayer behavior can be
// changed.
if (position == 0 && mExpectedPosition == FFWD_MS) {
return;
}
assertTrue(equalsSeekPosition(mExpectedPosition, position, mDelta));
if (mExpectedPosition == FFWD_MS) {
mExpectedPosition = position - REW_MS;
latchForFfwd.countDown();
} else {
latchForRew.countDown();
}
}
private boolean equalsSeekPosition(
long expected, long actual, long delta) {
return (actual < expected + delta) && (actual > expected - delta);
}
},
mFileSchemeMediaItem,
null);
setPlayerWrapper(playerWrapper);
assertTrue(latchForFfwd.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(allOf(withId(R.id.rew), isCompletelyDisplayed())).perform(click());
assertTrue(latchForRew.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
}
@Test
public void prevNextButtonClick() throws Throwable {
DefaultPlayerCallback callback = new DefaultPlayerCallback();
final List<androidx.media2.common.MediaItem> playlist = createTestPlaylist();
final PlayerWrapper playerWrapper = createPlayerWrapper(callback, null, playlist);
setPlayerWrapper(playerWrapper);
assertTrue(callback.mItemLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(0, playerWrapper.getCurrentMediaItemIndex());
onView(allOf(withId(R.id.prev), isCompletelyDisplayed()))
.check(matches(not(isEnabled())));
onView(allOf(withId(R.id.next), isCompletelyDisplayed())).check(matches(isEnabled()));
callback.mItemLatch = new CountDownLatch(1);
onView(allOf(withId(R.id.next), isCompletelyDisplayed())).perform(click());
assertTrue(callback.mItemLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(1, playerWrapper.getCurrentMediaItemIndex());
onView(allOf(withId(R.id.prev), isCompletelyDisplayed())).check(matches(isEnabled()));
onView(allOf(withId(R.id.next), isCompletelyDisplayed())).check(matches(isEnabled()));
callback.mItemLatch = new CountDownLatch(1);
onView(allOf(withId(R.id.next), isCompletelyDisplayed())).perform(click());
assertTrue(callback.mItemLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(2, playerWrapper.getCurrentMediaItemIndex());
onView(allOf(withId(R.id.prev), isCompletelyDisplayed())).check(matches(isEnabled()));
onView(allOf(withId(R.id.next), isCompletelyDisplayed()))
.check(matches(not(isEnabled())));
callback.mItemLatch = new CountDownLatch(1);
onView(allOf(withId(R.id.prev), isCompletelyDisplayed())).perform(click());
assertTrue(callback.mItemLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(1, playerWrapper.getCurrentMediaItemIndex());
onView(allOf(withId(R.id.prev), isCompletelyDisplayed())).check(matches(isEnabled()));
onView(allOf(withId(R.id.next), isCompletelyDisplayed())).check(matches(isEnabled()));
}
@FlakyTest(bugId = 179623359)
@Test
public void setMetadataForNonMusicFile() throws Throwable {
final String title = "BigBuckBunny";
final CountDownLatch latch = new CountDownLatch(1);
androidx.media2.common.MediaMetadata existingMetadata = mFileSchemeMediaItem.getMetadata();
androidx.media2.common.MediaMetadata.Builder metadataBuilder =
existingMetadata == null
? new androidx.media2.common.MediaMetadata.Builder()
: new androidx.media2.common.MediaMetadata.Builder(existingMetadata);
androidx.media2.common.MediaMetadata metadata =
metadataBuilder
.putString(androidx.media2.common.MediaMetadata.METADATA_KEY_TITLE, title)
.build();
mFileSchemeMediaItem.setMetadata(metadata);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
@Override
public void onCurrentMediaItemChanged(
@NonNull PlayerWrapper player,
@Nullable androidx.media2.common.MediaItem item) {
if (item != null) {
assertNotNull(item.getMetadata());
assertEquals(
title,
metadata.getString(
androidx.media2.common.MediaMetadata
.METADATA_KEY_TITLE));
latch.countDown();
}
}
},
mFileSchemeMediaItem,
null);
setPlayerWrapper(playerWrapper);
assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(withId(R.id.title_text)).check(matches(withText(title)));
}
@Test
public void subtitleButtonVisibilityForMusicFile() throws Throwable {
Uri uri = getResourceUri(androidx.media2.widget.test.R.raw.test_music);
final androidx.media2.common.MediaItem uriMediaItem = createTestMediaItem(uri);
final CountDownLatch latch = new CountDownLatch(1);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
@Override
void onTracksChanged(
@NonNull PlayerWrapper player,
@NonNull
List<androidx.media2.common.SessionPlayer.TrackInfo>
tracks) {
assertNotNull(tracks);
if (tracks.isEmpty()) {
// This callback can be called before tracks are available after
// setandroidx.media2.common.MediaItem
return;
}
latch.countDown();
}
},
uriMediaItem,
null);
setPlayerWrapper(playerWrapper);
assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
}
@Test
public void updateAndSelectSubtitleTrack() throws Throwable {
Uri uri = getResourceUri(
androidx.media2.widget.test.R.raw.testvideo_with_2_subtitle_tracks);
final String subtitleTrackOffText = mContext.getResources().getString(
R.string.MediaControlView_subtitle_off_text);
final String subtitleTrack1Text = mContext.getResources().getString(
R.string.MediaControlView_subtitle_track_number_text, 1);
final androidx.media2.common.MediaItem mediaItem = createTestMediaItem(uri);
final CountDownLatch latchForReady = new CountDownLatch(1);
final CountDownLatch latchForTrackUpdate = new CountDownLatch(1);
final CountDownLatch latchForSubtitleSelect = new CountDownLatch(1);
final CountDownLatch latchForSubtitleDeselect = new CountDownLatch(1);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
private androidx.media2.common.SessionPlayer.TrackInfo
mFirstSubtitleTrack;
@Override
public void onPlayerStateChanged(
@NonNull PlayerWrapper player, int state) {
if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PAUSED) {
latchForReady.countDown();
}
}
@Override
void onTracksChanged(
@NonNull PlayerWrapper player,
@NonNull
List<androidx.media2.common.SessionPlayer.TrackInfo>
tracks) {
if (mFirstSubtitleTrack != null) {
return;
}
assertNotNull(tracks);
for (int i = 0; i < tracks.size(); i++) {
androidx.media2.common.SessionPlayer.TrackInfo trackInfo =
tracks.get(i);
if (trackInfo.getTrackType()
== androidx.media2.common.SessionPlayer.TrackInfo
.MEDIA_TRACK_TYPE_SUBTITLE) {
mFirstSubtitleTrack = trackInfo;
latchForTrackUpdate.countDown();
break;
}
}
}
@Override
public void onTrackSelected(
@NonNull PlayerWrapper player,
@NonNull
androidx.media2.common.SessionPlayer.TrackInfo
trackInfo) {
assertEquals(mFirstSubtitleTrack, trackInfo);
latchForSubtitleSelect.countDown();
}
@Override
public void onTrackDeselected(
@NonNull PlayerWrapper player,
@NonNull
androidx.media2.common.SessionPlayer.TrackInfo
trackInfo) {
assertEquals(mFirstSubtitleTrack, trackInfo);
latchForSubtitleDeselect.countDown();
}
},
mediaItem,
null);
setPlayerWrapper(playerWrapper);
assertTrue(latchForReady.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
// MediaPlayer needs a surface to be set in order to produce subtitle tracks
playerWrapper.setSurface(mActivity.getSurfaceHolder().getSurface());
assertTrue(latchForTrackUpdate.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(withId(R.id.subtitle)).check(matches(isClickable()));
onView(withId(R.id.subtitle)).perform(click());
onView(withText(subtitleTrack1Text)).inRoot(isPlatformPopup())
.check(matches(isCompletelyDisplayed()));
onView(withText(subtitleTrack1Text)).inRoot(isPlatformPopup()).perform(click());
assertTrue(latchForSubtitleSelect.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(withId(R.id.subtitle)).check(matches(isClickable()));
onView(withId(R.id.subtitle)).perform(click());
onView(withText(subtitleTrackOffText)).inRoot(isPlatformPopup())
.check(matches(isCompletelyDisplayed()));
onView(withText(subtitleTrackOffText)).inRoot(isPlatformPopup()).perform(click());
assertTrue(latchForSubtitleDeselect.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
}
@Test
public void attachViewAndPlayAfterSetPlayerOrController() throws Throwable {
final CountDownLatch latchForPausedState = new CountDownLatch(1);
final CountDownLatch latchForPlayingState = new CountDownLatch(1);
final PlayerWrapper playerWrapper =
createPlayerWrapper(
new PlayerWrapper.PlayerCallback() {
@Override
public void onPlayerStateChanged(
@NonNull PlayerWrapper player, int state) {
if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PAUSED) {
latchForPausedState.countDown();
} else if (state
== androidx.media2.common.SessionPlayer
.PLAYER_STATE_PLAYING) {
latchForPlayingState.countDown();
}
}
},
mFileSchemeMediaItem,
null);
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
ViewGroup layout = mActivity.findViewById(
androidx.media2.widget.test.R.id.framelayout);
layout.removeView(mMediaControlView);
mMediaControlView = new MediaControlView(mActivity);
if (playerWrapper.mPlayer != null) {
mMediaControlView.setPlayer(playerWrapper.mPlayer);
} else if (playerWrapper.mController != null) {
mMediaControlView.setMediaController(playerWrapper.mController);
}
layout.addView(mMediaControlView);
}
});
checkAttachedToWindow(mMediaControlView);
assertTrue(latchForPausedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(allOf(withId(R.id.pause), isCompletelyDisplayed()))
.check(matches(withContentDescription(R.string.mcv2_play_button_desc)))
.perform(click());
assertTrue(latchForPlayingState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
onView(allOf(withId(R.id.pause), isCompletelyDisplayed()))
.check(matches(withContentDescription(R.string.mcv2_pause_button_desc)));
}
private void setPlayerWrapper(final PlayerWrapper playerWrapper) throws Throwable {
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
if (playerWrapper.mPlayer != null) {
mMediaControlView.setPlayer(playerWrapper.mPlayer);
} else if (playerWrapper.mController != null) {
mMediaControlView.setMediaController(playerWrapper.mController);
}
}
});
}
private PlayerWrapper createPlayerWrapper(
@NonNull PlayerWrapper.PlayerCallback callback,
@Nullable androidx.media2.common.MediaItem item,
@Nullable List<androidx.media2.common.MediaItem> playlist) {
return createPlayerWrapperOfType(callback, item, playlist, mPlayerType);
}
}