Android 7.0 Audio: AudioFlinger介绍和初始
http://blog.csdn.net/xiashaohua/article/details/53818568
frameworks/av/services/audioflinger/Threads.cpp:3027:status_t AudioFlinger::PlaybackThread
frameworks/av/services/audioflinger/Tracks.cpp:879:void AudioFlinger::PlaybackThread::Track AudioFlinger::ThreadBase::TrackBase
http://blog.csdn.net/droidphone/article/details/5951999
- PlaybackTread::Track // 用于普通播放,对应于应用层的AudioTrack
- PlaybackThread::OutputTrack // 用于多重设备输出,当蓝牙播放开启时使用
- RecordThread::RecordTrack // 用于录音,对应于应用层的AudioRecord
默认的播放线程是MixerThread,DuplicatingThread,它是MixerThread的子类。当系统中有两个设备要同时输出时,DuplicatingThread将被创建
Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合(Mixer),然后输送到AudioHardware中进行播放,目前Android的Froyo版本设定了同时最多可以创建32个音频流,也就是说,Mixer最多会同时处理32个AudioTrack的数据流
实际上,创建DuplicatingThread的工作是有AudioPolicyService中的AudioPolicyManager里发起的。主要是当蓝牙耳机和本机输出都开启时,AudioPolicyManager会做出以下动作:
- 首先打开(或创建)蓝牙输出线程A2dpOutput
- 以HardwareOutput和A2dpOutput作为参数,调用openDuplicateOutput,创建DuplicatingThread
- 把属于STRATEGY_MEDIA类型的Track移到A2dpOutput中
- 把属于STRATEGY_DTMF类型的Track移到A2dpOutput中
- 把属于STRATEGY_SONIFICATION类型的Track移到DuplicateOutput中
结果是,音乐和DTMF只会在蓝牙耳机中输出,而按键音和铃声等提示音会同时在本机和蓝牙耳机中输出。
图三 本机播放时的Thread和Track
图四 蓝牙播放时的Thread和Track
建立联系的过程
下面的序列图展示了AudioTrack和AudioFlinger建立联系的过程:
图二 AudioTrack和AudioFlinger建立联系
解释一下过程:
- Framework或者Java层通过JNI,new AudioTrack();
- 根据StreamType等参数,通过一系列的调用getOutput();
- 如有必要,AudioFlinger根据StreamType打开不同硬件设备;
- AudioFlinger为该输出设备创建混音线程: MixerThread(),并把该线程的id作为getOutput()的返回值返回给AudioTrack;
- AudioTrack通过binder机制调用AudioFlinger的createTrack();
- AudioFlinger注册该AudioTrack到MixerThread中;
- AudioFlinger创建一个用于控制的TrackHandle,并以IAudioTrack这一接口作为createTrack()的返回值;
- AudioTrack通过IAudioTrack接口,得到在AudioFlinger中创建的FIFO(audio_track_cblk_t);
- AudioTrack创建自己的监控线程:AudioTrackThread;
自此,AudioTrack建立了和AudioFlinger的全部联系工作,接下来,AudioTrack可以:
- 通过IAudioTrack接口控制该音轨的状态,例如start,stop,pause等等;
- 通过对FIFO的写入,实现连续的音频播放;
- 监控线程监控事件的发生,并通过audioCallback回调函数与用户程序进行交互;
AudioFlinger.cpp
loadHwModule_l();//加载HAL模块{
audio_hw_device_t *dev;
int rc = load_audio_interface(name, &dev);
mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));//dev ==> AudioHwDevice->hwDevice();
}
load_audio_interface(){
hw_get_module_by_class
audio_hw_device_open;//初始化输出设备
}
openOutput_l();//打开输出设备{
AudioHwDevice->openOutputStream();
}
AudioStreamOut.cpp
open();{
hwDev()->open_output_stream();//hwDev() <== AudioHwDevice->hwDevice();
}
HAL: hardware/libhardware/Hardware.c
hw_get_module_by_class
hardware/xxx/audio/hal/Android.mk:259:LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
03-13 10:53:10.662 515 515 I AudioFlinger: loadHwModule() Loaded primary audio interface from xxx Audio HAL (audio) handle 10
03-13 10:53:10.800 515 515 I bt_a2dp_hw: adev_open: adev_open in A2dp_hw module
03-13 10:53:10.800 515 515 I AudioFlinger: loadHwModule() Loaded a2dp audio interface from A2DP Audio HW HAL (audio) handle 18
03-13 10:53:10.805 515 515 I AudioFlinger: loadHwModule() Loaded usb audio interface from USB audio HW HAL (audio) handle 26
03-13 10:53:10.808 515 515 I r_submix: adev_open(name=audio_hw_if)
03-13 10:53:10.809 515 515 I r_submix: adev_init_check()
03-13 10:53:10.809 515 515 I AudioFlinger: loadHwModule() Loaded r_submix audio interface from Wifi Display audio HAL (audio) handle 34
03-13 11:43:20.291 519 519 E AudioFlinger: int android::load_audio_interface(const char *, audio_hw_device_t **) couldn't load audio hw module audio.primary (Success)
03-13 11:43:20.903 519 519 E AudioFlinger: int android::load_audio_interface(const char *, audio_hw_device_t **) couldn't load audio hw module audio.a2dp (Success)
03-13 11:43:20.903 519 519 I bt_a2dp_hw: adev_open: adev_open in A2dp_hw module
03-13 11:43:20.903 519 519 I AudioFlinger: loadHwModule() Loaded a2dp audio interface from A2DP Audio HW HAL (audio) handle 18
03-13 11:43:20.908 519 519 E AudioFlinger: int android::load_audio_interface(const char *, audio_hw_device_t **) couldn't load audio hw module audio.usb (Success)
03-13 11:43:20.908 519 519 I AudioFlinger: loadHwModule() Loaded usb audio interface from USB audio HW HAL (audio) handle 26
03-13 11:43:20.923 519 519 E AudioFlinger: int android::load_audio_interface(const char *, audio_hw_device_t **) couldn't load audio hw module audio.r_submix (Success)
audio_hw_device_t **dev struct audio_hw_device** device
hardware\libhardware\include\hardware\audio.h
/** convenience API for opening and closing a supported device */
static inline int audio_hw_device_open(const struct hw_module_t* module,
struct audio_hw_device** device)
{
return module->methods->open(module, AUDIO_HARDWARE_INTERFACE,
(struct hw_device_t**)device);
}
hardware/xxx/audio/hal/audio_hw.c
static struct hw_module_methods_t hal_module_methods = {
.open = adev_open,
};
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = AUDIO_MODULE_API_VERSION_0_1,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "xxx Audio HAL",
.author = "The Linux Foundation",
.methods = &hal_module_methods,
},
};
hardware/xxx/audio/hal/audio_extn/a2dp.c
hardware/libhardware/modules/usbaudio/audio_hal.c
static struct hw_module_methods_t hal_module_methods = {
.open = adev_open,
};
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = AUDIO_MODULE_API_VERSION_0_1,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "USB audio HW HAL",
.author = "The Android Open Source Project",
.methods = &hal_module_methods,
},
};
hardware/libhardware/modules/audio_remote_submix/audio_hw.cpp
static struct hw_module_methods_t hal_module_methods = {
/* open */ adev_open,
};
struct audio_module HAL_MODULE_INFO_SYM = {
/* common */ {
/* tag */ HARDWARE_MODULE_TAG,
/* module_api_version */ AUDIO_MODULE_API_VERSION_0_1,
/* hal_api_version */ HARDWARE_HAL_API_VERSION,
/* id */ AUDIO_HARDWARE_MODULE_ID,
/* name */ "Wifi Display audio HAL",
/* author */ "The Android Open Source Project",
/* methods */ &hal_module_methods,
/* dso */ NULL,
/* reserved */ { 0 },
},
};