1. AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface*)
上篇博客中已经分析如何调用到AudioPolicyManager的构造函数,本篇博客就从AudioPolicyManager的构造函数开始谈起。
/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
:
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
......
//保存AudioPolicyClient的对象,这个对象很重要,是获取AudioFlinger接口的一个对象
mpClientInterface = clientInterface;
//xml文件解析
#ifdef USE_XML_AUDIO_POLICY_CONF
//如果使用xml来配置的话,则解析audio_policy_configuration.xml文件
//初始化一个vector audio_stream_type_t类型的stream,用于保存解析到的xml中的stream信息
mVolumeCurves = new VolumeCurvesCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled,
static_cast<VolumeCurvesCollection *>(mVolumeCurves));
//遍历解析/odm/etc, vendor/etc/audio, vendor/etc/, system/etc这几个目录,如果找到audio_policy_configuration.xml,并解析成功,则break退出
if (deserializeAudioPolicyXmlConfig(config) != NO_ERROR) {
#else
//conf文件的解析
mVolumeCurves = new StreamDescriptorCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled);
//加载并解析conf文件
//#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"
//#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
(ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
#endif
ALOGE("could not load audio policy configuration file, setting defaults");
config.setDefault();
}
........
for (size_t i = 0; i < mHwModules.size(); i++) {
//1.加载Moudle
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
.......
//2.对output的处理
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
//获取每个module中的outProfile
const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];
......
//得到支持设备的类型
audio_devices_t profileType = outProfile->getSupportedDevicesType();
//将输出IOProfile封装为SwAudioOutputDescriptor对象
//创建一个outputDesc对象,该对象中描述了音频的一些参数,如采样率、通道数以及格式
sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
mpClientInterface);
......
outputDesc->mDevice = profileType;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = outputDesc->mSamplingRate;
config.channel_mask = outputDesc->mChannelMask;
config.format = outputDesc->mFormat;
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
//将调用audioFlinger中的openOutput,打开output,在AudioFlinger中创建PlaybackTread线程,并返回线程的id
status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
&output,
&config,
&outputDesc->mDevice,
address,
&outputDesc->mLatency,
outputDesc->mFlags);
.......
//将输出描述符对象SwAudioOutputDescriptor及创建的PlaybackTread线程id以键值对形式保存
addOutput(output, outputDesc);
setOutputDevice(outputDesc,
outputDesc->mDevice,
true,
0,
NULL,
address.string());
}
}
// open input streams needed to access attached devices to validate
// mAvailableInputDevices list
//3.input的处理
for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
{
//获取每个module中的inProfile
const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
// chose first device present in profile's SupportedDevices also part of
// inputDeviceTypes
//获取所支持的设备
audio_devices_t profileType = inProfile->getSupportedDeviceForType(inputDeviceTypes);
//将输入IOProfile封装成AudioInputDescriptor对象
sp<AudioInputDescriptor> inputDesc =
new AudioInputDescriptor(inProfile);
inputDesc->mDevice = profileType;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = inputDesc->mSamplingRate;
config.channel_mask = inputDesc->mChannelMask;
config.format = inputDesc->mFormat;
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
//将调用AudioFlinger中的openInput,在audioFlinger中创建recordThread线程,并返回其id
status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
&input,
&config,
&inputDesc->mDevice,
address,
AUDIO_SOURCE_MIC,
AUDIO_INPUT_FLAG_NONE);
if (status == NO_ERROR) {
const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
for (size_t k = 0; k < supportedDevices.size(); k++) {
ssize_t index = mAvailableInputDevices.indexOf(supportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
if (index >= 0) {
sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index];
if (!devDesc->isAttached()) {
devDesc->attach(mHwModules[i]);
devDesc->importAudioPort(inProfile, true);
}
}
}
mpClientInterface->closeInput(input);
}
}
}
.........
}
2. mpClientInterface->函数(...)
2.1 mpClientInterface->loadHwModule(...)
这个地方会调用到AudioFlinger中的loadHwModule函数,为什么?
mpClientInterface是由clientInterface赋值的。
看一下函数的调用流程:
mAudioPolicyClient = new AudioPolicyClient(this)------->createAudioPolicyManager(mAudioPolicyClient)-------->new AudioPolicyManager(clientInterface),因此mpClientInterface->loadHwModule实际上是调用了AudioPolicyClient类中的成员函数。
/frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp
audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
......
return af->loadHwModule(name);
}
从上面的代码可以看出,最终调用了AudioFlinger中的loadHwModule函数。在AudioFlinger的博客中再重点分析此函数。
2.2 mpClientInterface->openOutput(...)
/frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp
status_t AudioPolicyService::AudioPolicyClient::openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
......
return af->openOutput(module, output, config, devices, address, latencyMs, flags);
}
最终调用到了AudioFlinger中的openOutput函数
2.3 mpClientInterface->openInput(...)
status_t AudioPolicyService::AudioPolicyClient::openInput(audio_module_handle_t module,
audio_io_handle_t *input,
audio_config_t *config,
audio_devices_t *device,
const String8& address,
audio_source_t source,
audio_input_flags_t flags)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
......
return af->openInput(module, input, config, device, address, source, flags);
}
最终调用到AudioFlinger中的openInput函数。
3. XML配置文件解析
deserializeAudioPolicyXmlConfig函数用于解析xml文件,在该函数中,会依次解析/odm/etc/, /vendor/etc/audio/, /vendor/etc/, /system/etc这几个目录,如果找到audio_policy_configuration.xml文件,并解析成功,则break退出。
在android中,该文件的默认存放路径如下:
/frameworks/av/services/audiopolicy/config/audio_policy_configuration.xml
但是我们一般不会使用android自带的xml文件,而是使用厂家提供的。我们以SDM429W平台为例,厂家提供的xml文件路径如下:
/hardware/qcom/audio/configs/msm8937/audio_policy_configuration.xml
经编译后,被放到了目录:
/vendor/etc/audio/audio_policy_configuration.xml
/vendor/etc/audio_policy_configuraiton.xml
在代码中,通过宏USE_XML_AUDIO_POLICY_CONF来决定使用audio_policy.conf文件还是audio_policy_configuraiton.xml文件。该宏定义在:
/hardware/qcom/audio/configs/msm8937/msm8937.mk中
USE_XML_AUDIO_POLICY_CONF := 1
此时言归正传,回到函数 deserializeAudioPolicyXmlConfig
/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
#define AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH 128
#define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
#ifdef USE_XML_AUDIO_POLICY_CONF
// Treblized audio policy xml config will be located in /odm/etc or /vendor/etc.
static const char *kConfigLocationList[] =
{"/odm/etc", "/vendor/audio/etc","/vendor/etc", "/system/etc"};
static const int kConfigLocationListSize =
(sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
status_t ret;
for (int i = 0; i < kConfigLocationListSize; i++) {
PolicySerializer serializer;
snprintf(audioPolicyXmlConfigFile,
sizeof(audioPolicyXmlConfigFile),
"%s/%s",
kConfigLocationList[i],
AUDIO_POLICY_XML_CONFIG_FILE_NAME);
ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
if (ret == NO_ERROR) {
break;
}
}
return ret;
}
#endif
deserialize函数是解析XML的关键,不过这个函数非常复杂。对于这个函数的解析过程,可参考https://blog.csdn.net/qq_33750826/article/details/97757590