概述
这里以蓝牙耳机连接手机这一场景为例分析Audio路由策略是如何进行设备切换和管理输出的。蓝牙耳机连接上Android系统后,AudioService的handleDeviceConnection会被调用,然后调用到AudioPolicyManager的核心函数setDeviceConnectionState。
时序图
说明:连接过程的setDeviceConnectionState可以拆分为以下几个流程:
1.添加设备到mAvailableOutputDevices。
2.通知所有module有新设备连接。
3.创建dup output。
4.invalidate指定的流。
setDeviceConnectionStateInt函数
handleDeviceConnection被调用之后,从时序图可以看出AudioPolicyManager的setDeviceConnectionStateInt会被调用。这里来分析这个函数。
status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name)
{
//如果不是输入设备或者输出设备,则返回错误
if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
//mHwModules包含了所有模块的设备描述符
sp<DeviceDescriptor> devDesc =
mHwModules.getDeviceDescriptor(device, device_address, device_name);
if (audio_is_output_device(device)) {
ssize_t index = mAvailableOutputDevices.indexOf(devDesc);//很明显mAvailableOutputDevices没有这个设备,因为还没处理过
mPreviousOutputs = mOutputs;//预存ouput
switch (state)
{
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
if (index >= 0) {
//说明已经连接,而且已经处理过了
ALOGW("setDeviceConnectionState() device already connected: %x", device);
return INVALID_OPERATION;
}
index = mAvailableOutputDevices.add(devDesc); //添加到mAvailableOutputDevices中
if (index >= 0) {
//找到支持这个device的HwModule,这里会找到a2dp的module
sp<HwModule> module = mHwModules.getModuleForDevice(device);
....
mAvailableOutputDevices[index]->attach(module);//绑定module
}
//在checking output之前调用setParameters去通知所有的hardware module,有新的设备正在处理中。
//不同的hardware module会有不同的操作,比如primary module会去判断是否需要做bootcomplete。
broadcastDeviceConnectionState(device, state, devDesc->mAddress);
if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) {
mAvailableOutputDevices.remove(devDesc);
broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
devDesc->mAddress);
return INVALID_OPERATION;
}
}
}
}
}
checkOutputsForDevice是这个非常重要的函数,现在来分析这个函数的第一个阶段
status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& devDesc,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& outputs,
const String8& address)
{
......
if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
for (size_t i = 0; i < mOutputs.size(); i++) {
//查找当前的output是否能支持这个device,很明显当前的primary的,不支持a2dp的device
}
for (size_t i = 0; i < mHwModules.size(); i++){
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++){
sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
//从每一个hardware module中取出每一个profile,找到支持这个a2dp speaker的profile
}
}
ALOGV(" found %zu profiles, %zu outputs", profiles.size(), outputs.size());
//到了这里,找到1个profile,0个output
}
...
}
这里我之所以省略了部分代码,是因为这个过程我们前面已经做过类似的分析了Android 8.1 Audio框架(一)初始化分析。我们知道了checkOutputsForDevice前面的处理会找到1个profile,0个output。module和profile的信息我用dumpsys media.audio_policy打印出来给你们看下并作解释
- HW Module 3: //存在mHwModules[2]中
- name: a2dp //audiopolicy会根据这个名字找到audio.a2dp.default.so这个库,然后链接它
- handle