mirror of
https://github.com/samsonjs/media.git
synced 2026-04-17 13:15:47 +00:00
Add a release callback to DefaultDrmSession
In preparation for reference counting in DrmSession PiperOrigin-RevId: 247428114
This commit is contained in:
parent
0a6f81a2cc
commit
3b60584813
2 changed files with 60 additions and 56 deletions
|
|
@ -42,20 +42,16 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
|
|||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
/**
|
||||
* A {@link DrmSession} that supports playbacks using {@link ExoMediaDrm}.
|
||||
*/
|
||||
/** A {@link DrmSession} that supports playbacks using {@link ExoMediaDrm}. */
|
||||
@TargetApi(18)
|
||||
/* package */ class DefaultDrmSession<T extends ExoMediaCrypto> implements DrmSession<T> {
|
||||
|
||||
/**
|
||||
* Manages provisioning requests.
|
||||
*/
|
||||
/** Manages provisioning requests. */
|
||||
public interface ProvisioningManager<T extends ExoMediaCrypto> {
|
||||
|
||||
/**
|
||||
* Called when a session requires provisioning. The manager <em>may</em> call
|
||||
* {@link #provision()} to have this session perform the provisioning operation. The manager
|
||||
* Called when a session requires provisioning. The manager <em>may</em> call {@link
|
||||
* #provision()} to have this session perform the provisioning operation. The manager
|
||||
* <em>will</em> call {@link DefaultDrmSession#onProvisionCompleted()} when provisioning has
|
||||
* completed, or {@link DefaultDrmSession#onProvisionError} if provisioning fails.
|
||||
*
|
||||
|
|
@ -70,11 +66,19 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
*/
|
||||
void onProvisionError(Exception error);
|
||||
|
||||
/**
|
||||
* Called by a session when it successfully completes a provisioning operation.
|
||||
*/
|
||||
/** Called by a session when it successfully completes a provisioning operation. */
|
||||
void onProvisionCompleted();
|
||||
}
|
||||
|
||||
/** Callback to be notified when the session is released. */
|
||||
public interface ReleaseCallback<T extends ExoMediaCrypto> {
|
||||
|
||||
/**
|
||||
* Called when the session is released.
|
||||
*
|
||||
* @param session The session.
|
||||
*/
|
||||
void onSessionReleased(DefaultDrmSession<T> session);
|
||||
}
|
||||
|
||||
private static final String TAG = "DefaultDrmSession";
|
||||
|
|
@ -88,6 +92,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
|
||||
private final ExoMediaDrm<T> mediaDrm;
|
||||
private final ProvisioningManager<T> provisioningManager;
|
||||
private final ReleaseCallback<T> releaseCallback;
|
||||
private final @DefaultDrmSessionManager.Mode int mode;
|
||||
private final @Nullable HashMap<String, String> optionalKeyRequestParameters;
|
||||
private final EventDispatcher<DefaultDrmSessionEventListener> eventDispatcher;
|
||||
|
|
@ -115,6 +120,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
* @param uuid The UUID of the drm scheme.
|
||||
* @param mediaDrm The media DRM.
|
||||
* @param provisioningManager The manager for provisioning.
|
||||
* @param releaseCallback The {@link ReleaseCallback}.
|
||||
* @param schemeDatas DRM scheme datas for this session, or null if an {@code
|
||||
* offlineLicenseKeySetId} is provided.
|
||||
* @param mode The DRM mode.
|
||||
|
|
@ -131,6 +137,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
UUID uuid,
|
||||
ExoMediaDrm<T> mediaDrm,
|
||||
ProvisioningManager<T> provisioningManager,
|
||||
ReleaseCallback<T> releaseCallback,
|
||||
@Nullable List<SchemeData> schemeDatas,
|
||||
@DefaultDrmSessionManager.Mode int mode,
|
||||
@Nullable byte[] offlineLicenseKeySetId,
|
||||
|
|
@ -145,6 +152,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
}
|
||||
this.uuid = uuid;
|
||||
this.provisioningManager = provisioningManager;
|
||||
this.releaseCallback = releaseCallback;
|
||||
this.mediaDrm = mediaDrm;
|
||||
this.mode = mode;
|
||||
if (offlineLicenseKeySetId != null) {
|
||||
|
|
@ -178,10 +186,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
}
|
||||
}
|
||||
|
||||
/** @return True if the session is closed and cleaned up, false otherwise. */
|
||||
// Assigning null to various non-null variables for clean-up. Class won't be used after release.
|
||||
@SuppressWarnings("assignment.type.incompatible")
|
||||
public boolean release() {
|
||||
public void release() {
|
||||
if (--openCount == 0) {
|
||||
state = STATE_RELEASED;
|
||||
postResponseHandler.removeCallbacksAndMessages(null);
|
||||
|
|
@ -198,9 +205,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
sessionId = null;
|
||||
eventDispatcher.dispatch(DefaultDrmSessionEventListener::onDrmSessionReleased);
|
||||
}
|
||||
return true;
|
||||
releaseCallback.onSessionReleased(this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasSessionId(byte[] sessionId) {
|
||||
|
|
@ -330,8 +336,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
long licenseDurationRemainingSec = getLicenseDurationRemainingSec();
|
||||
if (mode == DefaultDrmSessionManager.MODE_PLAYBACK
|
||||
&& licenseDurationRemainingSec <= MAX_LICENSE_DURATION_TO_RENEW) {
|
||||
Log.d(TAG, "Offline license has expired or will expire soon. "
|
||||
+ "Remaining seconds: " + licenseDurationRemainingSec);
|
||||
Log.d(
|
||||
TAG,
|
||||
"Offline license has expired or will expire soon. "
|
||||
+ "Remaining seconds: "
|
||||
+ licenseDurationRemainingSec);
|
||||
postKeyRequest(sessionId, ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry);
|
||||
} else if (licenseDurationRemainingSec <= 0) {
|
||||
onError(new KeysExpiredException());
|
||||
|
|
@ -415,8 +424,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
} else {
|
||||
byte[] keySetId = mediaDrm.provideKeyResponse(sessionId, responseData);
|
||||
if ((mode == DefaultDrmSessionManager.MODE_DOWNLOAD
|
||||
|| (mode == DefaultDrmSessionManager.MODE_PLAYBACK && offlineLicenseKeySetId != null))
|
||||
&& keySetId != null && keySetId.length != 0) {
|
||||
|| (mode == DefaultDrmSessionManager.MODE_PLAYBACK
|
||||
&& offlineLicenseKeySetId != null))
|
||||
&& keySetId != null
|
||||
&& keySetId.length != 0) {
|
||||
offlineLicenseKeySetId = keySetId;
|
||||
}
|
||||
state = STATE_OPENED_WITH_KEYS;
|
||||
|
|
@ -480,10 +491,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("HandlerLeak")
|
||||
|
|
@ -541,6 +550,5 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
private long getRetryDelayMillis(int errorCount) {
|
||||
return Math.min((errorCount - 1) * 1000, 5000);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,12 +40,10 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A {@link DrmSessionManager} that supports playbacks using {@link ExoMediaDrm}.
|
||||
*/
|
||||
/** A {@link DrmSessionManager} that supports playbacks using {@link ExoMediaDrm}. */
|
||||
@TargetApi(18)
|
||||
public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSessionManager<T>,
|
||||
ProvisioningManager<T> {
|
||||
public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
||||
implements DrmSessionManager<T>, ProvisioningManager<T> {
|
||||
|
||||
/**
|
||||
* Signals that the {@link DrmInitData} passed to {@link #acquireSession} does not contain does
|
||||
|
|
@ -76,9 +74,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
* licenses.
|
||||
*/
|
||||
public static final int MODE_PLAYBACK = 0;
|
||||
/**
|
||||
* Restores an offline license to allow its status to be queried.
|
||||
*/
|
||||
/** Restores an offline license to allow its status to be queried. */
|
||||
public static final int MODE_QUERY = 1;
|
||||
/** Downloads an offline license or renews an existing one. */
|
||||
public static final int MODE_DOWNLOAD = 2;
|
||||
|
|
@ -272,8 +268,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
|
||||
/**
|
||||
* Provides access to {@link ExoMediaDrm#getPropertyString(String)}.
|
||||
* <p>
|
||||
* This method may be called when the manager is in any state.
|
||||
*
|
||||
* <p>This method may be called when the manager is in any state.
|
||||
*
|
||||
* @param key The key to request.
|
||||
* @return The retrieved property.
|
||||
|
|
@ -284,8 +280,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
|
||||
/**
|
||||
* Provides access to {@link ExoMediaDrm#setPropertyString(String, String)}.
|
||||
* <p>
|
||||
* This method may be called when the manager is in any state.
|
||||
*
|
||||
* <p>This method may be called when the manager is in any state.
|
||||
*
|
||||
* @param key The property to write.
|
||||
* @param value The value to write.
|
||||
|
|
@ -296,8 +292,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
|
||||
/**
|
||||
* Provides access to {@link ExoMediaDrm#getPropertyByteArray(String)}.
|
||||
* <p>
|
||||
* This method may be called when the manager is in any state.
|
||||
*
|
||||
* <p>This method may be called when the manager is in any state.
|
||||
*
|
||||
* @param key The key to request.
|
||||
* @return The retrieved property.
|
||||
|
|
@ -308,8 +304,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
|
||||
/**
|
||||
* Provides access to {@link ExoMediaDrm#setPropertyByteArray(String, byte[])}.
|
||||
* <p>
|
||||
* This method may be called when the manager is in any state.
|
||||
*
|
||||
* <p>This method may be called when the manager is in any state.
|
||||
*
|
||||
* @param key The property to write.
|
||||
* @param value The value to write.
|
||||
|
|
@ -373,7 +369,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
if (schemeType == null || C.CENC_TYPE_cenc.equals(schemeType)) {
|
||||
// If there is no scheme information, assume patternless AES-CTR.
|
||||
return true;
|
||||
} else if (C.CENC_TYPE_cbc1.equals(schemeType) || C.CENC_TYPE_cbcs.equals(schemeType)
|
||||
} else if (C.CENC_TYPE_cbc1.equals(schemeType)
|
||||
|| C.CENC_TYPE_cbcs.equals(schemeType)
|
||||
|| C.CENC_TYPE_cens.equals(schemeType)) {
|
||||
// API support for AES-CBC and pattern encryption was added in API 24. However, the
|
||||
// implementation was not stable until API 25.
|
||||
|
|
@ -423,7 +420,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
new DefaultDrmSession<>(
|
||||
uuid,
|
||||
mediaDrm,
|
||||
this,
|
||||
/* provisioningManager= */ this,
|
||||
/* releaseCallback= */ this::onSessionReleased,
|
||||
schemeDatas,
|
||||
mode,
|
||||
offlineLicenseKeySetId,
|
||||
|
|
@ -444,17 +442,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
// Do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultDrmSession<T> drmSession = (DefaultDrmSession<T>) session;
|
||||
if (drmSession.release()) {
|
||||
sessions.remove(drmSession);
|
||||
if (provisioningSessions.size() > 1 && provisioningSessions.get(0) == drmSession) {
|
||||
// Other sessions were waiting for the released session to complete a provision operation.
|
||||
// We need to have one of those sessions perform the provision operation instead.
|
||||
provisioningSessions.get(1).provision();
|
||||
}
|
||||
provisioningSessions.remove(drmSession);
|
||||
}
|
||||
((DefaultDrmSession<T>) session).release();
|
||||
}
|
||||
|
||||
// ProvisioningManager implementation.
|
||||
|
|
@ -490,6 +478,16 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
|
||||
// Internal methods.
|
||||
|
||||
private void onSessionReleased(DefaultDrmSession<T> drmSession) {
|
||||
sessions.remove(drmSession);
|
||||
if (provisioningSessions.size() > 1 && provisioningSessions.get(0) == drmSession) {
|
||||
// Other sessions were waiting for the released session to complete a provision operation.
|
||||
// We need to have one of those sessions perform the provision operation instead.
|
||||
provisioningSessions.get(1).provision();
|
||||
}
|
||||
provisioningSessions.remove(drmSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts {@link SchemeData} instances suitable for the given DRM scheme {@link UUID}.
|
||||
*
|
||||
|
|
@ -506,8 +504,9 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
List<SchemeData> matchingSchemeDatas = new ArrayList<>(drmInitData.schemeDataCount);
|
||||
for (int i = 0; i < drmInitData.schemeDataCount; i++) {
|
||||
SchemeData schemeData = drmInitData.get(i);
|
||||
boolean uuidMatches = schemeData.matches(uuid)
|
||||
|| (C.CLEARKEY_UUID.equals(uuid) && schemeData.matches(C.COMMON_PSSH_UUID));
|
||||
boolean uuidMatches =
|
||||
schemeData.matches(uuid)
|
||||
|| (C.CLEARKEY_UUID.equals(uuid) && schemeData.matches(C.COMMON_PSSH_UUID));
|
||||
if (uuidMatches && (schemeData.data != null || allowMissingData)) {
|
||||
matchingSchemeDatas.add(schemeData);
|
||||
}
|
||||
|
|
@ -536,7 +535,6 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class MediaDrmEventListener implements OnEventListener<T> {
|
||||
|
|
@ -550,7 +548,5 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
|
|||
@Nullable byte[] data) {
|
||||
Assertions.checkNotNull(mediaDrmHandler).obtainMessage(event, sessionId).sendToTarget();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue