Reland: Pass task runners to AudioManager constructor.
This patch replaces the internal AudioManagerBase::audio_thread with
an external task runner. The old implementation made it harder to test
and override the internal audio thread.
AudioManagerBase::Shutdown had to complete on the audio thread before
the AudioManager instance could be deleted. It relied on Thread::Stop
on the main thread to wait for the audio thread to shutdown. A subclass
using a different thread shared with other modules could not do that.
Passing a task runner into AudioManager and making GetTaskRunner
non-virtual ensures that the task runner will not change for the
lifetime of AudioManager instance.
BUG=594234
TBR=rkc,tommi,xhwang,jam,dalecurtis
Review URL: https://codereview.chromium.org/1894373002
Cr-Commit-Position: refs/heads/master@{#388211}
diff --git a/chromecast/media/audio/cast_audio_manager.cc b/chromecast/media/audio/cast_audio_manager.cc
index b098b56..e3b56d9 100644
--- a/chromecast/media/audio/cast_audio_manager.cc
+++ b/chromecast/media/audio/cast_audio_manager.cc
@@ -25,10 +25,15 @@
namespace chromecast {
namespace media {
-CastAudioManager::CastAudioManager(::media::AudioLogFactory* audio_log_factory,
- MediaPipelineBackendManager* backend_manager)
- : AudioManagerBase(audio_log_factory), backend_manager_(backend_manager) {
-}
+CastAudioManager::CastAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ ::media::AudioLogFactory* audio_log_factory,
+ MediaPipelineBackendManager* backend_manager)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory),
+ backend_manager_(backend_manager) {}
CastAudioManager::~CastAudioManager() {
Shutdown();
diff --git a/chromecast/media/audio/cast_audio_manager.h b/chromecast/media/audio/cast_audio_manager.h
index 97e3e3cf..572b99fe 100644
--- a/chromecast/media/audio/cast_audio_manager.h
+++ b/chromecast/media/audio/cast_audio_manager.h
@@ -20,9 +20,11 @@
class CastAudioManager : public ::media::AudioManagerBase {
public:
- CastAudioManager(::media::AudioLogFactory* audio_log_factory,
- MediaPipelineBackendManager* backend_manager);
- ~CastAudioManager() override;
+ CastAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ ::media::AudioLogFactory* audio_log_factory,
+ MediaPipelineBackendManager* backend_manager);
// AudioManager implementation.
bool HasAudioOutputDevices() override;
@@ -38,6 +40,9 @@
virtual std::unique_ptr<MediaPipelineBackend> CreateMediaPipelineBackend(
const MediaPipelineDeviceParams& params);
+ protected:
+ ~CastAudioManager() override;
+
private:
// AudioManagerBase implementation.
::media::AudioOutputStream* MakeLinearOutputStream(
diff --git a/chromecast/media/audio/cast_audio_manager_factory.cc b/chromecast/media/audio/cast_audio_manager_factory.cc
index c932c4b..c6b7794 100644
--- a/chromecast/media/audio/cast_audio_manager_factory.cc
+++ b/chromecast/media/audio/cast_audio_manager_factory.cc
@@ -17,9 +17,15 @@
CastAudioManagerFactory::~CastAudioManagerFactory() {}
-::media::AudioManager* CastAudioManagerFactory::CreateInstance(
+scoped_ptr<::media::AudioManager, ::media::AudioManagerDeleter>
+CastAudioManagerFactory::CreateInstance(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
::media::AudioLogFactory* audio_log_factory) {
- return new CastAudioManager(audio_log_factory, backend_manager_);
+ return scoped_ptr<::media::AudioManager, ::media::AudioManagerDeleter>(
+ new CastAudioManager(std::move(task_runner),
+ std::move(worker_task_runner), audio_log_factory,
+ backend_manager_));
}
} // namespace media
diff --git a/chromecast/media/audio/cast_audio_manager_factory.h b/chromecast/media/audio/cast_audio_manager_factory.h
index 627a68d..d80cc84 100644
--- a/chromecast/media/audio/cast_audio_manager_factory.h
+++ b/chromecast/media/audio/cast_audio_manager_factory.h
@@ -20,8 +20,10 @@
~CastAudioManagerFactory() override;
// ::media::AudioManagerFactory overrides.
- ::media::AudioManager* CreateInstance(
- ::media::AudioLogFactory* audio_log_factory) override;
+ scoped_ptr<::media::AudioManager, ::media::AudioManagerDeleter>
+ CreateInstance(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ ::media::AudioLogFactory* audio_log_factory) override;
private:
MediaPipelineBackendManager* const backend_manager_;
diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
index d529077..67bf295 100644
--- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc
+++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
@@ -10,7 +10,9 @@
#include "base/bind.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/thread_task_runner_handle.h"
#include "chromecast/base/metrics/cast_metrics_test_helper.h"
#include "chromecast/media/audio/cast_audio_manager.h"
#include "chromecast/media/base/media_message_loop.h"
@@ -184,8 +186,9 @@
class FakeAudioManager : public CastAudioManager {
public:
- FakeAudioManager()
- : CastAudioManager(nullptr, nullptr), media_pipeline_backend_(nullptr) {}
+ FakeAudioManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : CastAudioManager(task_runner, task_runner, nullptr, nullptr),
+ media_pipeline_backend_(nullptr) {}
~FakeAudioManager() override {}
// CastAudioManager overrides.
@@ -231,9 +234,9 @@
void SetUp() override {
metrics::InitializeMetricsHelperForTesting();
- audio_manager_.reset(new FakeAudioManager);
- audio_task_runner_ = audio_manager_->GetTaskRunner();
+ audio_task_runner_ = base::ThreadTaskRunnerHandle::Get();
backend_task_runner_ = media::MediaMessageLoop::GetTaskRunner();
+ audio_manager_.reset(new FakeAudioManager(audio_task_runner_));
}
void TearDown() override {
@@ -256,107 +259,68 @@
// Synchronous utility functions.
::media::AudioOutputStream* CreateStream() {
- ::media::AudioOutputStream* stream = nullptr;
-
- base::WaitableEvent completion_event(false, false);
- audio_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&CastAudioOutputStreamTest::CreateStreamOnAudioThread,
- base::Unretained(this), GetAudioParams(), &stream,
- &completion_event));
- completion_event.Wait();
-
- return stream;
+ return audio_manager_->MakeAudioOutputStream(GetAudioParams(),
+ kDefaultDeviceId);
}
bool OpenStream(::media::AudioOutputStream* stream) {
- DCHECK(stream);
-
- bool success = false;
- base::WaitableEvent completion_event(false, false);
- audio_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&CastAudioOutputStreamTest::OpenStreamOnAudioThread,
- base::Unretained(this), stream, &success,
- &completion_event));
- completion_event.Wait();
-
+ bool success = stream->Open();
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
return success;
}
void CloseStream(::media::AudioOutputStream* stream) {
- audio_task_runner_->PostTask(FROM_HERE,
- base::Bind(&::media::AudioOutputStream::Close,
- base::Unretained(stream)));
- RunUntilIdle(audio_task_runner_.get());
+ stream->Close();
RunUntilIdle(backend_task_runner_.get());
// Backend task runner may have posted more tasks to the audio task runner.
// So we need to drain it once more.
- RunUntilIdle(audio_task_runner_.get());
+ message_loop_.RunUntilIdle();
}
void StartStream(
::media::AudioOutputStream* stream,
::media::AudioOutputStream::AudioSourceCallback* source_callback) {
- audio_task_runner_->PostTask(
- FROM_HERE, base::Bind(&::media::AudioOutputStream::Start,
- base::Unretained(stream), source_callback));
- // Drain the audio task runner twice so that tasks posted by
+ stream->Start(source_callback);
+ // Drain the audio task runner so that tasks posted by
// media::AudioOutputStream::Start are run as well.
- RunUntilIdle(audio_task_runner_.get());
- RunUntilIdle(audio_task_runner_.get());
+ message_loop_.RunUntilIdle();
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
// Drain the audio task runner again to run the tasks posted by the
// backend on audio task runner.
- RunUntilIdle(audio_task_runner_.get());
+ message_loop_.RunUntilIdle();
}
void StopStream(::media::AudioOutputStream* stream) {
- audio_task_runner_->PostTask(FROM_HERE,
- base::Bind(&::media::AudioOutputStream::Stop,
- base::Unretained(stream)));
- RunUntilIdle(audio_task_runner_.get());
+ stream->Stop();
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
}
void SetStreamVolume(::media::AudioOutputStream* stream, double volume) {
- audio_task_runner_->PostTask(
- FROM_HERE, base::Bind(&::media::AudioOutputStream::SetVolume,
- base::Unretained(stream), volume));
- RunUntilIdle(audio_task_runner_.get());
+ stream->SetVolume(volume);
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
}
double GetStreamVolume(::media::AudioOutputStream* stream) {
double volume = 0.0;
- audio_task_runner_->PostTask(
- FROM_HERE, base::Bind(&::media::AudioOutputStream::GetVolume,
- base::Unretained(stream), &volume));
- RunUntilIdle(audio_task_runner_.get());
+ stream->GetVolume(&volume);
// No need to drain the backend task runner because getting the volume
// does not involve posting any task to the backend.
return volume;
}
- void CreateStreamOnAudioThread(const ::media::AudioParameters& audio_params,
- ::media::AudioOutputStream** stream,
- base::WaitableEvent* completion_event) {
- DCHECK(audio_task_runner_->BelongsToCurrentThread());
- *stream = audio_manager_->MakeAudioOutputStream(GetAudioParams(),
- kDefaultDeviceId);
- completion_event->Signal();
- }
- void OpenStreamOnAudioThread(::media::AudioOutputStream* stream,
- bool* success,
- base::WaitableEvent* completion_event) {
- DCHECK(audio_task_runner_->BelongsToCurrentThread());
- *success = stream->Open();
- completion_event->Signal();
+ void RunAudioLoopFor(int frames) {
+ ::media::AudioParameters audio_params = GetAudioParams();
+ base::TimeDelta duration = audio_params.GetBufferDuration() * frames;
+
+ base::RunLoop run_loop;
+ message_loop_.task_runner()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), duration);
+ run_loop.Run();
}
+ base::MessageLoop message_loop_;
std::unique_ptr<FakeAudioManager> audio_manager_;
scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_;
@@ -476,6 +440,7 @@
std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback);
StartStream(stream, source_callback.get());
+ RunAudioLoopFor(2);
StopStream(stream);
// Verify that the stream pushed frames to the backend.
@@ -518,10 +483,7 @@
// Sleep for a few frames and verify that more frames were not pushed
// because the backend device was busy.
- ::media::AudioParameters audio_params = GetAudioParams();
- base::TimeDelta pause = audio_params.GetBufferDuration() * 5;
- base::PlatformThread::Sleep(pause);
- RunUntilIdle(audio_task_runner_.get());
+ RunAudioLoopFor(5);
RunUntilIdle(backend_task_runner_.get());
EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
@@ -532,9 +494,7 @@
base::Bind(&FakeAudioDecoder::set_pipeline_status,
base::Unretained(audio_decoder),
FakeAudioDecoder::PIPELINE_STATUS_OK));
-
- base::PlatformThread::Sleep(pause);
- RunUntilIdle(audio_task_runner_.get());
+ RunAudioLoopFor(5);
RunUntilIdle(backend_task_runner_.get());
EXPECT_LT(1u, audio_decoder->pushed_buffer_count());
EXPECT_FALSE(source_callback->error());
@@ -555,6 +515,7 @@
std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback);
StartStream(stream, source_callback.get());
+ RunAudioLoopFor(2);
// Make sure that AudioOutputStream attempted to push the initial frame.
EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
@@ -578,6 +539,7 @@
std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback);
StartStream(stream, source_callback.get());
+ RunAudioLoopFor(5);
// Make sure that one frame was pushed.
EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
@@ -590,7 +552,7 @@
base::Unretained(audio_decoder),
FakeAudioDecoder::PIPELINE_STATUS_OK));
- RunUntilIdle(audio_task_runner_.get());
+ RunAudioLoopFor(5);
RunUntilIdle(backend_task_runner_.get());
// AudioOutputStream must report error to source callback.
EXPECT_TRUE(source_callback->error());
@@ -625,16 +587,11 @@
std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback);
- audio_task_runner_->PostTask(
- FROM_HERE, base::Bind(&::media::AudioOutputStream::Start,
- base::Unretained(stream), source_callback.get()));
- audio_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&::media::AudioOutputStream::Stop, base::Unretained(stream)));
- audio_task_runner_->PostTask(
- FROM_HERE, base::Bind(&::media::AudioOutputStream::Start,
- base::Unretained(stream), source_callback.get()));
- RunUntilIdle(audio_task_runner_.get());
+ stream->Start(source_callback.get());
+ RunAudioLoopFor(2);
+ stream->Stop();
+ stream->Start(source_callback.get());
+ RunAudioLoopFor(2);
RunUntilIdle(backend_task_runner_.get());
FakeAudioDecoder* audio_device = GetAudio();
diff --git a/components/audio_modem/BUILD.gn b/components/audio_modem/BUILD.gn
index d14a7b3..83cd882 100644
--- a/components/audio_modem/BUILD.gn
+++ b/components/audio_modem/BUILD.gn
@@ -63,6 +63,7 @@
deps = [
":test_support",
"//base",
+ "//base/test:test_support",
"//content/test:test_support",
"//media",
"//media:shared_memory_support",
diff --git a/components/audio_modem/audio_player_impl.cc b/components/audio_modem/audio_player_impl.cc
index cd52f05..2a02f5a 100644
--- a/components/audio_modem/audio_player_impl.cc
+++ b/components/audio_modem/audio_player_impl.cc
@@ -8,11 +8,9 @@
#include <string>
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/location.h"
#include "base/logging.h"
-#include "base/run_loop.h"
#include "components/audio_modem/public/audio_modem_types.h"
-#include "content/public/browser/browser_thread.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
@@ -162,19 +160,4 @@
base::Unretained(this)));
}
-void AudioPlayerImpl::FlushAudioLoopForTesting() {
- if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread())
- return;
-
- // Queue task on the audio thread, when it is executed, that means we've
- // successfully executed all the tasks before us.
- base::RunLoop rl;
- media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&AudioPlayerImpl::FlushAudioLoopForTesting),
- base::Unretained(this)),
- rl.QuitClosure());
- rl.Run();
-}
-
} // namespace audio_modem
diff --git a/components/audio_modem/audio_player_impl.h b/components/audio_modem/audio_player_impl.h
index 7ea518b..50f10bf 100644
--- a/components/audio_modem/audio_player_impl.h
+++ b/components/audio_modem/audio_player_impl.h
@@ -65,10 +65,6 @@
uint32_t frames_skipped) override;
void OnError(media::AudioOutputStream* stream) override;
- // Flushes the audio loop, making sure that any queued operations are
- // performed.
- void FlushAudioLoopForTesting();
-
bool is_playing_;
// Self-deleting object.
diff --git a/components/audio_modem/audio_player_unittest.cc b/components/audio_modem/audio_player_unittest.cc
index 153e6c0..2a96c0f9 100644
--- a/components/audio_modem/audio_player_unittest.cc
+++ b/components/audio_modem/audio_player_unittest.cc
@@ -8,11 +8,12 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
+#include "base/run_loop.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "components/audio_modem/audio_player_impl.h"
#include "components/audio_modem/public/audio_modem_types.h"
#include "components/audio_modem/test/random_samples.h"
-#include "media/audio/audio_manager.h"
#include "media/audio/audio_manager_base.h"
#include "media/base/audio_bus.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -77,8 +78,9 @@
public base::SupportsWeakPtr<AudioPlayerTest> {
public:
AudioPlayerTest() : buffer_index_(0), player_(nullptr) {
- if (!media::AudioManager::Get())
- media::AudioManager::CreateForTesting();
+ audio_manager_ = media::AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get());
+ base::RunLoop().RunUntilIdle();
}
~AudioPlayerTest() override { DeletePlayer(); }
@@ -91,6 +93,7 @@
kMaxFrameCount,
base::Bind(&AudioPlayerTest::GatherSamples, AsWeakPtr())));
player_->Initialize();
+ base::RunLoop().RunUntilIdle();
}
void DeletePlayer() {
@@ -98,6 +101,7 @@
return;
player_->Finalize();
player_ = nullptr;
+ base::RunLoop().RunUntilIdle();
}
void PlayAndVerifySamples(
@@ -107,8 +111,8 @@
buffer_ = media::AudioBus::Create(1, kMaxFrameCount);
buffer_index_ = 0;
player_->Play(samples);
- player_->FlushAudioLoopForTesting();
player_->Stop();
+ base::RunLoop().RunUntilIdle();
int differences = 0;
for (int i = 0; i < kMaxFrameCount; ++i) {
@@ -129,19 +133,20 @@
protected:
bool IsPlaying() {
- player_->FlushAudioLoopForTesting();
+ base::RunLoop().RunUntilIdle();
return player_->is_playing_;
}
static const int kDefaultFrameCount = 1024;
static const int kMaxFrameCount = 1024 * 100;
+ base::TestMessageLoop message_loop_;
+ media::ScopedAudioManagerPtr audio_manager_;
scoped_ptr<media::AudioBus> buffer_;
int buffer_index_;
// Deleted by calling Finalize() on the object.
AudioPlayerImpl* player_;
- base::MessageLoop message_loop_;
};
TEST_F(AudioPlayerTest, BasicPlayAndStop) {
@@ -151,16 +156,19 @@
player_->Play(samples);
EXPECT_TRUE(IsPlaying());
+
player_->Stop();
EXPECT_FALSE(IsPlaying());
- player_->Play(samples);
+ player_->Play(samples);
EXPECT_TRUE(IsPlaying());
+
player_->Stop();
EXPECT_FALSE(IsPlaying());
- player_->Play(samples);
+ player_->Play(samples);
EXPECT_TRUE(IsPlaying());
+
player_->Stop();
EXPECT_FALSE(IsPlaying());
diff --git a/components/audio_modem/audio_recorder_impl.cc b/components/audio_modem/audio_recorder_impl.cc
index 8d1b2c5..06bc728 100644
--- a/components/audio_modem/audio_recorder_impl.cc
+++ b/components/audio_modem/audio_recorder_impl.cc
@@ -198,20 +198,4 @@
base::Unretained(this)));
}
-void AudioRecorderImpl::FlushAudioLoopForTesting() {
- if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread())
- return;
-
- // Queue task on the audio thread, when it is executed, that means we've
- // successfully executed all the tasks before us.
- base::RunLoop rl;
- media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(
- base::IgnoreResult(&AudioRecorderImpl::FlushAudioLoopForTesting),
- base::Unretained(this)),
- rl.QuitClosure());
- rl.Run();
-}
-
} // namespace audio_modem
diff --git a/components/audio_modem/audio_recorder_impl.h b/components/audio_modem/audio_recorder_impl.h
index cce75fb..b0f5486 100644
--- a/components/audio_modem/audio_recorder_impl.h
+++ b/components/audio_modem/audio_recorder_impl.h
@@ -79,10 +79,6 @@
double volume) override;
void OnError(media::AudioInputStream* stream) override;
- // Flushes the audio loop, making sure that any queued operations are
- // performed.
- void FlushAudioLoopForTesting();
-
bool is_recording_;
media::AudioInputStream* stream_;
diff --git a/components/audio_modem/audio_recorder_unittest.cc b/components/audio_modem/audio_recorder_unittest.cc
index e960cd389..08b9a52 100644
--- a/components/audio_modem/audio_recorder_unittest.cc
+++ b/components/audio_modem/audio_recorder_unittest.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/aligned_memory.h"
#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/audio_modem/audio_recorder_impl.h"
#include "components/audio_modem/public/audio_modem_types.h"
@@ -82,8 +83,9 @@
class AudioRecorderTest : public testing::Test {
public:
AudioRecorderTest() : total_samples_(0), recorder_(nullptr) {
- if (!media::AudioManager::Get())
- media::AudioManager::CreateForTesting();
+ audio_manager_ = media::AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get());
+ base::RunLoop().RunUntilIdle();
}
~AudioRecorderTest() override {
@@ -101,6 +103,7 @@
recorder_ = new AudioRecorderImpl();
recorder_->Initialize(base::Bind(&AudioRecorderTest::DecodeSamples,
base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
} else {
CreateRecorder(kSomeNumber);
}
@@ -124,6 +127,7 @@
recorder_->set_params_for_testing(new media::AudioParameters(params_));
recorder_->Initialize(
base::Bind(&AudioRecorderTest::DecodeSamples, base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
}
void DeleteRecorder() {
@@ -131,6 +135,7 @@
return;
recorder_->Finalize();
recorder_ = nullptr;
+ base::RunLoop().RunUntilIdle();
}
void RecordAndVerifySamples() {
@@ -183,10 +188,13 @@
return samples;
}
bool IsRecording() {
- recorder_->FlushAudioLoopForTesting();
+ base::RunLoop().RunUntilIdle();
return recorder_->is_recording_;
}
+ content::TestBrowserThreadBundle thread_bundle_;
+ media::ScopedAudioManagerPtr audio_manager_;
+
std::vector<float*> channel_data_;
media::AudioParameters params_;
size_t total_samples_;
@@ -197,7 +205,6 @@
std::string received_samples_;
scoped_ptr<base::RunLoop> run_loop_;
- content::TestBrowserThreadBundle thread_bundle_;
};
@@ -213,16 +220,19 @@
recorder_->Record();
EXPECT_TRUE(IsRecording());
+
recorder_->Stop();
EXPECT_FALSE(IsRecording());
- recorder_->Record();
+ recorder_->Record();
EXPECT_TRUE(IsRecording());
+
recorder_->Stop();
EXPECT_FALSE(IsRecording());
- recorder_->Record();
+ recorder_->Record();
EXPECT_TRUE(IsRecording());
+
recorder_->Stop();
EXPECT_FALSE(IsRecording());
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index e96d2f92..bb67429 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -75,7 +75,6 @@
#include "content/public/common/result_codes.h"
#include "device/battery/battery_status_service.h"
#include "ipc/mojo/scoped_ipc_support.h"
-#include "media/audio/audio_manager.h"
#include "media/base/media.h"
#include "media/base/user_input_monitor.h"
#include "media/midi/midi_manager.h"
@@ -1226,8 +1225,7 @@
{
TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:AudioMan");
- audio_manager_.reset(media::AudioManager::CreateWithHangTimer(
- MediaInternals::GetInstance(), io_thread_->task_runner()));
+ CreateAudioManager();
}
{
@@ -1455,4 +1453,34 @@
base::Bind(OnStoppedStartupTracing, startup_trace_file_)));
}
+void BrowserMainLoop::CreateAudioManager() {
+ DCHECK(!audio_thread_);
+ DCHECK(!audio_manager_);
+ // TODO(alokp): Allow content embedders to override the default
+ // task runners by defining ContentBrowserClient::GetAudioTaskRunner.
+ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner;
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner;
+ scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner;
+ audio_thread_.reset(new base::Thread("AudioThread"));
+#if defined(OS_WIN)
+ audio_thread_->init_com_with_mta(true);
+#endif // defined(OS_WIN)
+ CHECK(audio_thread_->Start());
+#if defined(OS_MACOSX)
+ // On Mac audio task runner must belong to the main thread.
+ // See http://crbug.com/158170.
+ // Since the audio thread is the UI thread, a hang monitor is not
+ // necessary or recommended.
+ audio_task_runner = base::ThreadTaskRunnerHandle::Get();
+ worker_task_runner = audio_thread_->task_runner();
+#else
+ audio_task_runner = audio_thread_->task_runner();
+ worker_task_runner = audio_thread_->task_runner();
+ monitor_task_runner = io_thread_->task_runner();
+#endif // defined(OS_MACOSX)
+ audio_manager_ = media::AudioManager::Create(
+ std::move(audio_task_runner), std::move(worker_task_runner),
+ std::move(monitor_task_runner), MediaInternals::GetInstance());
+}
+
} // namespace content
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 7052211..4d344458 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -14,6 +14,7 @@
#include "build/build_config.h"
#include "content/browser/browser_process_sub_thread.h"
#include "content/public/browser/browser_main_runner.h"
+#include "media/audio/audio_manager.h"
#if defined(USE_AURA)
namespace aura {
@@ -39,7 +40,6 @@
}
namespace media {
-class AudioManager;
#if defined(OS_WIN)
class SystemMessageWindowWin;
#elif defined(OS_LINUX) && defined(USE_UDEV)
@@ -169,6 +169,7 @@
void InitStartupTracingForDuration(const base::CommandLine& command_line);
void EndStartupTracing();
+ void CreateAudioManager();
bool UsingInProcessGpu() const;
// Quick reference for initialization order:
@@ -260,7 +261,9 @@
// |user_input_monitor_| has to outlive |audio_manager_|, so declared first.
std::unique_ptr<media::UserInputMonitor> user_input_monitor_;
- std::unique_ptr<media::AudioManager> audio_manager_;
+ // AudioThread needs to outlive |audio_manager_|.
+ std::unique_ptr<base::Thread> audio_thread_;
+ media::ScopedAudioManagerPtr audio_manager_;
std::unique_ptr<media::midi::MidiManager> midi_manager_;
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index dd387bb..a465a63 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -13,11 +13,12 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/public/common/media_stream_request.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager_base.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -62,22 +63,16 @@
protected:
void SetUp() override {
- // The test must run on Browser::IO.
- message_loop_.reset(new base::MessageLoopForIO);
- io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
- message_loop_.get()));
- audio_manager_.reset(media::AudioManager::CreateForTesting());
- // Wait for audio thread initialization to complete. Otherwise the
- // enumeration type may not have been set yet.
- base::WaitableEvent event(false, false);
- audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &base::WaitableEvent::Signal, base::Unretained(&event)));
- event.Wait();
+ audio_manager_ = media::AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get());
+ // Flush the message loop to ensure proper initialization of AudioManager.
+ base::RunLoop().RunUntilIdle();
+
manager_ = new AudioInputDeviceManager(audio_manager_.get());
manager_->UseFakeDevice();
audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
manager_->Register(audio_input_listener_.get(),
- message_loop_->task_runner().get());
+ audio_manager_->GetTaskRunner());
// Gets the enumerated device list from the AudioInputDeviceManager.
manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
@@ -87,19 +82,17 @@
.WillOnce(SaveArg<1>(&devices_));
// Wait until we get the list.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
void TearDown() override {
manager_->Unregister();
- io_thread_.reset();
}
- std::unique_ptr<base::MessageLoop> message_loop_;
- std::unique_ptr<BrowserThreadImpl> io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
scoped_refptr<AudioInputDeviceManager> manager_;
std::unique_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_;
- std::unique_ptr<media::AudioManager> audio_manager_;
+ media::ScopedAudioManagerPtr audio_manager_;
StreamDeviceInfoArray devices_;
private:
@@ -123,7 +116,7 @@
Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
.Times(1);
// Waits for the callback.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
manager_->Close(session_id);
EXPECT_CALL(*audio_input_listener_,
@@ -131,7 +124,7 @@
.Times(1);
// Waits for the callback.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
}
@@ -156,7 +149,7 @@
.Times(1);
// Waits for the callback.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
// Checks if the session_ids are unique.
@@ -174,7 +167,7 @@
.Times(1);
// Waits for the callback.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
}
@@ -196,7 +189,7 @@
.Times(1);
// Waits for the callback.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
// Opens default device twice.
@@ -218,7 +211,7 @@
Opened(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id))
.Times(1);
// Waits for the callback.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
manager_->Close(first_session_id);
manager_->Close(second_session_id);
@@ -229,7 +222,7 @@
Closed(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id))
.Times(1);
// Waits for the callback.
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
// Accesses then closes the sessions after opening the devices.
@@ -251,7 +244,7 @@
EXPECT_CALL(*audio_input_listener_,
Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index]))
.Times(1);
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
const StreamDeviceInfo* info = manager_->GetOpenedDeviceInfoById(
session_id[index]);
@@ -261,7 +254,7 @@
EXPECT_CALL(*audio_input_listener_,
Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index]))
.Times(1);
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
}
@@ -275,7 +268,7 @@
EXPECT_CALL(*audio_input_listener_,
Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
.Times(1);
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Access a non-opened device.
// This should fail and return an empty StreamDeviceInfo.
@@ -288,7 +281,7 @@
EXPECT_CALL(*audio_input_listener_,
Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
.Times(1);
- message_loop_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
} // namespace content
diff --git a/content/browser/renderer_host/media/audio_output_device_enumerator.cc b/content/browser/renderer_host/media/audio_output_device_enumerator.cc
index 24ef8f9e..9c469c60 100644
--- a/content/browser/renderer_host/media/audio_output_device_enumerator.cc
+++ b/content/browser/renderer_host/media/audio_output_device_enumerator.cc
@@ -117,7 +117,7 @@
is_enumeration_ongoing_ = true;
seq_last_enumeration_ = NewEventSequence();
base::PostTaskAndReplyWithResult(
- audio_manager_->GetTaskRunner().get(), FROM_HERE,
+ audio_manager_->GetTaskRunner(), FROM_HERE,
base::Bind(&EnumerateDevicesOnDeviceThread, audio_manager_),
base::Bind(&AudioOutputDeviceEnumerator::DevicesEnumerated,
weak_factory_.GetWeakPtr()));
diff --git a/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc b/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc
index f84f87e..c84a684 100644
--- a/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc
+++ b/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -31,7 +30,10 @@
class MockAudioManager : public media::FakeAudioManager {
public:
MockAudioManager(size_t num_devices)
- : FakeAudioManager(&fake_audio_log_factory_), num_devices_(num_devices) {}
+ : FakeAudioManager(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ &fake_audio_log_factory_),
+ num_devices_(num_devices) {}
MockAudioManager() : MockAudioManager(0) {}
~MockAudioManager() override {}
@@ -81,9 +83,7 @@
class AudioOutputDeviceEnumeratorTest : public ::testing::Test {
public:
- AudioOutputDeviceEnumeratorTest()
- : thread_bundle_(), task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
-
+ AudioOutputDeviceEnumeratorTest() {}
~AudioOutputDeviceEnumeratorTest() override {}
MOCK_METHOD1(MockCallback, void(const AudioOutputDeviceEnumeration&));
@@ -110,18 +110,19 @@
const AudioOutputDeviceEnumeration& result) {
EXPECT_EQ(actual_devices_expected, result.has_actual_devices);
EXPECT_EQ(num_entries_expected, result.devices.size());
- task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop_.QuitClosure());
}
void QuitCallback(const AudioOutputDeviceEnumeration& result) {
MockCallback(result);
- task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop_.QuitClosure());
}
protected:
- std::unique_ptr<MockAudioManager> audio_manager_;
TestBrowserThreadBundle thread_bundle_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ std::unique_ptr<MockAudioManager, media::AudioManagerDeleter> audio_manager_;
base::RunLoop run_loop_;
private:
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index ae58022..1d72170 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -484,7 +484,7 @@
!media_stream_manager_->audio_output_device_enumerator()
->IsCacheEnabled()) {
base::PostTaskAndReplyWithResult(
- audio_manager_->GetTaskRunner().get(), FROM_HERE,
+ audio_manager_->GetTaskRunner(), FROM_HERE,
base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_),
base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id,
true));
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index a0cdfdb4..467e2be 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -187,7 +187,8 @@
class AudioRendererHostTest : public testing::Test {
public:
AudioRendererHostTest() {
- audio_manager_.reset(media::AudioManager::CreateForTesting());
+ audio_manager_ = media::AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get());
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
@@ -328,7 +329,7 @@
// TestBrowserThreadBundle.
std::unique_ptr<MediaStreamManager> media_stream_manager_;
TestBrowserThreadBundle thread_bundle_;
- std::unique_ptr<media::AudioManager> audio_manager_;
+ media::ScopedAudioManagerPtr audio_manager_;
MockAudioMirroringManager mirroring_manager_;
scoped_refptr<MockAudioRendererHost> host_;
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 0c18286..5560d0e 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -225,8 +225,8 @@
class MediaStreamDispatcherHostTest : public testing::Test {
public:
MediaStreamDispatcherHostTest()
- : old_browser_client_(NULL),
- thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ old_browser_client_(NULL),
origin_("https://test.com") {
audio_manager_.reset(
new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get()));
@@ -422,12 +422,13 @@
}
scoped_refptr<MockMediaStreamDispatcherHost> host_;
- std::unique_ptr<media::AudioManager> audio_manager_;
std::unique_ptr<MediaStreamManager> media_stream_manager_;
+ content::TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<media::AudioManager, media::AudioManagerDeleter>
+ audio_manager_;
MockMediaStreamUIProxy* stream_ui_;
ContentBrowserClient* old_browser_client_;
std::unique_ptr<ContentClient> content_client_;
- content::TestBrowserThreadBundle thread_bundle_;
content::TestBrowserContext browser_context_;
media::AudioDeviceNames physical_audio_devices_;
media::VideoCaptureDevice::Names physical_video_devices_;
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 34f2edaf..7b75f93 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -1128,7 +1128,7 @@
// its task runner, and MediaStreamManager is deleted on the UI thread,
// after the IO thread has been stopped.
base::PostTaskAndReplyWithResult(
- audio_manager_->GetTaskRunner().get(), FROM_HERE,
+ audio_manager_->GetTaskRunner(), FROM_HERE,
base::Bind(&media::AudioManager::GetDefaultOutputStreamParameters,
base::Unretained(audio_manager_)),
base::Bind(&MediaStreamManager::PostRequestToUI, base::Unretained(this),
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index ff2fada..6e7bec31 100644
--- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -11,7 +11,6 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
@@ -72,7 +71,9 @@
class MockAudioManager : public AudioManagerPlatform {
public:
MockAudioManager()
- : AudioManagerPlatform(&fake_audio_log_factory_),
+ : AudioManagerPlatform(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ &fake_audio_log_factory_),
num_output_devices_(2) {}
~MockAudioManager() override {}
@@ -176,21 +177,21 @@
class MediaStreamManagerTest : public ::testing::Test {
public:
MediaStreamManagerTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- task_runner_(base::ThreadTaskRunnerHandle::Get()) {
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
audio_manager_.reset(new MockAudioManager());
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
-}
-
- virtual ~MediaStreamManagerTest() {
+ base::RunLoop().RunUntilIdle();
}
+ ~MediaStreamManagerTest() override {}
+
MOCK_METHOD1(Response, void(int index));
void ResponseCallback(int index,
const MediaStreamDevices& devices,
std::unique_ptr<MediaStreamUIProxy> ui_proxy) {
Response(index);
- task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop_.QuitClosure());
}
protected:
@@ -208,10 +209,12 @@
security_origin, callback);
}
- std::unique_ptr<MockAudioManager> audio_manager_;
+ // media_stream_manager_ needs to outlive thread_bundle_ because it is a
+ // MessageLoop::DestructionObserver. audio_manager_ needs to outlive
+ // thread_bundle_ because it uses the underlying message loop.
std::unique_ptr<MediaStreamManager> media_stream_manager_;
content::TestBrowserThreadBundle thread_bundle_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ std::unique_ptr<MockAudioManager, media::AudioManagerDeleter> audio_manager_;
base::RunLoop run_loop_;
private:
@@ -231,7 +234,6 @@
// No callback is expected.
media_stream_manager_->CancelRequest(label);
run_loop_.RunUntilIdle();
- media_stream_manager_->WillDestroyCurrentMessageLoop();
}
TEST_F(MediaStreamManagerTest, MakeMultipleRequests) {
diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc
index 933c58d..a5f56706 100644
--- a/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -274,7 +274,7 @@
#endif
// Create our own MediaStreamManager.
- audio_manager_.reset(media::AudioManager::CreateForTesting());
+ audio_manager_ = media::AudioManager::CreateForTesting(task_runner_);
#ifndef TEST_REAL_CAPTURE_DEVICE
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
@@ -483,10 +483,13 @@
scoped_refptr<MockVideoCaptureHost> host_;
private:
+ // media_stream_manager_ needs to outlive thread_bundle_ because it is a
+ // MessageLoop::DestructionObserver. audio_manager_ needs to outlive
+ // thread_bundle_ because it uses the underlying message loop.
StrictMock<MockMediaStreamRequester> stream_requester_;
- std::unique_ptr<media::AudioManager> audio_manager_;
std::unique_ptr<MediaStreamManager> media_stream_manager_;
content::TestBrowserThreadBundle thread_bundle_;
+ media::ScopedAudioManagerPtr audio_manager_;
content::TestBrowserContext browser_context_;
content::TestContentBrowserClient browser_client_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 4be8b4b..4c06ff0 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -247,7 +247,7 @@
#endif
// Always query audio device parameters on the audio thread.
if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
- return audio_manager_->GetTaskRunner().get();
+ return audio_manager_->GetTaskRunner();
return NULL;
}
diff --git a/content/browser/speech/speech_recognizer_impl_unittest.cc b/content/browser/speech/speech_recognizer_impl_unittest.cc
index 38f66d1..1675e2e6 100644
--- a/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -8,11 +8,11 @@
#include <vector>
#include "base/sys_byteorder.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognizer_impl.h"
#include "content/public/browser/speech_recognition_event_listener.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
@@ -26,7 +26,6 @@
using media::AudioInputController;
using media::AudioInputStream;
-using media::AudioManager;
using media::AudioOutputStream;
using media::AudioParameters;
using media::TestAudioInputController;
@@ -38,8 +37,7 @@
public testing::Test {
public:
SpeechRecognizerImplTest()
- : io_thread_(BrowserThread::IO, &message_loop_),
- recognition_started_(false),
+ : recognition_started_(false),
recognition_ended_(false),
result_received_(false),
audio_started_(false),
@@ -184,10 +182,9 @@
}
protected:
- base::MessageLoopForIO message_loop_;
- BrowserThreadImpl io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
scoped_refptr<SpeechRecognizerImpl> recognizer_;
- std::unique_ptr<AudioManager> audio_manager_;
+ media::ScopedAudioManagerPtr audio_manager_;
bool recognition_started_;
bool recognition_ended_;
bool result_received_;
diff --git a/media/audio/alsa/alsa_output_unittest.cc b/media/audio/alsa/alsa_output_unittest.cc
index 1b13863..acf6d28 100644
--- a/media/audio/alsa/alsa_output_unittest.cc
+++ b/media/audio/alsa/alsa_output_unittest.cc
@@ -5,7 +5,10 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "media/audio/alsa/alsa_output.h"
#include "media/audio/alsa/alsa_wrapper.h"
#include "media/audio/alsa/audio_manager_alsa.h"
@@ -72,7 +75,10 @@
class MockAudioManagerAlsa : public AudioManagerAlsa {
public:
- MockAudioManagerAlsa() : AudioManagerAlsa(&fake_audio_log_factory_) {}
+ MockAudioManagerAlsa()
+ : AudioManagerAlsa(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ &fake_audio_log_factory_) {}
MOCK_METHOD0(Init, void());
MOCK_METHOD0(HasAudioOutputDevices, bool());
MOCK_METHOD0(HasAudioInputDevices, bool());
@@ -93,12 +99,6 @@
delete stream;
}
- // We don't mock this method since all tests will do the same thing
- // and use the current task runner.
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override {
- return base::MessageLoop::current()->task_runner();
- }
-
private:
FakeAudioLogFactory fake_audio_log_factory_;
};
@@ -168,9 +168,10 @@
static void* kFakeHints[];
static char kGenericSurround50[];
+ base::TestMessageLoop message_loop_;
StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
- scoped_ptr<StrictMock<MockAudioManagerAlsa> > mock_manager_;
- base::MessageLoop message_loop_;
+ std::unique_ptr<StrictMock<MockAudioManagerAlsa>, AudioManagerDeleter>
+ mock_manager_;
scoped_refptr<media::DataBuffer> packet_;
private:
@@ -442,7 +443,7 @@
// call Stop() immediately after to ensure we don't run the message loop
// forever.
test_stream->Stop();
- message_loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
.WillOnce(Return(0));
diff --git a/media/audio/alsa/audio_manager_alsa.cc b/media/audio/alsa/audio_manager_alsa.cc
index 5ddc425..80f8a21 100644
--- a/media/audio/alsa/audio_manager_alsa.cc
+++ b/media/audio/alsa/audio_manager_alsa.cc
@@ -86,8 +86,13 @@
return HasAnyAlsaAudioDevice(kStreamCapture);
}
-AudioManagerAlsa::AudioManagerAlsa(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory),
+AudioManagerAlsa::AudioManagerAlsa(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory),
wrapper_(new AlsaWrapper()) {
SetMaxOutputStreamsAllowed(kMaxOutputStreams);
}
diff --git a/media/audio/alsa/audio_manager_alsa.h b/media/audio/alsa/audio_manager_alsa.h
index d8410fd..5a6ebc1 100644
--- a/media/audio/alsa/audio_manager_alsa.h
+++ b/media/audio/alsa/audio_manager_alsa.h
@@ -18,7 +18,10 @@
class MEDIA_EXPORT AudioManagerAlsa : public AudioManagerBase {
public:
- AudioManagerAlsa(AudioLogFactory* audio_log_factory);
+ AudioManagerAlsa(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
static void ShowLinuxAudioInputSettings();
diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc
index a918a10..8079c166 100644
--- a/media/audio/android/audio_android_unittest.cc
+++ b/media/audio/android/audio_android_unittest.cc
@@ -415,11 +415,16 @@
public:
AudioAndroidOutputTest()
: loop_(new base::MessageLoopForUI()),
- audio_manager_(AudioManager::CreateForTesting()),
+ audio_manager_(AudioManager::CreateForTesting(loop_->task_runner())),
audio_output_stream_(NULL) {
+ // Flush the message loop to ensure that AudioManager is fully initialized.
+ loop_->RunUntilIdle();
}
- ~AudioAndroidOutputTest() override {}
+ ~AudioAndroidOutputTest() override {
+ audio_manager_.reset();
+ loop_->RunUntilIdle();
+ }
protected:
AudioManager* audio_manager() { return audio_manager_.get(); }
@@ -561,7 +566,7 @@
}
scoped_ptr<base::MessageLoopForUI> loop_;
- scoped_ptr<AudioManager> audio_manager_;
+ ScopedAudioManagerPtr audio_manager_;
AudioParameters audio_output_parameters_;
AudioOutputStream* audio_output_stream_;
base::TimeTicks start_time_;
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc
index 96a7c78..35534b3 100644
--- a/media/audio/android/audio_manager_android.cc
+++ b/media/audio/android/audio_manager_android.cc
@@ -45,12 +45,22 @@
} // namespace
-AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
- return new AudioManagerAndroid(audio_log_factory);
+ScopedAudioManagerPtr CreateAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory) {
+ return ScopedAudioManagerPtr(new AudioManagerAndroid(
+ std::move(task_runner), std::move(worker_task_runner),
+ audio_log_factory));
}
-AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory),
+AudioManagerAndroid::AudioManagerAndroid(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory),
communication_mode_is_on_(false),
output_volume_override_set_(false),
output_volume_override_(0) {
@@ -68,11 +78,13 @@
}
AudioManagerAndroid::~AudioManagerAndroid() {
- // It's safe to post a task here since Shutdown() will wait for all tasks to
- // complete before returning.
- GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &AudioManagerAndroid::ShutdownOnAudioThread, base::Unretained(this)));
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
Shutdown();
+
+ DVLOG(2) << "Destroying Java part of the audio manager";
+ Java_AudioManagerAndroid_close(base::android::AttachCurrentThread(),
+ j_audio_manager_.obj());
+ j_audio_manager_.Reset();
}
bool AudioManagerAndroid::HasAudioOutputDevices() {
@@ -337,15 +349,6 @@
j_audio_manager_.obj());
}
-void AudioManagerAndroid::ShutdownOnAudioThread() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- DVLOG(2) << "Destroying Java part of the audio manager";
- Java_AudioManagerAndroid_close(
- base::android::AttachCurrentThread(),
- j_audio_manager_.obj());
- j_audio_manager_.Reset();
-}
-
void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) {
Java_AudioManagerAndroid_setCommunicationAudioModeOn(
base::android::AttachCurrentThread(),
diff --git a/media/audio/android/audio_manager_android.h b/media/audio/android/audio_manager_android.h
index f9b7db25..22b48c8 100644
--- a/media/audio/android/audio_manager_android.h
+++ b/media/audio/android/audio_manager_android.h
@@ -20,7 +20,10 @@
// Android implemention of AudioManager.
class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase {
public:
- explicit AudioManagerAndroid(AudioLogFactory* audio_log_factory);
+ AudioManagerAndroid(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
// Implementation of AudioManager.
bool HasAudioOutputDevices() override;
@@ -71,7 +74,6 @@
private:
void InitializeOnAudioThread();
- void ShutdownOnAudioThread();
bool HasNoAudioInputStreams();
void SetCommunicationAudioModeOn(bool on);
diff --git a/media/audio/audio_input_controller_unittest.cc b/media/audio/audio_input_controller_unittest.cc
index 6a35d87..36ebc02c 100644
--- a/media/audio/audio_input_controller_unittest.cc
+++ b/media/audio/audio_input_controller_unittest.cc
@@ -67,11 +67,20 @@
// Test fixture.
class AudioInputControllerTest : public testing::Test {
public:
- AudioInputControllerTest() {}
- ~AudioInputControllerTest() override {}
+ AudioInputControllerTest()
+ : audio_manager_(
+ AudioManager::CreateForTesting(message_loop_.task_runner())) {
+ // Flush the message loop to ensure that AudioManager is fully initialized.
+ message_loop_.RunUntilIdle();
+ }
+ ~AudioInputControllerTest() override {
+ audio_manager_.reset();
+ message_loop_.RunUntilIdle();
+ }
protected:
base::MessageLoop message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
private:
DISALLOW_COPY_AND_ASSIGN(AudioInputControllerTest);
@@ -85,16 +94,12 @@
EXPECT_CALL(event_handler, OnCreated(NotNull()))
.WillOnce(QuitMessageLoop(&message_loop_));
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
AudioParameters params(AudioParameters::AUDIO_FAKE, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(audio_manager.get(),
- &event_handler,
- params,
- AudioManagerBase::kDefaultDeviceId,
- NULL);
+ AudioInputController::Create(audio_manager_.get(), &event_handler, params,
+ AudioManagerBase::kDefaultDeviceId, NULL);
ASSERT_TRUE(controller.get());
// Wait for OnCreated() to fire.
@@ -123,17 +128,13 @@
.WillRepeatedly(CheckCountAndPostQuitTask(
&count, 10, message_loop_.task_runner()));
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
AudioParameters params(AudioParameters::AUDIO_FAKE, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
// Creating the AudioInputController should render an OnCreated() call.
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(audio_manager.get(),
- &event_handler,
- params,
- AudioManagerBase::kDefaultDeviceId,
- NULL);
+ AudioInputController::Create(audio_manager_.get(), &event_handler, params,
+ AudioManagerBase::kDefaultDeviceId, NULL);
ASSERT_TRUE(controller.get());
// Start recording and trigger one OnRecording() call.
@@ -176,17 +177,13 @@
.Times(Exactly(1))
.WillOnce(QuitMessageLoop(&message_loop_));
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
AudioParameters params(AudioParameters::AUDIO_FAKE, kChannelLayout,
kSampleRate, kBitsPerSample, kSamplesPerPacket);
// Creating the AudioInputController should render an OnCreated() call.
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(audio_manager.get(),
- &event_handler,
- params,
- AudioManagerBase::kDefaultDeviceId,
- NULL);
+ AudioInputController::Create(audio_manager_.get(), &event_handler, params,
+ AudioManagerBase::kDefaultDeviceId, NULL);
ASSERT_TRUE(controller.get());
// Start recording and trigger one OnRecording() call.
@@ -213,18 +210,14 @@
EXPECT_CALL(event_handler, OnCreated(NotNull()))
.Times(Exactly(0));
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
AudioParameters params(AudioParameters::AUDIO_FAKE,
kChannelLayout,
kSampleRate,
kBitsPerSample,
kSamplesPerPacket * 1000);
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(audio_manager.get(),
- &event_handler,
- params,
- AudioManagerBase::kDefaultDeviceId,
- NULL);
+ AudioInputController::Create(audio_manager_.get(), &event_handler, params,
+ AudioManagerBase::kDefaultDeviceId, NULL);
ASSERT_FALSE(controller.get());
}
@@ -239,18 +232,14 @@
EXPECT_CALL(event_handler, OnRecording(NotNull()))
.Times(Exactly(1));
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
AudioParameters params(AudioParameters::AUDIO_FAKE,
kChannelLayout,
kSampleRate,
kBitsPerSample,
kSamplesPerPacket);
scoped_refptr<AudioInputController> controller =
- AudioInputController::Create(audio_manager.get(),
- &event_handler,
- params,
- AudioManagerBase::kDefaultDeviceId,
- NULL);
+ AudioInputController::Create(audio_manager_.get(), &event_handler, params,
+ AudioManagerBase::kDefaultDeviceId, NULL);
ASSERT_TRUE(controller.get());
controller->Record();
diff --git a/media/audio/audio_input_unittest.cc b/media/audio/audio_input_unittest.cc
index abb47ce..5d3ce9f 100644
--- a/media/audio/audio_input_unittest.cc
+++ b/media/audio/audio_input_unittest.cc
@@ -7,10 +7,9 @@
#include "base/bind.h"
#include "base/environment.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "media/audio/audio_io.h"
@@ -50,16 +49,16 @@
};
class AudioInputTest : public testing::Test {
- public:
- AudioInputTest() :
- message_loop_(base::MessageLoop::TYPE_UI),
- audio_manager_(AudioManager::CreateForTesting()),
- audio_input_stream_(NULL) {
- // Wait for the AudioManager to finish any initialization on the audio loop.
+ public:
+ AudioInputTest()
+ : message_loop_(base::MessageLoop::TYPE_UI),
+ audio_manager_(AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get())),
+ audio_input_stream_(NULL) {
base::RunLoop().RunUntilIdle();
}
- ~AudioInputTest() override { base::RunLoop().RunUntilIdle(); }
+ ~AudioInputTest() override {}
protected:
bool InputDevicesAvailable() {
@@ -144,29 +143,12 @@
// Synchronously runs the provided callback/closure on the audio thread.
void RunOnAudioThread(const base::Closure& closure) {
- if (!audio_manager_->GetTaskRunner()->BelongsToCurrentThread()) {
- base::WaitableEvent event(false, false);
- audio_manager_->GetTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&AudioInputTest::RunOnAudioThreadImpl,
- base::Unretained(this),
- closure,
- &event));
- event.Wait();
- } else {
- closure.Run();
- }
- }
-
- void RunOnAudioThreadImpl(const base::Closure& closure,
- base::WaitableEvent* event) {
DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
closure.Run();
- event->Signal();
}
- base::MessageLoop message_loop_;
- scoped_ptr<AudioManager> audio_manager_;
+ base::TestMessageLoop message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
AudioInputStream* audio_input_stream_;
private:
@@ -222,10 +204,11 @@
TestInputCallback test_callback;
OpenAndStartAudioInputStreamOnAudioThread(&test_callback);
- message_loop_.PostDelayedTask(FROM_HERE,
- base::MessageLoop::QuitWhenIdleClosure(),
- base::TimeDelta::FromMilliseconds(500));
- message_loop_.Run();
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(500));
+ run_loop.Run();
EXPECT_GE(test_callback.callback_count(), 2);
EXPECT_FALSE(test_callback.had_error());
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc
index 010b349..8a7728c 100644
--- a/media/audio/audio_low_latency_input_output_unittest.cc
+++ b/media/audio/audio_low_latency_input_output_unittest.cc
@@ -12,6 +12,7 @@
#include "base/path_service.h"
#include "base/synchronization/lock.h"
#include "base/test/test_timeouts.h"
+#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/audio/audio_io.h"
@@ -96,13 +97,12 @@
// the main thread instead of the audio thread.
class MockAudioManager : public AudioManagerAnyPlatform {
public:
- MockAudioManager() : AudioManagerAnyPlatform(&fake_audio_log_factory_) {}
+ MockAudioManager()
+ : AudioManagerAnyPlatform(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ &fake_audio_log_factory_) {}
~MockAudioManager() override {}
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override {
- return base::MessageLoop::current()->task_runner();
- }
-
private:
FakeAudioLogFactory fake_audio_log_factory_;
DISALLOW_COPY_AND_ASSIGN(MockAudioManager);
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc
index 5d5f3b3a..573102a0 100644
--- a/media/audio/audio_manager.cc
+++ b/media/audio/audio_manager.cc
@@ -69,30 +69,50 @@
AudioManagerHelper() {}
~AudioManagerHelper() override {}
- void HistogramThreadStatus(ThreadStatus status) {
- audio_thread_status_ = status;
- UMA_HISTOGRAM_ENUMERATION("Media.AudioThreadStatus", audio_thread_status_,
- THREAD_MAX + 1);
- }
-
void StartHangTimer(
- const scoped_refptr<base::SingleThreadTaskRunner>& monitor_task_runner) {
+ scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner) {
CHECK(!monitor_task_runner_);
- monitor_task_runner_ = monitor_task_runner;
+ CHECK(!audio_task_runner_);
+ CHECK(g_last_created);
+ monitor_task_runner_ = std::move(monitor_task_runner);
+ audio_task_runner_ = g_last_created->GetTaskRunner();
base::PowerMonitor::Get()->AddObserver(this);
- failed_pings_ = 0;
+
io_task_running_ = audio_task_running_ = true;
- UpdateLastAudioThreadTimeTick();
- RecordAudioThreadStatus();
+ audio_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick,
+ base::Unretained(this)));
+ monitor_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AudioManagerHelper::RecordAudioThreadStatus,
+ base::Unretained(this)));
}
+ AudioLogFactory* fake_log_factory() { return &fake_log_factory_; }
+
+#if defined(OS_WIN)
+ // This should be called before creating an AudioManager in tests to ensure
+ // that the creating thread is COM initialized.
+ void InitializeCOMForTesting() {
+ com_initializer_for_testing_.reset(new base::win::ScopedCOMInitializer());
+ }
+#endif
+
+#if defined(OS_LINUX)
+ void set_app_name(const std::string& app_name) { app_name_ = app_name; }
+ const std::string& app_name() const { return app_name_; }
+#endif
+
+ void enable_crash_key_logging() { enable_crash_key_logging_ = true; }
+
+ private:
+ // base::PowerObserver overrides.
// Disable hang detection when the system goes into the suspend state.
void OnSuspend() override {
base::AutoLock lock(hang_lock_);
hang_detection_enabled_ = false;
failed_pings_ = successful_pings_ = 0;
}
-
// Reenable hang detection once the system comes out of the suspend state.
void OnResume() override {
base::AutoLock lock(hang_lock_);
@@ -105,19 +125,25 @@
audio_task_running_ = true;
base::AutoUnlock unlock(hang_lock_);
- UpdateLastAudioThreadTimeTick();
+ audio_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick,
+ base::Unretained(this)));
}
if (!io_task_running_) {
io_task_running_ = true;
base::AutoUnlock unlock(hang_lock_);
- RecordAudioThreadStatus();
+ monitor_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AudioManagerHelper::RecordAudioThreadStatus,
+ base::Unretained(this)));
}
}
- // Runs on |monitor_task_runner| typically, but may be started on any thread.
+ // Runs on |monitor_task_runner|.
void RecordAudioThreadStatus() {
+ DCHECK(monitor_task_runner_->BelongsToCurrentThread());
{
base::AutoLock lock(hang_lock_);
@@ -159,8 +185,9 @@
max_hung_task_time_);
}
- // Runs on the audio thread typically, but may be started on any thread.
+ // Runs on the audio thread.
void UpdateLastAudioThreadTimeTick() {
+ DCHECK(audio_task_runner_->BelongsToCurrentThread());
{
base::AutoLock lock(hang_lock_);
last_audio_thread_timer_tick_ = base::TimeTicks::Now();
@@ -176,37 +203,22 @@
}
// Don't hold the lock while posting the next task.
- g_last_created->GetTaskRunner()->PostDelayedTask(
+ audio_task_runner_->PostDelayedTask(
FROM_HERE,
base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick,
base::Unretained(this)),
max_hung_task_time_ / 5);
}
- AudioLogFactory* fake_log_factory() { return &fake_log_factory_; }
-
-#if defined(OS_WIN)
- // This should be called before creating an AudioManager in tests to ensure
- // that the creating thread is COM initialized.
- void InitializeCOMForTesting() {
- com_initializer_for_testing_.reset(new base::win::ScopedCOMInitializer());
- }
-#endif
-
-#if defined(OS_LINUX)
- void set_app_name(const std::string& app_name) {
- app_name_ = app_name;
+ void HistogramThreadStatus(ThreadStatus status) {
+ DCHECK(monitor_task_runner_->BelongsToCurrentThread());
+ audio_thread_status_ = status;
+ UMA_HISTOGRAM_ENUMERATION("Media.AudioThreadStatus", audio_thread_status_,
+ THREAD_MAX + 1);
}
- const std::string& app_name() const {
- return app_name_;
- }
-#endif
-
- void enable_crash_key_logging() { enable_crash_key_logging_ = true; }
-
- private:
void LogAudioDriverCrashKeys() {
+ DCHECK(monitor_task_runner_->BelongsToCurrentThread());
DCHECK(enable_crash_key_logging_);
#if defined(OS_WIN)
@@ -228,6 +240,7 @@
const base::TimeDelta max_hung_task_time_ = base::TimeDelta::FromMinutes(1);
scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
base::Lock hang_lock_;
bool hang_detection_enabled_ = true;
@@ -255,14 +268,51 @@
} // namespace
-// Forward declaration of the platform specific AudioManager factory function.
-AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory);
+void AudioManagerDeleter::operator()(const AudioManager* instance) const {
+ CHECK(instance);
+ // We reset g_last_created here instead of in the destructor of AudioManager
+ // because the destructor runs on the audio thread. We want to always change
+ // g_last_created from the main thread.
+ if (g_last_created == instance) {
+ g_last_created = nullptr;
+ } else {
+ // We create multiple instances of AudioManager only when testing.
+ // We should not encounter this case in production.
+ LOG(WARNING) << "Multiple instances of AudioManager detected";
+ }
-AudioManager::AudioManager() {}
+ // AudioManager must be destroyed on the audio thread.
+ if (!instance->GetTaskRunner()->DeleteSoon(FROM_HERE, instance)) {
+ LOG(WARNING) << "Failed to delete AudioManager instance.";
+ }
+}
+
+// Forward declaration of the platform specific AudioManager factory function.
+ScopedAudioManagerPtr CreateAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
+
+AudioManager::AudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner)
+ : task_runner_(std::move(task_runner)),
+ worker_task_runner_(std::move(worker_task_runner)) {
+ DCHECK(task_runner_);
+ DCHECK(worker_task_runner_);
+
+ if (g_last_created) {
+ // We create multiple instances of AudioManager only when testing.
+ // We should not encounter this case in production.
+ LOG(WARNING) << "Multiple instances of AudioManager detected";
+ }
+ // We always override |g_last_created| irrespective of whether it is already
+ // set or not becuase it represents the last created instance.
+ g_last_created = this;
+}
AudioManager::~AudioManager() {
- CHECK(!g_last_created || g_last_created == this);
- g_last_created = nullptr;
+ DCHECK(task_runner_->BelongsToCurrentThread());
}
// static
@@ -282,37 +332,38 @@
}
// static
-AudioManager* AudioManager::Create(AudioLogFactory* audio_log_factory) {
- CHECK(!g_last_created);
- if (g_audio_manager_factory)
- g_last_created = g_audio_manager_factory->CreateInstance(audio_log_factory);
- else
- g_last_created = CreateAudioManager(audio_log_factory);
+ScopedAudioManagerPtr AudioManager::Create(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner,
+ AudioLogFactory* audio_log_factory) {
+ DCHECK(task_runner);
+ DCHECK(worker_task_runner);
+ ScopedAudioManagerPtr manager;
+ if (g_audio_manager_factory) {
+ manager = g_audio_manager_factory->CreateInstance(
+ std::move(task_runner), std::move(worker_task_runner),
+ audio_log_factory);
+ } else {
+ manager =
+ CreateAudioManager(std::move(task_runner),
+ std::move(worker_task_runner), audio_log_factory);
+ }
- return g_last_created;
-}
-
-// static
-AudioManager* AudioManager::CreateWithHangTimer(
- AudioLogFactory* audio_log_factory,
- const scoped_refptr<base::SingleThreadTaskRunner>& monitor_task_runner) {
- AudioManager* manager = Create(audio_log_factory);
-
-// On OSX the audio thread is the UI thread, for which a hang monitor is not
-// necessary or recommended.
-#if !defined(OS_MACOSX)
- g_helper.Pointer()->StartHangTimer(monitor_task_runner);
-#endif
+ if (monitor_task_runner)
+ g_helper.Pointer()->StartHangTimer(std::move(monitor_task_runner));
return manager;
}
// static
-AudioManager* AudioManager::CreateForTesting() {
+ScopedAudioManagerPtr AudioManager::CreateForTesting(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
#if defined(OS_WIN)
g_helper.Pointer()->InitializeCOMForTesting();
#endif
- return Create(g_helper.Pointer()->fake_log_factory());
+ return Create(task_runner, task_runner, nullptr,
+ g_helper.Pointer()->fake_log_factory());
}
// static
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index d3eea4a..4142581 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -5,10 +5,12 @@
#ifndef MEDIA_AUDIO_AUDIO_MANAGER_H_
#define MEDIA_AUDIO_AUDIO_MANAGER_H_
+#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "media/audio/audio_device_name.h"
@@ -22,9 +24,17 @@
namespace media {
class AudioInputStream;
+class AudioManager;
class AudioManagerFactory;
class AudioOutputStream;
+class MEDIA_EXPORT AudioManagerDeleter {
+ public:
+ void operator()(const AudioManager* instance) const;
+};
+using ScopedAudioManagerPtr =
+ std::unique_ptr<AudioManager, AudioManagerDeleter>;
+
// Manages all audio resources. Provides some convenience functions that avoid
// the need to provide iterators over the existing streams.
//
@@ -34,8 +44,6 @@
// logged on Windows (this allows us to report driver hangs to Microsoft).
class MEDIA_EXPORT AudioManager {
public:
- virtual ~AudioManager();
-
// This provides an alternative to the statically linked factory method used
// to create AudioManager. This is useful for dynamically-linked third
// party clients seeking to provide a platform-specific implementation of
@@ -46,20 +54,35 @@
// which must not be NULL.
static void SetFactory(AudioManagerFactory* factory);
- // Construct the audio manager; only one instance is allowed. The manager
- // will forward CreateAudioLog() calls to the provided AudioLogFactory; as
- // such |audio_log_factory| must outlive the AudioManager.
- static AudioManager* Create(AudioLogFactory* audio_log_factory);
+ // Construct the audio manager; only one instance is allowed.
+ // The returned instance must be deleted on AudioManager::GetTaskRunnner().
+ //
+ // The manager will forward CreateAudioLog() calls to the provided
+ // AudioLogFactory; as such |audio_log_factory| must outlive the AudioManager.
+ //
+ // The manager will use |task_runner| for audio IO. This same task runner
+ // is returned by GetTaskRunner().
+ // On OS_MACOSX, CoreAudio requires that |task_runner| must belong to the
+ // main thread of the process, which in our case is sadly the browser UI
+ // thread. Failure to execute calls on the right thread leads to crashes and
+ // odd behavior. See http://crbug.com/158170.
+ //
+ // The manager will use |worker_task_runner| for heavyweight tasks.
+ // The |worker_task_runner| may be the same as |task_runner|. This same
+ // task runner is returned by GetWorkerTaskRunner.
+ //
+ // If |monitor_task_runner| is not NULL, a monitor will be scheduled on
+ // |monitor_task_runner| to monitor |task_runner|. See EnableHangMonitor().
+ static ScopedAudioManagerPtr Create(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner,
+ AudioLogFactory* audio_log_factory);
- // Similar to Create() except also schedules a monitor on the given task
- // runner to ensure the audio thread is not stuck for more than 60 seconds; if
- // a hang is detected, the process will be crashed. See EnableHangMonitor().
- static AudioManager* CreateWithHangTimer(
- AudioLogFactory* audio_log_factory,
- const scoped_refptr<base::SingleThreadTaskRunner>& monitor_task_runner);
-
- // Similar to Create() except uses a FakeAudioLogFactory for testing.
- static AudioManager* CreateForTesting();
+ // A convenience wrapper of AudioManager::Create for testing.
+ // The given |task_runner| is shared for both audio io and heavyweight tasks.
+ static ScopedAudioManagerPtr CreateForTesting(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// Enables non-crash dumps when audio thread hangs are detected.
// TODO(dalecurtis): There are no callers to this function at present. A list
@@ -178,12 +201,18 @@
const std::string& device_id) = 0;
// Returns the task runner used for audio IO.
- virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() = 0;
+ // TODO(alokp): Rename to task_runner().
+ base::SingleThreadTaskRunner* GetTaskRunner() const {
+ return task_runner_.get();
+ }
// Heavyweight tasks should use GetWorkerTaskRunner() instead of
// GetTaskRunner(). On most platforms they are the same, but some share the
// UI loop with the audio IO loop.
- virtual scoped_refptr<base::SingleThreadTaskRunner> GetWorkerTaskRunner() = 0;
+ // TODO(alokp): Rename to worker_task_runner().
+ base::SingleThreadTaskRunner* GetWorkerTaskRunner() const {
+ return worker_task_runner_.get();
+ }
// Allows clients to listen for device state changes; e.g. preferred sample
// rate or channel layout changes. The typical response to receiving this
@@ -230,9 +259,15 @@
AudioLogFactory::AudioComponent component) = 0;
protected:
- AudioManager();
+ AudioManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner);
+ virtual ~AudioManager();
private:
+ friend class base::DeleteHelper<AudioManager>;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
DISALLOW_COPY_AND_ASSIGN(AudioManager);
};
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 8a6acc2..8845585f 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -89,8 +89,12 @@
return session_id && device_id.empty();
}
-AudioManagerBase::AudioManagerBase(AudioLogFactory* audio_log_factory)
- : max_num_output_streams_(kDefaultMaxOutputStreams),
+AudioManagerBase::AudioManagerBase(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManager(std::move(task_runner), std::move(worker_task_runner)),
+ max_num_output_streams_(kDefaultMaxOutputStreams),
max_num_input_streams_(kDefaultMaxInputStreams),
num_output_streams_(0),
num_input_streams_(0),
@@ -99,42 +103,21 @@
// block the UI thread when swapping devices.
output_listeners_(
base::ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY),
- audio_log_factory_(audio_log_factory) {
-}
+ audio_log_factory_(audio_log_factory) {}
AudioManagerBase::~AudioManagerBase() {
- // The platform specific AudioManager implementation must have already
- // stopped the audio thread. Otherwise, we may destroy audio streams before
- // stopping the thread, resulting an unexpected behavior.
- // This way we make sure activities of the audio streams are all stopped
- // before we destroy them.
- CHECK(!audio_thread_);
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+
// All the output streams should have been deleted.
- DCHECK_EQ(0, num_output_streams_);
+ CHECK_EQ(0, num_output_streams_);
// All the input streams should have been deleted.
- DCHECK_EQ(0, num_input_streams_);
+ CHECK_EQ(0, num_input_streams_);
}
base::string16 AudioManagerBase::GetAudioInputDeviceModel() {
return base::string16();
}
-scoped_refptr<base::SingleThreadTaskRunner> AudioManagerBase::GetTaskRunner() {
- if (!audio_thread_) {
- audio_thread_.reset(new base::Thread("AudioThread"));
-#if defined(OS_WIN)
- audio_thread_->init_com_with_mta(true);
-#endif
- CHECK(audio_thread_->Start());
- }
- return audio_thread_->task_runner();
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-AudioManagerBase::GetWorkerTaskRunner() {
- return GetTaskRunner();
-}
-
AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
const AudioParameters& params,
const std::string& device_id) {
@@ -329,26 +312,8 @@
}
void AudioManagerBase::Shutdown() {
- // Only true when we're sharing the UI message loop with the browser. The UI
- // loop is no longer running at this time and browser destruction is imminent.
- auto task_runner = GetTaskRunner();
- if (task_runner->BelongsToCurrentThread()) {
- ShutdownOnAudioThread();
- } else {
- task_runner->PostTask(FROM_HERE,
- base::Bind(&AudioManagerBase::ShutdownOnAudioThread,
- base::Unretained(this)));
- }
-
- // Stop() will wait for any posted messages to be processed first.
- if (audio_thread_) {
- audio_thread_->Stop();
- audio_thread_.reset();
- }
-}
-
-void AudioManagerBase::ShutdownOnAudioThread() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ // Close all output streams.
while (!output_dispatchers_.empty()) {
output_dispatchers_.back()->dispatcher->Shutdown();
output_dispatchers_.pop_back();
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index d850447..61292c67 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -63,8 +63,6 @@
~AudioManagerBase() override;
// AudioManager:
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
- scoped_refptr<base::SingleThreadTaskRunner> GetWorkerTaskRunner() override;
base::string16 GetAudioInputDeviceModel() override;
void ShowAudioInputSettings() override;
void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
@@ -122,11 +120,14 @@
int output_stream_count() const { return num_output_streams_; }
protected:
- AudioManagerBase(AudioLogFactory* audio_log_factory);
+ AudioManagerBase(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
- // Shuts down the audio thread and releases all the audio output dispatchers
- // on the audio thread. All audio streams should be freed before Shutdown()
- // is called. This must be called in the destructor of every AudioManagerBase
+ // Releases all the audio output dispatchers.
+ // All audio streams should be closed before Shutdown() is called.
+ // This must be called in the destructor of every AudioManagerBase
// implementation.
void Shutdown();
@@ -162,9 +163,6 @@
class CompareByParams;
- // Called by Shutdown().
- void ShutdownOnAudioThread();
-
// Max number of open output streams, modified by
// SetMaxOutputStreamsAllowed().
int max_num_output_streams_;
@@ -181,9 +179,6 @@
// Track output state change listeners.
base::ObserverList<AudioDeviceListener> output_listeners_;
- // Thread used to interact with audio streams created by this audio manager.
- scoped_ptr<base::Thread> audio_thread_;
-
// Map of cached AudioOutputDispatcher instances. Must only be touched
// from the audio thread (no locking).
AudioOutputDispatchers output_dispatchers_;
diff --git a/media/audio/audio_manager_factory.h b/media/audio/audio_manager_factory.h
index 11f1338..72501486 100644
--- a/media/audio/audio_manager_factory.h
+++ b/media/audio/audio_manager_factory.h
@@ -5,11 +5,18 @@
#ifndef MEDIA_AUDIO_AUDIO_MANAGER_FACTORY_H_
#define MEDIA_AUDIO_AUDIO_MANAGER_FACTORY_H_
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "media/base/media_export.h"
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
namespace media {
class AudioManager;
+class AudioManagerDeleter;
class AudioLogFactory;
// Allows a platform-specific implementation of AudioManager to be provided in
@@ -20,7 +27,10 @@
// Creates an instance of AudioManager implementation. Caller owns the
// returned instance. |audio_log_factory| must outlive the returned instance.
- virtual AudioManager* CreateInstance(AudioLogFactory* audio_log_factory) = 0;
+ virtual scoped_ptr<AudioManager, AudioManagerDeleter> CreateInstance(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory) = 0;
};
} // namespace media
diff --git a/media/audio/audio_manager_factory_unittest.cc b/media/audio/audio_manager_factory_unittest.cc
index 1d13c2e0..b4ceb363 100644
--- a/media/audio/audio_manager_factory_unittest.cc
+++ b/media/audio/audio_manager_factory_unittest.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/memory/scoped_ptr.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_manager_factory.h"
-#include "media/audio/fake_audio_log_factory.h"
#include "media/audio/fake_audio_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,11 +17,17 @@
FakeAudioManagerFactory() {}
~FakeAudioManagerFactory() override {}
- AudioManager* CreateInstance(AudioLogFactory* audio_log_factory) override {
+ ScopedAudioManagerPtr CreateInstance(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory) override {
+ ScopedAudioManagerPtr instance(
+ new FakeAudioManager(std::move(task_runner),
+ std::move(worker_task_runner), audio_log_factory));
// |created_instance_| is used for verifying. Ownership is transferred to
// caller.
- created_instance_ = new FakeAudioManager(audio_log_factory);
- return created_instance_;
+ created_instance_ = instance.get();
+ return instance;
}
AudioManager* created_instance() { return created_instance_; }
@@ -34,24 +40,29 @@
// Verifies that SetFactory has the intended effect.
TEST(AudioManagerFactoryTest, CreateInstance) {
- // Create an audio manager and verify that it is not null.
- scoped_ptr<AudioManager> manager(AudioManager::CreateForTesting());
- ASSERT_NE(nullptr, manager.get());
- manager.reset();
+ {
+ base::TestMessageLoop message_loop;
+ // Create an audio manager and verify that it is not null.
+ ScopedAudioManagerPtr manager =
+ AudioManager::CreateForTesting(base::ThreadTaskRunnerHandle::Get());
+ ASSERT_NE(nullptr, manager.get());
+ }
// Set the factory. Note that ownership of |factory| is transferred to
// AudioManager.
FakeAudioManagerFactory* factory = new FakeAudioManagerFactory();
AudioManager::SetFactory(factory);
-
- // Create the AudioManager instance. Verify that it matches the instance
- // provided by the factory.
- manager.reset(AudioManager::CreateForTesting());
- ASSERT_NE(nullptr, manager.get());
- ASSERT_EQ(factory->created_instance(), manager.get());
-
+ {
+ base::TestMessageLoop message_loop;
+ // Create the AudioManager instance. Verify that it matches the instance
+ // provided by the factory.
+ ScopedAudioManagerPtr manager =
+ AudioManager::CreateForTesting(base::ThreadTaskRunnerHandle::Get());
+ ASSERT_NE(nullptr, manager.get());
+ ASSERT_EQ(factory->created_instance(), manager.get());
+ }
// Reset AudioManagerFactory to prevent factory from persisting to other
- // tests on the same process. |manager| will reset when scope exits.
+ // tests on the same process.
AudioManager::ResetFactoryForTesting();
}
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 894f861..db0196a 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -6,7 +6,10 @@
#include "base/environment.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_manager_base.h"
@@ -32,6 +35,41 @@
namespace media {
+namespace {
+template <typename T>
+struct TestAudioManagerFactory {
+ static ScopedAudioManagerPtr Create(AudioLogFactory* audio_log_factory) {
+ return ScopedAudioManagerPtr(new T(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ audio_log_factory));
+ }
+};
+
+#if defined(USE_PULSEAUDIO)
+template <>
+struct TestAudioManagerFactory<AudioManagerPulse> {
+ static ScopedAudioManagerPtr Create(AudioLogFactory* audio_log_factory) {
+ std::unique_ptr<AudioManagerPulse, AudioManagerDeleter> manager(
+ new AudioManagerPulse(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ audio_log_factory));
+ if (!manager->Init())
+ manager.reset();
+ return std::move(manager);
+ }
+};
+#endif // defined(USE_PULSEAUDIO)
+
+template <>
+struct TestAudioManagerFactory<std::nullptr_t> {
+ static ScopedAudioManagerPtr Create(AudioLogFactory* audio_log_factory) {
+ return AudioManager::Create(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), nullptr,
+ audio_log_factory);
+ }
+};
+} // namespace
+
// Test fixture which allows us to override the default enumeration API on
// Windows.
class AudioManagerTest : public ::testing::Test {
@@ -77,14 +115,8 @@
}
protected:
- AudioManagerTest() : audio_manager_(AudioManager::CreateForTesting()) {
- // Wait for audio thread initialization to complete. Otherwise the
- // enumeration type may not have been set yet.
- base::WaitableEvent event(false, false);
- audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &base::WaitableEvent::Signal, base::Unretained(&event)));
- event.Wait();
- }
+ AudioManagerTest() { CreateAudioManagerForTesting(); }
+ ~AudioManagerTest() override {}
#if defined(OS_WIN)
bool SetMMDeviceEnumeration() {
@@ -149,71 +181,41 @@
}
}
- void HasInputDevicesAvailable(bool* has_devices) {
- *has_devices = audio_manager_->HasAudioInputDevices();
- }
-
- void HasOutputDevicesAvailable(bool* has_devices) {
- *has_devices = audio_manager_->HasAudioOutputDevices();
- }
-
bool InputDevicesAvailable() {
- bool has_devices = false;
- RunOnAudioThread(base::Bind(&AudioManagerTest::HasInputDevicesAvailable,
- base::Unretained(this), &has_devices));
- return has_devices;
+ return audio_manager_->HasAudioInputDevices();
}
-
bool OutputDevicesAvailable() {
- bool has_devices = false;
- RunOnAudioThread(base::Bind(&AudioManagerTest::HasOutputDevicesAvailable,
- base::Unretained(this), &has_devices));
- return has_devices;
+ return audio_manager_->HasAudioOutputDevices();
}
-#if defined(USE_ALSA) || defined(USE_PULSEAUDIO)
- template <class T>
+ template <typename T = std::nullptr_t>
void CreateAudioManagerForTesting() {
// Only one AudioManager may exist at a time, so destroy the one we're
// currently holding before creating a new one.
+ // Flush the message loop to run any shutdown tasks posted by AudioManager.
audio_manager_.reset();
- audio_manager_.reset(T::Create(&fake_audio_log_factory_));
- }
-#endif
+ base::RunLoop().RunUntilIdle();
- // Synchronously runs the provided callback/closure on the audio thread.
- void RunOnAudioThread(const base::Closure& closure) {
- if (!audio_manager_->GetTaskRunner()->BelongsToCurrentThread()) {
- base::WaitableEvent event(false, false);
- audio_manager_->GetTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&AudioManagerTest::RunOnAudioThreadImpl,
- base::Unretained(this),
- closure,
- &event));
- event.Wait();
- } else {
- closure.Run();
- }
+ audio_manager_ =
+ TestAudioManagerFactory<T>::Create(&fake_audio_log_factory_);
+ // A few AudioManager implementations post initialization tasks to
+ // audio thread. Flush the thread to ensure that |audio_manager_| is
+ // initialized and ready to use before returning from this function.
+ // TODO(alokp): We should perhaps do this in AudioManager::Create().
+ base::RunLoop().RunUntilIdle();
}
- void RunOnAudioThreadImpl(const base::Closure& closure,
- base::WaitableEvent* event) {
- DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
- closure.Run();
- event->Signal();
- }
-
+ base::TestMessageLoop message_loop_;
FakeAudioLogFactory fake_audio_log_factory_;
- scoped_ptr<AudioManager> audio_manager_;
+ ScopedAudioManagerPtr audio_manager_;
};
TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) {
// Use a fake manager so we can makeup device ids, this will still use the
// AudioManagerBase code.
- audio_manager_.reset(new FakeAudioManager(&fake_audio_log_factory_));
- RunOnAudioThread(base::Bind(&AudioManagerTest::HandleDefaultDeviceIDsTest,
- base::Unretained(this)));
+ CreateAudioManagerForTesting<FakeAudioManager>();
+ HandleDefaultDeviceIDsTest();
+ base::RunLoop().RunUntilIdle();
}
// Test that devices can be enumerated.
@@ -221,10 +223,7 @@
ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
AudioDeviceNames device_names;
- RunOnAudioThread(
- base::Bind(&AudioManager::GetAudioInputDeviceNames,
- base::Unretained(audio_manager_.get()),
- &device_names));
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
CheckDeviceNames(device_names);
}
@@ -233,10 +232,7 @@
ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
AudioDeviceNames device_names;
- RunOnAudioThread(
- base::Bind(&AudioManager::GetAudioOutputDeviceNames,
- base::Unretained(audio_manager_.get()),
- &device_names));
+ audio_manager_->GetAudioOutputDeviceNames(&device_names);
CheckDeviceNames(device_names);
}
@@ -403,9 +399,7 @@
ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
AudioParameters params;
- RunOnAudioThread(
- base::Bind(&AudioManagerTest::GetDefaultOutputStreamParameters,
- base::Unretained(this), ¶ms));
+ GetDefaultOutputStreamParameters(¶ms);
EXPECT_TRUE(params.IsValid());
#endif // defined(OS_WIN) || defined(OS_MACOSX)
}
@@ -415,9 +409,7 @@
ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable() && OutputDevicesAvailable());
AudioDeviceNames device_names;
- RunOnAudioThread(base::Bind(&AudioManager::GetAudioInputDeviceNames,
- base::Unretained(audio_manager_.get()),
- &device_names));
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
bool found_an_associated_device = false;
for (AudioDeviceNames::iterator it = device_names.begin();
it != device_names.end();
@@ -425,9 +417,7 @@
EXPECT_FALSE(it->unique_id.empty());
EXPECT_FALSE(it->device_name.empty());
std::string output_device_id;
- RunOnAudioThread(base::Bind(&AudioManagerTest::GetAssociatedOutputDeviceID,
- base::Unretained(this), it->unique_id,
- &output_device_id));
+ GetAssociatedOutputDeviceID(it->unique_id, &output_device_id);
if (!output_device_id.empty()) {
DVLOG(2) << it->unique_id << " matches with " << output_device_id;
found_an_associated_device = true;
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index 1046893..b81cb10 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -10,8 +10,9 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/run_loop.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_output_controller.h"
#include "media/audio/audio_parameters.h"
@@ -79,10 +80,6 @@
AudioSourceCallback* callback_;
};
-ACTION_P(SignalEvent, event) {
- event->Signal();
-}
-
static const float kBufferNonZeroData = 1.0f;
ACTION(PopulateBuffer) {
arg0->Zero();
@@ -94,29 +91,21 @@
class AudioOutputControllerTest : public testing::Test {
public:
AudioOutputControllerTest()
- : audio_manager_(AudioManager::CreateForTesting()),
- create_event_(false, false),
- play_event_(false, false),
- read_event_(false, false),
- pause_event_(false, false) {
+ : audio_manager_(AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get())) {
+ base::RunLoop().RunUntilIdle();
}
~AudioOutputControllerTest() override {}
protected:
void Create(int samples_per_packet) {
- EXPECT_FALSE(create_event_.IsSignaled());
- EXPECT_FALSE(play_event_.IsSignaled());
- EXPECT_FALSE(read_event_.IsSignaled());
- EXPECT_FALSE(pause_event_.IsSignaled());
-
params_ = AudioParameters(
AudioParameters::AUDIO_FAKE, kChannelLayout,
kSampleRate, kBitsPerSample, samples_per_packet);
if (params_.IsValid()) {
- EXPECT_CALL(mock_event_handler_, OnCreated())
- .WillOnce(SignalEvent(&create_event_));
+ EXPECT_CALL(mock_event_handler_, OnCreated());
}
controller_ = AudioOutputController::Create(
@@ -126,35 +115,33 @@
controller_->SetVolume(kTestVolume);
EXPECT_EQ(params_.IsValid(), controller_.get() != NULL);
+ base::RunLoop().RunUntilIdle();
}
void Play() {
// Expect the event handler to receive one OnPlaying() call.
- EXPECT_CALL(mock_event_handler_, OnPlaying())
- .WillOnce(SignalEvent(&play_event_));
+ EXPECT_CALL(mock_event_handler_, OnPlaying());
// During playback, the mock pretends to provide audio data rendered and
// sent from the render process.
EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_, _)).Times(AtLeast(1));
- EXPECT_CALL(mock_sync_reader_, Read(_))
- .WillRepeatedly(DoAll(PopulateBuffer(),
- SignalEvent(&read_event_)));
+ EXPECT_CALL(mock_sync_reader_, Read(_)).WillRepeatedly(PopulateBuffer());
controller_->Play();
+ base::RunLoop().RunUntilIdle();
}
void Pause() {
// Expect the event handler to receive one OnPaused() call.
- EXPECT_CALL(mock_event_handler_, OnPaused())
- .WillOnce(SignalEvent(&pause_event_));
+ EXPECT_CALL(mock_event_handler_, OnPaused());
controller_->Pause();
+ base::RunLoop().RunUntilIdle();
}
void ChangeDevice() {
// Expect the event handler to receive one OnPaying() call and no OnPaused()
// call.
- EXPECT_CALL(mock_event_handler_, OnPlaying())
- .WillOnce(SignalEvent(&play_event_));
+ EXPECT_CALL(mock_event_handler_, OnPlaying());
EXPECT_CALL(mock_event_handler_, OnPaused())
.Times(0);
@@ -169,8 +156,7 @@
if (was_playing) {
// Expect the handler to receive one OnPlaying() call as a result of the
// stream switching.
- EXPECT_CALL(mock_event_handler_, OnPlaying())
- .WillOnce(SignalEvent(&play_event_));
+ EXPECT_CALL(mock_event_handler_, OnPlaying());
}
EXPECT_CALL(mock_stream_, Open())
@@ -186,6 +172,7 @@
}
controller_->StartDiverting(&mock_stream_);
+ base::RunLoop().RunUntilIdle();
}
void ReadDivertedAudioData() {
@@ -201,13 +188,13 @@
if (was_playing) {
// Expect the handler to receive one OnPlaying() call as a result of the
// stream switching back.
- EXPECT_CALL(mock_event_handler_, OnPlaying())
- .WillOnce(SignalEvent(&play_event_));
+ EXPECT_CALL(mock_event_handler_, OnPlaying());
}
EXPECT_CALL(mock_stream_, Close());
controller_->StopDiverting();
+ base::RunLoop().RunUntilIdle();
}
void SwitchDevice(bool diverting) {
@@ -215,19 +202,22 @@
// Expect the current stream to close and a new stream to start
// playing if not diverting. When diverting, nothing happens
// until diverting is stopped.
- EXPECT_CALL(mock_event_handler_, OnPlaying())
- .WillOnce(SignalEvent(&play_event_));
+ EXPECT_CALL(mock_event_handler_, OnPlaying());
}
controller_->SwitchOutputDevice(AudioManager::GetDefaultDeviceName(),
base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
}
void Close() {
EXPECT_CALL(mock_sync_reader_, Close());
- controller_->Close(base::MessageLoop::QuitWhenIdleClosure());
- base::MessageLoop::current()->Run();
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&AudioOutputController::Close, controller_,
+ run_loop.QuitClosure()));
+ run_loop.Run();
}
// These help make test sequences more readable.
@@ -237,30 +227,12 @@
void RevertWasNotPlaying() { Revert(false); }
void RevertWhilePlaying() { Revert(true); }
- // These synchronize the main thread with key events taking place on other
- // threads.
- void WaitForCreate() { create_event_.Wait(); }
- void WaitForPlay() { play_event_.Wait(); }
- void WaitForReads() {
- // Note: Arbitrarily chosen, but more iterations causes tests to take
- // significantly more time.
- static const int kNumIterations = 3;
- for (int i = 0; i < kNumIterations; ++i) {
- read_event_.Wait();
- }
- }
- void WaitForPause() { pause_event_.Wait(); }
-
private:
- base::MessageLoopForIO message_loop_;
- scoped_ptr<AudioManager> audio_manager_;
+ base::TestMessageLoop message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
MockAudioOutputControllerEventHandler mock_event_handler_;
MockAudioOutputControllerSyncReader mock_sync_reader_;
MockAudioOutputStream mock_stream_;
- base::WaitableEvent create_event_;
- base::WaitableEvent play_event_;
- base::WaitableEvent read_event_;
- base::WaitableEvent pause_event_;
AudioParameters params_;
scoped_refptr<AudioOutputController> controller_;
@@ -278,134 +250,84 @@
TEST_F(AudioOutputControllerTest, PlayAndClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
Close();
}
TEST_F(AudioOutputControllerTest, PlayPauseClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
Pause();
- WaitForPause();
Close();
}
TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
Pause();
- WaitForPause();
Play();
- WaitForPlay();
Close();
}
TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
ChangeDevice();
- WaitForPlay();
- WaitForReads();
Close();
}
TEST_F(AudioOutputControllerTest, PlaySwitchDeviceClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
SwitchDevice(false);
- WaitForPlay();
- WaitForReads();
Close();
}
TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
DivertWhilePlaying();
- WaitForPlay();
ReadDivertedAudioData();
RevertWhilePlaying();
- WaitForPlay();
- WaitForReads();
Close();
}
TEST_F(AudioOutputControllerTest, PlayDivertSwitchDeviceRevertClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
DivertWhilePlaying();
- WaitForPlay();
SwitchDevice(true);
ReadDivertedAudioData();
RevertWhilePlaying();
- WaitForPlay();
- WaitForReads();
Close();
}
TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
Play();
- WaitForPlay();
- WaitForReads();
DivertWhilePlaying();
- WaitForPlay();
ReadDivertedAudioData();
RevertWhilePlaying();
- WaitForPlay();
- WaitForReads();
DivertWhilePlaying();
- WaitForPlay();
ReadDivertedAudioData();
RevertWhilePlaying();
- WaitForPlay();
- WaitForReads();
Close();
}
TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
DivertWillEventuallyBeTwicePlayed();
Play();
- WaitForPlay();
ReadDivertedAudioData();
Pause();
- WaitForPause();
Play();
- WaitForPlay();
ReadDivertedAudioData();
RevertWhilePlaying();
- WaitForPlay();
- WaitForReads();
Close();
}
TEST_F(AudioOutputControllerTest, DivertRevertClose) {
Create(kSamplesPerPacket);
- WaitForCreate();
DivertNeverPlaying();
RevertWasNotPlaying();
Close();
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc
index f0374618..3c5d0b5 100644
--- a/media/audio/audio_output_proxy_unittest.cc
+++ b/media/audio/audio_output_proxy_unittest.cc
@@ -8,6 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_manager_base.h"
@@ -87,10 +88,11 @@
class MockAudioManager : public AudioManagerBase {
public:
- MockAudioManager() : AudioManagerBase(&fake_audio_log_factory_) {}
- virtual ~MockAudioManager() {
- Shutdown();
- }
+ MockAudioManager()
+ : AudioManagerBase(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ &fake_audio_log_factory_) {}
+ ~MockAudioManager() override { Shutdown(); }
MOCK_METHOD0(HasAudioOutputDevices, bool());
MOCK_METHOD0(HasAudioInputDevices, bool());
@@ -143,10 +145,6 @@
class AudioOutputProxyTest : public testing::Test {
protected:
void SetUp() override {
- EXPECT_CALL(manager_, GetTaskRunner())
- .WillRepeatedly(Return(message_loop_.task_runner()));
- EXPECT_CALL(manager_, GetWorkerTaskRunner())
- .WillRepeatedly(Return(message_loop_.task_runner()));
// Use a low sample rate and large buffer size when testing otherwise the
// FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
// RunUntilIdle() will never terminate.
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 2a9b77d..0d70a58d 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -135,8 +135,13 @@
return false;
}
-AudioManagerCras::AudioManagerCras(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory),
+AudioManagerCras::AudioManagerCras(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory),
beamforming_on_device_id_(nullptr),
beamforming_off_device_id_(nullptr) {
SetMaxOutputStreamsAllowed(kMaxOutputStreams);
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h
index 6ad4f0e..3383a2f 100644
--- a/media/audio/cras/audio_manager_cras.h
+++ b/media/audio/cras/audio_manager_cras.h
@@ -18,7 +18,10 @@
class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
public:
- AudioManagerCras(AudioLogFactory* audio_log_factory);
+ AudioManagerCras(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
// AudioManager implementation.
bool HasAudioOutputDevices() override;
diff --git a/media/audio/cras/cras_input_unittest.cc b/media/audio/cras/cras_input_unittest.cc
index 3735322b0..9062bbda 100644
--- a/media/audio/cras/cras_input_unittest.cc
+++ b/media/audio/cras/cras_input_unittest.cc
@@ -4,11 +4,15 @@
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/test_message_loop.h"
#include "base/test/test_timeouts.h"
+#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "media/audio/cras/audio_manager_cras.h"
#include "media/audio/fake_audio_log_factory.h"
@@ -38,7 +42,10 @@
class MockAudioManagerCrasInput : public AudioManagerCras {
public:
- MockAudioManagerCrasInput() : AudioManagerCras(&fake_audio_log_factory_) {}
+ MockAudioManagerCrasInput()
+ : AudioManagerCras(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ &fake_audio_log_factory_) {}
// We need to override this function in order to skip checking the number
// of active output streams. It is because the number of active streams
@@ -57,10 +64,10 @@
protected:
CrasInputStreamTest() {
mock_manager_.reset(new StrictMock<MockAudioManagerCrasInput>());
+ base::RunLoop().RunUntilIdle();
}
- virtual ~CrasInputStreamTest() {
- }
+ ~CrasInputStreamTest() override {}
CrasInputStream* CreateStream(ChannelLayout layout) {
return CreateStream(layout, kTestFramesPerPacket);
@@ -115,7 +122,9 @@
static const uint32_t kTestFramesPerPacket;
static const int kTestSampleRate;
- scoped_ptr<StrictMock<MockAudioManagerCrasInput> > mock_manager_;
+ base::TestMessageLoop message_loop_;
+ std::unique_ptr<StrictMock<MockAudioManagerCrasInput>, AudioManagerDeleter>
+ mock_manager_;
private:
DISALLOW_COPY_AND_ASSIGN(CrasInputStreamTest);
diff --git a/media/audio/cras/cras_unified_unittest.cc b/media/audio/cras/cras_unified_unittest.cc
index cb4d71bf..2bc199ed 100644
--- a/media/audio/cras/cras_unified_unittest.cc
+++ b/media/audio/cras/cras_unified_unittest.cc
@@ -7,8 +7,11 @@
#include <string>
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/test_message_loop.h"
#include "base/test/test_timeouts.h"
+#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "media/audio/cras/audio_manager_cras.h"
#include "media/audio/fake_audio_log_factory.h"
@@ -33,7 +36,10 @@
class MockAudioManagerCras : public AudioManagerCras {
public:
- MockAudioManagerCras() : AudioManagerCras(&fake_audio_log_factory_) {}
+ MockAudioManagerCras()
+ : AudioManagerCras(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ &fake_audio_log_factory_) {}
MOCK_METHOD0(Init, void());
MOCK_METHOD0(HasAudioOutputDevices, bool());
@@ -65,10 +71,10 @@
protected:
CrasUnifiedStreamTest() {
mock_manager_.reset(new StrictMock<MockAudioManagerCras>());
+ base::RunLoop().RunUntilIdle();
}
- virtual ~CrasUnifiedStreamTest() {
- }
+ ~CrasUnifiedStreamTest() override {}
CrasUnifiedStream* CreateStream(ChannelLayout layout) {
return CreateStream(layout, kTestFramesPerPacket);
@@ -91,7 +97,9 @@
static const AudioParameters::Format kTestFormat;
static const uint32_t kTestFramesPerPacket;
- scoped_ptr<StrictMock<MockAudioManagerCras> > mock_manager_;
+ base::TestMessageLoop message_loop_;
+ scoped_ptr<StrictMock<MockAudioManagerCras>, AudioManagerDeleter>
+ mock_manager_;
private:
DISALLOW_COPY_AND_ASSIGN(CrasUnifiedStreamTest);
diff --git a/media/audio/fake_audio_manager.cc b/media/audio/fake_audio_manager.cc
index 3d76401..a4005e1f 100644
--- a/media/audio/fake_audio_manager.cc
+++ b/media/audio/fake_audio_manager.cc
@@ -13,10 +13,18 @@
} // namespace
-FakeAudioManager::FakeAudioManager(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory) {}
+FakeAudioManager::FakeAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory) {
+ LOG(INFO) << __FUNCTION__;
+}
FakeAudioManager::~FakeAudioManager() {
+ LOG(INFO) << __FUNCTION__;
Shutdown();
}
diff --git a/media/audio/fake_audio_manager.h b/media/audio/fake_audio_manager.h
index ee055c7..326988c 100644
--- a/media/audio/fake_audio_manager.h
+++ b/media/audio/fake_audio_manager.h
@@ -16,7 +16,10 @@
class MEDIA_EXPORT FakeAudioManager : public AudioManagerBase {
public:
- FakeAudioManager(AudioLogFactory* audio_log_factory);
+ FakeAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
// Implementation of AudioManager.
bool HasAudioOutputDevices() override;
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc
index 0e7c981..5d9676e 100644
--- a/media/audio/linux/audio_manager_linux.cc
+++ b/media/audio/linux/audio_manager_linux.cc
@@ -4,6 +4,8 @@
#include "base/command_line.h"
#include "base/metrics/histogram.h"
+#include "media/base/media_switches.h"
+
#if defined(USE_ALSA)
#include "media/audio/alsa/audio_manager_alsa.h"
#else
@@ -15,7 +17,6 @@
#if defined(USE_PULSEAUDIO)
#include "media/audio/pulse/audio_manager_pulse.h"
#endif
-#include "media/base/media_switches.h"
namespace media {
@@ -26,27 +27,42 @@
kAudioIOMax = kCras // Must always be equal to largest logged entry.
};
-AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
+ScopedAudioManagerPtr CreateAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory) {
#if defined(USE_CRAS)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kCras, kAudioIOMax + 1);
- return new AudioManagerCras(audio_log_factory);
+ return ScopedAudioManagerPtr(
+ new AudioManagerCras(std::move(task_runner),
+ std::move(worker_task_runner), audio_log_factory));
}
#endif
#if defined(USE_PULSEAUDIO)
- AudioManager* manager = AudioManagerPulse::Create(audio_log_factory);
- if (manager) {
+ // Do not move task runners when creating AudioManagerPulse.
+ // If the creation fails, we need to use the task runners to create other
+ // AudioManager implementations.
+ std::unique_ptr<AudioManagerPulse, AudioManagerDeleter> manager(
+ new AudioManagerPulse(task_runner, worker_task_runner,
+ audio_log_factory));
+ if (manager->Init()) {
UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kPulse, kAudioIOMax + 1);
- return manager;
+ return std::move(manager);
}
+ DVLOG(1) << "PulseAudio is not available on the OS";
#endif
#if defined(USE_ALSA)
UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kAlsa, kAudioIOMax + 1);
- return new AudioManagerAlsa(audio_log_factory);
+ return ScopedAudioManagerPtr(
+ new AudioManagerAlsa(std::move(task_runner),
+ std::move(worker_task_runner), audio_log_factory));
#else
- return new FakeAudioManager(audio_log_factory);
+ return ScopedAudioManagerPtr(
+ new FakeAudioManager(std::move(task_runner),
+ std::move(worker_task_runner), audio_log_factory));
#endif
}
diff --git a/media/audio/mac/audio_auhal_mac_unittest.cc b/media/audio/mac/audio_auhal_mac_unittest.cc
index 73191cd..044116b 100644
--- a/media/audio/mac/audio_auhal_mac_unittest.cc
+++ b/media/audio/mac/audio_auhal_mac_unittest.cc
@@ -4,9 +4,10 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_unittest_util.h"
@@ -35,12 +36,13 @@
public:
AUHALStreamTest()
: message_loop_(base::MessageLoop::TYPE_UI),
- manager_(AudioManager::CreateForTesting()) {
+ manager_(AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get())) {
// Wait for the AudioManager to finish any initialization on the audio loop.
base::RunLoop().RunUntilIdle();
}
- ~AUHALStreamTest() override { base::RunLoop().RunUntilIdle(); }
+ ~AUHALStreamTest() override {}
AudioOutputStream* Create() {
return manager_->MakeAudioOutputStream(
@@ -52,8 +54,8 @@
}
protected:
- base::MessageLoop message_loop_;
- scoped_ptr<AudioManager> manager_;
+ base::TestMessageLoop message_loop_;
+ ScopedAudioManagerPtr manager_;
MockAudioSourceCallback source_;
private:
diff --git a/media/audio/mac/audio_low_latency_input_mac_unittest.cc b/media/audio/mac/audio_low_latency_input_mac_unittest.cc
index ba30cf13..7309586 100644
--- a/media/audio/mac/audio_low_latency_input_mac_unittest.cc
+++ b/media/audio/mac/audio_low_latency_input_mac_unittest.cc
@@ -107,12 +107,16 @@
protected:
MacAudioInputTest()
: message_loop_(base::MessageLoop::TYPE_UI),
- audio_manager_(AudioManager::CreateForTesting()) {
+ audio_manager_(
+ AudioManager::CreateForTesting(message_loop_.task_runner())) {
// Wait for the AudioManager to finish any initialization on the audio loop.
base::RunLoop().RunUntilIdle();
}
- ~MacAudioInputTest() override { base::RunLoop().RunUntilIdle(); }
+ ~MacAudioInputTest() override {
+ audio_manager_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
bool InputDevicesAvailable() {
return audio_manager_->HasAudioInputDevices();
@@ -146,7 +150,7 @@
}
base::MessageLoop message_loop_;
- scoped_ptr<AudioManager> audio_manager_;
+ ScopedAudioManagerPtr audio_manager_;
};
// Test Create(), Close().
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 20cd4c8..0b29dcc13 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -293,18 +293,6 @@
return GetDefaultDevice(device, false);
}
-template <class T>
-void StopStreams(std::list<T*>* streams) {
- for (typename std::list<T*>::iterator it = streams->begin();
- it != streams->end();
- ++it) {
- // Stop() is safe to call multiple times, so it doesn't matter if a stream
- // has already been stopped.
- (*it)->Stop();
- }
- streams->clear();
-}
-
class AudioManagerMac::AudioPowerObserver : public base::PowerObserver {
public:
AudioPowerObserver()
@@ -370,55 +358,29 @@
DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver);
};
-AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory),
+AudioManagerMac::AudioManagerMac(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory),
current_sample_rate_(0),
current_output_device_(kAudioDeviceUnknown) {
SetMaxOutputStreamsAllowed(kMaxOutputStreams);
- // CoreAudio calls must occur on the main thread of the process, which in our
- // case is sadly the browser UI thread. Failure to execute calls on the right
- // thread leads to crashes and odd behavior. See http://crbug.com/158170.
- // TODO(dalecurtis): We should require the message loop to be passed in.
- task_runner_ = base::MessageLoopForUI::IsCurrent()
- ? base::ThreadTaskRunnerHandle::Get()
- : AudioManagerBase::GetTaskRunner();
-
// Task must be posted last to avoid races from handing out "this" to the
// audio thread. Always PostTask even if we're on the right thread since
// AudioManager creation is on the startup path and this may be slow.
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&AudioManagerMac::InitializeOnAudioThread,
- base::Unretained(this)));
+ GetTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&AudioManagerMac::InitializeOnAudioThread,
+ base::Unretained(this)));
}
AudioManagerMac::~AudioManagerMac() {
- if (task_runner_->BelongsToCurrentThread()) {
- ShutdownOnAudioThread();
- } else {
- // It's safe to post a task here since Shutdown() will wait for all tasks to
- // complete before returning.
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&AudioManagerMac::ShutdownOnAudioThread,
- base::Unretained(this)));
- }
-
Shutdown();
}
-scoped_refptr<base::SingleThreadTaskRunner> AudioManagerMac::GetTaskRunner() {
- return task_runner_;
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-AudioManagerMac::GetWorkerTaskRunner() {
- if (!worker_thread_) {
- worker_thread_.reset(new base::Thread("AudioWorkerThread"));
- CHECK(worker_thread_->Start());
- }
- return worker_thread_->task_runner();
-}
-
bool AudioManagerMac::HasAudioOutputDevices() {
return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
}
@@ -556,7 +518,7 @@
std::string AudioManagerMac::GetAssociatedOutputDeviceID(
const std::string& input_device_id) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id);
if (device == kAudioObjectUnknown)
return std::string();
@@ -681,7 +643,7 @@
}
std::string AudioManagerMac::GetDefaultOutputDeviceID() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
AudioDeviceID device_id = kAudioObjectUnknown;
if (!GetDefaultOutputDevice(&device_id))
return std::string();
@@ -780,31 +742,12 @@
}
void AudioManagerMac::InitializeOnAudioThread() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
power_observer_.reset(new AudioPowerObserver());
}
-void AudioManagerMac::ShutdownOnAudioThread() {
- DCHECK(task_runner_->BelongsToCurrentThread());
- output_device_listener_.reset();
- power_observer_.reset();
-
- // Since CoreAudio calls have to run on the UI thread and browser shutdown
- // doesn't wait for outstanding tasks to complete, we may have input/output
- // streams still running at shutdown.
- //
- // To avoid calls into destructed classes, we need to stop the OS callbacks
- // by stopping the streams. Note: The streams are leaked since process
- // destruction is imminent.
- //
- // See http://crbug.com/354139 for crash details.
- StopStreams(&basic_input_streams_);
- StopStreams(&low_latency_input_streams_);
- StopStreams(&output_streams_);
-}
-
void AudioManagerMac::HandleDeviceChanges() {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
const int new_sample_rate = HardwareSampleRate();
AudioDeviceID new_output_device;
GetDefaultOutputDevice(&new_output_device);
@@ -846,22 +789,22 @@
}
bool AudioManagerMac::IsSuspending() const {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return power_observer_->IsSuspending();
}
bool AudioManagerMac::ShouldDeferStreamStart() const {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return power_observer_->ShouldDeferStreamStart();
}
bool AudioManagerMac::IsOnBatteryPower() const {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return power_observer_->IsOnBatteryPower();
}
size_t AudioManagerMac::GetNumberOfResumeNotifications() const {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return power_observer_->num_resume_notifications();
}
@@ -871,7 +814,7 @@
size_t desired_buffer_size,
bool* size_was_changed,
size_t* io_buffer_frame_size) {
- DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
const bool is_input = (element == 1);
DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id
<< ", is_input=" << is_input << ", desired_buffer_size=" << std::dec
@@ -991,8 +934,13 @@
AudioManagerBase::ReleaseInputStream(stream);
}
-AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
- return new AudioManagerMac(audio_log_factory);
+ScopedAudioManagerPtr CreateAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory) {
+ return ScopedAudioManagerPtr(
+ new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner),
+ audio_log_factory));
}
} // namespace media
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index c110538..f8c99e8 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -26,11 +26,12 @@
// the AudioManager class.
class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase {
public:
- AudioManagerMac(AudioLogFactory* audio_log_factory);
+ AudioManagerMac(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
// Implementation of AudioManager.
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
- scoped_refptr<base::SingleThreadTaskRunner> GetWorkerTaskRunner() override;
bool HasAudioOutputDevices() override;
bool HasAudioInputDevices() override;
void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
@@ -117,7 +118,6 @@
private:
void InitializeOnAudioThread();
- void ShutdownOnAudioThread();
int ChooseBufferSize(bool is_input, int sample_rate);
@@ -127,9 +127,6 @@
scoped_ptr<AudioDeviceListenerMac> output_device_listener_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_ptr<base::Thread> worker_thread_;
-
// Track the output sample-rate and the default output device
// so we can intelligently handle device notifications only when necessary.
int current_sample_rate_;
@@ -141,8 +138,11 @@
class AudioPowerObserver;
scoped_ptr<AudioPowerObserver> power_observer_;
- // Tracks all constructed input and output streams so they can be stopped at
- // shutdown. See ShutdownOnAudioThread() for more details.
+ // Tracks all constructed input and output streams.
+ // TODO(alokp): We used to track these streams to close before destruction.
+ // We no longer close the streams, so we may be able to get rid of these
+ // member variables. They are currently used by MaybeChangeBufferSize().
+ // Investigate if we can remove these.
std::list<AudioInputStream*> basic_input_streams_;
std::list<AUAudioInputStream*> low_latency_input_streams_;
std::list<AUHALStream*> output_streams_;
diff --git a/media/audio/mock_audio_manager.cc b/media/audio/mock_audio_manager.cc
index 7183405a..e7726ca 100644
--- a/media/audio/mock_audio_manager.cc
+++ b/media/audio/mock_audio_manager.cc
@@ -11,8 +11,8 @@
namespace media {
MockAudioManager::MockAudioManager(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
- : task_runner_(task_runner) {}
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : AudioManager(task_runner, task_runner) {}
MockAudioManager::~MockAudioManager() {
}
@@ -63,15 +63,6 @@
return NULL;
}
-scoped_refptr<base::SingleThreadTaskRunner> MockAudioManager::GetTaskRunner() {
- return task_runner_;
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-MockAudioManager::GetWorkerTaskRunner() {
- return task_runner_;
-}
-
void MockAudioManager::AddOutputDeviceChangeListener(
AudioDeviceListener* listener) {
}
diff --git a/media/audio/mock_audio_manager.h b/media/audio/mock_audio_manager.h
index 60a8b1e..33f7e5e 100644
--- a/media/audio/mock_audio_manager.h
+++ b/media/audio/mock_audio_manager.h
@@ -11,19 +11,13 @@
namespace media {
// This class is a simple mock around AudioManager, used exclusively for tests,
-// which has the following purposes:
-// 1) Avoids to use the actual (system and platform dependent) AudioManager.
-// Some bots does not have input devices, thus using the actual AudioManager
-// would causing failures on classes which expect that.
-// 2) Allows the mock audio events to be dispatched on an arbitrary thread,
-// rather than forcing them on the audio thread, easing their handling in
-// browser tests (Note: sharing a thread can cause deadlocks on production
-// classes if WaitableEvents or any other form of lock is used for
-// synchronization purposes).
+// which avoids to use the actual (system and platform dependent) AudioManager.
+// Some bots does not have input devices, thus using the actual AudioManager
+// would causing failures on classes which expect that.
class MockAudioManager : public media::AudioManager {
public:
explicit MockAudioManager(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
bool HasAudioOutputDevices() override;
@@ -50,9 +44,6 @@
const media::AudioParameters& params,
const std::string& device_id) override;
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
- scoped_refptr<base::SingleThreadTaskRunner> GetWorkerTaskRunner() override;
-
void AddOutputDeviceChangeListener(AudioDeviceListener* listener) override;
void RemoveOutputDeviceChangeListener(AudioDeviceListener* listener) override;
@@ -71,8 +62,6 @@
~MockAudioManager() override;
private:
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
DISALLOW_COPY_AND_ASSIGN(MockAudioManager);
};
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc
index d6e9543..b96728c 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -47,18 +47,13 @@
FILE_PATH_LITERAL("libpulse.so.0");
#endif
-// static
-AudioManager* AudioManagerPulse::Create(AudioLogFactory* audio_log_factory) {
- scoped_ptr<AudioManagerPulse> ret(new AudioManagerPulse(audio_log_factory));
- if (ret->Init())
- return ret.release();
-
- DVLOG(1) << "PulseAudio is not available on the OS";
- return NULL;
-}
-
-AudioManagerPulse::AudioManagerPulse(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory),
+AudioManagerPulse::AudioManagerPulse(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory),
input_mainloop_(NULL),
input_context_(NULL),
devices_(NULL),
@@ -68,12 +63,20 @@
AudioManagerPulse::~AudioManagerPulse() {
Shutdown();
-
// The Pulse objects are the last things to be destroyed since Shutdown()
// needs them.
DestroyPulse();
}
+bool AudioManagerPulse::Init() {
+ // TODO(alokp): Investigate if InitPulse can happen on the audio thread.
+ // It currently needs to happen on the main thread so that is InitPulse fails,
+ // we can fallback to ALSA implementation. Initializing it on audio thread
+ // would unblock the main thread and make InitPulse consistent with
+ // DestroyPulse which happens on the audio thread.
+ return InitPulse();
+}
+
// Implementation of AudioManager.
bool AudioManagerPulse::HasAudioOutputDevices() {
AudioDeviceNames devices;
@@ -217,7 +220,7 @@
return native_input_sample_rate_;
}
-bool AudioManagerPulse::Init() {
+bool AudioManagerPulse::InitPulse() {
DCHECK(!input_mainloop_);
#if defined(DLOPEN_PULSEAUDIO)
diff --git a/media/audio/pulse/audio_manager_pulse.h b/media/audio/pulse/audio_manager_pulse.h
index 93a1c94..d2f6450 100644
--- a/media/audio/pulse/audio_manager_pulse.h
+++ b/media/audio/pulse/audio_manager_pulse.h
@@ -17,10 +17,12 @@
class MEDIA_EXPORT AudioManagerPulse : public AudioManagerBase {
public:
- AudioManagerPulse(AudioLogFactory* audio_log_factory);
- ~AudioManagerPulse() override;
+ AudioManagerPulse(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
- static AudioManager* Create(AudioLogFactory* audio_log_factory);
+ bool Init();
// Implementation of AudioManager.
bool HasAudioOutputDevices() override;
@@ -45,12 +47,14 @@
const std::string& device_id) override;
protected:
+ ~AudioManagerPulse() override;
+
AudioParameters GetPreferredOutputStreamParameters(
const std::string& output_device_id,
const AudioParameters& input_params) override;
private:
- bool Init();
+ bool InitPulse();
void DestroyPulse();
void GetAudioDeviceNames(bool input, media::AudioDeviceNames* device_names);
diff --git a/media/audio/sounds/audio_stream_handler_unittest.cc b/media/audio/sounds/audio_stream_handler_unittest.cc
index 1b87ca42..4863bc9 100644
--- a/media/audio/sounds/audio_stream_handler_unittest.cc
+++ b/media/audio/sounds/audio_stream_handler_unittest.cc
@@ -7,8 +7,9 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h"
#include "media/audio/simple_sources.h"
@@ -25,7 +26,9 @@
~AudioStreamHandlerTest() override {}
void SetUp() override {
- audio_manager_.reset(AudioManager::CreateForTesting());
+ audio_manager_ =
+ AudioManager::CreateForTesting(base::ThreadTaskRunnerHandle::Get());
+ base::RunLoop().RunUntilIdle();
base::StringPiece data(kTestAudioData, arraysize(kTestAudioData));
audio_stream_handler_.reset(new AudioStreamHandler(data));
@@ -33,7 +36,7 @@
void TearDown() override {
audio_stream_handler_.reset();
- audio_manager_.reset();
+ base::RunLoop().RunUntilIdle();
}
AudioStreamHandler* audio_stream_handler() {
@@ -50,10 +53,9 @@
}
private:
- scoped_ptr<AudioManager> audio_manager_;
+ base::TestMessageLoop message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
scoped_ptr<AudioStreamHandler> audio_stream_handler_;
-
- base::MessageLoop message_loop_;
};
TEST_F(AudioStreamHandlerTest, Play) {
diff --git a/media/audio/sounds/sounds_manager_unittest.cc b/media/audio/sounds/sounds_manager_unittest.cc
index 6dfcf119..21f5c65 100644
--- a/media/audio/sounds/sounds_manager_unittest.cc
+++ b/media/audio/sounds/sounds_manager_unittest.cc
@@ -7,10 +7,10 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_piece.h"
+#include "base/test/test_message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "media/audio/audio_manager.h"
#include "media/audio/simple_sources.h"
#include "media/audio/sounds/audio_stream_handler.h"
@@ -26,13 +26,15 @@
~SoundsManagerTest() override {}
void SetUp() override {
- audio_manager_.reset(AudioManager::CreateForTesting());
+ audio_manager_ =
+ AudioManager::CreateForTesting(base::ThreadTaskRunnerHandle::Get());
SoundsManager::Create();
+ base::RunLoop().RunUntilIdle();
}
void TearDown() override {
SoundsManager::Shutdown();
- audio_manager_.reset();
+ base::RunLoop().RunUntilIdle();
}
void SetObserverForTesting(AudioStreamHandler::TestObserver* observer) {
@@ -45,9 +47,8 @@
}
private:
- scoped_ptr<AudioManager> audio_manager_;
-
- base::MessageLoop message_loop_;
+ base::TestMessageLoop message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
};
TEST_F(SoundsManagerTest, Play) {
diff --git a/media/audio/win/audio_low_latency_input_win_unittest.cc b/media/audio/win/audio_low_latency_input_win_unittest.cc
index 8a9f366..1c67150 100644
--- a/media/audio/win/audio_low_latency_input_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_input_win_unittest.cc
@@ -250,15 +250,31 @@
DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream);
};
+class WinAudioInputTest : public ::testing::Test {
+ public:
+ WinAudioInputTest() {
+ audio_manager_ =
+ AudioManager::CreateForTesting(message_loop_.task_runner());
+ message_loop_.RunUntilIdle();
+ }
+ ~WinAudioInputTest() override {
+ audio_manager_.reset();
+ message_loop_.RunUntilIdle();
+ }
+
+ protected:
+ base::MessageLoop message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
+};
+
// Verify that we can retrieve the current hardware/mixing sample rate
// for all available input devices.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
// Retrieve a list of all available input devices.
media::AudioDeviceNames device_names;
- audio_manager->GetAudioInputDeviceNames(&device_names);
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
// Scan all available input devices and repeat the same test for all of them.
for (media::AudioDeviceNames::const_iterator it = device_names.begin();
@@ -272,30 +288,27 @@
}
// Test Create(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
ais.Close();
}
// Test Open(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
EXPECT_TRUE(ais->Open());
ais.Close();
}
// Test Open(), Start(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
@@ -303,11 +316,10 @@
}
// Test Open(), Start(), Stop(), Close() calling sequence.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
@@ -316,11 +328,10 @@
}
// Test some additional calling sequences.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
ScopedAudioInputStream ais(
- CreateDefaultAudioInputStream(audio_manager.get()));
+ CreateDefaultAudioInputStream(audio_manager_.get()));
WASAPIAudioInputStream* wais =
static_cast<WASAPIAudioInputStream*>(ais.get());
@@ -344,18 +355,16 @@
ais.Close();
}
-TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
int count = 0;
- base::MessageLoopForUI loop;
// 10 ms packet size.
// Create default WASAPI input stream which records in stereo using
// the shared mixing rate. The default buffer size is 10ms.
- AudioInputStreamWrapper aisw(audio_manager.get());
+ AudioInputStreamWrapper aisw(audio_manager_.get());
ScopedAudioInputStream ais(aisw.Create());
EXPECT_TRUE(ais->Open());
@@ -370,9 +379,9 @@
// estimate.
EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _))
.Times(AtLeast(10))
- .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
+ .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &message_loop_));
ais->Start(&sink);
- loop.Run();
+ message_loop_.Run();
ais->Stop();
// Store current packet size (to be used in the subsequent tests).
@@ -390,9 +399,9 @@
EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _))
.Times(AtLeast(10))
- .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
+ .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &message_loop_));
ais->Start(&sink);
- loop.Run();
+ message_loop_.Run();
ais->Stop();
ais.Close();
@@ -406,29 +415,28 @@
EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _))
.Times(AtLeast(10))
- .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
+ .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &message_loop_));
ais->Start(&sink);
- loop.Run();
+ message_loop_.Run();
ais->Stop();
ais.Close();
}
// Test that we can capture a stream in loopback.
-TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_manager->HasAudioOutputDevices() &&
+TEST_F(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices() &&
CoreAudioUtil::IsSupported());
- AudioParameters params = audio_manager->GetInputStreamParameters(
+ AudioParameters params = audio_manager_->GetInputStreamParameters(
AudioManagerBase::kLoopbackInputDeviceId);
EXPECT_EQ(params.effects(), 0);
AudioParameters output_params =
- audio_manager->GetOutputStreamParameters(std::string());
+ audio_manager_->GetOutputStreamParameters(std::string());
EXPECT_EQ(params.sample_rate(), output_params.sample_rate());
EXPECT_EQ(params.channel_layout(), output_params.channel_layout());
- ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream(
+ ScopedAudioInputStream stream(audio_manager_->MakeAudioInputStream(
params, AudioManagerBase::kLoopbackInputDeviceId));
ASSERT_TRUE(stream->Open());
FakeAudioInputCallback sink;
@@ -448,16 +456,15 @@
// To include disabled tests in test execution, just invoke the test program
// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
// environment variable to a value greater than 0.
-TEST(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
+TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
// Name of the output PCM file containing captured data. The output file
// will be stored in the directory containing 'media_unittests.exe'.
// Example of full name: \src\build\Debug\out_stereo_10sec.pcm.
const char* file_name = "out_stereo_10sec.pcm";
- AudioInputStreamWrapper aisw(audio_manager.get());
+ AudioInputStreamWrapper aisw(audio_manager_.get());
ScopedAudioInputStream ais(aisw.Create());
EXPECT_TRUE(ais->Open());
diff --git a/media/audio/win/audio_low_latency_output_win_unittest.cc b/media/audio/win/audio_low_latency_output_win_unittest.cc
index 5b748e7f..c8c6bdf 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -16,7 +16,6 @@
#include "base/time/time.h"
#include "base/win/scoped_com_initializer.h"
#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_unittest_util.h"
#include "media/audio/mock_audio_source_callback.h"
@@ -228,16 +227,32 @@
return aos;
}
+class WASAPIAudioOutputStreamTest : public ::testing::Test {
+ public:
+ WASAPIAudioOutputStreamTest() {
+ audio_manager_ =
+ AudioManager::CreateForTesting(message_loop_.task_runner());
+ message_loop_.RunUntilIdle();
+ }
+ ~WASAPIAudioOutputStreamTest() override {
+ audio_manager_.reset();
+ message_loop_.RunUntilIdle();
+ }
+
+ protected:
+ base::MessageLoopForUI message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
+};
+
// Verify that we can retrieve the current hardware/mixing sample rate
// for the default audio device.
// TODO(henrika): modify this test when we support full device enumeration.
-TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
+TEST_F(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
// Skip this test in exclusive mode since the resulting rate is only utilized
// for shared mode streams.
if (ExclusiveModeIsEnabled())
return;
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
// Default device intended for games, system notification sounds,
// and voice commands.
@@ -247,27 +262,24 @@
}
// Test Create(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, CreateAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, CreateAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
aos->Close();
}
// Test Open(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, OpenAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, OpenAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
EXPECT_TRUE(aos->Open());
aos->Close();
}
// Test Open(), Start(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
EXPECT_TRUE(aos->Open());
MockAudioSourceCallback source;
EXPECT_CALL(source, OnError(aos))
@@ -277,10 +289,9 @@
}
// Test Open(), Start(), Stop(), Close() calling sequence.
-TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
EXPECT_TRUE(aos->Open());
MockAudioSourceCallback source;
EXPECT_CALL(source, OnError(aos))
@@ -291,10 +302,9 @@
}
// Test SetVolume(), GetVolume()
-TEST(WASAPIAudioOutputStreamTest, Volume) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+TEST_F(WASAPIAudioOutputStreamTest, Volume) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
// Initial volume should be full volume (1.0).
double volume = 0.0;
@@ -327,11 +337,10 @@
}
// Test some additional calling sequences.
-TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
+TEST_F(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
- AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
+ AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get());
WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos);
// Open(), Open() is a valid calling sequence (second call does nothing).
@@ -366,16 +375,13 @@
}
// Use preferred packet size and verify that rendering starts.
-TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
+TEST_F(WASAPIAudioOutputStreamTest, ValidPacketSize) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
- base::MessageLoopForUI loop;
MockAudioSourceCallback source;
-
// Create default WASAPI output stream which plays out in stereo using
// the shared mixing rate. The default buffer size is 10ms.
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create();
EXPECT_TRUE(aos->Open());
@@ -386,14 +392,15 @@
// Wait for the first callback and verify its parameters. Ignore any
// subsequent callbacks that might arrive.
EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet), 0))
- .WillOnce(DoAll(QuitLoop(loop.task_runner()),
+ .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()),
Return(aosw.samples_per_packet())))
.WillRepeatedly(Return(0));
aos->Start(&source);
- loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
- TestTimeouts::action_timeout());
- loop.Run();
+ message_loop_.PostDelayedTask(FROM_HERE,
+ base::MessageLoop::QuitWhenIdleClosure(),
+ TestTimeouts::action_timeout());
+ message_loop_.Run();
aos->Stop();
aos->Close();
}
@@ -405,11 +412,10 @@
// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
// environment variable to a value greater than 0.
// The test files are approximately 20 seconds long.
-TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()));
+TEST_F(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()));
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create();
EXPECT_TRUE(aos->Open());
@@ -455,12 +461,11 @@
// The expected outcomes of each setting in this test has been derived
// manually using log outputs (--v=1).
// It's disabled by default because a flag is required to enable exclusive mode.
-TEST(WASAPIAudioOutputStreamTest, DISABLED_ExclusiveModeBufferSizesAt48kHz) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) &&
+TEST_F(WASAPIAudioOutputStreamTest, DISABLED_ExclusiveModeBufferSizesAt48kHz) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) &&
ExclusiveModeIsEnabled());
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
// 10ms @ 48kHz shall work.
// Note that, this is the same size as we can use for shared-mode streaming
@@ -504,12 +509,11 @@
// The expected outcomes of each setting in this test has been derived
// manually using log outputs (--v=1).
// It's disabled by default because a flag is required to enable exclusive mode.
-TEST(WASAPIAudioOutputStreamTest, DISABLED_ExclusiveModeBufferSizesAt44kHz) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) &&
+TEST_F(WASAPIAudioOutputStreamTest, DISABLED_ExclusiveModeBufferSizesAt44kHz) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) &&
ExclusiveModeIsEnabled());
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
// 10ms @ 44.1kHz does not work due to misalignment.
// This test will propose an aligned buffer size of 10.1587ms.
@@ -560,17 +564,15 @@
// Verify that we can open and start the output stream in exclusive mode at
// the lowest possible delay at 48kHz.
// It's disabled by default because a flag is required to enable exclusive mode.
-TEST(WASAPIAudioOutputStreamTest, DISABLED_ExclusiveModeMinBufferSizeAt48kHz) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) &&
+TEST_F(WASAPIAudioOutputStreamTest,
+ DISABLED_ExclusiveModeMinBufferSizeAt48kHz) {
+ ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) &&
ExclusiveModeIsEnabled());
- base::MessageLoopForUI loop;
MockAudioSourceCallback source;
-
// Create exclusive-mode WASAPI output stream which plays out in stereo
// using the minimum buffer size at 48kHz sample rate.
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create(48000, 160);
EXPECT_TRUE(aos->Open());
@@ -580,14 +582,15 @@
// Wait for the first callback and verify its parameters.
EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet), 0))
- .WillOnce(DoAll(QuitLoop(loop.task_runner()),
+ .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()),
Return(aosw.samples_per_packet())))
.WillRepeatedly(Return(aosw.samples_per_packet()));
aos->Start(&source);
- loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
- TestTimeouts::action_timeout());
- loop.Run();
+ message_loop_.PostDelayedTask(FROM_HERE,
+ base::MessageLoop::QuitWhenIdleClosure(),
+ TestTimeouts::action_timeout());
+ message_loop_.Run();
aos->Stop();
aos->Close();
}
@@ -595,16 +598,14 @@
// Verify that we can open and start the output stream in exclusive mode at
// the lowest possible delay at 44.1kHz.
// It's disabled by default because a flag is required to enable exclusive mode.
-TEST(WASAPIAudioOutputStreamTest, DISABLED_ExclusiveModeMinBufferSizeAt44kHz) {
+TEST_F(WASAPIAudioOutputStreamTest,
+ DISABLED_ExclusiveModeMinBufferSizeAt44kHz) {
ABORT_AUDIO_TEST_IF_NOT(ExclusiveModeIsEnabled());
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- base::MessageLoopForUI loop;
MockAudioSourceCallback source;
-
// Create exclusive-mode WASAPI output stream which plays out in stereo
// using the minimum buffer size at 44.1kHz sample rate.
- AudioOutputStreamWrapper aosw(audio_manager.get());
+ AudioOutputStreamWrapper aosw(audio_manager_.get());
AudioOutputStream* aos = aosw.Create(44100, 160);
EXPECT_TRUE(aos->Open());
@@ -614,14 +615,15 @@
// Wait for the first callback and verify its parameters.
EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet), 0))
- .WillOnce(DoAll(QuitLoop(loop.task_runner()),
+ .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()),
Return(aosw.samples_per_packet())))
.WillRepeatedly(Return(aosw.samples_per_packet()));
aos->Start(&source);
- loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
- TestTimeouts::action_timeout());
- loop.Run();
+ message_loop_.PostDelayedTask(FROM_HERE,
+ base::MessageLoop::QuitWhenIdleClosure(),
+ TestTimeouts::action_timeout());
+ message_loop_.Run();
aos->Stop();
aos->Close();
}
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index a3d5ead..df7faf4 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -126,14 +126,19 @@
return (base::win::GetVersion() == base::win::VERSION_VISTA) ? 4 : 3;
}
-AudioManagerWin::AudioManagerWin(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory),
+AudioManagerWin::AudioManagerWin(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory),
// |CoreAudioUtil::IsSupported()| uses static variables to avoid doing
// multiple initializations. This is however not thread safe.
// So, here we call it explicitly before we kick off the audio thread
// or do any other work.
- enumeration_type_(CoreAudioUtil::IsSupported() ?
- kMMDeviceEnumeration : kWaveEnumeration) {
+ enumeration_type_(CoreAudioUtil::IsSupported() ? kMMDeviceEnumeration
+ : kWaveEnumeration) {
SetMaxOutputStreamsAllowed(kMaxOutputStreams);
// WARNING: This is executed on the UI loop, do not add any code here which
@@ -147,10 +152,6 @@
}
AudioManagerWin::~AudioManagerWin() {
- // It's safe to post a task here since Shutdown() will wait for all tasks to
- // complete before returning.
- GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &AudioManagerWin::ShutdownOnAudioThread, base::Unretained(this)));
Shutdown();
}
@@ -174,11 +175,6 @@
}
}
-void AudioManagerWin::ShutdownOnAudioThread() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- output_device_listener_.reset();
-}
-
base::string16 AudioManagerWin::GetAudioInputDeviceModel() {
// Get the default audio capture device and its device interface name.
DWORD device_id = 0;
@@ -537,8 +533,13 @@
}
/// static
-AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
- return new AudioManagerWin(audio_log_factory);
+ScopedAudioManagerPtr CreateAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory) {
+ return ScopedAudioManagerPtr(
+ new AudioManagerWin(std::move(task_runner), std::move(worker_task_runner),
+ audio_log_factory));
}
} // namespace media
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index 583a98b..66b24260 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -19,7 +19,10 @@
// the AudioManager class.
class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
public:
- AudioManagerWin(AudioLogFactory* audio_log_factory);
+ AudioManagerWin(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
// Implementation of AudioManager.
bool HasAudioOutputDevices() override;
@@ -85,7 +88,6 @@
// Helper methods for performing expensive initialization tasks on the audio
// thread instead of on the UI thread which AudioManager is constructed on.
void InitializeOnAudioThread();
- void ShutdownOnAudioThread();
void GetAudioDeviceNamesImpl(bool input, AudioDeviceNames* device_names);
diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc
index 0c59d9b3..8fca2f55 100644
--- a/media/audio/win/audio_output_win_unittest.cc
+++ b/media/audio/win/audio_output_win_unittest.cc
@@ -9,6 +9,7 @@
#include "base/base_paths.h"
#include "base/memory/aligned_memory.h"
+#include "base/message_loop/message_loop.h"
#include "base/sync_socket.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/windows_version.h"
@@ -143,6 +144,23 @@
uint32_t size_;
};
+class WinAudioTest : public ::testing::Test {
+ public:
+ WinAudioTest() {
+ audio_manager_ =
+ AudioManager::CreateForTesting(message_loop_.task_runner());
+ message_loop_.RunUntilIdle();
+ }
+ ~WinAudioTest() override {
+ audio_manager_.reset();
+ message_loop_.RunUntilIdle();
+ }
+
+ protected:
+ base::MessageLoop message_loop_;
+ ScopedAudioManagerPtr audio_manager_;
+};
+
// ===========================================================================
// Validation of AudioManager::AUDIO_PCM_LINEAR
//
@@ -152,11 +170,10 @@
// at some point, possibly when the connection goes idle.
// Test that can it be created and closed.
-TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamGetAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
8000, 16, 256),
std::string());
@@ -165,44 +182,53 @@
}
// Test that can it be cannot be created with invalid parameters.
-TEST(WinAudioTest, SanityOnMakeParams) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, SanityOnMakeParams) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
- std::string()));
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
- std::string()));
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
- std::string()));
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
- std::string()));
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256),
- std::string()));
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
- std::string()));
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
- std::string()));
- EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
- media::limits::kMaxSamplesPerPacket + 1),
- std::string()));
+ EXPECT_TRUE(
+ NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
+ std::string()));
+ EXPECT_TRUE(
+ NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
+ std::string()));
+ EXPECT_TRUE(NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
+ std::string()));
+ EXPECT_TRUE(
+ NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
+ std::string()));
+ EXPECT_TRUE(NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256),
+ std::string()));
+ EXPECT_TRUE(NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
+ std::string()));
+ EXPECT_TRUE(NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
+ std::string()));
+ EXPECT_TRUE(NULL ==
+ audio_manager_->MakeAudioOutputStream(
+ AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
+ media::limits::kMaxSamplesPerPacket + 1),
+ std::string()));
}
// Test that it can be opened and closed.
-TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamOpenAndClose) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
8000, 16, 256),
std::string());
@@ -212,11 +238,10 @@
}
// Test that it has a maximum packet size.
-TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamOpenLimit) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
8000, 16, 1024 * 1024 * 1024),
std::string());
@@ -228,11 +253,10 @@
// Test potential deadlock situation if the source is slow or blocks for some
// time. The actual EXPECT_GT are mostly meaningless and the real test is that
// the test completes in reasonable time.
-TEST(WinAudioTest, PCMWaveSlowSource) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveSlowSource) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
16000, 16, 256),
std::string());
@@ -253,12 +277,11 @@
// Test another potential deadlock situation if the thread that calls Start()
// gets paused. This test is best when run over RDP with audio enabled. See
// bug 19276 for more details.
-TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
std::string());
@@ -281,15 +304,14 @@
// This test produces actual audio for .5 seconds on the default wave
// device at 44.1K s/sec. Parameters have been chosen carefully so you should
// not hear pops or noises while the sound is playing.
-TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- if (!audio_man->HasAudioOutputDevices()) {
+TEST_F(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
+ if (!audio_manager_->HasAudioOutputDevices()) {
LOG(WARNING) << "No output device detected.";
return;
}
uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
std::string());
@@ -309,12 +331,11 @@
// device at 22K s/sec. Parameters have been chosen carefully so you should
// not hear pops or noises while the sound is playing. The audio also should
// sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss.
-TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 20;
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate / 2, 16,
samples_100_ms),
@@ -341,9 +362,8 @@
// Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We
// try hard to generate situation where the two threads are accessing the
// object roughly at the same time.
-TEST(WinAudioTest, PushSourceFile16KHz) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PushSourceFile16KHz) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
static const int kSampleRate = 16000;
SineWaveAudioSource source(1, 200.0, kSampleRate);
@@ -352,7 +372,7 @@
// Restrict SineWaveAudioSource to 100ms of samples.
source.CapSamples(kSamples100ms);
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
kSampleRate, 16, kSamples100ms),
std::string());
@@ -381,12 +401,11 @@
// This test is to make sure an AudioOutputStream can be started after it was
// stopped. You will here two .5 seconds wave signal separated by 0.5 seconds
// of silence.
-TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
std::string());
@@ -415,21 +434,20 @@
// With the low latency mode, WASAPI is utilized by default for Vista and
// higher and Wave is used for XP and lower. It is possible to utilize a
// smaller buffer size for WASAPI than for Wave.
-TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
// Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave.
// Take the existing native sample rate into account.
- const AudioParameters params = audio_man->GetDefaultOutputStreamParameters();
+ const AudioParameters params =
+ audio_manager_->GetDefaultOutputStreamParameters();
int sample_rate = params.sample_rate();
uint32_t samples_10_ms = sample_rate / 100;
int n = 1;
(base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1;
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
- CHANNEL_LAYOUT_MONO, sample_rate,
- 16, n * samples_10_ms),
+ CHANNEL_LAYOUT_MONO, sample_rate, 16, n * samples_10_ms),
std::string());
ASSERT_TRUE(NULL != oas);
@@ -453,12 +471,11 @@
}
// Check that the pending bytes value is correct what the stream starts.
-TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, PCMWaveStreamPendingBytes) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
+ AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
std::string());
@@ -585,18 +602,16 @@
// principle of the test still remains and we avoid the additional complexity
// related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY.
// In this test you should hear a continuous 200Hz tone for 2 seconds.
-TEST(WinAudioTest, SyncSocketBasic) {
- scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
- ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
+TEST_F(WinAudioTest, SyncSocketBasic) {
+ ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices());
static const int sample_rate = AudioParameters::kAudioCDSampleRate;
static const uint32_t kSamples20ms = sample_rate / 50;
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms);
-
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params,
- std::string());
+ AudioOutputStream* oas =
+ audio_manager_->MakeAudioOutputStream(params, std::string());
ASSERT_TRUE(NULL != oas);
ASSERT_TRUE(oas->Open());
diff --git a/media/cast/test/receiver.cc b/media/cast/test/receiver.cc
index d32dd2d0..b452221 100644
--- a/media/cast/test/receiver.cc
+++ b/media/cast/test/receiver.cc
@@ -548,14 +548,15 @@
base::AtExitManager at_exit;
base::CommandLine::Init(argc, argv);
InitLogging(logging::LoggingSettings());
+ base::MessageLoop message_loop;
scoped_refptr<media::cast::CastEnvironment> cast_environment(
new media::cast::StandaloneCastEnvironment);
// Start up Chromium audio system.
- media::FakeAudioLogFactory fake_audio_log_factory_;
- const scoped_ptr<media::AudioManager> audio_manager(
- media::AudioManager::Create(&fake_audio_log_factory_));
+ const media::ScopedAudioManagerPtr audio_manager(
+ media::AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get()));
CHECK(media::AudioManager::Get());
media::cast::FrameReceiverConfig audio_config =
@@ -600,7 +601,7 @@
window_height);
player.Start();
- base::MessageLoop().Run(); // Run forever (i.e., until SIGTERM).
+ message_loop.Run(); // Run forever (i.e., until SIGTERM).
NOTREACHED();
return 0;
}
diff --git a/media/mojo/services/mojo_media_application.cc b/media/mojo/services/mojo_media_application.cc
index 76fd23a..5ef80e5 100644
--- a/media/mojo/services/mojo_media_application.cc
+++ b/media/mojo/services/mojo_media_application.cc
@@ -37,6 +37,11 @@
return true;
}
+bool MojoMediaApplication::ShellConnectionLost() {
+ mojo_media_client_->WillQuit();
+ return true;
+}
+
void MojoMediaApplication::Create(
shell::Connection* connection,
mojo::InterfaceRequest<interfaces::ServiceFactory> request) {
diff --git a/media/mojo/services/mojo_media_application.h b/media/mojo/services/mojo_media_application.h
index 373c221..9682d01 100644
--- a/media/mojo/services/mojo_media_application.h
+++ b/media/mojo/services/mojo_media_application.h
@@ -36,6 +36,7 @@
const shell::Identity& identity,
uint32_t id) final;
bool AcceptConnection(shell::Connection* connection) final;
+ bool ShellConnectionLost() final;
// shell::InterfaceFactory<interfaces::ServiceFactory> implementation.
void Create(shell::Connection* connection,
diff --git a/media/mojo/services/mojo_media_client.cc b/media/mojo/services/mojo_media_client.cc
index 2d81841b..56d16b0 100644
--- a/media/mojo/services/mojo_media_client.cc
+++ b/media/mojo/services/mojo_media_client.cc
@@ -12,6 +12,8 @@
void MojoMediaClient::Initialize() {}
+void MojoMediaClient::WillQuit() {}
+
std::unique_ptr<AudioDecoder> MojoMediaClient::CreateAudioDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
return nullptr;
diff --git a/media/mojo/services/mojo_media_client.h b/media/mojo/services/mojo_media_client.h
index eb923e2..d64c06c 100644
--- a/media/mojo/services/mojo_media_client.h
+++ b/media/mojo/services/mojo_media_client.h
@@ -32,6 +32,10 @@
// Called exactly once before any other method.
virtual void Initialize();
+ // Called before the host application is scheduled to quit.
+ // The application message loop is still valid at this point, so all clean
+ // up tasks requiring the message loop must be completed before returning.
+ virtual void WillQuit();
virtual std::unique_ptr<AudioDecoder> CreateAudioDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
diff --git a/media/mojo/services/test_mojo_media_client.cc b/media/mojo/services/test_mojo_media_client.cc
index 8dbd843..6388e530 100644
--- a/media/mojo/services/test_mojo_media_client.cc
+++ b/media/mojo/services/test_mojo_media_client.cc
@@ -5,6 +5,8 @@
#include "media/mojo/services/test_mojo_media_client.h"
#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_output_stream_sink.h"
#include "media/base/audio_hardware_config.h"
@@ -25,12 +27,14 @@
// TODO(dalecurtis): We should find a single owner per process for the audio
// manager or make it a lazy instance. It's not safe to call Get()/Create()
// across multiple threads...
- //
- // TODO(dalecurtis): Eventually we'll want something other than a fake audio
- // log factory here too. We should probably at least DVLOG() such info.
AudioManager* audio_manager = AudioManager::Get();
- if (!audio_manager)
- audio_manager = media::AudioManager::Create(&fake_audio_log_factory_);
+ if (!audio_manager) {
+ audio_manager_ = media::AudioManager::CreateForTesting(
+ base::ThreadTaskRunnerHandle::Get());
+ audio_manager = audio_manager_.get();
+ // Flush the message loop to ensure that the audio manager is initialized.
+ base::RunLoop().RunUntilIdle();
+ }
audio_hardware_config_.reset(new AudioHardwareConfig(
audio_manager->GetInputStreamParameters(
@@ -38,6 +42,15 @@
audio_manager->GetDefaultOutputStreamParameters()));
}
+void TestMojoMediaClient::WillQuit() {
+ DVLOG(1) << __FUNCTION__;
+ // AudioManager destructor requires MessageLoop.
+ // Destroy it before the message loop goes away.
+ audio_manager_.reset();
+ // Flush the message loop to ensure that the audio manager is destroyed.
+ base::RunLoop().RunUntilIdle();
+}
+
std::unique_ptr<RendererFactory> TestMojoMediaClient::CreateRendererFactory(
const scoped_refptr<MediaLog>& media_log) {
DVLOG(1) << __FUNCTION__;
diff --git a/media/mojo/services/test_mojo_media_client.h b/media/mojo/services/test_mojo_media_client.h
index 8bf795cd..5494e365 100644
--- a/media/mojo/services/test_mojo_media_client.h
+++ b/media/mojo/services/test_mojo_media_client.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "media/audio/fake_audio_log_factory.h"
+#include "media/audio/audio_manager.h"
#include "media/mojo/services/mojo_media_client.h"
namespace media {
@@ -26,6 +26,7 @@
// MojoMediaClient implementation.
void Initialize() final;
+ void WillQuit() final;
std::unique_ptr<RendererFactory> CreateRendererFactory(
const scoped_refptr<MediaLog>& media_log) final;
AudioRendererSink* CreateAudioRendererSink() final;
@@ -35,7 +36,7 @@
shell::mojom::InterfaceProvider* /* interface_provider */) final;
private:
- FakeAudioLogFactory fake_audio_log_factory_;
+ ScopedAudioManagerPtr audio_manager_;
std::unique_ptr<AudioHardwareConfig> audio_hardware_config_;
scoped_refptr<AudioRendererSink> audio_renderer_sink_;
std::unique_ptr<VideoRendererSink> video_renderer_sink_;