Commit a62ef37c authored by Marina Ciocea's avatar Marina Ciocea Committed by Commit Bot

Add UserInputMonitor in audio service.

audio::UserInputMonitor overrides audio::UserInputMonitor::GetKeyPressCount() to read key press
count (computed in browser process) from shared memory. Read only handle to key press count shmem
is passed over IPC on audio service input stream creation.

Design doc: https://docs.google.com/document/d/1GHL4uMlIFox2eAqsjUQVA8eJ7HYU3g2AoyAqyx3pxMA/edit?usp=sharing

Notes:
- Browser side implementation of key press count share memory, and  wrapping of memory handle
  into a Mojo handle will be added in dependent CL https://crrev.com/c/1025754.
- UserInputMonitor is enabled in MojoAudioInputStreamObserver constructor, when a stream is created,
  and disabled on connection error, called when the observed stream is destroyed.
- audio:: and media:: UserInputMonitor implementations inherit from media::UserInputMonitorBase in
  order to keep media::AudioInputController unchanged for now. Inheritance will be removed when
  switching to audio service input streams.

Streams design diagram: http://drawings/1_ZIKj6lihGKRjq4Mflduitmkn_REqpHFeqVNelBGHHk

Bug: 828864
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I0219494d73df2fd275d2b7ccb5bf01f81a1ff11c
Reviewed-on: https://chromium-review.googlesource.com/1011605
Commit-Queue: Marina Ciocea <marinaciocea@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarOlga Sharonova <olka@chromium.org>
Reviewed-by: default avatarMax Morin <maxmorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553967}
parent 6c2e15ce
...@@ -105,7 +105,7 @@ class MockEventHandler : public media::AudioInputDelegate::EventHandler { ...@@ -105,7 +105,7 @@ class MockEventHandler : public media::AudioInputDelegate::EventHandler {
MOCK_METHOD1(OnStreamError, void(int)); MOCK_METHOD1(OnStreamError, void(int));
}; };
class MockUserInputMonitor : public media::UserInputMonitor { class MockUserInputMonitor : public media::UserInputMonitorBase {
public: public:
MockUserInputMonitor() {} MockUserInputMonitor() {}
......
...@@ -83,7 +83,7 @@ class MockSyncWriter : public AudioInputController::SyncWriter { ...@@ -83,7 +83,7 @@ class MockSyncWriter : public AudioInputController::SyncWriter {
MOCK_METHOD0(Close, void()); MOCK_METHOD0(Close, void());
}; };
class MockUserInputMonitor : public UserInputMonitor { class MockUserInputMonitor : public UserInputMonitorBase {
public: public:
MockUserInputMonitor() = default; MockUserInputMonitor() = default;
......
...@@ -4,38 +4,66 @@ ...@@ -4,38 +4,66 @@
#include "media/base/user_input_monitor.h" #include "media/base/user_input_monitor.h"
#include "base/atomicops.h"
#include "base/logging.h" #include "base/logging.h"
namespace media { namespace media {
uint32_t ReadKeyPressMonitorCount(
const base::ReadOnlySharedMemoryMapping& shmem_mapping) {
if (!shmem_mapping.IsValid())
return 0;
// No ordering constraints between Load/Store operations, a temporary
// inconsistent value is fine.
return base::subtle::NoBarrier_Load(
reinterpret_cast<const base::subtle::Atomic32*>(shmem_mapping.memory()));
}
void WriteKeyPressMonitorCount(
const base::WritableSharedMemoryMapping& shmem_mapping,
uint32_t count) {
if (!shmem_mapping.IsValid())
return;
// No ordering constraints between Load/Store operations, a temporary
// inconsistent value is fine.
base::subtle::NoBarrier_Store(
reinterpret_cast<base::subtle::Atomic32*>(shmem_mapping.memory()), count);
}
#ifdef DISABLE_USER_INPUT_MONITOR #ifdef DISABLE_USER_INPUT_MONITOR
// static
std::unique_ptr<UserInputMonitor> UserInputMonitor::Create( std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
return nullptr; return nullptr;
} }
#endif // DISABLE_USER_INPUT_MONITOR #endif // DISABLE_USER_INPUT_MONITOR
UserInputMonitor::UserInputMonitor() = default;
UserInputMonitor::~UserInputMonitor() = default;
UserInputMonitor::UserInputMonitor() : key_press_counter_references_(0) {} UserInputMonitorBase::UserInputMonitorBase() = default;
UserInputMonitor::~UserInputMonitor() { UserInputMonitorBase::~UserInputMonitorBase() {
DCHECK_EQ(0u, key_press_counter_references_); DCHECK_EQ(0u, references_);
} }
void UserInputMonitor::EnableKeyPressMonitoring() { void UserInputMonitorBase::EnableKeyPressMonitoring() {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
++key_press_counter_references_; ++references_;
if (key_press_counter_references_ == 1) { if (references_ == 1) {
StartKeyboardMonitoring(); StartKeyboardMonitoring();
DVLOG(2) << "Started keyboard monitoring."; DVLOG(2) << "Started keyboard monitoring.";
} }
} }
void UserInputMonitor::DisableKeyPressMonitoring() { void UserInputMonitorBase::DisableKeyPressMonitoring() {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
DCHECK_NE(key_press_counter_references_, 0u); DCHECK_NE(references_, 0u);
--key_press_counter_references_; --references_;
if (key_press_counter_references_ == 0) { if (references_ == 0) {
StopKeyboardMonitoring(); StopKeyboardMonitoring();
DVLOG(2) << "Stopped keyboard monitoring."; DVLOG(2) << "Stopped keyboard monitoring.";
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "media/base/media_export.h" #include "media/base/media_export.h"
...@@ -20,24 +21,29 @@ class SingleThreadTaskRunner; ...@@ -20,24 +21,29 @@ class SingleThreadTaskRunner;
namespace media { namespace media {
// Monitors and notifies about keyboard events. // Utility functions for correctly and atomically reading from/writing to a
// Thread safe. // shared memory mapping containing key press count.
uint32_t MEDIA_EXPORT
ReadKeyPressMonitorCount(const base::ReadOnlySharedMemoryMapping& shmem);
void MEDIA_EXPORT
WriteKeyPressMonitorCount(const base::WritableSharedMemoryMapping& shmem,
uint32_t count);
// Base class for audio:: and media:: UserInputMonitor implementations.
class MEDIA_EXPORT UserInputMonitor { class MEDIA_EXPORT UserInputMonitor {
public: public:
UserInputMonitor(); UserInputMonitor();
virtual ~UserInputMonitor(); virtual ~UserInputMonitor();
// Creates a platform-specific instance of UserInputMonitor. // Creates a platform-specific instance of UserInputMonitorBase.
// |io_task_runner| is the task runner for an IO thread. // |io_task_runner| is the task runner for an IO thread.
// |ui_task_runner| is the task runner for a UI thread. // |ui_task_runner| is the task runner for a UI thread.
static std::unique_ptr<UserInputMonitor> Create( static std::unique_ptr<UserInputMonitor> Create(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner); scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
// A caller must call EnableKeyPressMonitoring and virtual void EnableKeyPressMonitoring() = 0;
// DisableKeyPressMonitoring in pair. virtual void DisableKeyPressMonitoring() = 0;
void EnableKeyPressMonitoring();
void DisableKeyPressMonitoring();
// Returns the number of keypresses. The starting point from when it is // Returns the number of keypresses. The starting point from when it is
// counted is not guaranteed, but consistent within the pair of calls of // counted is not guaranteed, but consistent within the pair of calls of
...@@ -47,14 +53,34 @@ class MEDIA_EXPORT UserInputMonitor { ...@@ -47,14 +53,34 @@ class MEDIA_EXPORT UserInputMonitor {
// any assumption on the initial value. // any assumption on the initial value.
virtual uint32_t GetKeyPressCount() const = 0; virtual uint32_t GetKeyPressCount() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(UserInputMonitor);
};
// Monitors and notifies about keyboard events.
// Thread safe.
class MEDIA_EXPORT UserInputMonitorBase : public UserInputMonitor {
public:
UserInputMonitorBase();
~UserInputMonitorBase() override;
// A caller must call EnableKeyPressMonitoring and
// DisableKeyPressMonitoring in pair.
void EnableKeyPressMonitoring() override;
void DisableKeyPressMonitoring() override;
private: private:
virtual void StartKeyboardMonitoring() = 0; virtual void StartKeyboardMonitoring() = 0;
virtual void StopKeyboardMonitoring() = 0; virtual void StopKeyboardMonitoring() = 0;
// Aquired in EnableKeyPressMonitoring()/DisableKeyPressMonitoring(). Together
// with |references_| updated under lock, it is used to ensure operation
// ordering for start/stop keyboard monitoring, i.e. start is always followed
// by stop and start is only called when keyboard monitoring is stopped.
base::Lock lock_; base::Lock lock_;
size_t key_press_counter_references_; size_t references_ = 0;
DISALLOW_COPY_AND_ASSIGN(UserInputMonitor); DISALLOW_COPY_AND_ASSIGN(UserInputMonitorBase);
}; };
} // namespace media } // namespace media
......
...@@ -68,7 +68,7 @@ class UserInputMonitorLinuxCore ...@@ -68,7 +68,7 @@ class UserInputMonitorLinuxCore
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinuxCore); DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinuxCore);
}; };
class UserInputMonitorLinux : public UserInputMonitor { class UserInputMonitorLinux : public UserInputMonitorBase {
public: public:
explicit UserInputMonitorLinux( explicit UserInputMonitorLinux(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner); const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
...@@ -219,6 +219,7 @@ void UserInputMonitorLinuxCore::StopMonitor() { ...@@ -219,6 +219,7 @@ void UserInputMonitorLinuxCore::StopMonitor() {
XCloseDisplay(x_control_display_); XCloseDisplay(x_control_display_);
x_control_display_ = NULL; x_control_display_ = NULL;
} }
// Stop observing message loop destruction if no event is being monitored. // Stop observing message loop destruction if no event is being monitored.
base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this); base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
} }
...@@ -275,21 +276,21 @@ uint32_t UserInputMonitorLinux::GetKeyPressCount() const { ...@@ -275,21 +276,21 @@ uint32_t UserInputMonitorLinux::GetKeyPressCount() const {
void UserInputMonitorLinux::StartKeyboardMonitoring() { void UserInputMonitorLinux::StartKeyboardMonitoring() {
io_task_runner_->PostTask( io_task_runner_->PostTask(
FROM_HERE, FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StartMonitor,
base::Bind(&UserInputMonitorLinuxCore::StartMonitor, core_->AsWeakPtr())); core_->AsWeakPtr()));
} }
void UserInputMonitorLinux::StopKeyboardMonitoring() { void UserInputMonitorLinux::StopKeyboardMonitoring() {
io_task_runner_->PostTask( io_task_runner_->PostTask(
FROM_HERE, FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StopMonitor,
base::Bind(&UserInputMonitorLinuxCore::StopMonitor, core_->AsWeakPtr())); core_->AsWeakPtr()));
} }
} // namespace } // namespace
std::unique_ptr<UserInputMonitor> UserInputMonitor::Create( std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
return std::make_unique<UserInputMonitorLinux>(io_task_runner); return std::make_unique<UserInputMonitorLinux>(io_task_runner);
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
namespace media { namespace media {
namespace { namespace {
class UserInputMonitorMac : public UserInputMonitor { class UserInputMonitorMac : public UserInputMonitorBase {
public: public:
UserInputMonitorMac(); UserInputMonitorMac();
~UserInputMonitorMac() override; ~UserInputMonitorMac() override;
...@@ -45,8 +45,8 @@ void UserInputMonitorMac::StopKeyboardMonitoring() {} ...@@ -45,8 +45,8 @@ void UserInputMonitorMac::StopKeyboardMonitoring() {}
} // namespace } // namespace
std::unique_ptr<UserInputMonitor> UserInputMonitor::Create( std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
return std::make_unique<UserInputMonitorMac>(); return std::make_unique<UserInputMonitorMac>();
} }
......
...@@ -5,15 +5,11 @@ ...@@ -5,15 +5,11 @@
#include "media/base/user_input_monitor.h" #include "media/base/user_input_monitor.h"
#include <memory> #include <memory>
#include <utility>
#include "base/logging.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "build/build_config.h"
#include "media/base/keyboard_event_counter.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkPoint.h"
#if defined(OS_LINUX) #if defined(OS_LINUX)
#include "base/files/file_descriptor_watcher_posix.h" #include "base/files/file_descriptor_watcher_posix.h"
...@@ -29,7 +25,6 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) { ...@@ -29,7 +25,6 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) {
base::MessageLoopForUI message_loop; base::MessageLoopForUI message_loop;
#endif // defined(OS_LINUX) #endif // defined(OS_LINUX)
base::RunLoop run_loop;
std::unique_ptr<UserInputMonitor> monitor = UserInputMonitor::Create( std::unique_ptr<UserInputMonitor> monitor = UserInputMonitor::Create(
message_loop.task_runner(), message_loop.task_runner()); message_loop.task_runner(), message_loop.task_runner());
...@@ -40,7 +35,20 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) { ...@@ -40,7 +35,20 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) {
monitor->DisableKeyPressMonitoring(); monitor->DisableKeyPressMonitoring();
monitor.reset(); monitor.reset();
run_loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
}
TEST(UserInputMonitorTest, KeyPressMonitorReadWriteCount) {
std::unique_ptr<base::MappedReadOnlyRegion> shmem =
std::make_unique<base::MappedReadOnlyRegion>(
base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t)));
ASSERT_TRUE(shmem->region.IsValid());
ASSERT_TRUE(shmem->mapping.IsValid());
constexpr uint32_t count = 10;
WriteKeyPressMonitorCount(shmem->mapping, count);
base::ReadOnlySharedMemoryMapping readonly_mapping = shmem->region.Map();
EXPECT_EQ(count, ReadKeyPressMonitorCount(readonly_mapping));
} }
} // namespace media } // namespace media
...@@ -79,7 +79,7 @@ class UserInputMonitorWinCore ...@@ -79,7 +79,7 @@ class UserInputMonitorWinCore
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWinCore); DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWinCore);
}; };
class UserInputMonitorWin : public UserInputMonitor { class UserInputMonitorWin : public UserInputMonitorBase {
public: public:
explicit UserInputMonitorWin( explicit UserInputMonitorWin(
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner); const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner);
...@@ -124,8 +124,8 @@ void UserInputMonitorWinCore::StartMonitor() { ...@@ -124,8 +124,8 @@ void UserInputMonitorWinCore::StartMonitor() {
std::unique_ptr<base::win::MessageWindow> window = std::unique_ptr<base::win::MessageWindow> window =
std::make_unique<base::win::MessageWindow>(); std::make_unique<base::win::MessageWindow>();
if (!window->Create(base::Bind(&UserInputMonitorWinCore::HandleMessage, if (!window->Create(base::BindRepeating(
base::Unretained(this)))) { &UserInputMonitorWinCore::HandleMessage, base::Unretained(this)))) {
PLOG(ERROR) << "Failed to create the raw input window"; PLOG(ERROR) << "Failed to create the raw input window";
return; return;
} }
...@@ -238,21 +238,21 @@ uint32_t UserInputMonitorWin::GetKeyPressCount() const { ...@@ -238,21 +238,21 @@ uint32_t UserInputMonitorWin::GetKeyPressCount() const {
void UserInputMonitorWin::StartKeyboardMonitoring() { void UserInputMonitorWin::StartKeyboardMonitoring() {
ui_task_runner_->PostTask( ui_task_runner_->PostTask(
FROM_HERE, FROM_HERE, base::BindOnce(&UserInputMonitorWinCore::StartMonitor,
base::Bind(&UserInputMonitorWinCore::StartMonitor, core_->AsWeakPtr())); core_->AsWeakPtr()));
} }
void UserInputMonitorWin::StopKeyboardMonitoring() { void UserInputMonitorWin::StopKeyboardMonitoring() {
ui_task_runner_->PostTask( ui_task_runner_->PostTask(
FROM_HERE, FROM_HERE, base::BindOnce(&UserInputMonitorWinCore::StopMonitor,
base::Bind(&UserInputMonitorWinCore::StopMonitor, core_->AsWeakPtr())); core_->AsWeakPtr()));
} }
} // namespace } // namespace
std::unique_ptr<UserInputMonitor> UserInputMonitor::Create( std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
return std::make_unique<UserInputMonitorWin>(ui_task_runner); return std::make_unique<UserInputMonitorWin>(ui_task_runner);
} }
......
...@@ -6,20 +6,34 @@ ...@@ -6,20 +6,34 @@
#include <utility> #include <utility>
#include "media/base/user_input_monitor.h"
namespace media { namespace media {
MojoAudioInputStreamObserver::MojoAudioInputStreamObserver( MojoAudioInputStreamObserver::MojoAudioInputStreamObserver(
mojom::AudioInputStreamObserverRequest request, mojom::AudioInputStreamObserverRequest request,
base::OnceClosure recording_started_callback, base::OnceClosure recording_started_callback,
base::OnceClosure connection_error_callback) base::OnceClosure connection_error_callback,
media::UserInputMonitor* user_input_monitor)
: binding_(this, std::move(request)), : binding_(this, std::move(request)),
recording_started_callback_(std::move(recording_started_callback)) { recording_started_callback_(std::move(recording_started_callback)),
connection_error_callback_(std::move(connection_error_callback)),
user_input_monitor_(user_input_monitor) {
DCHECK(recording_started_callback_); DCHECK(recording_started_callback_);
binding_.set_connection_error_handler(std::move(connection_error_callback)); if (user_input_monitor_)
user_input_monitor_->EnableKeyPressMonitoring();
// Unretained is safe because |this| owns |binding_|.
binding_.set_connection_error_handler(
base::BindOnce(&MojoAudioInputStreamObserver::OnConnectionError,
base::Unretained(this)));
} }
MojoAudioInputStreamObserver::~MojoAudioInputStreamObserver() { MojoAudioInputStreamObserver::~MojoAudioInputStreamObserver() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
// Check that DisableKeyPressMonitoring() was called.
DCHECK(!user_input_monitor_);
} }
void MojoAudioInputStreamObserver::DidStartRecording() { void MojoAudioInputStreamObserver::DidStartRecording() {
...@@ -28,4 +42,17 @@ void MojoAudioInputStreamObserver::DidStartRecording() { ...@@ -28,4 +42,17 @@ void MojoAudioInputStreamObserver::DidStartRecording() {
std::move(recording_started_callback_).Run(); std::move(recording_started_callback_).Run();
} }
void MojoAudioInputStreamObserver::OnConnectionError() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
if (user_input_monitor_) {
user_input_monitor_->DisableKeyPressMonitoring();
// Set to nullptr to check that DisableKeyPressMonitoring() was called
// before destructor.
user_input_monitor_ = nullptr;
}
std::move(connection_error_callback_).Run();
}
} // namespace media } // namespace media
...@@ -11,19 +11,26 @@ ...@@ -11,19 +11,26 @@
namespace media { namespace media {
class UserInputMonitor;
class MEDIA_MOJO_EXPORT MojoAudioInputStreamObserver class MEDIA_MOJO_EXPORT MojoAudioInputStreamObserver
: public mojom::AudioInputStreamObserver { : public mojom::AudioInputStreamObserver {
public: public:
MojoAudioInputStreamObserver(mojom::AudioInputStreamObserverRequest request, MojoAudioInputStreamObserver(mojom::AudioInputStreamObserverRequest request,
base::OnceClosure recording_started_callback, base::OnceClosure recording_started_callback,
base::OnceClosure connection_error_callback); base::OnceClosure connection_error_callback,
media::UserInputMonitor* user_input_monitor);
~MojoAudioInputStreamObserver() override; ~MojoAudioInputStreamObserver() override;
void DidStartRecording() override; void DidStartRecording() override;
private: private:
void OnConnectionError();
mojo::Binding<AudioInputStreamObserver> binding_; mojo::Binding<AudioInputStreamObserver> binding_;
base::OnceClosure recording_started_callback_; base::OnceClosure recording_started_callback_;
base::OnceClosure connection_error_callback_;
media::UserInputMonitor* user_input_monitor_;
SEQUENCE_CHECKER(owning_sequence_); SEQUENCE_CHECKER(owning_sequence_);
......
...@@ -29,7 +29,8 @@ class MojoAudioInputStreamObserverTest : public testing::Test { ...@@ -29,7 +29,8 @@ class MojoAudioInputStreamObserverTest : public testing::Test {
base::Unretained(this)), base::Unretained(this)),
base::BindOnce( base::BindOnce(
&MojoAudioInputStreamObserverTest::BindingConnectionError, &MojoAudioInputStreamObserverTest::BindingConnectionError,
base::Unretained(this))); base::Unretained(this)),
nullptr /*user_input_monitor*/);
} }
MOCK_METHOD0(RecordingStartedCallback, void()); MOCK_METHOD0(RecordingStartedCallback, void());
......
...@@ -57,6 +57,8 @@ source_set("lib") { ...@@ -57,6 +57,8 @@ source_set("lib") {
"sync_reader.h", "sync_reader.h",
"system_info.cc", "system_info.cc",
"system_info.h", "system_info.h",
"user_input_monitor.cc",
"user_input_monitor.h",
] ]
public_deps = [ public_deps = [
...@@ -90,6 +92,7 @@ source_set("tests") { ...@@ -90,6 +92,7 @@ source_set("tests") {
"test/service_lifetime_test_template.h", "test/service_lifetime_test_template.h",
"test/service_observer_mock.cc", "test/service_observer_mock.cc",
"test/service_observer_mock.h", "test/service_observer_mock.h",
"user_input_monitor_unittest.cc",
] ]
deps = [ deps = [
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "mojo/public/cpp/system/buffer.h" #include "mojo/public/cpp/system/buffer.h"
#include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/platform_handle.h" #include "mojo/public/cpp/system/platform_handle.h"
#include "services/audio/user_input_monitor.h"
namespace audio { namespace audio {
...@@ -28,7 +29,7 @@ InputStream::InputStream(CreatedCallback created_callback, ...@@ -28,7 +29,7 @@ InputStream::InputStream(CreatedCallback created_callback,
media::mojom::AudioInputStreamObserverPtr observer, media::mojom::AudioInputStreamObserverPtr observer,
media::mojom::AudioLogPtr log, media::mojom::AudioLogPtr log,
media::AudioManager* audio_manager, media::AudioManager* audio_manager,
media::UserInputMonitor* user_input_monitor, std::unique_ptr<UserInputMonitor> user_input_monitor,
const std::string& device_id, const std::string& device_id,
const media::AudioParameters& params, const media::AudioParameters& params,
uint32_t shared_memory_count, uint32_t shared_memory_count,
...@@ -46,6 +47,7 @@ InputStream::InputStream(CreatedCallback created_callback, ...@@ -46,6 +47,7 @@ InputStream::InputStream(CreatedCallback created_callback,
shared_memory_count, shared_memory_count,
params, params,
&foreign_socket_)), &foreign_socket_)),
user_input_monitor_(std::move(user_input_monitor)),
weak_factory_(this) { weak_factory_(this) {
DCHECK(audio_manager); DCHECK(audio_manager);
DCHECK(binding_.is_bound()); DCHECK(binding_.is_bound());
...@@ -75,8 +77,8 @@ InputStream::InputStream(CreatedCallback created_callback, ...@@ -75,8 +77,8 @@ InputStream::InputStream(CreatedCallback created_callback,
} }
controller_ = media::AudioInputController::Create( controller_ = media::AudioInputController::Create(
audio_manager, this, writer_.get(), user_input_monitor, params, device_id, audio_manager, this, writer_.get(), user_input_monitor_.get(), params,
enable_agc); device_id, enable_agc);
} }
InputStream::~InputStream() { InputStream::~InputStream() {
......
...@@ -21,12 +21,13 @@ namespace media { ...@@ -21,12 +21,13 @@ namespace media {
class AudioInputSyncWriter; class AudioInputSyncWriter;
class AudioManager; class AudioManager;
class AudioParameters; class AudioParameters;
class UserInputMonitor;
} // namespace media } // namespace media
namespace audio { namespace audio {
class UserInputMonitor;
class InputStream final : public media::mojom::AudioInputStream, class InputStream final : public media::mojom::AudioInputStream,
public media::AudioInputController::EventHandler { public media::AudioInputController::EventHandler {
public: public:
...@@ -41,7 +42,7 @@ class InputStream final : public media::mojom::AudioInputStream, ...@@ -41,7 +42,7 @@ class InputStream final : public media::mojom::AudioInputStream,
media::mojom::AudioInputStreamObserverPtr observer, media::mojom::AudioInputStreamObserverPtr observer,
media::mojom::AudioLogPtr log, media::mojom::AudioLogPtr log,
media::AudioManager* manager, media::AudioManager* manager,
media::UserInputMonitor* user_input_monitor, std::unique_ptr<UserInputMonitor> user_input_monitor,
const std::string& device_id, const std::string& device_id,
const media::AudioParameters& params, const media::AudioParameters& params,
uint32_t shared_memory_count, uint32_t shared_memory_count,
...@@ -76,6 +77,7 @@ class InputStream final : public media::mojom::AudioInputStream, ...@@ -76,6 +77,7 @@ class InputStream final : public media::mojom::AudioInputStream,
base::CancelableSyncSocket foreign_socket_; base::CancelableSyncSocket foreign_socket_;
const std::unique_ptr<media::AudioInputSyncWriter> writer_; const std::unique_ptr<media::AudioInputSyncWriter> writer_;
scoped_refptr<media::AudioInputController> controller_; scoped_refptr<media::AudioInputController> controller_;
const std::unique_ptr<UserInputMonitor> user_input_monitor_;
SEQUENCE_CHECKER(owning_sequence_); SEQUENCE_CHECKER(owning_sequence_);
......
...@@ -137,7 +137,7 @@ class AudioServiceInputStreamTest : public testing::Test { ...@@ -137,7 +137,7 @@ class AudioServiceInputStreamTest : public testing::Test {
mojo::MakeRequest(&stream_ptr), client_.MakePtr(), observer_.MakePtr(), mojo::MakeRequest(&stream_ptr), client_.MakePtr(), observer_.MakePtr(),
log_.MakePtr(), kDefaultDeviceId, log_.MakePtr(), kDefaultDeviceId,
media::AudioParameters::UnavailableDeviceParams(), media::AudioParameters::UnavailableDeviceParams(),
kDefaultSharedMemoryCount, enable_agc, kDefaultSharedMemoryCount, enable_agc, mojo::ScopedSharedBufferHandle(),
base::BindOnce(&AudioServiceInputStreamTest::OnCreated, base::BindOnce(&AudioServiceInputStreamTest::OnCreated,
base::Unretained(this))); base::Unretained(this)));
return stream_ptr; return stream_ptr;
......
...@@ -33,14 +33,18 @@ interface StreamFactory { ...@@ -33,14 +33,18 @@ interface StreamFactory {
// obtained from the audio.mojom.SystemInfo interface, or "default". // obtained from the audio.mojom.SystemInfo interface, or "default".
// |shared_memory_count| indicates how many buffer segments can the input // |shared_memory_count| indicates how many buffer segments can the input
// stream client read at once, to avoid data overwriting. |enable_agc| is used // stream client read at once, to avoid data overwriting. |enable_agc| is used
// for enabling automatic gain control. // for enabling automatic gain control. |key_press_count_buffer| is an
// optional readonly shared memory handle for reading the current key press
// count, updated by browser process in media::UserInputMonitor
// implementation.
CreateInputStream( CreateInputStream(
media.mojom.AudioInputStream& stream, media.mojom.AudioInputStream& stream,
media.mojom.AudioInputStreamClient client, media.mojom.AudioInputStreamClient client,
media.mojom.AudioInputStreamObserver observer, media.mojom.AudioInputStreamObserver observer,
media.mojom.AudioLog log, media.mojom.AudioLog log,
string device_id, media.mojom.AudioParameters params, string device_id, media.mojom.AudioParameters params,
uint32 shared_memory_count, bool enable_agc) uint32 shared_memory_count, bool enable_agc,
handle<shared_buffer>? key_press_count_buffer)
=> (media.mojom.AudioDataPipe? data_pipe, bool initially_muted); => (media.mojom.AudioDataPipe? data_pipe, bool initially_muted);
// Creates an AudioOutputStream and returns the AudioDataPipe it reads data // Creates an AudioOutputStream and returns the AudioDataPipe it reads data
......
...@@ -7,16 +7,16 @@ ...@@ -7,16 +7,16 @@
#include <utility> #include <utility>
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "media/base/user_input_monitor.h"
#include "services/audio/input_stream.h" #include "services/audio/input_stream.h"
#include "services/audio/local_muter.h" #include "services/audio/local_muter.h"
#include "services/audio/output_stream.h" #include "services/audio/output_stream.h"
#include "services/audio/user_input_monitor.h"
#include "services/service_manager/public/cpp/service_context_ref.h" #include "services/service_manager/public/cpp/service_context_ref.h"
namespace audio { namespace audio {
StreamFactory::StreamFactory(media::AudioManager* audio_manager) StreamFactory::StreamFactory(media::AudioManager* audio_manager)
: audio_manager_(audio_manager), user_input_monitor_(nullptr) {} : audio_manager_(audio_manager) {}
StreamFactory::~StreamFactory() { StreamFactory::~StreamFactory() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
...@@ -38,6 +38,7 @@ void StreamFactory::CreateInputStream( ...@@ -38,6 +38,7 @@ void StreamFactory::CreateInputStream(
const media::AudioParameters& params, const media::AudioParameters& params,
uint32_t shared_memory_count, uint32_t shared_memory_count,
bool enable_agc, bool enable_agc,
mojo::ScopedSharedBufferHandle key_press_count_buffer,
CreateInputStreamCallback created_callback) { CreateInputStreamCallback created_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
...@@ -48,8 +49,9 @@ void StreamFactory::CreateInputStream( ...@@ -48,8 +49,9 @@ void StreamFactory::CreateInputStream(
input_streams_.insert(std::make_unique<InputStream>( input_streams_.insert(std::make_unique<InputStream>(
std::move(created_callback), std::move(deleter_callback), std::move(created_callback), std::move(deleter_callback),
std::move(stream_request), std::move(client), std::move(observer), std::move(stream_request), std::move(client), std::move(observer),
std::move(log), audio_manager_, user_input_monitor_, device_id, params, std::move(log), audio_manager_,
shared_memory_count, enable_agc)); UserInputMonitor::Create(std::move(key_press_count_buffer)), device_id,
params, shared_memory_count, enable_agc));
} }
void StreamFactory::CreateOutputStream( void StreamFactory::CreateOutputStream(
......
...@@ -27,7 +27,6 @@ class UnguessableToken; ...@@ -27,7 +27,6 @@ class UnguessableToken;
namespace media { namespace media {
class AudioManager; class AudioManager;
class AudioParameters; class AudioParameters;
class UserInputMonitor;
} // namespace media } // namespace media
namespace service_manager { namespace service_manager {
...@@ -61,6 +60,7 @@ class StreamFactory final : public mojom::StreamFactory { ...@@ -61,6 +60,7 @@ class StreamFactory final : public mojom::StreamFactory {
const media::AudioParameters& params, const media::AudioParameters& params,
uint32_t shared_memory_count, uint32_t shared_memory_count,
bool enable_agc, bool enable_agc,
mojo::ScopedSharedBufferHandle key_press_count_buffer,
CreateInputStreamCallback created_callback) final; CreateInputStreamCallback created_callback) final;
void CreateOutputStream( void CreateOutputStream(
...@@ -87,7 +87,6 @@ class StreamFactory final : public mojom::StreamFactory { ...@@ -87,7 +87,6 @@ class StreamFactory final : public mojom::StreamFactory {
SEQUENCE_CHECKER(owning_sequence_); SEQUENCE_CHECKER(owning_sequence_);
media::AudioManager* const audio_manager_; media::AudioManager* const audio_manager_;
media::UserInputMonitor* user_input_monitor_;
mojo::BindingSet<mojom::StreamFactory, mojo::BindingSet<mojom::StreamFactory,
std::unique_ptr<service_manager::ServiceContextRef>> std::unique_ptr<service_manager::ServiceContextRef>>
......
// 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/audio/user_input_monitor.h"
#include <utility>
#include "mojo/public/cpp/system/platform_handle.h"
namespace audio {
// static
std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
mojo::ScopedSharedBufferHandle handle) {
base::ReadOnlySharedMemoryRegion memory =
mojo::UnwrapReadOnlySharedMemoryRegion(std::move(handle));
if (memory.IsValid())
return std::make_unique<UserInputMonitor>(memory.Map());
return nullptr;
}
UserInputMonitor::UserInputMonitor(
base::ReadOnlySharedMemoryMapping memory_mapping)
: key_press_count_mapping_(std::move(memory_mapping)) {}
UserInputMonitor::~UserInputMonitor() = default;
void UserInputMonitor::EnableKeyPressMonitoring() {}
void UserInputMonitor::DisableKeyPressMonitoring() {}
uint32_t UserInputMonitor::GetKeyPressCount() const {
return media::ReadKeyPressMonitorCount(key_press_count_mapping_);
}
} // namespace audio
// 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_AUDIO_USER_INPUT_MONITOR_H_
#define SERVICES_AUDIO_USER_INPUT_MONITOR_H_
#include <memory>
#include "base/memory/shared_memory_mapping.h"
#include "media/base/user_input_monitor.h"
#include "mojo/public/cpp/system/buffer.h"
namespace audio {
// TODO(https://crbug.com/836226) remove inheritance after switching to audio
// service input streams.
class UserInputMonitor : public media::UserInputMonitor {
public:
explicit UserInputMonitor(base::ReadOnlySharedMemoryMapping memory_mapping);
~UserInputMonitor() override;
// Returns nullptr for invalid handle.
static std::unique_ptr<UserInputMonitor> Create(
mojo::ScopedSharedBufferHandle keypress_count_buffer);
void EnableKeyPressMonitoring() override;
void DisableKeyPressMonitoring() override;
uint32_t GetKeyPressCount() const override;
private:
base::ReadOnlySharedMemoryMapping key_press_count_mapping_;
DISALLOW_COPY_AND_ASSIGN(UserInputMonitor);
};
} // namespace audio
#endif // SERVICES_AUDIO_USER_INPUT_MONITOR_H_
// 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/audio/user_input_monitor.h"
#include <memory>
#include <utility>
#include "media/base/user_input_monitor.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace audio {
namespace {
constexpr uint32_t kKeyPressCount = 10;
}
TEST(AudioServiceUserInputMonitorTest, CreateWithValidHandle) {
std::unique_ptr<base::MappedReadOnlyRegion> shmem =
std::make_unique<base::MappedReadOnlyRegion>(
base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t)));
ASSERT_TRUE(shmem->region.IsValid());
ASSERT_TRUE(shmem->mapping.IsValid());
mojo::ScopedSharedBufferHandle handle =
mojo::WrapReadOnlySharedMemoryRegion(shmem->region.Duplicate());
EXPECT_TRUE(UserInputMonitor::Create(std::move(handle)));
}
TEST(AudioServiceUserInputMonitorTest, CreateWithInvalidHandle_ReturnsNullptr) {
EXPECT_EQ(nullptr,
UserInputMonitor::Create(mojo::ScopedSharedBufferHandle()));
}
TEST(AudioServiceUserInputMonitorTest, GetKeyPressCount) {
std::unique_ptr<base::MappedReadOnlyRegion> shmem =
std::make_unique<base::MappedReadOnlyRegion>(
base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t)));
ASSERT_TRUE(shmem->region.IsValid());
ASSERT_TRUE(shmem->mapping.IsValid());
mojo::ScopedSharedBufferHandle handle =
mojo::WrapReadOnlySharedMemoryRegion(shmem->region.Duplicate());
std::unique_ptr<UserInputMonitor> monitor =
UserInputMonitor::Create(std::move(handle));
EXPECT_TRUE(monitor);
media::WriteKeyPressMonitorCount(shmem->mapping, kKeyPressCount);
EXPECT_EQ(kKeyPressCount, monitor->GetKeyPressCount());
}
TEST(AudioServiceUserInputMonitorTest, GetKeyPressCountAfterMemoryUnmap) {
std::unique_ptr<base::MappedReadOnlyRegion> shmem =
std::make_unique<base::MappedReadOnlyRegion>(
base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t)));
ASSERT_TRUE(shmem->region.IsValid());
ASSERT_TRUE(shmem->mapping.IsValid());
mojo::ScopedSharedBufferHandle handle =
mojo::WrapReadOnlySharedMemoryRegion(shmem->region.Duplicate());
std::unique_ptr<UserInputMonitor> monitor =
UserInputMonitor::Create(std::move(handle));
EXPECT_TRUE(monitor);
media::WriteKeyPressMonitorCount(shmem->mapping, kKeyPressCount);
EXPECT_EQ(kKeyPressCount, monitor->GetKeyPressCount());
// ReadOnlyMapping should still be valid, containing the last updated value,
// after shmem reset.
shmem.reset();
EXPECT_EQ(kKeyPressCount, monitor->GetKeyPressCount());
}
} // namespace audio
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