本文主要围绕以下几点来说明
- audiopatchd的概念以及相关应用场景
- audiopatch 在应用层的使用
- 框架中audiopatch的流程
- hal中audiopatch的流程
audiopatch的概念和使用场景
patch顾名思义路径,audiopatch就是构建一条声音流的路径。为什么要有这样的一条路径?
可以从两个方面考虑
-
降低音频数据的传输延时,比如一个场景耳返也就是录音的数据(麦克分收音)需要重新播放的耳机里面。 假设框架里面没有一条从录音直接到放音的路径,那么数据需要从框架录制到应用,然后从应用重新拷贝到播放,而有了audiopatch之后 框架里面就可以直接将录音的数据写到输出设备了。
-
支持外部设备的放音,比如FM收音机,声音从FM设备进来 可以通过hal层建立的patch,直接输出到设备中。
在audioflinger 中每种情况路径连接都可以定义为一个patch 路径。
audiopatch 在应用层的使用
代码位置:packages/services/Car/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/CarAudioZoneInputFragment.java
-
在AAOS的kitchensink测试项中的CarAudioZoneInpuFragment有使用patch来创建录音到播放的路径:
int result = AudioManager.createAudioPatch(patch, new AudioPortConfig[] { sourceConfig }, new AudioPortConfig[] { sinkConfig });
-
首先调用carAudioService的createAudioPatch,传递的是录音设备的地址和播放的usage media、其中录音设备的地址 也就是patch 中的source设备是作为输入,而patch中的sink 输出只要根据usage找到可以播的sink设备即可。
-
CarAudioService 需要根据sourceAddress构建 AudioPortConfig sinkConfig 和sourceConfig,这两个Config都是通过audioPolicyManager的getDevice返回的结构体中通过address/usage进行筛选构建的的,然后调用AudioManager的createAudioPatch 。
-
AudioMannger中会调用AudioSystem的createAudioPatch,这个通过jni调用,在jni 中会把sinkConfig 和 sourceConfig转换为path结构体中的sources 和sinks,并传递的handle指针。
-
AudioSystem会通过binder一路调用到AudioPolicyMangaer的createAudioPatchInternal
AudioPolicyMangaer会调用到patchPanel的createAudioPatch,在这边会为sink创建playthread 为source创建recordthread。同时为这两个线程创建软件bridge -
软件的bridge创建好之后 就调用track start 将track 启动,也就构造了一个录音设备录制的声音会写入到播放设备的路径的测试。
</
-