应用程序创建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_tif (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 buffersif (buffer == NULL) {//由AudioFlinger申请的共享内存mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);//要加上audio_track_cblk_t,才是指向的真实buffermemset(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 proxyif (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 来管理这块内存。