system/media/audio/include/system/audio_config.h
// 在手机上的目录列表中查找配置文件
static inline std::vector<std::string> audio_get_configuration_paths()
{
static const std::vector<std::string> paths = []() {
char value[PROPERTY_VALUE_MAX] = {};
if (property_get("ro.boot.product.vendor.sku", value, "") <= 0) {
return std::vector<std::string>({"/odm/etc", "/vendor/etc", "/system/etc"});
} else {
return std::vector<std::string>({
"/odm/etc", std::string("/vendor/etc/audio/sku_") + value,
"/vendor/etc", "/system/etc"});
}
}();
return paths;
}
static inline std::string audio_find_readable_configuration_file(const char* fileName)
{
for (const auto& path : audio_get_configuration_paths()) {
std::string tryPath = path + "/" + fileName;
if (access(tryPath.c_str(), R_OK) == 0) {
return tryPath;
}
}
return {};
}
static inline std::string audio_get_audio_policy_config_file()
{
static constexpr const char *apmXmlConfigFileName = "audio_policy_configuration.xml";
......
}
配置文件编译
device/generic/goldfish/vendor.mk
device/generic/goldfish/audio/policy/audio_policy_configuration.xml
device/generic/goldfish/audio/policy/primary_audio_policy_configuration.xml
mk文件中有如下代码:
PRODUCT_PACKAGES += \
android.hardware.audio.service \
android.hardware.audio@7.1-impl.ranchu \
android.hardware.soundtrigger@2.2-impl.ranchu \
android.hardware.audio.effect@7.0-impl \
DEVICE_MANIFEST_FILE += device/generic/goldfish/audio/android.hardware.audio.effects@7.0.xml
PRODUCT_COPY_FILES += \
device/generic/goldfish/audio/policy/audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_configuration.xml \
device/generic/goldfish/audio/policy/primary_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/primary_audio_policy_configuration.xml \
frameworks/av/services/audiopolicy/config/a2dp_in_audio_policy_configuration_7_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/a2dp_in_audio_policy_configuration_7_0.xml \
frameworks/av/services/audiopolicy/config/bluetooth_audio_policy_configuration_7_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/bluetooth_audio_policy_configuration_7_0.xml \
frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/r_submix_audio_policy_configuration.xml \
frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml \
frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
audio_policy_configuration.xml 文件的作用: 提供系统配置给 AudioPolicyManager.
device/generic/goldfish/audio/policy/audio_policy_configuration.xml 文件内容如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<!-- Global configuration Decalaration -->
<globalConfiguration speaker_drc_enabled="true"/>
<!-- Modules section:
There is one section per audio HW module present on the platform.
Each module section will contains two mandatory(必须的,强制的) tags for audio HAL “halVersion” and “name”.
The module names are the same as in current .conf file: “primary”, “A2DP”, “remote_submix”, “USB”.
Each module will contain the following sections:
“devicePorts”: A list of device descriptors(描述符) for all input and output devices accessible via this module. This contains both permanently(永久地,一直存在的) attached devices and removable(可插拔) devices.
“mixPorts”: Listing all output and input streams exposed by the audio HAL
“routes”: List of possible connections between input and output devices or between stream and devices.
"route": is defined by an attribute:
-"type": <mux|mix> means all sources are mutual exclusive (mux,互斥的,两个或多个事务不能同时存在或发生) or can be mixed (mix,混合)
-"sink": The sink(接收器,音频中的接收设备端口) involved in this route
-"sources": All the sources(源,音频中的发送端) than can be connected to the sink via vis route
“attachedDevices”: Permanently attached devices(手机内置的音频设备).
The attachedDevices section is a list of devices names. The names correspond to device names defined in <devicePorts> section.
“defaultOutputDevice”: Device to be used by default when no policy rule applies
-->
<modules>
<!-- Primary(主要的,首选的) Audio HAL -->
<module name="primary" halVersion="3.0">
<attachedDevices>
<item>Speaker</item>
<item>Built-In Mic</item>
<item>Built-In Back Mic</item>
</attachedDevices>
<defaultOutputDevice>Speaker</defaultOutputDevice>
<mixPorts>
<mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="deep_buffer" role="source" flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="compressed_offload" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD AUDIO_OUTPUT_FLAG_NON_BLOCKING">
<profile name="" format="AUDIO_FORMAT_MP3" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
<profile name="" format="AUDIO_FORMAT_AAC" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
<profile name="" format="AUDIO_FORMAT_AAC_LC" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
</mixPort>
<mixPort name="voice_tx" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</mixPort>
<mixPort name="primary input" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
</mixPort>
<mixPort name="voice_rx" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
</mixPort>
</mixPorts>
<devicePorts>
<!-- Output devices declaration, i.e. Sink DEVICE PORT -->
<devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
minValueMB="-8400"
maxValueMB="4000"
defaultValueMB="0"
stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
<devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
<devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
</devicePort>
<devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
</devicePort>
<devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
</devicePort>
<devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
</devicePort>
<devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
</devicePort>
</devicePorts>
<!-- route declaration, i.e. list all available sources for a given sink -->
<routes>
<route type="mix" sink="Earpiece" sources="primary output,deep_buffer,BT SCO Headset Mic"/>
<route type="mix" sink="Speaker" sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
<route type="mix" sink="Wired Headset" sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
<route type="mix" sink="Wired Headphones" sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
<route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
<route type="mix" sink="Telephony Tx" sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic, voice_tx"/>
<route type="mix" sink="voice_rx" sources="Telephony Rx"/>
</routes>
</module>
<!-- A2dp Input Audio HAL -->
<xi:include href="a2dp_in_audio_policy_configuration_7_0.xml"/>
<!-- Usb Audio HAL -->
<xi:include href="usb_audio_policy_configuration.xml"/>
<!-- Remote Submix Audio HAL -->
<xi:include href="r_submix_audio_policy_configuration.xml"/>
<!-- Bluetooth Audio HAL -->
<xi:include href="bluetooth_audio_policy_configuration_7_0.xml"/>
<!-- MSD Audio HAL (optional) -->
<xi:include href="msd_audio_policy_configuration_7_0.xml"/>
</modules>
<!-- End of Modules section -->
<!-- Volume section:
IMPORTANT NOTE: Volume tables have been moved to engine configuration.
Keep it here for legacy.
Engine will fallback on these files if none are provided by engine.
-->
<xi:include href="audio_policy_volumes.xml"/>
<xi:include href="default_volume_tables.xml"/>
<!-- End of Volume section -->
<!-- Surround Sound configuration -->
<xi:include href="surround_sound_configuration_5_0.xml"/>
<!-- End of Surround Sound configuration -->
</audioPolicyConfiguration>
device/generic/goldfish/audio/policy/primary_audio_policy_configuration.xml 文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Default Primary Audio HAL Module Audio Policy Configuration include file -->
<module name="primary" halVersion="3.0">
<attachedDevices>
<item>Speaker</item>
<item>Built-In Mic</item>
<item>Telephony Tx</item>
<item>Telephony Rx</item>
<item>FM Tuner</item>
</attachedDevices>
<defaultOutputDevice>Speaker</defaultOutputDevice>
<mixPorts>
<mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 16000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="primary input" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 16000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>
<mixPort name="telephony_tx" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 16000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="telephony_rx" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 16000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>
<mixPort name="fm_tuner" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 16000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
</devicePort>
<devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
</devicePort>
<devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
</devicePort>
<devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
</devicePort>
<devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">
</devicePort>
</devicePorts>
<routes>
<route type="mix" sink="Speaker" sources="primary output"/>
<route type="mix" sink="primary input" sources="Built-In Mic"/>
<route type="mix" sink="telephony_rx" sources="Telephony Rx"/>
<route type="mix" sink="Telephony Tx" sources="telephony_tx"/>
<route type="mix" sink="fm_tuner" sources="FM Tuner"/>
</routes>
</module>
FM Tuner 是收音机吗?
FM Tuner 是收音机接收调频广播信号的核心部件,但收音机是一个更为完整的设备。除了包含 FM Tuner 来实现信号的调谐接收外,还包括音频放大器、扬声器或耳机接口等其他组件,以将接收到的电信号转换为声音,让用户能够听到广播内容。所以,单纯的 FM Tuner 只是收音机实现收音功能的一个关键环节,不能直接等同于收音机。
frameworks/av/services/audiopolicy/config/a2dp_in_audio_policy_configuration_7_0.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- A2dp Audio HAL Audio Policy Configuration file -->
<module name="a2dp" halVersion="2.0">
<mixPorts>
<mixPort name="a2dp output" role="source"/>
<mixPort name="a2dp input" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
<devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
<devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
<devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
</devicePort>
</devicePorts>
<routes>
<route type="mix" sink="BT A2DP Out" sources="a2dp output"/>
<route type="mix" sink="BT A2DP Headphones" sources="a2dp output"/>
<route type="mix" sink="BT A2DP Speaker" sources="a2dp output"/>
<route type="mix" sink="a2dp input" sources="BT A2DP In"/>
</routes>
</module>
frameworks/av/services/audiopolicy/config/surround_sound_configuration_5_0.xml
// TV 环绕声
<surroundSound>
<!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
There must be a corresponding Java ENCODING_... contant defined in AudioFormat.java,
and a display name defined in AudioFormat.toDisplayName. For the formats that don't
need a dedicated Surrond Settings dialog entry, a subformats list has to be used. -->
<formats>
<format name="AUDIO_FORMAT_AC3" />
<format name="AUDIO_FORMAT_E_AC3" />
<format name="AUDIO_FORMAT_E_AC3_JOC" />
<format name="AUDIO_FORMAT_DOLBY_TRUEHD" />
<format name="AUDIO_FORMAT_DTS" />
<format name="AUDIO_FORMAT_DTS_HD" />
<format name="AUDIO_FORMAT_AAC_LC" subformats="AUDIO_FORMAT_AAC_HE_V1 AUDIO_FORMAT_AAC_HE_V2 AUDIO_FORMAT_AAC_ELD AUDIO_FORMAT_AAC_XHE" />
<format name="AUDIO_FORMAT_AC4" />
</formats>
</surroundSound>
modules标签-Xml结构
modules: primary、a2dp、bluetooth、msd、usb、stub、r_submix、hearing_aid
module(primary)
module(a2dp)
module(bluetooth)
module(msd)
module(usb)
module(stub)
module(r_submix)
module(hearing_aid)
module:
attachedDevices
defaultOutputDevice
mixPorts: mixPort
devicePorts: devicePort
routes: route
mixPort: name、role、flags="AUDIO_OUTPUT_FLAG_PRIMARY"、<profile>
devicePort: tagName、type、role、<profile>、<gains>
route: type、sink、sources
<profile name="" format="" samplingRates="" channelMasks=""/>
<gains>
<gain name="gain_1"
mode="AUDIO_GAIN_MODE_JOINT"
minValueMB="-8400"
maxValueMB="4000"
defaultValueMB="0"
stepValueMB="100"/>
</gains>
modules标签-封装类结构: HwModule frameworks/av/services/audiopolicy/common/managerdefinitions/include/HwModule.h
class IOProfile;
class InputProfile;
class OutputProfile;
typedef Vector<sp<IOProfile> > InputProfileCollection;
typedef Vector<sp<IOProfile> > OutputProfileCollection;
typedef Vector<sp<IOProfile> > IOProfileCollection;
class HwModule : public RefBase
{
public:
explicit HwModule(const char *name, uint32_t halVersionMajor = 0, uint32_t halVersionMinor = 0);
~HwModule();
const char *getName() const {
return mName.string();
}
const DeviceVector &getDeclaredDevices() const {
return mDeclaredDevices;
}
void setDeclaredDevices(const DeviceVector &devices);
DeviceVector getAllDevices() const {
DeviceVector devices = mDeclaredDevices;
devices.merge(mDynamicDevices);
return devices;
}
std::string getTagForDevice(audio_devices_t device, const String8 &address = String8(), audio_format_t codec = AUDIO_FORMAT_DEFAULT);
void addDynamicDevice(const sp<DeviceDescriptor> &device) {
device->setDynamic();
mDynamicDevices.add(device);
}
bool removeDynamicDevice(const sp<DeviceDescriptor> &device) {
return mDynamicDevices.remove(device) >= 0;
}
DeviceVector getDynamicDevices() const { return mDynamicDevices; }
const InputProfileCollection &getInputProfiles() const {
return mInputProfiles;
}
const OutputProfileCollection &getOutputProfiles() const {
return mOutputProfiles;
}
void setProfiles(const IOProfileCollection &profiles);
void setHalVersion(uint32_t major, uint32_t minor) {
mHalVersion = (major << 8) | (minor & 0xff);
}
uint32_t getHalVersionMajor() const { return mHalVersion >> 8; }
uint32_t getHalVersionMinor() const { return mHalVersion & 0xff; }
sp<DeviceDescriptor> getRouteSinkDevice(const sp<AudioRoute> &route) const;
DeviceVector getRouteSourceDevices(const sp<AudioRoute> &route) const;
const AudioRouteVector& getRoutes() const {
return mRoutes;
}
void setRoutes(const AudioRouteVector &routes);
status_t addOutputProfile(const sp<IOProfile> &profile);
status_t addInputProfile(const sp<IOProfile> &profile);
status_t addProfile(const sp<IOProfile> &profile);
status_t addOutputProfile(const std::string& name, const audio_config_t *config, audio_devices_t device, const String8& address);
status_t removeOutputProfile(const std::string& name);
status_t addInputProfile(const std::string& name, const audio_config_t *config, audio_devices_t device, const String8& address);
status_t removeInputProfile(const std::string& name);
audio_module_handle_t getHandle() const {
return mHandle;
}
void setHandle(audio_module_handle_t handle);
sp<PolicyAudioPort> findPortByTagName(const std::string &tagName) const {
return findByTagName(mPorts, tagName);
}
/**
* @brief supportsPatch checks if an audio patch between 2 ports beloging to this HwModule
* is supported by a HwModule.
* The ports and the route shall be declared in the audio_policy_configuration.xml file.
* @param srcPort (aka the source) to be considered
* @param dstPort (aka the sink) to be considered
* @return true if the HwModule supports the connection between the sink and the source, false otherwise
*/
bool supportsPatch(const sp<PolicyAudioPort> &srcPort, const sp<PolicyAudioPort> &dstPort) const;
// TODO remove from here (split serialization)
void dump(String8 *dst, int spaces) const;
// 下面是 HwModule.h 中定义的 HwModule 类的私有成员函数和变量
private:
void refreshSupportedDevices();
// Base name of the audio HW module: primary、a2dp、bluetooth、msd、usb、stub、r_submix、hearing_aid
const String8 mName;
audio_module_handle_t mHandle;
// Output profiles exposed by this module, 对应 <mixPorts> 下 <mixPort role="source"> 的 <profile> 标签列表
OutputProfileCollection mOutputProfiles;
// Input profiles exposed by this module, 对应 <mixPorts> 下 <mixPort role="sink"> 的 <profile> 标签列表
InputProfileCollection mInputProfiles;
// Audio HAL API version
uint32_t mHalVersion;
// Devices declared in audio_policy configuration file.
DeviceVector mDeclaredDevices;
// Devices that can be added/removed at runtime (e.g. rsbumix).
DeviceVector mDynamicDevices;
// <routes> 下的子标签 <route> 标签列表
AudioRouteVector mRoutes;
// <devicePorts> 下的子标签 <devicePort> 标签列表
PolicyAudioPortVector mPorts;
};
// 下面是 HwModuleCollection 类继承自 Vector<sp<HwModule>>, 是一个 Vector.
class HwModuleCollection : public Vector<sp<HwModule>>
{
public:
sp<HwModule> getModuleFromName(const char *name) const;
sp<HwModule> getModuleForDeviceType(audio_devices_t device, audio_format_t encodedFormat, std::string *tagName = nullptr) const;
sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device, audio_format_t encodedFormat) const;
DeviceVector getAvailableDevicesFromModuleName(const char *name, const DeviceVector &availableDevices) const;
sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t type, const char *address, const char *name, audio_format_t encodedFormat, bool allowToCreate = false, bool matchAddress = true) const;
sp<DeviceDescriptor> createDevice(const audio_devices_t type, const char *address, const char *name, const audio_format_t encodedFormat) const;
void cleanUpForDevice(const sp<DeviceDescriptor> &device);
void dump(String8 *dst) const;
};
Xml中标签解析后对应的类:
mixPort: name、role、flags="AUDIO_OUTPUT_FLAG_PRIMARY"、<profile>
devicePort: tagName、type、role、<profile>、<gains>
route: type、sink、sources
<profile name="" format="" samplingRates="" channelMasks=""/>
<gains>
<gain name="gain_1"
mode="AUDIO_GAIN_MODE_JOINT"
minValueMB="-8400"
maxValueMB="4000"
defaultValueMB="0"
stepValueMB="100"/>
</gains>
// AudioPort
class AudioPort : public virtual RefBase
{
public:
// AudioPort 类的构造函数
AudioPort(const std::string& name, audio_port_type_t type, audio_port_role_t role) : mName(name), mType(type), mRole(role) {}
virtual ~AudioPort() = default;
// AudioPort 类中定义的私有函数和变量
protected:
std::string mName;
audio_port_type_t mType;
audio_port_role_t mRole;
// AudioProfiles supported by this port (format, Rates, Channels)
AudioProfileVector mProfiles;
// Audio capabilities that are defined by hardware descriptors when the format is unrecognized by the platform, e.g. short audio descriptor in EDID for HDMI.
std::vector<media::audio::common::ExtraAudioDescriptor> mExtraAudioDescriptors;
union audio_io_flags mFlags = { .output = AUDIO_OUTPUT_FLAG_NONE };
};
// PolicyAudioPort
class PolicyAudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
{
public:
// PolicyAudioPort 类的构造函数
PolicyAudioPort() = default;
virtual ~PolicyAudioPort() = default;
virtual const std::string getTagName() const = 0;
bool equals(const sp<PolicyAudioPort> &right) const {
return right != 0 && getTagName() == right->getTagName();
}
virtual sp<AudioPort> asAudioPort() const = 0;
virtual void attach(const sp<HwModule>& module);
virtual void detach();
bool isAttached() { return mModule != 0; }
// Audio port IDs are in a different namespace than AudioFlinger unique IDs
static audio_port_handle_t getNextUniqueId();
// searches for an exact match
virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
// searches for a compatible match, currently implemented for input
// parameters are input|output, returned value is the best match.
status_t checkCompatibleAudioProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, audio_format_t &format) const
{
return checkCompatibleProfile(
asAudioPort()->getAudioProfiles(),
samplingRate, channelMask, format,
asAudioPort()->getType(),
asAudioPort()->getRole());
}
void pickAudioProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, audio_format_t &format) const;
static const audio_format_t sPcmFormatCompareTable[];
static int compareFormats(audio_format_t format1, audio_format_t format2);
// Used to select an audio HAL output stream with a sample format providing the
// less degradation for a given AudioTrack sample format.
static bool isBetterFormatMatch(audio_format_t newFormat, audio_format_t currentFormat, audio_format_t targetFormat);
static uint32_t formatDistance(audio_format_t format1, audio_format_t format2);
static const uint32_t kFormatDistanceMax = 4;
audio_module_handle_t getModuleHandle() const;
uint32_t getModuleVersionMajor() const;
const char *getModuleName() const;
sp<HwModule> getModule() const { return mModule; }
void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
const AudioRouteVector &getRoutes() const { return mRoutes; }
// PolicyAudioPort 类中定义的私有函数和变量
private:
void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelMaskSet &channelMasks) const;
void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;
// Audio HW module exposing this I/O stream
sp<HwModule> mModule;
// Routes involving this port
AudioRouteVector mRoutes;
};
class PolicyAudioPort;
using PolicyAudioPortVector = Vector<sp<PolicyAudioPort>>;
// IOProfile
class IOProfile : public AudioPort, public PolicyAudioPort
{
public:
// IOProfile 类的构造函数
IOProfile(const std::string &name, audio_port_role_t role) : AudioPort(name, AUDIO_PORT_TYPE_MIX, role), curOpenCount(0), curActiveCount(0) {}
virtual ~IOProfile() = default;
// For a Profile aka MixPort, tag name and name are equivalent.
virtual const std::string getTagName() const {
return getName();
}
virtual void addAudioProfile(const sp<AudioProfile> &profile) {
addAudioProfileAndSort(mProfiles, profile);
}
virtual sp<AudioPort> asAudioPort() const {
return static_cast<AudioPort*>(const_cast<IOProfile*>(this));
}
// FIXME: this is needed because shared MMAP stream clients use the same audio session.
// Once capture clients are tracked individually and not per session this can be removed
// MMAP no IRQ input streams do not have the default limitation of one active client
// max as they can be used in shared mode by the same application.
// NOTE: Please consider moving to AudioPort when addressing the FIXME
// NOTE: this works for explicit values set in audio_policy_configuration.xml because
// flags are parsed before maxActiveCount by the serializer.
void setFlags(uint32_t flags) override
{
AudioPort::setFlags(flags);
if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
maxActiveCount = 0;
}
}
/**
* @brief isCompatibleProfile: This method is used for input and direct output,
* and is not used for other output.
* Checks if the IO profile is compatible with specified parameters.
* For input, flags is interpreted as audio_input_flags_t.
* TODO: merge audio_output_flags_t and audio_input_flags_t.
*
* @param devices vector of devices to be checked for compatibility
* @param samplingRate to be checked for compatibility. Must be specified
* @param updatedSamplingRate if non-NULL, it is assigned the actual sample rate.
* @param format to be checked for compatibility. Must be specified
* @param updatedFormat if non-NULL, it is assigned the actual format
* @param channelMask to be checked for compatibility. Must be specified
* @param updatedChannelMask if non-NULL, it is assigned the actual channel mask
* @param flags to be checked for compatibility
* @param exactMatchRequiredForInputFlags true if exact match is required on flags
* @return true if the profile is compatible, false otherwise.
*/
bool isCompatibleProfile(const DeviceVector &devices,
uint32_t samplingRate,
uint32_t *updatedSamplingRate,
audio_format_t format,
audio_format_t *updatedFormat,
audio_channel_mask_t channelMask,
audio_channel_mask_t *updatedChannelMask,
// FIXME parameter type
uint32_t flags,
bool exactMatchRequiredForInputFlags = false) const;
void dump(String8 *dst, int spaces) const;
void log();
bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); }
bool supportsDeviceTypes(const DeviceTypeSet& deviceTypes) const
{
const bool areOutputDevices = Intersection(deviceTypes, getAudioDeviceInAllSet()).empty();
const bool devicesSupported = !mSupportedDevices.getDevicesFromTypes(deviceTypes).empty();
return devicesSupported && (!areOutputDevices || devicesSupportEncodedFormats(deviceTypes));
}
/**
* @brief getTag
* @param deviceTypes to be considered
* @return tagName of first matching device for the considered types, empty string otherwise.
*/
std::string getTag(const DeviceTypeSet& deviceTypes) const
{
if (supportsDeviceTypes(deviceTypes)) {
return mSupportedDevices.getDevicesFromTypes(deviceTypes).itemAt(0)->getTagName();
}
return {};
}
/**
* @brief supportsDevice
* @param device to be checked against
* forceCheckOnAddress if true, check on type and address whatever the type, otherwise
* the address enforcement is limited to "offical devices" that distinguishe on address
* @return true if the device is supported by type (for non bus / remote submix devices),
* true if the device is supported (both type and address) for bus / remote submix
* false otherwise
*/
bool supportsDevice(const sp<DeviceDescriptor> &device, bool forceCheckOnAddress = false) const
{
if (!device_distinguishes_on_address(device->type()) && !forceCheckOnAddress) {
return supportsDeviceTypes(DeviceTypeSet({device->type()}));
}
return mSupportedDevices.contains(device);
}
bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const
{
if (deviceTypes.empty()) {
return true; // required for getOffloadSupport() check
}
DeviceVector deviceList =
mSupportedDevices.getDevicesFromTypes(deviceTypes);
for (const auto& device : deviceList) {
if (device->hasCurrentEncodedFormat()) {
return true;
}
}
return false;
}
bool containsSingleDeviceSupportingEncodedFormats(const sp<DeviceDescriptor>& device) const;
void clearSupportedDevices() { mSupportedDevices.clear(); }
void addSupportedDevice(const sp<DeviceDescriptor> &device) {
mSupportedDevices.add(device);
}
void removeSupportedDevice(const sp<DeviceDescriptor> &device) {
ssize_t ret = mSupportedDevices.indexOf(device);
if (ret >= 0 && !mSupportedDevices.itemAt(ret)->isDynamic()) {
// devices equality checks only type, address, name and format
// Prevents from removing non dynamically added devices
return;
}
mSupportedDevices.remove(device);
}
void setSupportedDevices(const DeviceVector &devices) {
mSupportedDevices = devices;
}
const DeviceVector &getSupportedDevices() const { return mSupportedDevices; }
bool canOpenNewIo() {
if (maxOpenCount == 0 || curOpenCount < maxOpenCount) {
return true;
}
return false;
}
bool canStartNewIo() {
if (maxActiveCount == 0 || curActiveCount < maxActiveCount) {
return true;
}
return false;
}
// Number of streams currently opened for this profile.
uint32_t curOpenCount;
// Number of streams currently active for this profile. This is not the number of active clients(AudioTrack or AudioRecord) but the number of active HAL streams.
uint32_t curActiveCount;
private:
// supported devices: this input/output can be routed from/to
DeviceVector mSupportedDevices;
};
// InputProfile
class InputProfile : public IOProfile {
public:
explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
};
// OutputProfile
class OutputProfile : public IOProfile {
public:
explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
};
class DeviceDescriptor : public DeviceDescriptorBase, public PolicyAudioPort, public PolicyAudioPortConfig
{
public:
// Note that empty name refers by convention to a generic device.
explicit DeviceDescriptor(audio_devices_t type);
DeviceDescriptor(audio_devices_t type, const std::string &tagName, const FormatVector &encodedFormats = FormatVector{});
DeviceDescriptor(audio_devices_t type, const std::string &tagName, const std::string &address, const FormatVector &encodedFormats = FormatVector{});
DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr, const std::string &tagName = "", const FormatVector &encodedFormats = FormatVector{});
virtual ~DeviceDescriptor() = default;
virtual const std::string getTagName() const { return mTagName; }
// PolicyAudioPort
virtual sp<AudioPort> asAudioPort() const {
return static_cast<AudioPort*>(const_cast<DeviceDescriptor*>(this));
}
virtual sp<AudioPort> asAudioPort() const {
return static_cast<AudioPort*>(const_cast<DeviceDescriptor*>(this));
}
virtual void attach(const sp<HwModule>& module);
virtual void detach();
private:
std::string mTagName; // Unique human readable identifier for a device port found in conf file.
audio_format_t mCurrentEncodedFormat;
bool mIsDynamic = false;
const std::string mDeclaredAddress; // Original device address
};
class IOProfile;
class InputProfile;
class OutputProfile;
typedef Vector<sp<IOProfile> > InputProfileCollection;
typedef Vector<sp<IOProfile> > OutputProfileCollection;
typedef Vector<sp<IOProfile> > IOProfileCollection;
class DeviceDescriptor : public DeviceDescriptorBase, public PolicyAudioPort, public PolicyAudioPortConfig
class DeviceVector : public SortedVector<sp<DeviceDescriptor>>
class AudioRoute : public virtual RefBase
class AudioRoute;
using AudioRouteVector = Vector<sp<AudioRoute>>;
frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
class AudioPolicyConfig
{
public:
// 构造函数, 构造并赋值
AudioPolicyConfig(HwModuleCollection &hwModules,
DeviceVector &outputDevices,
DeviceVector &inputDevices,
sp<DeviceDescriptor> &defaultOutputDevice)
: mHwModules(hwModules),
mOutputDevices(outputDevices),
mInputDevices(inputDevices),
mDefaultOutputDevice(defaultOutputDevice) {
clear();
}
void clear() {
mSource = {};
mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
mHwModules.clear();
mOutputDevices.clear();
mInputDevices.clear();
mDefaultOutputDevice.clear();
mIsSpeakerDrcEnabled = false;
mIsCallScreenModeSupported = false;
mSurroundFormats.clear();
}
const std::string& getSource() const {
return mSource;
}
void setSource(const std::string& file) {
mSource = file;
}
const std::string& getEngineLibraryNameSuffix() const {
return mEngineLibraryNameSuffix;
}
void setEngineLibraryNameSuffix(const std::string& suffix) {
mEngineLibraryNameSuffix = suffix;
}
void setHwModules(const HwModuleCollection &hwModules) {
mHwModules = hwModules;
}
void addDevice(const sp<DeviceDescriptor> &device) {
if (audio_is_output_device(device->type())) {
mOutputDevices.add(device);
} else if (audio_is_input_device(device->type())) {
mInputDevices.add(device);
}
}
void addInputDevices(const DeviceVector &inputDevices) {
mInputDevices.add(inputDevices);
}
void addOutputDevices(const DeviceVector &outputDevices) {
mOutputDevices.add(outputDevices);
}
bool isSpeakerDrcEnabled() const {
return mIsSpeakerDrcEnabled;
}
void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled){
mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
}
bool isCallScreenModeSupported() const {
return mIsCallScreenModeSupported;
}
void setCallScreenModeSupported(bool isCallScreenModeSupported) {
mIsCallScreenModeSupported = isCallScreenModeSupported;
}
// 获取所有module
const HwModuleCollection getHwModules() const {
return mHwModules;
}
// 获取所有输入设备
const DeviceVector &getInputDevices() const {
return mInputDevices;
}
// 获取所有输出设备
const DeviceVector &getOutputDevices() const {
return mOutputDevices;
}
// 设置默认输出设备
void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice) {
mDefaultOutputDevice = defaultDevice;
}
// 获取默认输出设备
const sp<DeviceDescriptor> &getDefaultOutputDevice() const {
return mDefaultOutputDevice;
}
// 设置默认值 AudioPolicyConfig
void setDefault(void)
{
mSource = "AudioPolicyConfig::setDefault";
mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
// 指定默认输出设备-扬声器
mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
// 指定默认输入设备-麦克风
sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
sp<AudioProfile> micProfile = new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
defaultInputDevice->addAudioProfile(micProfile);
// 添加到输出设备列表
mOutputDevices.add(mDefaultOutputDevice);
// 添加到输入设备列表
mInputDevices.add(defaultInputDevice);
// 创建默认的音频硬件模块
sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
// 添加到音频硬件模块列表
mHwModules.add(module);
/**
函数调用 module->addOutputProfile(outProfile) 等价于向音频硬件模块添加如下输出参数配置
<mixPorts>
<mixPort name="primary" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
</mixPorts>
*/
sp<OutputProfile> outProfile = new OutputProfile("primary");
outProfile->addAudioProfile(new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
outProfile->addSupportedDevice(mDefaultOutputDevice);
outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
module->addOutputProfile(outProfile);
/**
函数调用 module->addInputProfile(inProfile) 等价于向音频硬件模块添加如下输入参数配置
<mixPorts>
<mixPort name="primary" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
</mixPort>
</mixPorts>
*/
sp<InputProfile> inProfile = new InputProfile("primary");
inProfile->addAudioProfile(micProfile);
inProfile->addSupportedDevice(defaultInputDevice);
module->addInputProfile(inProfile);
setDefaultSurroundFormats();
}
// Surround formats, with an optional list of subformats that are equivalent from users' POV.
using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
const SurroundFormats &getSurroundFormats() const {
return mSurroundFormats;
}
void setSurroundFormats(const SurroundFormats &surroundFormats) {
mSurroundFormats = surroundFormats;
}
void setDefaultSurroundFormats() {
mSurroundFormats = {
{AUDIO_FORMAT_AC3, {}},
{AUDIO_FORMAT_E_AC3, {}},
{AUDIO_FORMAT_DTS, {}},
{AUDIO_FORMAT_DTS_HD, {}},
{AUDIO_FORMAT_AAC_LC, { AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD, AUDIO_FORMAT_AAC_XHE}},
{AUDIO_FORMAT_DOLBY_TRUEHD, {}},
{AUDIO_FORMAT_E_AC3_JOC, {}},
{AUDIO_FORMAT_AC4, {}}};
}
// 下面是 AudioPolicyConfig.h 中定义的 AudioPolicyConfig 类的私有成员函数和变量
private:
static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
std::string mSource;
std::string mEngineLibraryNameSuffix;
// Collection of Module, with Profiles, i.e. Mix Ports.
HwModuleCollection &mHwModules;
// <devicePort type="AUDIO_DEVICE_OUT_xxxx"> 的列表
DeviceVector &mOutputDevices;
// <devicePort type="AUDIO_DEVICE_IN_xxxx"> 的列表
DeviceVector &mInputDevices;
// <defaultOutputDevice>Speaker</defaultOutputDevice> 指定的默认输出设备
sp<DeviceDescriptor> &mDefaultOutputDevice;
bool mIsSpeakerDrcEnabled;
bool mIsCallScreenModeSupported;
SurroundFormats mSurroundFormats;
};
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.h
// AudioPolicyManager implements audio policy manager behavior common to all platforms.
class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManagerObserver {
public:
explicit AudioPolicyManager(AudioPolicyClientInterface *clientInterface);
virtual ~AudioPolicyManager();
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
// ----------------------------------------------------------------------------
// AudioPolicyManager
// ----------------------------------------------------------------------------
uint32_t AudioPolicyManager::nextAudioPortGeneration()
{
return mAudioPortGeneration++;
}
// 开始解析
static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file(); !audioPolicyXmlConfigFile.empty()) {
status_t ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile.c_str(), &config);
if (ret == NO_ERROR) {
config.setSource(audioPolicyXmlConfigFile);
}
return ret;
}
return BAD_VALUE;
}
// 构造函数
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface, bool /*forTesting*/) :
mUidCached(AID_AUDIOSERVER), // no need to call getuid(), there's only one of us running.
mpClientInterface(clientInterface),
mLimitRingtoneVolume(false),
mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
// 此处是真正创建 AudioPolicyConfig 对象的地方.
mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
mMusicEffectOutput(AUDIO_IO_HANDLE_NONE) {}
// 构造函数
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) : AudioPolicyManager(clientInterface, false) {
loadConfig();
}
// 解析 audio_policy_configuration.xml 文件, 如果解析失败则调用setDefault()设置默认值
void AudioPolicyManager::loadConfig() {
if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
getConfig().setDefault();
}
}
// initialize
status_t AudioPolicyManager::initialize() {
{
auto engLib = EngineLibrary::load("libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
if (!engLib) {
ALOGE("%s: Failed to load the engine library", __FUNCTION__);
return NO_INIT;
}
mEngine = engLib->createEngine();
if (mEngine == nullptr) {
ALOGE("%s: Failed to instantiate the APM engine", __FUNCTION__);
return NO_INIT;
}
}
mEngine->setObserver(this);
status_t status = mEngine->initCheck();
if (status != NO_ERROR) {
LOG_FATAL("Policy engine not initialized(err=%d)", status);
return status;
}
mEngine->updateDeviceSelectionCache();
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
/// After parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices; open all output streams needed to access attached devices
onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
// make sure default device is reachable
if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable", mDefaultOutputDevice->toString().c_str());
status = NO_INIT;
}
// If microphones address is empty, set it according to device type
for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
if (mAvailableInputDevices[i]->address().empty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
} else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
}
}
}
ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
// Silence ALOGV statements
property_set("log.tag." LOG_TAG, "D");
updateDevicesAndOutputs();
return status;
}
AudioPolicyManager::~AudioPolicyManager() {
for (size_t i = 0; i < mOutputs.size(); i++) {
mOutputs.valueAt(i)->close();
}
for (size_t i = 0; i < mInputs.size(); i++) {
mInputs.valueAt(i)->close();
}
mAvailableOutputDevices.clear();
mAvailableInputDevices.clear();
mOutputs.clear();
mInputs.clear();
mHwModules.clear();
mHwModulesAll.clear();
mManualSurroundFormats.clear();
}
frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
class PolicySerializer {
public:
status_t deserialize(const char *configFile, AudioPolicyConfig *config, bool ignoreVendorExtensions = false);
template <class Trait>
status_t deserializeCollection(const xmlNode *cur, typename Trait::Collection *collection, typename Trait::PtrSerializingCtx serializingContext);
template <class Trait>
std::variant<status_t, typename Trait::Element> deserialize(const xmlNode *cur, typename Trait::PtrSerializingCtx serializingContext);
// PolicySerializer 类中定义的私有成员函数和变量
private:
static constexpr const char *rootName = "audioPolicyConfiguration";
static constexpr const char *versionAttribute = "version";
typedef AudioPolicyConfig Element;
bool mIgnoreVendorExtensions = false;
std::string mChannelMasksSeparator = ",";
std::string mSamplingRatesSeparator = ",";
std::string mFlagsSeparator = "|";
// Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional)
};
// deserialize
status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config, bool ignoreVendorExtensions)
{
mIgnoreVendorExtensions = ignoreVendorExtensions;
// 读取 Xml 文件
auto doc = make_xmlUnique(xmlParseFile(configFile));
if (doc == nullptr) {
ALOGE("%s: Could not parse %s document.", __func__, configFile);
return BAD_VALUE;
}
// 获取 Xml 的根结点
xmlNodePtr root = xmlDocGetRootElement(doc.get());
if (root == NULL) {
ALOGE("%s: Could not parse %s document: empty.", __func__, configFile);
return BAD_VALUE;
}
if (xmlXIncludeProcess(doc.get()) < 0) {
ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile);
}
if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName))) {
ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName, reinterpret_cast<const char*>(root->name));
return BAD_VALUE;
}
// 获取根结点的 "version" 属性值
std::string version = getXmlAttribute(root, versionAttribute);
if (version.empty()) {
ALOGE("%s: No version found in root node %s", __func__, rootName);
return BAD_VALUE;
}
if (version == "7.0" || version == "7.1") {
mChannelMasksSeparator = mSamplingRatesSeparator = mFlagsSeparator = " ";
} else if (version != "1.0") {
ALOGE("%s: Version does not match; expected "1.0", "7.0", or "7.1" got "%s"", __func__, version.c_str());
return BAD_VALUE;
}
// Let's deserialize children, 从 root 中解析 Modules 标签 <modules>
ModuleTraits::Collection modules;
status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);
if (status != NO_ERROR) {
return status;
}
config->setHwModules(modules);
// 从 root 中解析 Global Configuration 标签 <globalConfiguration>
deserialize<GlobalConfigTraits>(root, config);
// 从 root 中解析 Surround configuration 标签 <surroundSound>
deserialize<SurroundSoundTraits>(root, config);
return android::OK;
}
// deserializeAudioPolicyFile
status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
{
PolicySerializer serializer;
status_t status = serializer.deserialize(fileName, config);
if (status != OK) config->clear();
return status;
}
AudioGainTraits::Element gain = new AudioGain(index++, true);
AudioProfileTraits::Element profile = new AudioProfile(
formatFromString(format, gDynamicFormat),
channelMasksFromString(channels, mChannelMasksSeparator.c_str()),
samplingRatesFromString(samplingRates,
mSamplingRatesSeparator.c_str())
);
MixPortTraits::Element mixPort = new IOProfile(name, portRole);
RouteTraits::Element route = new AudioRoute(routeType);
ModuleTraits::Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
template<typename E, typename C>
struct AndroidCollectionTraits {
typedef sp<E> Element;
typedef C Collection;
typedef void* PtrSerializingCtx;
static status_t addElementToCollection(const Element &element, Collection *collection) {
return collection->add(element) >= 0 ? NO_ERROR : BAD_VALUE;
}
};
struct ModuleTraits : public AndroidCollectionTraits<HwModule, HwModuleCollection>
{
static constexpr const char *tag = "module";
static constexpr const char *collectionTag = "modules";
static constexpr const char *childAttachedDevicesTag = "attachedDevices";
static constexpr const char *childAttachedDeviceTag = "item";
static constexpr const char *childDefaultOutputDeviceTag = "defaultOutputDevice";
struct Attributes
{
static constexpr const char *name = "name";
static constexpr const char *version = "halVersion";
};
typedef AudioPolicyConfig *PtrSerializingCtx;
// Children: mixPortTraits, devicePortTraits, and routeTraits
// Need to call deserialize on each child
};
template<>
std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx)
{
using Attributes = ModuleTraits::Attributes;
auto& tag = ModuleTraits::tag;
auto& childAttachedDevicesTag = ModuleTraits::childAttachedDevicesTag;
auto& childAttachedDeviceTag = ModuleTraits::childAttachedDeviceTag;
auto& childDefaultOutputDeviceTag = ModuleTraits::childDefaultOutputDeviceTag;
// 获取<module>标签的 name 属性值: <module name="primary" halVersion="3.0">
std::string name = getXmlAttribute(cur, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::name);
return BAD_VALUE;
}
// 获取<module>标签的 halVersion 属性值: <module name="primary" halVersion="3.0">
uint32_t versionMajor = 0, versionMinor = 0;
std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
if (!versionLiteral.empty()) {
sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor);
ALOGV("%s: mHalVersion = major %u minor %u", __func__, versionMajor, versionMajor);
}
ALOGV("%s: %s %s=%s", __func__, ModuleTraits::tag, Attributes::name, name.c_str());
// 创建 HwModule 对象
ModuleTraits::Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
// Deserialize children: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
// 解析 <mixPorts> 子标签 <mixPort> 的子标签 <profile>
MixPortTraits::Collection mixPorts;
status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);
if (status != NO_ERROR) {
return status;
}
// 调用 setProfiles 设给 HwModule 对象
module->setProfiles(mixPorts);
DevicePortTraits::Collection devicePorts;
status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL);
if (status != NO_ERROR) {
return status;
}
module->setDeclaredDevices(devicePorts);
RouteTraits::Collection routes;
status = deserializeCollection<RouteTraits>(cur, &routes, module.get());
if (status != NO_ERROR) {
return status;
}
module->setRoutes(routes);
for (const xmlNode *children = cur->xmlChildrenNode; children != NULL;
children = children->next) {
if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) {
ALOGV("%s: %s %s found", __func__, tag, childAttachedDevicesTag);
for (const xmlNode *child = children->xmlChildrenNode; child != NULL; child = child->next) {
if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) {
auto attachedDevice = make_xmlUnique(xmlNodeListGetString(child->doc, child->xmlChildrenNode, 1));
if (attachedDevice != nullptr) {
ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag, reinterpret_cast<const char*>(attachedDevice.get()));
sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(std::string(reinterpret_cast<const char*>(attachedDevice.get())));
if (device == nullptr && mIgnoreVendorExtensions) {
ALOGW("Skipped attached device "%s" because it likely uses a vendor""extension type", reinterpret_cast<const char*>(attachedDevice.get()));
continue;
}
ctx->addDevice(device);
}
}
}
}
if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) {
auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString(children->doc, children->xmlChildrenNode, 1));
if (defaultOutputDevice != nullptr) {
ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag, reinterpret_cast<const char*>(defaultOutputDevice.get()));
sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
ctx->setDefaultOutputDevice(device);
ALOGV("%s: default is %08x", __func__, ctx->getDefaultOutputDevice()->type());
}
}
}
}
return module;
}
frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
文件内容说明:
namespace android {
namespace {
using utilities::convertTo;
/// maybeVendorExtension
static inline bool maybeVendorExtension(const std::string& s) {
// Only checks whether the string starts with the "vendor prefix".
static const std::string vendorPrefix = "VX_";
return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
}
/// 模版结构体 AndroidCollectionTraits
template<typename E, typename C>
struct AndroidCollectionTraits {
typedef sp<E> Element;
typedef C Collection;
typedef void* PtrSerializingCtx;
static status_t addElementToCollection(const Element &element, Collection *collection) {
return collection->add(element) >= 0 ? NO_ERROR : BAD_VALUE;
}
};
/// 模版结构体 StdCollectionTraits
template<typename C>
struct StdCollectionTraits {
typedef C Collection;
typedef typename C::value_type Element;
typedef void* PtrSerializingCtx;
static status_t addElementToCollection(const Element &element, Collection *collection) {
auto pair = collection->insert(element);
return pair.second ? NO_ERROR : BAD_VALUE;
}
};
/// AudioGainTraits 定义标签 <gains> 及子标签 <gain>
struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGains>
{
static constexpr const char *tag = "gain";
static constexpr const char *collectionTag = "gains";
struct Attributes
{
/** gain modes supported, e.g. AUDIO_GAIN_MODE_CHANNELS. */
static constexpr const char *mode = "mode";
/** controlled channels, needed if mode AUDIO_GAIN_MODE_CHANNELS. */
static constexpr const char *channelMask = "channel_mask";
static constexpr const char *minValueMB = "minValueMB"; /**< min value in millibel. */
static constexpr const char *maxValueMB = "maxValueMB"; /**< max value in millibel. */
/** default value in millibel. */
static constexpr const char *defaultValueMB = "defaultValueMB";
static constexpr const char *stepValueMB = "stepValueMB"; /**< step value in millibel. */
/** needed if mode AUDIO_GAIN_MODE_RAMP. */
static constexpr const char *minRampMs = "minRampMs";
/** needed if mode AUDIO_GAIN_MODE_RAMP. */
static constexpr const char *maxRampMs = "maxRampMs";
/** needed to allow use setPortGain instead of setStreamVolume. */
static constexpr const char *useForVolume = "useForVolume";
};
// No children
};
/// AudioProfileTraits 定义标签 <profiles> 及子标签 <profile>
// A profile section contains a name, one audio format and the list of supported sampling rates and channel masks for this format
struct AudioProfileTraits : public AndroidCollectionTraits<AudioProfile, AudioProfileVector>
{
static constexpr const char *tag = "profile";
static constexpr const char *collectionTag = "profiles";
struct Attributes
{
static constexpr const char *samplingRates = "samplingRates";
static constexpr const char *format = "format";
static constexpr const char *channelMasks = "channelMasks";
};
};
/// MixPortTraits 定义标签 <mixPorts> 及子标签 <mixPort>
struct MixPortTraits : public AndroidCollectionTraits<IOProfile, IOProfileCollection>
{
static constexpr const char *tag = "mixPort";
static constexpr const char *collectionTag = "mixPorts";
struct Attributes
{
static constexpr const char *name = "name";
static constexpr const char *role = "role";
// <attribute role source value>.
static constexpr const char *roleSource = "source";
static constexpr const char *flags = "flags";
static constexpr const char *maxOpenCount = "maxOpenCount";
static constexpr const char *maxActiveCount = "maxActiveCount";
static constexpr const char *recommendedMuteDurationMs = "recommendedMuteDurationMs";
};
// Children: GainTraits
};
/// DevicePortTraits 定义标签 <devicePorts> 及子标签 <devicePort>
struct DevicePortTraits : public AndroidCollectionTraits<DeviceDescriptor, DeviceVector>
{
static constexpr const char *tag = "devicePort";
static constexpr const char *collectionTag = "devicePorts";
struct Attributes
{
/** <device tag name>: any string without space. */
static constexpr const char *tagName = "tagName";
/**< <device type>. */
static constexpr const char *type = "type";
/**< <device role: sink or source>. */
static constexpr const char *role = "role";
/**< <attribute role source value>. */
static constexpr const char *roleSource = "source";
/** optional: device address, char string less than 64. */
static constexpr const char *address = "address";
/** optional: the list of encoded audio formats that are known to be supported. */
static constexpr const char *encodedFormats = "encodedFormats";
};
// Children: GainTraits (optional)
};
/// RouteTraits 定义标签 <routes> 及子标签 <route>
struct RouteTraits : public AndroidCollectionTraits<AudioRoute, AudioRouteVector>
{
static constexpr const char *tag = "route";
static constexpr const char *collectionTag = "routes";
struct Attributes
{
/**< <attribute role source value>. */
static constexpr const char *type = "type";
/**< type attribute mix value. */
static constexpr const char *typeMix = "mix";
/**< <sink: involved in this route>. */
static constexpr const char *sink = "sink";
/** sources: all source that can be involved in this route. */
static constexpr const char *sources = "sources";
};
typedef HwModule *PtrSerializingCtx;
};
/// ModuleTraits 定义标签 <modules> 及子标签 <module>
struct ModuleTraits : public AndroidCollectionTraits<HwModule, HwModuleCollection>
{
static constexpr const char *tag = "module";
static constexpr const char *collectionTag = "modules";
static constexpr const char *childAttachedDevicesTag = "attachedDevices";
static constexpr const char *childAttachedDeviceTag = "item";
static constexpr const char *childDefaultOutputDeviceTag = "defaultOutputDevice";
struct Attributes
{
static constexpr const char *name = "name";
static constexpr const char *version = "halVersion";
};
typedef AudioPolicyConfig *PtrSerializingCtx;
// Children: mixPortTraits, devicePortTraits, and routeTraits
// Need to call deserialize on each child
};
/// GlobalConfigTraits 定义标签 <globalConfiguration>
struct GlobalConfigTraits
{
typedef std::monostate Element;
static constexpr const char *tag = "globalConfiguration";
struct Attributes
{
static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled";
static constexpr const char *callScreenModeSupported= "call_screen_mode_supported";
static constexpr const char *engineLibrarySuffix = "engine_library";
};
typedef AudioPolicyConfig *PtrSerializingCtx;
};
/// SurroundSoundTraits 定义标签 <surroundSound>
struct SurroundSoundTraits
{
typedef std::monostate Element;
static constexpr const char *tag = "surroundSound";
typedef AudioPolicyConfig *PtrSerializingCtx;
// Children: SurroundSoundFormatTraits
};
/// SurroundSoundFormatTraits 定义标签 <formats> 及子标签 <format>
struct SurroundSoundFormatTraits : public StdCollectionTraits<AudioPolicyConfig::SurroundFormats>
{
static constexpr const char *tag = "format";
static constexpr const char *collectionTag = "formats";
struct Attributes
{
static constexpr const char *name = "name";
static constexpr const char *subformats = "subformats";
};
};
/// PolicySerializer 类定义
class PolicySerializer
{
public:
status_t deserialize(const char *configFile, AudioPolicyConfig *config, bool ignoreVendorExtensions = false);
template <class Trait>
status_t deserializeCollection(const xmlNode *cur, typename Trait::Collection *collection, typename Trait::PtrSerializingCtx serializingContext);
template <class Trait>
std::variant<status_t, typename Trait::Element> deserialize(const xmlNode *cur, typename Trait::PtrSerializingCtx serializingContext);
private:
static constexpr const char *rootName = "audioPolicyConfiguration";
static constexpr const char *versionAttribute = "version";
typedef AudioPolicyConfig Element;
bool mIgnoreVendorExtensions = false;
std::string mChannelMasksSeparator = ",";
std::string mSamplingRatesSeparator = ",";
std::string mFlagsSeparator = "|";
// Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional)
};
// Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
struct FreeDelete {
// NOTE: Deleting a const object is valid but free() takes a non-const pointer.
void operator()(const void* ptr) const {
free(const_cast<void*>(ptr));
}
};
// Alias for std::unique_ptr<> that uses the C function free() to delete objects.
template <typename T>
using UniqueCPtr = std::unique_ptr<T, FreeDelete>;
template <class T>
constexpr void (*xmlDeleter)(T* t);
template <>
constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
template <>
constexpr auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
/** @return a unique_ptr with the correct deleter for the libxml2 object. */
template <class T>
constexpr auto make_xmlUnique(T *t) {
// Wrap deleter in lambda to enable empty base optimization
auto deleter = [](T *t) { xmlDeleter<T>(t); };
return std::unique_ptr<T, decltype(deleter)>{t, deleter};
}
/// 获取属性值 getXmlAttribute
std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
{
auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
if (xmlValue == nullptr) {
return "";
}
std::string value(reinterpret_cast<const char*>(xmlValue.get()));
return value;
}
/// 获取引用 getReference, 例如 <xi:include href="r_submix_audio_policy_configuration.xml"/>
template <class Trait>
const xmlNode* getReference(const xmlNode *cur, const std::string &refName)
{
for (; cur != NULL; cur = cur->next) {
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
for (const xmlNode *child = cur->children; child != NULL; child = child->next) {
if ((!xmlStrcmp(child->name,
reinterpret_cast<const xmlChar*>(Trait::referenceTag)))) {
std::string name = getXmlAttribute(child, Trait::Attributes::referenceName);
if (refName == name) {
return child;
}
}
}
}
}
return NULL;
}
// 模版函数 deserializeCollection
template <class Trait>
status_t PolicySerializer::deserializeCollection(const xmlNode *cur, typename Trait::Collection *collection, typename Trait::PtrSerializingCtx serializingContext)
{
for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
const xmlNode *child = NULL;
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {
child = cur->xmlChildrenNode;
} else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
child = cur;
}
for (; child != NULL; child = child->next) {
if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
auto maybeElement = deserialize<Trait>(child, serializingContext);
if (maybeElement.index() == 1) {
/// 调用 addElementToCollection 函数将对象添加到集合里面
status_t status = Trait::addElementToCollection(std::get<1>(maybeElement), collection);
if (status != NO_ERROR) {
ALOGE("%s: could not add element to %s collection", __func__, Trait::collectionTag);
return status;
}
} else if (mIgnoreVendorExtensions && std::get<status_t>(maybeElement) == NO_INIT) {
// Skip a vendor extension element.
} else {
return BAD_VALUE;
}
}
}
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
return NO_ERROR;
}
}
return NO_ERROR;
}
/// 模版函数-解析 AudioGainTraits
template<>
std::variant<status_t, AudioGainTraits::Element> PolicySerializer::deserialize<AudioGainTraits>(const xmlNode *cur, AudioGainTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = AudioGainTraits::Attributes;
static uint32_t index = 0;
/// 创建 AudioGain 对象
AudioGainTraits::Element gain = new AudioGain(index++, true);
std::string mode = getXmlAttribute(cur, Attributes::mode);
if (!mode.empty()) {
gain->setMode(GainModeConverter::maskFromString(mode, " "));
}
std::string channelsLiteral = getXmlAttribute(cur, Attributes::channelMask);
if (!channelsLiteral.empty()) {
gain->setChannelMask(channelMaskFromString(channelsLiteral));
}
std::string minValueMBLiteral = getXmlAttribute(cur, Attributes::minValueMB);
int32_t minValueMB;
if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
gain->setMinValueInMb(minValueMB);
}
std::string maxValueMBLiteral = getXmlAttribute(cur, Attributes::maxValueMB);
int32_t maxValueMB;
if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
gain->setMaxValueInMb(maxValueMB);
}
std::string defaultValueMBLiteral = getXmlAttribute(cur, Attributes::defaultValueMB);
int32_t defaultValueMB;
if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
gain->setDefaultValueInMb(defaultValueMB);
}
std::string stepValueMBLiteral = getXmlAttribute(cur, Attributes::stepValueMB);
uint32_t stepValueMB;
if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
gain->setStepValueInMb(stepValueMB);
}
std::string minRampMsLiteral = getXmlAttribute(cur, Attributes::minRampMs);
uint32_t minRampMs;
if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
gain->setMinRampInMs(minRampMs);
}
std::string maxRampMsLiteral = getXmlAttribute(cur, Attributes::maxRampMs);
uint32_t maxRampMs;
if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
gain->setMaxRampInMs(maxRampMs);
}
std::string useForVolumeLiteral = getXmlAttribute(cur, Attributes::useForVolume);
bool useForVolume = false;
if (!useForVolumeLiteral.empty() && convertTo(useForVolumeLiteral, useForVolume)) {
gain->setUseForVolume(useForVolume);
}
ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d UseForVolume: %d", __func__, gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(), gain->getMaxValueInMb(), useForVolume);
if (gain->getMode() != 0) {
return gain;
} else {
return BAD_VALUE;
}
}
/// 模版函数-解析 AudioProfileTraits
template<>
std::variant<status_t, AudioProfileTraits::Element>
PolicySerializer::deserialize<AudioProfileTraits>(const xmlNode *cur, AudioProfileTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = AudioProfileTraits::Attributes;
std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates);
std::string format = getXmlAttribute(cur, Attributes::format);
std::string channels = getXmlAttribute(cur, Attributes::channelMasks);
if (mIgnoreVendorExtensions && maybeVendorExtension(format)) {
ALOGI("%s: vendor extension format "%s" skipped", __func__, format.c_str());
return NO_INIT;
}
/// 创建 AudioProfile 对象
AudioProfileTraits::Element profile = new AudioProfile(
formatFromString(format, gDynamicFormat),
channelMasksFromString(channels, mChannelMasksSeparator.c_str()),
samplingRatesFromString(samplingRates,
mSamplingRatesSeparator.c_str())
);
profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
profile->setDynamicChannels(profile->getChannels().empty());
profile->setDynamicRate(profile->getSampleRates().empty());
return profile;
}
/// 模版函数-解析 MixPortTraits
template<>
std::variant<status_t, MixPortTraits::Element> PolicySerializer::deserialize<MixPortTraits>(const xmlNode *child, MixPortTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = MixPortTraits::Attributes;
std::string name = getXmlAttribute(child, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::name);
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, MixPortTraits::tag, Attributes::name, name.c_str());
std::string role = getXmlAttribute(child, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::role);
return BAD_VALUE;
}
ALOGV("%s: Role=%s", __func__, role.c_str());
audio_port_role_t portRole = (role == Attributes::roleSource) ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
// 创建 IOProfile 对象
MixPortTraits::Element mixPort = new IOProfile(name, portRole);
/// 调用 deserializeCollection 函数, 解析 AudioProfileTraits
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
if (status != NO_ERROR) {
return status;
}
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
}
/// The audio profiles are in order of listed in audio policy configuration file. Sort audio profiles accroding to the format.
sortAudioProfiles(profiles);
/// 将 profiles 设置给 mixPort 对象
mixPort->setAudioProfiles(profiles);
std::string flags = getXmlAttribute(child, Attributes::flags);
if (!flags.empty()) {
// Source role
if (portRole == AUDIO_PORT_ROLE_SOURCE) {
//TODO: b/193496180 use spatializer flag at audio HAL when available until then,
// use DEEP_BUFFER+FAST flag combo to indicate the spatializer output profile
uint32_t intFlags = OutputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str());
if (intFlags == (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
intFlags = AUDIO_OUTPUT_FLAG_SPATIALIZER;
}
mixPort->setFlags(intFlags);
} else {
// Sink role
mixPort->setFlags(InputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str()));
}
}
std::string maxOpenCount = getXmlAttribute(child, Attributes::maxOpenCount);
if (!maxOpenCount.empty()) {
convertTo(maxOpenCount, mixPort->maxOpenCount);
}
std::string maxActiveCount = getXmlAttribute(child, Attributes::maxActiveCount);
if (!maxActiveCount.empty()) {
convertTo(maxActiveCount, mixPort->maxActiveCount);
}
std::string recommendedmuteDurationMsLiteral = getXmlAttribute(child, Attributes::recommendedMuteDurationMs);
if (!recommendedmuteDurationMsLiteral.empty()) {
convertTo(recommendedmuteDurationMsLiteral, mixPort->recommendedMuteDurationMs);
}
/// 调用 deserializeCollection 函数, 解析 AudioGainTraits
// Deserialize children
AudioGainTraits::Collection gains;
status = deserializeCollection<AudioGainTraits>(child, &gains, NULL);
if (status != NO_ERROR) {
return status;
}
mixPort->setGains(gains);
return mixPort;
}
/**
Xml中的配置如下:
<devicePorts>
<!-- Output devices declaration, i.e. Sink DEVICE PORT -->
<devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
minValueMB="-8400"
maxValueMB="4000"
defaultValueMB="0"
stepValueMB="100"/>
</gains>
</devicePort>
</devicePorts>
*/
/// 模版函数-解析 DevicePortTraits
template<>
std::variant<status_t, DevicePortTraits::Element> PolicySerializer::deserialize<DevicePortTraits>(const xmlNode *cur, DevicePortTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = DevicePortTraits::Attributes;
auto& tag = DevicePortTraits::tag;
std::string name = getXmlAttribute(cur, Attributes::tagName);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::tagName);
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::tagName, name.c_str());
std::string typeName = getXmlAttribute(cur, Attributes::type);
if (typeName.empty()) {
ALOGE("%s: no type for %s", __func__, name.c_str());
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, typeName.c_str());
std::string role = getXmlAttribute(cur, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::role);
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::role, role.c_str());
audio_port_role_t portRole = (role == Attributes::roleSource) ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
if (mIgnoreVendorExtensions && maybeVendorExtension(typeName)) {
ALOGI("%s: vendor extension device type "%s" skipped", __func__, typeName.c_str());
return NO_INIT;
}
audio_devices_t type = AUDIO_DEVICE_NONE;
if (!DeviceConverter::fromString(typeName, type) || (!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) || (!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
ALOGW("%s: bad type %08x", __func__, type);
return BAD_VALUE;
}
std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats);
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str());
FormatVector encodedFormats;
if (!encodedFormatsLiteral.empty()) {
encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
}
std::string address = getXmlAttribute(cur, Attributes::address);
/// 创建 DeviceDescriptor 对象
DevicePortTraits::Element deviceDesc = new DeviceDescriptor(type, name, address, encodedFormats);
/// 调用 deserializeCollection 函数, 解析 AudioProfileTraits
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
if (status != NO_ERROR) {
return status;
}
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
}
/// 排序 The audio profiles are in order of listed in audio policy configuration file. Sort audio profiles accroding to the format.
sortAudioProfiles(profiles);
/// 调用 setAudioProfiles 将 profiles 设置给 deviceDesc 对象
deviceDesc->setAudioProfiles(profiles);
/// 调用 deserializeCollection 函数, 解析 AudioGainTraits
/// Deserialize AudioGain children
status = deserializeCollection<AudioGainTraits>(cur, &deviceDesc->mGains, NULL);
if (status != NO_ERROR) {
return status;
}
ALOGV("%s: adding device tag %s type %08x address %s", __func__, deviceDesc->getName().c_str(), type, deviceDesc->address().c_str());
return deviceDesc;
}
/// 模版函数-解析 RouteTraits
template<>
std::variant<status_t, RouteTraits::Element> PolicySerializer::deserialize<RouteTraits>(const xmlNode *cur, RouteTraits::PtrSerializingCtx ctx)
{
using Attributes = RouteTraits::Attributes;
std::string type = getXmlAttribute(cur, Attributes::type);
if (type.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::type);
return BAD_VALUE;
}
audio_route_type_t routeType = (type == Attributes::typeMix) ? AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
ALOGV("%s: %s %s=%s", __func__, RouteTraits::tag, Attributes::type, type.c_str());
/// 创建 AudioRoute 对象
RouteTraits::Element route = new AudioRoute(routeType);
/// 获取 sink 属性值
std::string sinkAttr = getXmlAttribute(cur, Attributes::sink);
if (sinkAttr.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::sink);
return BAD_VALUE;
}
/// Convert Sink name to port pointer
/// <devicePort tagName="Earpiece" ...>
/// <mixPort name="primary input" role="sink">
/// <mixPort name="voice_rx" role="sink">
/// <route type="mix" sink="primary input" ....../>
/// <route type="mix" sink="Earpiece" .../>
/// 调用 findPortByTagName 函数的作用是查找 mixPort.name 或 devicePort.tagName 等于 route.sink 的 mixPort 或 devicePort, 即 PolicyAudioPort 对象, 且 sink 对象只有一个.
sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
if (sink == NULL && !mIgnoreVendorExtensions) {
ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
return BAD_VALUE;
} else if (sink == NULL) {
ALOGW("Skipping route to sink "%s" as it likely has vendor extension type", sinkAttr.c_str());
return NO_INIT;
}
/// 调用 setSink 函数将 sink 设置给 AudioRoute 对象.
route->setSink(sink)
// 获取 sources 属性值
std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources);
if (sourcesAttr.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::sources);
return BAD_VALUE;
}
/// Convert Sink name to port pointer
/// <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
/// <mixPort name="deep_buffer" role="source" flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
/// <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
/// <route type="mix" sources="primary output,deep_buffer,BT SCO Headset Mic"/>
/// 调用 findPortByTagName 函数的作用是查找 mixPort.name 或 devicePort.tagName 等于 route.sources 的 mixPort 或 devicePort, 即 PolicyAudioPort 对象, 且 sources 对象有多个.
/// Tokenize and Convert Sources name to port pointer
PolicyAudioPortVector sources;
UniqueCPtr<char> sourcesLiteral{strndup(sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))};
char *devTag = strtok(sourcesLiteral.get(), ",");
while (devTag != NULL) {
if (strlen(devTag) != 0) {
sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
if (source == NULL && !mIgnoreVendorExtensions) {
ALOGE("%s: no source found with name=%s", __func__, devTag);
return BAD_VALUE;
} else if (source == NULL) {
ALOGW("Skipping route source "%s" as it likely has vendor extension type", devTag);
} else {
sources.add(source);
}
}
devTag = strtok(NULL, ",");
}
/// 调用 addRoute 函数将 AudioRoute 设置给 sink 对应的 PolicyAudioPort 对象.
sink->addRoute(route);
for (size_t i = 0; i < sources.size(); i++) {
sp<PolicyAudioPort> source = sources.itemAt(i);
/// 调用 addRoute 函数将 AudioRoute 设置给 source 对应的 PolicyAudioPort 对象.
source->addRoute(route);
}
/// 调用 AudioRoute.setSources 函数将 sources 对应的 PolicyAudioPort 列表设置给 AudioRoute 对象.
route->setSources(sources);
return route;
}
/// 模版函数-解析 ModuleTraits
template<>
std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx)
{
using Attributes = ModuleTraits::Attributes;
auto& tag = ModuleTraits::tag;
auto& childAttachedDevicesTag = ModuleTraits::childAttachedDevicesTag;
auto& childAttachedDeviceTag = ModuleTraits::childAttachedDeviceTag;
auto& childDefaultOutputDeviceTag = ModuleTraits::childDefaultOutputDeviceTag;
std::string name = getXmlAttribute(cur, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::name);
return BAD_VALUE;
}
uint32_t versionMajor = 0, versionMinor = 0;
std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
if (!versionLiteral.empty()) {
sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor);
ALOGV("%s: mHalVersion = major %u minor %u", __func__, versionMajor, versionMajor);
}
ALOGV("%s: %s %s=%s", __func__, ModuleTraits::tag, Attributes::name, name.c_str());
/// 创建 HwModule 对象
ModuleTraits::Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
/// 调用 deserializeCollection 解析 MixPortTraits
// Deserialize children: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
MixPortTraits::Collection mixPorts;
status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);
if (status != NO_ERROR) {
return status;
}
module->setProfiles(mixPorts);
/// 调用 deserializeCollection 解析 DevicePortTraits
DevicePortTraits::Collection devicePorts;
status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL);
if (status != NO_ERROR) {
return status;
}
module->setDeclaredDevices(devicePorts);
/// 调用 deserializeCollection 解析 RouteTraits
RouteTraits::Collection routes;
status = deserializeCollection<RouteTraits>(cur, &routes, module.get());
if (status != NO_ERROR) {
return status;
}
module->setRoutes(routes);
for (const xmlNode *children = cur->xmlChildrenNode; children != NULL; children = children->next) {
/// 解析 attachedDevices 标签
if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) {
ALOGV("%s: %s %s found", __func__, tag, childAttachedDevicesTag);
for (const xmlNode *child = children->xmlChildrenNode; child != NULL; child = child->next) {
if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) {
/// 获取 attachedDevice 子标签 <item>Speaker</item> 的值.
auto attachedDevice = make_xmlUnique(xmlNodeListGetString(child->doc, child->xmlChildrenNode, 1));
if (attachedDevice != nullptr) {
ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag, reinterpret_cast<const char*>(attachedDevice.get()));
/// 调用 HwModule 的 getDeclaredDevices().getDeviceFromTagName 函数查找 <devicePort> 标签中 tagName 属性值等于 attachedDevice 的 device, 并返回DeviceDescriptor.
sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(std::string(reinterpret_cast<const char*>(attachedDevice.get())));
if (device == nullptr && mIgnoreVendorExtensions) {
ALOGW("Skipped attached device "%s" because it likely uses a vendor" "extension type", reinterpret_cast<const char*>(attachedDevice.get()));
continue;
}
ctx->addDevice(device);
}
}
}
}
if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) {
auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString(children->doc, children->xmlChildrenNode, 1));
if (defaultOutputDevice != nullptr) {
ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag, reinterpret_cast<const char*>(defaultOutputDevice.get()));
sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
/// 设置默认输出设备
ctx->setDefaultOutputDevice(device);
ALOGV("%s: default is %08x", __func__, ctx->getDefaultOutputDevice()->type());
}
}
}
}
return module;
}
/// 模版函数-解析 ModuleTraits
template<>
std::variant<status_t, GlobalConfigTraits::Element>
PolicySerializer::deserialize<GlobalConfigTraits>(const xmlNode *root, GlobalConfigTraits::PtrSerializingCtx config)
{
using Attributes = GlobalConfigTraits::Attributes;
for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
/// 获取 globalConfiguration 标签
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(GlobalConfigTraits::tag))) {
bool value;
/// 获取 globalConfiguration 标签的属性值 speaker_drc_enabled
std::string attr = getXmlAttribute(cur, Attributes::speakerDrcEnabled);
if (!attr.empty() && convertTo<std::string, bool>(attr, value)) {
config->setSpeakerDrcEnabled(value);
}
/// 获取 call_screen_mode_supported 的属性值
attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
if (!attr.empty() && convertTo<std::string, bool>(attr, value)) {
config->setCallScreenModeSupported(value);
}
/// 获取 engine_library 的属性值
std::string engineLibrarySuffix = getXmlAttribute(cur, Attributes::engineLibrarySuffix);
if (!engineLibrarySuffix.empty()) {
config->setEngineLibraryNameSuffix(engineLibrarySuffix);
}
return NO_ERROR;
}
}
return NO_ERROR;
}
/// 模版函数-解析 SurroundSoundTraits
template<>
std::variant<status_t, SurroundSoundTraits::Element>
PolicySerializer::deserialize<SurroundSoundTraits>(const xmlNode *root, SurroundSoundTraits::PtrSerializingCtx config)
{
config->setDefaultSurroundFormats();
for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
/// 获取 surroundSound 标签
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(SurroundSoundTraits::tag))) {
AudioPolicyConfig::SurroundFormats formats;
/// 调用 deserializeCollection 函数, 解析 SurroundSoundFormatTraits
status_t status = deserializeCollection<SurroundSoundFormatTraits>(cur, &formats, nullptr);
if (status == NO_ERROR) {
config->setSurroundFormats(formats);
}
return NO_ERROR;
}
}
return NO_ERROR;
}
template<>
std::variant<status_t, SurroundSoundFormatTraits::Element>
PolicySerializer::deserialize<SurroundSoundFormatTraits>(const xmlNode *cur, SurroundSoundFormatTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = SurroundSoundFormatTraits::Attributes;
///
std::string formatLiteral = getXmlAttribute(cur, Attributes::name);
if (formatLiteral.empty()) {
ALOGE("%s: No %s found for a surround format", __func__, Attributes::name);
return BAD_VALUE;
}
if (mIgnoreVendorExtensions && maybeVendorExtension(formatLiteral)) {
ALOGI("%s: vendor extension format "%s" skipped", __func__, formatLiteral.c_str());
return NO_INIT;
}
audio_format_t format = formatFromString(formatLiteral);
if (format == AUDIO_FORMAT_DEFAULT) {
ALOGE("%s: Unrecognized format %s", __func__, formatLiteral.c_str());
return BAD_VALUE;
}
SurroundSoundFormatTraits::Element pair = std::make_pair(format, SurroundSoundFormatTraits::Collection::mapped_type{});
///
std::string subformatsLiteral = getXmlAttribute(cur, Attributes::subformats);
if (subformatsLiteral.empty()) return pair;
FormatVector subformats = formatsFromString(subformatsLiteral, " ");
for (const auto& subformat : subformats) {
auto result = pair.second.insert(subformat);
if (!result.second) {
ALOGE("%s: could not add subformat %x to collection", __func__, subformat);
return BAD_VALUE;
}
}
return pair;
}
status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config, bool ignoreVendorExtensions)
{
mIgnoreVendorExtensions = ignoreVendorExtensions;
///
auto doc = make_xmlUnique(xmlParseFile(configFile));
if (doc == nullptr) {
ALOGE("%s: Could not parse %s document.", __func__, configFile);
return BAD_VALUE;
}
xmlNodePtr root = xmlDocGetRootElement(doc.get());
if (root == NULL) {
ALOGE("%s: Could not parse %s document: empty.", __func__, configFile);
return BAD_VALUE;
}
if (xmlXIncludeProcess(doc.get()) < 0) {
ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile);
}
if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName))) {
ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName, reinterpret_cast<const char*>(root->name));
return BAD_VALUE;
}
///
std::string version = getXmlAttribute(root, versionAttribute);
if (version.empty()) {
ALOGE("%s: No version found in root node %s", __func__, rootName);
return BAD_VALUE;
}
if (version == "7.0" || version == "7.1") {
mChannelMasksSeparator = mSamplingRatesSeparator = mFlagsSeparator = " ";
} else if (version != "1.0") {
ALOGE("%s: Version does not match; expected "1.0", "7.0", or "7.1" got "%s"", __func__, version.c_str());
return BAD_VALUE;
}
// Let's deserialize children
// Modules
ModuleTraits::Collection modules;
status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);
if (status != NO_ERROR) {
return status;
}
config->setHwModules(modules);
// Global Configuration
deserialize<GlobalConfigTraits>(root, config);
// Surround configuration
deserialize<SurroundSoundTraits>(root, config);
return android::OK;
}
} // namespace
status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
{
PolicySerializer serializer;
status_t status = serializer.deserialize(fileName, config);
if (status != OK) config->clear();
return status;
}
status_t deserializeAudioPolicyFileForVts(const char *fileName, AudioPolicyConfig *config)
{
PolicySerializer serializer;
status_t status = serializer.deserialize(fileName, config, true /*ignoreVendorExtensions*/);
if (status != OK) config->clear();
return status;
}
} // namespace android
system/media/audio/include/system/audio.h 中判断输入还是输出设备的函数定义:
static inline bool audio_is_output_device(audio_devices_t device) { ... }
static inline bool audio_is_input_device(audio_devices_t device) { ... }