diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java b/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java index 67d9711ceb95..309c0a0c1a54 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java @@ -445,11 +445,14 @@ void sendFeedback( void updateMediaSession( int playbackState, long actions, + long positionMs, + float speed, String title, String artist, String album, MediaImage[] artwork) { - cobaltMediaSession.updateMediaSession(playbackState, actions, title, artist, album, artwork); + cobaltMediaSession.updateMediaSession( + playbackState, actions, positionMs, speed, title, artist, album, artwork); } /** Returns string for kSbSystemPropertyUserAgentAuxField */ diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java b/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java index 225b814d5f19..8ca2a3121942 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java @@ -348,6 +348,8 @@ private static void nativeInvokeAction(long action) { public void updateMediaSession( final int playbackState, final long actions, + final long positionMs, + final float speed, final String title, final String artist, final String album, @@ -356,7 +358,9 @@ public void updateMediaSession( new Runnable() { @Override public void run() { - updateMediaSessionInternal(playbackState, actions, title, artist, album, artwork); + updateMediaSessionInternal( + playbackState, actions, positionMs, speed, + title, artist, album, artwork); } }); } @@ -365,6 +369,8 @@ public void run() { private void updateMediaSessionInternal( int playbackState, long actions, + long positionMs, + float speed, String title, String artist, String album, @@ -389,26 +395,30 @@ private void updateMediaSessionInternal( } int androidPlaybackState; + String stateName; switch (playbackState) { case PLAYBACK_STATE_PLAYING: androidPlaybackState = PlaybackState.STATE_PLAYING; + stateName = "PLAYING"; break; case PLAYBACK_STATE_PAUSED: androidPlaybackState = PlaybackState.STATE_PAUSED; + stateName = "PAUSED"; break; case PLAYBACK_STATE_NONE: default: androidPlaybackState = PlaybackState.STATE_NONE; + stateName = "NONE"; break; } + Log.i(TAG, String.format( + "MediaSession state: %s, position: %d ms, speed: %f x", stateName, positionMs, speed)); + playbackStateBuilder = new PlaybackState.Builder() .setActions(actions) - .setState( - androidPlaybackState, - PlaybackState.PLAYBACK_POSITION_UNKNOWN, - playbackState == PLAYBACK_STATE_PLAYING ? 1.0f : 0.0f); + .setState(androidPlaybackState, positionMs, speed); mediaSession.setPlaybackState(playbackStateBuilder.build()); // Reset the metadata to make sure we don't retain any fields from previous playback. diff --git a/starboard/android/shared/cobalt/android_media_session_client.cc b/starboard/android/shared/cobalt/android_media_session_client.cc index c68428ab6c0a..25b932331cc9 100644 --- a/starboard/android/shared/cobalt/android_media_session_client.cc +++ b/starboard/android/shared/cobalt/android_media_session_client.cc @@ -24,6 +24,7 @@ #include "starboard/log.h" #include "starboard/mutex.h" #include "starboard/once.h" +#include "starboard/player.h" namespace starboard { namespace android { @@ -170,6 +171,10 @@ class AndroidMediaSessionClient : public MediaSessionClient { // Protected by "mutex" static AndroidMediaSessionClient* active_client; + // TODO: Pass the necessary info through web MediaSession so we don't need to + // short-circuit to the player implementation to get info about the playback. + static SbPlayer active_player; + static void OnceInit() { SbMutexCreate(&mutex); } public: @@ -200,6 +205,15 @@ class AndroidMediaSessionClient : public MediaSessionClient { SbMutexRelease(&mutex); } + static void UpdateActiveSessionPlatformPlayer(SbPlayer player) { + SbOnce(&once_flag, OnceInit); + SbMutexAcquire(&mutex); + + active_player = player; + + SbMutexRelease(&mutex); + } + AndroidMediaSessionClient() {} virtual ~AndroidMediaSessionClient() { @@ -224,6 +238,12 @@ class AndroidMediaSessionClient : public MediaSessionClient { } else if (active_client == this) { active_client = NULL; } + + SbPlayerInfo2 player_info; + SbMemorySet(&player_info, 0, sizeof(player_info)); + if (active_player != kSbPlayerInvalid) { + SbPlayerGetInfo2(active_player, &player_info); + } SbMutexRelease(&mutex); jlong playback_state_actions = @@ -281,9 +301,11 @@ class AndroidMediaSessionClient : public MediaSessionClient { env->CallStarboardVoidMethodOrAbort( "updateMediaSession", - "(IJLjava/lang/String;Ljava/lang/String;Ljava/lang/String;" + "(IJJFLjava/lang/String;Ljava/lang/String;Ljava/lang/String;" "[Ldev/cobalt/media/MediaImage;)V", playback_state, playback_state_actions, + player_info.current_media_timestamp / kSbTimeMillisecond, + static_cast(player_info.playback_rate), j_title.Get(), j_artist.Get(), j_album.Get(), j_artwork.Get()); } }; @@ -291,6 +313,7 @@ class AndroidMediaSessionClient : public MediaSessionClient { SbOnceControl AndroidMediaSessionClient::once_flag = SB_ONCE_INITIALIZER; SbMutex AndroidMediaSessionClient::mutex; AndroidMediaSessionClient* AndroidMediaSessionClient::active_client = NULL; +SbPlayer AndroidMediaSessionClient::active_player = kSbPlayerInvalid; void UpdateActiveSessionPlatformPlaybackState(PlaybackState state) { MediaSessionPlaybackState media_session_state = @@ -300,6 +323,10 @@ void UpdateActiveSessionPlatformPlaybackState(PlaybackState state) { media_session_state); } +void UpdateActiveSessionPlatformPlayer(SbPlayer player) { + AndroidMediaSessionClient::UpdateActiveSessionPlatformPlayer(player); +} + } // namespace cobalt } // namespace shared } // namespace android diff --git a/starboard/android/shared/cobalt/android_media_session_client.h b/starboard/android/shared/cobalt/android_media_session_client.h index 5fc3f41652a6..284e165100f6 100644 --- a/starboard/android/shared/cobalt/android_media_session_client.h +++ b/starboard/android/shared/cobalt/android_media_session_client.h @@ -15,6 +15,8 @@ #ifndef STARBOARD_ANDROID_SHARED_COBALT_ANDROID_MEDIA_SESSION_CLIENT_H_ #define STARBOARD_ANDROID_SHARED_COBALT_ANDROID_MEDIA_SESSION_CLIENT_H_ +#include "starboard/player.h" + namespace starboard { namespace android { namespace shared { @@ -25,6 +27,10 @@ enum PlaybackState { kPlaying = 0, kPaused = 1, kNone = 2 }; void UpdateActiveSessionPlatformPlaybackState(PlaybackState state); +// TODO: Pass the necessary info through web MediaSession so we don't need to +// short-circuit to the player implementation to get info about the playback. +void UpdateActiveSessionPlatformPlayer(SbPlayer player); + } // namespace cobalt } // namespace shared } // namespace android diff --git a/starboard/android/shared/player_create.cc b/starboard/android/shared/player_create.cc index e34dd1989065..c305fe878025 100644 --- a/starboard/android/shared/player_create.cc +++ b/starboard/android/shared/player_create.cc @@ -28,6 +28,7 @@ using starboard::shared::starboard::player::PlayerWorker; using starboard::android::shared::cobalt::kPlaying; using starboard::android::shared::cobalt:: UpdateActiveSessionPlatformPlaybackState; +using starboard::android::shared::cobalt::UpdateActiveSessionPlatformPlayer; SbPlayer SbPlayerCreate(SbWindow window, SbMediaVideoCodec video_codec, @@ -109,5 +110,7 @@ SbPlayer SbPlayerCreate(SbWindow window, // matter. SbPlayerSetBounds(player, 0, 0, 0, 0, 0); + UpdateActiveSessionPlatformPlayer(player); + return player; } diff --git a/starboard/android/shared/player_destroy.cc b/starboard/android/shared/player_destroy.cc index b79072988b35..b1b5a9607f51 100644 --- a/starboard/android/shared/player_destroy.cc +++ b/starboard/android/shared/player_destroy.cc @@ -20,11 +20,13 @@ using starboard::android::shared::cobalt::kNone; using starboard::android::shared::cobalt:: UpdateActiveSessionPlatformPlaybackState; +using starboard::android::shared::cobalt::UpdateActiveSessionPlatformPlayer; void SbPlayerDestroy(SbPlayer player) { if (!SbPlayerIsValid(player)) { return; } UpdateActiveSessionPlatformPlaybackState(kNone); + UpdateActiveSessionPlatformPlayer(kSbPlayerInvalid); delete player; }