sp AudioFlinger::createTrack(
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
IAudioFlinger::track_flags_t *flags,
const sp& sharedBuffer,
audio_io_handle_t output,
pid_t tid,
int *sessionId,
status_t *status)
{
sp track;
sp trackHandle;
sp client;
status_t lStatus;
int lSessionId;
// client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
// but if someone uses binder directly they could bypass that and cause us to crash
if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
ALOGE("createTrack() invalid stream type %d", streamType);
lStatus = BAD_VALUE;
goto Exit;
}
// client is responsible for conversion of 8-bit PCM to 16-bit PCM,
// and we don't yet support 8.24 or 32-bit PCM
if (audio_is_linear_pcm(format) && format != AUDIO_FORMAT_PCM_16_BIT) {
ALOGE("createTrack() invalid format %d", format);
lStatus = BAD_VALUE;
goto Exit;
}
{
Mutex::Autolock _l(mLock);
PlaybackThread *thread = checkPlaybackThread_l(output);
PlaybackThread *effectThread = NULL;
if (thread == NULL) {
ALOGE("no playback thread found for output handle %d", output);
lStatus = BAD_VALUE;
goto Exit;
}
pid_t pid = IPCThreadState::self()->getCallingPid();
client = registerPid_l(pid);
ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
//当sessionId==0时,重新生成ID,由此区分MixChain和NoramChain
//即不会出现sessionId为0的track,由此可以保留sessionId为0的MixChain保存
//auxiliary类型的effect
if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
// check if an effect chain with the same session ID is present on another
// output thread and move it here.
// 查找其它线程中中是否有相同的sessionId的Chain,将其移到本线程中
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
sp t = mPlaybackThreads.valueAt(i);
if (mPlaybackThreads.keyAt(i) != output) {
uint32_t sessions = t->hasAudioSession(*sessionId);
if (sessions & PlaybackThread::EFFECT_SESSION) {
effectThread = t.get();
break;
}
}
}
lSessionId = *sessionId;
} else {
// if no audio session id is provided, create one here
lSessionId = nextUniqueId();
if (sessionId != NULL) {
*sessionId = lSessionId;
}
}
ALOGV("createTrack() lSessionId: %d", lSessionId);
track = thread->createTrack_l(client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
// 将Chain切换到本线程中
if (lStatus == NO_ERROR && effectThread != NULL) {
Mutex::Autolock _dl(thread->mLock);
Mutex::Autolock _sl(effectThread->mLock);
moveEffectChain_l(lSessionId, effectThread, thread, true);
}
// Look for sync events awaiting for a session to be used.
for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
if (lStatus == NO_ERROR) {
(void) track->setSyncEvent(mPendingSyncEvents[i]);
} else {
mPendingSyncEvents[i]->cancel();
}
mPendingSyncEvents.removeAt(i);
i--;
}
}
}
}
if (lStatus == NO_ERROR) {
trackHandle = new TrackHandle(track);
} else {
// remove local strong reference to Client before deleting the Track so that the Client
// destructor is called by the TrackBase destructor with mLock held
client.clear();
track.clear();
}
Exit:
if (status != NULL) {
*status = lStatus;
}
return trackHandle;
}
//0、判断是否是fast track模式,来设置输入缓冲区的大小
//1、根据该thread的类型判断输入参数的合法性,
// 具体有MIXER、DIRECT、DUPLICATING、RECORD、OFFLOAD五种类型
//2、构造track,根据是否限时,分为track和timetrack,将其添加到mTracks
//3、如果获得该会话对应EffectChain的input buffer,作为track的main buffer
// 后续由track处理之后的数据交由EffectChain继续处理
//4、根据seesionId关联track与对应的EffectChain,设置track的mMainBuff
//5、如果是Fast track,发送配置event消息
sp AudioFlinger::PlaybackThread::createTrack_l(
const sp& client,
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
const sp& sharedBuffer,
int sessionId,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
int uid,
status_t *status)
{
sp