Skip to main content
 首页 » 编程设计

Android音频(5)——框架中的概念和涉及的文件

2022年07月19日22lonelyxmas

一、涉及的概念


1. 概念output
(1) 一个output对应一个或多个设备节点,比如/dev/snd/pcmC0D0p。为了避免麻烦,一个设备节点只由一个Thread(线程)操作。
(2) 一个putput是多个device的组合(比如声卡上有喇叭(dev1)和耳机(dev2)),这些device(喇叭、耳机)属于同一个硬件上不同的端口。这些device需支持同样的参数,如采样率和通道。
(3) 一个output对一个Thread,
(4) 一个output对应一个或多个track(音轨),播放时来自多个App.
(5) 一个track对应一个AudioTrack


2. 使用Hardware Module(也称为module)来操作硬件
Hardware Module的名字是什么?这决定加载哪些动态库。Hardware Module支持哪些output?output支持哪些device,参数是什么?
以上这些在配置文件 /system/etc/audio_policy.conf 中指定


3. 概念
module: 硬件操作库,用于操作硬件
output: 一组有相同参数的来自同一硬件的device.
device: 喇叭,耳机等
这些也与配置文件 /system/etc/audio_policy.conf 有关。

4. profile和output的区别
profile: 配置,用来描述output,比如可以支持哪些设备,和参数,比如采样率,通道等信息。
output: 用于描述现在实际上可以支持哪些设备。
比如一个具有喇叭和耳机孔的声卡的profile为可以支持喇叭和耳机,但是output是接上耳机时才支持耳机。


5. App在播放音乐的时候有那么多的路径(比如播放到喇叭,耳机,蓝牙...),App怎么选择?
答:App不管这些,这是由音频系统决定的。当App要显示指定类型的声音时,它只需要使用宏表明stream type(声音类型)即可。
Java API和Native API使用的是不同的宏来指明stream type,但是它们是一一对应的,比如表示电话语音,Java中是STREAM_VOICE_CALL,Native中是AUDIO_STREAM_VOICE_CALL.
这些宏在system/core/include/system/audio.h中定义。
其中宏 AUDIO_STREAM_ENFORCED_AUDIBLE 表示强制发出声音,App不能mute它,必须发出来。比如有些国家要求拍照必须要有声音,以防止偷拍。

6. 既然有多种stream type,不方便管理,于是对他们分了组,组使用strategy表示,具有相同行为的stream被放
在同一个组中。这里的相同行为表示播放的device相同。
分组信息可以参考hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp中的getStrategy()

AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy( 
        AudioSystem::stream_type stream) { 
    // stream to strategy mapping 
    switch (stream) { 
    case AudioSystem::VOICE_CALL: 
    case AudioSystem::BLUETOOTH_SCO: 
        return STRATEGY_PHONE; 
    case AudioSystem::RING: 
    case AudioSystem::ALARM: 
        return STRATEGY_SONIFICATION; 
    case AudioSystem::NOTIFICATION: 
        return STRATEGY_SONIFICATION_RESPECTFUL; 
    case AudioSystem::DTMF: 
        return STRATEGY_DTMF; 
    default: 
        ALOGE("unknown stream type"); 
    case AudioSystem::SYSTEM: 
        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs 
        // while key clicks are played produces a poor result 
    case AudioSystem::TTS: 
    case AudioSystem::MUSIC: 
        return STRATEGY_MEDIA; 
    case AudioSystem::ENFORCED_AUDIBLE: 
        return STRATEGY_ENFORCED_AUDIBLE; 
    } 
}

7. out flag
每个output对应一个playbackthread,众多App都会把其数据丢给这个playbackthread,playbackthread就会把这些众多来源的
声音混合在一起,然后再输出出去。
有些特定的App会指定out flag为AUDIO_OUTPUT_FLAG_DIRECT,要求output不要混音,直接输出。比如输出到HDMI的声音数据可以指定这个flag。


8. 总结:
(1) Android系统里使用hardware module来访问硬件,比如声卡。声卡上有喇叭、耳机等等称为device。为了便于管理,把一个设备上具有相同参数的一组device称为output一个module能支持哪些output,一个output能支持哪些device,使用配置文件 /system/etc/audio_policy.conf 来描述。


