Index: media/base/android/java/src/org/chromium/media/MediaDrmBridge.java |
diff --git a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java |
index 302b8b32c032436cefcb691dbeb62ddc4730aa2d..b1bc8368466c78da51dafdd3b013c332e8b0d390 100644 |
--- a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java |
+++ b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java |
@@ -23,6 +23,7 @@ import java.io.IOException; |
import java.nio.ByteBuffer; |
import java.nio.ByteOrder; |
import java.util.ArrayDeque; |
+import java.util.Arrays; |
import java.util.HashMap; |
import java.util.UUID; |
@@ -60,6 +61,14 @@ public class MediaDrmBridge { |
private static final String SESSION_SHARING = "sessionSharing"; |
private static final String ENABLE = "enable"; |
private static final int INVALID_SESSION_ID = 0; |
+ private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray(); |
+ |
+ // KeyStatus for CDM key information. MUST keep this value in sync with |
+ // CdmKeyInformation::KeyStatus. |
+ private static final int KEY_STATUS_USABLE = 0; |
+ private static final int KEY_STATUS_INTERNAL_ERROR = 1; |
+ private static final int KEY_STATUS_EXPIRED = 2; |
+ private static final int KEY_STATUS_OUTPUT_NOT_ALLOWED = 3; |
private MediaDrm mMediaDrm; |
private long mNativeMediaDrmBridge; |
@@ -71,13 +80,11 @@ public class MediaDrmBridge { |
// time. All following createSession() calls will create a new session and |
// use it to call getKeyRequest(). No getKeyRequest() should ever be called |
// on |mMediaCryptoSession|. |
- private ByteBuffer mMediaCryptoSession; |
+ private byte[] mMediaCryptoSession; |
private MediaCrypto mMediaCrypto; |
- // The map of all opened sessions to their session reference IDs. |
- private HashMap<ByteBuffer, Integer> mSessionIds; |
- // The map of all opened sessions to their mime types. |
- private HashMap<ByteBuffer, String> mSessionMimeTypes; |
+ // The map of all opened sessions (excluding mMediaCryptoSession) to their mime types. |
+ private HashMap<ByteBuffer, String> mSessionIds; |
// The queue of all pending createSession() data. |
private ArrayDeque<PendingCreateSessionData> mPendingCreateSessionDataQueue; |
@@ -95,18 +102,14 @@ public class MediaDrmBridge { |
* This class contains data needed to call createSession(). |
*/ |
private static class PendingCreateSessionData { |
- private final int mSessionId; |
private final byte[] mInitData; |
private final String mMimeType; |
+ private final long mPromiseId; |
- private PendingCreateSessionData(int sessionId, byte[] initData, String mimeType) { |
- mSessionId = sessionId; |
+ private PendingCreateSessionData(byte[] initData, String mimeType, long promiseId) { |
mInitData = initData; |
mMimeType = mimeType; |
- } |
- |
- private int sessionId() { |
- return mSessionId; |
+ mPromiseId = promiseId; |
} |
private byte[] initData() { |
@@ -116,6 +119,10 @@ public class MediaDrmBridge { |
private String mimeType() { |
return mMimeType; |
} |
+ |
+ private long promiseId() { |
+ return mPromiseId; |
+ } |
} |
private static UUID getUUIDFromBytes(byte[] data) { |
@@ -134,18 +141,16 @@ public class MediaDrmBridge { |
} |
/** |
- * Gets session associated with the sessionId. |
- * |
- * @return session if sessionId maps a valid opened session. Returns null |
- * otherwise. |
+ * Convert byte array to hex string for logging. |
+ * This is modified from BytesToHexString() in url/url_canon_unittest.cc. |
*/ |
- private ByteBuffer getSession(int sessionId) { |
- for (ByteBuffer session : mSessionIds.keySet()) { |
- if (mSessionIds.get(session) == sessionId) { |
- return session; |
- } |
+ private static String bytesToHexString(byte[] bytes) { |
+ StringBuffer hexString = new StringBuffer(); |
+ for (int i = 0; i < bytes.length; ++i) { |
+ hexString.append(HEX_CHAR_LOOKUP[bytes[i] >>> 4]); |
+ hexString.append(HEX_CHAR_LOOKUP[bytes[i] & 0xf]); |
} |
- return null; |
+ return hexString.toString(); |
} |
private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge) |
@@ -154,8 +159,7 @@ public class MediaDrmBridge { |
mMediaDrm = new MediaDrm(schemeUUID); |
mNativeMediaDrmBridge = nativeMediaDrmBridge; |
mHandler = new Handler(); |
- mSessionIds = new HashMap<ByteBuffer, Integer>(); |
- mSessionMimeTypes = new HashMap<ByteBuffer, String>(); |
+ mSessionIds = new HashMap<ByteBuffer, String>(); |
mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData>(); |
mResetDeviceCredentialsPending = false; |
mProvisioningPending = false; |
@@ -190,15 +194,13 @@ public class MediaDrmBridge { |
Log.e(TAG, "Cannot create MediaCrypto Session."); |
return false; |
} |
- Log.d(TAG, "MediaCrypto Session created: " + mMediaCryptoSession); |
+ Log.d(TAG, "MediaCrypto Session created: " + bytesToHexString(mMediaCryptoSession)); |
// Create MediaCrypto object. |
try { |
if (MediaCrypto.isCryptoSchemeSupported(mSchemeUUID)) { |
- final byte[] mediaCryptoSession = mMediaCryptoSession.array(); |
- mMediaCrypto = new MediaCrypto(mSchemeUUID, mediaCryptoSession); |
+ mMediaCrypto = new MediaCrypto(mSchemeUUID, mMediaCryptoSession); |
Log.d(TAG, "MediaCrypto successfully created!"); |
- mSessionIds.put(mMediaCryptoSession, INVALID_SESSION_ID); |
// Notify the native code that MediaCrypto is ready. |
nativeOnMediaCryptoReady(mNativeMediaDrmBridge); |
return true; |
@@ -214,17 +216,16 @@ public class MediaDrmBridge { |
} |
/** |
- * Open a new session.. |
+ * Open a new session. |
* |
- * @return the session opened. Returns null if unexpected error happened. |
+ * @return ID of the session opened. Returns null if unexpected error happened. |
*/ |
- private ByteBuffer openSession() throws android.media.NotProvisionedException { |
+ private byte[] openSession() throws android.media.NotProvisionedException { |
assert mMediaDrm != null; |
try { |
- byte[] session = mMediaDrm.openSession(); |
- // ByteBuffer.wrap() is backed by the byte[]. Make a clone here in |
- // case the underlying byte[] is modified. |
- return ByteBuffer.wrap(session.clone()); |
+ byte[] sessionId = mMediaDrm.openSession(); |
+ // Make a clone here in case the underlying byte[] is modified. |
+ return sessionId.clone(); |
} catch (java.lang.RuntimeException e) { // TODO(xhwang): Drop this? |
Log.e(TAG, "Cannot open a new session", e); |
release(); |
@@ -242,16 +243,6 @@ public class MediaDrmBridge { |
} |
/** |
- * Close a session. |
- * |
- * @param session to be closed. |
- */ |
- private void closeSession(ByteBuffer session) { |
- assert mMediaDrm != null; |
- mMediaDrm.closeSession(session.array()); |
- } |
- |
- /** |
* Check whether the crypto scheme is supported for the given container. |
* If |containerMimeType| is an empty string, we just return whether |
* the crypto scheme is supported. |
@@ -274,7 +265,6 @@ public class MediaDrmBridge { |
* Create a new MediaDrmBridge from the crypto scheme UUID. |
* |
* @param schemeUUID Crypto scheme UUID. |
- * @param securityLevel Security level to be used. |
* @param nativeMediaDrmBridge Native object of this class. |
*/ |
@CalledByNative |
@@ -303,6 +293,9 @@ public class MediaDrmBridge { |
* Set the security level that the MediaDrm object uses. |
* This function should be called right after we construct MediaDrmBridge |
* and before we make any other calls. |
+ * |
+ * @param securityLevel Security level to be set. |
+ * @return whether the security level was successfully set. |
*/ |
@CalledByNative |
private boolean setSecurityLevel(String securityLevel) { |
@@ -359,16 +352,17 @@ public class MediaDrmBridge { |
// Do not reset mHandler and mNativeMediaDrmBridge so that we can still |
// post KeyError back to native code. |
+ for (PendingCreateSessionData data : mPendingCreateSessionDataQueue) { |
+ onPromiseRejected(data.promiseId(), "Create session aborted."); |
+ } |
mPendingCreateSessionDataQueue.clear(); |
mPendingCreateSessionDataQueue = null; |
- for (ByteBuffer session : mSessionIds.keySet()) { |
- closeSession(session); |
+ for (ByteBuffer sessionId : mSessionIds.keySet()) { |
+ mMediaDrm.closeSession(sessionId.array()); |
} |
mSessionIds.clear(); |
mSessionIds = null; |
- mSessionMimeTypes.clear(); |
- mSessionMimeTypes = null; |
// This session was closed in the "for" loop above. |
mMediaCryptoSession = null; |
@@ -387,13 +381,13 @@ public class MediaDrmBridge { |
/** |
* Get a key request. |
* |
- * @param session Session on which we need to get the key request. |
+ * @param sessionId ID of session on which we need to get the key request. |
* @param data Data needed to get the key request. |
* @param mime Mime type to get the key request. |
* |
* @return the key request. |
*/ |
- private MediaDrm.KeyRequest getKeyRequest(ByteBuffer session, byte[] data, String mime) |
+ private MediaDrm.KeyRequest getKeyRequest(byte[] sessionId, byte[] data, String mime) |
throws android.media.NotProvisionedException { |
assert mMediaDrm != null; |
assert mMediaCrypto != null; |
@@ -401,7 +395,7 @@ public class MediaDrmBridge { |
HashMap<String, String> optionalParameters = new HashMap<String, String>(); |
MediaDrm.KeyRequest request = mMediaDrm.getKeyRequest( |
- session.array(), data, mime, MediaDrm.KEY_TYPE_STREAMING, optionalParameters); |
+ sessionId, data, mime, MediaDrm.KEY_TYPE_STREAMING, optionalParameters); |
String result = (request != null) ? "successed" : "failed"; |
Log.d(TAG, "getKeyRequest " + result + "!"); |
return request; |
@@ -410,11 +404,15 @@ public class MediaDrmBridge { |
/** |
* Save data to |mPendingCreateSessionDataQueue| so that we can resume the |
* createSession() call later. |
+ * |
+ * @param initData Data needed to generate the key request. |
+ * @param mime Mime type. |
+ * @param promiseId Promise ID for the createSession() call. |
*/ |
- private void savePendingCreateSessionData(int sessionId, byte[] initData, String mime) { |
+ private void savePendingCreateSessionData(byte[] initData, String mime, long promiseId) { |
Log.d(TAG, "savePendingCreateSessionData()"); |
mPendingCreateSessionDataQueue.offer( |
- new PendingCreateSessionData(sessionId, initData, mime)); |
+ new PendingCreateSessionData(initData, mime, promiseId)); |
} |
/** |
@@ -430,10 +428,10 @@ public class MediaDrmBridge { |
while (mMediaDrm != null && !mProvisioningPending |
&& !mPendingCreateSessionDataQueue.isEmpty()) { |
PendingCreateSessionData pendingData = mPendingCreateSessionDataQueue.poll(); |
- int sessionId = pendingData.sessionId(); |
byte[] initData = pendingData.initData(); |
String mime = pendingData.mimeType(); |
- createSession(sessionId, initData, mime); |
+ long promiseId = pendingData.promiseId(); |
+ createSession(initData, mime, promiseId); |
} |
} |
@@ -450,14 +448,14 @@ public class MediaDrmBridge { |
} |
/** |
- * Create a session with |sessionId|, |initData| and |mime|. |
+ * Create a session, and generate a request with |initData| and |mime|. |
* |
- * @param sessionId ID for the session to be created. |
* @param initData Data needed to generate the key request. |
* @param mime Mime type. |
+ * @param promiseId Promise ID for this call. |
*/ |
@CalledByNative |
- private void createSession(int sessionId, byte[] initData, String mime) { |
+ private void createSession(byte[] initData, String mime, long promiseId) { |
Log.d(TAG, "createSession()"); |
if (mMediaDrm == null) { |
Log.e(TAG, "createSession() called when MediaDrm is null."); |
@@ -466,136 +464,130 @@ public class MediaDrmBridge { |
if (mProvisioningPending) { |
assert mMediaCrypto == null; |
- savePendingCreateSessionData(sessionId, initData, mime); |
+ savePendingCreateSessionData(initData, mime, promiseId); |
return; |
} |
boolean newSessionOpened = false; |
- ByteBuffer session = null; |
+ byte[] sessionId = null; |
try { |
// Create MediaCrypto if necessary. |
if (mMediaCrypto == null && !createMediaCrypto()) { |
- onSessionError(sessionId); |
+ onPromiseRejected(promiseId, "MediaCrypto creation failed."); |
return; |
} |
+ assert mMediaCryptoSession != null; |
assert mMediaCrypto != null; |
- assert mSessionIds.containsKey(mMediaCryptoSession); |
- session = openSession(); |
- if (session == null) { |
- Log.e(TAG, "Cannot open session in createSession()."); |
- onSessionError(sessionId); |
+ sessionId = openSession(); |
+ if (sessionId == null) { |
+ onPromiseRejected(promiseId, "Open session failed."); |
return; |
} |
newSessionOpened = true; |
- assert !mSessionIds.containsKey(session); |
+ assert !sessionExists(sessionId); |
MediaDrm.KeyRequest request = null; |
- request = getKeyRequest(session, initData, mime); |
+ request = getKeyRequest(sessionId, initData, mime); |
if (request == null) { |
- if (newSessionOpened) { |
- closeSession(session); |
- } |
- onSessionError(sessionId); |
+ mMediaDrm.closeSession(sessionId); |
+ onPromiseRejected(promiseId, "Generate request failed."); |
return; |
} |
- onSessionCreated(sessionId, getWebSessionId(session)); |
+ // Success! |
+ Log.d(TAG, "createSession(): Session (" + bytesToHexString(sessionId) + ") created."); |
+ onPromiseResolvedWithSession(promiseId, sessionId); |
onSessionMessage(sessionId, request); |
- if (newSessionOpened) { |
- Log.d(TAG, "createSession(): Session " + getWebSessionId(session) |
- + " (" + sessionId + ") created."); |
- } |
- |
- mSessionIds.put(session, sessionId); |
- mSessionMimeTypes.put(session, mime); |
+ mSessionIds.put(ByteBuffer.wrap(sessionId), mime); |
} catch (android.media.NotProvisionedException e) { |
Log.e(TAG, "Device not provisioned", e); |
if (newSessionOpened) { |
- closeSession(session); |
+ mMediaDrm.closeSession(sessionId); |
} |
- savePendingCreateSessionData(sessionId, initData, mime); |
+ savePendingCreateSessionData(initData, mime, promiseId); |
startProvisioning(); |
} |
} |
/** |
- * Returns whether |sessionId| is a valid key session, excluding the media |
+ * Check whether |sessionId| is an existing session ID, excluding the media |
* crypto session. |
* |
* @param sessionId Crypto session Id. |
+ * @return true if |sessionId| exists, false otherwise. |
*/ |
- private boolean sessionExists(ByteBuffer session) { |
+ private boolean sessionExists(byte[] sessionId) { |
if (mMediaCryptoSession == null) { |
assert mSessionIds.isEmpty(); |
Log.e(TAG, "Session doesn't exist because media crypto session is not created."); |
return false; |
} |
- assert mSessionIds.containsKey(mMediaCryptoSession); |
- return !session.equals(mMediaCryptoSession) && mSessionIds.containsKey(session); |
+ return !Arrays.equals(sessionId, mMediaCryptoSession) |
+ && mSessionIds.containsKey(ByteBuffer.wrap(sessionId)); |
} |
/** |
- * Cancel a key request for a session Id. |
+ * Close a session that was previously created by createSession(). |
* |
- * @param sessionId Reference ID of session to be released. |
+ * @param sessionId ID of session to be closed. |
+ * @param promiseId Promise ID of this call. |
*/ |
@CalledByNative |
- private void releaseSession(int sessionId) { |
- Log.d(TAG, "releaseSession(): " + sessionId); |
+ private void closeSession(byte[] sessionId, long promiseId) { |
+ Log.d(TAG, "closeSession()"); |
if (mMediaDrm == null) { |
- Log.e(TAG, "releaseSession() called when MediaDrm is null."); |
+ onPromiseRejected(promiseId, "closeSession() called when MediaDrm is null."); |
return; |
} |
- ByteBuffer session = getSession(sessionId); |
- if (session == null) { |
- Log.e(TAG, "Invalid sessionId in releaseSession."); |
- onSessionError(sessionId); |
+ if (!sessionExists(sessionId)) { |
+ onPromiseRejected(promiseId, |
+ "Invalid sessionId in closeSession(): " + bytesToHexString(sessionId)); |
return; |
} |
- mMediaDrm.removeKeys(session.array()); |
- |
- Log.d(TAG, "Session " + sessionId + "closed."); |
- closeSession(session); |
- mSessionIds.remove(session); |
- onSessionClosed(sessionId); |
+ mMediaDrm.removeKeys(sessionId); |
+ mMediaDrm.closeSession(sessionId); |
+ mSessionIds.remove(ByteBuffer.wrap(sessionId)); |
+ onPromiseResolved(promiseId); |
+ Log.d(TAG, "Session " + bytesToHexString(sessionId) + "closed."); |
gunsch
2015/01/22 05:41:15
Should onSessionClosed have been called here? Look
xhwang
2015/01/22 17:42:14
Good question.
For unprefixed EME, a session can
gunsch
2015/01/22 17:47:01
Thanks for the details. So to confirm my understan
xhwang
2015/01/22 17:48:44
This is a perfect summarize :)
ddorwin
2015/01/22 17:54:31
It is not a response to close session (we have pro
|
} |
/** |
- * Add a key for a session Id. |
+ * Update a session with response. |
* |
* @param sessionId Reference ID of session to be updated. |
- * @param key Response data from the server. |
+ * @param response Response data from the server. |
+ * @param promiseId Promise ID of this call. |
*/ |
@CalledByNative |
- private void updateSession(int sessionId, byte[] key) { |
- Log.d(TAG, "updateSession(): " + sessionId); |
+ private void updateSession(byte[] sessionId, byte[] response, long promiseId) { |
+ Log.d(TAG, "updateSession()"); |
if (mMediaDrm == null) { |
- Log.e(TAG, "updateSession() called when MediaDrm is null."); |
+ onPromiseRejected(promiseId, "closeSession() called when MediaDrm is null."); |
return; |
} |
- // TODO(xhwang): We should be able to DCHECK this when WD EME is implemented. |
- ByteBuffer session = getSession(sessionId); |
- if (!sessionExists(session)) { |
- Log.e(TAG, "Invalid session in updateSession."); |
- onSessionError(sessionId); |
+ // TODO(xhwang): DCHECK this when prefixed EME is deprecated. |
+ if (!sessionExists(sessionId)) { |
+ onPromiseRejected( |
+ promiseId, "Invalid session in updateSession: " + bytesToHexString(sessionId)); |
return; |
} |
try { |
try { |
- mMediaDrm.provideKeyResponse(session.array(), key); |
+ mMediaDrm.provideKeyResponse(sessionId, response); |
} catch (java.lang.IllegalStateException e) { |
// This is not really an exception. Some error code are incorrectly |
// reported as an exception. |
// TODO(qinmin): remove this exception catch when b/10495563 is fixed. |
Log.e(TAG, "Exception intentionally caught when calling provideKeyResponse()", e); |
} |
- onSessionReady(sessionId); |
- Log.d(TAG, "Key successfully added for session " + sessionId); |
+ Log.d(TAG, "Key successfully added for session " + bytesToHexString(sessionId)); |
+ onPromiseResolved(promiseId); |
+ onSessionKeysChange(sessionId, true, KEY_STATUS_USABLE); |
return; |
} catch (android.media.NotProvisionedException e) { |
// TODO(xhwang): Should we handle this? |
@@ -603,7 +595,7 @@ public class MediaDrmBridge { |
} catch (android.media.DeniedByServerException e) { |
Log.e(TAG, "failed to provide key response", e); |
} |
- onSessionError(sessionId); |
+ onPromiseRejected(promiseId, "Update session failed."); |
release(); |
} |
@@ -658,6 +650,7 @@ public class MediaDrmBridge { |
/** |
* Provide the provisioning response to MediaDrm. |
+ * |
* @returns false if the response is invalid or on error, true otherwise. |
*/ |
boolean provideProvisionResponse(byte[] response) { |
@@ -677,35 +670,47 @@ public class MediaDrmBridge { |
return false; |
} |
- private void onSessionCreated(final int sessionId, final String webSessionId) { |
+ // Helper functions to post native calls to prevent reentrancy. |
+ |
+ private void onPromiseResolved(final long promiseId) { |
mHandler.post(new Runnable(){ |
@Override |
public void run() { |
- nativeOnSessionCreated(mNativeMediaDrmBridge, sessionId, webSessionId); |
+ nativeOnPromiseResolved(mNativeMediaDrmBridge, promiseId); |
} |
}); |
} |
- private void onSessionMessage(final int sessionId, final MediaDrm.KeyRequest request) { |
+ private void onPromiseResolvedWithSession(final long promiseId, final byte[] sessionId) { |
mHandler.post(new Runnable(){ |
@Override |
public void run() { |
- nativeOnSessionMessage(mNativeMediaDrmBridge, sessionId, |
- request.getData(), request.getDefaultUrl()); |
+ nativeOnPromiseResolvedWithSession(mNativeMediaDrmBridge, promiseId, sessionId); |
} |
}); |
} |
- private void onSessionReady(final int sessionId) { |
+ private void onPromiseRejected(final long promiseId, final String errorMessage) { |
+ Log.e(TAG, "onPromiseRejected: " + errorMessage); |
mHandler.post(new Runnable() { |
@Override |
public void run() { |
- nativeOnSessionReady(mNativeMediaDrmBridge, sessionId); |
+ nativeOnPromiseRejected(mNativeMediaDrmBridge, promiseId, errorMessage); |
} |
}); |
} |
- private void onSessionClosed(final int sessionId) { |
+ private void onSessionMessage(final byte[] sessionId, final MediaDrm.KeyRequest request) { |
+ mHandler.post(new Runnable() { |
+ @Override |
+ public void run() { |
+ nativeOnSessionMessage(mNativeMediaDrmBridge, sessionId, request.getData(), |
+ request.getDefaultUrl()); |
+ } |
+ }); |
+ } |
+ |
+ private void onSessionClosed(final byte[] sessionId) { |
mHandler.post(new Runnable() { |
@Override |
public void run() { |
@@ -714,44 +719,37 @@ public class MediaDrmBridge { |
}); |
} |
- private void onSessionError(final int sessionId) { |
- // TODO(qinmin): pass the error code to native. |
+ private void onSessionKeysChange( |
+ final byte[] sessionId, final boolean hasAdditionalUsableKey, final int keyStatus) { |
mHandler.post(new Runnable() { |
@Override |
public void run() { |
- nativeOnSessionError(mNativeMediaDrmBridge, sessionId); |
+ nativeOnSessionKeysChange( |
+ mNativeMediaDrmBridge, sessionId, hasAdditionalUsableKey, keyStatus); |
} |
}); |
} |
- private String getWebSessionId(ByteBuffer session) { |
- String webSessionId = null; |
- try { |
- webSessionId = new String(session.array(), "UTF-8"); |
- } catch (java.io.UnsupportedEncodingException e) { |
- Log.e(TAG, "getWebSessionId failed", e); |
- } catch (java.lang.NullPointerException e) { |
- Log.e(TAG, "getWebSessionId failed", e); |
- } |
- return webSessionId; |
+ private void onLegacySessionError(final byte[] sessionId, final String errorMessage) { |
+ Log.e(TAG, "onLegacySessionError: " + errorMessage); |
+ mHandler.post(new Runnable() { |
+ @Override |
+ public void run() { |
+ nativeOnLegacySessionError(mNativeMediaDrmBridge, sessionId, errorMessage); |
+ } |
+ }); |
} |
private class MediaDrmListener implements MediaDrm.OnEventListener { |
@Override |
public void onEvent( |
- MediaDrm mediaDrm, byte[] sessionArray, int event, int extra, byte[] data) { |
- if (sessionArray == null) { |
+ MediaDrm mediaDrm, byte[] sessionId, int event, int extra, byte[] data) { |
+ if (sessionId == null) { |
Log.e(TAG, "MediaDrmListener: Null session."); |
return; |
} |
- ByteBuffer session = ByteBuffer.wrap(sessionArray); |
- if (!sessionExists(session)) { |
- Log.e(TAG, "MediaDrmListener: Invalid session."); |
- return; |
- } |
- Integer sessionId = mSessionIds.get(session); |
- if (sessionId == null || sessionId == INVALID_SESSION_ID) { |
- Log.e(TAG, "MediaDrmListener: Invalid session ID."); |
+ if (!sessionExists(sessionId)) { |
+ Log.e(TAG, "MediaDrmListener: Invalid session " + bytesToHexString(sessionId)); |
return; |
} |
switch(event) { |
@@ -763,10 +761,10 @@ public class MediaDrmBridge { |
if (mProvisioningPending) { |
return; |
} |
- String mime = mSessionMimeTypes.get(session); |
+ String mime = mSessionIds.get(ByteBuffer.wrap(sessionId)); |
MediaDrm.KeyRequest request = null; |
try { |
- request = getKeyRequest(session, data, mime); |
+ request = getKeyRequest(sessionId, data, mime); |
} catch (android.media.NotProvisionedException e) { |
Log.e(TAG, "Device not provisioned", e); |
startProvisioning(); |
@@ -775,12 +773,15 @@ public class MediaDrmBridge { |
if (request != null) { |
onSessionMessage(sessionId, request); |
} else { |
- onSessionError(sessionId); |
+ onLegacySessionError(sessionId, |
+ "MediaDrm EVENT_KEY_REQUIRED: Failed to generate request."); |
+ onSessionKeysChange(sessionId, false, KEY_STATUS_INTERNAL_ERROR); |
} |
break; |
case MediaDrm.EVENT_KEY_EXPIRED: |
Log.d(TAG, "MediaDrm.EVENT_KEY_EXPIRED"); |
- onSessionError(sessionId); |
+ onLegacySessionError(sessionId, "MediaDrm EVENT_KEY_EXPIRED."); |
+ onSessionKeysChange(sessionId, false, KEY_STATUS_EXPIRED); |
break; |
case MediaDrm.EVENT_VENDOR_DEFINED: |
Log.d(TAG, "MediaDrm.EVENT_VENDOR_DEFINED"); |
@@ -860,17 +861,19 @@ public class MediaDrmBridge { |
private native void nativeOnMediaCryptoReady(long nativeMediaDrmBridge); |
- private native void nativeOnSessionCreated(long nativeMediaDrmBridge, int sessionId, |
- String webSessionId); |
- |
- private native void nativeOnSessionMessage(long nativeMediaDrmBridge, int sessionId, |
- byte[] message, String destinationUrl); |
- |
- private native void nativeOnSessionReady(long nativeMediaDrmBridge, int sessionId); |
- |
- private native void nativeOnSessionClosed(long nativeMediaDrmBridge, int sessionId); |
- |
- private native void nativeOnSessionError(long nativeMediaDrmBridge, int sessionId); |
+ private native void nativeOnPromiseResolved(long nativeMediaDrmBridge, long promiseId); |
+ private native void nativeOnPromiseResolvedWithSession( |
+ long nativeMediaDrmBridge, long promiseId, byte[] sessionId); |
+ private native void nativeOnPromiseRejected( |
+ long nativeMediaDrmBridge, long promiseId, String errorMessage); |
+ |
+ private native void nativeOnSessionMessage( |
+ long nativeMediaDrmBridge, byte[] sessionId, byte[] message, String destinationUrl); |
+ private native void nativeOnSessionClosed(long nativeMediaDrmBridge, byte[] sessionId); |
+ private native void nativeOnSessionKeysChange(long nativeMediaDrmBridge, byte[] sessionId, |
+ boolean hasAdditionalUsableKey, int keyStatus); |
+ private native void nativeOnLegacySessionError( |
+ long nativeMediaDrmBridge, byte[] sessionId, String errorMessage); |
private native void nativeOnResetDeviceCredentialsCompleted( |
long nativeMediaDrmBridge, boolean success); |