From 6c65c27e9b130da7f748b80a90a0308eb8a50410 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 2 Dec 2019 13:58:12 +0000 Subject: [PATCH] Remove nullness blacklist for UI module PiperOrigin-RevId: 283324784 --- .../android/exoplayer2/util/Assertions.java | 36 +++++ .../exoplayer2/ui/PlayerControlView.java | 44 ++++-- .../android/exoplayer2/ui/PlayerView.java | 126 ++++++++++-------- 3 files changed, 138 insertions(+), 68 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java b/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java index 9a4891d329..0f3bbfa14d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java @@ -96,6 +96,42 @@ public final class Assertions { } } + /** + * Throws {@link IllegalStateException} if {@code reference} is null. + * + * @param The type of the reference. + * @param reference The reference. + * @return The non-null reference that was validated. + * @throws IllegalStateException If {@code reference} is null. + */ + @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @EnsuresNonNull({"#1"}) + public static T checkStateNotNull(@Nullable T reference) { + if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) { + throw new IllegalStateException(); + } + return reference; + } + + /** + * Throws {@link IllegalStateException} if {@code reference} is null. + * + * @param The type of the reference. + * @param reference The reference. + * @param errorMessage The exception message to use if the check fails. The message is converted + * to a string using {@link String#valueOf(Object)}. + * @return The non-null reference that was validated. + * @throws IllegalStateException If {@code reference} is null. + */ + @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @EnsuresNonNull({"#1"}) + public static T checkStateNotNull(@Nullable T reference, Object errorMessage) { + if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + return reference; + } + /** * Throws {@link NullPointerException} if {@code reference} is null. * diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java index b8642e2e42..a6636d71be 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java @@ -233,18 +233,18 @@ public class PlayerControlView extends FrameLayout { private final ComponentListener componentListener; private final CopyOnWriteArrayList visibilityListeners; - private final View previousButton; - private final View nextButton; - private final View playButton; - private final View pauseButton; - private final View fastForwardButton; - private final View rewindButton; - private final ImageView repeatToggleButton; - private final ImageView shuffleButton; - private final View vrButton; - private final TextView durationView; - private final TextView positionView; - private final TimeBar timeBar; + @Nullable private final View previousButton; + @Nullable private final View nextButton; + @Nullable private final View playButton; + @Nullable private final View pauseButton; + @Nullable private final View fastForwardButton; + @Nullable private final View rewindButton; + @Nullable private final ImageView repeatToggleButton; + @Nullable private final ImageView shuffleButton; + @Nullable private final View vrButton; + @Nullable private final TextView durationView; + @Nullable private final TextView positionView; + @Nullable private final TimeBar timeBar; private final StringBuilder formatBuilder; private final Formatter formatter; private final Timeline.Period period; @@ -299,6 +299,11 @@ public class PlayerControlView extends FrameLayout { this(context, attrs, defStyleAttr, attrs); } + @SuppressWarnings({ + "nullness:argument.type.incompatible", + "nullness:method.invocation.invalid", + "nullness:methodref.receiver.bound.invalid" + }) public PlayerControlView( Context context, @Nullable AttributeSet attrs, @@ -350,7 +355,7 @@ public class PlayerControlView extends FrameLayout { updateProgressAction = this::updateProgress; hideAction = this::hide; - LayoutInflater.from(context).inflate(controllerLayoutId, this); + LayoutInflater.from(context).inflate(controllerLayoutId, /* root= */ this); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); TimeBar customTimeBar = findViewById(R.id.exo_progress); @@ -778,6 +783,8 @@ public class PlayerControlView extends FrameLayout { if (!isVisible() || !isAttachedToWindow) { return; } + + @Nullable Player player = this.player; boolean enableSeeking = false; boolean enablePrevious = false; boolean enableRewind = false; @@ -809,16 +816,20 @@ public class PlayerControlView extends FrameLayout { if (!isVisible() || !isAttachedToWindow || repeatToggleButton == null) { return; } + if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE) { repeatToggleButton.setVisibility(GONE); return; } + + @Nullable Player player = this.player; if (player == null) { setButtonEnabled(false, repeatToggleButton); repeatToggleButton.setImageDrawable(repeatOffButtonDrawable); repeatToggleButton.setContentDescription(repeatOffButtonContentDescription); return; } + setButtonEnabled(true, repeatToggleButton); switch (player.getRepeatMode()) { case Player.REPEAT_MODE_OFF: @@ -843,6 +854,8 @@ public class PlayerControlView extends FrameLayout { if (!isVisible() || !isAttachedToWindow || shuffleButton == null) { return; } + + @Nullable Player player = this.player; if (!showShuffleButton) { shuffleButton.setVisibility(GONE); } else if (player == null) { @@ -861,6 +874,7 @@ public class PlayerControlView extends FrameLayout { } private void updateTimeline() { + @Nullable Player player = this.player; if (player == null) { return; } @@ -935,6 +949,7 @@ public class PlayerControlView extends FrameLayout { return; } + @Nullable Player player = this.player; long position = 0; long bufferedPosition = 0; if (player != null) { @@ -985,7 +1000,7 @@ public class PlayerControlView extends FrameLayout { } } - private void setButtonEnabled(boolean enabled, View view) { + private void setButtonEnabled(boolean enabled, @Nullable View view) { if (view == null) { return; } @@ -1129,6 +1144,7 @@ public class PlayerControlView extends FrameLayout { */ public boolean dispatchMediaKeyEvent(KeyEvent event) { int keyCode = event.getKeyCode(); + @Nullable Player player = this.player; if (player == null || !isHandledMediaKey(keyCode)) { return false; } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java index 2e29dd3388..c55fe09f76 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java @@ -71,6 +71,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; +import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * A high level view for {@link Player} media playbacks. It displays video, subtitles and album art @@ -280,19 +282,19 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider private static final int SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW = 4; // LINT.ThenChange(../../../../../../res/values/attrs.xml) + private final ComponentListener componentListener; @Nullable private final AspectRatioFrameLayout contentFrame; - private final View shutterView; + @Nullable private final View shutterView; @Nullable private final View surfaceView; - private final ImageView artworkView; - private final SubtitleView subtitleView; + @Nullable private final ImageView artworkView; + @Nullable private final SubtitleView subtitleView; @Nullable private final View bufferingView; @Nullable private final TextView errorMessageView; @Nullable private final PlayerControlView controller; - private final ComponentListener componentListener; @Nullable private final FrameLayout adOverlayFrameLayout; @Nullable private final FrameLayout overlayFrameLayout; - private Player player; + @Nullable private Player player; private boolean useController; @Nullable private PlayerControlView.VisibilityListener controllerVisibilityListener; private boolean useArtwork; @@ -318,9 +320,12 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider this(context, attrs, /* defStyleAttr= */ 0); } + @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:method.invocation.invalid"}) public PlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + componentListener = new ComponentListener(); + if (isInEditMode()) { contentFrame = null; shutterView = null; @@ -330,7 +335,6 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider bufferingView = null; errorMessageView = null; controller = null; - componentListener = null; adOverlayFrameLayout = null; overlayFrameLayout = null; ImageView logo = new ImageView(context); @@ -385,7 +389,6 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider } LayoutInflater.from(context).inflate(playerLayoutId, this); - componentListener = new ComponentListener(); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); // Content frame. @@ -540,9 +543,10 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider if (this.player == player) { return; } - if (this.player != null) { - this.player.removeListener(componentListener); - Player.VideoComponent oldVideoComponent = this.player.getVideoComponent(); + @Nullable Player oldPlayer = this.player; + if (oldPlayer != null) { + oldPlayer.removeListener(componentListener); + @Nullable Player.VideoComponent oldVideoComponent = oldPlayer.getVideoComponent(); if (oldVideoComponent != null) { oldVideoComponent.removeVideoListener(componentListener); if (surfaceView instanceof TextureView) { @@ -555,13 +559,13 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider oldVideoComponent.clearVideoSurfaceView((SurfaceView) surfaceView); } } - Player.TextComponent oldTextComponent = this.player.getTextComponent(); + @Nullable Player.TextComponent oldTextComponent = oldPlayer.getTextComponent(); if (oldTextComponent != null) { oldTextComponent.removeTextOutput(componentListener); } } this.player = player; - if (useController) { + if (useController()) { controller.setPlayer(player); } if (subtitleView != null) { @@ -571,7 +575,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider updateErrorMessage(); updateForCurrentTrackSelections(/* isNewPlayer= */ true); if (player != null) { - Player.VideoComponent newVideoComponent = player.getVideoComponent(); + @Nullable Player.VideoComponent newVideoComponent = player.getVideoComponent(); if (newVideoComponent != null) { if (surfaceView instanceof TextureView) { newVideoComponent.setVideoTextureView((TextureView) surfaceView); @@ -585,7 +589,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider } newVideoComponent.addVideoListener(componentListener); } - Player.TextComponent newTextComponent = player.getTextComponent(); + @Nullable Player.TextComponent newTextComponent = player.getTextComponent(); if (newTextComponent != null) { newTextComponent.addTextOutput(componentListener); } @@ -611,13 +615,13 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * @param resizeMode The {@link ResizeMode}. */ public void setResizeMode(@ResizeMode int resizeMode) { - Assertions.checkState(contentFrame != null); + Assertions.checkStateNotNull(contentFrame); contentFrame.setResizeMode(resizeMode); } /** Returns the {@link ResizeMode}. */ public @ResizeMode int getResizeMode() { - Assertions.checkState(contentFrame != null); + Assertions.checkStateNotNull(contentFrame); return contentFrame.getResizeMode(); } @@ -688,7 +692,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider return; } this.useController = useController; - if (useController) { + if (useController()) { controller.setPlayer(player); } else if (controller != null) { controller.hide(); @@ -793,9 +797,9 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider return super.dispatchKeyEvent(event); } - boolean isDpadAndUseController = isDpadKey(event.getKeyCode()) && useController; + boolean isDpadKey = isDpadKey(event.getKeyCode()); boolean handled = false; - if (isDpadAndUseController && !controller.isVisible()) { + if (isDpadKey && useController() && !controller.isVisible()) { // Handle the key event by showing the controller. maybeShowController(true); handled = true; @@ -804,7 +808,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider // controller, or extend its show timeout if already visible. maybeShowController(true); handled = true; - } else if (isDpadAndUseController) { + } else if (isDpadKey && useController()) { // The key event wasn't handled, but we should extend the controller's show timeout. maybeShowController(true); } @@ -819,7 +823,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * @return Whether the key event was handled. */ public boolean dispatchMediaKeyEvent(KeyEvent event) { - return useController && controller.dispatchMediaKeyEvent(event); + return useController() && controller.dispatchMediaKeyEvent(event); } /** Returns whether the controller is currently visible. */ @@ -865,7 +869,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * controller to remain visible indefinitely. */ public void setControllerShowTimeoutMs(int controllerShowTimeoutMs) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); this.controllerShowTimeoutMs = controllerShowTimeoutMs; if (controller.isVisible()) { // Update the controller's timeout if necessary. @@ -884,7 +888,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * @param controllerHideOnTouch Whether the playback controls are hidden by touch events. */ public void setControllerHideOnTouch(boolean controllerHideOnTouch) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); this.controllerHideOnTouch = controllerHideOnTouch; updateContentDescription(); } @@ -927,7 +931,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider */ public void setControllerVisibilityListener( @Nullable PlayerControlView.VisibilityListener listener) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); if (this.controllerVisibilityListener == listener) { return; } @@ -947,7 +951,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * preparer. */ public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setPlaybackPreparer(playbackPreparer); } @@ -958,7 +962,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * DefaultControlDispatcher}. */ public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setControlDispatcher(controlDispatcher); } @@ -969,7 +973,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * rewind button to be disabled. */ public void setRewindIncrementMs(int rewindMs) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setRewindIncrementMs(rewindMs); } @@ -980,7 +984,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * cause the fast forward button to be disabled. */ public void setFastForwardIncrementMs(int fastForwardMs) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setFastForwardIncrementMs(fastForwardMs); } @@ -990,7 +994,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * @param repeatToggleModes A set of {@link RepeatModeUtil.RepeatToggleModes}. */ public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setRepeatToggleModes(repeatToggleModes); } @@ -1000,7 +1004,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * @param showShuffleButton Whether the shuffle button is shown. */ public void setShowShuffleButton(boolean showShuffleButton) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setShowShuffleButton(showShuffleButton); } @@ -1010,7 +1014,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider * @param showMultiWindowTimeBar Whether to show all windows. */ public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setShowMultiWindowTimeBar(showMultiWindowTimeBar); } @@ -1026,7 +1030,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider */ public void setExtraAdGroupMarkers( @Nullable long[] extraAdGroupTimesMs, @Nullable boolean[] extraPlayedAdGroups) { - Assertions.checkState(controller != null); + Assertions.checkStateNotNull(controller); controller.setExtraAdGroupMarkers(extraAdGroupTimesMs, extraPlayedAdGroups); } @@ -1038,7 +1042,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider */ public void setAspectRatioListener( @Nullable AspectRatioFrameLayout.AspectRatioListener listener) { - Assertions.checkState(contentFrame != null); + Assertions.checkStateNotNull(contentFrame); contentFrame.setAspectRatioListener(listener); } @@ -1089,7 +1093,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider @Override public boolean onTouchEvent(MotionEvent event) { - if (!useController || player == null) { + if (!useController() || player == null) { return false; } switch (event.getAction()) { @@ -1116,7 +1120,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider @Override public boolean onTrackballEvent(MotionEvent ev) { - if (!useController || player == null) { + if (!useController() || player == null) { return false; } maybeShowController(true); @@ -1173,7 +1177,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider @Override public ViewGroup getAdViewGroup() { - return Assertions.checkNotNull( + return Assertions.checkStateNotNull( adOverlayFrameLayout, "exo_ad_overlay must be present for ad playback"); } @@ -1191,8 +1195,26 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider // Internal methods. + @EnsuresNonNullIf(expression = "controller", result = true) + private boolean useController() { + if (useController) { + Assertions.checkStateNotNull(controller); + return true; + } + return false; + } + + @EnsuresNonNullIf(expression = "artworkView", result = true) + private boolean useArtwork() { + if (useArtwork) { + Assertions.checkStateNotNull(artworkView); + return true; + } + return false; + } + private boolean toggleControllerVisibility() { - if (!useController || player == null) { + if (!useController() || player == null) { return false; } if (!controller.isVisible()) { @@ -1208,7 +1230,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider if (isPlayingAd() && controllerHideDuringAds) { return; } - if (useController) { + if (useController()) { boolean wasShowingIndefinitely = controller.isVisible() && controller.getShowTimeoutMs() <= 0; boolean shouldShowIndefinitely = shouldShowControllerIndefinitely(); if (isForced || wasShowingIndefinitely || shouldShowIndefinitely) { @@ -1229,7 +1251,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider } private void showController(boolean showIndefinitely) { - if (!useController) { + if (!useController()) { return; } controller.setShowTimeoutMs(showIndefinitely ? 0 : controllerShowTimeoutMs); @@ -1241,6 +1263,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider } private void updateForCurrentTrackSelections(boolean isNewPlayer) { + @Nullable Player player = this.player; if (player == null || player.getCurrentTrackGroups().isEmpty()) { if (!keepContentOnPlayerReset) { hideArtwork(); @@ -1267,12 +1290,12 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider // Video disabled so the shutter must be closed. closeShutter(); // Display artwork if enabled and available, else hide it. - if (useArtwork) { + if (useArtwork()) { for (int i = 0; i < selections.length; i++) { - TrackSelection selection = selections.get(i); + @Nullable TrackSelection selection = selections.get(i); if (selection != null) { for (int j = 0; j < selection.length(); j++) { - Metadata metadata = selection.getFormat(j).metadata; + @Nullable Metadata metadata = selection.getFormat(j).metadata; if (metadata != null && setArtworkFromMetadata(metadata)) { return; } @@ -1287,6 +1310,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider hideArtwork(); } + @RequiresNonNull("artworkView") private boolean setArtworkFromMetadata(Metadata metadata) { boolean isArtworkSet = false; int currentPictureType = PICTURE_TYPE_NOT_SET; @@ -1316,6 +1340,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider return isArtworkSet; } + @RequiresNonNull("artworkView") private boolean setDrawableArtwork(@Nullable Drawable drawable) { if (drawable != null) { int drawableWidth = drawable.getIntrinsicWidth(); @@ -1362,13 +1387,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider errorMessageView.setVisibility(View.VISIBLE); return; } - ExoPlaybackException error = null; - if (player != null - && player.getPlaybackState() == Player.STATE_IDLE - && errorMessageProvider != null) { - error = player.getPlaybackError(); - } - if (error != null) { + @Nullable ExoPlaybackException error = player != null ? player.getPlaybackError() : null; + if (error != null && errorMessageProvider != null) { CharSequence errorMessage = errorMessageProvider.getErrorMessage(error).second; errorMessageView.setText(errorMessage); errorMessageView.setVisibility(View.VISIBLE); @@ -1410,12 +1430,10 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider /** Applies a texture rotation to a {@link TextureView}. */ private static void applyTextureViewRotation(TextureView textureView, int textureViewRotation) { + Matrix transformMatrix = new Matrix(); float textureViewWidth = textureView.getWidth(); float textureViewHeight = textureView.getHeight(); - if (textureViewWidth == 0 || textureViewHeight == 0 || textureViewRotation == 0) { - textureView.setTransform(null); - } else { - Matrix transformMatrix = new Matrix(); + if (textureViewWidth != 0 && textureViewHeight != 0 && textureViewRotation != 0) { float pivotX = textureViewWidth / 2; float pivotY = textureViewHeight / 2; transformMatrix.postRotate(textureViewRotation, pivotX, pivotY); @@ -1429,8 +1447,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider textureViewHeight / rotatedTextureRect.height(), pivotX, pivotY); - textureView.setTransform(transformMatrix); } + textureView.setTransform(transformMatrix); } @SuppressLint("InlinedApi")