diff options
author | H. Lehmann <ByteHamster@users.noreply.github.com> | 2019-04-16 22:18:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-16 22:18:05 +0200 |
commit | 99c5e9dc395f52f78c1c6aafdc678763e12545ca (patch) | |
tree | 3e772929cc5fe409e124d821bffbaa438944b344 | |
parent | 5d459b5327a7ab7dcc3d76c2264a06d0d4671614 (diff) | |
parent | 0339ce7bcaef166b4fe952f6bb28e992e7688b46 (diff) | |
download | AntennaPod-99c5e9dc395f52f78c1c6aafdc678763e12545ca.zip |
Merge pull request #3117 from ByteHamster/fix-anr
Fixed cast related bugs
3 files changed, 60 insertions, 12 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 649082f6e..28889cee3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -55,10 +55,12 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { * Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads * have to wait until these operations have finished. */ - private final ReentrantLock playerLock; - private CountDownLatch seekLatch; - + private final PlayerLock playerLock; private final PlayerExecutor executor; + private boolean useCallerThread = true; + + + private CountDownLatch seekLatch; /** * All ExoPlayer methods must be executed on the same thread. @@ -68,7 +70,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { * Other players are still executed in a background thread. */ private class PlayerExecutor { - private boolean useCallerThread = true; private ThreadPoolExecutor threadPool; public Future<?> submit(Runnable r) { @@ -85,11 +86,56 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } } + /** + * All ExoPlayer methods must be executed on the same thread. + * We use the main application thread. This class allows to + * "fake" a lock that does nothing. A lock is not needed if + * everything is called on the same thread. + * Other players are still executed in a background thread and + * therefore use a real lock. + */ + private class PlayerLock { + private ReentrantLock lock = new ReentrantLock(); + + public void lock() { + if (!useCallerThread) { + lock.lock(); + } + } + + public boolean tryLock(int i, TimeUnit milliseconds) throws InterruptedException { + if (!useCallerThread) { + return lock.tryLock(i, milliseconds); + } + return true; + } + + public boolean tryLock() { + if (!useCallerThread) { + return lock.tryLock(); + } + return true; + } + + public void unlock() { + if (!useCallerThread) { + lock.unlock(); + } + } + + public boolean isHeldByCurrentThread() { + if (!useCallerThread) { + return lock.isHeldByCurrentThread(); + } + return true; + } + } + public LocalPSMP(@NonNull Context context, @NonNull PSMPCallback callback) { super(context, callback); this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - this.playerLock = new ReentrantLock(); + this.playerLock = new PlayerLock(); this.startWhenPrepared = new AtomicBoolean(false); executor = new PlayerExecutor(); @@ -132,7 +178,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { @Override public void playMediaObject(@NonNull final Playable playable, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) { Log.d(TAG, "playMediaObject(...)"); - executor.useCallerThread = UserPreferences.useExoplayer(); + useCallerThread = UserPreferences.useExoplayer(); executor.submit(() -> { playerLock.lock(); try { @@ -400,7 +446,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { */ @Override public void reinit() { - executor.useCallerThread = UserPreferences.useExoplayer(); + useCallerThread = UserPreferences.useExoplayer(); executor.submit(() -> { playerLock.lock(); Log.d(TAG, "reinit()"); @@ -850,7 +896,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { @Override protected Future<?> endPlayback(final boolean hasEnded, final boolean wasSkipped, final boolean shouldContinue, final boolean toStoppedState) { - executor.useCallerThread = UserPreferences.useExoplayer(); + useCallerThread = UserPreferences.useExoplayer(); return executor.submit(() -> { playerLock.lock(); releaseWifiLockIfNecessary(); @@ -1057,7 +1103,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { playerLock.unlock(); }; - if (executor.useCallerThread) { + if (useCallerThread) { r.run(); } else { new Thread(r).start(); diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java index a6b732a4f..85c8a22f5 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java +++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java @@ -174,9 +174,9 @@ public class PlaybackServiceFlavorHelper { } callback.sendNotificationBroadcast(PlaybackService.NOTIFICATION_TYPE_RELOAD, PlaybackService.EXTRA_CODE_CAST); - switchMediaPlayer(new RemotePSMP(context, callback.getMediaPlayerCallback()), - info, - wasLaunched); + RemotePSMP remotePSMP = new RemotePSMP(context, callback.getMediaPlayerCallback()); + switchMediaPlayer(remotePSMP, info, wasLaunched); + remotePSMP.init(); // hardware volume buttons control the remote device volume mediaRouter.setMediaSessionCompat(callback.getMediaSession()); registerWifiBroadcastReceiver(); diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java index 487849ef5..f91264c59 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java +++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java @@ -62,7 +62,9 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { startWhenPrepared = new AtomicBoolean(false); isBuffering = new AtomicBoolean(false); remoteState = MediaStatus.PLAYER_STATE_UNKNOWN; + } + public void init () { try { if (castMgr.isConnected() && castMgr.isRemoteMediaLoaded()) { onRemoteMediaPlayerStatusUpdated(); |