audio_policy.conf文件解析

概述

对于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\n", 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 "\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"
....依次类推

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

 

posted @ 2021-01-10 16:32  一代枭雄  阅读(1327)  评论(0编辑  收藏  举报