From 01f04aac7fce0d2b381a6a6ddcb627fee53e77a0 Mon Sep 17 00:00:00 2001 From: tianyifeng Date: Mon, 13 Mar 2023 12:39:28 +0000 Subject: [PATCH] Detect audio device change from API 23 with AudioCapabilitiesReceiver * Add AudioDeviceCallbackApi23 class which extends the AudioDeviceCallback. * Add registerAudioDeviceCallback and unregisterAudioDeviceCallback methods for Api23. * Modify the logics of AudioCapabilitiesReceiver constructor, register and unregister methods. PiperOrigin-RevId: 516183997 --- .../audio/AudioCapabilitiesReceiver.java | 68 ++++++++++++++++--- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java index 8500d36c72..1ca80e54a7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java @@ -15,17 +15,22 @@ */ package com.google.android.exoplayer2.audio; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; + import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; +import android.media.AudioDeviceCallback; +import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; +import androidx.annotation.DoNotInline; import androidx.annotation.Nullable; -import com.google.android.exoplayer2.util.Assertions; +import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.util.Util; /** @@ -48,7 +53,8 @@ public final class AudioCapabilitiesReceiver { private final Context context; private final Listener listener; private final Handler handler; - @Nullable private final BroadcastReceiver receiver; + @Nullable private final AudioDeviceCallbackV23 audioDeviceCallback; + @Nullable private final BroadcastReceiver hdmiAudioPlugBroadcastReceiver; @Nullable private final ExternalSurroundSoundSettingObserver externalSurroundSoundSettingObserver; @Nullable /* package */ AudioCapabilities audioCapabilities; @@ -61,9 +67,11 @@ public final class AudioCapabilitiesReceiver { public AudioCapabilitiesReceiver(Context context, Listener listener) { context = context.getApplicationContext(); this.context = context; - this.listener = Assertions.checkNotNull(listener); + this.listener = checkNotNull(listener); handler = Util.createHandlerForCurrentOrMainLooper(); - receiver = Util.SDK_INT >= 21 ? new HdmiAudioPlugBroadcastReceiver() : null; + audioDeviceCallback = Util.SDK_INT >= 23 ? new AudioDeviceCallbackV23() : null; + hdmiAudioPlugBroadcastReceiver = + Util.SDK_INT >= 21 ? new HdmiAudioPlugBroadcastReceiver() : null; Uri externalSurroundSoundUri = AudioCapabilities.getExternalSurroundSoundGlobalSettingUri(); externalSurroundSoundSettingObserver = externalSurroundSoundUri != null @@ -82,18 +90,24 @@ public final class AudioCapabilitiesReceiver { @SuppressWarnings("InlinedApi") public AudioCapabilities register() { if (registered) { - return Assertions.checkNotNull(audioCapabilities); + return checkNotNull(audioCapabilities); } registered = true; if (externalSurroundSoundSettingObserver != null) { externalSurroundSoundSettingObserver.register(); } + if (Util.SDK_INT >= 23 && audioDeviceCallback != null) { + Api23.registerAudioDeviceCallback(context, audioDeviceCallback, handler); + } @Nullable Intent stickyIntent = null; - if (receiver != null) { + if (hdmiAudioPlugBroadcastReceiver != null) { IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG); stickyIntent = context.registerReceiver( - receiver, intentFilter, /* broadcastPermission= */ null, handler); + hdmiAudioPlugBroadcastReceiver, + intentFilter, + /* broadcastPermission= */ null, + handler); } audioCapabilities = AudioCapabilities.getCapabilities(context, stickyIntent); return audioCapabilities; @@ -108,8 +122,11 @@ public final class AudioCapabilitiesReceiver { return; } audioCapabilities = null; - if (receiver != null) { - context.unregisterReceiver(receiver); + if (Util.SDK_INT >= 23 && audioDeviceCallback != null) { + Api23.unregisterAudioDeviceCallback(context, audioDeviceCallback); + } + if (hdmiAudioPlugBroadcastReceiver != null) { + context.unregisterReceiver(hdmiAudioPlugBroadcastReceiver); } if (externalSurroundSoundSettingObserver != null) { externalSurroundSoundSettingObserver.unregister(); @@ -159,4 +176,37 @@ public final class AudioCapabilitiesReceiver { onNewAudioCapabilities(AudioCapabilities.getCapabilities(context)); } } + + @RequiresApi(23) + private final class AudioDeviceCallbackV23 extends AudioDeviceCallback { + @Override + public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { + onNewAudioCapabilities(AudioCapabilities.getCapabilities(context)); + } + + @Override + public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { + onNewAudioCapabilities(AudioCapabilities.getCapabilities(context)); + } + } + + @RequiresApi(23) + private static final class Api23 { + + @DoNotInline + public static void registerAudioDeviceCallback( + Context context, AudioDeviceCallback callback, Handler handler) { + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + checkNotNull(audioManager).registerAudioDeviceCallback(callback, handler); + } + + @DoNotInline + public static void unregisterAudioDeviceCallback( + Context context, AudioDeviceCallback callback) { + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + checkNotNull(audioManager).unregisterAudioDeviceCallback(callback); + } + + private Api23() {} + } }