Android 8.1 Audio框架(二)AudioPolicy路由策略实例分析

本文详细分析了Android 8.1系统中蓝牙耳机连接时的AudioPolicy路由策略。从概述、时序图到核心函数setDeviceConnectionStateInt的调用,解释了设备连接如何影响AudioService、AudioPolicyManager以及输出设备的管理。通过checkOutputsForDevice函数的三个阶段,探讨了如何创建和管理SwAudioOutputDescriptor,以及DuplicatingThread在实现多设备音频输出中的作用。最后,阐述了invalidateStream过程如何触发AudioTrack的重建,确保音频流按预期输出。
摘要由CSDN通过智能技术生成

概述

这里以蓝牙耳机连接手机这一场景为例分析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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值