Commit e331af1b authored by Noah Rose Ledesma's avatar Noah Rose Ledesma Committed by Commit Bot

GMC: Add OnSetAudioSinkId to MediaSessionPlayerObserver

Changing audio sinks on pepper players is not supported. The mock media
session player observer needs to have OnSetSinkId implemented.

Bug: 1096246
Change-Id: Ie08b36cff98f4beb2a4148e0bd05e27e993308f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2295748
Commit-Queue: Noah Rose Ledesma <noahrose@google.com>
Reviewed-by: default avatarBecca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#794772}
parent 67a9b3fb
......@@ -4,10 +4,14 @@
#include "content/browser/media/session/media_session_controller.h"
#include "content/browser/media/media_devices_util.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/browser/media/session/media_session_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "media/base/media_content_type.h"
......@@ -87,6 +91,10 @@ void MediaSessionController::OnExitPictureInPicture(int player_id) {
id_.render_frame_host->GetRoutingID(), id_.delegate_id));
}
void MediaSessionController::OnSetAudioSinkId(
int player_id,
const std::string& raw_device_id) {}
RenderFrameHost* MediaSessionController::render_frame_host() const {
return id_.render_frame_host;
}
......
......@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLER_H_
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/media/session/media_session_player_observer.h"
......@@ -50,6 +51,8 @@ class CONTENT_EXPORT MediaSessionController
void OnSetVolumeMultiplier(int player_id, double volume_multiplier) override;
void OnEnterPictureInPicture(int player_id) override;
void OnExitPictureInPicture(int player_id) override;
void OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) override;
RenderFrameHost* render_frame_host() const override;
base::Optional<media_session::MediaPosition> GetPosition(
int player_id) const override;
......
......@@ -26,6 +26,7 @@
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "media/audio/audio_device_description.h"
#include "media/base/media_content_type.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
......@@ -1071,7 +1072,13 @@ void MediaSessionImpl::ExitPictureInPicture() {
normal_players_.begin()->first.player_id);
}
void MediaSessionImpl::SetAudioSinkId(const base::Optional<std::string>& id) {}
void MediaSessionImpl::SetAudioSinkId(const base::Optional<std::string>& id) {
for (const auto& it : normal_players_) {
it.first.observer->OnSetAudioSinkId(
it.first.player_id,
id.value_or(media::AudioDeviceDescription::kDefaultDeviceId));
}
}
void MediaSessionImpl::GetMediaImageBitmap(
const media_session::MediaImage& image,
......
......@@ -40,10 +40,10 @@ using media_session::mojom::AudioFocusType;
using media_session::mojom::MediaPlaybackState;
using media_session::mojom::MediaSessionInfo;
using ::testing::_;
using ::testing::Eq;
using ::testing::Expectation;
using ::testing::NiceMock;
using ::testing::_;
namespace {
......@@ -56,6 +56,8 @@ const base::string16 kExpectedSourceTitlePrefix =
constexpr gfx::Size kDefaultFaviconSize = gfx::Size(16, 16);
const std::string kExampleSinkId = "example_device_id";
class MockAudioFocusDelegate : public content::AudioFocusDelegate {
public:
MockAudioFocusDelegate(content::MediaSessionImpl* media_session,
......@@ -213,6 +215,10 @@ class MediaSessionImplBrowserTest : public ContentBrowserTest {
media_session_->Seek(base::TimeDelta::FromSeconds(-1));
}
void UISetAudioSink(const std::string& sink_id) {
media_session_->SetAudioSinkId(sink_id);
}
void SystemStartDucking() { media_session_->StartDucking(); }
void SystemStopDucking() { media_session_->StopDucking(); }
......@@ -2592,6 +2598,17 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
}
}
IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
SinkIdChangeNotifiesObservers) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
UISetAudioSink(kExampleSinkId);
EXPECT_EQ(player_observer->received_set_audio_sink_id_calls(), 1);
EXPECT_EQ(player_observer->GetAudioSinkId(0), kExampleSinkId);
}
class MediaSessionFaviconBrowserTest : public ContentBrowserTest {
protected:
MediaSessionFaviconBrowserTest() = default;
......
......@@ -53,6 +53,8 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
void(int player_id, double volume_multiplier));
MOCK_METHOD1(OnEnterPictureInPicture, void(int player_id));
MOCK_METHOD1(OnExitPictureInPicture, void(int player_id));
MOCK_METHOD2(OnSetAudioSinkId,
void(int player_id, const std::string& raw_device_id));
base::Optional<media_session::MediaPosition> GetPosition(
int player_id) const override {
......
......@@ -41,6 +41,8 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
}
void OnEnterPictureInPicture(int player_id) override {}
void OnExitPictureInPicture(int player_id) override {}
void OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) override {}
base::Optional<media_session::MediaPosition> GetPosition(
int player_id) const override {
......
......@@ -44,6 +44,11 @@ class MediaSessionPlayerObserver {
// The given |player_id| has been requested to exit picture-in-picture.
virtual void OnExitPictureInPicture(int player_id) = 0;
// The given |player_id| has been requested to route audio output to the
// specified audio device.
virtual void OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) = 0;
// Returns the position for |player_id|.
virtual base::Optional<media_session::MediaPosition> GetPosition(
int player_id) const = 0;
......
......@@ -54,6 +54,8 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
}
void OnEnterPictureInPicture(int player_id) override {}
void OnExitPictureInPicture(int player_id) override {}
void OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) override {}
base::Optional<media_session::MediaPosition> GetPosition(
int player_id) const override {
......
......@@ -72,6 +72,16 @@ void MockMediaSessionPlayerObserver::OnExitPictureInPicture(int player_id) {
players_[player_id].is_in_picture_in_picture_ = false;
}
void MockMediaSessionPlayerObserver::OnSetAudioSinkId(
int player_id,
const std::string& raw_device_id) {
EXPECT_GE(player_id, 0);
EXPECT_EQ(players_.size(), 1u);
++received_set_audio_sink_id_calls_;
players_[player_id].audio_sink_id_ = raw_device_id;
}
base::Optional<media_session::MediaPosition>
MockMediaSessionPlayerObserver::GetPosition(int player_id) const {
EXPECT_GE(player_id, 0);
......@@ -105,6 +115,12 @@ double MockMediaSessionPlayerObserver::GetVolumeMultiplier(size_t player_id) {
return players_[player_id].volume_multiplier_;
}
const std::string& MockMediaSessionPlayerObserver::GetAudioSinkId(
size_t player_id) {
EXPECT_GT(players_.size(), player_id);
return players_[player_id].audio_sink_id_;
}
void MockMediaSessionPlayerObserver::SetPlaying(size_t player_id,
bool playing) {
EXPECT_GT(players_.size(), player_id);
......@@ -144,15 +160,23 @@ int MockMediaSessionPlayerObserver::received_exit_picture_in_picture_calls()
return received_exit_picture_in_picture_calls_;
}
int MockMediaSessionPlayerObserver::received_set_audio_sink_id_calls() const {
return received_set_audio_sink_id_calls_;
}
bool MockMediaSessionPlayerObserver::HasVideo(int player_id) const {
EXPECT_GE(player_id, 0);
EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
return false;
}
MockMediaSessionPlayerObserver::MockPlayer::MockPlayer(bool is_playing,
double volume_multiplier)
: is_playing_(is_playing), volume_multiplier_(volume_multiplier) {}
MockMediaSessionPlayerObserver::MockPlayer::MockPlayer(
bool is_playing,
double volume_multiplier,
const std::string& audio_sink_id)
: is_playing_(is_playing),
volume_multiplier_(volume_multiplier),
audio_sink_id_(audio_sink_id) {}
MockMediaSessionPlayerObserver::MockPlayer::~MockPlayer() = default;
......
......@@ -30,6 +30,8 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
void OnSetVolumeMultiplier(int player_id, double volume_multiplier) override;
void OnEnterPictureInPicture(int player_id) override;
void OnExitPictureInPicture(int player_id) override;
void OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) override;
base::Optional<media_session::MediaPosition> GetPosition(
int player_id) const override;
bool IsPictureInPictureAvailable(int player_id) const override;
......@@ -46,6 +48,9 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
// Returns the volume multiplier of |player_id|.
double GetVolumeMultiplier(size_t player_id);
// Returns the sink id being used for the audio output of |player_id|
const std::string& GetAudioSinkId(size_t player_id);
// Simulate a play state change for |player_id|.
void SetPlaying(size_t player_id, bool playing);
......@@ -58,12 +63,15 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
int received_seek_backward_calls() const;
int received_enter_picture_in_picture_calls() const;
int received_exit_picture_in_picture_calls() const;
int received_set_audio_sink_id_calls() const;
private:
// Internal representation of the players to keep track of their statuses.
struct MockPlayer {
public:
MockPlayer(bool is_playing = true, double volume_multiplier = 1.0f);
explicit MockPlayer(bool is_playing = true,
double volume_multiplier = 1.0f,
const std::string& audio_sink_id = "");
~MockPlayer();
MockPlayer(const MockPlayer&);
......@@ -71,6 +79,7 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
double volume_multiplier_;
base::Optional<media_session::MediaPosition> position_;
bool is_in_picture_in_picture_;
std::string audio_sink_id_;
};
// Basic representation of the players. The position in the vector is the
......@@ -85,6 +94,7 @@ class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
int received_seek_backward_calls_ = 0;
int received_enter_picture_in_picture_calls_ = 0;
int received_exit_picture_in_picture_calls_ = 0;
int received_set_audio_sink_id_calls_ = 0;
};
} // namespace content
......
......@@ -72,6 +72,12 @@ void PepperPlayerDelegate::OnExitPictureInPicture(int player_id) {
// Pepper player cannot exit picture-in-picture. Do nothing.
}
void PepperPlayerDelegate::OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) {
// Pepper player cannot change audio sinks. Do nothing.
NOTREACHED();
}
base::Optional<media_session::MediaPosition> PepperPlayerDelegate::GetPosition(
int player_id) const {
// Pepper does not support position data.
......
......@@ -32,6 +32,8 @@ class PepperPlayerDelegate : public MediaSessionPlayerObserver {
double volume_multiplier) override;
void OnEnterPictureInPicture(int player_id) override;
void OnExitPictureInPicture(int player_id) override;
void OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) override;
base::Optional<media_session::MediaPosition> GetPosition(
int player_id) const override;
bool IsPictureInPictureAvailable(int player_id) const override;
......
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