Commit 253f1bbf authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Media Controller] Forward play pause key to service

If the media session feature is enabled then use the
media session service to control playback when the
play/pause media key is pressed.

BUG=894255

Change-Id: I5c34b24536456e4fcacabed6f4a8d2aa9f5d0ec5
Reviewed-on: https://chromium-review.googlesource.com/c/1278147
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600839}
parent bcb2dfd3
......@@ -1409,6 +1409,7 @@ component("ash") {
"//net",
"//services/content/public/cpp",
"//services/data_decoder/public/cpp",
"//services/media_session/public/mojom",
"//services/preferences/public/cpp",
"//services/service_manager/public/cpp",
"//services/ws/gpu_host",
......@@ -2056,6 +2057,7 @@ test("ash_unittests") {
"//mojo/core/embedder",
"//net:net",
"//services/catalog:lib",
"//services/media_session/public/cpp/test:test_support",
"//services/service_manager/public/cpp:service_test_support",
"//services/ws:test_support",
"//services/ws/public/cpp/input_devices:test_support",
......
......@@ -27,6 +27,7 @@ include_rules = [
"+mojo/public",
"+services/catalog/public",
"+services/content/public",
"+services/media_session/public",
"+services/preferences/public",
"+services/service_manager/public",
"+services/viz/public",
......
......@@ -41,6 +41,7 @@
#include "base/run_loop.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
#include "services/media_session/public/cpp/test/test_media_controller.h"
#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_window_delegate.h"
......@@ -842,25 +843,6 @@ TEST_F(AcceleratorControllerTest, GlobalAcceleratorsToggleAppList) {
GetAppListTestHelper()->CheckVisibility(true);
}
TEST_F(AcceleratorControllerTest, MediaGlobalAccelerators) {
TestMediaClient client;
Shell::Get()->media_controller()->SetClient(client.CreateAssociatedPtrInfo());
EXPECT_EQ(0, client.handle_media_next_track_count());
ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, client.handle_media_next_track_count());
EXPECT_EQ(0, client.handle_media_play_pause_count());
ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, client.handle_media_play_pause_count());
EXPECT_EQ(0, client.handle_media_prev_track_count());
ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, client.handle_media_prev_track_count());
}
TEST_F(AcceleratorControllerTest, ImeGlobalAccelerators) {
ASSERT_EQ(0u, Shell::Get()->ime_controller()->available_imes().size());
......@@ -1523,11 +1505,28 @@ class MediaSessionAcceleratorTest : public AcceleratorControllerTest,
}
AcceleratorControllerTest::SetUp();
client_ = std::make_unique<TestMediaClient>();
controller_ = std::make_unique<media_session::test::TestMediaController>();
MediaController* media_controller = Shell::Get()->media_controller();
media_controller->SetClient(client_->CreateAssociatedPtrInfo());
media_controller->SetMediaSessionControllerForTest(
controller_->CreateMediaControllerPtr());
}
TestMediaClient* client() const { return client_.get(); }
media_session::test::TestMediaController* controller() const {
return controller_.get();
}
bool service_enabled() const { return GetParam(); }
private:
std::unique_ptr<TestMediaClient> client_;
std::unique_ptr<media_session::test::TestMediaController> controller_;
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(MediaSessionAcceleratorTest);
......@@ -1571,4 +1570,38 @@ TEST_P(MediaSessionAcceleratorTest, MediaPlaybackAcceleratorsBehavior) {
}
}
TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_NextTrack) {
EXPECT_EQ(0, client()->handle_media_next_track_count());
ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
Shell::Get()->media_controller()->FlushForTesting();
EXPECT_EQ(1, client()->handle_media_next_track_count());
}
TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_PlayPause) {
EXPECT_EQ(0, client()->handle_media_play_pause_count());
EXPECT_EQ(0, controller()->toggle_suspend_resume_count());
ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE));
Shell::Get()->media_controller()->FlushForTesting();
if (service_enabled()) {
EXPECT_EQ(0, client()->handle_media_play_pause_count());
EXPECT_EQ(1, controller()->toggle_suspend_resume_count());
} else {
EXPECT_EQ(1, client()->handle_media_play_pause_count());
EXPECT_EQ(0, controller()->toggle_suspend_resume_count());
}
}
TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_PrevTrack) {
EXPECT_EQ(0, client()->handle_media_prev_track_count());
ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE));
Shell::Get()->media_controller()->FlushForTesting();
EXPECT_EQ(1, client()->handle_media_prev_track_count());
}
} // namespace ash
......@@ -4,9 +4,15 @@
#include "ash/media_controller.h"
#include "ash/public/cpp/ash_features.h"
#include "base/feature_list.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace ash {
MediaController::MediaController() = default;
MediaController::MediaController(service_manager::Connector* connector)
: connector_(connector) {}
MediaController::~MediaController() = default;
......@@ -32,17 +38,29 @@ void MediaController::NotifyCaptureState(
observer.OnMediaCaptureChanged(capture_states);
}
void MediaController::HandleMediaNextTrack() {
void MediaController::HandleMediaPlayPause() {
// If media session media key handling is enabled. Toggle play pause using the
// media session service.
if (base::FeatureList::IsEnabled(features::kMediaSessionAccelerators)) {
if (GetMediaSessionController())
GetMediaSessionController()->ToggleSuspendResume();
return;
}
if (client_)
client_->HandleMediaNextTrack();
client_->HandleMediaPlayPause();
}
void MediaController::HandleMediaPlayPause() {
void MediaController::HandleMediaNextTrack() {
// TODO(beccahughes): Add media session service integration.
if (client_)
client_->HandleMediaPlayPause();
client_->HandleMediaNextTrack();
}
void MediaController::HandleMediaPrevTrack() {
// TODO(beccahughes): Add media session service integration.
if (client_)
client_->HandleMediaPrevTrack();
}
......@@ -57,4 +75,33 @@ void MediaController::SuspendMediaSessions() {
client_->SuspendMediaSessions();
}
void MediaController::SetMediaSessionControllerForTest(
media_session::mojom::MediaControllerPtr controller) {
media_session_controller_ptr_ = std::move(controller);
}
void MediaController::FlushForTesting() {
client_.FlushForTesting();
media_session_controller_ptr_.FlushForTesting();
}
media_session::mojom::MediaController*
MediaController::GetMediaSessionController() {
// |connector_| can be null in tests.
if (connector_ && !media_session_controller_ptr_.is_bound()) {
connector_->BindInterface(media_session::mojom::kServiceName,
&media_session_controller_ptr_);
media_session_controller_ptr_.set_connection_error_handler(
base::BindRepeating(&MediaController::OnMediaSessionControllerError,
base::Unretained(this)));
}
return media_session_controller_ptr_.get();
}
void MediaController::OnMediaSessionControllerError() {
media_session_controller_ptr_.reset();
}
} // namespace ash
......@@ -5,12 +5,18 @@
#ifndef ASH_MEDIA_CONTROLLER_H_
#define ASH_MEDIA_CONTROLLER_H_
#include "ash/ash_export.h"
#include "ash/public/interfaces/media.mojom.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "components/account_id/interfaces/account_id.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/media_session/public/mojom/media_controller.mojom.h"
namespace service_manager {
class Connector;
} // namespace service_manager
namespace ash {
......@@ -29,9 +35,10 @@ class MediaCaptureObserver {
// Provides the MediaController interface to the outside world. This lets a
// consumer of ash provide a MediaClient, which we will dispatch to if one has
// been provided to us.
class MediaController : public mojom::MediaController {
class ASH_EXPORT MediaController : public mojom::MediaController {
public:
MediaController();
// |connector| can be null in tests.
explicit MediaController(service_manager::Connector* connector);
~MediaController() override;
void BindRequest(mojom::MediaControllerRequest request);
......@@ -45,15 +52,41 @@ class MediaController : public mojom::MediaController {
const base::flat_map<AccountId, mojom::MediaCaptureState>& capture_states)
override;
// If media session accelerators are enabled then this method will use the
// media session service to control playback. Otherwise it will forward to
// |client_|.
void HandleMediaPlayPause();
// Methods that forward to |client_|.
void HandleMediaNextTrack();
void HandleMediaPlayPause();
void HandleMediaPrevTrack();
void RequestCaptureState();
void SuspendMediaSessions();
private:
friend class MediaSessionAcceleratorTest;
friend class MultiProfileMediaTrayItemTest;
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_NextTrack);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_PlayPause);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_PrevTrack);
void SetMediaSessionControllerForTest(
media_session::mojom::MediaControllerPtr controller);
void FlushForTesting();
// Returns a pointer to the active media session controller.
media_session::mojom::MediaController* GetMediaSessionController();
void OnMediaSessionControllerError();
// Mojo pointer to the active media session controller.
media_session::mojom::MediaControllerPtr media_session_controller_ptr_;
service_manager::Connector* const connector_;
// Bindings for users of the mojo interface.
mojo::BindingSet<mojom::MediaController> bindings_;
......
......@@ -670,7 +670,7 @@ Shell::Shell(std::unique_ptr<ShellDelegate> shell_delegate,
locale_notification_controller_(
std::make_unique<LocaleNotificationController>()),
login_screen_controller_(std::make_unique<LoginScreenController>()),
media_controller_(std::make_unique<MediaController>()),
media_controller_(std::make_unique<MediaController>(connector)),
new_window_controller_(std::make_unique<NewWindowController>()),
session_controller_(std::make_unique<SessionController>(connector)),
note_taking_controller_(std::make_unique<NoteTakingController>()),
......
......@@ -8,6 +8,8 @@ component("test_support") {
sources = [
"audio_focus_test_util.cc",
"audio_focus_test_util.h",
"test_media_controller.cc",
"test_media_controller.h",
]
deps = [
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/media_session/public/cpp/test/test_media_controller.h"
namespace media_session {
namespace test {
TestMediaController::TestMediaController() = default;
TestMediaController::~TestMediaController() = default;
mojom::MediaControllerPtr TestMediaController::CreateMediaControllerPtr() {
mojom::MediaControllerPtr ptr;
binding_.Bind(mojo::MakeRequest(&ptr));
return ptr;
}
void TestMediaController::ToggleSuspendResume() {
++toggle_suspend_resume_count_;
}
} // namespace test
} // namespace media_session
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_MEDIA_SESSION_PUBLIC_CPP_TEST_TEST_MEDIA_CONTROLLER_H_
#define SERVICES_MEDIA_SESSION_PUBLIC_CPP_TEST_TEST_MEDIA_CONTROLLER_H_
#include "base/component_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/media_session/public/mojom/media_controller.mojom.h"
namespace media_session {
namespace test {
// Implements the MediaController mojo interface for tests.
class COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP) TestMediaController
: public mojom::MediaController {
public:
TestMediaController();
~TestMediaController() override;
mojom::MediaControllerPtr CreateMediaControllerPtr();
// mojom::MediaController:
void Suspend() override {}
void Resume() override {}
void ToggleSuspendResume() override;
int toggle_suspend_resume_count() const {
return toggle_suspend_resume_count_;
}
private:
int toggle_suspend_resume_count_ = 0;
mojo::Binding<mojom::MediaController> binding_{this};
DISALLOW_COPY_AND_ASSIGN(TestMediaController);
};
} // namespace test
} // namespace media_session
#endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_TEST_TEST_MEDIA_CONTROLLER_H_
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