#include "media/audio/audio_manager.h"
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/environment.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/test_message_loop.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_device_info_accessor_for_tests.h"
#include "media/audio/audio_device_name.h"
#include "media/audio/audio_output_proxy.h"
#include "media/audio/audio_unittest_util.h"
#include "media/audio/fake_audio_log_factory.h"
#include "media/audio/fake_audio_manager.h"
#include "media/audio/mock_audio_debug_recording_manager.h"
#include "media/audio/test_audio_thread.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/media_buildflags.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(USE_ALSA)
#include "media/audio/alsa/audio_manager_alsa.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "media/audio/mac/audio_manager_mac.h"
#include "media/base/mac/audio_latency_mac.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/scoped_com_initializer.h"
#include "media/audio/win/audio_manager_win.h"
#endif
#if defined(USE_PULSEAUDIO)
#include "media/audio/pulse/audio_manager_pulse.h"
#include "media/audio/pulse/pulse_util.h"
#endif
#if BUILDFLAG(USE_CRAS)
#include "media/audio/cras/audio_manager_cras.h"
#endif
namespace media {
namespace {
template <typename T>
struct TestAudioManagerFactory { … };
#if defined(USE_PULSEAUDIO)
template <>
struct TestAudioManagerFactory<AudioManagerPulse> { … };
#endif
template <>
struct TestAudioManagerFactory<std::nullptr_t> { … };
const char kRealDefaultInputDeviceID[] = …;
const char kRealDefaultOutputDeviceID[] = …;
const char kRealCommunicationsInputDeviceID[] = …;
const char kRealCommunicationsOutputDeviceID[] = …;
void CheckDescriptionLabels(const AudioDeviceDescriptions& descriptions,
const std::string& real_default_id,
const std::string& real_communications_id) { … }
}
class AudioManagerTest : public ::testing::Test { … };
TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) { … }
TEST_F(AudioManagerTest, EnumerateInputDevices) { … }
TEST_F(AudioManagerTest, EnumerateOutputDevices) { … }
#if BUILDFLAG(IS_WIN)
TEST_F(AudioManagerTest, EnumerateInputDevicesWinMMDevice) {
ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
AudioDeviceDescriptions device_descriptions;
device_info_accessor_->GetAudioInputDeviceDescriptions(&device_descriptions);
CheckDeviceDescriptions(device_descriptions);
}
TEST_F(AudioManagerTest, EnumerateOutputDevicesWinMMDevice) {
ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
AudioDeviceDescriptions device_descriptions;
device_info_accessor_->GetAudioOutputDeviceDescriptions(&device_descriptions);
CheckDeviceDescriptions(device_descriptions);
}
#endif
#if defined(USE_PULSEAUDIO)
TEST_F(AudioManagerTest, EnumerateInputDevicesPulseaudio) { … }
TEST_F(AudioManagerTest, EnumerateOutputDevicesPulseaudio) { … }
#endif
#if defined(USE_ALSA)
TEST_F(AudioManagerTest, EnumerateInputDevicesAlsa) { … }
TEST_F(AudioManagerTest, EnumerateInputDevicesAlsaWithInputDeviceSwitch) { … }
TEST_F(AudioManagerTest, EnumerateOutputDevicesAlsa) { … }
TEST_F(AudioManagerTest, EnumerateOutputDevicesAlsaWithOutputDeviceSwitch) { … }
#endif
TEST_F(AudioManagerTest, GetOutputStreamParameters) { … }
TEST_F(AudioManagerTest, GetAssociatedOutputDeviceID) { … }
class TestAudioManager : public FakeAudioManager { … };
TEST_F(AudioManagerTest, GroupId) { … }
TEST_F(AudioManagerTest, DefaultCommunicationsLabelsContainRealLabels) { … }
TEST_F(AudioManagerTest, CheckMakeOutputStreamWithPreferredParameters) { … }
#if BUILDFLAG(IS_MAC) || BUILDFLAG(USE_CRAS)
class TestAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
public:
TestAudioSourceCallback(int expected_frames_per_buffer,
base::WaitableEvent* event)
: expected_frames_per_buffer_(expected_frames_per_buffer),
event_(event) {}
TestAudioSourceCallback(const TestAudioSourceCallback&) = delete;
TestAudioSourceCallback& operator=(const TestAudioSourceCallback&) = delete;
~TestAudioSourceCallback() override {}
int OnMoreData(base::TimeDelta,
base::TimeTicks,
const AudioGlitchInfo&,
AudioBus* dest) override {
EXPECT_EQ(dest->frames(), expected_frames_per_buffer_);
event_->Signal();
return 0;
}
void OnError(ErrorType type) override { FAIL(); }
private:
const int expected_frames_per_buffer_;
raw_ptr<base::WaitableEvent> event_;
};
TEST_F(AudioManagerTest, CheckMinMaxAudioBufferSizeCallbacks) {
ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
#if BUILDFLAG(IS_MAC)
CreateAudioManagerForTesting<AudioManagerMac>();
#elif BUILDFLAG(USE_CRAS) && BUILDFLAG(IS_CHROMEOS_ASH)
CreateAudioManagerForTesting<AudioManagerCras>();
#endif
DCHECK(audio_manager_);
std::string default_device_id = AudioDeviceDescription::kDefaultDeviceId;
AudioParameters default_params = GetOutputStreamParameters(default_device_id);
ASSERT_LT(default_params.frames_per_buffer(),
media::limits::kMaxAudioBufferSize);
#if BUILDFLAG(IS_MAC)
ASSERT_GT(default_params.frames_per_buffer(),
GetMinAudioBufferSizeMacOS(media::limits::kMinAudioBufferSize,
default_params.sample_rate()));
#elif BUILDFLAG(USE_CRAS)
ASSERT_GE(default_params.frames_per_buffer(),
media::limits::kMinAudioBufferSize);
#else
NOTREACHED_IN_MIGRATION();
#endif
AudioOutputStream* stream;
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
AudioParameters min_params = default_params;
min_params.set_frames_per_buffer(media::limits::kMinAudioBufferSize);
stream = audio_manager_->MakeAudioOutputStreamProxy(min_params, "");
ASSERT_TRUE(stream);
EXPECT_TRUE(stream->Open());
event.Reset();
TestAudioSourceCallback min_source(min_params.frames_per_buffer(), &event);
stream->Start(&min_source);
event.Wait();
stream->Stop();
stream->Close();
AudioParameters max_params = default_params;
max_params.set_frames_per_buffer(media::limits::kMaxAudioBufferSize);
stream = audio_manager_->MakeAudioOutputStreamProxy(max_params, "");
ASSERT_TRUE(stream);
EXPECT_TRUE(stream->Open());
event.Reset();
TestAudioSourceCallback max_source(max_params.frames_per_buffer(), &event);
stream->Start(&max_source);
event.Wait();
stream->Stop();
stream->Close();
}
#endif
}