【Audio】Android 10车载音频路由

音频路由

在 Android 10 中,car_audio_configuration.xml 取代了 car_volumes_groups.xmlIAudioControl.getBusForContext。新的配置文件定义了一个音频区列表。每个音频区都拥有一个或多个音量组及其关联设备,而每台设备都具有应在该音频区内进行路由的上下文。所有上下文都必须在每个音频区内表示。

配置音频路由

音频政策文件通常位于 vendor 分区中,表示主板的音频硬件配置。car_audio_configuration.xml 中引用的所有设备必须在 audio_policy_configuration.xml 中进行定义。

启用 AAOS 路由

如需使用基于 AAOS 的路由,您必须将 audioUseDynamicRouting 标记设为 true

<resources><bool name="audioUseDynamicRouting">true</bool>
</resources>

如果设为 false,路由和大部分 CarAudioService 将被停用,并且操作系统将回退到 AudioService 的默认行为。

主音频区

默认情况下,所有音频都将路由到主音频区。只能有一个主音频区,该音频区在配置中通过属性 isPrimary="true" 进行指示。

示例配置

例如,车辆可能拥有两个音频区:主音频区和后座娱乐系统。对于该配置,可能的 car_audio_configuration.xml 的定义如下:

<audioZoneConfiguration version="2.0"><zone name="primary zone" isPrimary="true"><volumeGroups><group><device address="bus0_media_out"><context context="music"/><context context="announcement"/></device><device address="bus3_call_ring_out"><context context="call_ring"/></device><device address="bus6_notification_out"><context context="notification"/></device><device address="bus7_system_sound_out"><context context="system_sound"/><context context="emergency"/><context context="safety"/><context context="vehicle_status"/></device></group><group><device address="bus1_navigation_out"><context context="navigation"/></device><device address="bus2_voice_command_out"><context context="voice_command"/></device></group><group><device address="bus4_call_out"><context context="call"/></device></group><group><device address="bus5_alarm_out"><context context="alarm"/></device></group></volumeGroups></zone><zone name="rear seat zone" audioZoneId="1"><volumeGroups><group><device address="bus100_rear_seat"><context context="music"/><context context="navigation"/><context context="voice_command"/><context context="call_ring"/><context context="call"/><context context="alarm"/><context context="notification"/><context context="system_sound"/><context context="emergency"/><context context="safety"/><context context="vehicle_status"/><context context="announcement"/></device></group></volumeGroups></zones>
</audioZoneConfiguration>

在这里,主音频区将上下文分离给不同的设备。这样一来,HAL 便可使用车辆的硬件,在各个设备输出中应用不同的后处理效果和混音。设备已划分为四个音量组:媒体、导航、通话和闹钟。如果系统配置为 useFixedVolume,则每个组的音量级别都将传递到 HAL,以应用于这些设备的输出。

对于辅助音频区,应通过单台输出设备进行输出。在此示例中,所有使用请求都将路由到单台设备和音量组,以简化操作。

乘员区的音频配置

在 Android 11 中,car_audio_configuraton.xml 已经过进一步扩展,引入了 audioZoneIdoccupantZoneId 这两个新字段。首先,audioZoneId 可用于更好地控制音频区管理;另一方面,occupantZoneId 可用于配置基于用户 ID 的路由。

若要使用这些新字段,必须使用 V2 的 car_audio_configuration.xml。如果想重新访问上述音频配置,但利用该新字段进行乘员区 ID 和音频区 ID 之间的映射,则可按如下所示设置不含音频组定义的新配置:

<audioZoneConfiguration version="2.0"><zone name="primary zone" isPrimary="true" occupantZoneId="0">...</zone><zone name="rear seat zone" audioZoneId="1" occupantZoneId="1">...</zone></zones>
</audioZoneConfiguration>

上面的配置定义了主音频区到乘员区 0 以及 audioZoneId 1 到 occupantZoneId 1 的映射。一般来说,可以配置乘员区和音频区之间的任意映射,但这种映射必须是一对一的。以下是定义这两个新字段的规则:

  • 主音频区的 audioZoneId 始终为零
  • audioZoneIdoccupantZoneId 的编号不可重复
  • audioZoneIdoccupantZoneId 之间只能是一对一的映射

通过应用 UID 路由

在 Android 10 中,向 CarAudioManager 引入了一系列隐藏 API,使应用可以查询并设置音频区和焦点。

int[] getAudioZoneIds();
int getZoneIdForUid(int uid);
boolean setZoneIdForUid(int zoneId, int uid);
boolean clearZoneIdForUid(int uid);

您可以使用上面的 API 让第一方应用根据应用的 UID 管理音频路由。这样,您还需要同时提供音频区 ID 和应用的 UID。掌握这些信息后,您便可以使用 CarAudioManager#setZoneIdForUid API 来设置音频路由。

更改应用的音频区

默认情况下,所有音频将路由到主音频区。如需更新应用以路由到其他音频区,请使用 CarAudioManager#setZoneIdForUid

// Find zone to play
int zoneId = ...// Find application's uid
Int uid = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), 0).uid;if (mCarAudioManager.setZoneIdForUid(zoneId, info.uid)) {Log.d(TAG, "Zone successfully updated");
} else {Log.d(TAG, "Failed to change zone");
}

注意:声音流无法动态地切换音频区。因此,必须停止播放并重新请求焦点,才能更改音频区。

使用用户 ID 进行路由

虽然基于应用 UID 的路由可以精细控制每个应用的音频路由,但它还需要在应用实际请求获得音频焦点和播放音频之前,为每个应用定义音频路由。为了消除此问题并进一步帮助第三方应用无需修改音频即可播放音频,CarAudioService 会使用汽车乘员区和音频区之间的映射来定义基于用户 ID 的路由。这样,当用户登录到乘员区时,车载音频服务就会收到通知。收到此信号后,系统会自动为所有音频区配置音频焦点管理和路由。

基于应用 UID 的路由仍然可以使用,但必须在基于用户 ID 的路由之外单独使用。也就是说,如果定义了乘员区到车载音频区的映射,则基于 UID 的路由会处于停用状态;尝试调用 CarAudioManager#setZoneidForUid 的话,系统就会抛出错误。

虽然通过乘员区管理简化了音频路由和焦点管理,但还是必须为乘员区分配用户。您可以使用 CarOccupantZoneManager#assignProfileUserToOccupantZone 实现这一点。此 API 需要管理用户的权限。目前,原始设备制造商 (OEM) 应通过某种系统界面管理乘员区用户分配。完成后,系统便会自动为该用户配置应用启动、音频路由以及焦点管理所有这三项功能。

使用 setPreferredDevice 进行路由

除了上述更改外,Android 11 还新增了下列 API 来查询与各个音频区关联的输出设备:CarAudioManager#getOutputDeviceForUsage(int zoneId, int usage)。

该 API 可用于查询用于特定音频区的输出设备以及音频属性用法。通过这种方式,第一方应用便可利用播放器的 setPreferredDevice API,将音频路由到不同的音频区。getOutputDeviceForUsage API 需使用 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS,并且是系统 API。以下示例展示了如何查找用于特定音频区的媒体设备以及如何使用 setPreferredDevice API 路由到该设备。

audioZoneId = ... ;
mediaDeviceInfo = mCarAudioManager.getOutputDeviceForUsage(audioZoneId, AudioAttributes.USAGE_MEDIA);
…
mPlayer.setPreferredDevice(mediaDeviceInfo);

相关阅读:https://source.android.google.cn/docs/devices/automotive/audio?hl=en&authuser=1

参考链接:https://source.android.google.cn/docs/devices/automotive/audio/audio-routing?authuser=1&hl=en#sample-config

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/69668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Oracle专栏】本地 expdp 导出远程库

Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 近期需要在远程备份机器上远程导出数据库,之前用expdp数据泵只导出过本服务器的,本文跨服务器使用expdp 。 2. 测试 2.1 本机装完整oracle时,执行expdp导出远端数据库 实验说明:以下12为本机,14…

