Commit 22ab1484 by ibaker Committed by Ian Baker

Avoid DefaultDrmSessionManager releasing too many session references

Before this fix, if DefaultDrmSessionManager.release() was called while
there was at least one 'external' session reference still active (i.e.
session.referenceCount > 1) then the manager will release it's reference
immediately but when the session's reference count subsequently drops to
1 (due to external references being released) the manager will schedule
a task to release its internal reference *again*.

This change fixes the problem by only scheduling the timed release if
the manager is unreleased. This ensures that the internal references
are only released once.

Issue: #9193

#minor-release

PiperOrigin-RevId: 385580741
parent 135eb3f8
...@@ -98,6 +98,8 @@ ...@@ -98,6 +98,8 @@
using a `ForwardingPlayer` that overrides `getSeekBackIncrement`, using a `ForwardingPlayer` that overrides `getSeekBackIncrement`,
`seekBack`, `getSeekForwardIncrement` and `seekForward`. The rewind and `seekBack`, `getSeekForwardIncrement` and `seekForward`. The rewind and
fast forward buttons can be disabled by using a `ForwardingPlayer` that fast forward buttons can be disabled by using a `ForwardingPlayer` that
`seekBack`, `getSeekForwardIncrement` and `seekForward`. The
corresponding buttons can be disabled by using a `ForwardingPlayer` that
removes `COMMAND_SEEK_BACK` and `COMMAND_SEEK_FORWARD` from the removes `COMMAND_SEEK_BACK` and `COMMAND_SEEK_FORWARD` from the
available commands. available commands.
* Update `DefaultControlDispatcher` `getRewindIncrementMs` and * Update `DefaultControlDispatcher` `getRewindIncrementMs` and
...@@ -147,6 +149,10 @@ ...@@ -147,6 +149,10 @@
([#9106](https://github.com/google/ExoPlayer/issues/9106). ([#9106](https://github.com/google/ExoPlayer/issues/9106).
* DRM: * DRM:
* Allow repeated provisioning in `DefaultDrmSession(Manager)`. * Allow repeated provisioning in `DefaultDrmSession(Manager)`.
* Fix a crash due to `DefaultDrmSessionManager.release()` incorrectly
releasing too many keep-alive `DefaultDrmSession` references, resulting
in `DefaultDrmSession.release()` throwing an `IllegalStateException`
([#9193](https://github.com/google/ExoPlayer/issues/9193)).
* PlayerNotificationManager: * PlayerNotificationManager:
* Add `PendingIntent.FLAG_IMMUTABLE` flag to BroadcastReceiver to support * Add `PendingIntent.FLAG_IMMUTABLE` flag to BroadcastReceiver to support
Android 12. Android 12.
......
...@@ -914,8 +914,10 @@ public class DefaultDrmSessionManager implements DrmSessionManager { ...@@ -914,8 +914,10 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
@Override @Override
public void onReferenceCountDecremented(DefaultDrmSession session, int newReferenceCount) { public void onReferenceCountDecremented(DefaultDrmSession session, int newReferenceCount) {
if (newReferenceCount == 1 && sessionKeepaliveMs != C.TIME_UNSET) { if (newReferenceCount == 1 && prepareCallsCount > 0 && sessionKeepaliveMs != C.TIME_UNSET) {
// Only the internal keep-alive reference remains, so we can start the timeout. // Only the internal keep-alive reference remains, so we can start the timeout. We only
// do this if the manager isn't released, because a released manager has already released
// all its internal session keep-alive references.
keepaliveSessions.add(session); keepaliveSessions.add(session);
checkNotNull(playbackHandler) checkNotNull(playbackHandler)
.postAtTime( .postAtTime(
......
...@@ -222,6 +222,44 @@ public class DefaultDrmSessionManagerTest { ...@@ -222,6 +222,44 @@ public class DefaultDrmSessionManagerTest {
exoMediaDrm.release(); exoMediaDrm.release();
} }
// https://github.com/google/ExoPlayer/issues/9193
@Test(timeout = 10_000)
public void
managerReleasedBeforeSession_keepaliveEnabled_managerOnlyReleasesOneKeepaliveReference()
throws Exception {
FakeExoMediaDrm.LicenseServer licenseServer =
FakeExoMediaDrm.LicenseServer.allowingSchemeDatas(DRM_SCHEME_DATAS);
FakeExoMediaDrm exoMediaDrm = new FakeExoMediaDrm.Builder().build();
DrmSessionManager drmSessionManager =
new DefaultDrmSessionManager.Builder()
.setUuidAndExoMediaDrmProvider(DRM_SCHEME_UUID, new AppManagedProvider(exoMediaDrm))
.setSessionKeepaliveMs(10_000)
.build(/* mediaDrmCallback= */ licenseServer);
drmSessionManager.prepare();
DrmSession drmSession =
checkNotNull(
drmSessionManager.acquireSession(
/* playbackLooper= */ checkNotNull(Looper.myLooper()),
/* eventDispatcher= */ null,
FORMAT_WITH_DRM_INIT_DATA));
waitForOpenedWithKeys(drmSession);
// Release the manager (there's still an explicit reference to the session from acquireSession).
// This should immediately release the manager's internal keepalive session reference.
drmSessionManager.release();
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_OPENED_WITH_KEYS);
// Ensure the manager doesn't release a *second* keepalive session reference after the timer
// expires.
ShadowLooper.idleMainLooper(10, SECONDS);
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_OPENED_WITH_KEYS);
// Release the explicit session reference.
drmSession.release(/* eventDispatcher= */ null);
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_RELEASED);
}
@Test(timeout = 10_000) @Test(timeout = 10_000)
public void maxConcurrentSessionsExceeded_allKeepAliveSessionsEagerlyReleased() throws Exception { public void maxConcurrentSessionsExceeded_allKeepAliveSessionsEagerlyReleased() throws Exception {
ImmutableList<DrmInitData.SchemeData> secondSchemeDatas = ImmutableList<DrmInitData.SchemeData> secondSchemeDatas =
......
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