(2) app要播放出声音,需要指定声音的类型,也就是stream type,有那么多类型,系统会先看它属于哪一类strategy(策略),根据strategy确定要用什么device(设备)播放
,如喇叭,耳机还是蓝牙。根据device确定output,由于一个output对应一个thread,进而知道对应的playbackthread, 然后把声音传给这个thread。

(3) 一个stream如何最终选择到一个device,这些stream如何互相影响(一个高优先级的声音会使其它声音静音)等等,统称为policy(政策)。主要不要搞混淆了,虽然中英文翻译policy是政策,strategy是策略,但是以后说Android音频的策略时,指的是pilicy。说strategy时,它指的是一组stream type.

二、所涉及文件如下

(1) main_mediaserver
//在这个文件中启动AudioFlinger服务和AudioPolicyService服务
frameworks/av/media/mediaserver/main_mediaserver.cpp

(2) AudioFlinger
//实现AudioFlinger Service端的Binder通信接口,onTransact(),对外提供接口如openOutput,openInput
AudioFlinger.cpp (frameworks/av/services/audioflinger/AudioFlinger.cpp)

//对每一个device都对应一个thread,这个thread就在这里面实现
Threads.cpp (frameworks/av/services/audioflinger/Threads.cpp)

//AudioFlinger中有个mTracks,用于存储应用程序发来的数据
Tracks.cpp (frameworks/av/services/audioflinger/Tracks.cpp)

//提供出来的硬件抽象层接口,厂商的HAL代码必须提供出这一套接口出来给上层使用
audio_hw_hal.cpp (hardware/libhardware_legacy/audio/Audio_hw_hal.cpp)

//这是由厂商提供的HAL文件
AudioHardware.cpp (device/friendly-arm/common/libaudio/AudioHardware.cpp)

//tinyalsa文件库中使用到的文件
Mixer.c (external/)
Pcm.c (external/)

(3) AudioPolicyService

//定义AudioPolicyService类内部使用到的函数和类
AudioPolicyService.cpp (frameworks/av/services/audiopolicy/AudioPolicyService.cpp)

//封装成对AudioFlinger的使用,也即是提供binder client接口。它是AudioFlinger的client
AudioPolicyClientImpl.cpp (frameworks/av/services/audiopolicy/AudioPolicyClientImpl.cpp)

//实现服务,实现各种服务接口函数,和binder的onTransact()
AudioPolicyInterfaceImpl.cpp(frameworks/av/services/audiopolicy/AudioPolicyInterfaceImpl.cpp)

//厂商也可以参与实现策略,这个文件制定了厂商需要遵循的规范,厂商需要继承AudioPolicyManagerBase类,重写其成员方法。
AudioPolicyManagerBase.cpp (hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp)

//旧方法:AudioPolicyManager是厂商提供的策源管理文件,它必须派生自AudioPolicyManagerBase
AudioPolicyManager.cpp (device/friendly-arm/common/libaudio/AudioPolicyManager.cpp)
AudioPolicyManager.h (device/friendly-arm/common/libaudio/AudioPolicyManager.h)

//旧方法基本上不使用了,这是新方法,系统已经实现了,厂家不需要参与策略的制定了。上面3个文件被以下文件替代
AudioPolicyManager.cpp (frameworks/av/services/audiopolicy/AudioPolicyManager.cpp)

(4) 应用程序APP所用文件:

//C++实现的App并不直接使用AudioFlinger的接口,而是使用AudioTrack.cpp中实现的接口,它里面的接口
//会通过binder与AudioFlinger服务通信
AudioTrack.cpp (frameworks/av/media/libmedia/AudioTrack.cpp)
AudioSystem.cpp (frameworks/av/media/libmedia/AudioSystem.cpp)

//Java实现的App使用AudioTrack.java中实现的接口,通过android_media_AudioTrack.cpp中实现的JNI函数
//调用到AudioTrack.cpp中实现接口。
AudioTrack.java (frameworks/base/media/java/android/media/AudioTrack.java)
android_media_AudioTrack.cpp (frameworks/base/core/jni/android_media_AudioTrack.cpp)

优秀博客:

Android系统中音频的输入输出设备

Android系统Audio框架介绍

Android 音频系统:从 AudioTrack 到 AudioFlinger


本文参考链接:https://www.cnblogs.com/hellokitty2/p/10928125.html