Flink KafkaConsumer offset是如何提交的

一、fllink 内部配置 client.id.prefix&#xff0c;指定用于 Kafka Consumer 的客户端 ID 前缀partition.discovery.interval.ms&#xff0c;定义 Kafka Source 检查新分区的时间间隔。 请参阅下面的动态分区检查一节register.consumer.metrics 指定是否在 Flink 中注册 Kafka…

【leetcode】双指针:移动零 and 复写零

文章目录 1.移动零2.复写零 1.移动零 class Solution { public:void moveZeroes(vector<int>& nums) {for (int cur 0, dest -1; cur < nums.size(); cur)if (nums[cur] ! 0)swap(nums[dest], nums[cur]);} };class Solution { public:void moveZeroes(vector&l…

网络安全工程师逆元计算 网络安全逆向

中职逆向题目整理合集 逆向分析&#xff1a;PE01.exe算法破解&#xff1a;flag0072算法破解&#xff1a;flag0073算法破解&#xff1a;CrackMe.exe远程代码执行渗透测试天津逆向re1 re22023江苏省re12023年江苏省赛re2_easygo.exe2022天津市PWN 逆向分析&#xff1a;PE01.exe …

string类(二)

目录 前言 string类的常用接口说明 3、string类对象的容量操作 3.1 size&#xff0c;length和capacity 3.2 empty和clear 3.3 reserve 3.4 resize 4、string类的修改操作 4.1 operator 4.2 c_str 4.3 findnpos 5、string类非成员函数 5.1 operator>>和opera…

医疗影响分割 | 使用 Swin UNETR 训练自己的数据集(3D医疗影像分割教程)

<Swin UNETR: Swin Transformers for Semantic Segmentation of Brain Tumors in MRI Images> 代码地址:unetr 论文地址:https://arxiv.org/pdf/2201.01266 一、下载代码 在Github上下载代码,然后进入SWINUNETR,前两个是针对两个数据集(BRATS21、BTCV)的操作,这里…

在CAD中插入图块后为什么看不到?怎么解决?

按照正确操作插入图块&#xff0c;但图纸上不显示新插入的图块&#xff0c;这是为什么&#xff1f; 原因可能是大家插入的图块太小&#xff0c;导致看不到&#xff0c;显示成一个点&#xff0c;所以大家插入图块的时候记得根据图纸大小&#xff0c;将比例改大一些就可以啦✌️…

【CMAEL多智能体框架】第一节 环境搭建及简单应用(构建一个鲜花选购智能体)

第一节 环境搭建 文章目录 第一节 环境搭建前言一、安装二、获取API1. 使用熟悉的API代理平台2.设置不使用明文存放API 三 、具体应用进阶任务 总结 前言 CAMEL Multi-Agent是一个开源的、灵活的框架&#xff0c;它提供了一套完整的工具和库&#xff0c;用于构建和模拟多智能体…

Flink-序列化

一、概述 几乎每个Flink作业都必须在其运算符之间交换数据&#xff0c;由于这些记录不仅可以发送到同一JVM中的另一个实例&#xff0c;还可以发送到单独的进程&#xff0c;因此需要先将记录序列化为字节。类似地&#xff0c;Flink的堆外状态后端基于本地嵌入式RocksDB实例&…

使用DeepSeek和Kimi快速自动生成PPT

目录 步骤1&#xff1a;在DeepSeek中生成要制作的PPT主要大纲内容。 &#xff08;1&#xff09;在DeepSeek网页端生成 &#xff08;2&#xff09;在本地部署DeepSeek后&#xff0c;使用chatBox生成PPT内容 步骤2&#xff1a;将DeepSeek成的PPT内容复制到Kimi中 步骤3&…

第41天:Web开发-JS应用微信小程序源码架构编译预览逆向调试嵌套资产代码审计

#知识点 1、安全开发-微信小程序-搭建&开发&架构&安全 2、安全开发-微信小程序-编译调试&反编译&泄露 一、小程序创建&#xff08;了解即可&#xff09; 1、下载微信开发者工具 2、创建小程序模版引用 https://developers.weixin.qq.com/miniprogram/dev/d…

Arduino 第十一章:温度传感器

Arduino 第十一章&#xff1a;LM35 温度传感器 一、LM35 简介 LM35 是美国国家半导体公司&#xff08;现德州仪器&#xff09;生产的一款精密集成电路温度传感器。与基于热力学原理的传统温度传感器不同&#xff0c;LM35 能直接将温度转换为电压输出&#xff0c;且输出电压与…

Oracle常用导元数据方法

1 说明 前两天领导发邮件要求导出O库一批表和索引的ddl语句做国产化测试&#xff0c;涉及6个系统&#xff0c;6千多张表&#xff0c;还好涉及的用户并不多&#xff0c;要不然很麻烦。 如此大费周折原因&#xff0c;是某国产库无法做元数据迁移。。。额&#xff0c;只能我手动导…

2022java面试总结,1000道(集合+JVM+并发编程+Spring+Mybatis)的Java高频面试题

1、面试题模块汇总 面试题包括以下十九个模块&#xff1a; Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示…

Curser2_解除机器码限制

# Curser1_无限白嫖试用次数 文末有所需工具下载地址 Cursor Device ID Changer 一个用于修改 Cursor 编辑器设备 ID 的跨平台工具集。当遇到设备 ID 锁定问题时&#xff0c;可用于重置设备标识。 功能特性 ✨ 支持 Windows 和 macOS 系统&#x1f504; 自动生成符合格式的…

carbon 加入 GitCode:Golang 时间处理的 “瑞士军刀”

在 Golang 的开发生态中&#xff0c;时间处理领域长期存在着诸多挑战。高效、精准的时间处理对于各类软件应用的稳定运行与功能拓展至关重要。近日&#xff0c;carbon 正式加入 GitCode&#xff0c;为 Golang 开发者带来一款强大且便捷的时间处理利器&#xff0c;助力项目开发迈…

算法学习--链表

引言&#xff1a;为什么进行链表的学习&#xff1f; 考察能力独特&#xff1a;链表能很好地考察应聘者对指针操作、内存管理的理解和运用能力&#xff0c;还能检验代码的鲁棒性&#xff0c;比如处理链表的插入、删除操作时对边界条件的处理。数据结构基础&#xff1a;链表是很多…

域名劫持原理与实践

了解域名及域名劫持 由于点分十进制的IP地址难于记忆&#xff0c;便出现了域名。由于网络传输中最终还是基于IP&#xff0c;所以必须通过一种机制将IP和域名一一对应起来&#xff0c;这便是DNS。全球总共有13台根域名服务器。 域名劫持是互联网攻击中常见的一种攻击方式&…

【论文翻译】DeepSeek-V3论文翻译——DeepSeek-V3 Technical Report——第二部分:(训练硬件)基础设施

论文原文链接&#xff1a;DeepSeek-V3/DeepSeek_V3.pdf at main deepseek-ai/DeepSeek-V3 GitHub 特别声明&#xff0c;本文不做任何商业用途&#xff0c;仅作为个人学习相关论文的翻译记录。本文对原文内容直译&#xff0c;一切以论文原文内容为准&#xff0c;对原文作者表示…

MapReduce到底是个啥?

在聊 MapReduce 之前不妨先看个例子&#xff1a;假设某短视频平台日活用户大约在7000万左右&#xff0c;若平均每一个用户产生3条行为日志&#xff1a;点赞、转发、收藏&#xff1b;这样就是两亿条行为日志&#xff0c;再假设每条日志大小为100个字节&#xff0c;那么一天就会产…