diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java index 671ddb5aa6..ad6095fa98 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java @@ -15,17 +15,22 @@ */ package androidx.media3.exoplayer.audio; +import static androidx.media3.common.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 androidx.media3.common.util.Assertions; +import androidx.annotation.RequiresApi; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; @@ -50,7 +55,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; @@ -63,9 +69,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 @@ -84,18 +92,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; @@ -110,8 +124,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(); @@ -161,4 +178,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() {} + } }