7.3.2 通过流程分析AudioFlinger
最后更新于:2022-04-02 05:51:30
图7-5中说明的AT和AF交互的流程,对于分析AF来说非常重要。先来回顾一下图7-5的流程:
- AT调用createTrack,得到一个IAudioTrack对象。
- AT调用IAudioTrack对象的start,表示准备写数据了。
- AT通过write写数据,这个过程和audio_track_cblk_t有着密切关系。
- 最后AT调用IAudioTrack的stop或delete IAudioTrack结束工作。
至此,上面的每一步都很清楚了。根据Binder知识,AT调用的这些函数最终都会在AF端得到实现,所以可直接从AF端开始。
1. createTrack的分析
按照前面的流程步骤,第一个被调用的函数会是createTrack,请注意在用例中传的参数。
**AudioFlinger.cpp**
~~~
sp
AudioFlinger::createTrack(
pid_t pid,//AT的pid号
int streamType,//流类型,用例中是MUSIC类型
uint32_t sampleRate,//8000 采样率
int format,//PCM_16类型
int channelCount,//2,双声道
int frameCount,//需要创建缓冲的大小,以帧为单位
uint32_t flags,
const sp& sharedBuffer,//AT传入的共享buffer,这里为空
int output,//这个值前面提到过,是AF中的工作线程索引号
status_t *status)
{
sp track;
sp trackHandle;
sp client;
wpwclient;
status_t lStatus;
{
Mutex::Autolock _l(mLock);
//output代表索引号,这里根据索引号找到一个工作线程,它是一个PlaybackThread
PlaybackThread *thread = checkPlaybackThread_l(output);
//看看这个进程是否已经是AF的Client,AF根据进程pid来标识不同的Client
wclient = mClients.valueFor(pid);
if(wclient != NULL) {
}else {
//如果还没有这个Client信息,则创建一个,并加入到mClients中去
client = new Client(this, pid);
mClients.add(pid, client);
}
//在找到的工作线程对象中创建一个Track,注意它的类型是Track
track = thread->createTrack_l(client, streamType, sampleRate, format,
channelCount, frameCount, sharedBuffer, &lStatus);
}
/*
TrackHandle是Track对象的Proxy,它支持Binder通信,而Track不支持Binder
TrackHandle所接收的请求最终会由Track处理,这是典型的Proxy模式
*/
trackHandle= new TrackHandle(track);
returntrackHandle;
}
~~~
这个函数相当复杂,主要原因之一,是其中出现了几个我们没接触过的类。我刚接触这个函数的时候,大脑也曾因看到这些眼生的东西而“死机”!不过暂时先不用去理会它们,等了解了这个函数后,再回过头来收拾它们。先进入checkPlaybackThread_l看看。
(1) 选择工作线程
checkPlaybackThread_l的代码如下所示:
**AudioFlinger.cpp**
~~~
AudioFlinger::PlaybackThread *
AudioFlinger::checkPlaybackThread_l(intoutput) const
{
PlaybackThread*thread = NULL;
//根据output的值找到对应的thread
if(mPlaybackThreads.indexOfKey(output) >= 0) {
thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
}
returnthread;
}
~~~
上面函数中传入的output,就是之前在分析AT时提到的工作线程索引号。看到这里,是否感觉有点困惑?困惑的原因可能有二:
- 目前的流程中尚没有见到创建线程的地方,但在这里确实能找到一个线程。
- Output含义到底是什么?为什么会把它作为index来找线程呢?
关于这两个问题,待会儿再做解释。现在只需知道AudioFlinger会创建几个工作线程,AT会找到对应的工作线程即可。
(2) createTrack_l的分析
找到工作线程后,会执行createTrack_l函数,请看这个函数的作用:
**AudioFlinger.cpp**
~~~
// Android的很多代码都采用了内部类的方式进行封装,看习惯就好了
sp
AudioFlinger::PlaybackThread::createTrack_l(
const sp& client,int streamType,
uint32_tsampleRate,int format,int channelCount,int frameCount,
const sp& sharedBuffer,//注意这个参数,从AT中传入,为0
status_t *status)
{
sp
';