目录
1. AudioTrack初始化
1. 1 New AudioTrack
1. 2 Jni 函数
1.3 创建Native AudioTrack,并调用set函数
2. AudioTrack 播放
2.1 AudioTrack.java层play
2. native层调用
3. AudioTrack 写流
3.1 从java到native
3.2 native层调用
AudioTrack提供音频播放功能,从App调用AudioTrack,函数调用从java层一直到native层,从App进程,一直调到底层AudioServer进程,也会到Audio hal层,当然,也会牵扯到SystemServer进程。

图1 AudioTrack从java到native
下面就AudioTrack,从java层,一直分析到底层,看看调用是如何跟底层交互的。
1. AudioTrack初始化
1. 1 New AudioTrack
首先会new AudioTrack,AudioTrack有多个构造函数,其中有个构造函数会调用
private AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
int mode, int sessionId, boolean offload, int encapsulationMode,
@Nullable TunerConfiguration tunerConfiguration){
……
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session, 0 ,
offload, encapsulationMode, tunerConfiguration,
getCurrentOpPackageName());
}
1. 2 Jni 函数
Jni在文件frameworks\\base\\core\\jni的android_media_AudioTrack.cpp文件里,当然native_setup函数在进程启动时就已经注册,注册了static const JNINativeMethod gMethods[]函数数组,注册如下:
static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_is_direct_output_supported", "(IIIIIII)Z",
(void *)android_media_AudioTrack_is_direct_output_supported},
{"native_start", "()V", (void *)android_media_AudioTrack_start},
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
{"native_setup",
"(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
}
1.3 创建Native AudioTrack,并调用set函数
lpTrack = new AudioTrack(attributionSource);
……
status = lpTrack->set(AUDIO_STREAM_DEFAULT,…)
set 函数调用createTrack_l 函数
status_t AudioTrack::set(
audio_stream_type_t streamType,
……)
{
……
if (cbf != NULL) {
mAudioTrackThread = new AudioTrackThread(*this);
mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
// thread begins in paused state, and will not reference us until start()
}
// create the IAudioTrack
{
AutoMutex lock(mLock);
status = createTrack_l();
}
…
}
最终AudioTrack通过AudioSystem拿到AudioFlinger对象,调用AudioFlinger->CreateTrack, 再调用到AudioFlinger::PlaybackThread->CreateTrack_l函数,具体可参考图2

图2 AudioTrack初始化调用流程
2. AudioTrack 播放
2.1 AudioTrack.java层play
Play函数会调用startImpl函数,会调用native_start函数到native层。
public void play()
throws IllegalStateException {
……
try {
startImpl();
} catch (IllegalStateException e) {
……
}
}
}
2. native层调用
native_start调用mAudioTrack的start()函数,这是个binder接口,函数定义在frameworks/av/media/libmedia/IAudioTrack.aidl, 由AudioFlinger::PlaybackThread实现
status_t AudioTrack::start()
{
……
if (!(flags & CBLK_INVALID)) {
mAudioTrack->start(&status);
if (status == DEAD_OBJECT) {
flags |= CBLK_INVALID;
}
}
……
}

图3 AudioTrack play调用流程
当然PlaybackThread有子类MixerThread等,最终实现由其他子类实现。
3. AudioTrack 写流
3.1 从java到native
上述播放是控制AudioTrack进入播放状态,但实际播放是,需要喂流,在其他文章中描述过,AudioTrack可以以静态模式一次性写入,也可以按照stream方式喂流。
调用都差不多,一直调到native层
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@WriteMode int writeMode) {
……
final int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,writeMode == WRITE_BLOCKING);
……
return ret;
}
3.2 native层调用
会调用AudioTrack的Write
ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking)
{
……
while (userSize >= mFrameSize) {
audioBuffer.frameCount = userSize / mFrameSize;
status_t err = obtainBuffer(&audioBuffer,
blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);
if (err < 0) {
if (written > 0) {
break;
}
if (err == TIMED_OUT || err == -EINTR) {
err = WOULD_BLOCK;
}
return ssize_t(err);
}
size_t toWrite = audioBuffer.size;
memcpy(audioBuffer.i8, buffer, toWrite);
buffer = ((const char *) buffer) + toWrite;
userSize -= toWrite;
written += toWrite;
releaseBuffer(&audioBuffer);
}
……
}
AudioTrack::write() 从 Java 层接收音频数据后,最终将数据写入一块由 AudioFlinger 和 AudioTrack 共享的环形缓冲区(Shared Memory Ring Buffer)中。AudioFlinger 的播放线程(如 MixerThread)会从该缓冲区读取数据,混音后送入 HAL(硬件抽象层)进行播放。

图4 AudioTrack Write函数


