mirror of
https://github.com/samsonjs/media.git
synced 2026-06-29 05:39:31 +00:00
ExoPlayerImplInternal.releaseInternal(): unblock the app thread
This change makes ExoPlayerImplInternal.releaseInternal() unblock the app thread if a runtime exception is thrown while releasing components from the playback thread. Before this change, if a runtime exception occurred during releasing components in the playback thread, ExoPlayer.release() would wait for `releaseTimeoutMs` and then raise a player error. With this change, the player error is reported only when the playback thread is blocked but if there is a runtime exception, the application thread is unblocked. The impact of this change is potentially fewer ANRs on ExoPlayer.release() at the expense of less error reporting. PiperOrigin-RevId: 609702549
This commit is contained in:
parent
601d6ed587
commit
0480eff6a1
2 changed files with 51 additions and 14 deletions
|
|
@ -1478,20 +1478,23 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
}
|
||||
|
||||
private void releaseInternal() {
|
||||
resetInternal(
|
||||
/* resetRenderers= */ true,
|
||||
/* resetPosition= */ false,
|
||||
/* releaseMediaSourceList= */ true,
|
||||
/* resetError= */ false);
|
||||
releaseRenderers();
|
||||
loadControl.onReleased();
|
||||
setState(Player.STATE_IDLE);
|
||||
if (internalPlaybackThread != null) {
|
||||
internalPlaybackThread.quit();
|
||||
}
|
||||
synchronized (this) {
|
||||
released = true;
|
||||
notifyAll();
|
||||
try {
|
||||
resetInternal(
|
||||
/* resetRenderers= */ true,
|
||||
/* resetPosition= */ false,
|
||||
/* releaseMediaSourceList= */ true,
|
||||
/* resetError= */ false);
|
||||
releaseRenderers();
|
||||
loadControl.onReleased();
|
||||
setState(Player.STATE_IDLE);
|
||||
} finally {
|
||||
if (internalPlaybackThread != null) {
|
||||
internalPlaybackThread.quit();
|
||||
}
|
||||
synchronized (this) {
|
||||
released = true;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import static org.mockito.Mockito.inOrder;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
|
@ -12934,6 +12935,39 @@ public final class ExoPlayerTest {
|
|||
verify(listener).onVolumeChanged(anyFloat());
|
||||
}
|
||||
|
||||
/**
|
||||
* This test verifies that {@link ExoPlayer#release()} will return without a timeout reported when
|
||||
* there is a {@link RuntimeException} thrown on the playback thread during releasing the internal
|
||||
* components.
|
||||
*/
|
||||
@Test
|
||||
public void release_internalFailure_noTimeoutError() {
|
||||
Player.Listener listener = mock(Player.Listener.class);
|
||||
LoadControl loadControl =
|
||||
spy(
|
||||
new DefaultLoadControl() {
|
||||
@Override
|
||||
public void onReleased() {
|
||||
// Emulate a failure during player release.
|
||||
throw new RuntimeException();
|
||||
}
|
||||
});
|
||||
ExoPlayer player =
|
||||
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||
.setLoadControl(loadControl)
|
||||
.build();
|
||||
player.addListener(listener);
|
||||
// Ensure load control has not thrown the exception yet.
|
||||
verify(loadControl, never()).onReleased();
|
||||
|
||||
player.release();
|
||||
ShadowLooper.idleMainLooper();
|
||||
|
||||
// Verify load control threw the exception.
|
||||
verify(loadControl).onReleased();
|
||||
verify(listener, never()).onPlayerError(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void releaseAfterVolumeChanges_triggerPendingDeviceVolumeEventsInListener() {
|
||||
ExoPlayer player =
|
||||
|
|
|
|||
Loading…
Reference in a new issue