Commit 8ee18d31 authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Media Controller] Add playback state

Add playback state to MediaSessionInfo. This reflects
the actual playback state of the media. This is used
because the audio focus state may not line up with
whether there is media playing (e.g. apps commonly
hold audio focus when they are paused).

BUG=893296

Change-Id: I025856fe007c08e61e85cb1417b472aecd5a3ccb
Reviewed-on: https://chromium-review.googlesource.com/c/1282026
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602534}
parent badfb87f
......@@ -357,9 +357,9 @@ void AudioFocusManager::DidChangeFocus() {
if (audio_focus_stack_.empty()) {
active_media_controller_.ClearMediaSession();
} else {
active_media_controller_.SetMediaSession(
audio_focus_stack_.back()->session(),
audio_focus_stack_.back()->info()->state);
StackRow* row = audio_focus_stack_.back().get();
active_media_controller_.SetMediaSession(row->session(),
row->info()->playback_state);
}
}
......
......@@ -29,30 +29,27 @@ void MediaController::Resume() {
void MediaController::ToggleSuspendResume() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (state_) {
case mojom::MediaSessionInfo::SessionState::kInactive:
case mojom::MediaSessionInfo::SessionState::kSuspended:
Resume();
break;
case mojom::MediaSessionInfo::SessionState::kDucking:
case mojom::MediaSessionInfo::SessionState::kActive:
switch (playback_state_) {
case mojom::MediaPlaybackState::kPlaying:
Suspend();
break;
case mojom::MediaPlaybackState::kPaused:
Resume();
break;
}
}
void MediaController::SetMediaSession(
mojom::MediaSession* session,
mojom::MediaSessionInfo::SessionState state) {
void MediaController::SetMediaSession(mojom::MediaSession* session,
mojom::MediaPlaybackState state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
session_ = session;
state_ = state;
playback_state_ = state;
}
void MediaController::ClearMediaSession() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
session_ = nullptr;
state_ = mojom::MediaSessionInfo::SessionState::kInactive;
playback_state_ = mojom::MediaPlaybackState::kPaused;
}
void MediaController::BindToInterface(mojom::MediaControllerRequest request) {
......
......@@ -27,8 +27,7 @@ class MediaController : public mojom::MediaController {
void Resume() override;
void ToggleSuspendResume() override;
void SetMediaSession(mojom::MediaSession*,
mojom::MediaSessionInfo::SessionState);
void SetMediaSession(mojom::MediaSession*, mojom::MediaPlaybackState);
void ClearMediaSession();
void BindToInterface(mojom::MediaControllerRequest);
......@@ -38,9 +37,9 @@ class MediaController : public mojom::MediaController {
// Holds mojo bindings for mojom::MediaController.
mojo::BindingSet<mojom::MediaController> bindings_;
// The current state of the |session_|.
mojom::MediaSessionInfo::SessionState state_ =
mojom::MediaSessionInfo::SessionState::kInactive;
// The current playback state of the |session_|.
mojom::MediaPlaybackState playback_state_ =
mojom::MediaPlaybackState::kPaused;
// Raw pointer to the local proxy. This is used for sending control events to
// the underlying MediaSession.
......
......@@ -64,13 +64,13 @@ TEST_F(MediaControllerTest, ActiveController_Suspend) {
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->Suspend();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
}
}
......@@ -80,7 +80,7 @@ TEST_F(MediaControllerTest, ActiveController_Suspend_Multiple) {
{
test::MockMediaSessionMojoObserver observer(media_session_1);
RequestAudioFocus(media_session_1);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
test::MockMediaSession media_session_2;
......@@ -91,26 +91,26 @@ TEST_F(MediaControllerTest, ActiveController_Suspend_Multiple) {
RequestAudioFocus(media_session_2);
observer_1.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
observer_2.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer_1.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
observer_2.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
{
test::MockMediaSessionMojoObserver observer(media_session_2);
controller()->Suspend();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
}
{
test::MockMediaSessionMojoObserver observer(media_session_1);
media_session_2.AbandonAudioFocusFromClient();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
{
test::MockMediaSessionMojoObserver observer(media_session_1);
controller()->Suspend();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
}
}
......@@ -124,7 +124,7 @@ TEST_F(MediaControllerTest, ActiveController_Suspend_Noop_Abandoned) {
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
media_session.AbandonAudioFocusFromClient();
......@@ -134,7 +134,7 @@ TEST_F(MediaControllerTest, ActiveController_Suspend_Noop_Abandoned) {
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
}
......@@ -144,35 +144,35 @@ TEST_F(MediaControllerTest, ActiveController_SuspendResume) {
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->Suspend();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->Resume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
}
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Active) {
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Playing) {
test::MockMediaSession media_session;
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
}
}
......@@ -182,20 +182,19 @@ TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Ducked) {
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
media_session.StartDucking();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kDucking);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
media_session.StartDucking();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kDucking);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
media_session.StopDucking();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
controller()->ToggleSuspendResume();
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
}
}
......@@ -212,29 +211,29 @@ TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Inactive) {
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
}
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Suspended) {
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Paused) {
test::MockMediaSession media_session;
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->Suspend();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
}
}
......
......@@ -25,8 +25,10 @@ void MockMediaSessionMojoObserver::MediaSessionInfoChanged(
mojom::MediaSessionInfoPtr session) {
session_info_ = std::move(session);
if (wanted_state_ == session_info_->state)
if (wanted_state_ == session_info_->state ||
session_info_->playback_state == wanted_playback_state_) {
run_loop_.Quit();
}
}
void MockMediaSessionMojoObserver::WaitForState(
......@@ -38,6 +40,15 @@ void MockMediaSessionMojoObserver::WaitForState(
run_loop_.Run();
}
void MockMediaSessionMojoObserver::WaitForPlaybackState(
mojom::MediaPlaybackState wanted_state) {
if (session_info_ && session_info_->playback_state == wanted_state)
return;
wanted_playback_state_ = wanted_state;
run_loop_.Run();
}
MockMediaSession::MockMediaSession() = default;
MockMediaSession::MockMediaSession(bool force_duck) : force_duck_(force_duck) {}
......@@ -170,6 +181,11 @@ mojom::MediaSessionInfoPtr MockMediaSession::GetMediaSessionInfoSync() const {
info->state = state_;
if (is_ducking_)
info->state = mojom::MediaSessionInfo::SessionState::kDucking;
info->playback_state = mojom::MediaPlaybackState::kPaused;
if (state_ == mojom::MediaSessionInfo::SessionState::kActive)
info->playback_state = mojom::MediaPlaybackState::kPlaying;
return info;
}
......
......@@ -30,10 +30,12 @@ class MockMediaSessionMojoObserver : public mojom::MediaSessionObserver {
void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr session) override;
void WaitForState(mojom::MediaSessionInfo::SessionState wanted_state);
void WaitForPlaybackState(mojom::MediaPlaybackState wanted_state);
private:
mojom::MediaSessionInfoPtr session_info_;
base::Optional<mojom::MediaSessionInfo::SessionState> wanted_state_;
base::Optional<mojom::MediaPlaybackState> wanted_playback_state_;
base::RunLoop run_loop_;
mojo::Binding<mojom::MediaSessionObserver> binding_;
......
......@@ -4,7 +4,13 @@
module media_session.mojom;
// Next MinVersion: 1
// Next MinVersion: 2
[Extensible]
enum MediaPlaybackState {
kPaused,
kPlaying,
};
// Contains state information about a MediaSession.
struct MediaSessionInfo {
......@@ -23,11 +29,16 @@ struct MediaSessionInfo {
kInactive,
};
// The current state of the MediaSession.
// The current audio focus state of the MediaSession.
SessionState state;
// If true then we will always duck this MediaSession instead of suspending.
bool force_duck;
// The playback state tells the client whether the audio is playing. This is
// different from the audio focus state as it is common for a media session
// to hold audio focus sometimes even though it is not actually playing.
[MinVersion=1] MediaPlaybackState playback_state;
};
// Contains debugging information about a MediaSession. This will be displayed
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment