Android 11 AudioPolicyService 启动流程

news/2024/9/23 23:41:57/

AudioPolicyService在init进程中启动,源码路径:frameworks/av/media/audioserver/audioserver.rc

service audioserver /system/bin/audioserverclass coreuser audioserver# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)group audio camera drmrpc media mediadrm net_bt net_bt_admin net_bw_acct wakelockcapabilities BLOCK_SUSPENDioprio rt 4task_profiles ProcessCapacityHigh HighPerformanceonrestart restart vendor.audio-halonrestart restart vendor.audio-hal-4-0-msd# Keep the original service names for backward compatibilityonrestart restart vendor.audio-hal-2-0onrestart restart audio-hal-2-0

启动audioserver服务,对应的源文件为:frameworks/av/media/audioserver/main_audioserver.cpp

int main(int argc __unused, char **argv)
{if (doLog && (childPid = fork()) != 0) {//省略}else{//省略AudioFlinger::instantiate();//添加“media.audio_flinger”服务AudioPolicyService::instantiate();//添加media.audio_policy服务//省略}
}

创建AudioPolicyService时,导致其onFirstRef函数被调用

//frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
void AudioPolicyService::onFirstRef()
{{Mutex::Autolock _l(mLock);// start audio commands threadmAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);// start output activity command threadmOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);mAudioPolicyClient = new AudioPolicyClient(this);mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);}//省略

createAudioPolicyManager

//frameworks/av/services/audiopolicy/manager/AudioPolicyFactory.cpp
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);//1status_t status = apm->initialize();//2if (status != NO_ERROR) {delete apm;apm = nullptr;}return apm;
}

注释1处创建AudioPolicyManager对象,加载配置文件。关于配置文件的加载,参考:Android 11 Audio音频系统配置文件解析
注释2处,调用AudioPolicyManager的initialize函数

initialize

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::initialize() {{auto engLib = EngineLibrary::load("libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");//加载libaudiopolicyenginedefault.somEngine = engLib->createEngine();//得到Engine对象}// after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;// open all output streams needed to access attached devicesonNewAudioModulesAvailableInt(nullptr /*newDevices*/);//省略

在函数中onNewAudioModulesAvailableInt中,主要完成以下三件事情:

  1. 根据配置文件中hwModule的名字加载对应的so文件(loadHwModule)
  2. 每个hwModule的mOutputProfiles中的每个outProfile,打开输出流,创建播放线程
  3. 每个hwModule的mInputProfiles中的每个inProfile,打开输入流,创建录音线程

1,加载so文件

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
{for (const auto& hwModule : mHwModulesAll) {if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {continue;}hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));//1//省略      
}	

注释1处,调用loadHwModule处理,并将返回的结果handle赋值给hwModule 的mHandle。注意传入的是hwModule的名字,如:primary。最终调用到AudioFlinger的loadHwModule函数

//frameworks/av/services/audioflinger/AudioFlinger.cpp
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{//省略Mutex::Autolock _l(mLock);AutoMutex lock(mHardwareLock);return loadHwModule_l(name);
}

loadHwModule_l

//frameworks/av/services/audioflinger/AudioFlinger.cpp
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{//省略sp<DeviceHalInterface> dev;int rc = mDevicesFactoryHal->openDevice(name, &dev);//1//省略audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);//2mAudioHwDevs.add(handle, audioDevice);//3return handle;
}

注释1处通过hidl,去加载对应的so(如:audio.primary.default.so),并调用audio hal的open函数,从hal中得到一个audio_hw_device对象。注释2处将该对象封装在AudioHwDevice 中,然后注释3处将AudioHwDevice 添加到mAudioHwDevs数组中。

打开输出流创建线程

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
{for (const auto& hwModule : mHwModulesAll) {if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {continue;}//省略   for (const auto& outProfile : hwModule->getOutputProfiles()) {//省略sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,mpClientInterface);audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),AUDIO_STREAM_DEFAULT,AUDIO_OUTPUT_FLAG_NONE, &output);//省略addOutput(output, outputDesc);//保存到mOutputs数组中}   //省略
}	

针对module下的每个outProfile ,都会创建一个SwAudioOutputDescriptor对象,并调用其open方法,然后将该SwAudioOutputDescriptor保存到mOutputs数组中,注意是根据返回的output来保存的。open函数最终调用到AudioFlinger的openOutput_l函数

//frameworks/av/services/audioflinger/AudioFlinger.cpp
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,audio_io_handle_t *output,audio_config_t *config,audio_devices_t deviceType,const String8& address,audio_output_flags_t flags)
{AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);//根据handle,从mAudioHwDevs数组中找出AudioHwDevice //省略AudioStreamOut *outputStream = NULL;status_t status = outHwDev->openOutputStream(&outputStream,*output,deviceType,flags,config,address.string());//1if (status == NO_ERROR) {if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {//省略} else {sp<PlaybackThread> thread;if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {//省略} else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)|| !isValidPcmSinkFormat(config->format)|| !isValidPcmSinkChannelMask(config->channel_mask)) {//省略} else {thread = new MixerThread(this, outputStream, *output, mSystemReady);//创建MixerThread播放线程}mPlaybackThreads.add(*output, thread);//添加到mPlaybackThreadsreturn thread;}}return 0;
}

注释1处调用AudioHwDevice 的openOutputStream函数去打开输出流。然后就是创建MixerThread播放线程并保存在mPlaybackThreads数组中,需要注意的是,也是根据output添加的。这里的output和上面添加outputDesc时的output是同一个。

openOutputStream

//frameworks/av/services/audioflinger/AudioHwDevice.cpp
status_t AudioHwDevice::openOutputStream(AudioStreamOut **ppStreamOut,audio_io_handle_t handle,audio_devices_t deviceType,audio_output_flags_t flags,struct audio_config *config,const char *address)
{struct audio_config originalConfig = *config;AudioStreamOut *outputStream = new AudioStreamOut(this, flags);//创建AudioStreamOut对象status_t status = outputStream->open(handle, deviceType, config, address);//省略*ppStreamOut = outputStream;return status;
}

AudioStreamOut::open

//frameworks/av/services/audioflinger/AudioStreamOut.cpp
status_t AudioStreamOut::open(audio_io_handle_t handle,audio_devices_t deviceType,struct audio_config *config,const char *address)
{sp<StreamOutHalInterface> outStream;int status = hwDev()->openOutputStream(handle,deviceType,customFlags,config,address,&outStream);
//省略

openOutputStream最后会通过hidl,调用到audio hal 的open_output_stream函数,返回一个audio_stream_out对象。

打开输入流,创建录音线程

这个流程和上面的是一样的,最终调用到AudioFlinger的openInput_l处理

//frameworks/av/services/audioflinger/AudioFlinger.cpp
sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,audio_io_handle_t *input,audio_config_t *config,audio_devices_t devices,const String8& address,audio_source_t source,audio_input_flags_t flags,audio_devices_t outputDevice,const String8& outputDeviceAddress)
{AudioHwDevice *inHwDev = findSuitableHwDev_l(module, devices);//找出AudioHwDevice //省略sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();sp<StreamInHalInterface> inStream;status_t status = inHwHal->openInputStream(*input, devices, &halconfig, flags, address.string(), source,outputDevice, outputDeviceAddress, &inStream);//1//省略if (status == NO_ERROR && inStream != 0) {AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);//将HAL层得到的audio_stream_in保存在AudioStreamIn中if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {//省略} else {// Start record thread// RecordThread requires both input and output device indication to forward to audio// pre processing modulessp<RecordThread> thread = new RecordThread(this, inputStream, *input, mSystemReady);//创建RecordThread线程mRecordThreads.add(*input, thread);//保存在mRecordThreads数组中ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());return thread;}//省略

注释1处,通过hidl,调用到audio hal 的open_input_stream函数,返回一个audio_stream_in对象。

总结

AudioPolicyService服务的启动过程中,会解析配置文件。针对每个HwModule,根据名字去加载对应的HAL库,得到audio_hw_device对象,将其保存在AudioHwDevice对象中,并将AudioHwDevice对象添加到mAudioHwDevs数组中。

对于HwModule下的每个outProfile ,都会创建SwAudioOutputDescriptor对象,并去打开输出流,创建播放线程。根据返回的output,将SwAudioOutputDescriptor添加到mOutput数组中。在打开输出流的过程中,会得到HAL层的audio_stream_out对象,并将其保存在AudioStreamOut中,创建播放线程的时候,传入该AudioStreamOut,最后将播放线程保存到mPlaybackThreads中。

对于HwModule下的每个inProfile,都会去打开输入流,创建录音线程。在打开输出流的过程中,会得到HAL层的audio_stream_in对象,并将其保存在AudioStreamIn中,创建录音线程的时候,传入该AudioStreamIn。最后将录音线程保存在mRecordThreads中

保存AudioHwDevice和保存播放线程,是根据同一个output保存的。


http://www.ppmy.cn/news/1464220.html

相关文章

修复CentOS 6.6服务器YUM和RPM功能异常的技术实践20240523

修复CentOS 6.6服务器YUM和RPM功能异常的技术实践 引言 在复杂的生产环境中&#xff0c;服务器的稳定性至关重要。近期&#xff0c;我们遇到了一台CentOS 6.6服务器在执行yum update -y时被中断&#xff0c;导致YUM和RPM功能异常的问题。本文将详细介绍问题的诊断、解决过程以及…

Golang | Leetcode Golang题解之第103题二叉树的锯齿形层序遍历

题目&#xff1a; 题解&#xff1a; func zigzagLevelOrder(root *TreeNode) (ans [][]int) {if root nil {return}queue : []*TreeNode{root}for level : 0; len(queue) > 0; level {vals : []int{}q : queuequeue nilfor _, node : range q {vals append(vals, node.V…

【class19】人工智能初步---语音识别(5)

【class19】 上节课&#xff0c;我们学习了&#xff1a;语音识别模型的结构和原理&#xff0c;同时调用创建好的AipSpeech客户端实现了语音转文字功能。 本节课&#xff0c;我们将初识字幕&#xff0c;学习这些知识点&#xff1a;1. srt字幕 2. 获取时间数据 …

nginx学习记录-防盗链

1. 防盗链的概念 防盗链&#xff0c;顾名思义就是防止盗取链接&#xff0c;这里的链接一般是资源链接。 如图所示&#xff0c;我们访问一个网站时&#xff08;比如百度&#xff09;&#xff0c;我们第一个请求会获得一个html页面&#xff0c;页面中包含各种资源链接&#xff0…

【Hudi】hudi概述

Apache Hudi是什么 下一代数仓解决方法&#xff0c;提供高效的upsert和近实时更新Hudi提供了表、事务、高效的upsert/delete、高级索引、流摄取服务、数据集群/压缩优化和并发。同时保持数据的开源文件格式 两种文件格式&#xff1a;parquet、avroApache Hudi不仅非常适合流工…

python 面对对象 类 基础

面对对象 程序是由数据和功能组合而成的对象构建起来的&#xff0c;对数据与函数绑定到一起&#xff0c;进行封装&#xff0c;能够更快速的开发程序&#xff0c;减少重复代码 class --- 类&#xff0c;类是对象的抽象化&#xff0c;具有相同特征或行为的事物的统称 类的定义…

知识点最多最详细的JS自学学习笔记(连载)第一章、条件判断语法

条件判断语法 (1) if else if(条件1){ 条件成立执行的语句 }else if(条件2){ 条件2成立执行的语句 }else if(条件3){ 条件3成立执行的语句 }... else{ 以上条件都不成立执行的语句 } 1、if中…

微信加好友的方式有哪些?如何快捷自动回复?

微信加好友的方式&#xff1a; 1、通信录导入根据微信号综合评分&#xff0c;24小时只能加15-25位好友。即使超出了25个&#xff0c;添加后显示发送验证成功&#xff0c;对方也收不到你的验证信息&#xff0c;你手上有千万个老客户的手机号也没用。 2、查找添加10小时智能查找…