Move AudioBecomingNoisyManager system calls off main thread

PiperOrigin-RevId: 722569306
This commit is contained in:
tonihei 2025-02-03 02:14:26 -08:00 committed by Copybara-Service
parent 5f4c30c431
commit 82cb1d8ac7
3 changed files with 49 additions and 19 deletions

View File

@ -15,26 +15,48 @@
*/ */
package androidx.media3.exoplayer; package androidx.media3.exoplayer;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Handler; import android.os.Looper;
import androidx.media3.common.util.Clock;
import androidx.media3.common.util.HandlerWrapper;
/* package */ final class AudioBecomingNoisyManager { /* package */ final class AudioBecomingNoisyManager {
private final Context context; private final Context context;
private final AudioBecomingNoisyReceiver receiver; private final AudioBecomingNoisyReceiver receiver;
private boolean receiverRegistered; private final HandlerWrapper backgroundHandler;
private boolean isEnabled;
public interface EventListener { public interface EventListener {
void onAudioBecomingNoisy(); void onAudioBecomingNoisy();
} }
public AudioBecomingNoisyManager(Context context, Handler eventHandler, EventListener listener) { /**
* Creates the audio becoming noisy manager.
*
* @param context A {@link Context}.
* @param backgroundLooper The playback background {link Looper}.
* @param eventLooper The event listener {@link Looper}.
* @param listener The {@link EventListener}
* @param clock The {@link Clock} to schedule handler messages.
*/
public AudioBecomingNoisyManager(
Context context,
Looper backgroundLooper,
Looper eventLooper,
EventListener listener,
Clock clock) {
this.context = context.getApplicationContext(); this.context = context.getApplicationContext();
this.receiver = new AudioBecomingNoisyReceiver(eventHandler, listener); this.backgroundHandler = clock.createHandler(backgroundLooper, /* callback= */ null);
this.receiver =
new AudioBecomingNoisyReceiver(
clock.createHandler(eventLooper, /* callback= */ null), listener);
} }
/** /**
@ -44,22 +66,28 @@ import android.os.Handler;
* *
* @param enabled True if the listener should be notified when audio is becoming noisy. * @param enabled True if the listener should be notified when audio is becoming noisy.
*/ */
@SuppressLint("UnprotectedReceiver") // Protected system broadcasts must not specify protection.
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
if (enabled && !receiverRegistered) { if (enabled == isEnabled) {
return;
}
if (enabled) {
backgroundHandler.post(
() ->
context.registerReceiver( context.registerReceiver(
receiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); receiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)));
receiverRegistered = true; isEnabled = true;
} else if (!enabled && receiverRegistered) { } else {
context.unregisterReceiver(receiver); backgroundHandler.post(() -> context.unregisterReceiver(receiver));
receiverRegistered = false; isEnabled = false;
} }
} }
private final class AudioBecomingNoisyReceiver extends BroadcastReceiver implements Runnable { private final class AudioBecomingNoisyReceiver extends BroadcastReceiver {
private final EventListener listener; private final EventListener listener;
private final Handler eventHandler; private final HandlerWrapper eventHandler;
public AudioBecomingNoisyReceiver(Handler eventHandler, EventListener listener) { public AudioBecomingNoisyReceiver(HandlerWrapper eventHandler, EventListener listener) {
this.eventHandler = eventHandler; this.eventHandler = eventHandler;
this.listener = listener; this.listener = listener;
} }
@ -67,13 +95,12 @@ import android.os.Handler;
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
eventHandler.post(this); eventHandler.post(this::callListenerIfEnabled);
} }
} }
@Override private void callListenerIfEnabled() {
public void run() { if (isEnabled) {
if (receiverRegistered) {
listener.onAudioBecomingNoisy(); listener.onAudioBecomingNoisy();
} }
} }

View File

@ -402,7 +402,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
} }
audioBecomingNoisyManager = audioBecomingNoisyManager =
new AudioBecomingNoisyManager(builder.context, eventHandler, componentListener); new AudioBecomingNoisyManager(
builder.context, playbackLooper, builder.looper, componentListener, clock);
audioBecomingNoisyManager.setEnabled(builder.handleAudioBecomingNoisy); audioBecomingNoisyManager.setEnabled(builder.handleAudioBecomingNoisy);
audioFocusManager = new AudioFocusManager(builder.context, eventHandler, componentListener); audioFocusManager = new AudioFocusManager(builder.context, eventHandler, componentListener);
audioFocusManager.setAudioAttributes(builder.handleAudioFocus ? audioAttributes : null); audioFocusManager.setAudioAttributes(builder.handleAudioFocus ? audioAttributes : null);

View File

@ -6457,6 +6457,7 @@ public class ExoPlayerTest {
player.play(); player.play();
player.setHandleAudioBecomingNoisy(false); player.setHandleAudioBecomingNoisy(false);
runUntilPendingCommandsAreFullyHandled(player);
deliverBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); deliverBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
runUntilPendingCommandsAreFullyHandled(player); runUntilPendingCommandsAreFullyHandled(player);
boolean playWhenReadyAfterBroadcast = player.getPlayWhenReady(); boolean playWhenReadyAfterBroadcast = player.getPlayWhenReady();
@ -6471,6 +6472,7 @@ public class ExoPlayerTest {
player.play(); player.play();
player.setHandleAudioBecomingNoisy(true); player.setHandleAudioBecomingNoisy(true);
runUntilPendingCommandsAreFullyHandled(player);
deliverBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); deliverBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
runUntilPendingCommandsAreFullyHandled(player); runUntilPendingCommandsAreFullyHandled(player);
boolean playWhenReadyAfterBroadcast = player.getPlayWhenReady(); boolean playWhenReadyAfterBroadcast = player.getPlayWhenReady();