本文基于android7.0分析
一、概念
audio_policy.conf
: 顾名思义 audio hw 模块配置文件,用于加载音频硬件抽象层动态库。得到系统所支持的输入、输出音频设备。位于系统 /system/etc/
二、系统解析
以如下audio_policy.conf
为例:
# Global configuration section:
# - before audio HAL version 3.0:
# lists input and output devices always present on the device
# as well as the output device selected by default.
# Devices are designated by a string that corresponds to the enum in audio.h
#
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
default_output_device AUDIO_DEVICE_OUT_SPEAKER
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
#AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_DIA_REMOTE
}
#
# - after and including audio HAL 3.0 the global_configuration section is included in each
# hardware module section.
# it also includes the audio HAL version of this hw module:
# global_configuration {
# ...
# audio_hal_version <major.minor> # audio HAL version in e.g. 3.0
# }
# other attributes (attached devices, default device) have to be included in the
# global_configuration section of each hardware module
# audio hardware module section: contains descriptors for all audio hw modules present on the
# device. Each hw module node is named after the corresponding hw module library base name.
# For instance, "primary" corresponds to audio.primary.<device>.so.
# The "primary" module is mandatory and must include at least one output with
# AUDIO_OUTPUT_FLAG_PRIMARY flag.
# Each module descriptor contains one or more output profile descriptors and zero or more
# input profile descriptors. Each profile lists all the parameters supported by a given output
# or input stream category.
# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
audio_hw_modules {
#HwModule
primary {
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
default_output_device AUDIO_DEVICE_OUT_SPEAKER
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
audio_hal_version 3.0
}
#DeviceVector
devices {
speaker {
#DeviceDescriptor -> DeviceVector
type AUDIO_DEVICE_OUT_SPEAKER
#AudioGain -> audioPort.mGains
gains {
gain_1 {
mode AUDIO_GAIN_MODE_JOINT
min_value_mB -8400
max_value_mB 4000
default_value_mB 0
step_value_mB 100
}
}
}
HDMI {
type AUDIO_DEVICE_OUT_AUX_DIGITAL
}
SPDIF {
type AUDIO_DEVICE_OUT_SPDIF
}
wired_headphone {
type AUDIO_DEVICE_OUT_WIRED_HEADPHONE
}
wired_headset {
type AUDIO_DEVICE_OUT_WIRED_HEADSET
}
BT_sco {
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO
}
BT_sco_headset {
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
}
}
outputs {
#IOProfile
primary {
#SampleRateVector -->AudioProfile -->AudioProfileVector
sampling_rates 48000
#ChannelsVector -->AudioProfile -->AudioProfileVector
channel_masks AUDIO_CHANNEL_OUT_STEREO
#FormatVector -->AudioProfile -->AudioProfileVector
formats AUDIO_FORMAT_PCM_16_BIT
#IOProfile
devices speaker|HDMI|SPDIF|wired_headphone|wired_headset|BT_sco|BT_sco_headset
#IOProfile
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
#here for HDMI audio dynamic profile from edid
hdmi_output {
sampling_rates dynamic
channel_masks dynamic
formats dynamic
devices HDMI
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC
}
spdif_device_raw {
sampling_rates 32000|44100|48000
channel_masks AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_5POINT1
formats AUDIO_FORMAT_DTS|AUDIO_FORMAT_AC3
devices SPDIF
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO
}
}
inputs {
primary {
sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET
}
}
}
usb {
outputs {
usb_accessory {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_ACCESSORY
}
usb_device {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_DEVICE
}
}
inputs {
usb_device {
sampling_rates 8000|11025|16000|22050|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_USB_DEVICE
}
}
}
r_submix {
outputs {
submix {
sampling_rates 48000
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
}
}
inputs {
submix {
sampling_rates 48000
channel_masks AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
}
}
}
a2dp {
outputs {
a2dp {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_ALL_A2DP
}
}
}
}
第一小节已经说了 audio_policy.conf
文件 是 用于加载音频硬件抽象层动态库,而系统音频是否能够输入输出则取决于这些动态库是否能够加载成功。而是否能够加载自定义的音频库,则取决你是否在配置文件中加入自定义的音频库配置信息。
android 许多核心模块在开机的时候就要伴随系统的主进程启动而启动,音频服务当然也不例外,而加载音频hw模块动态库隶属于音频服务中,并且是在初始化的过程中,因为这样才能保证一开机系统音频便能够正常使用。
通过 ps -le
命令可以看到系统中第一个进程为init
而init
进程有个任务是启动init.rc
,
init.rc
会启动 audioserver.rc
,
audioserver.rc
位于 frameworks\av\media\audioserver
audioserver.rc
会启动 音频服务的主入口:main_audioserver.cpp
main_audioserver.cpp
位于 frameworks\av\media\audioserver
main_audioserver.cpp
主入口main函数会初始化 AudioPolicyService对象
AudioPolicyService.cpp
在 onFirstRef()
函数初始化 中 调用
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
AudioPolicyService.cpp
位于\frameworks\av\services\audiopolicy\service
createAudioPolicyManager 初始化 AudioPolicyManager对象
AudioPolicyManager.cpp
位于\frameworks\av\services\audiopolicy\managerdefault
AudioPolicyManager.cpp
构造函数 涉及最终解析 audio_policy.conf
好的,到了这里终于到了解析部分了,其实上面的流程也是音频模块的启动大致过程。有兴趣的可以去看源码深入了解完整的启动过程。
让我们找到AudioPolicyManager.cpp
构造函数如下部分
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,mDefaultOutputDevice, speakerDrcEnabled);
if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
(ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR))
首先看到了 AudioPolicyConfig对象
,AudioPolicyConfig.h
源码位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include
随后看到 ConfigParsingUtils对象
调用静态的函数 loadConfig
,ConfigParsingUtils.cpp
位于 \frameworks\av\services\audiopolicy\common\managerdefinitions\src
loadConfig
函数需要两个参数const char *path
//配置文件的路径 即/system/etc/
AudioPolicyConfig &config
源码如下:
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <AudioGain.h>
#include <VolumeCurve.h>
#include <AudioPort.h>
#include <AudioPatch.h>
#include <DeviceDescriptor.h>
#include <IOProfile.h>
#include <HwModule.h>
#include <AudioInputDescriptor.h>
#include <AudioOutputDescriptor.h>
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
#include <SoundTriggerSession.h>
#include <SessionRoute.h>
namespace android {
class AudioPolicyConfig
{
public:
AudioPolicyConfig(HwModuleCollection &hwModules,
DeviceVector &availableOutputDevices,
DeviceVector &availableInputDevices,
sp<DeviceDescriptor> &defaultOutputDevices,
bool &isSpeakerDrcEnabled,
VolumeCurvesCollection *volumes = nullptr)
: mHwModules(hwModules),
mAvailableOutputDevices(availableOutputDevices),
mAvailableInputDevices(availableInputDevices),
mDefaultOutputDevices(defaultOutputDevices),
mVolumeCurves(volumes),
mIsSpeakerDrcEnabled(isSpeakerDrcEnabled)
{}
void setVolumes(const VolumeCurvesCollection &volumes)
{
if (mVolumeCurves != nullptr) {
*mVolumeCurves = volumes;
}
}
void setHwModules(const HwModuleCollection &hwModules)
{
mHwModules = hwModules;
}
void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice)
{
if (audio_is_output_device(availableDevice->type())) {
mAvailableOutputDevices.add(availableDevice);
} else if (audio_is_input_device(availableDevice->type())) {
mAvailableInputDevices.add(availableDevice);
}
}
void addAvailableInputDevices(const DeviceVector &availableInputDevices)
{
mAvailableInputDevices.add(availableInputDevices);
}
void addAvailableOutputDevices(const DeviceVector &availableOutputDevices)
{
mAvailableOutputDevices.add(availableOutputDevices);
}
void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
{
mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
}
const HwModuleCollection getHwModules() const { return mHwModules; }
const DeviceVector &getAvailableInputDevices() const
{
return mAvailableInputDevices;
}
const DeviceVector &getAvailableOutputDevices() const
{
return mAvailableOutputDevices;
}
void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
{
mDefaultOutputDevices = defaultDevice;
}
const sp<DeviceDescriptor> &getDefaultOutputDevice() const { return mDefaultOutputDevices; }
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("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->mOutputProfiles.add(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->mInputProfiles.add(inProfile);
mHwModules.add(module);
}
private:
HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
DeviceVector &mAvailableOutputDevices;
DeviceVector &mAvailableInputDevices;
sp<DeviceDescriptor> &mDefaultOutputDevices;
VolumeCurvesCollection *mVolumeCurves;
bool &mIsSpeakerDrcEnabled;
};
}; // namespace android
可以看出 AudioPolicyConfig对象
为封装的audio_policy.conf
的对象。
而AudioPolicyConfig对象
包含了audio_policy.conf
中所有hw音频模块的集合、可获取的输入、输出设备的集合,默认输出设备的集合
分析完 AudioPolicyConfig对象
,来到 loadConfig
//static
status_t ConfigParsingUtils::loadConfig(const char *path, AudioPolicyConfig &config)
{
cnode *root;
char *data;
data = (char *)load_file(path, NULL);
if (data == NULL) {
return -ENODEV;
}
root = config_node("", "");
config_load(root, data);
HwModuleCollection hwModules;
loadHwModules(root, hwModules, config);
// legacy audio_policy.conf files have one global_configuration section, attached to primary.
loadGlobalConfig(root, config, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY));
config.setHwModules(hwModules);
config_free(root);
free(root);
free(data);
ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
return NO_ERROR;
}
前面 load_file
与 config_node
与 config_load
三个函数用于加载 audio_policy.conf
文件 并将文件中所有数据以 cnode
结构体的形式 保存在 变量root 中
而audio_policy.conf
文件分为两大块:
modules 模块
GlobalConfig 全局配置
cnode
定义在 config_utils.h
位于 \system\core\include\cutils
如下:
typedef struct cnode cnode;
struct cnode
{
cnode *next;
cnode *first_child;
cnode *last_child;
const char *name;
const char *value;
};
让我们来理解下 cnode
,有助于我们后续分析,
其中 ***{}
前面加node name 和两个大括号{}一个组合代表cnode
以上面的audio_policy.conf
为例:
# Global configuration section:
# - before audio HAL version 3.0:
# lists input and output devices always present on the device
# as well as the output device selected by default.
# Devices are designated by a string that corresponds to the enum in audio.h
#
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
default_output_device AUDIO_DEVICE_OUT_SPEAKER
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
#AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_DIA_REMOTE
}
#
# - after and including audio HAL 3.0 the global_configuration section is included in each
# hardware module section.
# it also includes the audio HAL version of this hw module:
# global_configuration {
# ...
# audio_hal_version <major.minor> # audio HAL version in e.g. 3.0
# }
# other attributes (attached devices, default device) have to be included in the
# global_configuration section of each hardware module
# audio hardware module section: contains descriptors for all audio hw modules present on the
# device. Each hw module node is named after the corresponding hw module library base name.
# For instance, "primary" corresponds to audio.primary.<device>.so.
# The "primary" module is mandatory and must include at least one output with
# AUDIO_OUTPUT_FLAG_PRIMARY flag.
# Each module descriptor contains one or more output profile descriptors and zero or more
# input profile descriptors. Each profile lists all the parameters supported by a given output
# or input stream category.
# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
audio_hw_modules {
#HwModule
primary {
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
default_output_device AUDIO_DEVICE_OUT_SPEAKER
#attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
audio_hal_version 3.0
}
#DeviceVector
devices {
speaker {
#DeviceDescriptor -> DeviceVector
type AUDIO_DEVICE_OUT_SPEAKER
#AudioGain -> audioPort.mGains
gains {
gain_1 {
mode AUDIO_GAIN_MODE_JOINT
min_value_mB -8400
max_value_mB 4000
default_value_mB 0
step_value_mB 100
}
}
}
HDMI {
type AUDIO_DEVICE_OUT_AUX_DIGITAL
}
SPDIF {
type AUDIO_DEVICE_OUT_SPDIF
}
wired_headphone {
type AUDIO_DEVICE_OUT_WIRED_HEADPHONE
}
wired_headset {
type AUDIO_DEVICE_OUT_WIRED_HEADSET
}
BT_sco {
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO
}
BT_sco_headset {
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
}
}
outputs {
#IOProfile
primary {
#SampleRateVector -->AudioProfile -->AudioProfileVector
sampling_rates 48000
#ChannelsVector -->AudioProfile -->AudioProfileVector
channel_masks AUDIO_CHANNEL_OUT_STEREO
#FormatVector -->AudioProfile -->AudioProfileVector
formats AUDIO_FORMAT_PCM_16_BIT
#IOProfile
devices speaker|HDMI|SPDIF|wired_headphone|wired_headset|BT_sco|BT_sco_headset
#IOProfile
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
#here for HDMI audio dynamic profile from edid
hdmi_output {
sampling_rates dynamic
channel_masks dynamic
formats dynamic
devices HDMI
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC
}
spdif_device_raw {
sampling_rates 32000|44100|48000
channel_masks AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_5POINT1
formats AUDIO_FORMAT_DTS|AUDIO_FORMAT_AC3
devices SPDIF
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO
}
}
inputs {
primary {
sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET
}
}
}
usb {
outputs {
usb_accessory {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_ACCESSORY
}
usb_device {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_DEVICE
}
}
inputs {
usb_device {
sampling_rates 8000|11025|16000|22050|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_USB_DEVICE
}
}
}
r_submix {
outputs {
submix {
sampling_rates 48000
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
}
}
inputs {
submix {
sampling_rates 48000
channel_masks AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
}
}
}
a2dp {
outputs {
a2dp {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_ALL_A2DP
}
}
}
}
整个文件为一个cnode
,称为 root
那么,root->first_child=audio_hw_modules{}
那么,root->next=NULL
那么,root->last_child=NULL
那么,root->name=""
那么,root->value=""
那么audio_hw_modules{}
的first_child
为 primary{}
那么audio_hw_modules{}
的next
为 usb{}
那么audio_hw_modules{}
的last_child
为 a2dp{}
那么audio_hw_modules{}
的 value=""
那么audio_hw_modules{}
的 name="audio_hw_modules"
…以此类推
了解了cnode
之后,
我们首先看到audio_policy.conf
的第一个大模块,modules模块,看到 loadHwModules
函数
/**
audio_hw_modules{}
*/
//static
void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules,
AudioPolicyConfig &config)
{
cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
if (node == NULL) {
return;
}
/**
primary {}
*/
node = node->first_child;
while (node) {
ALOGV("loadHwModules() loading module %s", node->name);
sp<HwModule> module = new HwModule(node->name);
if (loadHwModule(node, module, config) == NO_ERROR) {
hwModules.add(module);
}
/**
usb{}
*/
node = node->next;
}
}
看到 config_find
位于: \system\core\libcutils\config_utils.c
cnode* config_find(cnode *root, const char *name)
{
cnode *node, *match = NULL;
/* we walk the whole list, as we need to return the last (newest) entry */
for(node = root->first_child; node; node = node->next)
if(!strcmp(node->name, name))
match = node;
return match;
}
遍历一个大cnode ,通过name 与cnode->name匹配,找到相等的子cnode,并返回。
我们这里通过 宏定义 ,源码位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\audio_policy_conf.h
// hw modules descriptions
#define AUDIO_HW_MODULE_TAG "audio_hw_modules"
找到 audio_hw_modules{}
模块,
随之遍历audio_hw_modules{}
模块,之后为每个音频hw 动态库创建了 HwModule对象
例如:audio_hw_modules{}->first_child=primary{}
创建了 HwModule对象
并将 primary{}->name
传入构造,作为HwModule对象
的name
字段HwModule对象
位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\HwModule
然后使用 HwModuleCollection 对象
容器增加每个 HwModule对象
,
找到 HwModuleCollection 对象
源码,位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\HwModule
class HwModuleCollection : public Vector<sp<HwModule> >
{
public:
sp<HwModule> getModuleFromName(const char *name) const;
sp<HwModule> getModuleForDevice(audio_devices_t device) const;
sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
const char *device_address,
const char *device_name,
bool matchAdress = true) const;
status_t dump(int fd) const;
};
可以看到 HwModuleCollection 对象
为泛型为 HwModule 对象
的集合
接着解析每个音频hw模块,首先来到 primary{}
,看到 loadHwModule
/**
primary {}
*/
//static
status_t ConfigParsingUtils::loadHwModule(cnode *root, sp<HwModule> &module,
AudioPolicyConfig &config)
{
status_t status = NAME_NOT_FOUND;
/**
devices{}
devices{}
*/
cnode *node = config_find(root, DEVICES_TAG);
if (node != NULL) {
/**
speaker{}
*/
node = node->first_child;
DeviceVector devices;
while (node) {
ALOGV("loadHwModule() loading device %s", node->name);
status_t tmpStatus = loadHwModuleDevice(node, devices);
if (status == NAME_NOT_FOUND || status == NO_ERROR) {
status = tmpStatus;
}
/**
HDMI {}
*/
node = node->next;
}
module->setDeclaredDevices(devices);
}
/**
outputs {}
*/
node = config_find(root, OUTPUTS_TAG);
if (node != NULL) {
/**
primary {}
*/
node = node->first_child;
while (node) {
ALOGV("loadHwModule() loading output %s", node->name);
status_t tmpStatus = loadHwModuleProfile(node, module, AUDIO_PORT_ROLE_SOURCE);
if (status == NAME_NOT_FOUND || status == NO_ERROR) {
status = tmpStatus;
}
/**
hdmi_output{}
spdif_device_raw{}
*/
node = node->next;
}
}
/**
inputs{}
inputs{}
*/
node = config_find(root, INPUTS_TAG);
if (node != NULL) {
node = node->first_child;
while (node) {
ALOGV("loadHwModule() loading input %s", node->name);
status_t tmpStatus = loadHwModuleProfile(node, module, AUDIO_PORT_ROLE_SINK);
if (status == NAME_NOT_FOUND || status == NO_ERROR) {
status = tmpStatus;
}
node = node->next;
}
}
loadModuleGlobalConfig(root, module, config);
return status;
}
通过 loadHwModule
可以看出 每个 HwModule对象
也就是每个音频库模块大致又分为四个大类:
DEVICES_TAG ---->称为模块设备解析
OUTPUTS_TAG ---->称为模块输出设备解析
OUTPUTS_TAG ---->称为模块输入设备解析
loadModuleGlobalConfig ---->称为模块全局配置解析
- 1
- 2
- 3
- 4
首先看到 DEVICES_TAG
,也就是 primary{.....devices{}...}
看到代码中又是通过一个while循环遍历primary{.....devices{}...}
,
然后通过 loadHwModuleDevice
函数解析 primary{.....devices{}...}
子cnode,
HwModule对象
包含 DeviceVector 对象
属性
DeviceVector 对象
找到源码,位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\src\DeviceDescriptor.h
class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
{
public:
DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
ssize_t add(const sp<DeviceDescriptor>& item);
void add(const DeviceVector &devices);
ssize_t remove(const sp<DeviceDescriptor>& item);
ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
audio_devices_t types() const { return mDeviceTypes; }
sp<DeviceDescriptor> getDevice(audio_devices_t type, String8 address) const;
DeviceVector getDevicesFromType(audio_devices_t types) const;
sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const;
DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) const;
audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
status_t dump(int fd, const String8 &tag, int spaces = 0, bool verbose = true) const;
private:
void refreshTypes();
audio_devices_t mDeviceTypes;
};
可以看出DeviceVector 对象
为一个泛型为 DeviceDescriptor对象
的集合,由此可以得知 用 DeviceDescriptor对象
描述 每个 primary{.....devices{}...}
子cnode
那么,接着看看怎么将每个 primary{.....devices{}...}
子cnode 解析成 DeviceDescriptor对象
看到loadHwModuleDevice
,
/**
speaker{}
HDMI {}
*/
//static
status_t ConfigParsingUtils::loadHwModuleDevice(cnode *root, DeviceVector &devices)
{
/**
type{}
type{}
*/
cnode *node = root->first_child;
audio_devices_t type = AUDIO_DEVICE_NONE;
while (node) {
if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
DeviceConverter::fromString(node->value, type);
break;
}
node = node->next;
}
if (type == AUDIO_DEVICE_NONE ||
(!audio_is_input_device(type) && !audio_is_output_device(type))) {
ALOGW("loadDevice() bad type %08x", type);
return BAD_VALUE;
}
sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type, String8(root->name));
/**
type{}
type{}
*/
node = root->first_child;
while (node) {
if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) {
deviceDesc->mAddress = String8((char *)node->value);
} else if (strcmp(node->name, CHANNELS_TAG) == 0) {
if (audio_is_input_device(type)) {
deviceDesc->addAudioProfile(
new AudioProfile(gDynamicFormat,
inputChannelMasksFromString(node->value),
SampleRateVector()));
} else {
deviceDesc->addAudioProfile(
new AudioProfile(gDynamicFormat,
outputChannelMasksFromString(node->value),
SampleRateVector()));
}
} else if (strcmp(node->name, GAINS_TAG) == 0) {
loadDeviceDescriptorGains(node, deviceDesc);
}
/**
gains {}
*/
node = node->next;
}
ALOGV("loadDevice() adding device tag (literal type) %s type %08x address %s",
deviceDesc->getTagName().string(), type, deviceDesc->mAddress.string());
devices.add(deviceDesc);
return NO_ERROR;
}
通过 loadHwModuleDevice
也看出 使用 DeviceDescriptor
对象描述primary{.....devices{}...}
子cnode,DeviceDescriptor
对象源码位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\DeviceDescriptor.h
class DeviceDescriptor : public AudioPort, public AudioPortConfig
{
....
};
DeviceDescriptor对象
继承自 AudioPort 对象
和 AudioPortConfig对象
DeviceDescriptor
对象 构造需要name和type属性,源码位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\src\DeviceDescriptor.cpp
...
namespace android {
DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
mAddress(""), mTagName(tagName), mDeviceType(type), mId(0)
{
if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
mAddress = String8("0");
}
}
...
根据type给AudioPort对象
的第三个参数 role
赋值,如果是output的type,则 role=AUDIO_PORT_ROLE_SINK
,input role=AUDIO_PORT_ROLE_SOURCE
AudioPort对象
源码位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\src\AudioPort.h
...
class AudioPort : public virtual RefBase
{
public:
AudioPort(const String8& name, audio_port_type_t type, audio_port_role_t role) :
mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
...
}
可以看出 primary{.....devices{}...}
子cnode 中可以包含
type ,gains,channel_masks,address属性
channel_masks属性 又封装在AudioProfile对象
中AudioProfile对象
源码位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\AudioProfile.h
AudioProfile对象
构造需要 采样位宽、声道,采样率容器,三个参数。
声道参数则为 channel_masks 属性的值
gains通过 loadDeviceDescriptorGains函数
再到 loadAudioPortGains函数
:
/**
gains {}
*/
void ConfigParsingUtils::loadAudioPortGains(cnode *root, AudioPort &audioPort)
{
/**
gain_1 {}
*/
cnode *node = root->first_child;
int index = 0;
while (node) {
ALOGV("loadGains() loading gain %s", node->name);
loadAudioPortGain(node, audioPort, index++);
node = node->next;
}
}
可以看到 loadAudioPortGain函数
解析 gains {}
看到loadAudioPortGain函数
/**
gain_1 {}
*/
//static
void ConfigParsingUtils::loadAudioPortGain(cnode *root, AudioPort &audioPort, int index)
{
/**
mode{}
*/
cnode *node = root->first_child;
sp<AudioGain> gain = new AudioGain(index, audioPort.useInputChannelMask());
while (node) {
if (strcmp(node->name, GAIN_MODE) == 0) {
gain->setMode(GainModeConverter::maskFromString(node->value));
} else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
audio_channel_mask_t mask;
if (audioPort.useInputChannelMask()) {
if (InputChannelConverter::fromString(node->value, mask)) {
gain->setChannelMask(mask);
}
} else {
if (OutputChannelConverter::fromString(node->value, mask)) {
gain->setChannelMask(mask);
}
}
} else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
gain->setMinValueInMb(atoi(node->value));
} else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
gain->setMaxValueInMb(atoi(node->value));
} else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
gain->setDefaultValueInMb(atoi(node->value));
} else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
gain->setStepValueInMb(atoi(node->value));
} else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
gain->setMinRampInMs(atoi(node->value));
} else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
gain->setMaxRampInMs(atoi(node->value));
}
node = node->next;
}
ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
gain->getMaxValueInMb());
if (gain->getMode() == 0) {
return;
}
audioPort.mGains.add(gain);
}
可以看出 通过 AudioGain对象
封装 gains {}
子cnodegains {}
子cnode可以包含如下属性:
mode、channel_mask、min_value_mB、max_value_mB、default_value_mB、step_value_mB、min_ramp_ms、max_ramp_ms
最后将所有的 AudioGain对象
增加到 AudioGainCollection对象
容器中,AudioGainCollection对象
隶属于 AudioProfile对象
,
而 DeviceDescriptor对象
继承自 AudioPort 对象
到这里DEVICES_TAG
也就结束了
总结一下:
primary { ---->HwModule ---->HwModuleCollection
…
#DeviceVector
devices {
speaker { ----->DeviceDescriptor ---->DeviceVector
type AUDIO_DEVICE_OUT_SPEAKER
gains {
gain_1 { —> AudioGain —>AudioGainCollection —>AudioPort
mode AUDIO_GAIN_MODE_JOINT
min_value_mB -8400
max_value_mB 4000
default_value_mB 0
step_value_mB 100
}
}
}
HDMI { ----->DeviceDescriptor ---->DeviceVector
type AUDIO_DEVICE_OUT_AUX_DIGITAL
}
SPDIF { ----->DeviceDescriptor ---->DeviceVector
type AUDIO_DEVICE_OUT_SPDIF
}
wired_headphone { ----->DeviceDescriptor ---->DeviceVector
type AUDIO_DEVICE_OUT_WIRED_HEADPHONE
}
wired_headset { ----->DeviceDescriptor ---->DeviceVector
type AUDIO_DEVICE_OUT_WIRED_HEADSET
}
BT_sco { ----->DeviceDescriptor ---->DeviceVector
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO
}
BT_sco_headset { ----->DeviceDescriptor ---->DeviceVector
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
}
…
}
接着回到loadHwModule
,看看 OUTPUTS_TAG
/**
outputs {}
*/
node = config_find(root, OUTPUTS_TAG);
if (node != NULL) {
/**
primary {}
*/
node = node->first_child;
while (node) {
ALOGV("loadHwModule() loading output %s", node->name);
status_t tmpStatus = loadHwModuleProfile(node, module, AUDIO_PORT_ROLE_SOURCE);
if (status == NAME_NOT_FOUND || status == NO_ERROR) {
status = tmpStatus;
}
/**
hdmi_output{}
spdif_device_raw{}
*/
node = node->next;
}
}
首先找到primary{.....outputs{}...}
然后通过 loadHwModuleProfile 函数
解析 outputs{}
每个子cnode
根据示例,来到第一个字cnode primary{}
primary {
#SampleRateVector -->AudioProfile -->AudioProfileVector
sampling_rates 48000
#ChannelsVector -->AudioProfile -->AudioProfileVector
channel_masks AUDIO_CHANNEL_OUT_STEREO
#FormatVector -->AudioProfile -->AudioProfileVector
formats AUDIO_FORMAT_PCM_16_BIT
#IOProfile
devices speaker|HDMI|SPDIF|wired_headphone|wired_headset|BT_sco|BT_sco_headset
#IOProfile
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
loadHwModuleProfile 函数
如下:
/**
primary {}
primary{}
blemic{}
*/
//static
status_t ConfigParsingUtils::loadHwModuleProfile(cnode *root, sp<HwModule> &module,
audio_port_role_t role)
{
/**
sampling_rates{}
sampling_rates{}
*/
cnode *node = root->first_child;
sp<IOProfile> profile = new IOProfile(String8(root->name), role);
AudioProfileVector audioProfiles;
SampleRateVector sampleRates;
ChannelsVector channels;
FormatVector formats;
while (node) {
if (strcmp(node->name, FORMATS_TAG) == 0 &&
strcmp(node->value, DYNAMIC_VALUE_TAG) != 0) {
formats = formatsFromString(node->value);
} else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0 &&
strcmp(node->value, DYNAMIC_VALUE_TAG) != 0) {
collectionFromString<SampleRateTraits>(node->value, sampleRates);
} else if (strcmp(node->name, CHANNELS_TAG) == 0 &&
strcmp(node->value, DYNAMIC_VALUE_TAG) != 0) {
if (role == AUDIO_PORT_ROLE_SINK) {
channels = inputChannelMasksFromString(node->value);
} else {
channels = outputChannelMasksFromString(node->value);
}
} else if (strcmp(node->name, DEVICES_TAG) == 0) {
DeviceVector devices;
loadDevicesFromTag(node->value, devices, module->getDeclaredDevices());
profile->setSupportedDevices(devices);
} else if (strcmp(node->name, FLAGS_TAG) == 0) {
if (role == AUDIO_PORT_ROLE_SINK) {
profile->setFlags(InputFlagConverter::maskFromString(node->value));
} else {
profile->setFlags(OutputFlagConverter::maskFromString(node->value));
}
} else if (strcmp(node->name, GAINS_TAG) == 0) {
loadAudioPortGains(node, *profile);
}
/**
channel_masks{}
formats{}
devices{}
channel_masks{}
formats{}
devices{}
*/
node = node->next;
}
if (formats.isEmpty()) {
sp<AudioProfile> profileToAdd = new AudioProfile(gDynamicFormat, channels, sampleRates);
profileToAdd->setDynamicFormat(true);
profileToAdd->setDynamicChannels(channels.isEmpty());
profileToAdd->setDynamicRate(sampleRates.isEmpty());
audioProfiles.add(profileToAdd);
} else {
for (size_t i = 0; i < formats.size(); i++) {
// For compatibility reason, for each format, creates a profile with the same
// collection of rate and channels.
sp<AudioProfile> profileToAdd = new AudioProfile(formats[i], channels, sampleRates);
profileToAdd->setDynamicFormat(formats[i] == gDynamicFormat);
profileToAdd->setDynamicChannels(channels.isEmpty());
profileToAdd->setDynamicRate(sampleRates.isEmpty());
audioProfiles.add(profileToAdd);
}
}
profile->setAudioProfiles(audioProfiles);
ALOGW_IF(!profile->hasSupportedDevices(), "load%s() invalid supported devices",
role == AUDIO_PORT_ROLE_SINK ? "Input" : "Output");
if (profile->hasSupportedDevices()) {
ALOGV("load%s() adding Supported Devices %04x, mFlags %04x",
role == AUDIO_PORT_ROLE_SINK ? "Input" : "Output",
profile->getSupportedDevicesType(), profile->getFlags());
return module->addProfile(profile);
}
return BAD_VALUE;
}
从以上可以看到 outputs{}
子cnode通过 IOProfile对象
解析封装,
outputs{}
子cnode可以定义以下属性:
formats、sampling_rates、channel_masks、devices、 flags、gains
而formats —> 通过泛型为audio_format_t
的FormatVector
容器封装起来
sampling_rates–> 泛型为uint32_t
的SampleRateVector
容器,
channel_masks --> 泛型为audio_channel_mask_t
的ChannelsVector
容器
devices 属性 的流是这样:
//static
void ConfigParsingUtils::loadDevicesFromTag(const char *tag, DeviceVector &devices,
const DeviceVector &declaredDevices)
{
char *tagLiteral = strndup(tag, strlen(tag));
char *devTag = strtok(tagLiteral, "|");
while (devTag != NULL) {
if (strlen(devTag) != 0) {
audio_devices_t type;
if (DeviceConverter::fromString(devTag, type)) {
uint32_t inBit = type & AUDIO_DEVICE_BIT_IN;
type &= ~AUDIO_DEVICE_BIT_IN;
while (type) {
audio_devices_t singleType =
inBit | (1 << (31 - __builtin_clz(type)));
type &= ~singleType;
sp<DeviceDescriptor> dev = new DeviceDescriptor(singleType);
devices.add(dev);
}
} else {
sp<DeviceDescriptor> deviceDesc =
declaredDevices.getDeviceFromTagName(String8(devTag));
if (deviceDesc != 0) {
devices.add(deviceDesc);
}
}
}
devTag = strtok(NULL, "|");
}
free(tagLiteral);
}
首先获取到其属性值,通过 “|” 将每个值拆分开来,
然后 判断每个的值是否是device_type还是tagName,通过函数DeviceConverter::fromString(devTag, type)
区分
如果是tagName则从之前第一部分解析DEVICES_TAG的devices{} 部分获取到的DeviceVector
遍历其,获取DeviceDescriptor对象
,如果为null,则不添加,如果不为null,则添加到outputs{}
的DeviceVector对象
中
如果是device_type则new DeviceDescriptor
将device_type 传入作为其type值,而默认的 缺省参数 “” 作为tagName。
而 gains 的流程跟DEVICES_TAG的devices{} 相同
接着 又将 FormatVector 、SampleRateVector、ChannelsVector
三个容器封装在 AudioProfile对象
中,如果 FormatVector
为空,则只有一个 AudioProfile对象
,否则,根据FormatVector.size()
决定AudioProfile对象
的个数,通过AudioProfileVector对象
容器增加AudioProfile对象
。AudioProfile对象
位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\AudioProfile.h
看到 IOProfile 对象
,源码位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\IOProfile.h
...
class IOProfile : public AudioPort
...
可以看到 IOProfile对象
和 DeviceDescriptor对象
一样都继承自AudioPort对象
到这里 outputs{}
的第一个子cnode primary {}
就解析完毕,示例中outputs{}
其他子cnode hdmi_output {}
与 spdif_device_raw{}
也是类似,不再累赘
到这里OUTPUTS_TAG
模块就解析完毕,
总结一下:
primary { ---->HwModule ---->HwModuleCollection
…
outputs {
#IOProfile
primary { —> IOProfile —>OutputProfileCollection & AudioPortVector
sampling_rates 48000 —>SampleRateVector —>AudioProfile —>AudioProfileVector
channel_masks AUDIO_CHANNEL_OUT_STEREO —>ChannelsVector -->AudioProfile -->AudioProfileVector
formats AUDIO_FORMAT_PCM_16_BIT –>FormatVector -->AudioProfile -->AudioProfileVector
devices speaker|HDMI|SPDIF|wired_headphone|wired_headset|BT_sco|BT_sco_headset
---->DeviceDescriptor —>DeviceVector
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
…
}
…
}
接下看到 模块 INPUTS_TAG
/**
inputs{}
inputs{}
*/
node = config_find(root, INPUTS_TAG);
if (node != NULL) {
node = node->first_child;
while (node) {
ALOGV("loadHwModule() loading input %s", node->name);
status_t tmpStatus = loadHwModuleProfile(node, module, AUDIO_PORT_ROLE_SINK);
if (status == NAME_NOT_FOUND || status == NO_ERROR) {
status = tmpStatus;
}
node = node->next;
}
}
对比发现 INPUTS_TAG
& OUTPUTS_TAG
都是通过loadHwModuleProfile函数
解析,只是在 IOProfile对象
对象中表现的role是不一样的,如果是 OUTPUTS_TAG
, IOProfile对象
的role是 AUDIO_PORT_ROLE_SOURCE
, INPUTS_TAG
则是 AUDIO_PORT_ROLE_SINK
那么最后来看下模块全局的配置解析:
/**
primary {}
*/
//static
void ConfigParsingUtils::loadModuleGlobalConfig(cnode *root, const sp<HwModule> &module,
AudioPolicyConfig &config)
{
/**
global_configuration{}
*/
cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
if (node == NULL) {
return;
}
DeviceVector declaredDevices;
if (module != NULL) {
declaredDevices = module->getDeclaredDevices();
}
/**
attached_output_devices{}
*/
node = node->first_child;
while (node) {
if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
DeviceVector availableOutputDevices;
loadDevicesFromTag(node->value, availableOutputDevices, declaredDevices);
ALOGV("loadGlobalConfig() Attached Output Devices %08x",
availableOutputDevices.types());
config.addAvailableOutputDevices(availableOutputDevices);
} else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
audio_devices_t device = AUDIO_DEVICE_NONE;
DeviceConverter::fromString(node->value, device);
if (device != AUDIO_DEVICE_NONE) {
sp<DeviceDescriptor> defaultOutputDevice = new DeviceDescriptor(device);
config.setDefaultOutputDevice(defaultOutputDevice);
ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
} else {
ALOGW("loadGlobalConfig() default device not specified");
}
} else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
DeviceVector availableInputDevices;
loadDevicesFromTag(node->value, availableInputDevices, declaredDevices);
ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types());
config.addAvailableInputDevices(availableInputDevices);
} else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
uint32_t major, minor;
sscanf((char *)node->value, "%u.%u", &major, &minor);
module->setHalVersion(HARDWARE_DEVICE_API_VERSION(major, minor));
ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
module->getHalVersion(), major, minor);
}
node = node->next;
}
}
首先找到 primary {}
的子cnode global_configuration{}
,global_configuration{}
支持以下属性:
attached_output_devices、default_output_device、attached_input_devices、audio_hal_version
其中 attached_output_devices & attached_output_devices 也是通过 loadDevicesFromTag
函数解析,并将可获取的输入、输出设备集合添加到AudioPolicyConfig 对象
中
而default_output_device则是直接new DeviceDescriptor
,并传入其值作为type,其对象作为AudioPolicyConfig 对象
默认的输出设备
audio_hal_version则是将其主、次版本值、拼接在一起,并设置为其HwModule对象
模块的版本。
到这里我们的模块全局配置就解析完毕,
这样意味着我们已经将其中之一模块已经完整解析完毕,其他的每个模块也是类似。就不在累赘。
最后在看到audio_policy.conf
中的另一个大模块,全局配置GlobalConfig模块,
}
/**
audio_hw_modules{}
*/
//static
void ConfigParsingUtils::loadGlobalConfig(cnode *root, AudioPolicyConfig &config,
const sp<HwModule>& primaryModule)
{
/**
global_configuration{}
*/
cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
if (node == NULL) {
return;
}
/**
attached_output_devices{}
*/
node = node->first_child;
while (node) {
if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
bool speakerDrcEnabled;
if (utilities::convertTo<std::string, bool>(node->value, speakerDrcEnabled)) {
ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled);
config.setSpeakerDrcEnabled(speakerDrcEnabled);
}
}
node = node->next;
}
loadModuleGlobalConfig(root, primaryModule, config);
}
从上面可以看出全局配置GlobalConfig模块 比modules模块 中的模块全局配置
多了一个属性SPEAKER_DRC_ENABLED_TAG --> speaker_drc_enabled
其他的解析过程和modules模块 中的模块全局配置 都是通过 loadModuleGlobalConfig函数解析。
到这里的话整个audio_policy.conf
就解析完毕了,现在我们来总结下
...
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
#--->addAvailableOutputDevices --->AudioPolicyConfig
default_output_device AUDIO_DEVICE_OUT_SPEAKER
# --->setDefaultOutputDevice --->AudioPolicyConfig
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_DIA_REMOTE
# --->addAvailableInputDevices --->AudioPolicyConfig
}
...
audio_hw_modules { # --->HwModuleCollection --->AudioPolicyConfig.setHwModules(hwModules);
...
primary {#--->HwModule.mName--->HwModule(primary)
...
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
#--->AudioPolicyConfig.addAvailableOutputDevices
default_output_device AUDIO_DEVICE_OUT_SPEAKER
# --->AudioPolicyConfig.setDefaultOutputDevice
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
# --->AudioPolicyConfig.addAvailableInputDevices
audio_hal_version 3.0
#--->setHalVersion --->HwModule.mHalVersion
}
devices {
speaker { #--->DeviceDescriptor-->DeviceVector-->HwModule.mDeclaredDevices
type AUDIO_DEVICE_OUT_SPEAKER
#-->DeviceDescriptor.mDeviceType
gains {
gain_1 {
#-->AudioGain——>AudioPort.mGains(AudioGainCollection)-->DeviceDescriptor
mode AUDIO_GAIN_MODE_JOINT
#--->AudioGain.mode
min_value_mB -8400
#--->AudioGain.min_value
max_value_mB 4000
#--->AudioGain.max_value
default_value_mB 0
#--->AudioGain.default_value
step_value_mB 100
#--->AudioGain.step_value
}
}
}
...
}
outputs {
#OutputProfile-->IOProfile.AudioPort.mRole=AUDIO_PORT_ROLE_SOURCE
...
primary { #OutputProfile-->IOProfile--->AudioPort.mName
sampling_rates 48000
#SampleRateVector-->AudioProfile-->AudioProfileVector-->IOProfile-->AudioPort.mProfiles
channel_masks AUDIO_CHANNEL_OUT_STEREO
#ChannelsVector-->AudioProfile-->AudioProfileVector-->IOProfile-->AudioPort.mProfiles
formats AUDIO_FORMAT_PCM_16_BIT
#FormatVector-->AudioProfile-->AudioProfileVector-->IOProfile-->AudioPort.mProfiles
devices speaker|HDMI|SPDIF|wired_headphone|wired_headset|BT_sco|BT_sco_headset
#IOProfile.mSupportedDevices
flags AUDIO_OUTPUT_FLAG_PRIMARY
#IOProfile.mFlags
}
...
}
inputs { #InputProfile-->IOProfile.AudioPort.mRole=AUDIO_PORT_ROLE_SINK
primary { #InputProfile-->IOProfile--->AudioPort.mName
sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
#SampleRateVector-->AudioProfile-->AudioProfileVector-->IOProfile-->AudioPort.mProfiles
channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
#ChannelsVector-->AudioProfile-->AudioProfileVector-->IOProfile-->AudioPort.mProfiles
formats AUDIO_FORMAT_PCM_16_BIT
#FormatVector-->AudioProfile-->AudioProfileVector-->IOProfile-->AudioPort.mProfiles
devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET
#IOProfile.mSupportedDevices
}
}
...
}
...
}
本文基于android7.0分析
一、概念
audio_policy.conf
: 顾名思义 audio hw 模块配置文件,用于加载音频硬件抽象层动态库。得到系统所支持的输入、输出音频设备。位于系统 /system/etc/
二、系统解析
以如下audio_policy.conf
为例:
# Global configuration section:
# - before audio HAL version 3.0:
# lists input and output devices always present on the device
# as well as the output device selected by default.
# Devices are designated by a string that corresponds to the enum in audio.h
#
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
default_output_device AUDIO_DEVICE_OUT_SPEAKER
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
#AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_DIA_REMOTE
}
#
# - after and including audio HAL 3.0 the global_configuration section is included in each
# hardware module section.
# it also includes the audio HAL version of this hw module:
# global_configuration {
# ...
# audio_hal_version <major.minor> # audio HAL version in e.g. 3.0
# }
# other attributes (attached devices, default device) have to be included in the
# global_configuration section of each hardware module
# audio hardware module section: contains descriptors for all audio hw modules present on the
# device. Each hw module node is named after the corresponding hw module library base name.
# For instance, "primary" corresponds to audio.primary.<device>.so.
# The "primary" module is mandatory and must include at least one output with
# AUDIO_OUTPUT_FLAG_PRIMARY flag.
# Each module descriptor contains one or more output profile descriptors and zero or more
# input profile descriptors. Each profile lists all the parameters supported by a given output
# or input stream category.
# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
audio_hw_modules {
#HwModule
primary {
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
default_output_device AUDIO_DEVICE_OUT_SPEAKER
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
audio_hal_version 3.0
}
#DeviceVector
devices {
speaker {
#DeviceDescriptor -> DeviceVector
type AUDIO_DEVICE_OUT_SPEAKER
#AudioGain -> audioPort.mGains
gains {
gain_1 {
mode AUDIO_GAIN_MODE_JOINT
min_value_mB -8400
max_value_mB 4000
default_value_mB 0
step_value_mB 100
}
}
}
HDMI {
type AUDIO_DEVICE_OUT_AUX_DIGITAL
}
SPDIF {
type AUDIO_DEVICE_OUT_SPDIF
}
wired_headphone {
type AUDIO_DEVICE_OUT_WIRED_HEADPHONE
}
wired_headset {
type AUDIO_DEVICE_OUT_WIRED_HEADSET
}
BT_sco {
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO
}
BT_sco_headset {
type AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
}
}
outputs {
#IOProfile
primary {
#SampleRateVector -->AudioProfile -->AudioProfileVector
sampling_rates 48000
#ChannelsVector -->AudioProfile -->AudioProfileVector
channel_masks AUDIO_CHANNEL_OUT_STEREO
#FormatVector -->AudioProfile -->AudioProfileVector
formats AUDIO_FORMAT_PCM_16_BIT
#IOProfile
devices speaker|HDMI|SPDIF|wired_headphone|wired_headset|BT_sco|BT_sco_headset
#IOProfile
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
#here for HDMI audio dynamic profile from edid
hdmi_output {
sampling_rates dynamic
channel_masks dynamic
formats dynamic
devices HDMI
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC
}
spdif_device_raw {
sampling_rates 32000|44100|48000
channel_masks AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_5POINT1
formats AUDIO_FORMAT_DTS|AUDIO_FORMAT_AC3
devices SPDIF
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO
}
}
inputs {
primary {
sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET
}
}
}
usb {
outputs {
usb_accessory {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_ACCESSORY
}
usb_device {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_DEVICE
}
}
inputs {
usb_device {
sampling_rates 8000|11025|16000|22050|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_USB_DEVICE
}
}
}
r_submix {
outputs {
submix {
sampling_rates 48000
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
}
}
inputs {
submix {
sampling_rates 48000
channel_masks AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
}
}
}
a2dp {
outputs {
a2dp {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_ALL_A2DP
}
}
}
}