这篇文章主要介绍一下AudioFlinger到hal层的一些工作流程。我们知道AudioFlinger从FIFO种读取到数据之后会调用hal的out_write函数去写入数据,我们就以这个函数为入口展开分析。

  1. out_write函数
    这个函数首先是有一些out->devices的判断,然后会判断是否是standby,如果是会调用start_output_stream去打开输出设备。然后如果pcm状态正常的情况下会调用pcm_write函数向adsp中写入数据。pcm_write是kernel的函数,我们这里只分析hal层,所以接下来我们去看一下start_output_stream函数打开设备的流程。
  2. start_output_stream函数
    这个函数首先调用platform_get_pcm_device_id函数去获取device id,这个id的定义是取决于kernel的,也就是说hal层把这个id传给kernel,kernel根据对应的id去打开相应的通路。platform_get_pcm_device_id函数在platform.c中,主要是从pcm_device_table中根据相应的usecase去获取对应的通路id。定义如下:
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,DEEP_BUFFER_PCM_DEVICE},[USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = {AUDIO_HAPTICS_PCM_DEVICE,AUDIO_HAPTICS_PCM_DEVICE},[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,LOWLATENCY_PCM_DEVICE},[USECASE_AUDIO_PLAYBACK_ULL]         = {MULTIMEDIA3_PCM_DEVICE,MULTIMEDIA3_PCM_DEVICE},[USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,MULTIMEDIA2_PCM_DEVICE},[USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE,MULTIMEDIA2_PCM_DEVICE},[USECASE_AUDIO_PLAYBACK_TTS] = {MULTIMEDIA2_PCM_DEVICE,MULTIMEDIA2_PCM_DEVICE},[USECASE_AUDIO_PLAYBACK_OFFLOAD] ={PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},[USECASE_AUDIO_PLAYBACK_OFFLOAD2] ={PLAYBACK_OFFLOAD_DEVICE2, PLAYBACK_OFFLOAD_DEVICE2},[USECASE_AUDIO_PLAYBACK_OFFLOAD3] ={PLAYBACK_OFFLOAD_DEVICE3, PLAYBACK_OFFLOAD_DEVICE3},[USECASE_AUDIO_PLAYBACK_OFFLOAD4] ={PLAYBACK_OFFLOAD_DEVICE4, PLAYBACK_OFFLOAD_DEVICE4},[USECASE_AUDIO_PLAYBACK_OFFLOAD5] ={PLAYBACK_OFFLOAD_DEVICE5, PLAYBACK_OFFLOAD_DEVICE5},[USECASE_AUDIO_PLAYBACK_OFFLOAD6] ={PLAYBACK_OFFLOAD_DEVICE6, PLAYBACK_OFFLOAD_DEVICE6},[USECASE_AUDIO_PLAYBACK_OFFLOAD7] ={PLAYBACK_OFFLOAD_DEVICE7, PLAYBACK_OFFLOAD_DEVICE7},[USECASE_AUDIO_PLAYBACK_OFFLOAD8] ={PLAYBACK_OFFLOAD_DEVICE8, PLAYBACK_OFFLOAD_DEVICE8},[USECASE_AUDIO_PLAYBACK_OFFLOAD9] ={PLAYBACK_OFFLOAD_DEVICE9, PLAYBACK_OFFLOAD_DEVICE9},。。。
};

然后DEEP_BUFFER_PCM_DEVICE等分别对应定义好的一个int值。
然后会调用到select_devices函数中。
3. select_devices函数

int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
{ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);usecase = get_usecase_from_list(adev, uc_id);if (usecase == NULL) {ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);return -EINVAL;}if (usecase->type == PCM_PLAYBACK) {if (usecase->stream.out == NULL) {ALOGE("%s: stream.out is NULL", __func__);return -EINVAL;}usecase->devices = usecase->stream.out->devices;in_snd_device = SND_DEVICE_NONE;if (out_snd_device == SND_DEVICE_NONE) {struct stream_out *voip_out = adev->primary_output;struct stream_in *voip_in = get_voice_communication_input(adev);if (usecase->devices & AUDIO_DEVICE_OUT_BUS)out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);elseout_snd_device = platform_get_output_snd_device(adev->platform,usecase->stream.out);voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);if (voip_usecase)voip_out = voip_usecase->stream.out;if (usecase->stream.out == voip_out && voip_in != NULL)select_devices(adev, voip_in->usecase);}} /* Enable new sound devices */if (out_snd_device != SND_DEVICE_NONE) {check_usecases_codec_backend(adev, usecase, out_snd_device);if (platform_check_codec_asrc_support(adev->platform))check_and_set_asrc_mode(adev, usecase, out_snd_device);enable_snd_device(adev, out_snd_device);}enable_audio_route(adev, usecase);audio_extn_qdsp_set_device(usecase);}

