Add a test for the provisioning flow to DefaultDrmSessionManagerTest
#minor-release PiperOrigin-RevId: 379913814
This commit is contained in:
parent
6c05a469cb
commit
0f23fddeef
@ -43,9 +43,7 @@ import org.robolectric.shadows.ShadowLooper;
|
||||
// TODO: Test more branches:
|
||||
// - Different sources for licenseServerUrl.
|
||||
// - Multiple acquisitions & releases for same keys -> multiple requests.
|
||||
// - Provisioning.
|
||||
// - Key denial.
|
||||
// - Handling of ResourceBusyException (indicating session scarcity).
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DefaultDrmSessionManagerTest {
|
||||
|
||||
@ -538,6 +536,33 @@ public class DefaultDrmSessionManagerTest {
|
||||
exoMediaDrm.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceNotProvisioned_provisioningDoneAndOpenSessionRetried() {
|
||||
FakeExoMediaDrm.LicenseServer licenseServer =
|
||||
FakeExoMediaDrm.LicenseServer.allowingSchemeDatas(DRM_SCHEME_DATAS);
|
||||
|
||||
DefaultDrmSessionManager drmSessionManager =
|
||||
new DefaultDrmSessionManager.Builder()
|
||||
.setUuidAndExoMediaDrmProvider(
|
||||
DRM_SCHEME_UUID,
|
||||
uuid -> new FakeExoMediaDrm.Builder().setProvisionsRequired(1).build())
|
||||
.build(/* mediaDrmCallback= */ licenseServer);
|
||||
drmSessionManager.prepare();
|
||||
DrmSession drmSession =
|
||||
checkNotNull(
|
||||
drmSessionManager.acquireSession(
|
||||
/* playbackLooper= */ checkNotNull(Looper.myLooper()),
|
||||
/* eventDispatcher= */ null,
|
||||
FORMAT_WITH_DRM_INIT_DATA));
|
||||
// Confirm the device isn't provisioned (otherwise state would be OPENED)
|
||||
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_OPENING);
|
||||
waitForOpenedWithKeys(drmSession);
|
||||
|
||||
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_OPENED_WITH_KEYS);
|
||||
assertThat(drmSession.queryKeyStatus())
|
||||
.containsExactly(FakeExoMediaDrm.KEY_STATUS_KEY, FakeExoMediaDrm.KEY_STATUS_AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void managerNotPrepared_acquireSessionAndPreacquireSessionFail() throws Exception {
|
||||
FakeExoMediaDrm.LicenseServer licenseServer =
|
||||
@ -602,10 +627,10 @@ public class DefaultDrmSessionManagerTest {
|
||||
}
|
||||
|
||||
private static void waitForOpenedWithKeys(DrmSession drmSession) {
|
||||
// Check the error first, so we get a meaningful failure if there's been an error.
|
||||
assertThat(drmSession.getError()).isNull();
|
||||
assertThat(drmSession.getState()).isEqualTo(DrmSession.STATE_OPENED);
|
||||
while (drmSession.getState() != DrmSession.STATE_OPENED_WITH_KEYS) {
|
||||
// Check the error first, so we get a meaningful failure if there's been an error.
|
||||
assertThat(drmSession.getError()).isNull();
|
||||
assertThat(drmSession.getState()).isAnyOf(DrmSession.STATE_OPENING, DrmSession.STATE_OPENED);
|
||||
// Allow the key response to be handled.
|
||||
ShadowLooper.idleMainLooper();
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -61,8 +62,59 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
@RequiresApi(29)
|
||||
public final class FakeExoMediaDrm implements ExoMediaDrm {
|
||||
|
||||
/** Builder for {@link FakeExoMediaDrm} instances. */
|
||||
public static class Builder {
|
||||
private int provisionsRequired;
|
||||
private int maxConcurrentSessions;
|
||||
|
||||
/** Constructs an instance. */
|
||||
public Builder() {
|
||||
provisionsRequired = 0;
|
||||
maxConcurrentSessions = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets how many successful provisioning round trips are needed for the {@link FakeExoMediaDrm}
|
||||
* to be provisioned.
|
||||
*
|
||||
* <p>An unprovisioned {@link FakeExoMediaDrm} will throw {@link NotProvisionedException} from
|
||||
* {@link FakeExoMediaDrm#openSession()} until enough valid provisioning responses are passed to
|
||||
* {@link FakeExoMediaDrm#provideProvisionResponse(byte[])}.
|
||||
*
|
||||
* <p>Defaults to 0 (i.e. device is already provisioned).
|
||||
*/
|
||||
public Builder setProvisionsRequired(int provisionsRequired) {
|
||||
this.provisionsRequired = provisionsRequired;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of concurrent sessions the {@link FakeExoMediaDrm} will support.
|
||||
*
|
||||
* <p>If this is exceeded then subsequent calls to {@link FakeExoMediaDrm#openSession()} will
|
||||
* throw {@link ResourceBusyException}.
|
||||
*
|
||||
* <p>Defaults to {@link Integer#MAX_VALUE}.
|
||||
*/
|
||||
public Builder setMaxConcurrentSessions(int maxConcurrentSessions) {
|
||||
this.maxConcurrentSessions = maxConcurrentSessions;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link FakeExoMediaDrm} instance with an initial reference count of 1. The caller
|
||||
* is responsible for calling {@link FakeExoMediaDrm#release()} when they no longer need the
|
||||
* instance.
|
||||
*/
|
||||
public FakeExoMediaDrm build() {
|
||||
return new FakeExoMediaDrm(provisionsRequired, maxConcurrentSessions);
|
||||
}
|
||||
}
|
||||
|
||||
public static final ProvisionRequest FAKE_PROVISION_REQUEST =
|
||||
new ProvisionRequest(TestUtil.createByteArray(7, 8, 9), "bar.test");
|
||||
public static final ImmutableList<Byte> VALID_PROVISION_RESPONSE =
|
||||
TestUtil.createByteList(4, 5, 6);
|
||||
|
||||
/** Key for use with the Map returned from {@link FakeExoMediaDrm#queryKeyStatus(byte[])}. */
|
||||
public static final String KEY_STATUS_KEY = "KEY_STATUS";
|
||||
@ -74,6 +126,7 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
|
||||
private static final ImmutableList<Byte> VALID_KEY_RESPONSE = TestUtil.createByteList(1, 2, 3);
|
||||
private static final ImmutableList<Byte> KEY_DENIED_RESPONSE = TestUtil.createByteList(9, 8, 7);
|
||||
|
||||
private final int provisionsRequired;
|
||||
private final int maxConcurrentSessions;
|
||||
private final Map<String, byte[]> byteProperties;
|
||||
private final Map<String, String> stringProperties;
|
||||
@ -81,24 +134,24 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
|
||||
private final Set<List<Byte>> sessionIdsWithValidKeys;
|
||||
private final AtomicInteger sessionIdGenerator;
|
||||
|
||||
private int provisionsReceived;
|
||||
private int referenceCount;
|
||||
@Nullable private OnEventListener onEventListener;
|
||||
|
||||
/**
|
||||
* Constructs an instance that returns random and unique {@code sessionIds} for subsequent calls
|
||||
* to {@link #openSession()} with no limit on the number of concurrent open sessions.
|
||||
*/
|
||||
/** @deprecated Use {@link Builder} instead. */
|
||||
@Deprecated
|
||||
public FakeExoMediaDrm() {
|
||||
this(/* maxConcurrentSessions= */ Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance that returns random and unique {@code sessionIds} for subsequent calls
|
||||
* to {@link #openSession()} with a limit on the number of concurrent open sessions.
|
||||
*
|
||||
* @param maxConcurrentSessions The max number of sessions allowed to be open simultaneously.
|
||||
*/
|
||||
/** @deprecated Use {@link Builder} instead. */
|
||||
@Deprecated
|
||||
public FakeExoMediaDrm(int maxConcurrentSessions) {
|
||||
this(/* provisionsRequired= */ 0, maxConcurrentSessions);
|
||||
}
|
||||
|
||||
private FakeExoMediaDrm(int provisionsRequired, int maxConcurrentSessions) {
|
||||
this.provisionsRequired = provisionsRequired;
|
||||
this.maxConcurrentSessions = maxConcurrentSessions;
|
||||
byteProperties = new HashMap<>();
|
||||
stringProperties = new HashMap<>();
|
||||
@ -129,6 +182,9 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
|
||||
@Override
|
||||
public byte[] openSession() throws MediaDrmException {
|
||||
Assertions.checkState(referenceCount > 0);
|
||||
if (provisionsReceived < provisionsRequired) {
|
||||
throw new NotProvisionedException("Not provisioned.");
|
||||
}
|
||||
if (openSessionIds.size() >= maxConcurrentSessions) {
|
||||
throw new ResourceBusyException("Too many sessions open. max=" + maxConcurrentSessions);
|
||||
}
|
||||
@ -200,6 +256,9 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
|
||||
@Override
|
||||
public void provideProvisionResponse(byte[] response) throws DeniedByServerException {
|
||||
Assertions.checkState(referenceCount > 0);
|
||||
if (Bytes.asList(response).equals(VALID_PROVISION_RESPONSE)) {
|
||||
provisionsReceived++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -340,7 +399,11 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
|
||||
@Override
|
||||
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request)
|
||||
throws MediaDrmCallbackException {
|
||||
return new byte[0];
|
||||
if (Arrays.equals(request.getData(), FAKE_PROVISION_REQUEST.getData())) {
|
||||
return Bytes.toArray(VALID_PROVISION_RESPONSE);
|
||||
} else {
|
||||
return Util.EMPTY_BYTE_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user