一、判断广播是否发出
- checkSendBecomingNoisyIntentInt
用于判断在音频设备状态改变时(特别是断开连接时),是否需要向媒体应用发送 ACTION_AUDIO_BECOMING_NOISY广播。
主要职责是评估断开连接的设备是否是当前活跃的音频输出设备,以及当前系统状态(是否有音乐播放、是否处于通话中等),
并最终决定是否需要发送广播,如果需要,则返回一个延迟时间(通常用于等待蓝牙设备的短暂重连机会)。
java
// 创建一个 MediaMetrics 对象用于记录该方法的执行指标。
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
+ "checkSendBecomingNoisyIntentInt")
// 设置属性:正在评估的设备名称。
.set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(device))
// 设置属性:设备的连接状态(已连接或已断开)。
.set(MediaMetrics.Property.STATE,
state == AudioService.CONNECTION_STATE_CONNECTED
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED);
// 情况1:如果设备状态不是"断开连接",则无需发送广播,直接返回。
if (state != AudioService.CONNECTION_STATE_DISCONNECTED) {
Log.i(TAG, "not sending NOISY: state=" + state);
mmi.set(MediaMetrics.Property.DELAY_MS, 0).record(); // 记录延迟时间为0,然后返回。
return 0;
}
// 情况2:如果断开连接的设备类型不在预设的"需要发送NOISY广播的设备集合"中,也无需发送,直接返回。
if (!BECOMING_NOISY_INTENT_DEVICES_SET.contains(device)) {
Log.i(TAG, "not sending NOISY: device=0x" + Integer.toHexString(device)
+ " not in set " + BECOMING_NOISY_INTENT_DEVICES_SET);
mmi.set(MediaMetrics.Property.DELAY_MS, 0).record();
return 0;
}
// 延迟时间变量,默认0。
int delay = 0;
// 创建一个集合,用于存储当前所有已连接且应触发NOISY广播的**输出设备**类型。
Set<Integer> devices = new HashSet<>();
// 遍历所有已连接的设备。
for (DeviceInfo di : mConnectedDevices.values()) {
// 筛选条件:1. 是输出设备;2. 设备类型在上述集合中。
if (!AudioSystem.isInputDevice(di.mDeviceType)
&& BECOMING_NOISY_INTENT_DEVICES_SET.contains(di.mDeviceType)) {
// 满足条件的设备类型加入集合。
devices.add(di.mDeviceType);
Log.i(TAG, "NOISY: adding 0x" + Integer.toHexString(di.mDeviceType));
}
}
// 如果传入的 `musicDevice` 参数表示"未指定",则查询系统当前实际用于音乐播放(STREAM_MUSIC)的设备。
if (musicDevice == AudioSystem.DEVICE_NONE) {
musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
Log.i(TAG, "NOISY: musicDevice changing from NONE to 0x"
+ Integer.toHexString(musicDevice));
}
// **核心逻辑判断**:决定是否发送广播。
// 准备判断所需的状态变量:
// 1. 系统是否正在通信中(例如,通话或语音识别)。
final boolean inCommunication = mDeviceBroker.isInCommunication();
// 2. 判断断开连接的设备是否是集合 `devices` 中唯一或最后一个符合NOISY触发条件的音频设备类型。
final boolean singleAudioDeviceType = AudioSystem.isSingleAudioDeviceType(devices, device);
// 3. 是否有动态音频策略正在影响媒体路由。
final boolean hasMediaDynamicPolicy = mDeviceBroker.hasMediaDynamicPolicy();
// 判断条件全部满足时,才需要发送广播:
// 1. 条件A:断开连接的设备是当前音乐播放设备 **或者** 系统正处于通信模式。
// 2. 条件B:该断开连接的设备是唯一或最后一个应触发NOISY的音频设备类型。
// 3. 条件C:没有动态音频策略影响媒体路由。
// 4. 条件D:当前音乐播放设备不是远程子混音设备(`DEVICE_OUT_REMOTE_SUBMIX`,通常用于屏幕录制或投屏)。
if (((device == musicDevice) || inCommunication)
&& singleAudioDeviceType
&& !hasMediaDynamicPolicy
&& (musicDevice != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)) {
// **进一步检查**:即使满足以上条件,如果系统当前既没有播放音乐,也没有持有音频焦用的用户,则不应视为"即将嘈杂",无需打断远程播放的应用。
if (!mAudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0 /*not looking in past*/)
&& !mDeviceBroker.hasAudioFocusUsers()) {
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
"dropping ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
mmi.set(MediaMetrics.Property.DELAY_MS, 0).record();
return 0;
}
// **发送广播**:所有条件满足,提交一个延迟发送"即将嘈杂"广播的任务。
mDeviceBroker.postBroadcastBecomingNoisy();
// 设置返回的延迟时间(通常是预定义的常量,例如 `AudioService.BECOMING_NOISY_DELAY_MS`)。
delay = AudioService.BECOMING_NOISY_DELAY_MS;
} else {
// 如果以上条件不满足,则记录详细的日志,说明不发送广播的原因。
Log.i(TAG, "not sending NOISY: device:0x" + Integer.toHexString(device)
+ " musicDevice:0x" + Integer.toHexString(musicDevice)
+ " inComm:" + inCommunication
+ " mediaPolicy:" + hasMediaDynamicPolicy
+ " singleDevice:" + singleAudioDeviceType);
}
// 最终记录本次调用计算的延迟时间指标,并返回该值。
mmi.set(MediaMetrics.Property.DELAY_MS, delay).record();
return delay;