Android 8 AudioPolicy 初始化
记录一下AudioPolicy初始化过程。
frameworks\av\media\audioserver\audioserver.rc
service audioserver /system/bin/audioserver
class main
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct oem_2901
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
onrestart restart audio-hal-2-0
frameworks\av\media\audioserver\main_audioserver.cpp
int main(int argc __unused, char **argv)
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
frameworks\av\services\audiopolicy\service\AudioPolicyService.cpp
void AudioPolicyService::onFirstRef()
{
{
Mutex::Autolock _l(mLock);
// start tone playback thread
mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
// start output activity command thread
mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
mAudioPolicyClient = new AudioPolicyClient(this);
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient); // 创建AudioPolicyManager
}
// load audio processing modules
sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(); // 加载声音效果文件
{
Mutex::Autolock _l(mLock);
mAudioPolicyEffects = audioPolicyEffects;
}
}
// 加载声音效果
AudioPolicyEffects::AudioPolicyEffects()
{
status_t loadResult = loadAudioEffectXmlConfig();
if (loadResult < 0) {
ALOGW("Failed to load XML effect configuration, fallback to .conf");
// load automatic audio effect modules
if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
} else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
}
} else if (loadResult > 0) {
ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
}
}
system\media\audio\include\system\audio_effects\audio_effects_conf.h
#define AUDIO_EFFECT_DEFAULT_CONFIG_FILE "/system/etc/audio_effects.conf"
#define AUDIO_EFFECT_VENDOR_CONFIG_FILE "/vendor/etc/audio_effects.conf"
frameworks\av\services\audiopolicy\manager\AudioPolicyFactory.cpp
extern "C" AudioPolicyInterface* createAudioPolicyManager(
AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManager(clientInterface);
}
AudioPolicyManager创建:
初始化主要读取xml文件,获取可以支持的设备类型,采样率等参数。
frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
:
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
mUidCached = getuid();
mpClientInterface = clientInterface;
// 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 speakerDrcEnabled = false;
//hardware\qcom\audio\configs\msm8953\msm8953.mk
//USE_XML_AUDIO_POLICY_CONF := 1
#ifdef USE_XML_AUDIO_POLICY_CONF
// 设置声音曲线
mVolumeCurves = new VolumeCurvesCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled,
static_cast<VolumeCurvesCollection *>(mVolumeCurves));
// 解析文件audio_policy_configuration.xml
if (deserializeAudioPolicyXmlConfig(config) != NO_ERROR) {
#else
mVolumeCurves = new StreamDescriptorCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled);
// #define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
// #define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"
if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
(ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
#endif
ALOGE("could not load audio policy configuration file, setting defaults");
config.setDefault();
}
// must be done after reading the policy (since conditionned by Speaker Drc Enabling)
mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled);
// Once policy config has been parsed, retrieve an instance of the engine and initialize it.
audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
if (!engineInstance) {
ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__);
return;
}
// Retrieve the Policy Manager Interface
mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
if (mEngine == NULL) {
ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
return;
}
mEngine->setObserver(this);
status_t status = mEngine->initCheck();
(void) status;
ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// open all output streams needed to access attached devices
audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
for (size_t i = 0; i < mHwModules.size(); i++) {
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
ALOGE("Liutao %s: mHwModules.name: %s", __FUNCTION__, mHwModules[i]->getName());
/*
打印出的模块名 // 对应xml的mudule.
AudioPolicyManager: mHwModules.name: primary
AudioPolicyManager: mHwModules.name: a2dp
AudioPolicyManager: mHwModules.name: usb
AudioPolicyManager: mHwModules.name: r_submix
*/
if (mHwModules[i]->mHandle == 0) {
ALOGW("could not open HW module %s", mHwModules[i]->getName());
continue;
}
// open all output streams needed to access attached devices
// except for direct output streams that are only opened when they are actually
// required by an app.
// This also validates mAvailableOutputDevices list
// 对应xml的profile
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];
// ALOGE("Liutao %s: mOutputProfile.name: %s", __FUNCTION__, mHwModules[i]->mOutputProfiles.getName());
if (!outProfile->hasSupportedDevices()) {
ALOGW("Output profile contains no device on module %s", mHwModules[i]->getName());
continue;
}
if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
mTtsOutputAvailable = true;
}
if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
continue;
}
audio_devices_t profileType = outProfile->getSupportedDevicesType();
if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
profileType = mDefaultOutputDevice->type();
} else {
// chose first device present in profile's SupportedDevices also part of
// outputDeviceTypes
profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes);
}
if ((profileType & outputDeviceTypes) == 0) {
continue;
}
sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
mpClientInterface);
const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType);
String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress
: String8("");
outputDesc->mDevice = profileType;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = outputDesc->mSamplingRate;
config.channel_mask = outputDesc->mChannelMask;
config.format = outputDesc->mFormat;
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
&output,
&config,
&outputDesc->mDevice,
address,
&outputDesc->mLatency,
outputDesc->mFlags);
if (status != NO_ERROR) {
ALOGW("Cannot open output stream for device %08x on hw module %s",
outputDesc->mDevice,
mHwModules[i]->getName());
} else {
outputDesc->mSamplingRate = config.sample_rate;
outputDesc->mChannelMask = config.channel_mask;
outputDesc->mFormat = config.format;
for (size_t k = 0; k < supportedDevices.size(); k++) {
ssize_t index = mAvailableOutputDevices.indexOf(supportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
mAvailableOutputDevices[index]->attach(mHwModules[i]);
}
}
if (mPrimaryOutput == 0 &&
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
addOutput(output, outputDesc);
setOutputDevice(outputDesc,
outputDesc->mDevice,
true,
0,
NULL,
address.string());
}
}
...
// config文件解析
#define AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH 128
#define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
#ifdef USE_XML_AUDIO_POLICY_CONF
// Treblized audio policy xml config will be located in /odm/etc or /vendor/etc.
static const char *kConfigLocationList[] =
{"/odm/etc", "/vendor/etc/audio", "/vendor/etc", "/system/etc"};
static const int kConfigLocationListSize =
(sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
status_t ret;
for (int i = 0; i < kConfigLocationListSize; i++) {
PolicySerializer serializer;
snprintf(audioPolicyXmlConfigFile,
sizeof(audioPolicyXmlConfigFile),
"%s/%s",
kConfigLocationList[i],
AUDIO_POLICY_XML_CONFIG_FILE_NAME);
ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
if (ret == NO_ERROR) {
break;
}
}
return ret;
}
#endif
audio_policy_configuration.xml文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) 2016-2017, The Linux Foundation. All rights reserved
Not a Contribution.
-->
<!-- Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
<!-- 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="2.0">
<attachedDevices>
<item>Earpiece</item>
<item>Speaker</item>
<item>Telephony Tx</item>
<item>Built-In Mic</item>
<item>Built-In Back Mic</item>
<item>FM Tuner</item>
<item>Telephony Rx</item>
</attachedDevices>
<defaultOutputDevice>Speaker</defaultOutputDevice>
<mixPorts>
<mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_PRIMARY
">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="raw" role="source"
flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW">
<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="direct_pcm" role="source"
flags="AUDIO_OUTPUT_FLAG_DIRECT">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,1
28000,176400,192000"
channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1
,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OU
T_7POINT1"/>
<profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,1
28000,176400,192000"
channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1
,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OU
T_7POINT1"/>
<profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
...
<!-- include 包含其他的xml文件 -->
<!-- A2dp Audio HAL -->
<xi:include href="/vendor/etc/a2dp_audio_policy_configuration.xml"/>
<!-- Usb Audio HAL -->
<xi:include href="/vendor/etc/usb_audio_policy_configuration.xml"/>
<!-- Remote Submix Audio HAL -->
<xi:include href="/vendor/etc/r_submix_audio_policy_configuration.xml"/>
</modules>
<!-- End of Modules section -->
<!-- Volume section -->
<xi:include href="/vendor/etc/audio_policy_volumes.xml"/>
<xi:include href="/vendor/etc/default_volume_tables.xml"/>
Shenzhen,2018-8-30
Android 8 AudioPolicy 初始化的更多相关文章
- Android编译系统环境初始化过程分析
Android源代码在编译之前,要先对编译环境进行初始化,其中最主要就是指定编译的类型和目标设备的型号.Android的编译类型主要有eng.userdebug和user三种,而支持的目标设备型号则是 ...
- Android M AudioPolicy 分析
1.AudioPolicyService基础 AudioPolicy在Android系统中主要负责Audio"策略"相关的问题.它和AudioFlinger一起组成了Android ...
- Android - ViewPager+Fragment初始化问题
Android应用开发中,经常会用到ViewPager + Fragment,虽然效果不错,但随之而来的还有一些问题,下面就说说其中的初始化问题. ViewPager初始化时会预加载前后的2个页面,即 ...
- android:Android中用文件初始化sqlite数据库(zz)
很多时候在应用安装初始化时,需要创建本地数据库,同时为数据库添加数据,之后再从数据库中读取数据. 这里有2个思路 1.先在本地创建一个能支持android使用的sqlite数据库文件,启动时, ...
- Android中用文件初始化sqlite 数据库(二)
博 androidsqlite启动时数据库初始化 方法1已经讲述了一种初始化数据库的方法 它的数据库初始化不是用sql语句,而是用一个现成的sqlite的二进制文件进行直接copy到Android系 ...
- Android 8 Wifi 初始化过程
记录一下wifi初始化过程. packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java public void on ...
- android kernel控制台初始化过程
对于我们的android平台,控制台被定义到了串口1上,因此初始化过程就是把控制台的输出配置到串口1上 对kernel控制台初始化是在挂载文件系统之前,由于没有串口的设备文件,不能通过打开设备文件来访 ...
- Android如何在初始化的时候获取加载的布局的宽高
在自定义ListView中,需要将下拉刷新的View在初始化的时候设置padding隐藏起来,这时就要在初始化的时候获得要加载的布局View的高度. private View headView; he ...
- android:Android中用文件初始化sqlite数据库
很多时候在应用安装初始化时,需要创建本地数据库,同时为数据库添加数据,之后再从数据库中读取数据. 这里有2个思路 1.先在本地创建一个能支持android使用的sqlite数据库文件,启动时,用现成的 ...
随机推荐
- maven生成jar,运行却提示没有“没有主清单属性”
转自:http://www.jianshu.com/p/fd5bd8657852 修改pom.xml <project xmlns="http://maven.apache.org/P ...
- 添加Fragment报已有父view,需先移除的错
错误LOG: 12-13 17:05:28.754: E/AndroidRuntime(8344): FATAL EXCEPTION: main 12-13 17:05:28.754: E/Andro ...
- NGUI的UISprite动态染色的一种方法
本文主要参考iwinterice 的 NGUI的UISprite动态染色的一种解决方案 文章. 参考参考,就是既参详又拷贝,-,-||| 相关理论依据,还请去移步 NGUI的UISprite动态染色的 ...
- STL之std::set、std::map的lower_bound和upper_bound函数使用说明
由于在使用std::map时感觉lower_bound和upper_bound函数了解不多,这里整理并记录下相关用法及功能. STL的map.multimap.set.multiset都有三个比较特殊 ...
- Lintcode: Majority Number 解题报告
Majority Number 原题链接:http://lintcode.com/en/problem/majority-number/# Given an array of integers, th ...
- 代码重定位和位置无关码——运行于nor flash
通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位. 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简 ...
- Spring Batch并行与扩展
1. 概述 Spring Batch提供了多种方式用于处理并行,提高性能.主要分为2大类: - 单个进程,多线程 - 多个进程 因此,可以细分为以下几类: - 多线程Step(Multi-thread ...
- MVC LinqToSql Json DbComparisonExpression 需要具有可比较类型的参数。
需求是:使用post方式传入Controller一个id,然后返回给前台一个Json.突然就报了这个错误,折腾了俩小时, 发现是linq to sql 的语法错了
- 基于html5海贼王单页视差滚动特效
分享一款基于html5海贼王单页视差滚动特效是一款流行滑落网页特效代码.效果图如下: 在线预览 源码下载 实现的代码: <div class="top"> < ...
- spring data jpa的update操作
简介 使用jpa进行update操作主要有两种方式: 1.调用保存实体的方法 1)保存一个实体:repository.save(T entity) 2)保存多个实体:repository.save(I ...