Commit 834490b7 authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Media Controller] Add resume and toggle suspend resume

Adds resume to the Media Controller mojo interface. Also
adds a ToggleSuspendResume method to make it easier to
toggle play/pause.

BUG=893296

Change-Id: Ib9615d3c93909ca24e0eec0b4d6e690c186703dc
Reviewed-on: https://chromium-review.googlesource.com/c/1272081
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600802}
parent c99130ad
......@@ -83,6 +83,7 @@ class AudioFocusManager::StackRow : public mojom::AudioFocusRequestClient {
void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr info) override {
session_info_ = std::move(info);
owner_->DidChangeFocus();
}
void GetRequestId(GetRequestIdCallback callback) override {
......@@ -346,9 +347,13 @@ void AudioFocusManager::EnforceAudioFocusAbandon(mojom::AudioFocusType type) {
}
void AudioFocusManager::DidChangeFocus() {
active_media_controller_.SetMediaSession(
audio_focus_stack_.empty() ? nullptr
: audio_focus_stack_.back()->session());
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);
}
}
AudioFocusManager::AudioFocusManager() {
......
......@@ -19,9 +19,40 @@ void MediaController::Suspend() {
session_->Suspend(mojom::MediaSession::SuspendType::kUI);
}
void MediaController::SetMediaSession(mojom::MediaSession* session) {
void MediaController::Resume() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (session_)
session_->Resume(mojom::MediaSession::SuspendType::kUI);
}
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:
Suspend();
break;
}
}
void MediaController::SetMediaSession(
mojom::MediaSession* session,
mojom::MediaSessionInfo::SessionState state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
session_ = session;
state_ = state;
}
void MediaController::ClearMediaSession() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
session_ = nullptr;
state_ = mojom::MediaSessionInfo::SessionState::kInactive;
}
void MediaController::BindToInterface(mojom::MediaControllerRequest request) {
......
......@@ -24,8 +24,12 @@ class MediaController : public mojom::MediaController {
// mojom::MediaController overrides.
void Suspend() override;
void Resume() override;
void ToggleSuspendResume() override;
void SetMediaSession(mojom::MediaSession*);
void SetMediaSession(mojom::MediaSession*,
mojom::MediaSessionInfo::SessionState);
void ClearMediaSession();
void BindToInterface(mojom::MediaControllerRequest);
void FlushForTesting();
......@@ -34,6 +38,10 @@ 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;
// Raw pointer to the local proxy. This is used for sending control events to
// the underlying MediaSession.
mojom::MediaSession* session_ = nullptr;
......
......@@ -138,4 +138,104 @@ TEST_F(MediaControllerTest, ActiveController_Suspend_Noop_Abandoned) {
}
}
TEST_F(MediaControllerTest, ActiveController_SuspendResume) {
test::MockMediaSession media_session;
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->Suspend();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->Resume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
}
}
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Active) {
test::MockMediaSession media_session;
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
}
}
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Ducked) {
test::MockMediaSession media_session;
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
media_session.StartDucking();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kDucking);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kDucking);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
media_session.StopDucking();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
}
}
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Inactive) {
test::MockMediaSession media_session;
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
media_session.Stop();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kInactive);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
}
}
TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Suspended) {
test::MockMediaSession media_session;
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->Suspend();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
}
{
test::MockMediaSessionMojoObserver observer(media_session);
controller()->ToggleSuspendResume();
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
}
}
} // namespace media_session
......@@ -49,7 +49,6 @@ void MockMediaSession::Suspend(SuspendType suspend_type) {
}
void MockMediaSession::Resume(SuspendType suspend_type) {
DCHECK_EQ(SuspendType::kSystem, suspend_type);
SetState(mojom::MediaSessionInfo::SessionState::kActive);
}
......@@ -83,6 +82,10 @@ void MockMediaSession::GetDebugInfo(GetDebugInfoCallback callback) {
std::move(callback).Run(std::move(debug_info));
}
void MockMediaSession::Stop() {
SetState(mojom::MediaSessionInfo::SessionState::kInactive);
}
void MockMediaSession::AbandonAudioFocusFromClient() {
DCHECK(afr_client_.is_bound());
afr_client_->AbandonAudioFocus();
......
......@@ -57,6 +57,8 @@ class MockMediaSession : public mojom::MediaSession {
void AddObserver(mojom::MediaSessionObserverPtr) override;
void GetDebugInfo(GetDebugInfoCallback) override;
void Stop();
void AbandonAudioFocusFromClient();
base::UnguessableToken GetRequestIdFromClient();
......
......@@ -10,4 +10,11 @@ module media_session.mojom;
interface MediaController {
// Suspend the media session.
Suspend();
// Resume the media session.
Resume();
// This will either suspend or resume the media session based on the
// playback state.
ToggleSuspendResume();
};
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