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
This commit is contained in:
ibaker 2021-05-27 17:53:10 +01:00 committed by Oliver Woodman
parent 10e96c99e5
commit fd25d2f5ea
2 changed files with 69 additions and 2 deletions

View File

@ -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 =

View File

@ -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<byte[]> sessionIdPredicate, int event, int extra, @Nullable byte[] data) {
@Nullable OnEventListener onEventListener = this.onEventListener;
if (onEventListener == null) {
return;
}
for (List<Byte> sessionId : openSessionIds) {
byte[] sessionIdArray = Bytes.toArray(sessionId);
if (sessionIdPredicate.apply(sessionIdArray)) {
onEventListener.onEvent(this, sessionIdArray, event, extra, data);
}
}
}
private static ImmutableList<Byte> toByteList(byte[] byteArray) {
return ImmutableList.copyOf(Bytes.asList(byteArray));
}