Commit a92344ac by tonihei Committed by Oliver Woodman

Log warning with stack trace if player is accessed from the wrong thread.

This doesn't break apps which violate this policy. But it creates a clear
warning which is also likely to be reported in analytics tools.

Issue:#4463

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=213442510
parent db33b3bb
......@@ -109,6 +109,7 @@ public class SimpleExoPlayer
private List<Cue> currentCues;
private VideoFrameMetadataListener videoFrameMetadataListener;
private CameraMotionListener cameraMotionListener;
private boolean hasNotifiedFullWrongThreadWarning;
/**
* @param context A {@link Context}.
......@@ -266,6 +267,7 @@ public class SimpleExoPlayer
*/
@Override
public void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode) {
verifyApplicationThread();
this.videoScalingMode = videoScalingMode;
for (Renderer renderer : renderers) {
if (renderer.getTrackType() == C.TRACK_TYPE_VIDEO) {
......@@ -285,11 +287,13 @@ public class SimpleExoPlayer
@Override
public void clearVideoSurface() {
verifyApplicationThread();
setVideoSurface(null);
}
@Override
public void clearVideoSurface(Surface surface) {
verifyApplicationThread();
if (surface != null && surface == this.surface) {
setVideoSurface(null);
}
......@@ -297,6 +301,7 @@ public class SimpleExoPlayer
@Override
public void setVideoSurface(@Nullable Surface surface) {
verifyApplicationThread();
removeSurfaceCallbacks();
setVideoSurfaceInternal(surface, false);
int newSurfaceSize = surface == null ? 0 : C.LENGTH_UNSET;
......@@ -305,6 +310,7 @@ public class SimpleExoPlayer
@Override
public void setVideoSurfaceHolder(SurfaceHolder surfaceHolder) {
verifyApplicationThread();
removeSurfaceCallbacks();
this.surfaceHolder = surfaceHolder;
if (surfaceHolder == null) {
......@@ -326,6 +332,7 @@ public class SimpleExoPlayer
@Override
public void clearVideoSurfaceHolder(SurfaceHolder surfaceHolder) {
verifyApplicationThread();
if (surfaceHolder != null && surfaceHolder == this.surfaceHolder) {
setVideoSurfaceHolder(null);
}
......@@ -343,6 +350,7 @@ public class SimpleExoPlayer
@Override
public void setVideoTextureView(TextureView textureView) {
verifyApplicationThread();
removeSurfaceCallbacks();
this.textureView = textureView;
if (textureView == null) {
......@@ -367,6 +375,7 @@ public class SimpleExoPlayer
@Override
public void clearVideoTextureView(TextureView textureView) {
verifyApplicationThread();
if (textureView != null && textureView == this.textureView) {
setVideoTextureView(null);
}
......@@ -389,6 +398,7 @@ public class SimpleExoPlayer
@Override
public void setAudioAttributes(AudioAttributes audioAttributes, boolean handleAudioFocus) {
verifyApplicationThread();
if (!Util.areEqual(this.audioAttributes, audioAttributes)) {
this.audioAttributes = audioAttributes;
for (Renderer renderer : renderers) {
......@@ -424,6 +434,7 @@ public class SimpleExoPlayer
@Override
public void setAuxEffectInfo(AuxEffectInfo auxEffectInfo) {
verifyApplicationThread();
for (Renderer renderer : renderers) {
if (renderer.getTrackType() == C.TRACK_TYPE_AUDIO) {
player
......@@ -442,6 +453,7 @@ public class SimpleExoPlayer
@Override
public void setVolume(float audioVolume) {
verifyApplicationThread();
audioVolume = Util.constrainValue(audioVolume, /* min= */ 0, /* max= */ 1);
if (this.audioVolume == audioVolume) {
return;
......@@ -500,6 +512,7 @@ public class SimpleExoPlayer
* @param listener The listener to be added.
*/
public void addAnalyticsListener(AnalyticsListener listener) {
verifyApplicationThread();
analyticsCollector.addListener(listener);
}
......@@ -509,6 +522,7 @@ public class SimpleExoPlayer
* @param listener The listener to be removed.
*/
public void removeAnalyticsListener(AnalyticsListener listener) {
verifyApplicationThread();
analyticsCollector.removeListener(listener);
}
......@@ -571,6 +585,7 @@ public class SimpleExoPlayer
@Override
public void setVideoFrameMetadataListener(VideoFrameMetadataListener listener) {
verifyApplicationThread();
videoFrameMetadataListener = listener;
for (Renderer renderer : renderers) {
if (renderer.getTrackType() == C.TRACK_TYPE_VIDEO) {
......@@ -585,6 +600,7 @@ public class SimpleExoPlayer
@Override
public void clearVideoFrameMetadataListener(VideoFrameMetadataListener listener) {
verifyApplicationThread();
if (videoFrameMetadataListener != listener) {
return;
}
......@@ -601,6 +617,7 @@ public class SimpleExoPlayer
@Override
public void setCameraMotionListener(CameraMotionListener listener) {
verifyApplicationThread();
cameraMotionListener = listener;
for (Renderer renderer : renderers) {
if (renderer.getTrackType() == C.TRACK_TYPE_CAMERA_MOTION) {
......@@ -615,6 +632,7 @@ public class SimpleExoPlayer
@Override
public void clearCameraMotionListener(CameraMotionListener listener) {
verifyApplicationThread();
if (cameraMotionListener != listener) {
return;
}
......@@ -814,26 +832,31 @@ public class SimpleExoPlayer
@Override
public void addListener(Player.EventListener listener) {
verifyApplicationThread();
player.addListener(listener);
}
@Override
public void removeListener(Player.EventListener listener) {
verifyApplicationThread();
player.removeListener(listener);
}
@Override
public int getPlaybackState() {
verifyApplicationThread();
return player.getPlaybackState();
}
@Override
public @Nullable ExoPlaybackException getPlaybackError() {
verifyApplicationThread();
return player.getPlaybackError();
}
@Override
public void retry() {
verifyApplicationThread();
if (mediaSource != null
&& (getPlaybackError() != null || getPlaybackState() == Player.STATE_IDLE)) {
prepare(mediaSource, /* resetPosition= */ false, /* resetState= */ false);
......@@ -847,6 +870,7 @@ public class SimpleExoPlayer
@Override
public void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
verifyApplicationThread();
if (this.mediaSource != null) {
this.mediaSource.removeEventListener(analyticsCollector);
analyticsCollector.resetForNewMediaSource();
......@@ -861,6 +885,7 @@ public class SimpleExoPlayer
@Override
public void setPlayWhenReady(boolean playWhenReady) {
verifyApplicationThread();
@AudioFocusManager.PlayerCommand
int playerCommand = audioFocusManager.handleSetPlayWhenReady(playWhenReady, getPlaybackState());
updatePlayWhenReady(playWhenReady, playerCommand);
......@@ -868,80 +893,95 @@ public class SimpleExoPlayer
@Override
public boolean getPlayWhenReady() {
verifyApplicationThread();
return player.getPlayWhenReady();
}
@Override
public @RepeatMode int getRepeatMode() {
verifyApplicationThread();
return player.getRepeatMode();
}
@Override
public void setRepeatMode(@RepeatMode int repeatMode) {
verifyApplicationThread();
player.setRepeatMode(repeatMode);
}
@Override
public void setShuffleModeEnabled(boolean shuffleModeEnabled) {
verifyApplicationThread();
player.setShuffleModeEnabled(shuffleModeEnabled);
}
@Override
public boolean getShuffleModeEnabled() {
verifyApplicationThread();
return player.getShuffleModeEnabled();
}
@Override
public boolean isLoading() {
verifyApplicationThread();
return player.isLoading();
}
@Override
public void seekToDefaultPosition() {
verifyApplicationThread();
analyticsCollector.notifySeekStarted();
player.seekToDefaultPosition();
}
@Override
public void seekToDefaultPosition(int windowIndex) {
verifyApplicationThread();
analyticsCollector.notifySeekStarted();
player.seekToDefaultPosition(windowIndex);
}
@Override
public void seekTo(long positionMs) {
verifyApplicationThread();
analyticsCollector.notifySeekStarted();
player.seekTo(positionMs);
}
@Override
public void seekTo(int windowIndex, long positionMs) {
verifyApplicationThread();
analyticsCollector.notifySeekStarted();
player.seekTo(windowIndex, positionMs);
}
@Override
public void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters) {
verifyApplicationThread();
player.setPlaybackParameters(playbackParameters);
}
@Override
public PlaybackParameters getPlaybackParameters() {
verifyApplicationThread();
return player.getPlaybackParameters();
}
@Override
public void setSeekParameters(@Nullable SeekParameters seekParameters) {
verifyApplicationThread();
player.setSeekParameters(seekParameters);
}
@Override
public SeekParameters getSeekParameters() {
verifyApplicationThread();
return player.getSeekParameters();
}
@Override
public @Nullable Object getCurrentTag() {
verifyApplicationThread();
return player.getCurrentTag();
}
......@@ -952,6 +992,7 @@ public class SimpleExoPlayer
@Override
public void stop(boolean reset) {
verifyApplicationThread();
player.stop(reset);
if (mediaSource != null) {
mediaSource.removeEventListener(analyticsCollector);
......@@ -992,6 +1033,7 @@ public class SimpleExoPlayer
@Override
public PlayerMessage createMessage(PlayerMessage.Target target) {
verifyApplicationThread();
return player.createMessage(target);
}
......@@ -1004,116 +1046,139 @@ public class SimpleExoPlayer
@Override
public int getRendererCount() {
verifyApplicationThread();
return player.getRendererCount();
}
@Override
public int getRendererType(int index) {
verifyApplicationThread();
return player.getRendererType(index);
}
@Override
public TrackGroupArray getCurrentTrackGroups() {
verifyApplicationThread();
return player.getCurrentTrackGroups();
}
@Override
public TrackSelectionArray getCurrentTrackSelections() {
verifyApplicationThread();
return player.getCurrentTrackSelections();
}
@Override
public Timeline getCurrentTimeline() {
verifyApplicationThread();
return player.getCurrentTimeline();
}
@Override
public @Nullable Object getCurrentManifest() {
verifyApplicationThread();
return player.getCurrentManifest();
}
@Override
public int getCurrentPeriodIndex() {
verifyApplicationThread();
return player.getCurrentPeriodIndex();
}
@Override
public int getCurrentWindowIndex() {
verifyApplicationThread();
return player.getCurrentWindowIndex();
}
@Override
public int getNextWindowIndex() {
verifyApplicationThread();
return player.getNextWindowIndex();
}
@Override
public int getPreviousWindowIndex() {
verifyApplicationThread();
return player.getPreviousWindowIndex();
}
@Override
public long getDuration() {
verifyApplicationThread();
return player.getDuration();
}
@Override
public long getCurrentPosition() {
verifyApplicationThread();
return player.getCurrentPosition();
}
@Override
public long getBufferedPosition() {
verifyApplicationThread();
return player.getBufferedPosition();
}
@Override
public int getBufferedPercentage() {
verifyApplicationThread();
return player.getBufferedPercentage();
}
@Override
public long getTotalBufferedDuration() {
verifyApplicationThread();
return player.getTotalBufferedDuration();
}
@Override
public boolean isCurrentWindowDynamic() {
verifyApplicationThread();
return player.isCurrentWindowDynamic();
}
@Override
public boolean isCurrentWindowSeekable() {
verifyApplicationThread();
return player.isCurrentWindowSeekable();
}
@Override
public boolean isPlayingAd() {
verifyApplicationThread();
return player.isPlayingAd();
}
@Override
public int getCurrentAdGroupIndex() {
verifyApplicationThread();
return player.getCurrentAdGroupIndex();
}
@Override
public int getCurrentAdIndexInAdGroup() {
verifyApplicationThread();
return player.getCurrentAdIndexInAdGroup();
}
@Override
public long getContentDuration() {
verifyApplicationThread();
return player.getContentDuration();
}
@Override
public long getContentPosition() {
verifyApplicationThread();
return player.getContentPosition();
}
@Override
public long getContentBufferedPosition() {
verifyApplicationThread();
return player.getContentBufferedPosition();
}
......@@ -1183,12 +1248,23 @@ public class SimpleExoPlayer
private void updatePlayWhenReady(
boolean playWhenReady, @AudioFocusManager.PlayerCommand int playerCommand) {
player.setPlayWhenReady(
playWhenReady && playerCommand != AudioFocusManager.PLAYER_COMMAND_DO_NOT_PLAY,
playerCommand != AudioFocusManager.PLAYER_COMMAND_PLAY_WHEN_READY);
}
private void verifyApplicationThread() {
if (Looper.myLooper() != getApplicationLooper()) {
Log.w(
TAG,
"Player is accessed on the wrong thread. See "
+ "https://google.github.io/ExoPlayer/faqs.html#"
+ "what-do-player-is-accessed-on-the-wrong-thread-warnings-mean",
hasNotifiedFullWrongThreadWarning ? null : new IllegalStateException());
hasNotifiedFullWrongThreadWarning = true;
}
}
private final class ComponentListener
implements VideoRendererEventListener,
AudioRendererEventListener,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment