音频路由
在 Android 10 中,car_audio_configuration.xml
替换 car_volumes_groups.xml
和IAudioControl.getBusForContext。
在新的配置文件中,定义了一个区域列表。每个区域都有一个或多个卷组及其关联的设备,并且每个设备都有应该在该区域内路由的上下文。要求在每个区域内表示所有上下文。
配置音频路由
音频策略文件通常位于供应商分区中,代表主板的音频硬件配置。中引用的所有设备都 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 11car_audio_configuraton.xml
中进一步扩展引入了两个新领域,audioZoneId
和occupantZoneId.
第一,audioZoneId
可用于更好的控制区管理。另一方面,occupantZoneId可以用来配置基于用户ID的路由。
要使用这些新字段,car_audio_configuration.xml
需要 V2。重新访问上面的音频配置,但利用新字段进行占用区域 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
和 audioZoneId1
到occupantZoneId1
的映射。通常,占用区域和音频区域之间的任何映射都可以配置,但映射必须是一对一的。以下是定义这两个新字段的规则:
- 主要区域的audioZoneId始终为零
- audioZoneId并且occupantZoneId数字不能重复
- audioZoneId并且occupantZoneId只能有一对一的映射
通过应用程序 UID 进行路由
在 10中引入了一系列隐藏的 API,CarAudioManager以允许应用程序查询和设置音频区域和焦点。
int[] getAudioZoneIds();
int getZoneIdForUid(int uid);
boolean setZoneIdForUid(int zoneId, int uid);
boolean clearZoneIdForUid(int uid);
上述 API 允许第一方应用程序根据应用程序的 UID 管理音频路由。因此,还需要音频区域 ID 和应用程序的 UID。有了这些信息,就可以使用 CarAudioManager#setZoneIdForUidAPI 设置音频路由。
更改应用的区域
默认情况下,所有音频路由到主要区域。要更新要路由到不同区域的应用程序,请使用CarAudioManager#setZoneIdForUid:
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");
}
N 注意:流和焦点不能动态切换区域。因此,必须停止播放并重新请求焦点以更改区域。
使用用户 ID 路由
虽然应用程序的基于 UID 的路由允许对每个应用程序的音频路由进行精细控制,但它还要求在应用程序实际请求音频焦点和播放音频之前定义每个应用程序的音频路由。为了缓解此问题并进一步促进第三方应用程序无需修改即可播放音频, CarAudioService
请使用汽车乘员区域和音频区域映射来定义基于用户 ID 的路由。这样,当用户登录到乘员区时,就会通知汽车音频服务。有了这个信号,所有音频区域的音频焦点管理和路由都会自动配置。
应用程序基于 UID 的路由仍然可以使用,但必须独立于用户 ID 路由来完成。这意味着如果定义了乘员区域到汽车音频区域的映射,则基于 UID 的路由将被禁用,并且尝试调用 CarAudioManager#setZoneidForUid
将引发错误。
虽然占用区域管理简化了音频路由和焦点管理,但仍必须将用户分配到占用区域。这可以通过使用CarOccupantZoneManager#assignProfileUserToOccupantZone
. 此 API 需要管理用户的权限。当前的期望是 OEM 通过某种系统 UI 来管理用户到占用区域的分配。完成后,应用程序启动、音频路由、焦点管理都将为用户自动配置。
使用 setPreferredDevice 路由
除了上述更改之外,Android 11 还提供了一个新 API 来查询与每个区域关联的输出设备,即 CarAudioManager#getOutputDeviceForUsage(int zoneId, int usage)。
API 可用于查询输出设备的特定区域和音频属性使用情况。以这种方式,第一方应用程序可以利用播放器的setPreferredDeviceAPI
将音频路由到不同的区域。getOutputDeviceForUsageAPI
需要 并且 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS
是系统 API。下面是为特定区域查找媒体设备并使用setPreferredDeviceAPI
路由到该设备的示例。
mediaDeviceInfo = mCarAudioManager
.getOutputDeviceForUsage(audioZoneId, AudioAttributes.USAGE_MEDIA);
…
mPlayer.setPreferredDevice(mediaDeviceInfo);