diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 26357a18dc..47ee6b062c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -659,7 +659,14 @@ import java.util.concurrent.TimeoutException; public void setForegroundMode(boolean foregroundMode) { if (this.foregroundMode != foregroundMode) { this.foregroundMode = foregroundMode; - internalPlayer.setForegroundMode(foregroundMode); + if (!internalPlayer.setForegroundMode(foregroundMode)) { + notifyListeners( + listener -> + listener.onPlayerError( + ExoPlaybackException.createForUnexpected( + new RuntimeException( + new TimeoutException("Setting foreground mode timed out."))))); + } } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 53c8a5d080..f7abd4dd9d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -43,6 +43,7 @@ import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.util.Supplier; import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.Util; import java.io.IOException; @@ -296,29 +297,24 @@ import java.util.concurrent.atomic.AtomicBoolean; handler.obtainMessage(MSG_SEND_MESSAGE, message).sendToTarget(); } - public synchronized void setForegroundMode(boolean foregroundMode) { + public synchronized boolean setForegroundMode(boolean foregroundMode) { if (released || !internalPlaybackThread.isAlive()) { - return; + return true; } if (foregroundMode) { handler.obtainMessage(MSG_SET_FOREGROUND_MODE, /* foregroundMode */ 1, 0).sendToTarget(); + return true; } else { AtomicBoolean processedFlag = new AtomicBoolean(); handler .obtainMessage(MSG_SET_FOREGROUND_MODE, /* foregroundMode */ 0, 0, processedFlag) .sendToTarget(); - boolean wasInterrupted = false; - while (!processedFlag.get()) { - try { - wait(); - } catch (InterruptedException e) { - wasInterrupted = true; - } - } - if (wasInterrupted) { - // Restore the interrupted status. - Thread.currentThread().interrupt(); + if (releaseTimeoutMs > 0) { + waitUninterruptibly(/* condition= */ processedFlag::get, releaseTimeoutMs); + } else { + waitUninterruptibly(/* condition= */ processedFlag::get); } + return processedFlag.get(); } } @@ -328,16 +324,11 @@ import java.util.concurrent.atomic.AtomicBoolean; } handler.sendEmptyMessage(MSG_RELEASE); - try { - if (releaseTimeoutMs > 0) { - waitUntilReleased(releaseTimeoutMs); - } else { - waitUntilReleased(); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + if (releaseTimeoutMs > 0) { + waitUninterruptibly(/* condition= */ () -> released, releaseTimeoutMs); + } else { + waitUninterruptibly(/* condition= */ () -> released); } - return released; } @@ -505,59 +496,54 @@ import java.util.concurrent.atomic.AtomicBoolean; // Private methods. /** - * Blocks the current thread until {@link #releaseInternal()} is executed on the playback Thread. + * Blocks the current thread until a condition becomes true. * - *
If the current thread is interrupted while waiting for {@link #releaseInternal()} to - * complete, this method will delay throwing the {@link InterruptedException} to ensure that the - * underlying resources have been released, and will an {@link InterruptedException} after - * {@link #releaseInternal()} is complete. + *
If the current thread is interrupted while waiting for the condition to become true, this
+ * method will restore the interrupt after the condition became true.
*
- * @throws {@link InterruptedException} if the current Thread was interrupted while waiting for
- * {@link #releaseInternal()} to complete.
+ * @param condition The condition.
*/
- private synchronized void waitUntilReleased() throws InterruptedException {
- InterruptedException interruptedException = null;
- while (!released) {
+ private synchronized void waitUninterruptibly(Supplier If the current thread is interrupted while waiting for {@link #releaseInternal()} to
- * complete, this method will delay throwing the {@link InterruptedException} to ensure that the
- * underlying resources have been released or the operation timed out, and will throw an {@link
- * InterruptedException} afterwards.
+ * If the current thread is interrupted while waiting for the condition to become true, this
+ * method will restore the interrupt after the condition became true or the operation times
+ * out.
*
- * @param timeoutMs the time in milliseconds to wait for {@link #releaseInternal()} to complete.
- * @throws {@link InterruptedException} if the current Thread was interrupted while waiting for
- * {@link #releaseInternal()} to complete.
+ * @param condition The condition.
+ * @param timeoutMs The time in milliseconds to wait for the condition to become true.
*/
- private synchronized void waitUntilReleased(long timeoutMs) throws InterruptedException {
+ private synchronized void waitUninterruptibly(Supplier