应用程序创建AudioTrack时,导致AudioFlinger在播放线程中,创建Track和其对应。那它们之间是通过什么来建立联系传递数据的?答案是共享内存。
创建Track时,导致其父类TrackBase的构造函数被调用
//frameworks/av/services/audioflinger/Tracks.cpp
AudioFlinger::ThreadBase::TrackBase::TrackBase(/*省略*/){
//省略
size_t size = sizeof(audio_track_cblk_t);//大小为audio_track_cblk_t
if (buffer == NULL && alloc == ALLOC_CBLK) {//如果客户端没有申请过共享内存
//省略
size += bufferSize;//大小要加上buffer的大小
}
/*开始申请了*/
if (client != 0) {
mCblkMemory = client->heap()->allocate(size);
if (mCblkMemory == 0 ||
(mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
//省略
return;
}
} else {
mCblk = (audio_track_cblk_t *) malloc(size);
//省略
}
if (mCblk != NULL) {
new(mCblk) audio_track_cblk_t();
switch (alloc) {
//省略
case ALLOC_CBLK:
// clear all buffers
if (buffer == NULL) {//由AudioFlinger申请的共享内存
mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);//要加上audio_track_cblk_t,才是指向的真实buffer
memset(mBuffer, 0, bufferSize);
} else {
mBuffer = buffer;//由客户端申请的内存,mBuffer 直接指向它
}
break;
}
}
}
可以看出,共享内存可以由客户端申请,也可以由AudioFlinger申请。
客户端已经申请了buffer:
AudioFlinger这边,只会申请audio_track_cblk_t头部信息,不会再去申请buffer了,而是直接将mBuffer 指向客户端申请的buffer
客户端没有申请buffer:
AudioFlinger这边除了申请audio_track_cblk_t外,还会去申请buffer,并且将mBuffer 指向自己申请的这块buffer
管理共享内存
共享内存创建好之后,客户端和AudioFlinger都需要管理这块内存。AudioFlinger通过mServerProxy来管理
//frameworks/av/services/audioflinger/Tracks.cpp
if (sharedBuffer == 0) {
mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
mFrameSize, !isExternalTrack(), sampleRate);
} else {
mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
mFrameSize, sampleRate);
}
mServerProxy = mAudioTrackServerProxy;
对于是客户端创建的内存,使用 StaticAudioTrackServerProxy 来管理,对于AudioFlinger创建的内存,使用AudioTrackServerProxy来管理。
客户端通过mProxy来管理
//frameworks/av/media/libaudioclient/AudioTrack.cpp
//省略
sp<IMemory> iMem = track->getCblk();//获取内存地址,包含了audio_track_cblk_t头部地址
void *iMemPointer = iMem->unsecurePointer();//指向它
audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
mCblk = cblk;
void* buffers;
if (mSharedBuffer == 0) {//AudioFlinger申请的内存
buffers = cblk + 1;//指向buffer
} else {
buffers = mSharedBuffer->unsecurePointer();
}
// update proxy
if (mSharedBuffer == 0) {
mStaticProxy.clear();
mProxy = new AudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
} else {
mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
mProxy = mStaticProxy;
}
对于是客户端创建的内存,客户端使用 StaticAudioTrackClientProxy来管理,对于AudioFlinger创建的内存,使用AudioTrackClientProxy来管理。
总结
AudioTrack和Track之间通过共享内存来建立联系,这个内存可以由客户端的AudioTrack创建,也可以由AudioFlinger的Track创建。但是audio_track_cblk_t一定是由Track创建的。客户端和AudioFlinger分别通过mProxy 和mServerProxy 来管理这块内存。