展会信息港展会大全

蓝牙耳机简单的流程分析 android开发教程
来源:互联网   发布日期:2015-09-28 16:01:40   浏览:2413次  

导读:最近在关注蓝牙耳机方面的问题,做下简单的流程分析。解码后,在AudioFlinger里把音频数据写到设备里。这里主要看看AudioFlinger,AudioPolicyManager和ext...

最近在关注蓝牙耳机方面的问题,做下简单的流程分析。

解码后,在AudioFlinger里把音频数据写到设备里。这里主要看看AudioFlinger,AudioPolicyManager和external/bluetooth/bluez/audio里面的android_audio_hw.c和liba2dp.c。

在AudioPolicyManager里有设备连接判断。

status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_devices device,

AudioSystem::device_connection_state state,

const char *device_address)

{

#ifdef WITH_A2DP

// handle A2DP device connection

if (AudioSystem::isA2dpDevice(device)) {

status_t status = handleA2dpConnection(device, device_address);//这里是执行蓝牙连接

if (status != NO_ERROR) {

mAvailableOutputDevices &= ~device;

return status;

}

} else

#endif

}

。。。。。

status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device,

const char *device_address)

{

...............

mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice,

&outputDesc->mSamplingRate,

&outputDesc->mFormat,

&outputDesc->mChannels,

&outputDesc->mLatency,

outputDesc->mFlags);

if (mA2dpOutput) {

// add A2DP output descriptor

addOutput(mA2dpOutput, outputDesc);

//TODO: configure audio effect output stage here

// set initial stream volume for A2DP device

applyStreamVolumes(mA2dpOutput, device);

if (a2dpUsedForSonification()) {

mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);

}

if (mDuplicatedOutput != 0 ||

!a2dpUsedForSonification()) {

// If both A2DP and duplicated outputs are open, send device address to A2DP hardware

// interface

AudioParameter param;

param.add(String8("a2dp_sink_address"), String8(device_address));

mpClientInterface->setParameters(mA2dpOutput, param.toString());

mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);

if (a2dpUsedForSonification()) {

// add duplicated output descriptor

AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor();

dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput);

dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput);

dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate;

dupOutputDesc->mFormat = outputDesc->mFormat;

dupOutputDesc->mChannels = outputDesc->mChannels;

dupOutputDesc->mLatency = outputDesc->mLatency;

addOutput(mDuplicatedOutput, dupOutputDesc);

applyStreamVolumes(mDuplicatedOutput, device);

}

} else {

.........

}

如果只是蓝牙播放,那么mDuplicatedOutput和a2dpUsedForSonification都为0,仅执行addOutput(mA2dpOutput, outputDesc);,走类似speaker和麦克风的流程。

如果是蓝牙和speaker或麦克风同时播放声音,走mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);注意的是,第一个参数是mA2dpOutput,蓝牙的,第二个参数是mHardwareOutput,speaker或mic等其他输出设备。

那么接下来我们去看看openDuplicateOutput函数。在AudioFlinger.cpp里有定义

int AudioFlinger::openDuplicateOutput(int output1, int output2)

{

Mutex::Autolock _l(mLock);

MixerThread *thread1 = checkMixerThread_l(output1);

MixerThread *thread2 = checkMixerThread_l(output2);

if (thread1 == NULL || thread2 == NULL) {

LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);

return 0;

}

int id = nextUniqueId();

DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);

thread->addOutputTrack(thread2);

mPlaybackThreads.add(id, thread);

// notify client processes of the new output creation

thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);

return id;

}

这个函数开启2个线程,一个是蓝牙的,另一个是mHardwareOutput,实现两者同时播放,比如来电,短信,闹铃声等。

先暂停在这里,接着

static const char *audio_interfaces[] = {

"primary",

"a2dp",

"usb",

};

4.0的代码有三种audio接口,一个是primary,是codec,我们常用的speaker,mic等;二是a2dp,是蓝牙;三是usb接口。

void AudioFlinger::onFirstRef()

{

int rc = 0;

Mutex::Autolock _l(mLock);

/* TODO: move all this work into an Init() function */

mHardwareStatus = AUDIO_HW_IDLE;

for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {

const hw_module_t *mod;

audio_hw_device_t *dev;

rc = load_audio_interface(audio_interfaces[i], &mod, &dev);//加载接口.so文件

if (rc)

continue;

LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],

mod->name, mod->id);

mAudioHwDevs.push(dev);

.........

}

这里会遍历audio接口。

void AudioFlinger::RecordThread::onFirstRef()

{

run(mName, PRIORITY_URGENT_AUDIO);

}

int AudioFlinger::openOutput(uint32_t *pDevices,

uint32_t *pSamplingRate,

uint32_t *pFormat,

uint32_t *pChannels,

uint32_t *pLatencyMs,

uint32_t flags){

......

outHwDev = findSuitableHwDev_l(*pDevices);//获取有效audio接口设备

if (outHwDev == NULL)

return 0;

//获取接口.so库里面的参数信息

status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,

&channels, &samplingRate, &outStream);

LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",

outStream,

samplingRate,

format,

channels,

status);

mHardwareStatus = AUDIO_HW_IDLE;

if (outStream != NULL) {

AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);//建立这种设备的输出

........

}

outHwDev->open_output_stream 来自蓝牙audio里的接口函数。

再看android_audio_hw.c

static int adev_open(const hw_module_t* module, const char* name,

hw_device_t** device)

{

struct adev_a2dp *adev;

int ret;

if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)

return -EINVAL;

adev = calloc(1, sizeof(struct adev_a2dp));

if (!adev)

return -ENOMEM;

adev->bt_enabled = true;

adev->suspended = false;

pthread_mutex_init(&adev->lock, NULL);

adev->output = NULL;

adev->device.common.tag = HARDWARE_DEVICE_TAG;

adev->device.common.version = 0;

adev->device.common.module = (struct hw_module_t *) module;

adev->device.common.close = adev_close;

adev->device.get_supported_devices = adev_get_supported_devices;

adev->device.init_check = adev_init_check;

adev->device.set_voice_volume = adev_set_voice_volume;

adev->device.set_master_volume = adev_set_master_volume;

adev->device.set_mode = adev_set_mode;

adev->device.set_mic_mute = adev_set_mic_mute;

adev->device.get_mic_mute = adev_get_mic_mute;

adev->device.set_parameters = adev_set_parameters;

adev->device.get_parameters = adev_get_parameters;

adev->device.get_input_buffer_size = adev_get_input_buffer_size;

adev->device.open_output_stream = adev_open_output_stream;

adev->device.close_output_stream = adev_close_output_stream;

adev->device.open_input_stream = adev_open_input_stream;

adev->device.close_input_stream = adev_close_input_stream;

adev->device.dump = adev_dump;

*device = &adev->device.common;

return 0;

err_str_parms_create:

free(adev);

return ret;

}

这样AudioFlinger里需要的参数,通过这里设定。接着蓝牙audio进行相关init,config,start,stop等状态操作。当然包括蓝牙读写。

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
推荐内容
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港