Chromium Code Reviews| 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..cc6fed84f970db87b5767ff4a4171f07b9edd237 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. |
| + * Converts byte array to hex string for logging. |
|
qinmin
2015/01/15 18:17:25
nit: s/Converts/Convert/
xhwang
2015/01/15 19:03:44
Done.
|
| + * 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. |
| @@ -359,16 +350,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; |
| @@ -393,7 +385,7 @@ public class MediaDrmBridge { |
| * |
| * @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 +393,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; |
| @@ -411,10 +403,10 @@ public class MediaDrmBridge { |
| * Save data to |mPendingCreateSessionDataQueue| so that we can resume the |
| * createSession() call later. |
| */ |
|
qinmin
2015/01/15 18:17:25
nit: @param?
xhwang
2015/01/15 19:03:44
Done.
|
| - 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 +422,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 +442,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 +458,129 @@ 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 |
| + * Return whether |sessionId| is a valid key session, excluding the media |
| * crypto session. |
| * |
| * @param sessionId Crypto session Id. |
|
qinmin
2015/01/15 18:17:25
nit @return?
xhwang
2015/01/15 19:03:44
Done.
|
| */ |
| - 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."); |
| } |
| /** |
| - * 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 +588,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(); |
| } |
| @@ -677,35 +662,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 +711,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 +753,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 +765,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 +853,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); |