Add DownloadManager.getApplicationLooper

This is equivalent to the method ExoPlayer provides. It's nice for consistency,
and for retrieving the looper from test code.

PiperOrigin-RevId: 308830288
This commit is contained in:
olly 2020-04-28 16:45:32 +01:00 committed by Oliver Woodman
parent c746885ca2
commit 528104919f
4 changed files with 39 additions and 30 deletions

View file

@ -153,14 +153,14 @@ public final class ExoPlayerFactory {
RenderersFactory renderersFactory, RenderersFactory renderersFactory,
TrackSelector trackSelector, TrackSelector trackSelector,
LoadControl loadControl, LoadControl loadControl,
Looper looper) { Looper applicationLooper) {
return newSimpleInstance( return newSimpleInstance(
context, context,
renderersFactory, renderersFactory,
trackSelector, trackSelector,
loadControl, loadControl,
new AnalyticsCollector(Clock.DEFAULT), new AnalyticsCollector(Clock.DEFAULT),
looper); applicationLooper);
} }
/** @deprecated Use {@link SimpleExoPlayer.Builder} instead. */ /** @deprecated Use {@link SimpleExoPlayer.Builder} instead. */
@ -172,7 +172,7 @@ public final class ExoPlayerFactory {
TrackSelector trackSelector, TrackSelector trackSelector,
LoadControl loadControl, LoadControl loadControl,
AnalyticsCollector analyticsCollector, AnalyticsCollector analyticsCollector,
Looper looper) { Looper applicationLooper) {
return newSimpleInstance( return newSimpleInstance(
context, context,
renderersFactory, renderersFactory,
@ -180,7 +180,7 @@ public final class ExoPlayerFactory {
loadControl, loadControl,
DefaultBandwidthMeter.getSingletonInstance(context), DefaultBandwidthMeter.getSingletonInstance(context),
analyticsCollector, analyticsCollector,
looper); applicationLooper);
} }
/** @deprecated Use {@link SimpleExoPlayer.Builder} instead. */ /** @deprecated Use {@link SimpleExoPlayer.Builder} instead. */
@ -193,7 +193,7 @@ public final class ExoPlayerFactory {
LoadControl loadControl, LoadControl loadControl,
BandwidthMeter bandwidthMeter, BandwidthMeter bandwidthMeter,
AnalyticsCollector analyticsCollector, AnalyticsCollector analyticsCollector,
Looper looper) { Looper applicationLooper) {
return new SimpleExoPlayer( return new SimpleExoPlayer(
context, context,
renderersFactory, renderersFactory,
@ -204,7 +204,7 @@ public final class ExoPlayerFactory {
analyticsCollector, analyticsCollector,
/* useLazyPreparation= */ true, /* useLazyPreparation= */ true,
Clock.DEFAULT, Clock.DEFAULT,
looper); applicationLooper);
} }
/** @deprecated Use {@link ExoPlayer.Builder} instead. */ /** @deprecated Use {@link ExoPlayer.Builder} instead. */
@ -231,14 +231,14 @@ public final class ExoPlayerFactory {
Renderer[] renderers, Renderer[] renderers,
TrackSelector trackSelector, TrackSelector trackSelector,
LoadControl loadControl, LoadControl loadControl,
Looper looper) { Looper applicationLooper) {
return newInstance( return newInstance(
context, context,
renderers, renderers,
trackSelector, trackSelector,
loadControl, loadControl,
DefaultBandwidthMeter.getSingletonInstance(context), DefaultBandwidthMeter.getSingletonInstance(context),
looper); applicationLooper);
} }
/** @deprecated Use {@link ExoPlayer.Builder} instead. */ /** @deprecated Use {@link ExoPlayer.Builder} instead. */
@ -249,7 +249,7 @@ public final class ExoPlayerFactory {
TrackSelector trackSelector, TrackSelector trackSelector,
LoadControl loadControl, LoadControl loadControl,
BandwidthMeter bandwidthMeter, BandwidthMeter bandwidthMeter,
Looper looper) { Looper applicationLooper) {
return new ExoPlayerImpl( return new ExoPlayerImpl(
renderers, renderers,
trackSelector, trackSelector,
@ -259,6 +259,6 @@ public final class ExoPlayerFactory {
/* analyticsCollector= */ null, /* analyticsCollector= */ null,
/* useLazyPreparation= */ true, /* useLazyPreparation= */ true,
Clock.DEFAULT, Clock.DEFAULT,
looper); applicationLooper);
} }
} }

View file

