以数据为导向,分析代码,音频流程
ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t bytes)
{
// LOGV("AudioStreamOutALSA::write(%p, %u)", buffer, bytes);
status_t status = NO_INIT;
const uint8_t* p = static_cast<const uint8_t*>(buffer);
int ret;
if (mHardware == NULL) return NO_INIT;
{ // scope for the lock
AutoMutex lock(mLock);
if (mStandby) {
AutoMutex hwLock(mHardware->lock());
LOGD("AudioHardware pcm playback is exiting standby.");
acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");获得PARTIAL_WAKE_LOCK,这个锁使得CPU在此代码之后不会进入低功耗,STRONG
sp<AudioStreamInALSA> spIn = mHardware->getActiveInput_l();spIn是要写数据的指针
while (spIn != 0) {如果有数据需要写
int cnt = spIn->standbyCnt();
mHardware->lock().unlock();
// Mutex 请求顺序是 out -> in -> hw
spIn->lock();
mHardware->lock().lock();
// make sure that another thread did not change input state
// while the mutex is released
if ((spIn == mHardware->getActiveInput_l()) &&
(cnt == spIn->standbyCnt())) {强制退出
LOGV("AudioStreamOutALSA::write() force input standby");
spIn->close_l();
break;
}
spIn->unlock();
spIn = mHardware->getActiveInput_l();最后一次去获取ActiveInput,返回空,退出
}
spIn只有在仍然有活跃数据需要写,却被强制关闭情况下才不为0
在写入数据之前,先打开输出通道
open_l();
if (spIn != 0) {被强制退出
if (spIn->open_l() != NO_ERROR) {
spIn->doStandby_l();里面会释放掉PARTIAL_WAKE_LOCK
}
spIn->unlock();
}
if (mPcm == NULL) {PCM丢失?
release_wake_lock("AudioOutLock");
goto Error;
}
mStandby = false;下次不会进入while(mStandby),而直接跑到pcm_write
}
TRACE_DRIVER_IN(DRV_PCM_WRITE)
ret = pcm_write(mPcm,(void*) p, bytes);
TRACE_DRIVER_OUT
if (ret == 0) {
return bytes;返回写了多少byte数据,用于andioFlinger计算硬件sleep时间
}
LOGW("write error: %d", errno);
status = -errno;
}
Error:
standby();
// Simulate audio output timing in case of error
usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
return status;
}