diff --git a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java index 1b595d6886e..eca31c98e44 100644 --- a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java +++ b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java @@ -20,6 +20,7 @@ import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.audio.AudioProcessor; +import com.google.android.exoplayer2.util.Assertions; import com.google.vr.sdk.audio.GvrAudioSurround; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -148,18 +149,21 @@ public int getOutputSampleRateHz() { @Override public void queueInput(ByteBuffer input) { int position = input.position(); + Assertions.checkNotNull(gvrAudioSurround); int readBytes = gvrAudioSurround.addInput(input, position, input.limit() - position); input.position(position + readBytes); } @Override public void queueEndOfStream() { + Assertions.checkNotNull(gvrAudioSurround); inputEnded = true; gvrAudioSurround.triggerProcessing(); } @Override public ByteBuffer getOutput() { + Assertions.checkNotNull(gvrAudioSurround); int writtenBytes = gvrAudioSurround.getOutput(buffer, 0, buffer.capacity()); buffer.position(0).limit(writtenBytes); return buffer; @@ -167,6 +171,7 @@ public ByteBuffer getOutput() { @Override public boolean isEnded() { + Assertions.checkNotNull(gvrAudioSurround); return inputEnded && gvrAudioSurround.getAvailableOutputSize() == 0; } diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsMediaSource.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsMediaSource.java index d3e1d9725e3..19ee3fe10b4 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsMediaSource.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsMediaSource.java @@ -23,6 +23,7 @@ import com.google.android.exoplayer2.source.BaseMediaSource; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSource.SourceInfoRefreshListener; import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.DataSource; @@ -34,12 +35,10 @@ * @deprecated Use com.google.android.exoplayer2.source.ads.AdsMediaSource with ImaAdsLoader. */ @Deprecated -public final class ImaAdsMediaSource extends BaseMediaSource { +public final class ImaAdsMediaSource extends BaseMediaSource implements SourceInfoRefreshListener { private final AdsMediaSource adsMediaSource; - private SourceInfoRefreshListener adsMediaSourceListener; - /** * Constructs a new source that inserts ads linearly with the content specified by * {@code contentMediaSource}. @@ -78,15 +77,7 @@ public ImaAdsMediaSource( @Override public void prepareSourceInternal(final ExoPlayer player, boolean isTopLevelSource) { - adsMediaSourceListener = - new SourceInfoRefreshListener() { - @Override - public void onSourceInfoRefreshed( - MediaSource source, Timeline timeline, @Nullable Object manifest) { - refreshSourceInfo(timeline, manifest); - } - }; - adsMediaSource.prepareSource(player, isTopLevelSource, adsMediaSourceListener); + adsMediaSource.prepareSource(player, isTopLevelSource, /* listener= */ this); } @Override @@ -106,6 +97,12 @@ public void releasePeriod(MediaPeriod mediaPeriod) { @Override public void releaseSourceInternal() { - adsMediaSource.releaseSource(adsMediaSourceListener); + adsMediaSource.releaseSource(/* listener= */ this); + } + + @Override + public void onSourceInfoRefreshed( + MediaSource source, Timeline timeline, @Nullable Object manifest) { + refreshSourceInfo(timeline, manifest); } } diff --git a/extensions/jobdispatcher/src/main/java/com/google/android/exoplayer2/ext/jobdispatcher/JobDispatcherScheduler.java b/extensions/jobdispatcher/src/main/java/com/google/android/exoplayer2/ext/jobdispatcher/JobDispatcherScheduler.java index c6701da9646..f75607f268e 100644 --- a/extensions/jobdispatcher/src/main/java/com/google/android/exoplayer2/ext/jobdispatcher/JobDispatcherScheduler.java +++ b/extensions/jobdispatcher/src/main/java/com/google/android/exoplayer2/ext/jobdispatcher/JobDispatcherScheduler.java @@ -29,6 +29,7 @@ import com.firebase.jobdispatcher.Lifetime; import com.google.android.exoplayer2.scheduler.Requirements; import com.google.android.exoplayer2.scheduler.Scheduler; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; /** @@ -146,11 +147,14 @@ public static final class JobDispatcherSchedulerService extends JobService { public boolean onStartJob(JobParameters params) { logd("JobDispatcherSchedulerService is started"); Bundle extras = params.getExtras(); + Assertions.checkNotNull(extras, "Service started without extras."); Requirements requirements = new Requirements(extras.getInt(KEY_REQUIREMENTS)); if (requirements.checkRequirements(this)) { logd("Requirements are met"); String serviceAction = extras.getString(KEY_SERVICE_ACTION); String servicePackage = extras.getString(KEY_SERVICE_PACKAGE); + Assertions.checkNotNull(serviceAction, "Service action missing."); + Assertions.checkNotNull(servicePackage, "Service package missing."); Intent intent = new Intent(serviceAction).setPackage(servicePackage); logd("Starting service action: " + serviceAction + " package: " + servicePackage); Util.startForegroundService(this, intent); diff --git a/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java b/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java index 03f53c263f5..9937bb7ca0a 100644 --- a/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java +++ b/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java @@ -39,7 +39,7 @@ import com.google.android.exoplayer2.video.VideoListener; /** Leanback {@code PlayerAdapter} implementation for {@link Player}. */ -public final class LeanbackPlayerAdapter extends PlayerAdapter { +public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnable { static { ExoPlayerLibraryInfo.registerModule("goog.exo.leanback"); @@ -49,12 +49,12 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter { private final Player player; private final Handler handler; private final ComponentListener componentListener; - private final Runnable updateProgressRunnable; + private final int updatePeriodMs; private @Nullable PlaybackPreparer playbackPreparer; private ControlDispatcher controlDispatcher; private @Nullable ErrorMessageProvider errorMessageProvider; - private SurfaceHolderGlueHost surfaceHolderGlueHost; + private @Nullable SurfaceHolderGlueHost surfaceHolderGlueHost; private boolean hasSurface; private boolean lastNotifiedPreparedState; @@ -70,18 +70,10 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter { public LeanbackPlayerAdapter(Context context, Player player, final int updatePeriodMs) { this.context = context; this.player = player; + this.updatePeriodMs = updatePeriodMs; handler = new Handler(); componentListener = new ComponentListener(); controlDispatcher = new DefaultControlDispatcher(); - updateProgressRunnable = new Runnable() { - @Override - public void run() { - Callback callback = getCallback(); - callback.onCurrentPositionChanged(LeanbackPlayerAdapter.this); - callback.onBufferedPositionChanged(LeanbackPlayerAdapter.this); - handler.postDelayed(this, updatePeriodMs); - } - }; } /** @@ -138,7 +130,7 @@ public void onDetachedFromHost() { videoComponent.removeVideoListener(componentListener); } if (surfaceHolderGlueHost != null) { - surfaceHolderGlueHost.setSurfaceHolderCallback(null); + removeSurfaceHolderCallback(surfaceHolderGlueHost); surfaceHolderGlueHost = null; } hasSurface = false; @@ -150,9 +142,9 @@ public void onDetachedFromHost() { @Override public void setProgressUpdatingEnabled(boolean enabled) { - handler.removeCallbacks(updateProgressRunnable); + handler.removeCallbacks(this); if (enabled) { - handler.post(updateProgressRunnable); + handler.post(this); } } @@ -211,9 +203,19 @@ public boolean isPrepared() { && (surfaceHolderGlueHost == null || hasSurface); } + // Runnable implementation. + + @Override + public void run() { + Callback callback = getCallback(); + callback.onCurrentPositionChanged(this); + callback.onBufferedPositionChanged(this); + handler.postDelayed(this, updatePeriodMs); + } + // Internal methods. - /* package */ void setVideoSurface(Surface surface) { + /* package */ void setVideoSurface(@Nullable Surface surface) { hasSurface = surface != null; Player.VideoComponent videoComponent = player.getVideoComponent(); if (videoComponent != null) { @@ -241,6 +243,11 @@ private void maybeNotifyPreparedStateChanged(Callback callback) { } } + @SuppressWarnings("nullness:argument.type.incompatible") + private static void removeSurfaceHolderCallback(SurfaceHolderGlueHost surfaceHolderGlueHost) { + surfaceHolderGlueHost.setSurfaceHolderCallback(null); + } + private final class ComponentListener extends Player.DefaultEventListener implements SurfaceHolder.Callback, VideoListener { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Player.java b/library/core/src/main/java/com/google/android/exoplayer2/Player.java index 328816d7096..3075c9273ca 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Player.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Player.java @@ -97,7 +97,7 @@ interface VideoComponent { * * @param surface The {@link Surface}. */ - void setVideoSurface(Surface surface); + void setVideoSurface(@Nullable Surface surface); /** * Clears the {@link Surface} onto which video is being rendered if it matches the one passed.