<一>Android Audio音频框架
目录
1.0 设备驱动
2.0 android hal层
3.0 选择设备的暗箱策略AudioPolicy
4.0 软件层面的混音,AudioFlinger
5.0 完整的对外接口 AudioSystem.cpp
6.0 换壳java形似的对外接口AudioSystem.java
7.0 java层的服务供应AudioService.java
8.0 应用层的一对一服务AudioManager
9.0 为了支持和兼容多音频设备的car, 提供的动态策略。
10.0 CarAudioService CarAudioManager
11.0 AudioTrack OpenslEs AAudio
Aaudiotrack:
opensl:
AAudio:
12.0 oboe 库
总览:个人对于Android 音频模块的整体理解,分析各个子模块存在的意义,领悟设计者架构思想,探讨未来可能的发展趋势。篇幅有限,码字不易,部分子模块的详细分析还为上blog
放一张自制图:
图中有一个小的拼写错误,为AlSA ,非ALSO。
全文涉及到 AudioFlinger AudioPolicy AudioSystem AudioService AudioManager
以及用于音频流数据传输的 AudioTrack OpenSLes AAudio。 部分子篇还为编写,先预留占坑。
1.0 设备驱动
linux 系统上一个应用要播放一个音频,原理是open一个音频播放设备的设备节点,然后往节点写入数据即可。设备节点由内核里面的驱动提供,往该设备节点写数据就是输入到了驱动中,对应音频设备的驱动,linux 提供的是名为ALSA 的框架,通常对音频来说都是pcm设备,所以里面的驱动也就是pcm设备驱动。属于字符设备,串行。(linux 设备类型:字符设备,块设备,网络设备) 由该pcm设备的驱动,处理获得的pcm数据给到硬件信号达到播放声音的目的。
驱动要处理的问题:竞争,阻塞,可重入。
pcm设备当然也是支持多个进程同时使用的,那么内核的pcm驱动就需要处理这个并发的情况 (内部也应该是作了混合音频的处理的,待后续补充详细)
android 也有相应的工具,tinyalsa. 就是直接通过和linux 内核的alsa框架进行交互,可以不经过hal层。当然这个机制只是为了方便调试的,android并不打算把它给应用层使用,应用层的接口还需要经过android系统的层层包装和管理。
详细参考:
《 1.有待补充blog linux pcm设备驱动 》
《 1. android tinyalsa 理解_王二の黄金时代的博客-CSDN博客》
2.0 android hal层
既然是基于linux内核,硬件厂商完全可以实现自己的驱动,然后系统启动insmod加载进去,普通的应用程序即可通过驱动的设备节点,来open write/read iocontrol 完成对设备的操作。但是为了厂家并不乐意公开自己的驱动全部,于是安卓整了一套硬件抽象层 hal.( 关于hal,介绍的资料不少,不再赘述)
一个普通的c++的层序,就已经可以直接调用hal层的接口,打开指定的设备,把pcm数据流写入进行播放了。
《2..1 android 直接使用hal库播放pcm demo》
但是设备众多,总不能都需要开发者自己选择具体的输出设备,于是android又为我们提供了一个自动确定具体设备的模块:AudioPolicy
3.0 选择设备的暗箱策略AudioPolicy
AudioPolicy 根据有限的固定的流类型,来确定最终的设备。之所以说它是暗箱操作,应为应用层不会参与也不清楚具体选择那个输出设备。很好地将应用开发者和设备制作者再进行了一次分离,通过这个相对不会有太多变化的流类型,让应用开发者不需要再往下关注不同android设备具体音频设备的组成。 而到底这个流类型的数据是输出给听筒,还是扬声器,还是一起都输出,这就需要设备制作者来暗箱操作了,这个就是AudioPolicyServe的用途。
详细参考:
《3. 待后续补充blog AudioPolicy 选择设备策略的源码分析》
4.0 软件层面的混音,AudioFlinger
每一个应用都需要自己去调用hal驱动,这看起来是linux上面的开发模式,移动端的系统总是期望什么功能都有系统的一个统一管理,Android系统音频也就是这么干的,这就是AudioFlinger. 从linux的角度来看, android 系统只有一个进程在播放声音,就是AudioFlinger所在的进程。
关于AudioFlinger的角色,从其命名就可以直接看出来,Flinger的原本意思就是将多个汇合成一个的意思,同样命名的还有SurfaceFlinger,所以它的作用就是汇合所有的应用的音频输入,合成一个音频流再输入hal层。故而android应用想要播放生音,就需要通过跨进程的方式将自己的pcm数据传递给AudioFlinger,由AudioFlinger汇合,AudioFlinger顺便在汇合的时候可以根据需要做一个音效处理,然后输出给对应的hal层设备。
当然,如果我们应用不想这么做,而是想直接自行通过hal层输出数据,也是可以的,只要你能访问到hal层接口,有足够的权限,那就不走AudioFlinger中间商,当然也就没办法享用到AudiFlinger提供的增值服务比如音效。
要说明的是,输入给AudioFlinger的数据也不全是经过解码的pcm数据,有些特殊的设备它可以直接自己解码特殊格式的音频,这些音频数据就不能被AudioFlinger进行混合,AudioFlinger对这些数据就不会处理,直接交给对应的dsp设备,这算是特殊通道,这样的数据流类型被标记为offload 顾名思义就是包袱,打包的数据,一般用于dsp硬件解码的流数据
详细参考:
《4. 待补充blog AudioFlinger 混音及线程模型分析》
《4. Android native层直接使用AudioFlinger播放pcm》
5.0 完整的对外接口 AudioSystem.cpp
到此已经完全具备完整的音频能力了,如果是开发一个c++的程序,完全可以使用AudioPolicyServe 和AudioFlingerServer 的接口,从AudioPolicy获取到合适的输出设备,然后把pcm数据给到AudioFlinger让其帮忙播放。这个AudioSystem正是对内部AudioPolicyServe 和AudioFlingerServer的接口的一个外壳包装,让它门两个看起来成为一个整体,已经具备完整的音频能力,取名System也无可厚非。
6.0 换壳java形似的对外接口AudioSystem.java
为了给java使用,同样再换了个外壳,AudioSystem.java ,AudioSystem.java的作用就完全是为了通过java ->jni-> cpp了。没什么逻辑,只是个桥梁。
7.0 java层的服务供应AudioService.java
如何让应用层使用到AudioSystem.java? Android还是不想直接将AudioSystem的接口暴露给应用,毕竟还涉及到权限管理,音量的控制,焦点的控制等等,这些逻辑就都被放在了java sdk层统一处理,所以从java 层面来看,android 将音频相关的控制,都放在了 AudioService.java 可以说这是android 音频java 层的大本营, 由它来唯一和AudioSystem同底层控制交互。(也不完全是唯一和AudioSystem交互的模块,比如AudioManager在列举所有音频设备时,没有经过AudioService.java ,而是直接调用的AudioSystem.java. 但是总的设计上的思想,应该是都要经过AudioService的)
AudioService.java 源码有相关的注释:
The implementation of the audio service for volume, audio focus, device management...
详细参考《7. 待后续补充blog AudioService 如何同AudioManager AudioSystem关联》
8.0 应用层的一对一服务AudioManager
为了更加方便应用层的使用,AudioService.java 服务为每一个应用派遣了一个一对一的接待AudioManager 。 每一个应用可以申请到一个只为自己服务的AudioManager对象。 但是AudioManager 的实际业务基本上是去跨进程调用AudioService服务, 应用获得AudioManager对象也是通过getSystemService(Context.AUDIO_SERVICE) 得到。
9.0 为了支持和兼容多音频设备的car, 提供的动态策略。
原来的android只是用于音频固件相对比较少的手机,一般只有 扬声器、听筒、有线耳机和蓝牙耳机,以及虚拟的用于无线投屏远程播放的 REMOTE_SUBMIX。 应用层只需要表明音频流的类型,由AudioPolicy来决定该流类型应该使用具体是扬声器设备还是听筒设备,这个AudioPolicy就提自定义策略的实现,由Android设备制作厂家来定制自己的策略,当然这个策略是在 底层AudioPolicy内部的。 对于音频输出设备比较多的car 而言,动不动就6个到10个的喇叭,光靠几个流类型显得不太够用,并且策略完全在底层的AudioPolicy ,修改也很不灵活,于是从 Android 9 开始, 对AudioPolicy进行了修改, 他定义了一个策略的接口 AudioMix ,可以由外部实现,然后注册进来覆盖原来的传统策略模式,这个外部策略甚至可以更加灵活,一直对外暴露到AudioSystem -> AudioService.java->AudioManager.java . 在java层这个策略的定义为AudioPolicy.java 。
这样连应用层都可以使用AudioManager.java来定义注册自己的AudioPolicy,这就是动态音频策略。当没有app来注册动态策略的时候,系统默认就使用传统的内置在AudioPolicy的策略。当有应用向系统注册了音频策略的时候,就优先使用注册的动态外部策略。当然并不是所有的应用都能随意注册,需要SystemApi级别, 需要android.Manifest.permission.MODIFY_AUDIO_ROUTING权限。
于是对于传统的手机,可以默认使用原来的策略,对于汽车,只需要外挂一个系统级别的app,即源码中的 packages/services/Car 然后在里面实现自己的AudioPolicy ,用AudioManager.registerAudioPolicy注入即可。
详细参考《 9. 待后续补充blog android 动态音频策略的原理》
10.0 CarAudioService CarAudioManager
这就是对于car 设备,外挂的系统级别app, 在应用层 java 实现了定制的音频策略,比如多音区.
安卓中很多这种manager+service的结构,类似于AudioManager+AudioService的结构,就像我们在8.0 AudioManager中提到的那样, manager是给应用层一对一专门服务的接待对象,而manager内部实现则是经过统一的跨进程到service中去完成功能。
详细参考:《10. 待后续补充 blog android CarAudio》
11.0 AudioTrack OpenslEs AAudio
以上全部在讨论关于设备的选择策略,音量的控制等等,对于应用如何把pcm数据流交给系统,就需要看AudioTrack了。
Aaudiotrack:
Track原本的意思,是轨迹,轨道,这个名词在安卓系统中有多处使用。 在AudioFlinger中, 每一路音频输入,都是一个 track. 这个就是AudioFlinger 内部创建的track, 为了让外部应用层可以访问到,于是专门抽象出一个类AudioTrack.cpp (为了方便区分是java还是c++ 故意在对象后面加上后缀名), 专门负责和AudioFlinger内部的track进行流数据的拷贝交互。 AudioTrack.cpp 负责直接和AudioFlinger进行流数据的交互, 它不负责具体使用那个音频设备。 它被暴露给应用层,也就是java层的AudioTrack.java , app 可以用AudioTrack来输出一个音频流到AudioFlinger. 然后AudioFlinger将其输送到具体的音频输出设备。
native层为了配合媒体播放,利用AudioTrack.cpp 的接口编写了一个TrackPlayer,让他符合plaer播放器的特性。
《11. Android native层使用TrackPlayer播放pcm》
opensl:
同时为了支持opensl 这套公共api标准, 又基于TrackPlayer 实现了Wilhelm project这个工程,所以android 上使用 opensl 实际上就是通过native层的AudioTrack 来和AudioFlinger交互数据流。 至于opensles 相对于AudioTrack.java的性能提升,其实就是少了一层从java 到 native的拷贝延时,两者最后都会通过AudioTrack.cpp -> AudioFlinger -> hal
AAudio:
其实就是Android Audio的缩写,android 在java层提供了AudioTrack.java 这个api,但是在native层却没有相应的独立API, 而对 opensles 的支持只是为了适应一套通用规范的接口,并不能提供一些android 自己特性的音频接口,于是在Android O(8.0版本,API-26 ) 版本中引入的全新 Android C API , 取名AAudio (Android Audio) 其中还支持 mmap通路,内存映射的方式直接通到内核层,以减少拷贝,降低延迟。
详细参考:
《11. Android native层使用TrackPlayer播放pcm_》
《11. 有待补充 blog android opensl 源码原理分析》
《11. 有待补充 blog android AAudio分析》
12.0 oboe 库
为了简化调用流程,自动选择是使用 opensl 还是AAudio (毕竟在低于8.0的设备上是没有AAudio的支持的),谷歌整合了一个c++ 库,叫做oboe, 目前是以第三方库的方式提供,应用层可以嵌入使用,相比于opensl 确实调用起来简洁多了。
官方源码 https://github.com/google/oboe
Oboe audio library | Android Developers (google.cn)
读源码不容易! 码字更是费时费力! 原创!!!发扬共享精神!
<一>Android Audio音频框架相关推荐
- Android Audio音频通路(七)
android audio 生产者与消费者 简介 全面接触生产者/消费者问题是在操作系统原理中,并发性原理讨论的问题 生产者/消费者问题.最近的工作偏向音频,接着上一篇文章,用生产者,消费者模型来理解 ...
- Android Audio 音频输出设备切换
扬声器输出和耳机输出是音频系统最基本的音频输出通路,实际应用中用户可根据自己需要随意切换,具体表现是通过插入耳机选择耳机输出,拔出耳机选择默认的扬声器输出. 如图5-13所示,扬声器与耳机输出切换的实 ...
- Android Audio 音频路由
一.在 AudioPolicyService 中,选择音频路由时会从当前音频流的类型获取音频的路由策略: /frameworks/av/services/audiopolicy/managerdefa ...
- 【Android】Audio音频输出通道切换 - 蓝牙bluetooth、外放
参考: [Android]Audio音频输出通道切换 - 蓝牙.外放 Android Audio 音频输出通道切换 为什么 iOS 或 Android 设备连接蓝牙设备后不能通过蓝牙设备接电话? xq ...
- Android Audio - 支持多个APK同时录音
Android Audio - 支持多个APK同时录音 原理说明 Android4.4 修改方法 Android5.1 & 6.0 修改方法 Android8.1 修改方法 Android9. ...
- Android Audio - 支持多应用同时录音_Android8.1修改方法
支持多应用同时录音_Android8.1修改方法 修改方法 与之相关 修改方法 源码路径: sdk\frameworks\av\services\audiopolicy\managerdefault\ ...
- Android audio音频流数据异常问题分析
一.背景 在 Android 系统的开发过程当中,音频异常问题通常有如下几类,无声,调节不了声音,爆音,声音卡顿,声音效果异常(忽大忽小,低音缺失等)等.尤其声音效果这部分问题通常从日志上信息量较少, ...
- Android音频框架笔记 - 下篇
原址 六.HAL层 6-1.Audio HAL层,其实包括了audio.xxx.so 和 audiopolicy.so等.从前述的总框架图,也有写,代码库路径也有写. 具体运行时so对象图,对于aud ...
- Android音频框架笔记 - 上篇
原址 一.音频数字化基础知识 见书,列出知识点如下: 声音 声波,声音频率.响度, 音调.音色. 音响设备中的声道 得翻翻初高中的课本了. 声音数字化过程 声源 -> mic -> ADC ...
最新文章
- 20165235实验四 Android程序设计
- iOS打包framework - Swift完整项目打包Framework,嵌入OC项目使用
- OneNote2016安装代码高亮插件-NoteHightlight
- [codevs 3273] 两圆的交
- PADS 非常用操作 备忘
- python 对象转dict_如何将python dict对象转换为java等效对象?
- win7域内桌面黑屏
- 德国软件巨头SAP旗下风投基金募集10亿美元 专门投资科技初创公司
- Linux内核多线程(二)
- idm下载器怎么下载网页视频?如何用idm自动下载网站文件?
- visual C#(二十五)实现UWP应用的用户界面
- 从WinMain函数看Windows程序内部运行机制
- word中如何将空格变成换行
- Windows 10 build Error !include: could not find: ****StdUtils.nsh
- EasyCVR出现只有HLS协议可播放,其他协议均无法播放是什么原因?
- SFTP命令常用操作
- matlab土方计算,土方量计算的MATLAB工具箱研制
- 【PPP概念股龙头】PPP再迎风口 相关概念股表现格外抢眼(2)
- 计算机基础与office应用考试专题,一级考试计算机基础及WPS Office应用模拟题
- 投资理念研究分析报告