Skip to content

Commit

Permalink
Avoid providing invalid responses to MediaDrm
Browse files Browse the repository at this point in the history
MediaDrm.provideXResponse methods only accept the response
corresponding to the most recent MediaDrm.getXRequest call.
Previously, our code allowed the following incorrect call
sequence:

a = getKeyRequest
b = getKeyRequest
provideKeyResponse(responseFor(a));

This would occur in the edge case of a second key request
being triggered whilst the first was still in flight. The
provideKeyResponse call would then fail.

This change fixes the problem by treating responseFor(a)
as stale. Note that a slightly better fix would be to
defer calling getKeyRequest the second time until after
processing the response corresponding to the first one,
however this is significantly harder to implement, and is
probably not worth it for what should be an edge case.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=203481685
  • Loading branch information
ojw28 committed Jul 23, 2018
1 parent a50d31a commit 6ad9840
Showing 1 changed file with 32 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ public interface ProvisioningManager<T extends ExoMediaCrypto> {
private byte[] sessionId;
private byte[] offlineLicenseKeySetId;

private Object currentKeyRequest;
private Object currentProvisionRequest;

/**
* Instantiates a new DRM session.
*
Expand Down Expand Up @@ -171,6 +174,8 @@ public boolean release() {
requestHandlerThread = null;
mediaCrypto = null;
lastException = null;
currentKeyRequest = null;
currentProvisionRequest = null;
if (sessionId != null) {
mediaDrm.closeSession(sessionId);
sessionId = null;
Expand Down Expand Up @@ -215,8 +220,8 @@ public void onMediaDrmEvent(int what) {
// Provisioning implementation.

public void provision() {
ProvisionRequest request = mediaDrm.getProvisionRequest();
postRequestHandler.obtainMessage(MSG_PROVISION, request, true).sendToTarget();
currentProvisionRequest = mediaDrm.getProvisionRequest();
postRequestHandler.post(MSG_PROVISION, currentProvisionRequest, /* allowRetry= */ true);
}

public void onProvisionCompleted() {
Expand Down Expand Up @@ -289,11 +294,12 @@ private boolean openInternal(boolean allowProvisioning) {
return false;
}

private void onProvisionResponse(Object response) {
if (state != STATE_OPENING && !isOpen()) {
private void onProvisionResponse(Object request, Object response) {
if (request != currentProvisionRequest || (state != STATE_OPENING && !isOpen())) {
// This event is stale.
return;
}
currentProvisionRequest = null;

if (response instanceof Exception) {
provisioningManager.onProvisionError((Exception) response);
Expand Down Expand Up @@ -383,20 +389,21 @@ private void postKeyRequest(int type, boolean allowRetry) {
licenseServerUrl = schemeData.licenseServerUrl;
}
try {
KeyRequest request =
KeyRequest mediaDrmKeyRequest =
mediaDrm.getKeyRequest(scope, initData, mimeType, type, optionalKeyRequestParameters);
Pair<KeyRequest, String> arguments = Pair.create(request, licenseServerUrl);
postRequestHandler.obtainMessage(MSG_KEYS, arguments, allowRetry).sendToTarget();
currentKeyRequest = Pair.create(mediaDrmKeyRequest, licenseServerUrl);
postRequestHandler.post(MSG_KEYS, currentKeyRequest, allowRetry);
} catch (Exception e) {
onKeysError(e);
}
}

private void onKeyResponse(Object response) {
if (!isOpen()) {
private void onKeyResponse(Object request, Object response) {
if (request != currentKeyRequest || !isOpen()) {
// This event is stale.
return;
}
currentKeyRequest = null;

if (response instanceof Exception) {
onKeysError((Exception) response);
Expand Down Expand Up @@ -461,12 +468,15 @@ public PostResponseHandler(Looper looper) {

@Override
public void handleMessage(Message msg) {
Pair<?, ?> requestAndResponse = (Pair<?, ?>) msg.obj;
Object request = requestAndResponse.first;
Object response = requestAndResponse.second;
switch (msg.what) {
case MSG_PROVISION:
onProvisionResponse(msg.obj);
onProvisionResponse(request, response);
break;
case MSG_KEYS:
onKeyResponse(msg.obj);
onKeyResponse(request, response);
break;
default:
break;
Expand All @@ -483,23 +493,27 @@ public PostRequestHandler(Looper backgroundLooper) {
super(backgroundLooper);
}

Message obtainMessage(int what, Object object, boolean allowRetry) {
return obtainMessage(what, allowRetry ? 1 : 0 /* allow retry*/, 0 /* error count */,
object);
void post(int what, Object request, boolean allowRetry) {
int allowRetryInt = allowRetry ? 1 : 0;
int errorCount = 0;
obtainMessage(what, allowRetryInt, errorCount, request).sendToTarget();
}

@Override
@SuppressWarnings("unchecked")
public void handleMessage(Message msg) {
Object request = msg.obj;
Object response;
try {
switch (msg.what) {
case MSG_PROVISION:
response = callback.executeProvisionRequest(uuid, (ProvisionRequest) msg.obj);
response = callback.executeProvisionRequest(uuid, (ProvisionRequest) request);
break;
case MSG_KEYS:
Pair<KeyRequest, String> arguments = (Pair<KeyRequest, String>) msg.obj;
response = callback.executeKeyRequest(uuid, arguments.first, arguments.second);
Pair<KeyRequest, String> keyRequest = (Pair<KeyRequest, String>) request;
KeyRequest mediaDrmKeyRequest = keyRequest.first;
String licenseServerUrl = keyRequest.second;
response = callback.executeKeyRequest(uuid, mediaDrmKeyRequest, licenseServerUrl);
break;
default:
throw new RuntimeException();
Expand All @@ -510,7 +524,7 @@ public void handleMessage(Message msg) {
}
response = e;
}
postResponseHandler.obtainMessage(msg.what, response).sendToTarget();
postResponseHandler.obtainMessage(msg.what, Pair.create(request, response)).sendToTarget();
}

private boolean maybeRetryRequest(Message originalMsg) {
Expand Down

0 comments on commit 6ad9840

Please sign in to comment.