Android audio之 AudioDeviceInventory
1. 类介绍
AudioDeviceInventory
是 Android 音频系统中的一个核心类,位于 frameworks/base/services/core/java/com/android/server/audio/
路径下。它负责 管理所有音频设备的连接状态,包括设备的添加、移除、状态更新以及策略应用。
- 设备连接状态管理:记录所有已连接的音频设备(如蓝牙耳机、有线耳机、USB设备等)。
- 设备策略协调:处理设备优先级、路由策略(如 A2DP 和 LE Audio 的切换)。
- 与 AudioPolicyManager 交互:通过
AudioSystem
接口通知底层音频策略管理器(APM)设备状态变化。 - 广播设备状态变更:发送系统广播(如
ACTION_AUDIO_BECOMING_NOISY
)通知应用设备变化。
2. 核心功能
(1) 设备连接状态管理
- 设备类型:支持多种设备类型(如
DEVICE_OUT_BLUETOOTH_A2DP
、DEVICE_OUT_WIRED_HEADSET
等)。 - 设备信息存储:通过
DeviceInfo
类存储设备的类型、地址、名称、编解码格式等信息。 - 连接/断开处理:
- 连接:调用
AudioSystem.setDeviceConnectionState()
通知底层设备可用。 - 断开:移除设备并通知底层,处理延迟断开(如蓝牙设备淡出)。
- 连接:调用
(2) 音频路由策略
- 蓝牙设备优先级:协调 A2DP、LE Audio、HFP 等蓝牙配置的切换(如
updateBluetoothPreferredModes_l
)。 - 策略应用:通过
setPreferredDevicesForStrategy()
设置设备优先级(如音乐播放优先使用 A2DP)。
(3) 事件通知
- 系统广播:发送
ACTION_AUDIO_BECOMING_NOISY
(当耳机拔出时通知应用暂停播放)。 - 内部回调:通过
IAudioRoutesObserver
通知其他服务(如AudioService
)设备路由变化。
3. 与 AudioManager 的关系
AudioDeviceInventory
是 AudioManager
的 底层支持模块,两者通过 AudioService
和 AudioDeviceBroker
交互:
组件 | 角色 |
---|---|
AudioManager | 面向应用的 API 层,提供 requestAudioFocus() 、setWiredHeadsetOn() 等方法。 |
AudioService | 系统服务,协调 AudioManager 和底层模块(如 AudioDeviceInventory )。 |
AudioDeviceBroker | 中介层,处理线程安全和跨进程通信(如 Binder 调用)。 |
AudioDeviceInventory | 设备状态管理的核心实现,维护设备列表并同步到 AudioPolicyManager 。 |
交互流程示例
-
应用调用
AudioManager.setWiredHeadsetOn()
→AudioService
通过AudioDeviceBroker
转发请求
→AudioDeviceInventory
更新设备状态并调用AudioSystem.setDeviceConnectionState()
→ 底层音频策略生效,触发路由切换。 -
蓝牙耳机连接
→ 蓝牙栈通知AudioService
→AudioDeviceInventory.makeA2dpDeviceAvailable()
更新设备列表
→ 发送广播通知应用焦点变化。
4. 关键代码解析
(1) 设备连接处理
// 处理设备连接/断开
boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect, ...) {int res = mAudioSystem.setDeviceConnectionState(attributes, connect ? DEVICE_STATE_AVAILABLE : DEVICE_STATE_UNAVAILABLE, ...);if (res == AUDIO_STATUS_OK) {mConnectedDevices.add/remove(deviceKey); // 更新设备列表}
}
(2) 蓝牙设备优先级协调
// 更新蓝牙设备模式(如 A2DP 和 LE Audio 的切换)
void updateBluetoothPreferredModes_l(BluetoothDevice device) {if (isA2dpPreferred()) {disableLeAudio(); // 禁用 LE Audio}
}
(3) 发送 ACTION_AUDIO_BECOMING_NOISY
广播
int checkSendBecomingNoisyIntentInt(int device, int state) {if (device == currentMusicDevice && isLastConnectedDevice()) {mDeviceBroker.postBroadcastBecomingNoisy(); // 发送广播}
}
5. 典型应用场景
-
耳机拔出
→AudioDeviceInventory
检测到断开 → 发送ACTION_AUDIO_BECOMING_NOISY
→ 音乐播放器暂停。 -
蓝牙设备切换
→ 用户从 A2DP 切换到 LE Audio →AudioDeviceInventory
更新设备优先级 → 音频路由切换。 -
USB 设备插入
→ 系统通知AudioService
→AudioDeviceInventory
添加设备 → 触发 HDMI 音频输出。