Commit 73a21d4b authored by Guido Urdaneta's avatar Guido Urdaneta Committed by Commit Bot

Add LogFactoryManager to audio service.

This allows the browser process to set a factory so that the audio
service can create audio logs on the browser process.

Bug: 812557
Change-Id: Ia88acb6cb911fc0ad4a47f20b3a628c814233c6b
Reviewed-on: https://chromium-review.googlesource.com/1128974Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarMax Morin <maxmorin@chromium.org>
Reviewed-by: default avatarMarina Ciocea <marinaciocea@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575561}
parent 54d95ca9
...@@ -6,12 +6,16 @@ ...@@ -6,12 +6,16 @@
#include <utility> #include <utility>
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/time/default_tick_clock.h" #include "base/time/default_tick_clock.h"
#include "content/browser/media/audio_log_factory.h"
#include "content/public/browser/child_process_data.h" #include "content/public/browser/child_process_data.h"
#include "content/public/browser/child_process_termination_info.h" #include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/audio/public/mojom/constants.mojom.h" #include "services/audio/public/mojom/constants.mojom.h"
#include "services/audio/public/mojom/log_factory_manager.mojom.h"
namespace content { namespace content {
...@@ -88,14 +92,15 @@ void AudioServiceListener::Metrics::LogServiceStartStatus( ...@@ -88,14 +92,15 @@ void AudioServiceListener::Metrics::LogServiceStartStatus(
AudioServiceListener::AudioServiceListener( AudioServiceListener::AudioServiceListener(
std::unique_ptr<service_manager::Connector> connector) std::unique_ptr<service_manager::Connector> connector)
: binding_(this), : binding_(this),
connector_(std::move(connector)),
metrics_(base::DefaultTickClock::GetInstance()) { metrics_(base::DefaultTickClock::GetInstance()) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
if (!connector) if (!connector_)
return; // Happens in unittests. return; // Happens in unittests.
service_manager::mojom::ServiceManagerPtr service_manager; service_manager::mojom::ServiceManagerPtr service_manager;
connector->BindInterface(service_manager::mojom::kServiceName, connector_->BindInterface(service_manager::mojom::kServiceName,
&service_manager); &service_manager);
service_manager::mojom::ServiceManagerListenerPtr listener; service_manager::mojom::ServiceManagerListenerPtr listener;
service_manager::mojom::ServiceManagerListenerRequest request( service_manager::mojom::ServiceManagerListenerRequest request(
mojo::MakeRequest(&listener)); mojo::MakeRequest(&listener));
...@@ -123,6 +128,7 @@ void AudioServiceListener::OnInit( ...@@ -123,6 +128,7 @@ void AudioServiceListener::OnInit(
if (instance->identity.name() == audio::mojom::kServiceName) { if (instance->identity.name() == audio::mojom::kServiceName) {
process_id_ = instance->pid; process_id_ = instance->pid;
metrics_.ServiceAlreadyRunning(); metrics_.ServiceAlreadyRunning();
MaybeSetLogFactory();
break; break;
} }
} }
...@@ -134,6 +140,7 @@ void AudioServiceListener::OnServiceCreated( ...@@ -134,6 +140,7 @@ void AudioServiceListener::OnServiceCreated(
if (service->identity.name() != audio::mojom::kServiceName) if (service->identity.name() != audio::mojom::kServiceName)
return; return;
metrics_.ServiceCreated(); metrics_.ServiceCreated();
MaybeSetLogFactory();
} }
void AudioServiceListener::OnServiceStarted( void AudioServiceListener::OnServiceStarted(
...@@ -169,6 +176,7 @@ void AudioServiceListener::OnServiceStopped( ...@@ -169,6 +176,7 @@ void AudioServiceListener::OnServiceStopped(
if (identity.name() != audio::mojom::kServiceName) if (identity.name() != audio::mojom::kServiceName)
return; return;
metrics_.ServiceStopped(); metrics_.ServiceStopped();
log_factory_is_set_ = false;
} }
void AudioServiceListener::BrowserChildProcessHostDisconnected( void AudioServiceListener::BrowserChildProcessHostDisconnected(
...@@ -203,4 +211,20 @@ void AudioServiceListener::BrowserChildProcessKilled( ...@@ -203,4 +211,20 @@ void AudioServiceListener::BrowserChildProcessKilled(
Metrics::ServiceProcessTerminationStatus::kKill); Metrics::ServiceProcessTerminationStatus::kKill);
} }
void AudioServiceListener::MaybeSetLogFactory() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
if (!base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess) ||
!connector_ || log_factory_is_set_)
return;
media::mojom::AudioLogFactoryPtr audio_log_factory_ptr;
mojo::MakeStrongBinding(std::make_unique<AudioLogFactory>(),
mojo::MakeRequest(&audio_log_factory_ptr));
audio::mojom::LogFactoryManagerPtr log_factory_manager_ptr;
connector_->BindInterface(audio::mojom::kServiceName,
mojo::MakeRequest(&log_factory_manager_ptr));
log_factory_manager_ptr->SetLogFactory(std::move(audio_log_factory_ptr));
log_factory_is_set_ = true;
}
} // namespace content } // namespace content
...@@ -116,9 +116,13 @@ class CONTENT_EXPORT AudioServiceListener ...@@ -116,9 +116,13 @@ class CONTENT_EXPORT AudioServiceListener
void BrowserChildProcessKilled(const ChildProcessData& data, void BrowserChildProcessKilled(const ChildProcessData& data,
const ChildProcessTerminationInfo& info) final; const ChildProcessTerminationInfo& info) final;
void MaybeSetLogFactory();
mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_; mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_;
std::unique_ptr<service_manager::Connector> connector_;
base::ProcessId process_id_ = base::kNullProcessId; base::ProcessId process_id_ = base::kNullProcessId;
Metrics metrics_; Metrics metrics_;
bool log_factory_is_set_ = false;
SEQUENCE_CHECKER(owning_sequence_); SEQUENCE_CHECKER(owning_sequence_);
DISALLOW_COPY_AND_ASSIGN(AudioServiceListener); DISALLOW_COPY_AND_ASSIGN(AudioServiceListener);
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
"info", "info",
"debug_recording", "debug_recording",
"device_notifier", "device_notifier",
"log_factory_manager",
"stream_factory", "stream_factory",
"testing_api" "testing_api"
], ],
......
...@@ -51,6 +51,12 @@ source_set("lib") { ...@@ -51,6 +51,12 @@ source_set("lib") {
"input_sync_writer.h", "input_sync_writer.h",
"local_muter.cc", "local_muter.cc",
"local_muter.h", "local_muter.h",
"log_adapter.cc",
"log_adapter.h",
"log_factory_adapter.cc",
"log_factory_adapter.h",
"log_factory_manager.cc",
"log_factory_manager.h",
"loopback_stream.cc", "loopback_stream.cc",
"loopback_stream.h", "loopback_stream.h",
"output_controller.cc", "output_controller.cc",
...@@ -104,6 +110,7 @@ source_set("tests") { ...@@ -104,6 +110,7 @@ source_set("tests") {
"input_stream_unittest.cc", "input_stream_unittest.cc",
"input_sync_writer_unittest.cc", "input_sync_writer_unittest.cc",
"local_muter_unittest.cc", "local_muter_unittest.cc",
"log_factory_manager_unittest.cc",
"loopback_stream_unittest.cc", "loopback_stream_unittest.cc",
"output_controller_unittest.cc", "output_controller_unittest.cc",
"output_stream_unittest.cc", "output_stream_unittest.cc",
......
...@@ -27,4 +27,9 @@ media::AudioManager* InProcessAudioManagerAccessor::GetAudioManager() { ...@@ -27,4 +27,9 @@ media::AudioManager* InProcessAudioManagerAccessor::GetAudioManager() {
return audio_manager_; return audio_manager_;
} }
void InProcessAudioManagerAccessor::SetAudioLogFactory(
media::AudioLogFactory* factory) {
NOTREACHED();
}
} // namespace audio } // namespace audio
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
namespace media { namespace media {
class AudioManager; class AudioManager;
class AudioLogFactory;
} }
namespace audio { namespace audio {
...@@ -25,6 +26,9 @@ class InProcessAudioManagerAccessor : public Service::AudioManagerAccessor { ...@@ -25,6 +26,9 @@ class InProcessAudioManagerAccessor : public Service::AudioManagerAccessor {
void Shutdown() final {} // AudioManager must be shut down by its owner. void Shutdown() final {} // AudioManager must be shut down by its owner.
media::AudioManager* GetAudioManager() final; media::AudioManager* GetAudioManager() final;
// Should not be called on this implementation.
void SetAudioLogFactory(media::AudioLogFactory* factory) final;
private: private:
media::AudioManager* const audio_manager_; media::AudioManager* const audio_manager_;
DISALLOW_COPY_AND_ASSIGN(InProcessAudioManagerAccessor); DISALLOW_COPY_AND_ASSIGN(InProcessAudioManagerAccessor);
......
// 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/log_adapter.h"
#include <utility>
namespace audio {
LogAdapter::LogAdapter(media::mojom::AudioLogPtr audio_log)
: audio_log_(std::move(audio_log)) {}
LogAdapter::~LogAdapter() = default;
void LogAdapter::OnCreated(const media::AudioParameters& params,
const std::string& device_id) {
audio_log_->OnCreated(params, device_id);
}
void LogAdapter::OnStarted() {
audio_log_->OnStarted();
}
void LogAdapter::OnStopped() {
audio_log_->OnStopped();
}
void LogAdapter::OnClosed() {
audio_log_->OnClosed();
}
void LogAdapter::OnError() {
audio_log_->OnError();
}
void LogAdapter::OnSetVolume(double volume) {
audio_log_->OnSetVolume(volume);
}
void LogAdapter::OnLogMessage(const std::string& message) {
audio_log_->OnLogMessage(message);
}
} // 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_LOG_ADAPTER_H_
#define SERVICES_AUDIO_LOG_ADAPTER_H_
#include <string>
#include "media/audio/audio_logging.h"
#include "media/mojo/interfaces/audio_logging.mojom.h"
namespace media {
class AudioParameters;
}
namespace audio {
// This class wraps a media::mojom::AudioLogPtr into a media::AudioLog.
class LogAdapter : public media::AudioLog {
public:
explicit LogAdapter(media::mojom::AudioLogPtr audio_log);
~LogAdapter() override;
// media::AudioLog implementation.
void OnCreated(const media::AudioParameters& params,
const std::string& device_id) override;
void OnStarted() override;
void OnStopped() override;
void OnClosed() override;
void OnError() override;
void OnSetVolume(double volume) override;
void OnLogMessage(const std::string& message) override;
private:
media::mojom::AudioLogPtr audio_log_;
DISALLOW_COPY_AND_ASSIGN(LogAdapter);
};
} // namespace audio
#endif // SERVICES_AUDIO_LOG_ADAPTER_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/log_factory_adapter.h"
#include <utility>
#include "services/audio/log_adapter.h"
namespace audio {
const int kMaxPendingLogRequests = 500;
struct LogFactoryAdapter::PendingLogRequest {
PendingLogRequest(media::mojom::AudioLogComponent component,
int component_id,
media::mojom::AudioLogRequest request)
: component(component),
component_id(component_id),
request(std::move(request)) {}
PendingLogRequest(PendingLogRequest&& other) = default;
PendingLogRequest& operator=(PendingLogRequest&& other) = default;
PendingLogRequest(const PendingLogRequest& other) = delete;
PendingLogRequest& operator=(const PendingLogRequest& other) = delete;
~PendingLogRequest() = default;
media::mojom::AudioLogComponent component;
int component_id;
media::mojom::AudioLogRequest request;
};
LogFactoryAdapter::LogFactoryAdapter() = default;
LogFactoryAdapter::~LogFactoryAdapter() = default;
void LogFactoryAdapter::SetLogFactory(
media::mojom::AudioLogFactoryPtr log_factory) {
if (log_factory_) {
LOG(WARNING) << "Attempting to set log factory more than once. Ignoring "
"request.";
return;
}
log_factory_ = std::move(log_factory);
while (!pending_requests_.empty()) {
auto& front = pending_requests_.front();
log_factory_->CreateAudioLog(front.component, front.component_id,
std::move(front.request));
pending_requests_.pop();
}
}
std::unique_ptr<media::AudioLog> LogFactoryAdapter::CreateAudioLog(
AudioComponent component,
int component_id) {
media::mojom::AudioLogPtr audio_log_ptr;
media::mojom::AudioLogRequest audio_log_request =
mojo::MakeRequest(&audio_log_ptr);
media::mojom::AudioLogComponent mojo_component =
static_cast<media::mojom::AudioLogComponent>(component);
if (log_factory_) {
log_factory_->CreateAudioLog(mojo_component, component_id,
std::move(audio_log_request));
} else if (pending_requests_.size() >= kMaxPendingLogRequests) {
LOG(WARNING) << "Maximum number of queued log requests exceeded. Fulfilling"
" request with fake log.";
return fake_log_factory_.CreateAudioLog(component, component_id);
} else {
pending_requests_.emplace(mojo_component, component_id,
std::move(audio_log_request));
}
return std::make_unique<LogAdapter>(std::move(audio_log_ptr));
}
} // 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_LOG_FACTORY_ADAPTER_H_
#define SERVICES_AUDIO_LOG_FACTORY_ADAPTER_H_
#include <memory>
#include "base/containers/queue.h"
#include "media/audio/audio_logging.h"
#include "media/audio/fake_audio_log_factory.h"
#include "services/audio/public/mojom/log_factory_manager.mojom.h"
namespace media {
class AudioLogFactory;
} // namespace media
namespace audio {
// This class allows setting a mojo audio log factory to create audio logs
// in the audio service. It also acts as a media::AudioLogFactory to interface
// with AudioManager.
class LogFactoryAdapter final : public media::AudioLogFactory {
public:
LogFactoryAdapter();
~LogFactoryAdapter() final;
void SetLogFactory(media::mojom::AudioLogFactoryPtr log_factory);
// media::AudioLogFactory implementation
std::unique_ptr<media::AudioLog> CreateAudioLog(AudioComponent component,
int component_id) override;
private:
struct PendingLogRequest;
media::mojom::AudioLogFactoryPtr log_factory_;
base::queue<PendingLogRequest> pending_requests_;
media::FakeAudioLogFactory fake_log_factory_;
DISALLOW_COPY_AND_ASSIGN(LogFactoryAdapter);
};
} // namespace audio
#endif // SERVICES_AUDIO_LOG_FACTORY_ADAPTER_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/log_factory_manager.h"
#include <utility>
#include "services/service_manager/public/cpp/service_context_ref.h"
namespace audio {
LogFactoryManager::LogFactoryManager() {}
LogFactoryManager::~LogFactoryManager() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
}
void LogFactoryManager::Bind(mojom::LogFactoryManagerRequest request,
TracedServiceRef context_ref) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
bindings_.AddBinding(this, std::move(request), std::move(context_ref));
}
void LogFactoryManager::SetLogFactory(
media::mojom::AudioLogFactoryPtr log_factory) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
log_factory_adapter_.SetLogFactory(std::move(log_factory));
}
media::AudioLogFactory* LogFactoryManager::GetLogFactory() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
return &log_factory_adapter_;
}
} // 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_LOG_FACTORY_MANAGER_H_
#define SERVICES_AUDIO_LOG_FACTORY_MANAGER_H_
#include <memory>
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/audio/log_factory_adapter.h"
#include "services/audio/public/mojom/log_factory_manager.mojom.h"
#include "services/audio/traced_service_ref.h"
namespace media {
class AudioLogFactory;
}
namespace audio {
// This class is used to provide the LogFactoryManager interface. It will
// typically be instantiated when needed and remain for the lifetime of the
// service.
class LogFactoryManager final : public mojom::LogFactoryManager {
public:
LogFactoryManager();
~LogFactoryManager() final;
void Bind(mojom::LogFactoryManagerRequest request,
TracedServiceRef context_ref);
// LogFactoryManager implementation.
void SetLogFactory(media::mojom::AudioLogFactoryPtr log_factory) final;
media::AudioLogFactory* GetLogFactory();
private:
mojo::BindingSet<mojom::LogFactoryManager, TracedServiceRef> bindings_;
LogFactoryAdapter log_factory_adapter_;
SEQUENCE_CHECKER(owning_sequence_);
DISALLOW_COPY_AND_ASSIGN(LogFactoryManager);
};
} // namespace audio
#endif // SERVICES_AUDIO_LOG_FACTORY_MANAGER_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/log_factory_manager.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/memory/ptr_util.h"
#include "base/test/scoped_task_environment.h"
#include "media/mojo/interfaces/audio_logging.mojom.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/audio/traced_service_ref.h"
#include "services/service_manager/public/cpp/service_context_ref.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace audio {
using testing::_;
using testing::SaveArg;
namespace {
class MockAudioLog : public media::mojom::AudioLog {
public:
MockAudioLog() {}
MOCK_METHOD2(OnCreated,
void(const media::AudioParameters& params,
const std::string& device_id));
MOCK_METHOD0(OnStarted, void());
MOCK_METHOD0(OnStopped, void());
MOCK_METHOD0(OnClosed, void());
MOCK_METHOD0(OnError, void());
MOCK_METHOD1(OnSetVolume, void(double));
MOCK_METHOD1(OnLogMessage, void(const std::string&));
};
class MockAudioLogFactory : public media::mojom::AudioLogFactory {
public:
MockAudioLogFactory(media::mojom::AudioLogFactoryRequest request,
size_t num_mock_logs)
: binding_(this, std::move(request)) {
for (size_t i = 0; i < num_mock_logs; ++i)
mock_logs_.push_back(new MockAudioLog());
}
MOCK_METHOD2(MockCreateAudioLog,
void(media::mojom::AudioLogComponent, int32_t));
void CreateAudioLog(
media::mojom::AudioLogComponent component,
int32_t component_id,
media::mojom::AudioLogRequest audio_log_request) override {
MockCreateAudioLog(component, component_id);
mojo::MakeStrongBinding(base::WrapUnique(mock_logs_[current_mock_log_++]),
std::move(audio_log_request));
};
MockAudioLog* GetMockLog(size_t index) { return mock_logs_[index]; }
private:
mojo::Binding<media::mojom::AudioLogFactory> binding_;
size_t current_mock_log_ = 0;
std::vector<MockAudioLog*> mock_logs_;
DISALLOW_COPY_AND_ASSIGN(MockAudioLogFactory);
};
} // namespace
class LogFactoryManagerTest : public ::testing::Test {
public:
LogFactoryManagerTest()
: service_ref_factory_(
base::BindRepeating(&LogFactoryManagerTest::OnNoServiceRefs,
base::Unretained(this))) {}
protected:
MOCK_METHOD0(OnNoServiceRefs, void());
void CreateLogFactoryManager() {
log_factory_manager_ = std::make_unique<LogFactoryManager>();
log_factory_manager_->Bind(
mojo::MakeRequest(&log_factory_manager_ptr_),
TracedServiceRef(service_ref_factory_.CreateRef(),
"audio::LogFactoryManager Binding"));
EXPECT_FALSE(service_ref_factory_.HasNoRefs());
}
void DestroyLogFactoryManager() {
log_factory_manager_ptr_.reset();
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(service_ref_factory_.HasNoRefs());
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
mojom::LogFactoryManagerPtr log_factory_manager_ptr_;
std::unique_ptr<LogFactoryManager> log_factory_manager_;
private:
service_manager::ServiceContextRefFactory service_ref_factory_;
DISALLOW_COPY_AND_ASSIGN(LogFactoryManagerTest);
};
TEST_F(LogFactoryManagerTest, LogFactoryManagerQueuesRequestsAndSetsFactory) {
EXPECT_CALL(*this, OnNoServiceRefs());
CreateLogFactoryManager();
// Create a log before setting the log factory.
const int kComponentId1 = 1;
const double kVolume1 = 0.5;
media::AudioLogFactory* log_factory = log_factory_manager_->GetLogFactory();
std::unique_ptr<media::AudioLog> log1 = log_factory->CreateAudioLog(
media::AudioLogFactory::AUDIO_OUTPUT_STREAM, kComponentId1);
log1->OnStarted();
log1->OnSetVolume(kVolume1);
log1->OnStopped();
log1->OnClosed();
// Set the factory.
media::mojom::AudioLogFactoryPtr log_factory_ptr;
MockAudioLogFactory mock_factory(mojo::MakeRequest(&log_factory_ptr), 2);
MockAudioLog* mock_log1 = mock_factory.GetMockLog(0);
testing::InSequence s;
// Set the factory and expect that queued operations run.
EXPECT_CALL(mock_factory,
MockCreateAudioLog(media::mojom::AudioLogComponent::kOutputStream,
kComponentId1));
EXPECT_CALL(*mock_log1, OnStarted());
EXPECT_CALL(*mock_log1, OnSetVolume(kVolume1));
EXPECT_CALL(*mock_log1, OnStopped());
EXPECT_CALL(*mock_log1, OnClosed());
log_factory_manager_ptr_->SetLogFactory(std::move(log_factory_ptr));
scoped_task_environment_.RunUntilIdle();
// Create another log after the factory is already set.
const int kComponentId2 = 2;
const double kVolume2 = 0.1;
EXPECT_CALL(
mock_factory,
MockCreateAudioLog(media::mojom::AudioLogComponent::kInputController,
kComponentId2));
MockAudioLog* mock_log2 = mock_factory.GetMockLog(1);
EXPECT_CALL(*mock_log2, OnStarted());
EXPECT_CALL(*mock_log2, OnSetVolume(kVolume2));
EXPECT_CALL(*mock_log2, OnStopped());
EXPECT_CALL(*mock_log2, OnClosed());
std::unique_ptr<media::AudioLog> log2 = log_factory->CreateAudioLog(
media::AudioLogFactory::AUDIO_INPUT_CONTROLLER, 2);
log2->OnStarted();
log2->OnSetVolume(kVolume2);
log2->OnStopped();
log2->OnClosed();
// Ensure all mock objects are released.
log1.reset();
log2.reset();
DestroyLogFactoryManager();
}
} // namespace audio
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
"debug_recording": [ "audio.mojom.DebugRecording" ], "debug_recording": [ "audio.mojom.DebugRecording" ],
"stream_factory": [ "audio.mojom.StreamFactory" ], "stream_factory": [ "audio.mojom.StreamFactory" ],
"device_notifier": [ "audio.mojom.DeviceNotifier" ], "device_notifier": [ "audio.mojom.DeviceNotifier" ],
"log_factory_manager": [ "audio.mojom.LogFactoryManager" ],
"testing_api": [ "audio.mojom.TestingApi" ] "testing_api": [ "audio.mojom.TestingApi" ]
}, },
"requires": { "requires": {
......
...@@ -90,12 +90,10 @@ media::AudioManager* OwningAudioManagerAccessor::GetAudioManager() { ...@@ -90,12 +90,10 @@ media::AudioManager* OwningAudioManagerAccessor::GetAudioManager() {
if (!audio_manager_) { if (!audio_manager_) {
TRACE_EVENT0("audio", "AudioManager creation"); TRACE_EVENT0("audio", "AudioManager creation");
DCHECK(audio_manager_factory_cb_); DCHECK(audio_manager_factory_cb_);
DCHECK(log_factory_);
base::TimeTicks creation_start_time = base::TimeTicks::Now(); base::TimeTicks creation_start_time = base::TimeTicks::Now();
// TODO(http://crbug/812557): pass AudioLogFactory (needed for output
// streams).
audio_manager_ = std::move(audio_manager_factory_cb_) audio_manager_ = std::move(audio_manager_factory_cb_)
.Run(std::make_unique<MainThread>(), &log_factory_); .Run(std::make_unique<MainThread>(), log_factory_);
DCHECK(audio_manager_); DCHECK(audio_manager_);
UMA_HISTOGRAM_TIMES("Media.AudioService.AudioManagerStartupTime", UMA_HISTOGRAM_TIMES("Media.AudioService.AudioManagerStartupTime",
base::TimeTicks::Now() - creation_start_time); base::TimeTicks::Now() - creation_start_time);
...@@ -104,6 +102,11 @@ media::AudioManager* OwningAudioManagerAccessor::GetAudioManager() { ...@@ -104,6 +102,11 @@ media::AudioManager* OwningAudioManagerAccessor::GetAudioManager() {
return audio_manager_.get(); return audio_manager_.get();
} }
void OwningAudioManagerAccessor::SetAudioLogFactory(
media::AudioLogFactory* log_factory) {
log_factory_ = log_factory;
}
void OwningAudioManagerAccessor::Shutdown() { void OwningAudioManagerAccessor::Shutdown() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (audio_manager_) if (audio_manager_)
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "media/audio/fake_audio_log_factory.h"
#include "services/audio/service.h" #include "services/audio/service.h"
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -40,6 +39,7 @@ class OwningAudioManagerAccessor : public Service::AudioManagerAccessor { ...@@ -40,6 +39,7 @@ class OwningAudioManagerAccessor : public Service::AudioManagerAccessor {
~OwningAudioManagerAccessor() override; ~OwningAudioManagerAccessor() override;
media::AudioManager* GetAudioManager() final; media::AudioManager* GetAudioManager() final;
void SetAudioLogFactory(media::AudioLogFactory* factory) final;
void Shutdown() final; void Shutdown() final;
private: private:
...@@ -49,10 +49,7 @@ class OwningAudioManagerAccessor : public Service::AudioManagerAccessor { ...@@ -49,10 +49,7 @@ class OwningAudioManagerAccessor : public Service::AudioManagerAccessor {
#endif #endif
AudioManagerFactoryCallback audio_manager_factory_cb_; AudioManagerFactoryCallback audio_manager_factory_cb_;
std::unique_ptr<media::AudioManager> audio_manager_; std::unique_ptr<media::AudioManager> audio_manager_;
media::AudioLogFactory* log_factory_ = nullptr; // not owned.
// TODO(http://crbug/812557): Use a real AudioLogFactory (needed for output
// streams).
media::FakeAudioLogFactory log_factory_;
THREAD_CHECKER(thread_checker_); THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(OwningAudioManagerAccessor); DISALLOW_COPY_AND_ASSIGN(OwningAudioManagerAccessor);
......
...@@ -9,6 +9,7 @@ mojom("mojom") { ...@@ -9,6 +9,7 @@ mojom("mojom") {
"audio_device_description.mojom", "audio_device_description.mojom",
"debug_recording.mojom", "debug_recording.mojom",
"device_notifications.mojom", "device_notifications.mojom",
"log_factory_manager.mojom",
"stream_factory.mojom", "stream_factory.mojom",
"system_info.mojom", "system_info.mojom",
"testing_api.mojom", "testing_api.mojom",
......
// 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.
module audio.mojom;
import "media/mojo/interfaces/audio_logging.mojom";
// This interface is exposed by the audio service to allow trusted clients
// (like the browser process) to set a factory for creating audio logs.
interface LogFactoryManager {
// Sets the factory for creating audio logs. If a previous factory exists,
// the request is ignored.
SetLogFactory(media.mojom.AudioLogFactory factory);
};
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "media/audio/audio_manager.h" #include "media/audio/audio_manager.h"
#include "services/audio/debug_recording.h" #include "services/audio/debug_recording.h"
#include "services/audio/device_notifier.h" #include "services/audio/device_notifier.h"
#include "services/audio/log_factory_manager.h"
#include "services/audio/service_metrics.h" #include "services/audio/service_metrics.h"
#include "services/audio/system_info.h" #include "services/audio/system_info.h"
#include "services/service_manager/public/cpp/service_context.h" #include "services/service_manager/public/cpp/service_context.h"
...@@ -28,15 +29,22 @@ namespace audio { ...@@ -28,15 +29,22 @@ namespace audio {
Service::Service(std::unique_ptr<AudioManagerAccessor> audio_manager_accessor, Service::Service(std::unique_ptr<AudioManagerAccessor> audio_manager_accessor,
base::TimeDelta quit_timeout, base::TimeDelta quit_timeout,
bool device_notifier_enabled, bool enable_remote_client_support,
std::unique_ptr<service_manager::BinderRegistry> registry) std::unique_ptr<service_manager::BinderRegistry> registry)
: quit_timeout_(quit_timeout), : quit_timeout_(quit_timeout),
audio_manager_accessor_(std::move(audio_manager_accessor)), audio_manager_accessor_(std::move(audio_manager_accessor)),
device_notifier_enabled_(device_notifier_enabled), enable_remote_client_support_(enable_remote_client_support),
registry_(std::move(registry)) { registry_(std::move(registry)) {
DCHECK(audio_manager_accessor_); DCHECK(audio_manager_accessor_);
if (!device_notifier_enabled) if (enable_remote_client_support_) {
log_factory_manager_ = std::make_unique<LogFactoryManager>();
audio_manager_accessor_->SetAudioLogFactory(
log_factory_manager_->GetLogFactory());
} else {
// Start device monitoring explicitly if no mojo device notifier will be
// created. This is required for in-process device notifications.
InitializeDeviceMonitor(); InitializeDeviceMonitor();
}
} }
Service::~Service() { Service::~Service() {
...@@ -77,9 +85,11 @@ void Service::OnStart() { ...@@ -77,9 +85,11 @@ void Service::OnStart() {
&Service::BindDebugRecordingRequest, base::Unretained(this))); &Service::BindDebugRecordingRequest, base::Unretained(this)));
registry_->AddInterface<mojom::StreamFactory>(base::BindRepeating( registry_->AddInterface<mojom::StreamFactory>(base::BindRepeating(
&Service::BindStreamFactoryRequest, base::Unretained(this))); &Service::BindStreamFactoryRequest, base::Unretained(this)));
if (device_notifier_enabled_) { if (enable_remote_client_support_) {
registry_->AddInterface<mojom::DeviceNotifier>(base::BindRepeating( registry_->AddInterface<mojom::DeviceNotifier>(base::BindRepeating(
&Service::BindDeviceNotifierRequest, base::Unretained(this))); &Service::BindDeviceNotifierRequest, base::Unretained(this)));
registry_->AddInterface<mojom::LogFactoryManager>(base::BindRepeating(
&Service::BindLogFactoryManagerRequest, base::Unretained(this)));
} }
} }
...@@ -160,7 +170,7 @@ void Service::BindStreamFactoryRequest(mojom::StreamFactoryRequest request) { ...@@ -160,7 +170,7 @@ void Service::BindStreamFactoryRequest(mojom::StreamFactoryRequest request) {
void Service::BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request) { void Service::BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(ref_factory_); DCHECK(ref_factory_);
DCHECK(device_notifier_enabled_); DCHECK(enable_remote_client_support_);
if (!system_monitor_) { if (!system_monitor_) {
CHECK(!base::SystemMonitor::Get()); CHECK(!base::SystemMonitor::Get());
...@@ -174,6 +184,17 @@ void Service::BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request) { ...@@ -174,6 +184,17 @@ void Service::BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request) {
"audio::DeviceNotifier Binding")); "audio::DeviceNotifier Binding"));
} }
void Service::BindLogFactoryManagerRequest(
mojom::LogFactoryManagerRequest request) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(ref_factory_);
DCHECK(log_factory_manager_);
DCHECK(enable_remote_client_support_);
log_factory_manager_->Bind(
std::move(request), TracedServiceRef(ref_factory_->CreateRef(),
"audio::LogFactoryManager Binding"));
}
void Service::MaybeRequestQuitDelayed() { void Service::MaybeRequestQuitDelayed() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
metrics_->HasNoConnections(); metrics_->HasNoConnections();
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "services/audio/public/mojom/debug_recording.mojom.h" #include "services/audio/public/mojom/debug_recording.mojom.h"
#include "services/audio/public/mojom/device_notifications.mojom.h" #include "services/audio/public/mojom/device_notifications.mojom.h"
#include "services/audio/public/mojom/log_factory_manager.mojom.h"
#include "services/audio/public/mojom/stream_factory.mojom.h" #include "services/audio/public/mojom/stream_factory.mojom.h"
#include "services/audio/public/mojom/system_info.mojom.h" #include "services/audio/public/mojom/system_info.mojom.h"
#include "services/audio/stream_factory.h" #include "services/audio/stream_factory.h"
...@@ -29,6 +30,7 @@ class SystemMonitor; ...@@ -29,6 +30,7 @@ class SystemMonitor;
namespace media { namespace media {
class AudioDeviceListenerMac; class AudioDeviceListenerMac;
class AudioManager; class AudioManager;
class AudioLogFactory;
} // namespace media } // namespace media
namespace service_manager { namespace service_manager {
...@@ -38,6 +40,7 @@ class ServiceContextRefFactory; ...@@ -38,6 +40,7 @@ class ServiceContextRefFactory;
namespace audio { namespace audio {
class DebugRecording; class DebugRecording;
class DeviceNotifier; class DeviceNotifier;
class LogFactoryManager;
class ServiceMetrics; class ServiceMetrics;
class SystemInfo; class SystemInfo;
...@@ -55,16 +58,22 @@ class Service : public service_manager::Service { ...@@ -55,16 +58,22 @@ class Service : public service_manager::Service {
// Returns a pointer to AudioManager. // Returns a pointer to AudioManager.
virtual media::AudioManager* GetAudioManager() = 0; virtual media::AudioManager* GetAudioManager() = 0;
// Attempts to associate |factory| with the audio manager.
// |factory| must outlive the audio manager.
// It only makes sense to call this method before GetAudioManager().
virtual void SetAudioLogFactory(media::AudioLogFactory* factory) = 0;
}; };
// Service will attempt to quit if there are no connections to it within // Service will attempt to quit if there are no connections to it within
// |quit_timeout| interval. If |quit_timeout| is base::TimeDelta() the // |quit_timeout| interval. If |quit_timeout| is base::TimeDelta() the
// service never quits. If |device_notifier_enabled| is true, the service // service never quits. If |enable_remote_client_support| is true, the service
// will make available a DeviceNotifier object that allows clients to // will make available a DeviceNotifier object that allows clients to
// subscribe to notifications about device changes. // subscribe to notifications about device changes and a LogFactoryManager
// object that allows clients to set a factory for audio logs.
Service(std::unique_ptr<AudioManagerAccessor> audio_manager_accessor, Service(std::unique_ptr<AudioManagerAccessor> audio_manager_accessor,
base::TimeDelta quit_timeout, base::TimeDelta quit_timeout,
bool device_notifier_enabled, bool enable_remote_client_support,
std::unique_ptr<service_manager::BinderRegistry> registry); std::unique_ptr<service_manager::BinderRegistry> registry);
~Service() final; ~Service() final;
...@@ -82,6 +91,7 @@ class Service : public service_manager::Service { ...@@ -82,6 +91,7 @@ class Service : public service_manager::Service {
void BindDebugRecordingRequest(mojom::DebugRecordingRequest request); void BindDebugRecordingRequest(mojom::DebugRecordingRequest request);
void BindStreamFactoryRequest(mojom::StreamFactoryRequest request); void BindStreamFactoryRequest(mojom::StreamFactoryRequest request);
void BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request); void BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request);
void BindLogFactoryManagerRequest(mojom::LogFactoryManagerRequest request);
void MaybeRequestQuitDelayed(); void MaybeRequestQuitDelayed();
void MaybeRequestQuit(); void MaybeRequestQuit();
...@@ -103,7 +113,7 @@ class Service : public service_manager::Service { ...@@ -103,7 +113,7 @@ class Service : public service_manager::Service {
base::OneShotTimer quit_timer_; base::OneShotTimer quit_timer_;
std::unique_ptr<AudioManagerAccessor> audio_manager_accessor_; std::unique_ptr<AudioManagerAccessor> audio_manager_accessor_;
const bool device_notifier_enabled_; const bool enable_remote_client_support_;
std::unique_ptr<base::SystemMonitor> system_monitor_; std::unique_ptr<base::SystemMonitor> system_monitor_;
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
std::unique_ptr<media::AudioDeviceListenerMac> audio_device_listener_mac_; std::unique_ptr<media::AudioDeviceListenerMac> audio_device_listener_mac_;
...@@ -112,6 +122,7 @@ class Service : public service_manager::Service { ...@@ -112,6 +122,7 @@ class Service : public service_manager::Service {
std::unique_ptr<DebugRecording> debug_recording_; std::unique_ptr<DebugRecording> debug_recording_;
base::Optional<StreamFactory> stream_factory_; base::Optional<StreamFactory> stream_factory_;
std::unique_ptr<DeviceNotifier> device_notifier_; std::unique_ptr<DeviceNotifier> device_notifier_;
std::unique_ptr<LogFactoryManager> log_factory_manager_;
std::unique_ptr<ServiceMetrics> metrics_; std::unique_ptr<ServiceMetrics> metrics_;
std::unique_ptr<service_manager::BinderRegistry> registry_; std::unique_ptr<service_manager::BinderRegistry> registry_;
......
...@@ -69,7 +69,7 @@ std::unique_ptr<service_manager::Service> CreateStandaloneService( ...@@ -69,7 +69,7 @@ std::unique_ptr<service_manager::Service> CreateStandaloneService(
return std::make_unique<Service>( return std::make_unique<Service>(
std::make_unique<audio::OwningAudioManagerAccessor>( std::make_unique<audio::OwningAudioManagerAccessor>(
base::BindOnce(&media::AudioManager::Create)), base::BindOnce(&media::AudioManager::Create)),
GetQuitTimeout(), true /* enable_device_notifications */, GetQuitTimeout(), true /* enable_remote_client_support */,
std::move(registry)); std::move(registry));
} }
......
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