一.音频总体的架构:

二.Audio Policy
•
Stream
类型选择合适的
device :
•
音频管理策略管理音频的输入输出,它
决定各种类型的声音优先送往系统哪个输
出设备,或使用哪个输入设备进行采样。
•
比如,如果有蓝牙耳机或者耳机,将优
先使用他们作为输入输出设备。
•
创建
AudioTrack
的时候会传入一个
Stream
类型,根据这个类型获得
strategy,
然后根据
strategy
获得一个
device。

•
Stream
类型选择合适的
Strategy
类型
:
•
第一栏是流的类型,第二栏是音频策略
•
从表中可以看出,某些流可以使用相同
的音频策略进行输入或者输出。

•
Strategy
类型选择合适的
device :
•
第一栏是
Strategy
的类型,第二栏是
device
。
•
按照一定的优先级顺序,检查哪些可用的输入
输出设备,然后选择一个设备用来输入输出。

三.
Audio
使用
•
比如音乐播放器,录音机
APK
进行录音或播放。
•
播放声音能够用
MediaPlayer
和
AudioTrack
,
MediaRecorder
和
AudioRecord
进行录音。
•
MediaPlayer
在
framework
层还是会创建
AudioTrack
,
把解码后的
PCM
数流传递给
AudioTrack。AudioTrack
再传递给
AudioFlinger
进行混音,然后才传递给硬件播放
,
所以是
MediaPlayer
包括了
AudioTrack
。
四.
Audio播放流程
•
Android
的播放架构图

•播放流程一般分为三个部分:
1.
AudioTrack
构造;
•Framework或者APP层通过JNI创建AudioTrack (JAVA)对象;
•调用到android_media_AudioRecord_setup(JNI),然后创建一个AudioRecord(C++);
•AudioRecord(C++)会调用getOutputForAttr,这个函数会调用到AudioPolicy,根据策略选择输出设备;
•AudioTrack(C++)通过binder机制调用AudioFlinger的createTrack()创建Track,同时分配共享内存。
•AudioFlinger拥有多个工作线程,每一个线程拥有多个Track。
•每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合(Mixer),然后输送到AudioHardware中进行播放。
目前Android同时最多可以创建32个音频流,也就是说,Mixer最多会同时处理32个AudioTrack
的数据流
2.
AudioTrack
的
Start
;
•
Framework
或者
APP
层调用
AudioTrack(java)
的
play()
进行音频播放的准备
;
•
play()
会调用
jni
的
native_start
(),
对应的函数是
android_media_AudioTrack_start();
•
android_media_AudioTrack_start
()
只是做了转发,最后会调用
AudioTrack
(C++)
的
start();
•
AudioTrack
的
start()
进过转发
,
最后会调用
PlaybackThread
的
start();
•
PlaybackThread
的
start()
的又会调用
addTrack_l();
•
PlaybackTread
的
addTrack_l
主要工作是添加
track
到
mActiveTracks,
并激活沉睡的
PlaybackTread
线程
。

3.
AudioTrack
的
Write
。
•
Framework
或者
APP
层调用
AudioTrack(java)
的
AudioTrack(java)
的
write()
写入音频数据
;
•
调用
jni
的
android_media_AudioTrack_write_byte()
,主要是获取
java
传下来的数据,并调用
writeToTrack()
来向共享内存写入数据
;
•
writeToTrack
()
调用
AudioTrack(c++)
的
write()
,
AudioTrack(C++)
会使用
obtainBuffer
获取一块共享内存, 并写入数据,写完后用
releaseBuffer
释放共享内存。
•
服务端读取共享内存的音频数据是在
PlaybackThread
的
threadLoop()
中进行的,调用
threadLoop_mix()
进行混音
;
•
完成混音后,调用
threadLoop_write
(),
它会调用
mOutput->stream->write()
写入,这里会调用到
HAL
层
;
•
HAL
层的调用
tiny_alsa
的
pcm_open()
打开相应的录音设备,再通过
pcm_write()
写入音频数据到
linux
系统,再到硬件。
四.Audio录音流程
•Android的录音架构图

1.
AudioRecord
构造过程
:
•
Framework
或者
APP
层通过
JNI
创建
AudioRecord (JAVA)
对象
;
•
调用到
android_media_AudioRecord_setup(JNI),
然后创建一个
AudioRecord(C++);
•
AudioRecord
会通过
AudioSystem::getInputForAttr
,这个函数会调用到
AudioPolicy
,根据策略选择输出设备
;
•
AudioRecord
通过
binder
机制调用
AudioFlinger
的
createRecordTrack_l()
创建
RecordTrack
,同时分配共享内存
。
2.
AudioRecord
的
Start :
•
Framework
或者
APP
层调用
AudioTrack(java)
的
startRecording()
进行音频播放的准备
;
•
startRecording()
会调用
jni
的
native_start(),
对应的函数是
android_media_AudioRecord_start();
•
android_media_AudioRecord_start()
只是做了转发,最后会调用
AudioRecord(c++)
的
start();
•
AudioRecord
的
start
又会调用
TrackHandle(
服务端的
Track
代理
)
的
start,
最后会调用到
RecordThread
的
start();
•
RecordThread
的
start()
会激活沉睡的
RecordThread 。
3.
AudioRecord
的
Read :
•
Framework
或者
APP
层调用
AudioRecord(java)
的
AudioTrack(java)
的
read
读取音频数据
;
•
调用
jni
的
android_media_AudioRecord_readInByteArray
,调用
AudioTrack(c++)
的
read
读取数据
;
•
AudioTrack(C++)
会使用
obtainBuffer
获取一块共享内存, 并读取数据
;
•
服务端读取共享内存的音频数据是在
RecordThread
的
threadLoop()
中进行
;
•
调用
mInput->stream->read
读取,这里会调用到
HAL
层
;
•
HAL
层的调用
tiny_alsa
的
pcm_open
打开设备,然后通过
pcm_read()
读取相应设备数据。