Index: media/audio/android/audio_android_unittest.cc |
diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc |
index 91bf5d8461b663e21b9d0d652d5ffc3a379dd9cf..0dc31254afb94d88fbf33907293a14301a37505a 100644 |
--- a/media/audio/android/audio_android_unittest.cc |
+++ b/media/audio/android/audio_android_unittest.cc |
@@ -8,6 +8,7 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop/message_loop.h" |
#include "base/path_service.h" |
+#include "base/run_loop.h" |
#include "base/strings/stringprintf.h" |
#include "base/synchronization/lock.h" |
#include "base/synchronization/waitable_event.h" |
@@ -410,23 +411,76 @@ class FullDuplexAudioSinkSource |
// Test fixture class for tests which only exercise the output path. |
class AudioAndroidOutputTest : public testing::Test { |
public: |
- AudioAndroidOutputTest() {} |
- |
- protected: |
- virtual void SetUp() { |
- audio_manager_.reset(AudioManager::CreateForTesting()); |
- loop_.reset(new base::MessageLoopForUI()); |
+ AudioAndroidOutputTest() |
+ : loop_(new base::MessageLoopForUI()), |
+ audio_manager_(AudioManager::CreateForTesting()), |
+ audio_output_stream_(NULL) { |
} |
- virtual void TearDown() {} |
+ virtual ~AudioAndroidOutputTest() { |
+ } |
+ protected: |
AudioManager* audio_manager() { return audio_manager_.get(); } |
base::MessageLoopForUI* loop() { return loop_.get(); } |
+ AudioOutputStream* audio_output_stream() const { |
+ return audio_output_stream_; |
+ } |
+ |
+ // 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(&AudioAndroidOutputTest::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(); |
+ } |
AudioParameters GetDefaultOutputStreamParameters() { |
return audio_manager()->GetDefaultOutputStreamParameters(); |
} |
+ void MakeAOSOnAudioThread(const AudioParameters& params) { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidOutputTest::MakeOutputStream, |
+ base::Unretained(this), |
+ params)); |
+ } |
+ |
+ void OpenAndCloseAOSOnAudioThread() { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidOutputTest::OpenAndClose, |
+ base::Unretained(this))); |
+ } |
+ |
+ void OpenAndStartAOSOnAudioThread( |
+ AudioOutputStream::AudioSourceCallback* source) { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidOutputTest::OpenAndStart, |
+ base::Unretained(this), |
+ source)); |
+ } |
+ |
+ void StopAndCloseAOSOnAudioThread() { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidOutputTest::StopAndClose, |
+ base::Unretained(this))); |
+ } |
+ |
double AverageTimeBetweenCallbacks(int num_callbacks) const { |
return ((end_time_ - start_time_) / static_cast<double>(num_callbacks - 1)) |
.InMillisecondsF(); |
@@ -437,9 +491,8 @@ class AudioAndroidOutputTest : public testing::Test { |
ExpectedTimeBetweenCallbacks(params); |
const int num_callbacks = |
(kCallbackTestTimeMs / expected_time_between_callbacks_ms); |
- AudioOutputStream* stream = audio_manager()->MakeAudioOutputStream( |
- params, std::string(), std::string()); |
- EXPECT_TRUE(stream); |
+ |
+ MakeAOSOnAudioThread(params); |
int count = 0; |
MockAudioSourceCallback source; |
@@ -449,16 +502,16 @@ class AudioAndroidOutputTest : public testing::Test { |
.WillRepeatedly( |
DoAll(CheckCountAndPostQuitTask(&count, num_callbacks, loop()), |
Invoke(RealOnMoreData))); |
- EXPECT_CALL(source, OnError(stream)).Times(0); |
+ EXPECT_CALL(source, OnError(audio_output_stream())).Times(0); |
EXPECT_CALL(source, OnMoreIOData(_, _, _)).Times(0); |
- EXPECT_TRUE(stream->Open()); |
- stream->Start(&source); |
+ OpenAndStartAOSOnAudioThread(&source); |
+ |
start_time_ = base::TimeTicks::Now(); |
loop()->Run(); |
end_time_ = base::TimeTicks::Now(); |
- stream->Stop(); |
- stream->Close(); |
+ |
+ StopAndCloseAOSOnAudioThread(); |
double average_time_between_callbacks_ms = |
AverageTimeBetweenCallbacks(num_callbacks); |
@@ -472,8 +525,34 @@ class AudioAndroidOutputTest : public testing::Test { |
1.30 * expected_time_between_callbacks_ms); |
} |
+ void MakeOutputStream(const AudioParameters& params) { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ audio_output_stream_ = audio_manager()->MakeAudioOutputStream( |
+ params, std::string(), std::string()); |
+ EXPECT_TRUE(audio_output_stream_); |
+ } |
+ |
+ void OpenAndClose() { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ EXPECT_TRUE(audio_output_stream()->Open()); |
+ audio_output_stream()->Close(); |
+ } |
+ |
+ void OpenAndStart(AudioOutputStream::AudioSourceCallback* source) { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ EXPECT_TRUE(audio_output_stream()->Open()); |
+ audio_output_stream()->Start(source); |
+ } |
+ |
+ void StopAndClose() { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ audio_output_stream()->Stop(); |
+ audio_output_stream()->Close(); |
+ } |
+ |
scoped_ptr<base::MessageLoopForUI> loop_; |
scoped_ptr<AudioManager> audio_manager_; |
+ AudioOutputStream* audio_output_stream_; |
base::TimeTicks start_time_; |
base::TimeTicks end_time_; |
@@ -497,9 +576,11 @@ std::vector<bool> RunAudioRecordInputPathTests() { |
class AudioAndroidInputTest : public AudioAndroidOutputTest, |
public testing::WithParamInterface<bool> { |
public: |
- AudioAndroidInputTest() {} |
+ AudioAndroidInputTest() : audio_input_stream_(NULL) {} |
protected: |
+ AudioInputStream* audio_input_stream() { return audio_input_stream_; } |
+ |
AudioParameters GetInputStreamParameters() { |
AudioParameters input_params = audio_manager()->GetInputStreamParameters( |
AudioManagerBase::kDefaultDeviceId); |
@@ -517,32 +598,61 @@ class AudioAndroidInputTest : public AudioAndroidOutputTest, |
return params; |
} |
+ void MakeAISOnAudioThread(const AudioParameters& params) { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidInputTest::MakeInputStream, |
+ base::Unretained(this), |
+ params)); |
+ } |
+ |
+ void OpenAndCloseAISOnAudioThread() { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidInputTest::OpenAndClose, |
+ base::Unretained(this))); |
+ } |
+ |
+ void OpenAndStartAISOnAudioThread( |
+ AudioInputStream::AudioInputCallback* sink) { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidInputTest::OpenAndStart, |
+ base::Unretained(this), |
+ sink)); |
+ } |
+ |
+ void StopAndCloseAISOnAudioThread() { |
+ RunOnAudioThread( |
+ base::Bind(&AudioAndroidInputTest::StopAndClose, |
+ base::Unretained(this))); |
+ } |
+ |
void StartInputStreamCallbacks(const AudioParameters& params) { |
double expected_time_between_callbacks_ms = |
ExpectedTimeBetweenCallbacks(params); |
const int num_callbacks = |
(kCallbackTestTimeMs / expected_time_between_callbacks_ms); |
- AudioInputStream* stream = audio_manager()->MakeAudioInputStream( |
- params, AudioManagerBase::kDefaultDeviceId); |
- EXPECT_TRUE(stream); |
+ |
+ MakeAISOnAudioThread(params); |
int count = 0; |
MockAudioInputCallback sink; |
EXPECT_CALL(sink, |
- OnData(stream, NotNull(), params.GetBytesPerBuffer(), _, _)) |
+ OnData(audio_input_stream(), |
+ NotNull(), |
+ params. |
+ GetBytesPerBuffer(), _, _)) |
.Times(AtLeast(num_callbacks)) |
.WillRepeatedly( |
CheckCountAndPostQuitTask(&count, num_callbacks, loop())); |
- EXPECT_CALL(sink, OnError(stream)).Times(0); |
+ EXPECT_CALL(sink, OnError(audio_input_stream())).Times(0); |
+ |
+ OpenAndStartAISOnAudioThread(&sink); |
- EXPECT_TRUE(stream->Open()); |
- stream->Start(&sink); |
start_time_ = base::TimeTicks::Now(); |
loop()->Run(); |
end_time_ = base::TimeTicks::Now(); |
- stream->Stop(); |
- stream->Close(); |
+ |
+ StopAndCloseAISOnAudioThread(); |
double average_time_between_callbacks_ms = |
AverageTimeBetweenCallbacks(num_callbacks); |
@@ -556,8 +666,33 @@ class AudioAndroidInputTest : public AudioAndroidOutputTest, |
1.30 * expected_time_between_callbacks_ms); |
} |
+ void MakeInputStream(const AudioParameters& params) { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ audio_input_stream_ = audio_manager()->MakeAudioInputStream( |
+ params, AudioManagerBase::kDefaultDeviceId); |
+ EXPECT_TRUE(audio_input_stream_); |
+ } |
+ |
+ void OpenAndClose() { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ EXPECT_TRUE(audio_input_stream()->Open()); |
+ audio_input_stream()->Close(); |
+ } |
+ |
+ void OpenAndStart(AudioInputStream::AudioInputCallback* sink) { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ EXPECT_TRUE(audio_input_stream()->Open()); |
+ audio_input_stream()->Start(sink); |
+ } |
+ |
+ void StopAndClose() { |
+ DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); |
+ audio_input_stream()->Stop(); |
+ audio_input_stream()->Close(); |
+ } |
private: |
+ AudioInputStream* audio_input_stream_; |
DISALLOW_COPY_AND_ASSIGN(AudioAndroidInputTest); |
}; |
@@ -578,16 +713,10 @@ TEST_F(AudioAndroidOutputTest, GetDefaultOutputStreamParameters) { |
VLOG(1) << params; |
} |
-// Check if low-latency output is supported and log the result as output. |
-TEST_F(AudioAndroidOutputTest, IsAudioLowLatencySupported) { |
- AudioManagerAndroid* manager = |
- static_cast<AudioManagerAndroid*>(audio_manager()); |
- bool low_latency = manager->IsAudioLowLatencySupported(); |
- low_latency ? VLOG(0) << "Low latency output is supported" |
- : VLOG(0) << "Low latency output is *not* supported"; |
-} |
- |
// Verify input device enumeration. |
+// GetAudioInputDeviceNames() is mainly called from a dedicated device thread |
+// in Chrome but perform the test on the main thread here. The call will be |
+// sent to the audio thread in AudioManagerAndroid::GetAudioInputDeviceNames(). |
TEST_F(AudioAndroidInputTest, GetAudioInputDeviceNames) { |
if (!audio_manager()->HasAudioInputDevices()) |
return; |
@@ -608,10 +737,10 @@ TEST_F(AudioAndroidOutputTest, GetAudioOutputDeviceNames) { |
// Ensure that a default input stream can be created and closed. |
TEST_P(AudioAndroidInputTest, CreateAndCloseInputStream) { |
AudioParameters params = GetInputStreamParameters(); |
- AudioInputStream* ais = audio_manager()->MakeAudioInputStream( |
- params, AudioManagerBase::kDefaultDeviceId); |
- EXPECT_TRUE(ais); |
- ais->Close(); |
+ MakeAISOnAudioThread(params); |
+ RunOnAudioThread( |
+ base::Bind(&AudioInputStream::Close, |
+ base::Unretained(audio_input_stream()))); |
} |
// Ensure that a default output stream can be created and closed. |
@@ -620,46 +749,37 @@ TEST_P(AudioAndroidInputTest, CreateAndCloseInputStream) { |
// it is called? |
TEST_F(AudioAndroidOutputTest, CreateAndCloseOutputStream) { |
AudioParameters params = GetDefaultOutputStreamParameters(); |
- AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream( |
- params, std::string(), std::string()); |
- EXPECT_TRUE(aos); |
- aos->Close(); |
+ MakeAOSOnAudioThread(params); |
+ RunOnAudioThread( |
+ base::Bind(&AudioOutputStream::Close, |
+ base::Unretained(audio_output_stream()))); |
} |
// Ensure that a default input stream can be opened and closed. |
TEST_P(AudioAndroidInputTest, OpenAndCloseInputStream) { |
AudioParameters params = GetInputStreamParameters(); |
- AudioInputStream* ais = audio_manager()->MakeAudioInputStream( |
- params, AudioManagerBase::kDefaultDeviceId); |
- EXPECT_TRUE(ais); |
- EXPECT_TRUE(ais->Open()); |
- ais->Close(); |
+ MakeAISOnAudioThread(params); |
+ OpenAndCloseAISOnAudioThread(); |
} |
// Ensure that a default output stream can be opened and closed. |
TEST_F(AudioAndroidOutputTest, OpenAndCloseOutputStream) { |
AudioParameters params = GetDefaultOutputStreamParameters(); |
- AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream( |
- params, std::string(), std::string()); |
- EXPECT_TRUE(aos); |
- EXPECT_TRUE(aos->Open()); |
- aos->Close(); |
+ MakeAOSOnAudioThread(params); |
+ OpenAndCloseAOSOnAudioThread(); |
} |
// Start input streaming using default input parameters and ensure that the |
// callback sequence is sane. |
-// Disabled per crbug/337867 |
-TEST_P(AudioAndroidInputTest, DISABLED_StartInputStreamCallbacks) { |
- AudioParameters params = GetInputStreamParameters(); |
- StartInputStreamCallbacks(params); |
+TEST_P(AudioAndroidInputTest, StartInputStreamCallbacks) { |
+ AudioParameters native_params = GetInputStreamParameters(); |
+ StartInputStreamCallbacks(native_params); |
} |
// Start input streaming using non default input parameters and ensure that the |
// callback sequence is sane. The only change we make in this test is to select |
// a 10ms buffer size instead of the default size. |
-// TODO(henrika): possibly add support for more variations. |
-// Disabled per crbug/337867 |
-TEST_P(AudioAndroidInputTest, DISABLED_StartInputStreamCallbacksNonDefaultParameters) { |
+TEST_P(AudioAndroidInputTest, StartInputStreamCallbacksNonDefaultParameters) { |
AudioParameters native_params = GetInputStreamParameters(); |
AudioParameters params(native_params.format(), |
native_params.channel_layout(), |
@@ -700,9 +820,7 @@ TEST_F(AudioAndroidOutputTest, StartOutputStreamCallbacksNonDefaultParameters) { |
TEST_F(AudioAndroidOutputTest, DISABLED_RunOutputStreamWithFileAsSource) { |
AudioParameters params = GetDefaultOutputStreamParameters(); |
VLOG(1) << params; |
- AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream( |
- params, std::string(), std::string()); |
- EXPECT_TRUE(aos); |
+ MakeAOSOnAudioThread(params); |
std::string file_name; |
if (params.sample_rate() == 48000 && params.channels() == 2) { |
@@ -721,13 +839,10 @@ TEST_F(AudioAndroidOutputTest, DISABLED_RunOutputStreamWithFileAsSource) { |
base::WaitableEvent event(false, false); |
FileAudioSource source(&event, file_name); |
- EXPECT_TRUE(aos->Open()); |
- aos->SetVolume(1.0); |
- aos->Start(&source); |
+ OpenAndStartAOSOnAudioThread(&source); |
VLOG(0) << ">> Verify that the file is played out correctly..."; |
EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout())); |
- aos->Stop(); |
- aos->Close(); |
+ StopAndCloseAOSOnAudioThread(); |
} |
// Start input streaming and run it for ten seconds while recording to a |
@@ -737,9 +852,7 @@ TEST_F(AudioAndroidOutputTest, DISABLED_RunOutputStreamWithFileAsSource) { |
TEST_P(AudioAndroidInputTest, DISABLED_RunSimplexInputStreamWithFileAsSink) { |
AudioParameters params = GetInputStreamParameters(); |
VLOG(1) << params; |
- AudioInputStream* ais = audio_manager()->MakeAudioInputStream( |
- params, AudioManagerBase::kDefaultDeviceId); |
- EXPECT_TRUE(ais); |
+ MakeAISOnAudioThread(params); |
std::string file_name = base::StringPrintf("out_simplex_%d_%d_%d.pcm", |
params.sample_rate(), |
@@ -749,12 +862,10 @@ TEST_P(AudioAndroidInputTest, DISABLED_RunSimplexInputStreamWithFileAsSink) { |
base::WaitableEvent event(false, false); |
FileAudioSink sink(&event, params, file_name); |
- EXPECT_TRUE(ais->Open()); |
- ais->Start(&sink); |
+ OpenAndStartAISOnAudioThread(&sink); |
VLOG(0) << ">> Speak into the microphone to record audio..."; |
EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout())); |
- ais->Stop(); |
- ais->Close(); |
+ StopAndCloseAISOnAudioThread(); |
} |
// Same test as RunSimplexInputStreamWithFileAsSink but this time output |
@@ -763,15 +874,13 @@ TEST_P(AudioAndroidInputTest, DISABLED_RunSimplexInputStreamWithFileAsSink) { |
// automatized test on bots. |
TEST_P(AudioAndroidInputTest, DISABLED_RunDuplexInputStreamWithFileAsSink) { |
AudioParameters in_params = GetInputStreamParameters(); |
- AudioInputStream* ais = audio_manager()->MakeAudioInputStream( |
- in_params, AudioManagerBase::kDefaultDeviceId); |
- EXPECT_TRUE(ais); |
+ VLOG(1) << in_params; |
+ MakeAISOnAudioThread(in_params); |
AudioParameters out_params = |
audio_manager()->GetDefaultOutputStreamParameters(); |
- AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream( |
- out_params, std::string(), std::string()); |
- EXPECT_TRUE(aos); |
+ VLOG(1) << out_params; |
+ MakeAOSOnAudioThread(out_params); |
std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm", |
in_params.sample_rate(), |
@@ -784,19 +893,15 @@ TEST_P(AudioAndroidInputTest, DISABLED_RunDuplexInputStreamWithFileAsSink) { |
EXPECT_CALL(source, OnMoreData(NotNull(), _)) |
.WillRepeatedly(Invoke(RealOnMoreData)); |
- EXPECT_CALL(source, OnError(aos)).Times(0); |
+ EXPECT_CALL(source, OnError(audio_output_stream())).Times(0); |
EXPECT_CALL(source, OnMoreIOData(_, _, _)).Times(0); |
- EXPECT_TRUE(ais->Open()); |
- EXPECT_TRUE(aos->Open()); |
- ais->Start(&sink); |
- aos->Start(&source); |
+ OpenAndStartAISOnAudioThread(&sink); |
+ OpenAndStartAOSOnAudioThread(&source); |
VLOG(0) << ">> Speak into the microphone to record audio"; |
EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout())); |
- aos->Stop(); |
- ais->Stop(); |
- aos->Close(); |
- ais->Close(); |
+ StopAndCloseAOSOnAudioThread(); |
+ StopAndCloseAISOnAudioThread(); |
} |
// Start audio in both directions while feeding captured data into a FIFO so |
@@ -825,12 +930,8 @@ TEST_P(AudioAndroidInputTest, |
VLOG(1) << io_params; |
// Create input and output streams using the common audio parameters. |
- AudioInputStream* ais = audio_manager()->MakeAudioInputStream( |
- io_params, AudioManagerBase::kDefaultDeviceId); |
- EXPECT_TRUE(ais); |
- AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream( |
- io_params, std::string(), std::string()); |
- EXPECT_TRUE(aos); |
+ MakeAISOnAudioThread(io_params); |
+ MakeAOSOnAudioThread(io_params); |
FullDuplexAudioSinkSource full_duplex(io_params); |
@@ -838,20 +939,16 @@ TEST_P(AudioAndroidInputTest, |
// delay we should expect from the FIFO. If real-time delay measurements are |
// performed, the result should be reduced by this extra delay since it is |
// something that has been added by the test. |
- EXPECT_TRUE(ais->Open()); |
- EXPECT_TRUE(aos->Open()); |
- ais->Start(&full_duplex); |
- aos->Start(&full_duplex); |
+ OpenAndStartAISOnAudioThread(&full_duplex); |
+ OpenAndStartAOSOnAudioThread(&full_duplex); |
VLOG(1) << "HINT: an estimate of the extra FIFO delay will be updated " |
<< "once per second during this test."; |
VLOG(0) << ">> Speak into the mic and listen to the audio in loopback..."; |
fflush(stdout); |
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20)); |
printf("\n"); |
- aos->Stop(); |
- ais->Stop(); |
- aos->Close(); |
- ais->Close(); |
+ StopAndCloseAOSOnAudioThread(); |
+ StopAndCloseAISOnAudioThread(); |
} |
INSTANTIATE_TEST_CASE_P(AudioAndroidInputTest, AudioAndroidInputTest, |