您的位置:首页 > 移动开发 > Android开发

Android Framework学习笔记 -- 蓝牙设备播放流程

2017-11-12 10:54 489 查看
因为蓝牙通路与其他设备不同(多了一个蓝牙设备),因此播放的流程也与其他设备略有不同。



蓝牙设备的连接

从setDeviceConnectionState开始,AudioPolicyManager先注册Device后,再去打开设备对应的output,如果是duplicating类型的话,还要建一个DuplicateOutput,关联该output与mPrimaryOutput

//--->frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name)
{
return setDeviceConnectionStateInt(device, state, device_address, device_name);
}

status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name)
{
...
sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(device, device_address, device_name);
...
// handle output devices
...
SortedVector <audio_io_handle_t> outputs;
ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
mPreviousOutputs = mOutputs;
...(注册设备)
if (index >= 0) {
sp<HwModule> module = mHwModules.getModuleForDevice(device);
if (module == 0) {
mAvailableOutputDevices.remove(devDesc);
return INVALID_OPERATION;
}
mAvailableOutputDevices[index]->attach(module);
} else {
return NO_MEMORY;
}

if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) {
mAvailableOutputDevices.remove(devDesc);
return INVALID_OPERATION;
}
...
}

status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& outputs,
const String8 address)
{
...
// 打开设备所对应的output
for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) {
sp<IOProfile> profile = profiles[profile_index];
...
status_t status = mpClientInterface->openOutput(profile->getModuleHandle(),
&output,
&config,
&desc->mDevice,
address,
&desc->mLatency,
desc->mFlags);
}
...
// 后续处理
if (output != AUDIO_IO_HANDLE_NONE) {
addOutput(output, desc);
...
else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
hasPrimaryOutput()) {
...
// open a duplicating output thread for the new output and the primary output
duplicatedOutput =
mpClientInterface->openDuplicateOutput(output,
mPrimaryOutput->mIoHandle);
...
}
}
}


openOutput的流程跟其他Output的流程是一样的,最终在AudioFlinger建立了对应Output的Thread。DuplicateOutput使用openDuplicateOutput来打开,最终也是在AudioFlinger建立一个DuplicatingThread。

//--->frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp
// AudioPolicyService的转发
audio_io_handle_t AudioPolicyService::AudioPolicyClient::openDuplicateOut
4000
put(
audio_io_handle_t output1,
audio_io_handle_t output2)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
ALOGW("%s: could not get AudioFlinger", __func__);
return 0;
}
return af->openDuplicateOutput(output1, output2);
}

//--->frameworks/av/services/audioflinger/AudioFlinger.cpp
audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
audio_io_handle_t output2)
{
// 这里两个output对应的thread都是MixerThread,意味着DuplicatingThread对应的线程是MixerThread??
Mutex::Autolock _l(mLock);
MixerThread *thread1 = checkMixerThread_l(output1);
MixerThread *thread2 = checkMixerThread_l(output2);
...

audio_io_handle_t id = nextUniqueId();
DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady);
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
return id;
}

//--->frameworks/av/services/audioflinger/Threads.cpp
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady)
:   MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->outDevice(),
systemReady, DUPLICATING),
mWaitTimeMs(UINT_MAX)
{
addOutputTrack(mainThread);
}


DuplicatingThread的addOutputTrack会创建对应thread的track(也就是生产者啦)

//--->frameworks/av/services/audioflinger/Threads.cpp
void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
{
Mutex::Autolock _l(mLock);
// The downstream MixerThread consumes thread->frameCount() amount of frames per mix pass.
// Adjust for thread->sampleRate() to determine minimum buffer frame count.
// Then triple buffer because Threads do not run synchronously and may not be clock locked.
const size_t frameCount =
3 * sourceFramesNeeded(mSampleRate, thread->frameCount(), thread->sampleRate());

sp<OutputTrack> outputTrack = new OutputTrack(thread,
this,
mSampleRate,
mFormat,
mChannelMask,
frameCount,
IPCThreadState::self()->getCallingUid());
...
}


DuplicatingThread播放

普通的连蓝牙播放(音乐,触屏音等)还不会用到DuplicatingThread,只有在需要双设备播放的情况下(如闹铃,来电等),才会用到DuplicatingThread。DuplicatingThread跟别的PlaybackThread一样,也有prepareTrack_l和mix,就是write的时候不大一样。

ssize_t AudioFlinger::DuplicatingThread::threadLoop_write()
{
// 对每个Tracks写数据 这里DuplicatingThread相当于生产者了
for (size_t i = 0; i < outputTracks.size(); i++) {
outputTracks[i]->write(mSinkBuffer, writeFrames);
}
mStandby = false;
return (ssize_t)mSinkBufferSize;
}


OutputThrack与AudioTrack类似,也是用obtainBuffer与releaseBuffer来驱动PlaybackThread

bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames)
{
...
while (waitTimeLeftMs) {
...
status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
...
memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
...
mClientProxy->releaseBuffer(&buf);

}
...
}


DuplicatingThread作用很明了,就是把一个output的流dup到其他output,这个一开始看名字就看出来了,就是不知道关联的是那个output,驱动其他两个thread的方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: