Merge "MediaSession2: Change return type of CommandGroup#getCommands()" into pi-dev
diff --git a/packages/MediaComponents/res/layout/full_transport_controls.xml b/packages/MediaComponents/res/layout/full_transport_controls.xml
index dd41a1f..0914785 100644
--- a/packages/MediaComponents/res/layout/full_transport_controls.xml
+++ b/packages/MediaComponents/res/layout/full_transport_controls.xml
@@ -28,4 +28,4 @@
<ImageButton android:id="@+id/pause" style="@style/FullTransportControlsButton.Pause" />
<ImageButton android:id="@+id/ffwd" style="@style/FullTransportControlsButton.Ffwd" />
<ImageButton android:id="@+id/next" style="@style/FullTransportControlsButton.Next" />
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/MediaComponents/res/layout/media_controller.xml b/packages/MediaComponents/res/layout/media_controller.xml
index c5fbee8..dfda840 100644
--- a/packages/MediaComponents/res/layout/media_controller.xml
+++ b/packages/MediaComponents/res/layout/media_controller.xml
@@ -105,6 +105,7 @@
android:id="@+id/cast"
android:layout_centerVertical="true"
android:visibility="gone"
+ android:contentDescription="@string/mr_button_content_description"
style="@style/TitleBarButton" />
</LinearLayout>
@@ -120,6 +121,7 @@
<SeekBar
android:id="@+id/mediacontroller_progress"
+ android:contentDescription="@string/mcv2_seek_bar_desc"
android:layout_width="match_parent"
android:layout_height="12dp"
android:maxHeight="2dp"
@@ -233,4 +235,4 @@
</LinearLayout>
</LinearLayout>
</RelativeLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/MediaComponents/res/values/strings.xml b/packages/MediaComponents/res/values/strings.xml
index 69e9dff..aaceac8 100644
--- a/packages/MediaComponents/res/values/strings.xml
+++ b/packages/MediaComponents/res/values/strings.xml
@@ -84,10 +84,6 @@
<!-- Placeholder text indicating that the user is currently casting screen. [CHAR LIMIT=50] -->
<string name="mr_controller_casting_screen">Casting screen</string>
- <string name="lockscreen_pause_button_content_description">Pause</string>
- <string name="lockscreen_play_button_content_description">Play</string>
- <string name="lockscreen_replay_button_content_description">Replay</string>
-
<!-- Text for error alert when a video container is not valid for progressive download/playback. -->
<string name="VideoView2_error_text_invalid_progressive_playback">This video isn\'t valid for streaming to this device.</string>
<!-- Text for error alert when a video cannot be played. It can be used by any app. -->
@@ -133,4 +129,25 @@
<string name="MediaControlView2_audio_track_number_text">
Track <xliff:g id="audio_number" example="1">%1$s</xliff:g>
</string>
+
+ <!--Content Descriptions -->
+ <string name="mcv2_back_button_desc">Back</string>
+ <string name="mcv2_overflow_left_button_desc">See more buttons</string>
+ <string name="mcv2_overflow_right_button_desc">Back to previous button list</string>
+ <string name="mcv2_seek_bar_desc">Playback progress</string>
+ <string name="mcv2_settings_button_desc">Settings</string>
+ <string name="mcv2_video_quality_button_desc">Video Quality Selection</string>
+ <string name="mcv2_cc_is_on">Subtitle is on. Click to hide it.</string>
+ <string name="mcv2_cc_is_off">Subtitle is off. Click to show it.</string>
+ <string name="mcv2_replay_button_desc">Replay</string>
+ <string name="mcv2_play_button_desc">Play</string>
+ <string name="mcv2_pause_button_desc">Pause</string>
+ <string name="mcv2_previous_button_desc">Previous media</string>
+ <string name="mcv2_next_button_desc">Next media</string>
+ <string name="mcv2_rewind_button_desc">Rewind by 10 seconds</string>
+ <string name="mcv2_ffwd_button_desc">Go forward by 30 seconds</string>
+ <string name="mcv2_launch_button_desc">Launch Link</string>
+ <string name="mcv2_muted_button_desc">Muted. Click to unmute</string>
+ <string name="mcv2_unmuted_button_desc">Click to Mute</string>
+ <string name="mcv2_full_screen_button_desc">Full screen</string>
</resources>
diff --git a/packages/MediaComponents/res/values/style.xml b/packages/MediaComponents/res/values/style.xml
index b1da137..0be04e6 100644
--- a/packages/MediaComponents/res/values/style.xml
+++ b/packages/MediaComponents/res/values/style.xml
@@ -10,30 +10,35 @@
<item name="android:src">@drawable/ic_skip_previous</item>
<item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_previous_button_desc</item>
</style>
<style name="FullTransportControlsButton.Next">
<item name="android:src">@drawable/ic_skip_next</item>
<item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_next_button_desc</item>
</style>
<style name="FullTransportControlsButton.Pause">
<item name="android:src">@drawable/ic_pause_circle_filled</item>
<item name="android:layout_width">@dimen/mcv2_pause_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_pause_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_pause_button_desc</item>
</style>
<style name="FullTransportControlsButton.Ffwd">
<item name="android:src">@drawable/ic_forward_30</item>
<item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_ffwd_button_desc</item>
</style>
<style name="FullTransportControlsButton.Rew">
<item name="android:src">@drawable/ic_rewind_10</item>
<item name="android:layout_width">@dimen/mcv2_full_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_full_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_rewind_button_desc</item>
</style>
<style name="EmbeddedTransportControlsButton">
@@ -46,30 +51,35 @@
<item name="android:src">@drawable/ic_skip_previous</item>
<item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_previous_button_desc</item>
</style>
<style name="EmbeddedTransportControlsButton.Next">
<item name="android:src">@drawable/ic_skip_next</item>
<item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_next_button_desc</item>
</style>
<style name="EmbeddedTransportControlsButton.Pause">
<item name="android:src">@drawable/ic_pause_circle_filled</item>
<item name="android:layout_width">@dimen/mcv2_pause_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_pause_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_pause_button_desc</item>
</style>
<style name="EmbeddedTransportControlsButton.Ffwd">
<item name="android:src">@drawable/ic_forward_30</item>
<item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_ffwd_button_desc</item>
</style>
<style name="EmbeddedTransportControlsButton.Rew">
<item name="android:src">@drawable/ic_rewind_10</item>
<item name="android:layout_width">@dimen/mcv2_embedded_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_embedded_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_rewind_button_desc</item>
</style>
<style name="MinimalTransportControlsButton">
@@ -81,6 +91,7 @@
<item name="android:src">@drawable/ic_pause_circle_filled</item>
<item name="android:layout_width">@dimen/mcv2_minimal_icon_size</item>
<item name="android:layout_height">@dimen/mcv2_minimal_icon_size</item>
+ <item name="android:contentDescription">@string/mcv2_pause_button_desc</item>
</style>
<style name="TitleBar">
@@ -95,10 +106,12 @@
<style name="TitleBarButton.Back">
<item name="android:src">@drawable/ic_arrow_back</item>
+ <item name="android:contentDescription">@string/mcv2_back_button_desc</item>
</style>
<style name="TitleBarButton.Launch">
<item name="android:src">@drawable/ic_launch</item>
+ <item name="android:contentDescription">@string/mcv2_launch_button_desc</item>
</style>
<style name="TimeText">
@@ -137,29 +150,36 @@
<style name="BottomBarButton.CC">
<item name="android:src">@drawable/ic_subtitle_off</item>
+ <item name="android:contentDescription">@string/mcv2_cc_is_off</item>
</style>
<style name="BottomBarButton.FullScreen">
<item name="android:src">@drawable/ic_fullscreen</item>
+ <item name="android:contentDescription">@string/mcv2_full_screen_button_desc</item>
</style>
<style name="BottomBarButton.OverflowRight">
<item name="android:src">@drawable/ic_chevron_right</item>
+ <item name="android:contentDescription">@string/mcv2_overflow_right_button_desc</item>
</style>
<style name="BottomBarButton.OverflowLeft">
<item name="android:src">@drawable/ic_chevron_left</item>
+ <item name="android:contentDescription">@string/mcv2_overflow_left_button_desc</item>
</style>
<style name="BottomBarButton.Settings">
<item name="android:src">@drawable/ic_settings</item>
+ <item name="android:contentDescription">@string/mcv2_settings_button_desc</item>
</style>
<style name="BottomBarButton.Mute">
<item name="android:src">@drawable/ic_unmute</item>
+ <item name="android:contentDescription">@string/mcv2_unmuted_button_desc</item>
</style>
<style name="BottomBarButton.VideoQuality">
- <item name="android:src">@drawable/ic_high_quality</item>
+ <item name="android:src">@drawable/ic_high_quality</item>
+ <item name="android:contentDescription">@string/mcv2_video_quality_button_desc</item>
</style>
</resources>
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 59c90ab..721e0a2 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -24,12 +24,12 @@
import static android.media.MediaSession2.COMMAND_CODE_PLAYLIST_SET_LIST_METADATA;
import static android.media.MediaSession2.COMMAND_CODE_PLAYLIST_SET_REPEAT_MODE;
import static android.media.MediaSession2.COMMAND_CODE_PLAYLIST_SET_SHUFFLE_MODE;
-import static android.media.MediaSession2.COMMAND_CODE_PLAY_FROM_MEDIA_ID;
-import static android.media.MediaSession2.COMMAND_CODE_PLAY_FROM_SEARCH;
-import static android.media.MediaSession2.COMMAND_CODE_PLAY_FROM_URI;
-import static android.media.MediaSession2.COMMAND_CODE_PREPARE_FROM_MEDIA_ID;
-import static android.media.MediaSession2.COMMAND_CODE_PREPARE_FROM_SEARCH;
-import static android.media.MediaSession2.COMMAND_CODE_PREPARE_FROM_URI;
+import static android.media.MediaSession2.COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID;
+import static android.media.MediaSession2.COMMAND_CODE_SESSION_PLAY_FROM_SEARCH;
+import static android.media.MediaSession2.COMMAND_CODE_SESSION_PLAY_FROM_URI;
+import static android.media.MediaSession2.COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID;
+import static android.media.MediaSession2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH;
+import static android.media.MediaSession2.COMMAND_CODE_SESSION_PREPARE_FROM_URI;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -438,7 +438,7 @@
@Override
public void prepareFromUri_impl(Uri uri, Bundle extras) {
- final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PREPARE_FROM_URI);
+ final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_SESSION_PREPARE_FROM_URI);
if (uri == null) {
throw new IllegalArgumentException("uri shouldn't be null");
}
@@ -455,7 +455,8 @@
@Override
public void prepareFromSearch_impl(String query, Bundle extras) {
- final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PREPARE_FROM_SEARCH);
+ final IMediaSession2 binder = getSessionBinderIfAble(
+ COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH);
if (TextUtils.isEmpty(query)) {
throw new IllegalArgumentException("query shouldn't be empty");
}
@@ -472,7 +473,8 @@
@Override
public void prepareFromMediaId_impl(String mediaId, Bundle extras) {
- final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PREPARE_FROM_MEDIA_ID);
+ final IMediaSession2 binder = getSessionBinderIfAble(
+ COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID);
if (mediaId == null) {
throw new IllegalArgumentException("mediaId shouldn't be null");
}
@@ -489,7 +491,7 @@
@Override
public void playFromUri_impl(Uri uri, Bundle extras) {
- final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAY_FROM_URI);
+ final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_SESSION_PLAY_FROM_URI);
if (uri == null) {
throw new IllegalArgumentException("uri shouldn't be null");
}
@@ -506,7 +508,7 @@
@Override
public void playFromSearch_impl(String query, Bundle extras) {
- final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAY_FROM_SEARCH);
+ final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_SESSION_PLAY_FROM_SEARCH);
if (TextUtils.isEmpty(query)) {
throw new IllegalArgumentException("query shouldn't be empty");
}
@@ -523,7 +525,8 @@
@Override
public void playFromMediaId_impl(String mediaId, Bundle extras) {
- final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAY_FROM_MEDIA_ID);
+ final IMediaSession2 binder = getSessionBinderIfAble(
+ COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID);
if (mediaId == null) {
throw new IllegalArgumentException("mediaId shouldn't be null");
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java b/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
index 286f5ee..5fd5812 100644
--- a/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
@@ -78,8 +78,6 @@
METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_URI, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_ADVERTISEMENT, METADATA_TYPE_LONG);
METADATA_KEYS_TYPE.put(METADATA_KEY_DOWNLOAD_STATUS, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_RADIO_FREQUENCY, METADATA_TYPE_FLOAT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_RADIO_CALLSIGN, METADATA_TYPE_TEXT);
}
private static final @TextKey
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 2b46feb..a3cb0c6 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -539,7 +539,7 @@
@Override
public void prepareFromUri(final IMediaController2 caller, final Uri uri,
final Bundle extras) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PREPARE_FROM_URI, (session, controller) -> {
+ onCommand(caller, MediaSession2.COMMAND_CODE_SESSION_PREPARE_FROM_URI, (session, controller) -> {
if (uri == null) {
Log.w(TAG, "prepareFromUri(): Ignoring null uri from " + controller);
return;
@@ -551,7 +551,7 @@
@Override
public void prepareFromSearch(final IMediaController2 caller, final String query,
final Bundle extras) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PREPARE_FROM_SEARCH, (session, controller) -> {
+ onCommand(caller, MediaSession2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH, (session, controller) -> {
if (TextUtils.isEmpty(query)) {
Log.w(TAG, "prepareFromSearch(): Ignoring empty query from " + controller);
return;
@@ -564,7 +564,7 @@
@Override
public void prepareFromMediaId(final IMediaController2 caller, final String mediaId,
final Bundle extras) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PREPARE_FROM_MEDIA_ID,
+ onCommand(caller, MediaSession2.COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID,
(session, controller) -> {
if (mediaId == null) {
Log.w(TAG, "prepareFromMediaId(): Ignoring null mediaId from " + controller);
@@ -578,7 +578,7 @@
@Override
public void playFromUri(final IMediaController2 caller, final Uri uri,
final Bundle extras) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PLAY_FROM_URI, (session, controller) -> {
+ onCommand(caller, MediaSession2.COMMAND_CODE_SESSION_PLAY_FROM_URI, (session, controller) -> {
if (uri == null) {
Log.w(TAG, "playFromUri(): Ignoring null uri from " + controller);
return;
@@ -590,7 +590,7 @@
@Override
public void playFromSearch(final IMediaController2 caller, final String query,
final Bundle extras) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PLAY_FROM_SEARCH, (session, controller) -> {
+ onCommand(caller, MediaSession2.COMMAND_CODE_SESSION_PLAY_FROM_SEARCH, (session, controller) -> {
if (TextUtils.isEmpty(query)) {
Log.w(TAG, "playFromSearch(): Ignoring empty query from " + controller);
return;
@@ -603,7 +603,7 @@
@Override
public void playFromMediaId(final IMediaController2 caller, final String mediaId,
final Bundle extras) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PLAY_FROM_MEDIA_ID, (session, controller) -> {
+ onCommand(caller, MediaSession2.COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID, (session, controller) -> {
if (mediaId == null) {
Log.w(TAG, "playFromMediaId(): Ignoring null mediaId from " + controller);
return;
@@ -616,8 +616,7 @@
@Override
public void setRating(final IMediaController2 caller, final String mediaId,
final Bundle ratingBundle) {
- // TODO(jaewan): Define COMMAND_CODE_SET_RATING
- onCommand(caller, MediaSession2.COMMAND_CODE_SET_RATING, (session, controller) -> {
+ onCommand(caller, MediaSession2.COMMAND_CODE_SESSION_SET_RATING, (session, controller) -> {
if (mediaId == null) {
Log.w(TAG, "setRating(): Ignoring null mediaId from " + controller);
return;
@@ -716,7 +715,7 @@
@Override
public void skipToPreviousItem(IMediaController2 caller) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM,
+ onCommand(caller, MediaSession2.COMMAND_CODE_PLAYLIST_SKIP_PREV_ITEM,
(session, controller) -> {
session.getInstance().skipToPreviousItem();
});
@@ -724,7 +723,7 @@
@Override
public void skipToNextItem(IMediaController2 caller) {
- onCommand(caller, MediaSession2.COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM,
+ onCommand(caller, MediaSession2.COMMAND_CODE_PLAYLIST_SKIP_NEXT_ITEM,
(session, controller) -> {
session.getInstance().skipToNextItem();
});
diff --git a/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java b/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
index 693e137..dfbe56a 100644
--- a/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
+++ b/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
@@ -23,6 +23,7 @@
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;
@@ -47,8 +48,8 @@
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")
@@ -69,6 +70,22 @@
@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;
@@ -127,14 +144,23 @@
}
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();
}
}
@@ -172,6 +198,7 @@
mMetadata = metadata;
mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1);
+ updatePlayerDataSourceLocked();
}
notifyPlaylistChanged();
}
@@ -210,6 +237,7 @@
}
if (!hasValidItem()) {
mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1);
+ updatePlayerDataSourceLocked();
} else {
updateCurrentIfNeededLocked();
}
@@ -249,6 +277,7 @@
mPlaylist.set(index, item);
if (!hasValidItem()) {
mCurrent = getNextValidPlayItemLocked(END_OF_PLAYLIST, 1);
+ updatePlayerDataSourceLocked();
} else {
updateCurrentIfNeededLocked();
}
@@ -291,7 +320,7 @@
@Override
public void skipToNextItem() {
synchronized (mLock) {
- if (!hasValidItem()) {
+ if (!hasValidItem() || mCurrent == mEopPlayItem) {
return;
}
PlayItem next = getNextValidPlayItemLocked(mCurrent.shuffledIdx, 1);
@@ -318,6 +347,23 @@
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();
}
@@ -339,6 +385,7 @@
}
mShuffleMode = shuffleMode;
applyShuffleModeLocked();
+ updateCurrentIfNeededLocked();
}
notifyShuffleModeChanged();
}
@@ -373,6 +420,7 @@
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) {
@@ -414,9 +462,21 @@
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);
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index 9ae75b0..4cdc41d 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -207,10 +207,6 @@
private List<String> mPlaybackSpeedTextList;
private List<Float> mPlaybackSpeedList;
- private CharSequence mPlayDescription;
- private CharSequence mPauseDescription;
- private CharSequence mReplayDescription;
-
public MediaControlView2Impl(MediaControlView2 instance,
ViewGroupProvider superProvider, ViewGroupProvider privateProvider) {
super(instance, superProvider, privateProvider);
@@ -479,12 +475,6 @@
}
private void initControllerView(View v) {
- mPlayDescription = mResources.getText(R.string.lockscreen_play_button_content_description);
- mPauseDescription =
- mResources.getText(R.string.lockscreen_pause_button_content_description);
- mReplayDescription =
- mResources.getText(R.string.lockscreen_replay_button_content_description);
-
// Relating to Title Bar View
mTitleBar = v.findViewById(R.id.title_bar);
mTitleView = v.findViewById(R.id.title_text);
@@ -707,12 +697,14 @@
mControls.pause();
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_play_circle_filled, null));
- mPlayPauseButton.setContentDescription(mPlayDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_play_button_desc));
} else {
mControls.play();
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_pause_circle_filled, null));
- mPlayPauseButton.setContentDescription(mPauseDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_pause_button_desc));
}
}
@@ -748,7 +740,8 @@
if (mIsStopped) {
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_play_circle_filled, null));
- mPlayPauseButton.setContentDescription(mPlayDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_play_button_desc));
mIsStopped = false;
}
}
@@ -897,11 +890,15 @@
if (!mIsMute) {
mMuteButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_mute, null));
+ mMuteButton.setContentDescription(
+ mResources.getString(R.string.mcv2_muted_button_desc));
mIsMute = true;
mController.sendCommand(COMMAND_MUTE, null, null);
} else {
mMuteButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_unmute, null));
+ mMuteButton.setContentDescription(
+ mResources.getString(R.string.mcv2_unmuted_button_desc));
mIsMute = false;
mController.sendCommand(COMMAND_UNMUTE, null, null);
}
@@ -975,12 +972,16 @@
MediaControlView2Impl.COMMAND_SHOW_SUBTITLE, extra, null);
mSubtitleButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_subtitle_on, null));
+ mSubtitleButton.setContentDescription(
+ mResources.getString(R.string.mcv2_cc_is_on));
mSubtitleIsEnabled = true;
} else {
mController.sendCommand(
MediaControlView2Impl.COMMAND_HIDE_SUBTITLE, null, null);
mSubtitleButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_subtitle_off, null));
+ mSubtitleButton.setContentDescription(
+ mResources.getString(R.string.mcv2_cc_is_off));
mSubtitleIsEnabled = false;
}
@@ -1106,11 +1107,13 @@
if (isPlaying()) {
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_pause_circle_filled, null));
- mPlayPauseButton.setContentDescription(mPauseDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_pause_button_desc));
} else {
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_play_circle_filled, null));
- mPlayPauseButton.setContentDescription(mPlayDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_play_button_desc));
}
}
@@ -1218,19 +1221,22 @@
case PlaybackState.STATE_PLAYING:
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_pause_circle_filled, null));
- mPlayPauseButton.setContentDescription(mPauseDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_pause_button_desc));
mInstance.removeCallbacks(mUpdateProgress);
mInstance.post(mUpdateProgress);
break;
case PlaybackState.STATE_PAUSED:
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_play_circle_filled, null));
- mPlayPauseButton.setContentDescription(mPlayDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_play_button_desc));
break;
case PlaybackState.STATE_STOPPED:
mPlayPauseButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_replay_circle_filled, null));
- mPlayPauseButton.setContentDescription(mReplayDescription);
+ mPlayPauseButton.setContentDescription(
+ mResources.getString(R.string.mcv2_replay_button_desc));
mIsStopped = true;
break;
default:
diff --git a/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java b/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
index ca941ab..55a34fd 100644
--- a/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
+++ b/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
@@ -24,6 +24,7 @@
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;
@@ -35,6 +36,7 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Matchers;
import java.util.ArrayList;
import java.util.List;
@@ -56,6 +58,7 @@
private Context mContext;
private MediaSession2Impl mSessionImpl;
private MediaPlayerBase mPlayer;
+ private PlayerEventCallback mPlayerEventCallback;
private SessionPlaylistAgent mAgent;
private OnDataSourceMissingHelper mDataSourceHelper;
private MyPlaylistEventCallback mEventCallback;
@@ -229,6 +232,12 @@
};
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);
@@ -567,6 +576,33 @@
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) {