这个函数会调用get_usecase_from_list函数把device和usecase等信息封装到audio_usecase结构体中,如果usecase->type是播放的话会去判断输出设备是否是AUDIO_DEVICE_OUT_BUS(这个是车机的device,因为我们是车机,所以就看一下这个if调用的函数),然后调用audio_extn_auto_hal_get_output_snd_device函数,再到auto_hal_get_output_snd_device函数,这个函数会根据device和usecase去选择hal层对应的snd_device。这个snd_device和上面传过来的device不同,传过来的device是framework上定义的一个名称,这个snd_device才是真正的hal层的device,比如framework传过来的是通过offload模式(媒体播放)设备是AUDIO_DEVICE_OUT_BUS去播放设备,在这里会根据这个usecase和device把snd_device转换成SND_DEVICE_OUT_BUS_MEDIA,如果framework传过来的是NAV(导航)模式AUDIO_DEVICE_OUT_BUS设备,那么snd_device对应的就是SND_DEVICE_OUT_BUS_NAV。同样的,如果设备不是AUDIO_DEVICE_OUT_BUS会调用platform_get_output_snd_device,但是这个函数也是做上面的一些操作,只不过这个函数相对会复杂一些,除了AUDIO_DEVICE_OUT_BUS之外所有的device转换都是从这里做的,比如headset,手机上的听筒等。最后调用enable_snd_device去打开输出设备通路,以及调用enable_audio_route去使能audio route。
4. enable_snd_device函数
这个函数首先调用platform_get_snd_device_name_extn函数使用上一步得到的snd_device去获取device_name,这个device_name就是mixer_path中所定义的名字,还是以SND_DEVICE_OUT_BUS_MEDIA为例进行分析,这里从device_table数组中得到的device_name是"bus-speaker"。然后继续往下走,会走到audio_route_apply_and_update_path函数,再到audio_route_update_path函数,这里首先根据上面获取到的device_name去解析mixer_path,然后拿到mixer_path中定义的"bus-speaker"所对应的通路,然后调用tinyalsa的mixer.c中的mixer_ctl_set_value函数去打开设备通路。
5. enable_audio_route函数
这个函数会调用platform_add_backend_name函数在通路的设备上添加设备名,用于不同的usecase定义,也就是把"headphones-44.1","speaker-and-headphones"等添加到usecase的设备名称中,主要是为了应对同样的usecase不同的设备配置不同的问题。比如同样的offload模式,有如下两种不同的定义

    <path name="compress-offload-playback"><ctl name="TERT_TDM_RX_0 Channels" value="Six" /><ctl name="TERT_TDM_RX_0 Audio Mixer MultiMedia4" value="1" /></path><path name="compress-offload-playback bt-sco"><ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia4" value="1" /></path>

通过上面的例子我们可以看到,同样的offload模式,蓝牙的和默认的定义是完全不同的。最后这个函数和enable_snd_device函数一样也是调用audio_route_apply_and_update_path函数通过tinyalsa去打开对应的usecase。到这里hal层的打开usecase通路以及打开device输出设备的流程就大体分析完成了

