audiopolicymanagertest.cpp中,使用gtest框架,代码调用RUN_ALL_TESTS()时,TEST_F(…)的主要流程如下:
代码如下:
void AudioPolicyManagerTest::SetUp() {
mClient.reset(new AudioPolicyManagerTestClient);
mManager.reset(new AudioPolicyTestManager(mClient.get()));
mManager->getConfig().setDefault();
ASSERT_EQ(NO_ERROR, mManager->initialize());
ASSERT_EQ(NO_ERROR, mManager->initCheck());
}
AudioPolicyManagerTestClient
与AudioPolicyTestManager
这两个对象。在创建AudioPolicyTestManager
时将之前创建的client注册到里面,创建声音曲线mVolumeCurves
与audioPolicyConfig
对象。 mpClientInterface(clientInterface),
...
mVolumeCurves(new StreamDescriptorCollection()),
mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice),
...
DeviceDescriptor
类型的输入输出设备,mType都为:AUDIO_PORT_TYPE_DEVICE
。并将其分别加入到DeviceVector
类型的数组中。HwModule
模块。OutputProfile
的对象,其中mType为:AUDIO_PORT_TYPE_MIX
。并将mModule指向 2. 创建的HwModule
模块。AudioProfile
对象,并初始化该对象的音频格式、通道数、采样格式等,最后将创建的AudioProfile
对象添加到OutputProfile
对象的数组成员中(mProfiles)。DeviceVector
类型的输出设备数组到OutputProfile
对象中,并设置输出场景的Flag。HwModule
与输入场景关联起来,创建音频场景并将其添加到输入场景中,添加默认输入设备数组到输入场景支持的数组中去。HwModule
中去,将HwModule
添加到mHwModules
列表中去。// VolumeProfiles定义如下:
// default volume curves per stream and device category. See initializeVolumeCurves()
static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][DEVICE_CATEGORY_CNT];
// 电话声音流定义如下:
const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
[DEVICE_CATEGORY_CNT] = {
{ // AUDIO_STREAM_VOICE_CALL
Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EXT_MEDIA
Gains::sHearingAidVolumeCurve // DEVICE_CATEGORY_HEARING_AID
},
...
}
// VolumeCurvePoint数组定义如下:
const VolumeCurvePoint
Gains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = {
{0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
};
// 其中VolumeCurvePoint包含两个成员变量,mIndex(音量),mDBAttenuation(DB的衰减值)
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// open all output streams needed to access attached devices
audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
// 设备类型生成方式如下:
void DeviceVector::refreshTypes()
{
mDeviceTypes = AUDIO_DEVICE_NONE;
for (size_t i = 0; i < size(); i++) {
mDeviceTypes |= itemAt(i)->type();
}
ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
}
mHwModulesAll
,初始化每一个HwModule对象。首先加载hwModule指定的硬件库,并将加载后的句柄返回给HwModule的mHandle
成员变量,其次依次遍历HwModule对应的输出场景,并对其进行打开输出流等操作,最后一次遍历HwModule对应的输入场景,并对其进行打开/关闭输入流等操作。 for (const auto& hwModule : mHwModulesAll) {
hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
ALOGW("could not open HW module %s", hwModule->getName());
continue;
}
mHwModules.push_back(hwModule);
// open all output streams needed to access attached devices
// except for direct output streams that are only opened when they are actually
// required by an app.
// This also validates mAvailableOutputDevices list
for (const auto& outProfile : hwModule->getOutputProfiles()) {
...
}
// open input streams needed to access attached devices to validate
// mAvailableInputDevices list
for (const auto& inProfile : hwModule->getInputProfiles()) {
...
}
}
OutputProfile
中支持的设备类型,创建SwAudioOutputDescriptor
实例,并把OutputProfile
和mpClientInterface
注册进去。通过mPort获取OutputProfile
之前注册的音频格式、通道数、采样率并分别初始化自己对应的成员变量。之后设置获取OutputProfile
中的Flag,设置成mFlag。OutputProfile
的配置(设备)类型,每个OutputProfile
对应一个profileType。DeviceDescriptor
设备数组,并获取第一个DeviceDescriptor
的address。SwAudioOutputDescriptor
的open打开outputstream。SwAudioOutputDescriptor
注册到mPrimaryOutput中。SwAudioOutputDescriptor
键值对添加到mOutputs
中去。SwAudioOutputDescriptor
对象每个流的曲线音量。将当前有效的输出设置到mMusicEffectOutput
中。SwAudioOutputDescriptor
对象的patch,调用mpClientInterface->createAudioPatch创建patch,应用stream音量。// open all output streams needed to access attached devices
// except for direct output streams that are only opened when they are actually
// required by an app.
// This also validates mAvailableOutputDevices list
for (const auto& outProfile : hwModule->getOutputProfiles()) {
...
audio_devices_t profileType = outProfile->getSupportedDevicesType();
if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
profileType = mDefaultOutputDevice->type();
} else {
// chose first device present in profile's SupportedDevices also part of
// outputDeviceTypes
profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes);
}
sp outputDesc = new SwAudioOutputDescriptor(outProfile,
mpClientInterface);
const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType);
String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress
: String8("");
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status = outputDesc->open(nullptr, profileType, address,
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
ALOGW("Cannot open output stream for device %08x on hw module %s",
outputDesc->mDevice,
hwModule->getName());
} else {
for (const auto& dev : supportedDevices) {
ssize_t index = mAvailableOutputDevices.indexOf(dev);
// give a valid ID to an attached device once confirmed it is reachable
if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
mAvailableOutputDevices[index]->attach(hwModule);
}
}
if (mPrimaryOutput == 0 &&
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
addOutput(output, outputDesc);
setOutputDevice(outputDesc,
profileType,
true,
0,
NULL,
address);
}
}
InputProfile
中找到mAvailableInputDevices
支持的设备类型。创建AudioInputDescriptor
对象,并将InputProfile
和mpClientInterface
注册到该对象的mProfile和mClientInterface中,通过InputProfile
获取音频格式、通道数、采样率分别赋值给mSamplingRate, mChannelMask, mFormat。profileType
查找到支持的输入设备列表。通过输入设备列表获取到address。最后调用open打开输入设备,返回输入设备句柄。mAvailableInputDevices
中对应的设备与该HwModule关联。并将inputprofile
导入到具体的设备中去。最后关闭输入设备。status_t AudioPolicyManager::initCheck()
{
return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}
// patch为空断言
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(nullptr, &handle, 0));
// handle为空断言
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, nullptr, 0));
// patch的num_sources==0 断言
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
// patch的num_source大于1断言
patch.num_sources = AUDIO_PATCH_PORTS_MAX + 1;
patch.num_sinks = 1;
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
// patch的num_sinks大于16断言
patch.num_sources = 1;
patch.num_sinks = AUDIO_PATCH_PORTS_MAX + 1;
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0))
patch的num_source大于1断言
patch.num_sources = 2;
patch.num_sinks = 1;
ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
//patch的sources[0].role不为AUDIO_PORT_ROLE_SINK 断言
patch = {};
patch.num_sources = 1;
patch.sources[0].role = AUDIO_PORT_ROLE_SINK;
patch.num_sinks = 1;
patch.sinks[0].role = AUDIO_PORT_ROLE_SINK;
ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
// patch的sinks[0].role不为AUDIO_PORT_ROLE_SOURCE 断言
patch = {};
patch.num_sources = 1;
patch.sources[0].role = AUDIO_PORT_ROLE_SOURCE;
patch.num_sinks = 1;
patch.sinks[0].role = AUDIO_PORT_ROLE_SOURCE;
ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
// Verify that the handle is left unchanged.
ASSERT_EQ(AUDIO_PATCH_HANDLE_NONE, handle);
ASSERT_EQ(patchCountBefore, mClient->getActivePatchesCount());
void AudioPolicyManagerTest::TearDown() {
mManager.reset();
mClient.reset();
}