From 6af92b0af3526fb3aa534a5c7c6c1eb2df1369dc Mon Sep 17 00:00:00 2001 From: Colin Kho Date: Tue, 13 Aug 2024 10:17:32 -0700 Subject: [PATCH 1/5] Differ AudioManager retrieval to whenever AudioFocusManagement is required --- .../media3/exoplayer/AudioFocusManager.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java index fb9823beba..29a98708ce 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java @@ -160,11 +160,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private static final float VOLUME_MULTIPLIER_DUCK = 0.2f; private static final float VOLUME_MULTIPLIER_DEFAULT = 1.0f; - private final AudioManager audioManager; private final AudioFocusListener focusListener; + private final Context applicationContext; @Nullable private PlayerControl playerControl; @Nullable private AudioAttributes audioAttributes; - + @Nullable private AudioManager audioManager; private @AudioFocusState int audioFocusState; private @AudioFocusGain int focusGainToRequest; private float volumeMultiplier = VOLUME_MULTIPLIER_DEFAULT; @@ -180,9 +180,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * @param playerControl A {@link PlayerControl} to handle commands from this instance. */ public AudioFocusManager(Context context, Handler eventHandler, PlayerControl playerControl) { - this.audioManager = - checkNotNull( - (AudioManager) context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)); + this.applicationContext = context; this.playerControl = playerControl; this.focusListener = new AudioFocusListener(eventHandler); this.audioFocusState = AUDIO_FOCUS_STATE_NOT_REQUESTED; @@ -287,7 +285,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } private int requestAudioFocusDefault() { - return audioManager.requestAudioFocus( + return getAudioManager().requestAudioFocus( focusListener, Util.getStreamTypeForAudioUsage(checkNotNull(audioAttributes).usage), focusGainToRequest); @@ -312,17 +310,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; rebuildAudioFocusRequest = false; } - return audioManager.requestAudioFocus(audioFocusRequest); + return getAudioManager().requestAudioFocus(audioFocusRequest); } private void abandonAudioFocusDefault() { - audioManager.abandonAudioFocus(focusListener); + getAudioManager().abandonAudioFocus(focusListener); } @RequiresApi(26) private void abandonAudioFocusV26() { if (audioFocusRequest != null) { - audioManager.abandonAudioFocusRequest(audioFocusRequest); + getAudioManager().abandonAudioFocusRequest(audioFocusRequest); } } @@ -455,6 +453,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } } + private AudioManager getAudioManager() { + if (audioManager == null) { + audioManager = (AudioManager) applicationContext.getSystemService(Context.AUDIO_SERVICE); + } + return audioManager; + } + // Internal audio focus listener. private class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener { From 0a0444b9a536c8e95178ee316e5157f099440609 Mon Sep 17 00:00:00 2001 From: Colin Kho Date: Wed, 14 Aug 2024 10:35:29 -0700 Subject: [PATCH 2/5] Use Suppliers.memoize for lazy instantiation of AudioManager --- .../media3/exoplayer/AudioFocusManager.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java index 29a98708ce..72c16f33a1 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java @@ -32,6 +32,8 @@ import androidx.media3.common.Player; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -161,14 +163,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private static final float VOLUME_MULTIPLIER_DEFAULT = 1.0f; private final AudioFocusListener focusListener; - private final Context applicationContext; + private final Supplier audioManager; @Nullable private PlayerControl playerControl; @Nullable private AudioAttributes audioAttributes; - @Nullable private AudioManager audioManager; private @AudioFocusState int audioFocusState; private @AudioFocusGain int focusGainToRequest; private float volumeMultiplier = VOLUME_MULTIPLIER_DEFAULT; - private @MonotonicNonNull AudioFocusRequest audioFocusRequest; private boolean rebuildAudioFocusRequest; @@ -180,7 +180,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * @param playerControl A {@link PlayerControl} to handle commands from this instance. */ public AudioFocusManager(Context context, Handler eventHandler, PlayerControl playerControl) { - this.applicationContext = context; + this.audioManager = + Suppliers.memoize(() -> checkNotNull( + (AudioManager) context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE))); this.playerControl = playerControl; this.focusListener = new AudioFocusListener(eventHandler); this.audioFocusState = AUDIO_FOCUS_STATE_NOT_REQUESTED; @@ -285,7 +287,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } private int requestAudioFocusDefault() { - return getAudioManager().requestAudioFocus( + return audioManager.get().requestAudioFocus( focusListener, Util.getStreamTypeForAudioUsage(checkNotNull(audioAttributes).usage), focusGainToRequest); @@ -310,17 +312,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; rebuildAudioFocusRequest = false; } - return getAudioManager().requestAudioFocus(audioFocusRequest); + return audioManager.get().requestAudioFocus(audioFocusRequest); } private void abandonAudioFocusDefault() { - getAudioManager().abandonAudioFocus(focusListener); + audioManager.get().abandonAudioFocus(focusListener); } @RequiresApi(26) private void abandonAudioFocusV26() { if (audioFocusRequest != null) { - getAudioManager().abandonAudioFocusRequest(audioFocusRequest); + audioManager.get().abandonAudioFocusRequest(audioFocusRequest); } } @@ -453,13 +455,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } } - private AudioManager getAudioManager() { - if (audioManager == null) { - audioManager = (AudioManager) applicationContext.getSystemService(Context.AUDIO_SERVICE); - } - return audioManager; - } - // Internal audio focus listener. private class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener { From a6f5d3daf59ad19e6fa025a3cbfbd197dd5e23cb Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Thu, 15 Aug 2024 12:21:53 +0100 Subject: [PATCH 3/5] Format with google-java-format --- .../media3/exoplayer/AudioFocusManager.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java index 72c16f33a1..95407e6a2a 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java @@ -181,8 +181,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; */ public AudioFocusManager(Context context, Handler eventHandler, PlayerControl playerControl) { this.audioManager = - Suppliers.memoize(() -> checkNotNull( - (AudioManager) context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE))); + Suppliers.memoize( + () -> + checkNotNull( + (AudioManager) + context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE))); this.playerControl = playerControl; this.focusListener = new AudioFocusListener(eventHandler); this.audioFocusState = AUDIO_FOCUS_STATE_NOT_REQUESTED; @@ -287,10 +290,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } private int requestAudioFocusDefault() { - return audioManager.get().requestAudioFocus( - focusListener, - Util.getStreamTypeForAudioUsage(checkNotNull(audioAttributes).usage), - focusGainToRequest); + return audioManager + .get() + .requestAudioFocus( + focusListener, + Util.getStreamTypeForAudioUsage(checkNotNull(audioAttributes).usage), + focusGainToRequest); } @RequiresApi(26) From 9c25845cd799d138993ba2b34e81fc6a0b4fecef Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Tue, 20 Aug 2024 17:45:14 +0100 Subject: [PATCH 4/5] Restore a couple of blank lines --- .../main/java/androidx/media3/exoplayer/AudioFocusManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java index 95407e6a2a..c82281cae4 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioFocusManager.java @@ -162,10 +162,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private static final float VOLUME_MULTIPLIER_DUCK = 0.2f; private static final float VOLUME_MULTIPLIER_DEFAULT = 1.0f; - private final AudioFocusListener focusListener; private final Supplier audioManager; + private final AudioFocusListener focusListener; @Nullable private PlayerControl playerControl; @Nullable private AudioAttributes audioAttributes; + private @AudioFocusState int audioFocusState; private @AudioFocusGain int focusGainToRequest; private float volumeMultiplier = VOLUME_MULTIPLIER_DEFAULT; From bed1dadcbf75f930823f4022f488bd45598826ec Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Tue, 20 Aug 2024 17:50:45 +0100 Subject: [PATCH 5/5] Add release note --- RELEASENOTES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 37d29c1494..c39f102309 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -34,6 +34,11 @@ API 35+ (where the device advertises support for this). * Handle preload callbacks asynchronously in `PreloadMediaSource` ([#1568](https://github.com/androidx/media/issues/1568)). + * Defer the blocking call to + `Context.getSystemService(Context.AUDIO_SERVICE)` until audio focus + handling is enabled. This ensures the blocking call isn't done if audio + focus handling is not enabled + ([#1616](https://github.com/androidx/media/pull/1616)). * Transformer: * Add `SurfaceAssetLoader`, which supports queueing video data to Transformer via a `Surface`.