@ -65,7 +65,7 @@ import java.util.concurrent.TimeoutException;
private final Renderer[] renderers; private final Renderer[] renderers;
private final TrackSelector trackSelector; private final TrackSelector trackSelector;
private final Handler eventHandler; private final Handler applicationHandler;
private final ExoPlayerImplInternal internalPlayer; private final ExoPlayerImplInternal internalPlayer;
private final Handler internalPlayerHandler; private final Handler internalPlayerHandler;
private final CopyOnWriteArrayList<ListenerHolder> listeners; private final CopyOnWriteArrayList<ListenerHolder> listeners;
@ -110,8 +110,8 @@ import java.util.concurrent.TimeoutException;
* loads and other initial preparation steps happen immediately. If true, these initial * loads and other initial preparation steps happen immediately. If true, these initial
* preparations are triggered only when the player starts buffering the media. * preparations are triggered only when the player starts buffering the media.
* @param clock The {@link Clock}. * @param clock The {@link Clock}.
* @param looper The {@link Looper} which must be used for all calls to the player and which is * @param applicationLooper The {@link Looper} that must be used for all calls to the player and
* used to call listeners on. * which is used to call listeners on.
*/ */
@SuppressLint("HandlerLeak") @SuppressLint("HandlerLeak")
public ExoPlayerImpl( public ExoPlayerImpl(
@ -123,7 +123,7 @@ import java.util.concurrent.TimeoutException;
@Nullable AnalyticsCollector analyticsCollector, @Nullable AnalyticsCollector analyticsCollector,
boolean useLazyPreparation, boolean useLazyPreparation,
Clock clock, Clock clock,
Looper looper) { Looper applicationLooper) {
Log.i(TAG, "Init " + Integer.toHexString(System.identityHashCode(this)) + " [" Log.i(TAG, "Init " + Integer.toHexString(System.identityHashCode(this)) + " ["
+ ExoPlayerLibraryInfo.VERSION_SLASHY + "] [" + Util.DEVICE_DEBUG_INFO + "]"); + ExoPlayerLibraryInfo.VERSION_SLASHY + "] [" + Util.DEVICE_DEBUG_INFO + "]");
Assertions.checkState(renderers.length > 0); Assertions.checkState(renderers.length > 0);
@ -144,8 +144,8 @@ import java.util.concurrent.TimeoutException;
playbackSpeed = Player.DEFAULT_PLAYBACK_SPEED; playbackSpeed = Player.DEFAULT_PLAYBACK_SPEED;
seekParameters = SeekParameters.DEFAULT; seekParameters = SeekParameters.DEFAULT;
maskingWindowIndex = C.INDEX_UNSET; maskingWindowIndex = C.INDEX_UNSET;
eventHandler = applicationHandler =
new Handler(looper) { new Handler(applicationLooper) {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
ExoPlayerImpl.this.handleEvent(msg); ExoPlayerImpl.this.handleEvent(msg);
@ -166,7 +166,7 @@ import java.util.concurrent.TimeoutException;
repeatMode, repeatMode,
shuffleModeEnabled, shuffleModeEnabled,
analyticsCollector, analyticsCollector,
eventHandler, applicationHandler,
clock); clock);
internalPlayerHandler = new Handler(internalPlayer.getPlaybackLooper()); internalPlayerHandler = new Handler(internalPlayer.getPlaybackLooper());
} }
@ -232,7 +232,7 @@ import java.util.concurrent.TimeoutException;
@Override @Override
public Looper getApplicationLooper() { public Looper getApplicationLooper() {
return eventHandler.getLooper(); return applicationHandler.getLooper();
} }
@Override @Override
@ -568,7 +568,7 @@ import java.util.concurrent.TimeoutException;
// general because the midroll ad preceding the seek destination must be played before the // general because the midroll ad preceding the seek destination must be played before the
// content position can be played, if a different ad is playing at the moment. // content position can be played, if a different ad is playing at the moment.
Log.w(TAG, "seekTo ignored because an ad is playing"); Log.w(TAG, "seekTo ignored because an ad is playing");
eventHandler applicationHandler
.obtainMessage( .obtainMessage(
ExoPlayerImplInternal.MSG_PLAYBACK_INFO_CHANGED, ExoPlayerImplInternal.MSG_PLAYBACK_INFO_CHANGED,
/* operationAcks */ 1, /* operationAcks */ 1,
@ -690,7 +690,7 @@ import java.util.concurrent.TimeoutException;
ExoPlaybackException.createForUnexpected( ExoPlaybackException.createForUnexpected(
new RuntimeException(new TimeoutException("Player release timed out."))))); new RuntimeException(new TimeoutException("Player release timed out.")))));
} }
eventHandler.removeCallbacksAndMessages(null); applicationHandler.removeCallbacksAndMessages(null);
playbackInfo = playbackInfo =
getResetPlaybackInfo( getResetPlaybackInfo(
/* clearPlaylist= */ false, /* clearPlaylist= */ false,

View file

@ -343,7 +343,6 @@ public class SimpleExoPlayer extends BasePlayer
protected final Renderer[] renderers; protected final Renderer[] renderers;
private final ExoPlayerImpl player; private final ExoPlayerImpl player;
private final Handler eventHandler;
private final ComponentListener componentListener; private final ComponentListener componentListener;
private final CopyOnWriteArraySet<com.google.android.exoplayer2.video.VideoListener> private final CopyOnWriteArraySet<com.google.android.exoplayer2.video.VideoListener>
videoListeners; videoListeners;
@ -420,8 +419,8 @@ public class SimpleExoPlayer extends BasePlayer
* preparations are triggered only when the player starts buffering the media. * preparations are triggered only when the player starts buffering the media.
* @param clock The {@link Clock} that will be used by the instance. Should always be {@link * @param clock The {@link Clock} that will be used by the instance. Should always be {@link
* Clock#DEFAULT}, unless the player is being used from a test. * Clock#DEFAULT}, unless the player is being used from a test.
* @param looper The {@link Looper} which must be used for all calls to the player and which is * @param applicationLooper The {@link Looper} which must be used for all calls to the player and
* used to call listeners on. * which is used to call listeners on.
*/ */
protected SimpleExoPlayer( protected SimpleExoPlayer(
Context context, Context context,
@ -433,7 +432,7 @@ public class SimpleExoPlayer extends BasePlayer
AnalyticsCollector analyticsCollector, AnalyticsCollector analyticsCollector,
boolean useLazyPreparation, boolean useLazyPreparation,
Clock clock, Clock clock,
Looper looper) { Looper applicationLooper) {
this.bandwidthMeter = bandwidthMeter; this.bandwidthMeter = bandwidthMeter;
this.analyticsCollector = analyticsCollector; this.analyticsCollector = analyticsCollector;
componentListener = new ComponentListener(); componentListener = new ComponentListener();
@ -444,7 +443,7 @@ public class SimpleExoPlayer extends BasePlayer
deviceListeners = new CopyOnWriteArraySet<>(); deviceListeners = new CopyOnWriteArraySet<>();
videoDebugListeners = new CopyOnWriteArraySet<>(); videoDebugListeners = new CopyOnWriteArraySet<>();
audioDebugListeners = new CopyOnWriteArraySet<>(); audioDebugListeners = new CopyOnWriteArraySet<>();
eventHandler = new Handler(looper); Handler eventHandler = new Handler(applicationLooper);
renderers = renderers =
renderersFactory.createRenderers( renderersFactory.createRenderers(
eventHandler, eventHandler,
@ -471,7 +470,7 @@ public class SimpleExoPlayer extends BasePlayer
analyticsCollector, analyticsCollector,
useLazyPreparation, useLazyPreparation,
clock, clock,
looper); applicationLooper);
analyticsCollector.setPlayer(player); analyticsCollector.setPlayer(player);
player.addListener(analyticsCollector); player.addListener(analyticsCollector);
player.addListener(componentListener); player.addListener(componentListener);

View file

@ -62,7 +62,9 @@ import java.util.concurrent.CopyOnWriteArraySet;
* *
* <p>A download manager instance must be accessed only from the thread that created it, unless that * <p>A download manager instance must be accessed only from the thread that created it, unless that
* thread does not have a {@link Looper}. In that case, it must be accessed only from the * thread does not have a {@link Looper}. In that case, it must be accessed only from the
* application's main thread. Registered listeners will be called on the same thread. * application's main thread. Registered listeners will be called on the same thread. In all cases
* the `Looper` of the thread from which the manager must be accessed can be queried using {@link
* #getApplicationLooper()}.
*/ */
public final class DownloadManager { public final class DownloadManager {
@ -167,7 +169,7 @@ public final class DownloadManager {
private final Context context; private final Context context;
private final WritableDownloadIndex downloadIndex; private final WritableDownloadIndex downloadIndex;
private final Handler mainHandler; private final Handler applicationHandler;
private final InternalHandler internalHandler; private final InternalHandler internalHandler;
private final RequirementsWatcher.Listener requirementsListener; private final RequirementsWatcher.Listener requirementsListener;
private final CopyOnWriteArraySet<Listener> listeners; private final CopyOnWriteArraySet<Listener> listeners;
@ -224,7 +226,7 @@ public final class DownloadManager {
@SuppressWarnings("methodref.receiver.bound.invalid") @SuppressWarnings("methodref.receiver.bound.invalid")
Handler mainHandler = Util.createHandler(this::handleMainMessage); Handler mainHandler = Util.createHandler(this::handleMainMessage);
this.mainHandler = mainHandler; this.applicationHandler = mainHandler;
HandlerThread internalThread = new HandlerThread("ExoPlayer:DownloadManager"); HandlerThread internalThread = new HandlerThread("ExoPlayer:DownloadManager");
internalThread.start(); internalThread.start();
internalHandler = internalHandler =
@ -250,6 +252,14 @@ public final class DownloadManager {
.sendToTarget(); .sendToTarget();
} }
/**
* Returns the {@link Looper} associated with the application thread that's used to access the
* manager, and on which the manager will call its {@link Listener Listeners}.
*/
public Looper getApplicationLooper() {
return applicationHandler.getLooper();
}
/** Returns whether the manager has completed initialization. */ /** Returns whether the manager has completed initialization. */
public boolean isInitialized() { public boolean isInitialized() {
return initialized; return initialized;
@ -488,7 +498,7 @@ public final class DownloadManager {
// Restore the interrupted status. // Restore the interrupted status.
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
mainHandler.removeCallbacksAndMessages(/* token= */ null); applicationHandler.removeCallbacksAndMessages(/* token= */ null);
// Reset state. // Reset state.
downloads = Collections.emptyList(); downloads = Collections.emptyList();
pendingMessages = 0; pendingMessages = 0;