本文基于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

怎么配置android开发环境 安卓开发 配置文件_加载

init 进程有个任务是启动init.rc,

init.rc 会启动 audioserver.rc,

audioserver.rc 位于 frameworks\av\media\audioserveraudioserver.rc 会启动 音频服务的主入口:main_audioserver.cpp

main_audioserver.cpp 位于 frameworks\av\media\audioservermain_audioserver.cpp 主入口main函数会初始化 AudioPolicyService对象

AudioPolicyService.cpponFirstRef() 函数初始化 中 调用

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_fileconfig_nodeconfig_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_childprimary{} 那么audio_hw_modules{}nextusb{} 那么audio_hw_modules{}last_childa2dp{} 那么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_SOURCEAudioPort对象 源码位于:
\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.hAudioProfile对象 构造需要 采样位宽、声道,采样率容器,三个参数。
声道参数则为 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 {} 子cnode
gains {} 子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_tFormatVector容器封装起来
sampling_rates–> 泛型为uint32_tSampleRateVector容器,
channel_masks --> 泛型为audio_channel_mask_tChannelsVector 容器

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_TAGIOProfile对象 的role是 AUDIO_PORT_ROLE_SOURCEINPUTS_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
      }
    }
  }
}