代码段一览
TEST(AudioPolicyManagerTestInit, Failure) {
AudioPolicyTestClient client;
AudioPolicyTestManager manager(&client);
manager.getConfig().setDefault();
// Since the default client fails to open anything,
// APM should indicate that the initialization didn't succeed.
ASSERT_EQ(NO_INIT, manager.initialize());
ASSERT_EQ(NO_INIT, manager.initCheck());
}
流程分析
根据gtest框架,test代码最终会执行上面的代码块中的内容。
- 首先创建一个
AudioPolicyTestClient
对象
AudioPolicyTestClient
派生于AudioPolicyClientInterface
。是AudioPolicy与AudioFlinger通信的客户端。AudioPolicyClientInterface
提供了关于硬件的一些操作方法。比如一些常用的接口loadHwModule
、openOutput
、openInput
、getParameters
、setParameters
等。
- 创建
AudioPolicyTestManager
对象
AudioPolicyTestManager
派生于AudioPolicyManager
。而AudioPolicyManager
继承于AudioPolicyInterface
。AudioPolicyInterface
提供了对音频流的管理接口。AudioPolicyInterface
提供了对于音频流控制和策略选择的操作方法,比如getStrategy
、startOutput
、getOutputForAttr
等。所以AudioPolicyManager
提供了音频策略和设备管理,以及音频流控制的功能。AudioPolicyTestManager
的定义如下:
class AudioPolicyTestManager : public AudioPolicyManager {
public:
explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
: AudioPolicyManager(clientInterface, true /*forTesting*/) { }
using AudioPolicyManager::getConfig;
using AudioPolicyManager::initialize;
};
实例化AudiopolicyManager
对象,则会调用父类的AudioPolicyManager(clientInterface, true)
构造函数,在父类的构造函数中会将AudioPolicyTestClient
的实例注册到mpClientInterface。创建StreamDescriptorCollection
/VolumeCurvesCollection
对象,该对象注册到mVolumeCurves,mVolumeCurves包含一个mVector,mVector保存着流id
:StreamDescriptor
。创建AudioPolicyConfig
对象注册到mConfig。代码如下:
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
bool /*forTesting*/)
:
mUidCached(getuid()),
mpClientInterface(clientInterface),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
#ifdef USE_XML_AUDIO_POLICY_CONF
mVolumeCurves(new VolumeCurvesCollection()),
mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, static_cast<VolumeCurvesCollection*>(mVolumeCurves.get())),
#else
mVolumeCurves(new StreamDescriptorCollection()),
mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice),
#endif
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
}
AudioPolicyTestManager
设置配置
- 通过调用
setDefault
来对AudioPolicyTestManager
实例设置配置,具体代码如下:
manager.getConfig().setDefault()
最终会调用AudioPolicyConfig
中的setDefault()方法。
void setDefault(void)
{
mDefaultOutputDevices = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
sp<HwModule> module;
sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
mAvailableOutputDevices.add(mDefaultOutputDevices);
mAvailableInputDevices.add(defaultInputDevice);
module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
sp<OutputProfile> outProfile;
outProfile = new OutputProfile(String8("primary"));
outProfile->attach(module);
outProfile->addAudioProfile(
new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
outProfile->addSupportedDevice(mDefaultOutputDevices);
outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
module->addOutputProfile(outProfile);
sp<InputProfile> inProfile;
inProfile = new InputProfile(String8("primary"));
inProfile->attach(module);
inProfile->addAudioProfile(
new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000));
inProfile->addSupportedDevice(defaultInputDevice);
module->addInputProfile(inProfile);
mHwModules.add(module);
}
setDefault
流程分析
首先通过newDeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER)
创建一个mDefaultOutputDevices
对象。通过newDeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC)
创建一个defaultInputDevice
对象。最终将mDefaultOutputDevices
和defaultInputDevice
分别注册mAvailableOutputDevices
和mAvailableInputDevices
链表中。
接着通过newHwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY)
创建一个硬件模块module
。
通过newOutputProfile(String8("primary"))
创建一个输出配置outProfile
,给输出配置添加一个newAudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100)
对象,并将之前创建的SPEAK
设备添加到outProfile
中,最后在硬件模块module
中添加outProfile
。
通过newInputProfile(String8("primary"))
创建一个输入配置inProfile
,给输入配置添加一个 newAudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000)
对象,并将之前创建的MIC
设备添加到InputProfile
中,最后在硬件模块module
中添加InputProfile
。
最后,将module
注册到mHwModules中。
- 对
manager
的initialize
和initCheck
进行断言。
具体代码如下:
ASSERT_EQ(NO_INIT, manager.initialize());
ASSERT_EQ(NO_INIT, manager.initCheck());
- 调用
initializeVolumeCurves
来进行每一个流的StreamDescriptor
策略初始化。如果该Speaker有DRC1功能,则使用默认的VolumeCurvePoint。 - 创建Engine引擎实例,并返回引擎实例。Engine代码如下:
Engine::Engine()
: mManagerInterface(this),
mPhoneState(AUDIO_MODE_NORMAL),
mApmObserver(NULL)
{
for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
}
}
- 将
AudioPolicyManager
注册到Engine实例中,并做观察者检测。
mEngine->setObserver(this);
status_t status = mEngine->initCheck();
if (status != NO_ERROR) {
LOG_FATAL("Policy engine not initialized(err=%d)", status);
return status;
}
- 加载硬件库,并将其返回句柄添加到
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;
}
...
}
默认会调用AudioPolicyClient
中的loadHwModule方法,但是测试类重新了此方法。具体代码如下:
//默认方法
audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
ALOGW("%s: could not get AudioFlinger", __func__);
return AUDIO_MODULE_HANDLE_NONE;
}
return af->loadHwModule(name);
}
//AudioPolicyTestClient重新的方法
audio_module_handle_t loadHwModule(const char* /*name*/) override {
return AUDIO_MODULE_HANDLE_NONE;
}
如果返回参数为AUDIO_MODULE_HANDLE_NONE则不调用后面的操作,最终退出循环。
5. 将无效的输入输出从mAvailableOutputDevices
和mAvailableInputDevices
列表中移除,并返回NO_INIT
,初始化断言成功。
6. 调用AudioPolicyManager::initCheck()
来进行初始化检查。代码如下:
status_t AudioPolicyManager::initCheck()
{
return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}
- for循环没有执行,就没有创建输出,故
mPrimaryOutput
为0。
Dynamic Range Control(动态范围控制)提供声音压缩和放大能力,使声音听起来更柔和或更大声,即一种信号调幅方式。 ↩︎