1.1.1 PlaybackThread的循环主体
当一个PlaybackThread进入主循环后(threadLoop),音频事务就正式开启了。仔细观察的话,我们会发现这个循环中会不断地调用以“threadLoop_”开头的若干接口,比如threadLoop_mix、threadLoop_sleepTime、threadLoop_standby等等。以这样的前缀开头,是因为这些函数都是在threadLoop这个主体里被调用的,可以说代表了这个PlaybackThread所需要完成的各个操作步骤。
从上一小节可以了解到,当程序执行到PlaybackThread::onFirstRef时会去真正启动一个线程承载运行threadLoop,接下来我们具体看下这个循环体的处理流程。
bool AudioFlinger::PlaybackThread::threadLoop()
{ …
while (!exitPending())/*Step1.*/
{ …
processConfigEvents();/*Step 2. */
{ /*把这段代码框起来的目的是限制自动锁变量_l的生命期,
从而灵活地实现了自动锁的控制范围*/
Mutex::Autolock _l(mLock);
…
/*Step 3. Standby判断*/
if(CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime)|| mSuspended> 0)) {
if (!mStandby){
threadLoop_standby();//调用设备的
mStandby =true;
mBytesWritten = 0;
}
…
}
/*Step 4.*/
mMixerStatus =prepareTracks_l(&tracksToRemove);
…
}
/*Step5.*/
if(CC_LIKELY(mMixerStatus == MIXER_TRACKS_READY)) {
threadLoop_mix();
} else {
threadLoop_sleepTime();
}
…
/*Step 6.*/
if (sleepTime == 0) {
threadLoop_write(); //不需要休眠,有数据要写
…
mStandby = false;
} else {
usleep(sleepTime);//进入休眠,时间长短是sleepTime
}
/*Step 7.*/
threadLoop_removeTracks(tracksToRemove);//移除相关Track
tracksToRemove.clear();…
}//while (!exitPending())结束
…
releaseWakeLock();
return false;
}
Step1@ PlaybackThread::threadLoop, 循环的条件是!exitPending()为true。这个函数属于Thread类,它主要通过判断内部变量mExitP