Move offload events to their own listener
Move offload events from Player.EventListener to ExoPlayer.AudioOffloadListener. PiperOrigin-RevId: 362472462
This commit is contained in:
parent
b563b82787
commit
3f4f2f90b5
@ -612,24 +612,6 @@ public interface Player {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
default void onSeekProcessed() {}
|
default void onSeekProcessed() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the player has started or stopped offload scheduling.
|
|
||||||
*
|
|
||||||
* <p>If using ExoPlayer, this is done by calling {@code
|
|
||||||
* ExoPlayer#experimentalSetOffloadSchedulingEnabled(boolean)}.
|
|
||||||
*
|
|
||||||
* <p>This method is experimental, and will be renamed or removed in a future release.
|
|
||||||
*/
|
|
||||||
// TODO(b/172315872) Move this method in a new ExoPlayer.EventListener.
|
|
||||||
default void onExperimentalOffloadSchedulingEnabledChanged(boolean offloadSchedulingEnabled) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the player has started or finished sleeping for offload.
|
|
||||||
*
|
|
||||||
* <p>This method is experimental, and will be renamed or removed in a future release.
|
|
||||||
*/
|
|
||||||
default void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when one or more player states changed.
|
* Called when one or more player states changed.
|
||||||
*
|
*
|
||||||
|
@ -140,6 +140,28 @@ public interface ExoPlayer extends Player {
|
|||||||
*/
|
*/
|
||||||
long DEFAULT_RELEASE_TIMEOUT_MS = 500;
|
long DEFAULT_RELEASE_TIMEOUT_MS = 500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener for audio offload events.
|
||||||
|
*
|
||||||
|
* <p>This class is experimental, and might be renamed, moved or removed in a future release.
|
||||||
|
*/
|
||||||
|
interface AudioOffloadListener {
|
||||||
|
/**
|
||||||
|
* Called when the player has started or stopped offload scheduling using {@link
|
||||||
|
* ExoPlayer#experimentalSetOffloadSchedulingEnabled(boolean)}.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
|
*/
|
||||||
|
default void onExperimentalOffloadSchedulingEnabledChanged(boolean offloadSchedulingEnabled) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the player has started or finished sleeping for offload.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
|
*/
|
||||||
|
default void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder for {@link ExoPlayer} instances.
|
* A builder for {@link ExoPlayer} instances.
|
||||||
*
|
*
|
||||||
@ -450,6 +472,20 @@ public interface ExoPlayer extends Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a listener to receive audio offload events.
|
||||||
|
*
|
||||||
|
* @param listener The listener to register.
|
||||||
|
*/
|
||||||
|
void addAudioOffloadListener(AudioOffloadListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a listener of audio offload events.
|
||||||
|
*
|
||||||
|
* @param listener The listener to unregister.
|
||||||
|
*/
|
||||||
|
void removeAudioOffloadListener(AudioOffloadListener listener);
|
||||||
|
|
||||||
/** Returns the number of renderers. */
|
/** Returns the number of renderers. */
|
||||||
int getRendererCount();
|
int getRendererCount();
|
||||||
|
|
||||||
@ -665,7 +701,7 @@ public interface ExoPlayer extends Player {
|
|||||||
* <p>While offload scheduling is enabled, player events may be delivered severely delayed and
|
* <p>While offload scheduling is enabled, player events may be delivered severely delayed and
|
||||||
* apps should not interact with the player. When returning to the foreground, disable offload
|
* apps should not interact with the player. When returning to the foreground, disable offload
|
||||||
* scheduling and wait for {@link
|
* scheduling and wait for {@link
|
||||||
* Player.EventListener#onExperimentalOffloadSchedulingEnabledChanged(boolean)} to be called with
|
* AudioOffloadListener#onExperimentalOffloadSchedulingEnabledChanged(boolean)} to be called with
|
||||||
* {@code offloadSchedulingEnabled = false} before interacting with the player.
|
* {@code offloadSchedulingEnabled = false} before interacting with the player.
|
||||||
*
|
*
|
||||||
* <p>This mode should save significant power when the phone is playing offload audio with the
|
* <p>This mode should save significant power when the phone is playing offload audio with the
|
||||||
@ -697,7 +733,7 @@ public interface ExoPlayer extends Player {
|
|||||||
* Returns whether the player has paused its main loop to save power in offload scheduling mode.
|
* Returns whether the player has paused its main loop to save power in offload scheduling mode.
|
||||||
*
|
*
|
||||||
* @see #experimentalSetOffloadSchedulingEnabled(boolean)
|
* @see #experimentalSetOffloadSchedulingEnabled(boolean)
|
||||||
* @see EventListener#onExperimentalSleepingForOffloadChanged(boolean)
|
* @see AudioOffloadListener#onExperimentalSleepingForOffloadChanged(boolean)
|
||||||
*/
|
*/
|
||||||
boolean experimentalIsSleepingForOffload();
|
boolean experimentalIsSleepingForOffload();
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link ExoPlayer} implementation. Instances can be obtained from {@link ExoPlayer.Builder}.
|
* An {@link ExoPlayer} implementation. Instances can be obtained from {@link ExoPlayer.Builder}.
|
||||||
@ -72,6 +73,7 @@ import java.util.List;
|
|||||||
private final ExoPlayerImplInternal.PlaybackInfoUpdateListener playbackInfoUpdateListener;
|
private final ExoPlayerImplInternal.PlaybackInfoUpdateListener playbackInfoUpdateListener;
|
||||||
private final ExoPlayerImplInternal internalPlayer;
|
private final ExoPlayerImplInternal internalPlayer;
|
||||||
private final ListenerSet<Player.EventListener> listeners;
|
private final ListenerSet<Player.EventListener> listeners;
|
||||||
|
private final CopyOnWriteArraySet<AudioOffloadListener> audioOffloadListeners;
|
||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
private final List<MediaSourceHolderSnapshot> mediaSourceHolderSnapshots;
|
private final List<MediaSourceHolderSnapshot> mediaSourceHolderSnapshots;
|
||||||
private final boolean useLazyPreparation;
|
private final boolean useLazyPreparation;
|
||||||
@ -166,6 +168,7 @@ import java.util.List;
|
|||||||
applicationLooper,
|
applicationLooper,
|
||||||
clock,
|
clock,
|
||||||
(listener, flags) -> listener.onEvents(playerForListeners, new Events(flags)));
|
(listener, flags) -> listener.onEvents(playerForListeners, new Events(flags)));
|
||||||
|
audioOffloadListeners = new CopyOnWriteArraySet<>();
|
||||||
mediaSourceHolderSnapshots = new ArrayList<>();
|
mediaSourceHolderSnapshots = new ArrayList<>();
|
||||||
shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0);
|
shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0);
|
||||||
emptyTrackSelectorResult =
|
emptyTrackSelectorResult =
|
||||||
@ -284,6 +287,16 @@ import java.util.List;
|
|||||||
listeners.remove(listener);
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAudioOffloadListener(AudioOffloadListener listener) {
|
||||||
|
audioOffloadListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAudioOffloadListener(AudioOffloadListener listener) {
|
||||||
|
audioOffloadListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCommandAvailable(@Command int command) {
|
public boolean isCommandAvailable(@Command int command) {
|
||||||
return availableCommands.contains(command);
|
return availableCommands.contains(command);
|
||||||
@ -1099,21 +1112,20 @@ import java.util.List;
|
|||||||
if (seekProcessed) {
|
if (seekProcessed) {
|
||||||
listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed);
|
listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed);
|
||||||
}
|
}
|
||||||
if (previousPlaybackInfo.offloadSchedulingEnabled != newPlaybackInfo.offloadSchedulingEnabled) {
|
|
||||||
listeners.queueEvent(
|
|
||||||
/* eventFlag= */ C.INDEX_UNSET,
|
|
||||||
listener ->
|
|
||||||
listener.onExperimentalOffloadSchedulingEnabledChanged(
|
|
||||||
newPlaybackInfo.offloadSchedulingEnabled));
|
|
||||||
}
|
|
||||||
if (previousPlaybackInfo.sleepingForOffload != newPlaybackInfo.sleepingForOffload) {
|
|
||||||
listeners.queueEvent(
|
|
||||||
/* eventFlag= */ C.INDEX_UNSET,
|
|
||||||
listener ->
|
|
||||||
listener.onExperimentalSleepingForOffloadChanged(newPlaybackInfo.sleepingForOffload));
|
|
||||||
}
|
|
||||||
updateAvailableCommands();
|
updateAvailableCommands();
|
||||||
listeners.flushEvents();
|
listeners.flushEvents();
|
||||||
|
|
||||||
|
if (previousPlaybackInfo.offloadSchedulingEnabled != newPlaybackInfo.offloadSchedulingEnabled) {
|
||||||
|
for (AudioOffloadListener listener : audioOffloadListeners) {
|
||||||
|
listener.onExperimentalOffloadSchedulingEnabledChanged(
|
||||||
|
newPlaybackInfo.offloadSchedulingEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (previousPlaybackInfo.sleepingForOffload != newPlaybackInfo.sleepingForOffload) {
|
||||||
|
for (AudioOffloadListener listener : audioOffloadListeners) {
|
||||||
|
listener.onExperimentalSleepingForOffloadChanged(newPlaybackInfo.sleepingForOffload);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<Boolean, Integer> evaluateMediaItemTransitionReason(
|
private Pair<Boolean, Integer> evaluateMediaItemTransitionReason(
|
||||||
|
@ -685,6 +685,7 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
builder.looper,
|
builder.looper,
|
||||||
/* wrappingPlayer= */ this);
|
/* wrappingPlayer= */ this);
|
||||||
player.addListener(componentListener);
|
player.addListener(componentListener);
|
||||||
|
player.addAudioOffloadListener(componentListener);
|
||||||
|
|
||||||
audioBecomingNoisyManager =
|
audioBecomingNoisyManager =
|
||||||
new AudioBecomingNoisyManager(builder.context, eventHandler, componentListener);
|
new AudioBecomingNoisyManager(builder.context, eventHandler, componentListener);
|
||||||
@ -894,6 +895,18 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAudioOffloadListener(AudioOffloadListener listener) {
|
||||||
|
// Don't verify application thread. We allow calls to this method from any thread.
|
||||||
|
player.addAudioOffloadListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAudioOffloadListener(AudioOffloadListener listener) {
|
||||||
|
// Don't verify application thread. We allow calls to this method from any thread.
|
||||||
|
player.removeAudioOffloadListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAudioListener(AudioListener listener) {
|
public void addAudioListener(AudioListener listener) {
|
||||||
// Don't verify application thread. We allow calls to this method from any thread.
|
// Don't verify application thread. We allow calls to this method from any thread.
|
||||||
@ -1973,7 +1986,8 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
AudioFocusManager.PlayerControl,
|
AudioFocusManager.PlayerControl,
|
||||||
AudioBecomingNoisyManager.EventListener,
|
AudioBecomingNoisyManager.EventListener,
|
||||||
StreamVolumeManager.Listener,
|
StreamVolumeManager.Listener,
|
||||||
Player.EventListener {
|
Player.EventListener,
|
||||||
|
AudioOffloadListener {
|
||||||
|
|
||||||
// VideoRendererEventListener implementation
|
// VideoRendererEventListener implementation
|
||||||
|
|
||||||
@ -2241,6 +2255,8 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
updateWakeAndWifiLock();
|
updateWakeAndWifiLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Player.AudioOffloadListener implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {
|
public void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {
|
||||||
updateWakeAndWifiLock();
|
updateWakeAndWifiLock();
|
||||||
|
@ -210,46 +210,48 @@ public class TestPlayerRunHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs tasks of the main {@link Looper} until a {@link
|
* Runs tasks of the main {@link Looper} until a {@link
|
||||||
* Player.EventListener#onExperimentalOffloadSchedulingEnabledChanged} callback occurred.
|
* ExoPlayer.AudioOffloadListener#onExperimentalOffloadSchedulingEnabledChanged} callback
|
||||||
|
* occurred.
|
||||||
*
|
*
|
||||||
* @param player The {@link Player}.
|
* @param player The {@link Player}.
|
||||||
* @return The new offloadSchedulingEnabled state.
|
* @return The new offloadSchedulingEnabled state.
|
||||||
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||||
* exceeded.
|
* exceeded.
|
||||||
*/
|
*/
|
||||||
public static boolean runUntilReceiveOffloadSchedulingEnabledNewState(Player player)
|
public static boolean runUntilReceiveOffloadSchedulingEnabledNewState(ExoPlayer player)
|
||||||
throws TimeoutException {
|
throws TimeoutException {
|
||||||
verifyMainTestThread(player);
|
verifyMainTestThread(player);
|
||||||
AtomicReference<@NullableType Boolean> offloadSchedulingEnabledReceiver =
|
AtomicReference<@NullableType Boolean> offloadSchedulingEnabledReceiver =
|
||||||
new AtomicReference<>();
|
new AtomicReference<>();
|
||||||
Player.EventListener listener =
|
ExoPlayer.AudioOffloadListener listener =
|
||||||
new Player.EventListener() {
|
new ExoPlayer.AudioOffloadListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onExperimentalOffloadSchedulingEnabledChanged(
|
public void onExperimentalOffloadSchedulingEnabledChanged(
|
||||||
boolean offloadSchedulingEnabled) {
|
boolean offloadSchedulingEnabled) {
|
||||||
offloadSchedulingEnabledReceiver.set(offloadSchedulingEnabled);
|
offloadSchedulingEnabledReceiver.set(offloadSchedulingEnabled);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
player.addListener(listener);
|
player.addAudioOffloadListener(listener);
|
||||||
runMainLooperUntil(() -> offloadSchedulingEnabledReceiver.get() != null);
|
runMainLooperUntil(() -> offloadSchedulingEnabledReceiver.get() != null);
|
||||||
return Assertions.checkNotNull(offloadSchedulingEnabledReceiver.get());
|
return Assertions.checkNotNull(offloadSchedulingEnabledReceiver.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs tasks of the main {@link Looper} until a {@link
|
* Runs tasks of the main {@link Looper} until a {@link
|
||||||
* Player.EventListener#onExperimentalSleepingForOffloadChanged(boolean)} callback occurred.
|
* ExoPlayer.AudioOffloadListener#onExperimentalSleepingForOffloadChanged(boolean)} callback
|
||||||
|
* occurred.
|
||||||
*
|
*
|
||||||
* @param player The {@link Player}.
|
* @param player The {@link Player}.
|
||||||
* @param expectedSleepForOffload The expected sleep of offload state.
|
* @param expectedSleepForOffload The expected sleep of offload state.
|
||||||
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||||
* exceeded.
|
* exceeded.
|
||||||
*/
|
*/
|
||||||
public static void runUntilSleepingForOffload(Player player, boolean expectedSleepForOffload)
|
public static void runUntilSleepingForOffload(ExoPlayer player, boolean expectedSleepForOffload)
|
||||||
throws TimeoutException {
|
throws TimeoutException {
|
||||||
verifyMainTestThread(player);
|
verifyMainTestThread(player);
|
||||||
AtomicBoolean receiverCallback = new AtomicBoolean(false);
|
AtomicBoolean receiverCallback = new AtomicBoolean(false);
|
||||||
Player.EventListener listener =
|
ExoPlayer.AudioOffloadListener listener =
|
||||||
new Player.EventListener() {
|
new ExoPlayer.AudioOffloadListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {
|
public void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {
|
||||||
if (sleepingForOffload == expectedSleepForOffload) {
|
if (sleepingForOffload == expectedSleepForOffload) {
|
||||||
@ -257,7 +259,7 @@ public class TestPlayerRunHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
player.addListener(listener);
|
player.addAudioOffloadListener(listener);
|
||||||
runMainLooperUntil(
|
runMainLooperUntil(
|
||||||
() -> { // Make sure progress is being made, see [internal: b/170387438#comment2]
|
() -> { // Make sure progress is being made, see [internal: b/170387438#comment2]
|
||||||
assertThat(player.getPlayerError()).isNull();
|
assertThat(player.getPlayerError()).isNull();
|
||||||
|
@ -91,6 +91,16 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAudioOffloadListener(AudioOffloadListener listener) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAudioOffloadListener(AudioOffloadListener listener) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@State
|
@State
|
||||||
public int getPlaybackState() {
|
public int getPlaybackState() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user