概述
对于Android7.0之后,虽然不再使用audio_policy.conf文件,但是从学习的角度有必要去分析一下这个文件。
1. AudioPolicyConfig config
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled);
定义了一个AudioPolicyConfig的构造函数,源码如下:
/frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
class AudioPolicyConfig { public: AudioPolicyConfig(HwModuleCollection &hwModules, DeviceVector &availableOutputDevices, DeviceVector &availableInputDevices, sp<DeviceDescriptor> &defaultOutputDevices, VolumeCurvesCollection *volumes = nullptr) : mHwModules(hwModules), mAvailableOutputDevices(availableOutputDevices), mAvailableInputDevices(availableInputDevices), mDefaultOutputDevices(defaultOutputDevices), mVolumeCurves(volumes), mIsSpeakerDrcEnabled(false) {} 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); } bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; } 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(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); } private: HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */ DeviceVector &mAvailableOutputDevices; DeviceVector &mAvailableInputDevices; sp<DeviceDescriptor> &mDefaultOutputDevices; VolumeCurvesCollection *mVolumeCurves; // TODO: remove when legacy conf file is removed. true on devices that use DRC on the // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly. // Note: remove also speaker_drc_enabled from global configuration of XML config file. bool mIsSpeakerDrcEnabled; };
可以看出AudioPolicyConfig对象为封装的audio_policy.conf对象。
AudioPolicyConfig对象包含了audio_policy.conf中所有hw音频模块的集合、可获取的输入、输出设备的集合、默认输出设备的集合
2. ConfigParsingUtils::loadConfig
调用ConfigParsingUtils类的静态成员函数loadConfig
/frameworks/av/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
//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 ", path); return NO_ERROR; }
前面load_file与config_node与config_load三个函数用于加载audio_policy.conf文件,并将文件中所有数据以cnode结构体的形式保存在变量root中。
举个例子:
从上面这个例子中可以看出:
audio_policy.conf文件分为两大块:
modules模块
GlobalConfig全局配置
我们来看一下cnode结构体的定义:
/system/core/include/cutils/config_utils.h
typedef struct cnode cnode; struct cnode { cnode *next; cnode *first_child; cnode *last_child; const char *name; const char *value; };
以audio_policy.conf文件为例,再进一步理解cnode结构体。
# 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 " ". 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"
....依次类推
3. Modules模块
需要分析函数 loadHwModules(root, hwModules, config)
/frameworks/av/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules, AudioPolicyConfig &config) { //hw modules descriptions //#define AUDIO_HW_MODULE_TAG "audio_hw_modules" /*audio_hw_modules{}*/ cnode *node = config_find(root, AUDIO_HW_MODULE_TAG); /*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.cpp
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 */ //遍历root的child,找到与name相匹配的cnode for(node = root->first_child; node; node = node->next) if(!strcmp(node->name, name)) match = node; return match; }
通过config_find函数找到了audio_hw_modules{}模块
随后会遍历audio_Hw_modules{}模块,为每个音频hw动态库创建了HwModule对象。
例如:audio_Hw_modules{}->first_child = primary{},primary{}->name = primary。
new HwModule(node->name)即new HwModule(primary),创建了一个module对象指针
HwModule::HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersionMinor) : mName(String8(name)), mHandle(AUDIO_MODULE_HANDLE_NONE) { setHalVersion(halVersionMajor, halVersionMinor); }
接下来分析 loadHwModule(node, module, config)
/frameworks/av/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
//static status_t ConfigParsingUtils::loadHwModule(cnode *root, sp<HwModule> &module, AudioPolicyConfig &config) { status_t status = NAME_NOT_FOUND; //如果我们以primary{}模块来分析,此时root就是primary{} //#define DEVICES_TAG "devices",在primary{}模块下,寻找devices{}的cnode,并放回 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); } //#define OUTPUTS_TAG "outputs" node = config_find(root, OUTPUTS_TAG); //outputs{} 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{} ... node = node->next; } } //#define INPUTS_TAG "inputs" node = config_find(root, INPUTS_TAG); //inputs{} if (node != NULL) { //primary{} 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 ----->称为模块输出设备解析
INPUTS_TAG ------>称为模块输入设备解析
loadModuleGlobalConfig ---->称为模块全局配置解析
DeviceVector devices定义了一个DeviceVector类对象
/frameworks/av/services/audiopolicy/common/managerdefinitions/include/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, const 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, const 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(node, devices)
node为speaker{}; devices为类 DeviceVector的对象
/frameworks/av/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
//static status_t ConfigParsingUtils::loadHwModuleDevice(cnode *root, DeviceVector &devices) { //type{} cnode *node = root->first_child; audio_devices_t type = AUDIO_DEVICE_NONE; while (node) { //#define APM_DEVICE_TYPE "type" //node->name = type if (strcmp(node->name, APM_DEVICE_TYPE) == 0) { //将speaker{}-->type->value转换为audio_devices_t类型的type deviceFromString(node->value, type); break; } node = node->next; } ...... //创建DeviceDescriptor对象指针, sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type, String8(root->name)); //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); } 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; }
看一下类 DeviceDescriptor的构造函数
/frameworks/av/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp