Remove nullness blacklist for UI module

PiperOrigin-RevId: 283324784
This commit is contained in:
olly 2019-12-02 13:58:12 +00:00 committed by bachinger
parent d12c7235f9
commit 6c65c27e9b
3 changed files with 138 additions and 68 deletions

View File

@ -96,6 +96,42 @@ public final class Assertions {
} }
} }
/**
* Throws {@link IllegalStateException} if {@code reference} is null.
*
* @param <T> 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> 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 <T> 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> 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. * Throws {@link NullPointerException} if {@code reference} is null.
* *

View File

@ -233,18 +233,18 @@ public class PlayerControlView extends FrameLayout {
private final ComponentListener componentListener; private final ComponentListener componentListener;
private final CopyOnWriteArrayList<VisibilityListener> visibilityListeners; private final CopyOnWriteArrayList<VisibilityListener> visibilityListeners;
private final View previousButton; @Nullable private final View previousButton;
private final View nextButton; @Nullable private final View nextButton;
private final View playButton; @Nullable private final View playButton;
private final View pauseButton; @Nullable private final View pauseButton;
private final View fastForwardButton; @Nullable private final View fastForwardButton;
private final View rewindButton; @Nullable private final View rewindButton;
private final ImageView repeatToggleButton; @Nullable private final ImageView repeatToggleButton;
private final ImageView shuffleButton; @Nullable private final ImageView shuffleButton;
private final View vrButton; @Nullable private final View vrButton;
private final TextView durationView; @Nullable private final TextView durationView;
private final TextView positionView; @Nullable private final TextView positionView;
private final TimeBar timeBar; @Nullable private final TimeBar timeBar;
private final StringBuilder formatBuilder; private final StringBuilder formatBuilder;
private final Formatter formatter; private final Formatter formatter;
private final Timeline.Period period; private final Timeline.Period period;
@ -299,6 +299,11 @@ public class PlayerControlView extends FrameLayout {
this(context, attrs, defStyleAttr, attrs); this(context, attrs, defStyleAttr, attrs);
} }
@SuppressWarnings({
"nullness:argument.type.incompatible",
"nullness:method.invocation.invalid",
"nullness:methodref.receiver.bound.invalid"
})
public PlayerControlView( public PlayerControlView(
Context context, Context context,
@Nullable AttributeSet attrs, @Nullable AttributeSet attrs,
@ -350,7 +355,7 @@ public class PlayerControlView extends FrameLayout {
updateProgressAction = this::updateProgress; updateProgressAction = this::updateProgress;
hideAction = this::hide; hideAction = this::hide;
LayoutInflater.from(context).inflate(controllerLayoutId, this); LayoutInflater.from(context).inflate(controllerLayoutId, /* root= */ this);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
TimeBar customTimeBar = findViewById(R.id.exo_progress); TimeBar customTimeBar = findViewById(R.id.exo_progress);
@ -778,6 +783,8 @@ public class PlayerControlView extends FrameLayout {
if (!isVisible() || !isAttachedToWindow) { if (!isVisible() || !isAttachedToWindow) {
return; return;
} }
@Nullable Player player = this.player;
boolean enableSeeking = false; boolean enableSeeking = false;
boolean enablePrevious = false; boolean enablePrevious = false;
boolean enableRewind = false; boolean enableRewind = false;
@ -809,16 +816,20 @@ public class PlayerControlView extends FrameLayout {
if (!isVisible() || !isAttachedToWindow || repeatToggleButton == null) { if (!isVisible() || !isAttachedToWindow || repeatToggleButton == null) {
return; return;
} }
if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE) { if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE) {
repeatToggleButton.setVisibility(GONE); repeatToggleButton.setVisibility(GONE);
return; return;
} }
@Nullable Player player = this.player;
if (player == null) { if (player == null) {
setButtonEnabled(false, repeatToggleButton); setButtonEnabled(false, repeatToggleButton);
repeatToggleButton.setImageDrawable(repeatOffButtonDrawable); repeatToggleButton.setImageDrawable(repeatOffButtonDrawable);
repeatToggleButton.setContentDescription(repeatOffButtonContentDescription); repeatToggleButton.setContentDescription(repeatOffButtonContentDescription);
return; return;
} }
setButtonEnabled(true, repeatToggleButton); setButtonEnabled(true, repeatToggleButton);
switch (player.getRepeatMode()) { switch (player.getRepeatMode()) {
case Player.REPEAT_MODE_OFF: case Player.REPEAT_MODE_OFF:
@ -843,6 +854,8 @@ public class PlayerControlView extends FrameLayout {
if (!isVisible() || !isAttachedToWindow || shuffleButton == null) { if (!isVisible() || !isAttachedToWindow || shuffleButton == null) {
return; return;
} }
@Nullable Player player = this.player;
if (!showShuffleButton) { if (!showShuffleButton) {
shuffleButton.setVisibility(GONE); shuffleButton.setVisibility(GONE);
} else if (player == null) { } else if (player == null) {
@ -861,6 +874,7 @@ public class PlayerControlView extends FrameLayout {
} }
private void updateTimeline() { private void updateTimeline() {
@Nullable Player player = this.player;
if (player == null) { if (player == null) {
return; return;
} }
@ -935,6 +949,7 @@ public class PlayerControlView extends FrameLayout {
return; return;
} }
@Nullable Player player = this.player;
long position = 0; long position = 0;
long bufferedPosition = 0; long bufferedPosition = 0;
if (player != null) { 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) { if (view == null) {
return; return;
} }
@ -1129,6 +1144,7 @@ public class PlayerControlView extends FrameLayout {
*/ */
public boolean dispatchMediaKeyEvent(KeyEvent event) { public boolean dispatchMediaKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode(); int keyCode = event.getKeyCode();
@Nullable Player player = this.player;
if (player == null || !isHandledMediaKey(keyCode)) { if (player == null || !isHandledMediaKey(keyCode)) {
return false; return false;
} }

View File

@ -71,6 +71,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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 * 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; private static final int SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW = 4;
// LINT.ThenChange(../../../../../../res/values/attrs.xml) // LINT.ThenChange(../../../../../../res/values/attrs.xml)
private final ComponentListener componentListener;
@Nullable private final AspectRatioFrameLayout contentFrame; @Nullable private final AspectRatioFrameLayout contentFrame;
private final View shutterView; @Nullable private final View shutterView;
@Nullable private final View surfaceView; @Nullable private final View surfaceView;
private final ImageView artworkView; @Nullable private final ImageView artworkView;
private final SubtitleView subtitleView; @Nullable private final SubtitleView subtitleView;
@Nullable private final View bufferingView; @Nullable private final View bufferingView;
@Nullable private final TextView errorMessageView; @Nullable private final TextView errorMessageView;
@Nullable private final PlayerControlView controller; @Nullable private final PlayerControlView controller;
private final ComponentListener componentListener;
@Nullable private final FrameLayout adOverlayFrameLayout; @Nullable private final FrameLayout adOverlayFrameLayout;
@Nullable private final FrameLayout overlayFrameLayout; @Nullable private final FrameLayout overlayFrameLayout;
private Player player; @Nullable private Player player;
private boolean useController; private boolean useController;
@Nullable private PlayerControlView.VisibilityListener controllerVisibilityListener; @Nullable private PlayerControlView.VisibilityListener controllerVisibilityListener;
private boolean useArtwork; private boolean useArtwork;
@ -318,9 +320,12 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
this(context, attrs, /* defStyleAttr= */ 0); this(context, attrs, /* defStyleAttr= */ 0);
} }
@SuppressWarnings({"nullness:argument.type.incompatible", "nullness:method.invocation.invalid"})
public PlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { public PlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
componentListener = new ComponentListener();
if (isInEditMode()) { if (isInEditMode()) {
contentFrame = null; contentFrame = null;
shutterView = null; shutterView = null;
@ -330,7 +335,6 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
bufferingView = null; bufferingView = null;
errorMessageView = null; errorMessageView = null;
controller = null; controller = null;
componentListener = null;
adOverlayFrameLayout = null; adOverlayFrameLayout = null;
overlayFrameLayout = null; overlayFrameLayout = null;
ImageView logo = new ImageView(context); ImageView logo = new ImageView(context);
@ -385,7 +389,6 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
} }
LayoutInflater.from(context).inflate(playerLayoutId, this); LayoutInflater.from(context).inflate(playerLayoutId, this);
componentListener = new ComponentListener();
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
// Content frame. // Content frame.
@ -540,9 +543,10 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
if (this.player == player) { if (this.player == player) {
return; return;
} }
if (this.player != null) { @Nullable Player oldPlayer = this.player;
this.player.removeListener(componentListener); if (oldPlayer != null) {
Player.VideoComponent oldVideoComponent = this.player.getVideoComponent(); oldPlayer.removeListener(componentListener);
@Nullable Player.VideoComponent oldVideoComponent = oldPlayer.getVideoComponent();
if (oldVideoComponent != null) { if (oldVideoComponent != null) {
oldVideoComponent.removeVideoListener(componentListener); oldVideoComponent.removeVideoListener(componentListener);
if (surfaceView instanceof TextureView) { if (surfaceView instanceof TextureView) {
@ -555,13 +559,13 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
oldVideoComponent.clearVideoSurfaceView((SurfaceView) surfaceView); oldVideoComponent.clearVideoSurfaceView((SurfaceView) surfaceView);
} }
} }
Player.TextComponent oldTextComponent = this.player.getTextComponent(); @Nullable Player.TextComponent oldTextComponent = oldPlayer.getTextComponent();
if (oldTextComponent != null) { if (oldTextComponent != null) {
oldTextComponent.removeTextOutput(componentListener); oldTextComponent.removeTextOutput(componentListener);
} }
} }
this.player = player; this.player = player;
if (useController) { if (useController()) {
controller.setPlayer(player); controller.setPlayer(player);
} }
if (subtitleView != null) { if (subtitleView != null) {
@ -571,7 +575,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
updateErrorMessage(); updateErrorMessage();
updateForCurrentTrackSelections(/* isNewPlayer= */ true); updateForCurrentTrackSelections(/* isNewPlayer= */ true);
if (player != null) { if (player != null) {
Player.VideoComponent newVideoComponent = player.getVideoComponent(); @Nullable Player.VideoComponent newVideoComponent = player.getVideoComponent();
if (newVideoComponent != null) { if (newVideoComponent != null) {
if (surfaceView instanceof TextureView) { if (surfaceView instanceof TextureView) {
newVideoComponent.setVideoTextureView((TextureView) surfaceView); newVideoComponent.setVideoTextureView((TextureView) surfaceView);
@ -585,7 +589,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
} }
newVideoComponent.addVideoListener(componentListener); newVideoComponent.addVideoListener(componentListener);
} }
Player.TextComponent newTextComponent = player.getTextComponent(); @Nullable Player.TextComponent newTextComponent = player.getTextComponent();
if (newTextComponent != null) { if (newTextComponent != null) {
newTextComponent.addTextOutput(componentListener); newTextComponent.addTextOutput(componentListener);
} }
@ -611,13 +615,13 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* @param resizeMode The {@link ResizeMode}. * @param resizeMode The {@link ResizeMode}.
*/ */
public void setResizeMode(@ResizeMode int resizeMode) { public void setResizeMode(@ResizeMode int resizeMode) {
Assertions.checkState(contentFrame != null); Assertions.checkStateNotNull(contentFrame);
contentFrame.setResizeMode(resizeMode); contentFrame.setResizeMode(resizeMode);
} }
/** Returns the {@link ResizeMode}. */ /** Returns the {@link ResizeMode}. */
public @ResizeMode int getResizeMode() { public @ResizeMode int getResizeMode() {
Assertions.checkState(contentFrame != null); Assertions.checkStateNotNull(contentFrame);
return contentFrame.getResizeMode(); return contentFrame.getResizeMode();
} }
@ -688,7 +692,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
return; return;
} }
this.useController = useController; this.useController = useController;
if (useController) { if (useController()) {
controller.setPlayer(player); controller.setPlayer(player);
} else if (controller != null) { } else if (controller != null) {
controller.hide(); controller.hide();
@ -793,9 +797,9 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
return super.dispatchKeyEvent(event); return super.dispatchKeyEvent(event);
} }
boolean isDpadAndUseController = isDpadKey(event.getKeyCode()) && useController; boolean isDpadKey = isDpadKey(event.getKeyCode());
boolean handled = false; boolean handled = false;
if (isDpadAndUseController && !controller.isVisible()) { if (isDpadKey && useController() && !controller.isVisible()) {
// Handle the key event by showing the controller. // Handle the key event by showing the controller.
maybeShowController(true); maybeShowController(true);
handled = true; handled = true;
@ -804,7 +808,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
// controller, or extend its show timeout if already visible. // controller, or extend its show timeout if already visible.
maybeShowController(true); maybeShowController(true);
handled = 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. // The key event wasn't handled, but we should extend the controller's show timeout.
maybeShowController(true); maybeShowController(true);
} }
@ -819,7 +823,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* @return Whether the key event was handled. * @return Whether the key event was handled.
*/ */
public boolean dispatchMediaKeyEvent(KeyEvent event) { public boolean dispatchMediaKeyEvent(KeyEvent event) {
return useController && controller.dispatchMediaKeyEvent(event); return useController() && controller.dispatchMediaKeyEvent(event);
} }
/** Returns whether the controller is currently visible. */ /** Returns whether the controller is currently visible. */
@ -865,7 +869,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* controller to remain visible indefinitely. * controller to remain visible indefinitely.
*/ */
public void setControllerShowTimeoutMs(int controllerShowTimeoutMs) { public void setControllerShowTimeoutMs(int controllerShowTimeoutMs) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
this.controllerShowTimeoutMs = controllerShowTimeoutMs; this.controllerShowTimeoutMs = controllerShowTimeoutMs;
if (controller.isVisible()) { if (controller.isVisible()) {
// Update the controller's timeout if necessary. // 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. * @param controllerHideOnTouch Whether the playback controls are hidden by touch events.
*/ */
public void setControllerHideOnTouch(boolean controllerHideOnTouch) { public void setControllerHideOnTouch(boolean controllerHideOnTouch) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
this.controllerHideOnTouch = controllerHideOnTouch; this.controllerHideOnTouch = controllerHideOnTouch;
updateContentDescription(); updateContentDescription();
} }
@ -927,7 +931,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
*/ */
public void setControllerVisibilityListener( public void setControllerVisibilityListener(
@Nullable PlayerControlView.VisibilityListener listener) { @Nullable PlayerControlView.VisibilityListener listener) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
if (this.controllerVisibilityListener == listener) { if (this.controllerVisibilityListener == listener) {
return; return;
} }
@ -947,7 +951,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* preparer. * preparer.
*/ */
public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) { public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setPlaybackPreparer(playbackPreparer); controller.setPlaybackPreparer(playbackPreparer);
} }
@ -958,7 +962,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* DefaultControlDispatcher}. * DefaultControlDispatcher}.
*/ */
public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) { public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setControlDispatcher(controlDispatcher); controller.setControlDispatcher(controlDispatcher);
} }
@ -969,7 +973,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* rewind button to be disabled. * rewind button to be disabled.
*/ */
public void setRewindIncrementMs(int rewindMs) { public void setRewindIncrementMs(int rewindMs) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setRewindIncrementMs(rewindMs); controller.setRewindIncrementMs(rewindMs);
} }
@ -980,7 +984,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* cause the fast forward button to be disabled. * cause the fast forward button to be disabled.
*/ */
public void setFastForwardIncrementMs(int fastForwardMs) { public void setFastForwardIncrementMs(int fastForwardMs) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setFastForwardIncrementMs(fastForwardMs); controller.setFastForwardIncrementMs(fastForwardMs);
} }
@ -990,7 +994,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* @param repeatToggleModes A set of {@link RepeatModeUtil.RepeatToggleModes}. * @param repeatToggleModes A set of {@link RepeatModeUtil.RepeatToggleModes}.
*/ */
public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) { public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setRepeatToggleModes(repeatToggleModes); controller.setRepeatToggleModes(repeatToggleModes);
} }
@ -1000,7 +1004,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* @param showShuffleButton Whether the shuffle button is shown. * @param showShuffleButton Whether the shuffle button is shown.
*/ */
public void setShowShuffleButton(boolean showShuffleButton) { public void setShowShuffleButton(boolean showShuffleButton) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setShowShuffleButton(showShuffleButton); controller.setShowShuffleButton(showShuffleButton);
} }
@ -1010,7 +1014,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
* @param showMultiWindowTimeBar Whether to show all windows. * @param showMultiWindowTimeBar Whether to show all windows.
*/ */
public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) { public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setShowMultiWindowTimeBar(showMultiWindowTimeBar); controller.setShowMultiWindowTimeBar(showMultiWindowTimeBar);
} }
@ -1026,7 +1030,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
*/ */
public void setExtraAdGroupMarkers( public void setExtraAdGroupMarkers(
@Nullable long[] extraAdGroupTimesMs, @Nullable boolean[] extraPlayedAdGroups) { @Nullable long[] extraAdGroupTimesMs, @Nullable boolean[] extraPlayedAdGroups) {
Assertions.checkState(controller != null); Assertions.checkStateNotNull(controller);
controller.setExtraAdGroupMarkers(extraAdGroupTimesMs, extraPlayedAdGroups); controller.setExtraAdGroupMarkers(extraAdGroupTimesMs, extraPlayedAdGroups);
} }
@ -1038,7 +1042,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
*/ */
public void setAspectRatioListener( public void setAspectRatioListener(
@Nullable AspectRatioFrameLayout.AspectRatioListener listener) { @Nullable AspectRatioFrameLayout.AspectRatioListener listener) {
Assertions.checkState(contentFrame != null); Assertions.checkStateNotNull(contentFrame);
contentFrame.setAspectRatioListener(listener); contentFrame.setAspectRatioListener(listener);
} }
@ -1089,7 +1093,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if (!useController || player == null) { if (!useController() || player == null) {
return false; return false;
} }
switch (event.getAction()) { switch (event.getAction()) {
@ -1116,7 +1120,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
@Override @Override
public boolean onTrackballEvent(MotionEvent ev) { public boolean onTrackballEvent(MotionEvent ev) {
if (!useController || player == null) { if (!useController() || player == null) {
return false; return false;
} }
maybeShowController(true); maybeShowController(true);
@ -1173,7 +1177,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
@Override @Override
public ViewGroup getAdViewGroup() { public ViewGroup getAdViewGroup() {
return Assertions.checkNotNull( return Assertions.checkStateNotNull(
adOverlayFrameLayout, "exo_ad_overlay must be present for ad playback"); adOverlayFrameLayout, "exo_ad_overlay must be present for ad playback");
} }
@ -1191,8 +1195,26 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
// Internal methods. // 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() { private boolean toggleControllerVisibility() {
if (!useController || player == null) { if (!useController() || player == null) {
return false; return false;
} }
if (!controller.isVisible()) { if (!controller.isVisible()) {
@ -1208,7 +1230,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
if (isPlayingAd() && controllerHideDuringAds) { if (isPlayingAd() && controllerHideDuringAds) {
return; return;
} }
if (useController) { if (useController()) {
boolean wasShowingIndefinitely = controller.isVisible() && controller.getShowTimeoutMs() <= 0; boolean wasShowingIndefinitely = controller.isVisible() && controller.getShowTimeoutMs() <= 0;
boolean shouldShowIndefinitely = shouldShowControllerIndefinitely(); boolean shouldShowIndefinitely = shouldShowControllerIndefinitely();
if (isForced || wasShowingIndefinitely || shouldShowIndefinitely) { if (isForced || wasShowingIndefinitely || shouldShowIndefinitely) {
@ -1229,7 +1251,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
} }
private void showController(boolean showIndefinitely) { private void showController(boolean showIndefinitely) {
if (!useController) { if (!useController()) {
return; return;
} }
controller.setShowTimeoutMs(showIndefinitely ? 0 : controllerShowTimeoutMs); controller.setShowTimeoutMs(showIndefinitely ? 0 : controllerShowTimeoutMs);
@ -1241,6 +1263,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
} }
private void updateForCurrentTrackSelections(boolean isNewPlayer) { private void updateForCurrentTrackSelections(boolean isNewPlayer) {
@Nullable Player player = this.player;
if (player == null || player.getCurrentTrackGroups().isEmpty()) { if (player == null || player.getCurrentTrackGroups().isEmpty()) {
if (!keepContentOnPlayerReset) { if (!keepContentOnPlayerReset) {
hideArtwork(); hideArtwork();
@ -1267,12 +1290,12 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
// Video disabled so the shutter must be closed. // Video disabled so the shutter must be closed.
closeShutter(); closeShutter();
// Display artwork if enabled and available, else hide it. // Display artwork if enabled and available, else hide it.
if (useArtwork) { if (useArtwork()) {
for (int i = 0; i < selections.length; i++) { for (int i = 0; i < selections.length; i++) {
TrackSelection selection = selections.get(i); @Nullable TrackSelection selection = selections.get(i);
if (selection != null) { if (selection != null) {
for (int j = 0; j < selection.length(); j++) { 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)) { if (metadata != null && setArtworkFromMetadata(metadata)) {
return; return;
} }
@ -1287,6 +1310,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
hideArtwork(); hideArtwork();
} }
@RequiresNonNull("artworkView")
private boolean setArtworkFromMetadata(Metadata metadata) { private boolean setArtworkFromMetadata(Metadata metadata) {
boolean isArtworkSet = false; boolean isArtworkSet = false;
int currentPictureType = PICTURE_TYPE_NOT_SET; int currentPictureType = PICTURE_TYPE_NOT_SET;
@ -1316,6 +1340,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
return isArtworkSet; return isArtworkSet;
} }
@RequiresNonNull("artworkView")
private boolean setDrawableArtwork(@Nullable Drawable drawable) { private boolean setDrawableArtwork(@Nullable Drawable drawable) {
if (drawable != null) { if (drawable != null) {
int drawableWidth = drawable.getIntrinsicWidth(); int drawableWidth = drawable.getIntrinsicWidth();
@ -1362,13 +1387,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
errorMessageView.setVisibility(View.VISIBLE); errorMessageView.setVisibility(View.VISIBLE);
return; return;
} }
ExoPlaybackException error = null; @Nullable ExoPlaybackException error = player != null ? player.getPlaybackError() : null;
if (player != null if (error != null && errorMessageProvider != null) {
&& player.getPlaybackState() == Player.STATE_IDLE
&& errorMessageProvider != null) {
error = player.getPlaybackError();
}
if (error != null) {
CharSequence errorMessage = errorMessageProvider.getErrorMessage(error).second; CharSequence errorMessage = errorMessageProvider.getErrorMessage(error).second;
errorMessageView.setText(errorMessage); errorMessageView.setText(errorMessage);
errorMessageView.setVisibility(View.VISIBLE); errorMessageView.setVisibility(View.VISIBLE);
@ -1410,12 +1430,10 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
/** Applies a texture rotation to a {@link TextureView}. */ /** Applies a texture rotation to a {@link TextureView}. */
private static void applyTextureViewRotation(TextureView textureView, int textureViewRotation) { private static void applyTextureViewRotation(TextureView textureView, int textureViewRotation) {
Matrix transformMatrix = new Matrix();
float textureViewWidth = textureView.getWidth(); float textureViewWidth = textureView.getWidth();
float textureViewHeight = textureView.getHeight(); float textureViewHeight = textureView.getHeight();
if (textureViewWidth == 0 || textureViewHeight == 0 || textureViewRotation == 0) { if (textureViewWidth != 0 && textureViewHeight != 0 && textureViewRotation != 0) {
textureView.setTransform(null);
} else {
Matrix transformMatrix = new Matrix();
float pivotX = textureViewWidth / 2; float pivotX = textureViewWidth / 2;
float pivotY = textureViewHeight / 2; float pivotY = textureViewHeight / 2;
transformMatrix.postRotate(textureViewRotation, pivotX, pivotY); transformMatrix.postRotate(textureViewRotation, pivotX, pivotY);
@ -1429,8 +1447,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
textureViewHeight / rotatedTextureRect.height(), textureViewHeight / rotatedTextureRect.height(),
pivotX, pivotX,
pivotY); pivotY);
textureView.setTransform(transformMatrix);
} }
textureView.setTransform(transformMatrix);
} }
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")