安卓Audio hal层 select_devices()函数解析

本分解析android audio是如何选择device的

0 是select_devices(),函数的主干,后面小节对其中重要或难点 按层次作了解析。

参考链接:
https://blog.csdn.net/weijory/article/details/62422869
https://blog.csdn.net/edmond999/article/details/107843761

0. select_devices

# code/vendor/qcom/opensource/audio-hal/primary-hal/hal/audio_hw.c
int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
{
	// 1. 通过uc_id获取usecase
	usecase = get_usecase_from_list(adev, uc_id);
	
	// 2. 通过usecase,获取snd_device
	// 如果是播放模式,获取输出设备 和 设备列表
	if (usecase->type == PCM_PLAYBACK) {
		out_snd_device = platform_get_output_snd_device(adev->platform,
                                                                    usecase->stream.out,
                                                                    usecase->type);
        assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
    // 如果是录音模式,获取输入设备
    } else if (usecase->type == PCM_CAPTURE) {
		in_snd_device = platform_get_input_snd_device(adev->platform,
                                                                  priority_in,
                                                                  &out_devices,
                                                                  usecase->type);
	}  else ...

	// 3. 启用snd_device
	enable_snd_device(adev, out_snd_device);
	enable_snd_device(adev, in_snd_device);
	
	// 4. 启用audio_route
	enable_audio_route(adev, usecase);
}

1. enable_snd_device

int enable_snd_device(struct audio_device *adev,
                      snd_device_t snd_device)
{
	// 1.获取设备名
	platform_get_snd_device_name_extn(adev->platform, snd_device, device_name)
	
	// 2. 根据snd_device的不同情况, 进行一系列前置操作,然后启用and更新audio_path
	// 2.1 snd_device支持,并且已启用外放保护
    if (platform_can_enable_spkr_prot_on_device(snd_device) &&
         audio_extn_spkr_prot_is_enabled()) {
         // 能否正常获取acdb_id
        if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
            goto err;
        }
        audio_extn_dev_arbi_acquire(snd_device);
        // 3. 打开带保护的设备,保护算法也开始运作。应用and更新path
        if (audio_extn_spkr_prot_start_processing(snd_device)) {
            ALOGE("%s: spkr_start_processing failed", __func__);
            audio_extn_dev_arbi_release(snd_device);
            goto err;
        }
    // 2.2 如果设备可分割
    } else if (platform_split_snd_device(adev->platform,
                                         snd_device,
                                         &num_devices,
                                         new_snd_devices) == 0) {
        for (i = 0; i < num_devices; i++) {
            enable_snd_device(adev, new_snd_devices[i]);
        }
        // 3. 设置speaker_gain 。应用and更新path
        platform_set_speaker_gain_in_combo(adev, snd_device, true);
	// 2.3
    } else {
    	// 2.3.1 启用island power mode
    	// 2.3.2 
		// 3. 应用and更新path
		audio_route_apply_and_update_path(adev->audio_route, device_name);
	}
}

1.1 audio_route_apply_and_update_path

audio_route_apply_and_update_path() 函数分为两步:
audio_route_apply_path() 和
audio_route_update_path ()

1.1.1 audio_route_apply_path
int audio_route_apply_path(struct audio_route *ar, const char *name)
{
	// 根据device_name获取path
	path = path_get_by_name(ar, name);
	
    path_print(ar, path);
    path_apply(ar, path);
}
1.1.2 audio_route_update_path
static int audio_route_update_path(struct audio_route *ar, const char *name, int direction)
{
	// 根据不同的ctl类型
	if (type == MIXER_CTL_TYPE_BYTE) {
		// 1. 如果值有改变
		if (ms->old_value.bytes[j] != ms->new_value.bytes[j]) {
			// 2. 如果反转且激活次数 > 0
			if (reverse && ms->active_count > 0) {
				// 3. 复制旧值给新值
				memcpy(ms->new_value.bytes, ms->old_value.bytes,
                            ms->num_values * value_sz);
			} else {
				// 3. 写ms->num_values到 ms->ctl
				mixer_ctl_set_array(ms->ctl, ms->new_value.bytes, ms->num_values);
                memcpy(ms->old_value.bytes, ms->new_value.bytes, ms->num_values * value_sz);
			}
		}
	} else if (type == MIXER_CTL_TYPE_ENUM) {
		...
	} else if (ms->old_value.integer[j] != ms->new_value.integer[j]) {
		...
	}
}
static int path_apply(struct audio_route *ar, struct mixer_path *path)
{
	// 1. 判断类型是否支持
	...
	// 2. 复制 。。。 进audio_route
	memcpy(ar->mixer_state[ctl_index].new_value.ptr, path->setting[i].value.ptr,
	                path->setting[i].num_values * value_sz);
}

2. enable_audio_route

int enable_audio_route(struct audio_device *adev,
                       struct audio_usecase *usecase)
{
	// 1. 根据usecase获取snd_device
	if (usecase->type == PCM_CAPTURE) {
		snd_device = usecase->in_snd_device;
	} else if ( ... ) {
	} else {
        snd_device = usecase->out_snd_device;
    }
	// 2. 根据 snd_device 和 usecase 拼接出mixer_path
	strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path));
	platform_add_backend_name(mixer_path, snd_device, usecase);

	// 
	audio_route_apply_and_update_path(adev->audio_route, mixer_path);
}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值