高通AudioHAL分析相关推荐

  1. 高通平台fingerprint指纹框架

    指纹是android系统中目前应用比较广发的一种安全验证手段,它使得我们的手机安全得到了极大的提高,同时指纹它也拥有了极高权限,这就意味着,对于指纹这个软件需要一个绝对安全的运行环境,让外界很难突破去 ...

  2. linux驱动由浅入深系列:高通sensor架构实例分析之一

    点击打开链接 本系列导航: linux驱动由浅入深系列:高通sensor架构实例分析之一(整体概览+AP侧代码分析) linux驱动由浅入深系列:高通sensor架构实例分析之二(adsp驱动代码结构 ...

  3. 高通、猎户机型Android典型bootloader分析

    1.bootloader是什么? 简单地说,bootloader 就是在操作系统内核运行之前运行的一段小程序.通过这段小程序,我们可以初始化硬件设备.建立内存空间的映射图,从而将系统的软硬件环境带到一 ...

  4. AUTOSAR从入门到精通100讲(二十)-特斯拉、高通、华为AI处理器深度分析

    很多人会问,为什么没有英伟达?目前所有主流深度学习运算主流框架后端都是英伟达的CUDA,包括TensorFlow.Caffe.Caffe2.PyTorch.mxnet.PaddlePaddle,CUD ...

  5. 高通android开源代码下载,高通平台Android源码bootloader分析之sbl1(三)

    前两篇博文分析了启动流程.代码流程.cdt,接下来就分析另外几个需要格外关注的部分. ##log系统 sbl1中的log系统也是sbl1部分调试会经常接触得部分高通平台在sbl中做的log系统并不是很 ...

  6. Android 功耗(3)---高通功耗问题分析方法

    高通功耗问题分析 高通官方提供了一篇文档extensive_power_debug_guide_(simplified_chinese功耗调试).pdf  用来分析中断功耗问题. 本文结合该文档简单的 ...

  7. 分析 | 高通骁龙845已发布,明年智能手机会变成什么样

    ▼ 大型年度AI人物评选--2017中国AI英雄风云榜已于12月4日在乌镇张榜,12月18日在北京国贸三期举行颁奖典礼. 榜单评选出年度技术创新人物TOP 10:商业创新人物TOP 10,获取完整榜单 ...

  8. 高通(Qualcomm)LK源码深度分析(三)

    本编文章的内容主要是分析 boot/recovery 的启动过程,其中的 boot 就是 android 的kernel, 是整个 android 系统的核心.本文的分析是紧接着 aboot_init ...

  9. android加载efi分区,高通Android UEFI XBL 代码流程分析

    高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...

最新文章

  1. linux mint 屏保_Linux Mint 修复了两个孩子发现的屏保锁定绕过漏洞
  2. 剑指offer:面试题35. 复杂链表的复制
  3. Spring多数据源配置和使用
  4. 从零开始PyTorch项目:YOLO v3目标检测实现
  5. SharePoint 2010 BI(2):使用Visio“.NET研究” Service
  6. 入门:现实世界中的推荐系统(术语、技术等)
  7. Xcode6 管理provisioning profile
  8. CCF201812-2 小明放学(100分)【序列处理】
  9. C#问题——interface class
  10. Altium Designer 10 安装破解教程
  11. java毕业设计补课管理系统Mybatis+系统+数据库+调试部署
  12. [Irving]字符串相似度-字符编辑距离算法(c#实现)
  13. 以“文博珠宝管理系统”为例,分析信息管理系统在物流分销中的应用
  14. 百果园港交所上市:市值近百亿港元 80%营收来自加盟店
  15. Excel自学笔记 第五节 怎么在列后加统一固定字符?
  16. win10右键卡顿问题 简单实用
  17. 股权激励,要从这六个层面去理解
  18. 如何使用OpenCV进行Delaunay三角剖分和Voronoi图
  19. 2018.1.28 牛客网2018年全国多校算法寒假训练营练习比赛题解
  20. vue-router页面不渲染

热门文章

  1. Window7系统的完整开机加载过程的原理和机制
  2. Odoo 16 企业版手册 - 销售管理之销售报价
  3. Swoole案例教程
  4. AI人工智能电话机服务电话
  5. BurpSuite与Chrome浏览器设置
  6. CentOS服务器搭建与项目部署
  7. 最小二乘法的一阶、二阶辨识系统
  8. 改变maven打包路径_Maven打包技巧
  9. 数据压缩 —— 一种基于LZ4算法的硬件加速的快速无损压缩
  10. 上海英方科技招股书市场分析