mirror of
https://github.com/androidx/media.git
synced 2025-05-06 23:20:42 +08:00
Allow DefaultDRMSession to retry provisioning/key request
For initial DRM provisioning and key request, we allow the requests to be retried (with increasing delay for each successive retry) before failing. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=171271384
This commit is contained in:
parent
f73a5bf692
commit
d5101d8d46
@ -82,6 +82,7 @@ import java.util.UUID;
|
||||
private final HashMap<String, String> optionalKeyRequestParameters;
|
||||
private final Handler eventHandler;
|
||||
private final DefaultDrmSessionManager.EventListener eventListener;
|
||||
private final int initialDrmRequestRetryCount;
|
||||
|
||||
/* package */ final MediaDrmCallback callback;
|
||||
/* package */ final UUID uuid;
|
||||
@ -89,7 +90,7 @@ import java.util.UUID;
|
||||
private @DrmSession.State int state;
|
||||
private int openCount;
|
||||
private HandlerThread requestHandlerThread;
|
||||
private Handler postRequestHandler;
|
||||
private PostRequestHandler postRequestHandler;
|
||||
private T mediaCrypto;
|
||||
private DrmSessionException lastException;
|
||||
private byte[] sessionId;
|
||||
@ -111,13 +112,16 @@ import java.util.UUID;
|
||||
* @param playbackLooper The playback looper.
|
||||
* @param eventHandler The handler to post listener events.
|
||||
* @param eventListener The DRM session manager event listener.
|
||||
* @param initialDrmRequestRetryCount The number of times to retry for initial provisioning and
|
||||
* key request before reporting error.
|
||||
*/
|
||||
public DefaultDrmSession(UUID uuid, ExoMediaDrm<T> mediaDrm,
|
||||
ProvisioningManager<T> provisioningManager, byte[] initData, String mimeType,
|
||||
@DefaultDrmSessionManager.Mode int mode, byte[] offlineLicenseKeySetId,
|
||||
HashMap<String, String> optionalKeyRequestParameters, MediaDrmCallback callback,
|
||||
Looper playbackLooper, Handler eventHandler,
|
||||
DefaultDrmSessionManager.EventListener eventListener) {
|
||||
DefaultDrmSessionManager.EventListener eventListener,
|
||||
int initialDrmRequestRetryCount) {
|
||||
this.uuid = uuid;
|
||||
this.provisioningManager = provisioningManager;
|
||||
this.mediaDrm = mediaDrm;
|
||||
@ -125,6 +129,7 @@ import java.util.UUID;
|
||||
this.offlineLicenseKeySetId = offlineLicenseKeySetId;
|
||||
this.optionalKeyRequestParameters = optionalKeyRequestParameters;
|
||||
this.callback = callback;
|
||||
this.initialDrmRequestRetryCount = initialDrmRequestRetryCount;
|
||||
|
||||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
@ -152,7 +157,7 @@ import java.util.UUID;
|
||||
return;
|
||||
}
|
||||
if (openInternal(true)) {
|
||||
doLicense();
|
||||
doLicense(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,12 +196,12 @@ import java.util.UUID;
|
||||
|
||||
public void provision() {
|
||||
ProvisionRequest request = mediaDrm.getProvisionRequest();
|
||||
postRequestHandler.obtainMessage(MSG_PROVISION, request).sendToTarget();
|
||||
postRequestHandler.obtainMessage(MSG_PROVISION, request, true).sendToTarget();
|
||||
}
|
||||
|
||||
public void onProvisionCompleted() {
|
||||
if (openInternal(false)) {
|
||||
doLicense();
|
||||
doLicense(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,12 +290,12 @@ import java.util.UUID;
|
||||
provisioningManager.onProvisionCompleted();
|
||||
}
|
||||
|
||||
private void doLicense() {
|
||||
private void doLicense(boolean allowRetry) {
|
||||
switch (mode) {
|
||||
case DefaultDrmSessionManager.MODE_PLAYBACK:
|
||||
case DefaultDrmSessionManager.MODE_QUERY:
|
||||
if (offlineLicenseKeySetId == null) {
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_STREAMING);
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_STREAMING, allowRetry);
|
||||
} else {
|
||||
if (restoreKeys()) {
|
||||
long licenseDurationRemainingSec = getLicenseDurationRemainingSec();
|
||||
@ -298,7 +303,7 @@ import java.util.UUID;
|
||||
&& licenseDurationRemainingSec <= MAX_LICENSE_DURATION_TO_RENEW) {
|
||||
Log.d(TAG, "Offline license has expired or will expire soon. "
|
||||
+ "Remaining seconds: " + licenseDurationRemainingSec);
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE);
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry);
|
||||
} else if (licenseDurationRemainingSec <= 0) {
|
||||
onError(new KeysExpiredException());
|
||||
} else {
|
||||
@ -317,11 +322,11 @@ import java.util.UUID;
|
||||
break;
|
||||
case DefaultDrmSessionManager.MODE_DOWNLOAD:
|
||||
if (offlineLicenseKeySetId == null) {
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE);
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry);
|
||||
} else {
|
||||
// Renew
|
||||
if (restoreKeys()) {
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE);
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -329,7 +334,7 @@ import java.util.UUID;
|
||||
// It's not necessary to restore the key (and open a session to do that) before releasing it
|
||||
// but this serves as a good sanity/fast-failure check.
|
||||
if (restoreKeys()) {
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_RELEASE);
|
||||
postKeyRequest(ExoMediaDrm.KEY_TYPE_RELEASE, allowRetry);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -356,12 +361,12 @@ import java.util.UUID;
|
||||
return Math.min(pair.first, pair.second);
|
||||
}
|
||||
|
||||
private void postKeyRequest(int type) {
|
||||
private void postKeyRequest(int type, boolean allowRetry) {
|
||||
byte[] scope = type == ExoMediaDrm.KEY_TYPE_RELEASE ? offlineLicenseKeySetId : sessionId;
|
||||
try {
|
||||
KeyRequest request = mediaDrm.getKeyRequest(scope, initData, mimeType, type,
|
||||
optionalKeyRequestParameters);
|
||||
postRequestHandler.obtainMessage(MSG_KEYS, request).sendToTarget();
|
||||
postRequestHandler.obtainMessage(MSG_KEYS, request, allowRetry).sendToTarget();
|
||||
} catch (Exception e) {
|
||||
onKeysError(e);
|
||||
}
|
||||
@ -452,7 +457,7 @@ import java.util.UUID;
|
||||
}
|
||||
switch (what) {
|
||||
case ExoMediaDrm.EVENT_KEY_REQUIRED:
|
||||
doLicense();
|
||||
doLicense(false);
|
||||
break;
|
||||
case ExoMediaDrm.EVENT_KEY_EXPIRED:
|
||||
// When an already expired key is loaded MediaDrm sends this event immediately. Ignore
|
||||
@ -501,6 +506,11 @@ import java.util.UUID;
|
||||
super(backgroundLooper);
|
||||
}
|
||||
|
||||
Message obtainMessage(int what, Object object, boolean allowRetry) {
|
||||
return obtainMessage(what, allowRetry ? 1 : 0 /* allow retry*/, 0 /* error count */,
|
||||
object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
Object response;
|
||||
@ -516,11 +526,33 @@ import java.util.UUID;
|
||||
throw new RuntimeException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (maybeRetryRequest(msg)) {
|
||||
return;
|
||||
}
|
||||
response = e;
|
||||
}
|
||||
postResponseHandler.obtainMessage(msg.what, response).sendToTarget();
|
||||
}
|
||||
|
||||
private boolean maybeRetryRequest(Message originalMsg) {
|
||||
boolean allowRetry = originalMsg.arg1 == 1;
|
||||
if (!allowRetry) {
|
||||
return false;
|
||||
}
|
||||
int errorCount = originalMsg.arg2 + 1;
|
||||
if (errorCount > initialDrmRequestRetryCount) {
|
||||
return false;
|
||||
}
|
||||
Message retryMsg = Message.obtain(originalMsg);
|
||||
retryMsg.arg2 = errorCount;
|
||||
sendMessageDelayed(retryMsg, getRetryDelayMillis(errorCount));
|
||||
return true;
|
||||
}
|
||||
|
||||
private long getRetryDelayMillis(int errorCount) {
|
||||
return Math.min((errorCount - 1) * 1000, 5000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -97,6 +97,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
||||
public static final int MODE_DOWNLOAD = 2;
|
||||
/** Releases an existing offline license. */
|
||||
public static final int MODE_RELEASE = 3;
|
||||
/** Number of times to retry for initial provisioning and key request for reporting error. */
|
||||
public static final int INITIAL_DRM_REQUEST_RETRY_COUNT = 3;
|
||||
|
||||
private final UUID uuid;
|
||||
private final ExoMediaDrm<T> mediaDrm;
|
||||
@ -105,6 +107,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
||||
private final Handler eventHandler;
|
||||
private final EventListener eventListener;
|
||||
private final boolean multiSession;
|
||||
private final int initialDrmRequestRetryCount;
|
||||
|
||||
private final List<DefaultDrmSession<T>> sessions;
|
||||
private final List<DefaultDrmSession<T>> provisioningSessions;
|
||||
@ -176,7 +179,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
||||
UUID uuid, MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters,
|
||||
Handler eventHandler, EventListener eventListener) throws UnsupportedDrmException {
|
||||
return new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), callback,
|
||||
optionalKeyRequestParameters, eventHandler, eventListener, false);
|
||||
optionalKeyRequestParameters, eventHandler, eventListener, false,
|
||||
INITIAL_DRM_REQUEST_RETRY_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -193,7 +197,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
||||
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
|
||||
EventListener eventListener) {
|
||||
this(uuid, mediaDrm, callback, optionalKeyRequestParameters, eventHandler, eventListener,
|
||||
false);
|
||||
false, INITIAL_DRM_REQUEST_RETRY_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,6 +215,27 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
||||
public DefaultDrmSessionManager(UUID uuid, ExoMediaDrm<T> mediaDrm, MediaDrmCallback callback,
|
||||
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
|
||||
EventListener eventListener, boolean multiSession) {
|
||||
this(uuid, mediaDrm, callback, optionalKeyRequestParameters, eventHandler, eventListener,
|
||||
multiSession, INITIAL_DRM_REQUEST_RETRY_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uuid The UUID of the drm scheme.
|
||||
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
|
||||
* @param callback Performs key and provisioning requests.
|
||||
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
|
||||
* to {@link ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param multiSession A boolean that specify whether multiple key session support is enabled.
|
||||
* Default is false.
|
||||
* @param initialDrmRequestRetryCount The number of times to retry for initial provisioning and
|
||||
* key request before reporting error.
|
||||
*/
|
||||
public DefaultDrmSessionManager(UUID uuid, ExoMediaDrm<T> mediaDrm, MediaDrmCallback callback,
|
||||
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
|
||||
EventListener eventListener, boolean multiSession, int initialDrmRequestRetryCount) {
|
||||
Assertions.checkNotNull(uuid);
|
||||
Assertions.checkNotNull(mediaDrm);
|
||||
Assertions.checkArgument(!C.COMMON_PSSH_UUID.equals(uuid), "Use C.CLEARKEY_UUID instead");
|
||||
@ -221,6 +246,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
||||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
this.multiSession = multiSession;
|
||||
this.initialDrmRequestRetryCount = initialDrmRequestRetryCount;
|
||||
mode = MODE_PLAYBACK;
|
||||
sessions = new ArrayList<>();
|
||||
provisioningSessions = new ArrayList<>();
|
||||
@ -377,7 +403,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
||||
// Create a new session.
|
||||
session = new DefaultDrmSession<>(uuid, mediaDrm, this, initData, mimeType, mode,
|
||||
offlineLicenseKeySetId, optionalKeyRequestParameters, callback, playbackLooper,
|
||||
eventHandler, eventListener);
|
||||
eventHandler, eventListener, initialDrmRequestRetryCount);
|
||||
sessions.add(session);
|
||||
}
|
||||
session.acquire();
|
||||
|
Loading…
x
Reference in New Issue
Block a user