audiopolicymanagertest TEST_F(…)学习
提要
audiopolicymanagertest.cpp中,使用gtest框架,代码调用RUN_ALL_TESTS()时,TEST_F(…)的主要流程如下:
- 调用testsuite类SetUp()进行基础的初始化工作。
- 执行TEST_F代码块中的代码。
- 调用testsuite类TearDown)进行销毁工作。
AudioPolicyManagerTest::SetUp()分析
代码如下:
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),
...
- 设置audiopolicyconfig的默认配置
- 创建
DeviceDescriptor
类型的输入输出设备,mType都为:AUDIO_PORT_TYPE_DEVICE
。并将其分别加入到DeviceVector
类型的数组中。 - 创建名字为"primary"的
HwModule
模块。 - 创建
OutputProfile
的对象,其中mType为:AUDIO_PORT_TYPE_MIX
。并将mModule指向 2. 创建的HwModule
模块。 - 创建一个
AudioProfile
对象,并初始化该对象的音频格式、通道数、采样格式等,最后将创建的AudioProfile
对象添加到OutputProfile
对象的数组成员中(mProfiles)。 - 添加
DeviceVector
类型的输出设备数组到OutputProfile
对象中,并设置输出场景的Flag。 - 创建输入场景,并将
HwModule
与输入场景关联起来,创建音频场景并将其添加到输入场景中,添加默认输入设备数组到输入场景支持的数组中去。 - 最后将输入输出场景注册到
HwModule
中去,将HwModule
添加到mHwModules
列表中去。
- AudioPolicyTestManager初始化
- 初始化每种流对应策略的音量曲线。
// 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的衰减值)
- 创建Engine引擎。
- 获取当前有效的输入输出设备类型。
// 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()) {
...
}
}
- 遍历HwModule的输出场景。获取
OutputProfile
中支持的设备类型,创建SwAudioOutputDescriptor
实例,并把OutputProfile
和mpClientInterface
注册进去。通过mPort获取OutputProfile
之前注册的音频格式、通道数、采样率并分别初始化自己对应的成员变量。之后设置获取OutputProfile
中的Flag,设置成mFlag。
获取OutputProfile
的配置(设备)类型,每个OutputProfile
对应一个profileType。
在支持的设备数组中,通过profileType查找对应的DeviceDescriptor
设备数组,并获取第一个DeviceDescriptor
的address。
调用SwAudioOutputDescriptor
的open打开outputstream。
将当前HwModule关联到mAvailableOutputDevices中来更新mAvailableOutputDevices连接状态。并将SwAudioOutputDescriptor
注册到mPrimaryOutput中。
将output与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<SwAudioOutputDescriptor> 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);
}
}
- 遍历HwModule的输入场景。从
InputProfile
中找到mAvailableInputDevices
支持的设备类型。创建AudioInputDescriptor
对象,并将InputProfile
和mpClientInterface
注册到该对象的mProfile和mClientInterface中,通过InputProfile
获取音频格式、通道数、采样率分别赋值给mSamplingRate, mChannelMask, mFormat。
通过当前场景支持的类型profileType
查找到支持的输入设备列表。通过输入设备列表获取到address。最后调用open打开输入设备,返回输入设备句柄。
将mAvailableInputDevices
中对应的设备与该HwModule关联。并将inputprofile
导入到具体的设备中去。最后关闭输入设备。 - updateDevicesAndOutputs()
- 做断言处理
- ASSERT_EQ(NO_ERROR, mManager->initCheck()),根据代码断言为真。
status_t AudioPolicyManager::initCheck()
{
return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}
TEST_F代码段
- createAudioPatch参数断言
// 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());
AudioPolicyManagerTest::TearDown()分析
void AudioPolicyManagerTest::TearDown() {
mManager.reset();
mClient.reset();
}