Commit 2f481bd4 authored by Thomas Guilbert's avatar Thomas Guilbert Committed by Commit Bot

Add AAudio output audio driver

This CL add the necessary boilerplate to dynamically load the AAudio
library, along with an output audio stream implementation built on top
of AAudio.

Change-Id: If07039e278ea8aadace44a03e2c2035073047f03
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1814543
Commit-Queue: Thomas Guilbert <tguilbert@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699094}
parent e4e1a4c6
...@@ -19,6 +19,17 @@ if (use_pulseaudio && !link_pulseaudio) { ...@@ -19,6 +19,17 @@ if (use_pulseaudio && !link_pulseaudio) {
} }
} }
if (is_android) {
generate_stubs("aaudio_stubs") {
extra_header = "android/aaudio_stub_header.fragment"
sigs = [ "android/aaudio.sigs" ]
output_name = "android/aaudio_stubs"
deps = [
"//base",
]
}
}
config("platform_config") { config("platform_config") {
defines = [] defines = []
if (is_chromecast) { if (is_chromecast) {
...@@ -217,6 +228,8 @@ source_set("audio") { ...@@ -217,6 +228,8 @@ source_set("audio") {
if (is_android) { if (is_android) {
sources += [ sources += [
"android/aaudio_output.cc",
"android/aaudio_output.h",
"android/audio_manager_android.cc", "android/audio_manager_android.cc",
"android/audio_manager_android.h", "android/audio_manager_android.h",
"android/audio_track_output_stream.cc", "android/audio_track_output_stream.cc",
...@@ -231,7 +244,10 @@ source_set("audio") { ...@@ -231,7 +244,10 @@ source_set("audio") {
"android/opensles_wrapper.cc", "android/opensles_wrapper.cc",
] ]
deps += [ "//media/base/android:media_jni_headers" ] deps += [
":aaudio_stubs",
"//media/base/android:media_jni_headers",
]
} }
if (is_linux) { if (is_linux) {
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//------------------------------------------------
// Functions from AAudio used in media code.
//------------------------------------------------
const char * AAudio_convertResultToText(aaudio_result_t returnCode);
aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder);
void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder, int32_t deviceId);
void AAudioStreamBuilder_setSampleRate(AAudioStreamBuilder* builder, int32_t sampleRate);
void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder, int32_t channelCount);
void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder, int32_t samplesPerFrame);
void AAudioStreamBuilder_setFormat(AAudioStreamBuilder* builder, aaudio_format_t format);
void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder, aaudio_direction_t direction);
void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder, int32_t numFrames);
void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder, aaudio_performance_mode_t mode);
void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder, int32_t numFrames);
void AAudioStreamBuilder_setUsage(AAudioStreamBuilder* builder, aaudio_usage_t usage);
void AAudioStreamBuilder_setDataCallback(AAudioStreamBuilder* builder, AAudioStream_dataCallback callback, void *userData);
void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builder, AAudioStream_errorCallback callback, void *userData);
aaudio_result_t AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder, AAudioStream** stream);
aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* builder);
aaudio_result_t AAudioStream_close(AAudioStream* stream);
aaudio_result_t AAudioStream_requestStart(AAudioStream* stream);
aaudio_result_t AAudioStream_requestStop(AAudioStream* stream);
aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream, clockid_t clockid, int64_t *framePosition, int64_t *timeNanoseconds);
int64_t AAudioStream_getFramesWritten(AAudioStream* stream);
\ No newline at end of file
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/audio/android/aaudio_output.h"
#include "base/logging.h"
#include "media/audio/android/aaudio_stubs.h"
#include "media/audio/android/audio_manager_android.h"
#include "media/base/audio_bus.h"
namespace media {
static aaudio_data_callback_result_t OnAudioDataRequestedCallback(
AAudioStream* stream,
void* user_data,
void* audio_data,
int32_t num_frames) {
AAudioOutputStream* output_stream =
reinterpret_cast<AAudioOutputStream*>(user_data);
return output_stream->OnAudioDataRequested(audio_data, num_frames);
}
static void OnStreamErrorCallback(AAudioStream* stream,
void* user_data,
aaudio_result_t error) {
AAudioOutputStream* output_stream =
reinterpret_cast<AAudioOutputStream*>(user_data);
output_stream->OnStreamError(error);
}
AAudioOutputStream::AAudioOutputStream(AudioManagerAndroid* manager,
const AudioParameters& params,
aaudio_usage_t usage)
: audio_manager_(manager),
params_(params),
usage_(usage),
performance_mode_(AAUDIO_PERFORMANCE_MODE_NONE),
ns_per_frame_(base::Time::kNanosecondsPerSecond /
static_cast<double>(params.sample_rate())) {
DCHECK(manager);
DCHECK(params.IsValid());
if (AudioManagerAndroid::SupportsPerformanceModeForOutput()) {
if (params.latency_tag() == AudioLatency::LATENCY_PLAYBACK)
performance_mode_ = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
else if (params.latency_tag() == AudioLatency::LATENCY_RTC)
performance_mode_ = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
}
}
AAudioOutputStream::~AAudioOutputStream() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
void AAudioOutputStream::Flush() {}
bool AAudioOutputStream::Open() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
AAudioStreamBuilder* builder;
auto result = AAudio_createStreamBuilder(&builder);
if (AAUDIO_OK != result)
return false;
// Parameters
AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
AAudioStreamBuilder_setSampleRate(builder, params_.sample_rate());
AAudioStreamBuilder_setChannelCount(builder, params_.channels());
AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
AAudioStreamBuilder_setUsage(builder, usage_);
AAudioStreamBuilder_setPerformanceMode(builder, performance_mode_);
AAudioStreamBuilder_setBufferCapacityInFrames(builder,
params_.frames_per_buffer());
AAudioStreamBuilder_setFramesPerDataCallback(builder,
params_.frames_per_buffer());
// Callbacks
AAudioStreamBuilder_setDataCallback(builder, OnAudioDataRequestedCallback,
this);
AAudioStreamBuilder_setErrorCallback(builder, OnStreamErrorCallback, this);
result = AAudioStreamBuilder_openStream(builder, &aaudio_stream_);
AAudioStreamBuilder_delete(builder);
if (AAUDIO_OK != result)
return false;
audio_bus_ = AudioBus::Create(params_);
return true;
}
void AAudioOutputStream::Close() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Stop();
if (aaudio_stream_) {
const auto result = AAudioStream_close(aaudio_stream_);
if (result != AAUDIO_OK) {
DLOG(ERROR) << "Failed to close audio stream, result: "
<< AAudio_convertResultToText(result);
}
}
// Note: This must be last, it will delete |this|.
audio_manager_->ReleaseOutputStream(this);
}
void AAudioOutputStream::Start(AudioSourceCallback* callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(aaudio_stream_);
{
base::AutoLock al(lock_);
DCHECK(!callback_);
callback_ = callback;
}
auto result = AAudioStream_requestStart(aaudio_stream_);
if (result != AAUDIO_OK) {
DLOG(ERROR) << "Failed to start audio stream, result: "
<< AAudio_convertResultToText(result);
// Lock is required in case a previous asynchronous requestStop() still has
// not completed by the time we reach this point.
base::AutoLock al(lock_);
callback_->OnError();
callback_ = nullptr;
}
}
void AAudioOutputStream::Stop() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::AutoLock al(lock_);
if (!callback_ || !aaudio_stream_)
return;
// Note: This call is asynchronous, so we must clear |callback_| under lock
// below to ensure no further calls occur after Stop().
auto result = AAudioStream_requestStop(aaudio_stream_);
if (result != AAUDIO_OK) {
DLOG(ERROR) << "Failed to stop audio stream, result: "
<< AAudio_convertResultToText(result);
callback_->OnError();
}
callback_ = nullptr;
}
base::TimeDelta AAudioOutputStream::GetDelay(base::TimeTicks delay_timestamp) {
// Get the time that a known audio frame was presented for playing.
int64_t existing_frame_index;
int64_t existing_frame_pts;
auto result =
AAudioStream_getTimestamp(aaudio_stream_, CLOCK_MONOTONIC,
&existing_frame_index, &existing_frame_pts);
if (result != AAUDIO_OK) {
DLOG(ERROR) << "Failed to get audio latency, result: "
<< AAudio_convertResultToText(result);
return base::TimeDelta();
}
// Calculate the number of frames between our known frame and the write index.
const int64_t frame_index_delta =
AAudioStream_getFramesWritten(aaudio_stream_) - existing_frame_index;
// Calculate the time which the next frame will be presented.
const base::TimeDelta next_frame_pts = base::TimeDelta::FromNanosecondsD(
existing_frame_pts + frame_index_delta * ns_per_frame_);
// Calculate the latency between write time and presentation time.
return next_frame_pts - (delay_timestamp - base::TimeTicks());
}
aaudio_data_callback_result_t AAudioOutputStream::OnAudioDataRequested(
void* audio_data,
int32_t num_frames) {
// TODO(tguilbert): This can be downgraded to a DCHECK after we've launched.
CHECK_EQ(num_frames, audio_bus_->frames());
base::AutoLock al(lock_);
if (!callback_)
return AAUDIO_CALLBACK_RESULT_STOP;
const base::TimeTicks delay_timestamp = base::TimeTicks::Now();
const base::TimeDelta delay = GetDelay(delay_timestamp);
const int frames_filled =
callback_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get());
audio_bus_->Scale(muted_ ? 0.0 : volume_);
audio_bus_->ToInterleaved<Float32SampleTypeTraits>(
frames_filled, reinterpret_cast<float*>(audio_data));
return AAUDIO_CALLBACK_RESULT_CONTINUE;
}
void AAudioOutputStream::OnStreamError(aaudio_result_t error) {
base::AutoLock al(lock_);
if (callback_)
callback_->OnError();
}
void AAudioOutputStream::SetVolume(double volume) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
double volume_override = 0;
if (audio_manager_->HasOutputVolumeOverride(&volume_override))
volume = volume_override;
if (volume < 0.0 || volume > 1.0)
return;
base::AutoLock al(lock_);
volume_ = volume;
}
void AAudioOutputStream::GetVolume(double* volume) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::AutoLock al(lock_);
*volume = volume_;
}
void AAudioOutputStream::SetMute(bool muted) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::AutoLock al(lock_);
muted_ = muted;
}
} // namespace media
\ No newline at end of file
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_AUDIO_ANDROID_AAUDIO_OUTPUT_H_
#define MEDIA_AUDIO_ANDROID_AAUDIO_OUTPUT_H_
#include <aaudio/AAudio.h>
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/threading/thread_checker.h"
#include "media/audio/android/muteable_audio_output_stream.h"
#include "media/base/audio_parameters.h"
namespace media {
class AudioManagerAndroid;
class AAudioOutputStream : public MuteableAudioOutputStream {
public:
AAudioOutputStream(AudioManagerAndroid* manager,
const AudioParameters& params,
aaudio_usage_t usage);
~AAudioOutputStream() override;
// Implementation of MuteableAudioOutputStream.
bool Open() override;
void Close() override;
void Start(AudioSourceCallback* callback) override;
void Stop() override;
void Flush() override;
void SetVolume(double volume) override;
void GetVolume(double* volume) override;
void SetMute(bool muted) override;
// Public callbacks.
aaudio_data_callback_result_t OnAudioDataRequested(void* audio_data,
int32_t num_frames);
void OnStreamError(aaudio_result_t error);
private:
// Returns the amount of unplayed audio relative to |delay_timestamp|. See the
// definition for AudioOutputStream::AudioSourceCallback::OnMoreData() for
// more information on these terms.
base::TimeDelta GetDelay(base::TimeTicks delay_timestamp);
THREAD_CHECKER(thread_checker_);
AudioManagerAndroid* const audio_manager_;
const AudioParameters params_;
aaudio_usage_t usage_;
aaudio_performance_mode_t performance_mode_;
// Constant used for calculating latency. Amount of nanoseconds per frame.
const double ns_per_frame_;
std::unique_ptr<AudioBus> audio_bus_;
AAudioStream* aaudio_stream_ = nullptr;
// Lock protects all members below which may be read concurrently from the
// audio manager thread and the OS provided audio thread.
base::Lock lock_;
AudioSourceCallback* callback_ GUARDED_BY(lock_) = nullptr;
bool muted_ GUARDED_BY(lock_) = false;
double volume_ GUARDED_BY(lock_) = 1.0;
DISALLOW_COPY_AND_ASSIGN(AAudioOutputStream);
};
} // namespace media
#endif // MEDIA_AUDIO_ANDROID_AAUDIO_OUTPUT_H_
\ No newline at end of file
// The extra include header needed in the generated stub file for defining
// various AAudio types.
extern "C" {
#include <aaudio/AAudio.h>
}
...@@ -11,12 +11,16 @@ ...@@ -11,12 +11,16 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "media/audio/android/aaudio_output.h"
#include "media/audio/android/aaudio_stubs.h"
#include "media/audio/android/audio_track_output_stream.h" #include "media/audio/android/audio_track_output_stream.h"
#include "media/audio/android/opensles_input.h" #include "media/audio/android/opensles_input.h"
#include "media/audio/android/opensles_output.h" #include "media/audio/android/opensles_output.h"
#include "media/audio/audio_device_description.h" #include "media/audio/audio_device_description.h"
#include "media/audio/audio_features.h"
#include "media/audio/audio_manager.h" #include "media/audio/audio_manager.h"
#include "media/audio/fake_audio_input_stream.h" #include "media/audio/fake_audio_input_stream.h"
#include "media/base/android/media_jni_headers/AudioManagerAndroid_jni.h" #include "media/base/android/media_jni_headers/AudioManagerAndroid_jni.h"
...@@ -31,6 +35,13 @@ using base::android::JavaParamRef; ...@@ -31,6 +35,13 @@ using base::android::JavaParamRef;
using base::android::JavaRef; using base::android::JavaRef;
using base::android::ScopedJavaLocalRef; using base::android::ScopedJavaLocalRef;
using media_audio_android::InitializeStubs;
using media_audio_android::kModuleAaudio;
using media_audio_android::StubPathMap;
static const base::FilePath::CharType kAaudioLib[] =
FILE_PATH_LITERAL("libaaudio.so");
namespace media { namespace media {
namespace { namespace {
...@@ -47,6 +58,18 @@ const int kDefaultOutputBufferSize = 2048; ...@@ -47,6 +58,18 @@ const int kDefaultOutputBufferSize = 2048;
} // namespace } // namespace
static bool InitAAudio() {
StubPathMap paths;
// Check if the AAudio library is available.
paths[kModuleAaudio].push_back(kAaudioLib);
if (!InitializeStubs(paths)) {
VLOG(1) << "Failed on loading the AAudio library and symbols";
return false;
}
return true;
}
std::unique_ptr<AudioManager> CreateAudioManager( std::unique_ptr<AudioManager> CreateAudioManager(
std::unique_ptr<AudioThread> audio_thread, std::unique_ptr<AudioThread> audio_thread,
AudioLogFactory* audio_log_factory) { AudioLogFactory* audio_log_factory) {
...@@ -225,6 +248,10 @@ AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( ...@@ -225,6 +248,10 @@ AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
const LogCallback& log_callback) { const LogCallback& log_callback) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
DCHECK(GetTaskRunner()->BelongsToCurrentThread()); DCHECK(GetTaskRunner()->BelongsToCurrentThread());
if (UseAAudio())
return new AAudioOutputStream(this, params, AAUDIO_USAGE_MEDIA);
return new OpenSLESOutputStream(this, params, SL_ANDROID_STREAM_MEDIA); return new OpenSLESOutputStream(this, params, SL_ANDROID_STREAM_MEDIA);
} }
...@@ -235,10 +262,18 @@ AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( ...@@ -235,10 +262,18 @@ AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
if (UseAAudio()) {
const aaudio_usage_t usage = communication_mode_is_on_
? AAUDIO_USAGE_VOICE_COMMUNICATION
: AAUDIO_USAGE_MEDIA;
return new AAudioOutputStream(this, params, usage);
}
// Set stream type which matches the current system-wide audio mode used by // Set stream type which matches the current system-wide audio mode used by
// the Android audio manager. // the Android audio manager.
const SLint32 stream_type = communication_mode_is_on_ ? const SLint32 stream_type = communication_mode_is_on_
SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA; ? SL_ANDROID_STREAM_VOICE
: SL_ANDROID_STREAM_MEDIA;
return new OpenSLESOutputStream(this, params, stream_type); return new OpenSLESOutputStream(this, params, stream_type);
} }
...@@ -443,10 +478,26 @@ void AudioManagerAndroid::DoSetVolumeOnAudioThread(double volume) { ...@@ -443,10 +478,26 @@ void AudioManagerAndroid::DoSetVolumeOnAudioThread(double volume) {
output_volume_override_ = volume; output_volume_override_ = volume;
DCHECK(GetTaskRunner()->BelongsToCurrentThread()); DCHECK(GetTaskRunner()->BelongsToCurrentThread());
for (OutputStreams::iterator it = streams_.begin(); for (OutputStreams::iterator it = streams_.begin(); it != streams_.end();
it != streams_.end(); ++it) { ++it) {
(*it)->SetVolume(volume); (*it)->SetVolume(volume);
} }
} }
bool AudioManagerAndroid::UseAAudio() {
if (!base::FeatureList::IsEnabled(features::kUseAAudioDriver))
return false;
if (base::android::BuildInfo::GetInstance()->sdk_int() <
base::android::SDK_VERSION_P) {
// We need APIs that weren't added until API Level 28.
return false;
}
if (!is_aaudio_available_.has_value())
is_aaudio_available_ = InitAAudio();
return is_aaudio_available_.value();
}
} // namespace media } // namespace media
...@@ -107,6 +107,9 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase { ...@@ -107,6 +107,9 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase {
void DoSetMuteOnAudioThread(bool muted); void DoSetMuteOnAudioThread(bool muted);
void DoSetVolumeOnAudioThread(double volume); void DoSetVolumeOnAudioThread(double volume);
// Returns whether or not we can and should use AAudio.
bool UseAAudio();
// Java AudioManager instance. // Java AudioManager instance.
base::android::ScopedJavaGlobalRef<jobject> j_audio_manager_; base::android::ScopedJavaGlobalRef<jobject> j_audio_manager_;
...@@ -117,6 +120,8 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase { ...@@ -117,6 +120,8 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase {
// input stream is destroyed. Also affects the stream type of output streams. // input stream is destroyed. Also affects the stream type of output streams.
bool communication_mode_is_on_; bool communication_mode_is_on_;
base::Optional<bool> is_aaudio_available_;
// If set, overrides volume level on output streams // If set, overrides volume level on output streams
bool output_volume_override_set_; bool output_volume_override_set_;
double output_volume_override_; double output_volume_override_;
......
...@@ -23,6 +23,13 @@ const base::Feature kAudioServiceOutOfProcessKillAtHang{ ...@@ -23,6 +23,13 @@ const base::Feature kAudioServiceOutOfProcessKillAtHang{
const base::Feature kDumpOnAudioServiceHang{"DumpOnAudioServiceHang", const base::Feature kDumpOnAudioServiceHang{"DumpOnAudioServiceHang",
base::FEATURE_DISABLED_BY_DEFAULT}; base::FEATURE_DISABLED_BY_DEFAULT};
#if defined(OS_ANDROID)
// Enables loading and using AAudio instead of OpenSLES on compatible devices,
// for audio output streams.
const base::Feature kUseAAudioDriver{"UseAAudioDriver",
base::FEATURE_DISABLED_BY_DEFAULT};
#endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
const base::Feature kCrOSSystemAEC{"CrOSSystemAEC", const base::Feature kCrOSSystemAEC{"CrOSSystemAEC",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
......
...@@ -14,6 +14,10 @@ namespace features { ...@@ -14,6 +14,10 @@ namespace features {
MEDIA_EXPORT extern const base::Feature kAudioServiceOutOfProcessKillAtHang; MEDIA_EXPORT extern const base::Feature kAudioServiceOutOfProcessKillAtHang;
MEDIA_EXPORT extern const base::Feature kDumpOnAudioServiceHang; MEDIA_EXPORT extern const base::Feature kDumpOnAudioServiceHang;
#if defined(OS_ANDROID)
MEDIA_EXPORT extern const base::Feature kUseAAudioDriver;
#endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
MEDIA_EXPORT extern const base::Feature kCrOSSystemAEC; MEDIA_EXPORT extern const base::Feature kCrOSSystemAEC;
MEDIA_EXPORT extern const base::Feature kCrOSSystemAECDeactivatedGroups; MEDIA_EXPORT extern const base::Feature kCrOSSystemAECDeactivatedGroups;
......
...@@ -9,12 +9,14 @@ ...@@ -9,12 +9,14 @@
#include "base/memory/aligned_memory.h" #include "base/memory/aligned_memory.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/test/test_timeouts.h" #include "base/test/test_timeouts.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "media/audio/audio_device_info_accessor_for_tests.h" #include "media/audio/audio_device_info_accessor_for_tests.h"
#include "media/audio/audio_features.h"
#include "media/audio/audio_io.h" #include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h" #include "media/audio/audio_manager.h"
#include "media/audio/audio_unittest_util.h" #include "media/audio/audio_unittest_util.h"
...@@ -25,13 +27,18 @@ ...@@ -25,13 +27,18 @@
namespace media { namespace media {
class AudioOutputTest : public ::testing::Test { class AudioOutputTest : public testing::TestWithParam<bool> {
public: public:
AudioOutputTest() { AudioOutputTest() {
audio_manager_ = audio_manager_ =
AudioManager::CreateForTesting(std::make_unique<TestAudioThread>()); AudioManager::CreateForTesting(std::make_unique<TestAudioThread>());
audio_manager_device_info_ = audio_manager_device_info_ =
std::make_unique<AudioDeviceInfoAccessorForTests>(audio_manager_.get()); std::make_unique<AudioDeviceInfoAccessorForTests>(audio_manager_.get());
#if defined(OS_ANDROID)
// The only parameter is used to enable/disable AAudio.
if (GetParam())
features_.InitAndEnableFeature(features::kUseAAudioDriver);
#endif
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
~AudioOutputTest() override { ~AudioOutputTest() override {
...@@ -62,17 +69,20 @@ class AudioOutputTest : public ::testing::Test { ...@@ -62,17 +69,20 @@ class AudioOutputTest : public ::testing::Test {
std::unique_ptr<AudioDeviceInfoAccessorForTests> audio_manager_device_info_; std::unique_ptr<AudioDeviceInfoAccessorForTests> audio_manager_device_info_;
AudioParameters stream_params_; AudioParameters stream_params_;
AudioOutputStream* stream_ = nullptr; AudioOutputStream* stream_ = nullptr;
#if defined(OS_ANDROID)
base::test::ScopedFeatureList features_;
#endif
}; };
// Test that can it be created and closed. // Test that can it be created and closed.
TEST_F(AudioOutputTest, GetAndClose) { TEST_P(AudioOutputTest, GetAndClose) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
CreateWithDefaultParameters(); CreateWithDefaultParameters();
ASSERT_TRUE(stream_); ASSERT_TRUE(stream_);
} }
// Test that it can be opened and closed. // Test that it can be opened and closed.
TEST_F(AudioOutputTest, OpenAndClose) { TEST_P(AudioOutputTest, OpenAndClose) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
CreateWithDefaultParameters(); CreateWithDefaultParameters();
...@@ -81,7 +91,7 @@ TEST_F(AudioOutputTest, OpenAndClose) { ...@@ -81,7 +91,7 @@ TEST_F(AudioOutputTest, OpenAndClose) {
} }
// Verify that Stop() can be called before Start(). // Verify that Stop() can be called before Start().
TEST_F(AudioOutputTest, StopBeforeStart) { TEST_P(AudioOutputTest, StopBeforeStart) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
CreateWithDefaultParameters(); CreateWithDefaultParameters();
EXPECT_TRUE(stream_->Open()); EXPECT_TRUE(stream_->Open());
...@@ -89,7 +99,7 @@ TEST_F(AudioOutputTest, StopBeforeStart) { ...@@ -89,7 +99,7 @@ TEST_F(AudioOutputTest, StopBeforeStart) {
} }
// Verify that Stop() can be called more than once. // Verify that Stop() can be called more than once.
TEST_F(AudioOutputTest, StopTwice) { TEST_P(AudioOutputTest, StopTwice) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
CreateWithDefaultParameters(); CreateWithDefaultParameters();
EXPECT_TRUE(stream_->Open()); EXPECT_TRUE(stream_->Open());
...@@ -101,7 +111,7 @@ TEST_F(AudioOutputTest, StopTwice) { ...@@ -101,7 +111,7 @@ TEST_F(AudioOutputTest, StopTwice) {
} }
// This test produces actual audio for .25 seconds on the default device. // This test produces actual audio for .25 seconds on the default device.
TEST_F(AudioOutputTest, Play200HzTone) { TEST_P(AudioOutputTest, Play200HzTone) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
stream_params_ = stream_params_ =
...@@ -139,7 +149,7 @@ TEST_F(AudioOutputTest, Play200HzTone) { ...@@ -139,7 +149,7 @@ TEST_F(AudioOutputTest, Play200HzTone) {
} }
// Test that SetVolume() and GetVolume() work as expected. // Test that SetVolume() and GetVolume() work as expected.
TEST_F(AudioOutputTest, VolumeControl) { TEST_P(AudioOutputTest, VolumeControl) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
CreateWithDefaultParameters(); CreateWithDefaultParameters();
...@@ -159,4 +169,14 @@ TEST_F(AudioOutputTest, VolumeControl) { ...@@ -159,4 +169,14 @@ TEST_F(AudioOutputTest, VolumeControl) {
stream_->Stop(); stream_->Stop();
} }
// The test parameter is only relevant on Android. It controls whether or not we
// allow the use of AAudio.
INSTANTIATE_TEST_SUITE_P(Base, AudioOutputTest, testing::Values(false));
#if defined(OS_ANDROID)
// Run tests with AAudio enabled. On Android O and below, this is the same as
// the Base test above, as we only use AAudio on P+.
INSTANTIATE_TEST_SUITE_P(AAudio, AudioOutputTest, testing::Values(true));
#endif
} // namespace media } // namespace media
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment