Android R CarAudio行为变更
本文主要梳理CarAudio模块,从Q升到R的行为变更,如有错误或者理解偏差,欢迎指正
文章目录
一、CarAudioManager行为变更
1.1 成员变量
INVALID_AUDIO_ZONE用于CarOccupantService的初始化和判定,INVALID_VOLUME_GROUP_ID用于usage找groupId时,找不到对应groupId的情况,之前返回的-1。
/**
* Zone id of the invalid audio zone.
* @hide
*/
@SystemApi
public static final int INVALID_AUDIO_ZONE = 0xffffffff;
/**
* Volume Group ID when volume group not found.
* @hide
*/
public static final int INVALID_VOLUME_GROUP_ID = -1;
1.2 新增API
getOutputDeviceForUsage
通过usage拿到对应的device address 如BUS media,然后通过audiomanger拿到所有的outputdevice后进行address匹配,匹配成功返回AudioDeviceInfo
/**
* Gets the output device for a given {@link AudioAttributes} usage in zoneId.
*
* <p><b>Note:</b> To be used for routing to a specific device. Most applications should
* use the regular routing mechanism, which is to set audio attribute usage to
* an audio track.
*
* @param zoneId zone id to query for device
* @param usage usage where audio is routed
* @return Audio device info, returns {@code null} if audio device usage fails to map to
* an active audio device. This is different from the using an invalid value for
* {@link AudioAttributes} usage. In the latter case the query will fail with a
* RuntimeException indicating the issue.
*
* @hide
*/
@SystemApi
@Nullable
@RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)
public AudioDeviceInfo getOutputDeviceForUsage(int zoneId,
@AudioAttributes.AttributeUsage int usage) {
try {
String deviceAddress = mService.getOutputDeviceAddressForUsage(zoneId, usage);
if (deviceAddress == null) {
return null;
}
AudioDeviceInfo[] outputDevices =
mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
for (AudioDeviceInfo info : outputDevices) {
if (info.getAddress().equals(deviceAddress)) {
return info;
}
}
return null;
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, null);
}
}
getInputDevicesForZoneId
先通过CarAudioService拿到对应zoneId的所有的inputDevices,然后通过audioManger拿到所有的InputDevice然后匹配对应的address,成功加入到list后一起返回
/**
* Gets the input devices for an audio zone
*
* @return list of input devices
* @hide
*/
@SystemApi
@RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)
public @NonNull List<AudioDeviceInfo> getInputDevicesForZoneId(int zoneId) {
try {
return convertInputDevicesToDeviceInfos(
mService.getInputDevicesForZoneId(zoneId),
AudioManager.GET_DEVICES_INPUTS);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, new ArrayList<>());
}
}
private List<AudioDeviceInfo> convertInputDevicesToDeviceInfos(
List<AudioDeviceAttributes> devices, @AudioDeviceRole int flag) {
int addressesSize = devices.size();
Set<String> deviceAddressMap = new HashSet<>(addressesSize);
for (int i = 0; i < addressesSize; ++i) {
AudioDeviceAttributes device = devices.get(i);
deviceAddressMap.add(device.getAddress());
}
List<AudioDeviceInfo> deviceInfoList = new ArrayList<>(devices.size());
AudioDeviceInfo[] inputDevices = mAudioManager.getDevices(flag);
for (int i = 0; i < inputDevices.length; ++i) {
AudioDeviceInfo info = inputDevices[i];
if (info.isSource() && deviceAddressMap.contains(info.getAddress())) {
deviceInfoList.add(info);
}
}
return deviceInfoList;
}
1.3 移除API
getZoneIdForDisplay
getZoneIdForDisplayPortId
两个关于displayId和zoneId来回转换的API被移除了,通样的car_audio_configuration.xml里zones里绑定的display也被去掉了。
移除原因:carService里新增了CarOccupantZoneManger和service用来管理display和users,
/**
* API to get information on displays and users in the car.
*/
该api移除后,需要进行适配到getAudioZoneIdForOccupant和getOccupantForAudioZoneId API上
/**
* Get the zone id for the display
*
* @param display display to query
* @return zone id for display or
* CarAudioManager.PRIMARY_AUDIO_ZONE if no match is found.
* @hide
*/
@RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)
public int getZoneIdForDisplay(Display display) {
}
/**
* Get the zone id for the display port id passed in
*
* @param displayPortId display port id to query
* @return zone id for display port id or
* CarAudioManager.PRIMARY_AUDIO_ZONE if no match is found.
* @hide
*/
@RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)
public int getZoneIdForDisplayPortId(byte displayPortId) {
}
//======================================================================>
/**
* Gets the audio zone id for the occupant, or returns
* {@code CarAudioManager.INVALID_AUDIO_ZONE} if no audio zone matches the requirements.
* throws InvalidArgumentException if occupantZone does not exist.
*
* @hide
*/
@SystemApi
@RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)
public int getAudioZoneIdForOccupant(@NonNull OccupantZoneInfo occupantZone) {
assertNonNullOccupant(occupantZone);
try {
return mService.getAudioZoneIdForOccupant(occupantZone.zoneId);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, null);
}
}
/**
* Gets occupant for the audio zone id, or returns {@code null}
* if no audio zone matches the requirements.
*
* @hide
*/
@Nullable
@SystemApi
@RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)
public OccupantZoneInfo getOccupantForAudioZoneId(int audioZoneId) {
try {
return mService.getOccupantForAudioZoneId(audioZoneId);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, null);
}
}
二、CarAudioService的行为变更
Q的目录结构
src\com\android\car\audio\CarAudioDeviceInfo.java
src\com\android\car\audio\CarAudioDynamicRouting.java
src\com\android\car\audio\CarAudioFocus.java
src\com\android\car\audio\CarAudioService.java
src\com\android\car\audio\CarAudioZone.java
src\com\android\car\audio\CarAudioZonesHelper.java
src\com\android\car\audio\CarAudioZonesHelperLegacy.java
src\com\android\car\audio\CarVolumeGroup.java
src\com\android\car\audio\CarZonesAudioFocus.java
R的目录结构
src\com\android\car\audio\hal\AudioControlFactory.java
src\com\android\car\audio\hal\AudioControlWrapper.java
src\com\android\car\audio\hal\AudioControlWrapperV1.java
src\com\android\car\audio\hal\AudioControlWrapperV2.java
src\com\android\car\audio\hal\HalAudioFocus.java
src\com\android\car\audio\CarAudioContext.java
src\com\android\car\audio\CarAudioDeviceInfo.java
src\com\android\car\audio\CarAudioDynamicRouting.java
src\com\android\car\audio\CarAudioFocus.java
src\com\android\car\audio\CarAudioService.java
src\com\android\car\audio\CarAudioSettings.java
src\com\android\car\audio\CarAudioZone.java
src\com\android\car\audio\CarAudioZonesHelper.java
src\com\android\car\audio\CarAudioZonesHelperLegacy.java
src\com\android\car\audio\CarAudioZonesValidator.java
src\com\android\car\audio\CarVolume.java
src\com\android\car\audio\CarVolumeCallbackHandler.java
src\com\android\car\audio\CarVolumeGroup.java
src\com\android\car\audio\CarZonesAudioFocus.java
src\com\android\car\audio\FocusEntry.java
src\com\android\car\audio\FocusInteraction.java
src\com\android\car\audio\OWNERS
对比之后多了好多小模块,好多模块也做了优化
2.1 CarAudioZonesHelper解析car_audio_configuration 2.0
car_audio_configuration新增字段,新增字段后version也变成了2,如果使用了audioZoneId occupantZoneId inputDevices字段但是version没有生成2,会在解析阶段报异常。
<?xml version="1.0" encoding="utf-8"?>
<carAudioConfiguration version="2">
<zones>
<zone name="primary zone" isPrimary="true" audioZoneId="0" occupantZoneId="1">
<volumeGroups>
<group>
<device address="bus0_media_out">
<context context="music"/>
</device>
<device address="bus3_call_ring_out">
<context context="call_ring"/>
</device>
</group>
<group>
<device address="bus1_navigation_out">
<context context="navigation"/>
<context context="emergency"/>
<context context="safety"/>
<context context="vehicle_status"/>
<context context="announcement"/>
</device>
</group>
</volumeGroups>
<inputDevices>
<inputDevice address="fm_tuner"/>
<inputDevice address="Built-In Mic"/>
</inputDevices>
</zone>
<zone name="rear seat zone" audioZoneId="2">
<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="system_sound"/>
<context context="notification"/>
<context context="emergency"/>
<context context="safety"/>
<context context="vehicle_status"/>
<context context="announcement"/>
</device>
</group>
</volumeGroups>
<inputDevices>
<inputDevice address="bus_1000_input"/>
<inputDevice address="Built-In Back Mic"/>
</inputDevices>
</zone>
</zones>
</carAudioConfiguration>
inputDevices
为了支持getInputDeviceForZoneId,CarAudioZones初始化时也会去读取xml里的inputDevice,如官方示例中
<inputDevices>
<inputDevice address