From fd25d2f5ea2dc26bef34f52da83b17e9fb79b17a Mon Sep 17 00:00:00 2001 From: ibaker Date: Thu, 27 May 2021 17:53:10 +0100 Subject: [PATCH] Add a test for handling of DRM key refresh events In a follow-up change I will add an additional test to ensure these events continue to be correctly handled when DefaultDrmSessionManager has prepareCount==0 but a non-null ExoMediaDrm instance. PiperOrigin-RevId: 376190225 --- .../drm/DefaultDrmSessionManagerTest.java | 44 +++++++++++++++++++ .../exoplayer2/testutil/FakeExoMediaDrm.java | 27 +++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/library/core/src/test/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManagerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManagerTest.java index b29c82e61e..86e6c55d6b 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManagerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManagerTest.java @@ -25,12 +25,14 @@ import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.drm.ExoMediaDrm.AppManagedProvider; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.testutil.FakeExoMediaDrm; import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; @@ -408,6 +410,48 @@ public class DefaultDrmSessionManagerTest { drmSessionManager.release(); } + @Test(timeout = 10_000) + public void keyRefreshEvent_triggersKeyRefresh() throws Exception { + FakeExoMediaDrm exoMediaDrm = new FakeExoMediaDrm(); + FakeExoMediaDrm.LicenseServer licenseServer = + FakeExoMediaDrm.LicenseServer.allowingSchemeDatas(DRM_SCHEME_DATAS); + DrmSessionManager drmSessionManager = + new DefaultDrmSessionManager.Builder() + .setUuidAndExoMediaDrmProvider(DRM_SCHEME_UUID, new AppManagedProvider(exoMediaDrm)) + .build(/* mediaDrmCallback= */ licenseServer); + + drmSessionManager.prepare(); + + DefaultDrmSession drmSession = + (DefaultDrmSession) + checkNotNull( + drmSessionManager.acquireSession( + /* playbackLooper= */ checkNotNull(Looper.myLooper()), + /* eventDispatcher= */ null, + FORMAT_WITH_DRM_INIT_DATA)); + waitForOpenedWithKeys(drmSession); + + assertThat(licenseServer.getReceivedSchemeDatas()).hasSize(1); + + exoMediaDrm.triggerEvent( + drmSession::hasSessionId, + ExoMediaDrm.EVENT_KEY_REQUIRED, + /* extra= */ 0, + /* data= */ Util.EMPTY_BYTE_ARRAY); + + while (licenseServer.getReceivedSchemeDatas().size() == 1) { + // Allow the key refresh event to be handled. + ShadowLooper.idleMainLooper(); + } + + assertThat(licenseServer.getReceivedSchemeDatas()).hasSize(2); + assertThat(ImmutableSet.copyOf(licenseServer.getReceivedSchemeDatas())).hasSize(1); + + drmSession.release(/* eventDispatcher= */ null); + drmSessionManager.release(); + exoMediaDrm.release(); + } + @Test public void managerNotPrepared_acquireSessionAndPreacquireSessionFail() throws Exception { FakeExoMediaDrm.LicenseServer licenseServer = diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java index 5ad0435885..35bb52ccec 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java @@ -33,6 +33,7 @@ import com.google.android.exoplayer2.drm.MediaDrmCallback; import com.google.android.exoplayer2.drm.MediaDrmCallbackException; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; +import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -81,6 +82,7 @@ public final class FakeExoMediaDrm implements ExoMediaDrm { private final AtomicInteger sessionIdGenerator; private int referenceCount; + @Nullable private OnEventListener onEventListener; /** * Constructs an instance that returns random and unique {@code sessionIds} for subsequent calls @@ -107,11 +109,11 @@ public final class FakeExoMediaDrm implements ExoMediaDrm { referenceCount = 1; } - // ExoMediaCrypto implementation + // ExoMediaDrm implementation @Override public void setOnEventListener(@Nullable OnEventListener listener) { - // Do nothing. + this.onEventListener = listener; } @Override @@ -279,6 +281,27 @@ public final class FakeExoMediaDrm implements ExoMediaDrm { return FakeExoMediaCrypto.class; } + // Methods to facilitate testing + + /** + * Calls {@link OnEventListener#onEvent(ExoMediaDrm, byte[], int, int, byte[])} on the attached + * listener (if present) once for each open session ID which passes {@code sessionIdPredicate}, + * passing the provided values for {@code event}, {@code extra} and {@code data}. + */ + public void triggerEvent( + Predicate sessionIdPredicate, int event, int extra, @Nullable byte[] data) { + @Nullable OnEventListener onEventListener = this.onEventListener; + if (onEventListener == null) { + return; + } + for (List sessionId : openSessionIds) { + byte[] sessionIdArray = Bytes.toArray(sessionId); + if (sessionIdPredicate.apply(sessionIdArray)) { + onEventListener.onEvent(this, sessionIdArray, event, extra, data); + } + } + } + private static ImmutableList toByteList(byte[] byteArray) { return ImmutableList.copyOf(Bytes.asList(byteArray)); }