Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: media/base/android/java/src/org/chromium/media/MediaDrmBridge.java

Issue 850183002: media: Support unprefixed EME API on Android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: jrummell's comments addressed Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.media; 5 package org.chromium.media;
6 6
7 import android.media.MediaCrypto; 7 import android.media.MediaCrypto;
8 import android.media.MediaDrm; 8 import android.media.MediaDrm;
9 import android.os.AsyncTask; 9 import android.os.AsyncTask;
10 import android.os.Handler; 10 import android.os.Handler;
11 import android.util.Log; 11 import android.util.Log;
12 12
13 import org.apache.http.HttpResponse; 13 import org.apache.http.HttpResponse;
14 import org.apache.http.client.ClientProtocolException; 14 import org.apache.http.client.ClientProtocolException;
15 import org.apache.http.client.HttpClient; 15 import org.apache.http.client.HttpClient;
16 import org.apache.http.client.methods.HttpPost; 16 import org.apache.http.client.methods.HttpPost;
17 import org.apache.http.impl.client.DefaultHttpClient; 17 import org.apache.http.impl.client.DefaultHttpClient;
18 import org.apache.http.util.EntityUtils; 18 import org.apache.http.util.EntityUtils;
19 import org.chromium.base.CalledByNative; 19 import org.chromium.base.CalledByNative;
20 import org.chromium.base.JNINamespace; 20 import org.chromium.base.JNINamespace;
21 21
22 import java.io.IOException; 22 import java.io.IOException;
23 import java.nio.ByteBuffer; 23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder; 24 import java.nio.ByteOrder;
25 import java.util.ArrayDeque; 25 import java.util.ArrayDeque;
26 import java.util.Arrays;
26 import java.util.HashMap; 27 import java.util.HashMap;
27 import java.util.UUID; 28 import java.util.UUID;
28 29
29 /** 30 /**
30 * A wrapper of the android MediaDrm class. Each MediaDrmBridge manages multiple 31 * A wrapper of the android MediaDrm class. Each MediaDrmBridge manages multiple
31 * sessions for a single MediaSourcePlayer. 32 * sessions for a single MediaSourcePlayer.
32 */ 33 */
33 @JNINamespace("media") 34 @JNINamespace("media")
34 public class MediaDrmBridge { 35 public class MediaDrmBridge {
35 // Implementation Notes: 36 // Implementation Notes:
(...skipping 17 matching lines...) Expand all
53 // release() immediately after the error happens (e.g. after mMediaDrm) 54 // release() immediately after the error happens (e.g. after mMediaDrm)
54 // calls. Indirect calls should not call release() again to avoid 55 // calls. Indirect calls should not call release() again to avoid
55 // duplication (even though it doesn't hurt to call release() twice). 56 // duplication (even though it doesn't hurt to call release() twice).
56 57
57 private static final String TAG = "MediaDrmBridge"; 58 private static final String TAG = "MediaDrmBridge";
58 private static final String SECURITY_LEVEL = "securityLevel"; 59 private static final String SECURITY_LEVEL = "securityLevel";
59 private static final String PRIVACY_MODE = "privacyMode"; 60 private static final String PRIVACY_MODE = "privacyMode";
60 private static final String SESSION_SHARING = "sessionSharing"; 61 private static final String SESSION_SHARING = "sessionSharing";
61 private static final String ENABLE = "enable"; 62 private static final String ENABLE = "enable";
62 private static final int INVALID_SESSION_ID = 0; 63 private static final int INVALID_SESSION_ID = 0;
64 private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray ();
65
66 // KeyStatus for CDM key information. MUST keep this value in sync with
67 // CdmKeyInformation::KeyStatus.
dcheng 2015/01/17 00:08:16 As I recall, there's some way to automatically gen
xhwang 2015/01/17 01:20:40 +qinmin: If there's a way to do this, I'll be happ
68 private static final int KEY_STATUS_USABLE = 0;
69 private static final int KEY_STATUS_INTERNAL_ERROR = 1;
70 private static final int KEY_STATUS_EXPIRED = 2;
71 private static final int KEY_STATUS_OUTPUT_NOT_ALLOWED = 3;
63 72
64 private MediaDrm mMediaDrm; 73 private MediaDrm mMediaDrm;
65 private long mNativeMediaDrmBridge; 74 private long mNativeMediaDrmBridge;
66 private UUID mSchemeUUID; 75 private UUID mSchemeUUID;
67 private Handler mHandler; 76 private Handler mHandler;
68 77
69 // A session only for the purpose of creating a MediaCrypto object. 78 // A session only for the purpose of creating a MediaCrypto object.
70 // This session is opened when createSession() is called for the first 79 // This session is opened when createSession() is called for the first
71 // time. All following createSession() calls will create a new session and 80 // time. All following createSession() calls will create a new session and
72 // use it to call getKeyRequest(). No getKeyRequest() should ever be called 81 // use it to call getKeyRequest(). No getKeyRequest() should ever be called
73 // on |mMediaCryptoSession|. 82 // on |mMediaCryptoSession|.
74 private ByteBuffer mMediaCryptoSession; 83 private byte[] mMediaCryptoSession;
75 private MediaCrypto mMediaCrypto; 84 private MediaCrypto mMediaCrypto;
76 85
77 // The map of all opened sessions to their session reference IDs. 86 // The map of all opened sessions (excluding mMediaCryptoSession) to their m ime types.
78 private HashMap<ByteBuffer, Integer> mSessionIds; 87 private HashMap<ByteBuffer, String> mSessionIds;
79 // The map of all opened sessions to their mime types.
80 private HashMap<ByteBuffer, String> mSessionMimeTypes;
81 88
82 // The queue of all pending createSession() data. 89 // The queue of all pending createSession() data.
83 private ArrayDeque<PendingCreateSessionData> mPendingCreateSessionDataQueue; 90 private ArrayDeque<PendingCreateSessionData> mPendingCreateSessionDataQueue;
84 91
85 private boolean mResetDeviceCredentialsPending; 92 private boolean mResetDeviceCredentialsPending;
86 93
87 // MediaDrmBridge is waiting for provisioning response from the server. 94 // MediaDrmBridge is waiting for provisioning response from the server.
88 // 95 //
89 // Notes about NotProvisionedException: This exception can be thrown in a 96 // Notes about NotProvisionedException: This exception can be thrown in a
90 // lot of cases. To streamline implementation, we do not catch it in private 97 // lot of cases. To streamline implementation, we do not catch it in private
91 // non-native methods and only catch it in public APIs. 98 // non-native methods and only catch it in public APIs.
92 private boolean mProvisioningPending; 99 private boolean mProvisioningPending;
93 100
94 /** 101 /**
95 * This class contains data needed to call createSession(). 102 * This class contains data needed to call createSession().
96 */ 103 */
97 private static class PendingCreateSessionData { 104 private static class PendingCreateSessionData {
98 private final int mSessionId;
99 private final byte[] mInitData; 105 private final byte[] mInitData;
100 private final String mMimeType; 106 private final String mMimeType;
107 private final long mPromiseId;
101 108
102 private PendingCreateSessionData(int sessionId, byte[] initData, String mimeType) { 109 private PendingCreateSessionData(byte[] initData, String mimeType, long promiseId) {
103 mSessionId = sessionId;
104 mInitData = initData; 110 mInitData = initData;
105 mMimeType = mimeType; 111 mMimeType = mimeType;
106 } 112 mPromiseId = promiseId;
107
108 private int sessionId() {
109 return mSessionId;
110 } 113 }
111 114
112 private byte[] initData() { 115 private byte[] initData() {
113 return mInitData; 116 return mInitData;
114 } 117 }
115 118
116 private String mimeType() { 119 private String mimeType() {
117 return mMimeType; 120 return mMimeType;
118 } 121 }
122
123 private long promiseId() {
124 return mPromiseId;
125 }
119 } 126 }
120 127
121 private static UUID getUUIDFromBytes(byte[] data) { 128 private static UUID getUUIDFromBytes(byte[] data) {
122 if (data.length != 16) { 129 if (data.length != 16) {
123 return null; 130 return null;
124 } 131 }
125 long mostSigBits = 0; 132 long mostSigBits = 0;
126 long leastSigBits = 0; 133 long leastSigBits = 0;
127 for (int i = 0; i < 8; i++) { 134 for (int i = 0; i < 8; i++) {
128 mostSigBits = (mostSigBits << 8) | (data[i] & 0xff); 135 mostSigBits = (mostSigBits << 8) | (data[i] & 0xff);
129 } 136 }
130 for (int i = 8; i < 16; i++) { 137 for (int i = 8; i < 16; i++) {
131 leastSigBits = (leastSigBits << 8) | (data[i] & 0xff); 138 leastSigBits = (leastSigBits << 8) | (data[i] & 0xff);
132 } 139 }
133 return new UUID(mostSigBits, leastSigBits); 140 return new UUID(mostSigBits, leastSigBits);
134 } 141 }
135 142
136 /** 143 /**
137 * Gets session associated with the sessionId. 144 * Convert byte array to hex string for logging.
138 * 145 * This is modified from BytesToHexString() in url/url_canon_unittest.cc.
139 * @return session if sessionId maps a valid opened session. Returns null
140 * otherwise.
141 */ 146 */
142 private ByteBuffer getSession(int sessionId) { 147 private static String bytesToHexString(byte[] bytes) {
143 for (ByteBuffer session : mSessionIds.keySet()) { 148 StringBuffer hexString = new StringBuffer();
144 if (mSessionIds.get(session) == sessionId) { 149 for (int i = 0; i < bytes.length; ++i) {
145 return session; 150 hexString.append(HEX_CHAR_LOOKUP[bytes[i] >>> 4]);
146 } 151 hexString.append(HEX_CHAR_LOOKUP[bytes[i] & 0xf]);
147 } 152 }
148 return null; 153 return hexString.toString();
149 } 154 }
150 155
151 private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge) 156 private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge)
152 throws android.media.UnsupportedSchemeException { 157 throws android.media.UnsupportedSchemeException {
153 mSchemeUUID = schemeUUID; 158 mSchemeUUID = schemeUUID;
154 mMediaDrm = new MediaDrm(schemeUUID); 159 mMediaDrm = new MediaDrm(schemeUUID);
155 mNativeMediaDrmBridge = nativeMediaDrmBridge; 160 mNativeMediaDrmBridge = nativeMediaDrmBridge;
156 mHandler = new Handler(); 161 mHandler = new Handler();
157 mSessionIds = new HashMap<ByteBuffer, Integer>(); 162 mSessionIds = new HashMap<ByteBuffer, String>();
158 mSessionMimeTypes = new HashMap<ByteBuffer, String>();
159 mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData >(); 163 mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData >();
160 mResetDeviceCredentialsPending = false; 164 mResetDeviceCredentialsPending = false;
161 mProvisioningPending = false; 165 mProvisioningPending = false;
162 166
163 mMediaDrm.setOnEventListener(new MediaDrmListener()); 167 mMediaDrm.setOnEventListener(new MediaDrmListener());
164 mMediaDrm.setPropertyString(PRIVACY_MODE, ENABLE); 168 mMediaDrm.setPropertyString(PRIVACY_MODE, ENABLE);
165 mMediaDrm.setPropertyString(SESSION_SHARING, ENABLE); 169 mMediaDrm.setPropertyString(SESSION_SHARING, ENABLE);
166 170
167 // We could open a MediaCrypto session here to support faster start of 171 // We could open a MediaCrypto session here to support faster start of
168 // clear lead (no need to wait for createSession()). But on 172 // clear lead (no need to wait for createSession()). But on
(...skipping 14 matching lines...) Expand all
183 assert !mProvisioningPending; 187 assert !mProvisioningPending;
184 assert mMediaCryptoSession == null; 188 assert mMediaCryptoSession == null;
185 assert mMediaCrypto == null; 189 assert mMediaCrypto == null;
186 190
187 // Open media crypto session. 191 // Open media crypto session.
188 mMediaCryptoSession = openSession(); 192 mMediaCryptoSession = openSession();
189 if (mMediaCryptoSession == null) { 193 if (mMediaCryptoSession == null) {
190 Log.e(TAG, "Cannot create MediaCrypto Session."); 194 Log.e(TAG, "Cannot create MediaCrypto Session.");
191 return false; 195 return false;
192 } 196 }
193 Log.d(TAG, "MediaCrypto Session created: " + mMediaCryptoSession); 197 Log.d(TAG, "MediaCrypto Session created: " + bytesToHexString(mMediaCryp toSession));
194 198
195 // Create MediaCrypto object. 199 // Create MediaCrypto object.
196 try { 200 try {
197 if (MediaCrypto.isCryptoSchemeSupported(mSchemeUUID)) { 201 if (MediaCrypto.isCryptoSchemeSupported(mSchemeUUID)) {
198 final byte[] mediaCryptoSession = mMediaCryptoSession.array(); 202 mMediaCrypto = new MediaCrypto(mSchemeUUID, mMediaCryptoSession) ;
199 mMediaCrypto = new MediaCrypto(mSchemeUUID, mediaCryptoSession);
200 Log.d(TAG, "MediaCrypto successfully created!"); 203 Log.d(TAG, "MediaCrypto successfully created!");
201 mSessionIds.put(mMediaCryptoSession, INVALID_SESSION_ID);
202 // Notify the native code that MediaCrypto is ready. 204 // Notify the native code that MediaCrypto is ready.
203 nativeOnMediaCryptoReady(mNativeMediaDrmBridge); 205 nativeOnMediaCryptoReady(mNativeMediaDrmBridge);
204 return true; 206 return true;
205 } else { 207 } else {
206 Log.e(TAG, "Cannot create MediaCrypto for unsupported scheme."); 208 Log.e(TAG, "Cannot create MediaCrypto for unsupported scheme.");
207 } 209 }
208 } catch (android.media.MediaCryptoException e) { 210 } catch (android.media.MediaCryptoException e) {
209 Log.e(TAG, "Cannot create MediaCrypto", e); 211 Log.e(TAG, "Cannot create MediaCrypto", e);
210 } 212 }
211 213
212 release(); 214 release();
213 return false; 215 return false;
214 } 216 }
215 217
216 /** 218 /**
217 * Open a new session.. 219 * Open a new session.
218 * 220 *
219 * @return the session opened. Returns null if unexpected error happened. 221 * @return ID of the session opened. Returns null if unexpected error happen ed.
220 */ 222 */
221 private ByteBuffer openSession() throws android.media.NotProvisionedExceptio n { 223 private byte[] openSession() throws android.media.NotProvisionedException {
222 assert mMediaDrm != null; 224 assert mMediaDrm != null;
223 try { 225 try {
224 byte[] session = mMediaDrm.openSession(); 226 byte[] sessionId = mMediaDrm.openSession();
225 // ByteBuffer.wrap() is backed by the byte[]. Make a clone here in 227 // Make a clone here in case the underlying byte[] is modified.
226 // case the underlying byte[] is modified. 228 return sessionId.clone();
227 return ByteBuffer.wrap(session.clone());
228 } catch (java.lang.RuntimeException e) { // TODO(xhwang): Drop this? 229 } catch (java.lang.RuntimeException e) { // TODO(xhwang): Drop this?
229 Log.e(TAG, "Cannot open a new session", e); 230 Log.e(TAG, "Cannot open a new session", e);
230 release(); 231 release();
231 return null; 232 return null;
232 } catch (android.media.NotProvisionedException e) { 233 } catch (android.media.NotProvisionedException e) {
233 // Throw NotProvisionedException so that we can startProvisioning(). 234 // Throw NotProvisionedException so that we can startProvisioning().
234 throw e; 235 throw e;
235 } catch (android.media.MediaDrmException e) { 236 } catch (android.media.MediaDrmException e) {
236 // Other MediaDrmExceptions (e.g. ResourceBusyException) are not 237 // Other MediaDrmExceptions (e.g. ResourceBusyException) are not
237 // recoverable. 238 // recoverable.
238 Log.e(TAG, "Cannot open a new session", e); 239 Log.e(TAG, "Cannot open a new session", e);
239 release(); 240 release();
240 return null; 241 return null;
241 } 242 }
242 } 243 }
243 244
244 /** 245 /**
245 * Close a session.
246 *
247 * @param session to be closed.
248 */
249 private void closeSession(ByteBuffer session) {
250 assert mMediaDrm != null;
251 mMediaDrm.closeSession(session.array());
252 }
253
254 /**
255 * Check whether the crypto scheme is supported for the given container. 246 * Check whether the crypto scheme is supported for the given container.
256 * If |containerMimeType| is an empty string, we just return whether 247 * If |containerMimeType| is an empty string, we just return whether
257 * the crypto scheme is supported. 248 * the crypto scheme is supported.
258 * 249 *
259 * @return true if the container and the crypto scheme is supported, or 250 * @return true if the container and the crypto scheme is supported, or
260 * false otherwise. 251 * false otherwise.
261 */ 252 */
262 @CalledByNative 253 @CalledByNative
263 private static boolean isCryptoSchemeSupported(byte[] schemeUUID, String con tainerMimeType) { 254 private static boolean isCryptoSchemeSupported(byte[] schemeUUID, String con tainerMimeType) {
264 UUID cryptoScheme = getUUIDFromBytes(schemeUUID); 255 UUID cryptoScheme = getUUIDFromBytes(schemeUUID);
265 256
266 if (containerMimeType.isEmpty()) { 257 if (containerMimeType.isEmpty()) {
267 return MediaDrm.isCryptoSchemeSupported(cryptoScheme); 258 return MediaDrm.isCryptoSchemeSupported(cryptoScheme);
268 } 259 }
269 260
270 return MediaDrm.isCryptoSchemeSupported(cryptoScheme, containerMimeType) ; 261 return MediaDrm.isCryptoSchemeSupported(cryptoScheme, containerMimeType) ;
271 } 262 }
272 263
273 /** 264 /**
274 * Create a new MediaDrmBridge from the crypto scheme UUID. 265 * Create a new MediaDrmBridge from the crypto scheme UUID.
275 * 266 *
276 * @param schemeUUID Crypto scheme UUID. 267 * @param schemeUUID Crypto scheme UUID.
277 * @param securityLevel Security level to be used.
278 * @param nativeMediaDrmBridge Native object of this class. 268 * @param nativeMediaDrmBridge Native object of this class.
279 */ 269 */
280 @CalledByNative 270 @CalledByNative
281 private static MediaDrmBridge create(byte[] schemeUUID, long nativeMediaDrmB ridge) { 271 private static MediaDrmBridge create(byte[] schemeUUID, long nativeMediaDrmB ridge) {
282 UUID cryptoScheme = getUUIDFromBytes(schemeUUID); 272 UUID cryptoScheme = getUUIDFromBytes(schemeUUID);
283 if (cryptoScheme == null || !MediaDrm.isCryptoSchemeSupported(cryptoSche me)) { 273 if (cryptoScheme == null || !MediaDrm.isCryptoSchemeSupported(cryptoSche me)) {
284 return null; 274 return null;
285 } 275 }
286 276
287 MediaDrmBridge mediaDrmBridge = null; 277 MediaDrmBridge mediaDrmBridge = null;
288 try { 278 try {
289 mediaDrmBridge = new MediaDrmBridge(cryptoScheme, nativeMediaDrmBrid ge); 279 mediaDrmBridge = new MediaDrmBridge(cryptoScheme, nativeMediaDrmBrid ge);
290 Log.d(TAG, "MediaDrmBridge successfully created."); 280 Log.d(TAG, "MediaDrmBridge successfully created.");
291 } catch (android.media.UnsupportedSchemeException e) { 281 } catch (android.media.UnsupportedSchemeException e) {
292 Log.e(TAG, "Unsupported DRM scheme", e); 282 Log.e(TAG, "Unsupported DRM scheme", e);
293 } catch (java.lang.IllegalArgumentException e) { 283 } catch (java.lang.IllegalArgumentException e) {
294 Log.e(TAG, "Failed to create MediaDrmBridge", e); 284 Log.e(TAG, "Failed to create MediaDrmBridge", e);
295 } catch (java.lang.IllegalStateException e) { 285 } catch (java.lang.IllegalStateException e) {
296 Log.e(TAG, "Failed to create MediaDrmBridge", e); 286 Log.e(TAG, "Failed to create MediaDrmBridge", e);
297 } 287 }
298 288
299 return mediaDrmBridge; 289 return mediaDrmBridge;
300 } 290 }
301 291
302 /** 292 /**
303 * Set the security level that the MediaDrm object uses. 293 * Set the security level that the MediaDrm object uses.
304 * This function should be called right after we construct MediaDrmBridge 294 * This function should be called right after we construct MediaDrmBridge
305 * and before we make any other calls. 295 * and before we make any other calls.
296 *
297 * @param securityLevel Security level to be set.
298 * @return whether the security level was successfully set.
306 */ 299 */
307 @CalledByNative 300 @CalledByNative
308 private boolean setSecurityLevel(String securityLevel) { 301 private boolean setSecurityLevel(String securityLevel) {
309 if (mMediaDrm == null || mMediaCrypto != null) { 302 if (mMediaDrm == null || mMediaCrypto != null) {
310 return false; 303 return false;
311 } 304 }
312 305
313 String currentSecurityLevel = mMediaDrm.getPropertyString(SECURITY_LEVEL ); 306 String currentSecurityLevel = mMediaDrm.getPropertyString(SECURITY_LEVEL );
314 Log.e(TAG, "Security level: current " + currentSecurityLevel + ", new " + securityLevel); 307 Log.e(TAG, "Security level: current " + currentSecurityLevel + ", new " + securityLevel);
315 if (securityLevel.equals(currentSecurityLevel)) { 308 if (securityLevel.equals(currentSecurityLevel)) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 345 }
353 346
354 /** 347 /**
355 * Release the MediaDrmBridge object. 348 * Release the MediaDrmBridge object.
356 */ 349 */
357 @CalledByNative 350 @CalledByNative
358 private void release() { 351 private void release() {
359 // Do not reset mHandler and mNativeMediaDrmBridge so that we can still 352 // Do not reset mHandler and mNativeMediaDrmBridge so that we can still
360 // post KeyError back to native code. 353 // post KeyError back to native code.
361 354
355 for (PendingCreateSessionData data : mPendingCreateSessionDataQueue) {
356 onPromiseRejected(data.promiseId(), "Create session aborted.");
357 }
362 mPendingCreateSessionDataQueue.clear(); 358 mPendingCreateSessionDataQueue.clear();
363 mPendingCreateSessionDataQueue = null; 359 mPendingCreateSessionDataQueue = null;
364 360
365 for (ByteBuffer session : mSessionIds.keySet()) { 361 for (ByteBuffer sessionId : mSessionIds.keySet()) {
366 closeSession(session); 362 mMediaDrm.closeSession(sessionId.array());
367 } 363 }
368 mSessionIds.clear(); 364 mSessionIds.clear();
369 mSessionIds = null; 365 mSessionIds = null;
370 mSessionMimeTypes.clear();
371 mSessionMimeTypes = null;
372 366
373 // This session was closed in the "for" loop above. 367 // This session was closed in the "for" loop above.
374 mMediaCryptoSession = null; 368 mMediaCryptoSession = null;
375 369
376 if (mMediaCrypto != null) { 370 if (mMediaCrypto != null) {
377 mMediaCrypto.release(); 371 mMediaCrypto.release();
378 mMediaCrypto = null; 372 mMediaCrypto = null;
379 } 373 }
380 374
381 if (mMediaDrm != null) { 375 if (mMediaDrm != null) {
382 mMediaDrm.release(); 376 mMediaDrm.release();
383 mMediaDrm = null; 377 mMediaDrm = null;
384 } 378 }
385 } 379 }
386 380
387 /** 381 /**
388 * Get a key request. 382 * Get a key request.
389 * 383 *
390 * @param session Session on which we need to get the key request. 384 * @param sessionId ID of session on which we need to get the key request.
391 * @param data Data needed to get the key request. 385 * @param data Data needed to get the key request.
392 * @param mime Mime type to get the key request. 386 * @param mime Mime type to get the key request.
393 * 387 *
394 * @return the key request. 388 * @return the key request.
395 */ 389 */
396 private MediaDrm.KeyRequest getKeyRequest(ByteBuffer session, byte[] data, S tring mime) 390 private MediaDrm.KeyRequest getKeyRequest(byte[] sessionId, byte[] data, Str ing mime)
397 throws android.media.NotProvisionedException { 391 throws android.media.NotProvisionedException {
398 assert mMediaDrm != null; 392 assert mMediaDrm != null;
399 assert mMediaCrypto != null; 393 assert mMediaCrypto != null;
400 assert !mProvisioningPending; 394 assert !mProvisioningPending;
401 395
402 HashMap<String, String> optionalParameters = new HashMap<String, String> (); 396 HashMap<String, String> optionalParameters = new HashMap<String, String> ();
403 MediaDrm.KeyRequest request = mMediaDrm.getKeyRequest( 397 MediaDrm.KeyRequest request = mMediaDrm.getKeyRequest(
404 session.array(), data, mime, MediaDrm.KEY_TYPE_STREAMING, option alParameters); 398 sessionId, data, mime, MediaDrm.KEY_TYPE_STREAMING, optionalPara meters);
405 String result = (request != null) ? "successed" : "failed"; 399 String result = (request != null) ? "successed" : "failed";
406 Log.d(TAG, "getKeyRequest " + result + "!"); 400 Log.d(TAG, "getKeyRequest " + result + "!");
407 return request; 401 return request;
408 } 402 }
409 403
410 /** 404 /**
411 * Save data to |mPendingCreateSessionDataQueue| so that we can resume the 405 * Save data to |mPendingCreateSessionDataQueue| so that we can resume the
412 * createSession() call later. 406 * createSession() call later.
407 *
408 * @param initData Data needed to generate the key request.
409 * @param mime Mime type.
410 * @param promiseId Promise ID for the createSession() call.
413 */ 411 */
414 private void savePendingCreateSessionData(int sessionId, byte[] initData, St ring mime) { 412 private void savePendingCreateSessionData(byte[] initData, String mime, long promiseId) {
415 Log.d(TAG, "savePendingCreateSessionData()"); 413 Log.d(TAG, "savePendingCreateSessionData()");
416 mPendingCreateSessionDataQueue.offer( 414 mPendingCreateSessionDataQueue.offer(
417 new PendingCreateSessionData(sessionId, initData, mime)); 415 new PendingCreateSessionData(initData, mime, promiseId));
418 } 416 }
419 417
420 /** 418 /**
421 * Process all pending createSession() calls synchronously. 419 * Process all pending createSession() calls synchronously.
422 */ 420 */
423 private void processPendingCreateSessionData() { 421 private void processPendingCreateSessionData() {
424 Log.d(TAG, "processPendingCreateSessionData()"); 422 Log.d(TAG, "processPendingCreateSessionData()");
425 assert mMediaDrm != null; 423 assert mMediaDrm != null;
426 424
427 // Check mMediaDrm != null because error may happen in createSession(). 425 // Check mMediaDrm != null because error may happen in createSession().
428 // Check !mProvisioningPending because NotProvisionedException may be 426 // Check !mProvisioningPending because NotProvisionedException may be
429 // thrown in createSession(). 427 // thrown in createSession().
430 while (mMediaDrm != null && !mProvisioningPending 428 while (mMediaDrm != null && !mProvisioningPending
431 && !mPendingCreateSessionDataQueue.isEmpty()) { 429 && !mPendingCreateSessionDataQueue.isEmpty()) {
432 PendingCreateSessionData pendingData = mPendingCreateSessionDataQueu e.poll(); 430 PendingCreateSessionData pendingData = mPendingCreateSessionDataQueu e.poll();
433 int sessionId = pendingData.sessionId();
434 byte[] initData = pendingData.initData(); 431 byte[] initData = pendingData.initData();
435 String mime = pendingData.mimeType(); 432 String mime = pendingData.mimeType();
436 createSession(sessionId, initData, mime); 433 long promiseId = pendingData.promiseId();
434 createSession(initData, mime, promiseId);
437 } 435 }
438 } 436 }
439 437
440 /** 438 /**
441 * Process pending operations asynchrnously. 439 * Process pending operations asynchrnously.
442 */ 440 */
443 private void resumePendingOperations() { 441 private void resumePendingOperations() {
444 mHandler.post(new Runnable(){ 442 mHandler.post(new Runnable(){
445 @Override 443 @Override
446 public void run() { 444 public void run() {
447 processPendingCreateSessionData(); 445 processPendingCreateSessionData();
448 } 446 }
449 }); 447 });
450 } 448 }
451 449
452 /** 450 /**
453 * Create a session with |sessionId|, |initData| and |mime|. 451 * Create a session, and generate a request with |initData| and |mime|.
454 * 452 *
455 * @param sessionId ID for the session to be created.
456 * @param initData Data needed to generate the key request. 453 * @param initData Data needed to generate the key request.
457 * @param mime Mime type. 454 * @param mime Mime type.
455 * @param promiseId Promise ID for this call.
458 */ 456 */
459 @CalledByNative 457 @CalledByNative
460 private void createSession(int sessionId, byte[] initData, String mime) { 458 private void createSession(byte[] initData, String mime, long promiseId) {
461 Log.d(TAG, "createSession()"); 459 Log.d(TAG, "createSession()");
462 if (mMediaDrm == null) { 460 if (mMediaDrm == null) {
463 Log.e(TAG, "createSession() called when MediaDrm is null."); 461 Log.e(TAG, "createSession() called when MediaDrm is null.");
464 return; 462 return;
465 } 463 }
466 464
467 if (mProvisioningPending) { 465 if (mProvisioningPending) {
468 assert mMediaCrypto == null; 466 assert mMediaCrypto == null;
469 savePendingCreateSessionData(sessionId, initData, mime); 467 savePendingCreateSessionData(initData, mime, promiseId);
470 return; 468 return;
471 } 469 }
472 470
473 boolean newSessionOpened = false; 471 boolean newSessionOpened = false;
474 ByteBuffer session = null; 472 byte[] sessionId = null;
475 try { 473 try {
476 // Create MediaCrypto if necessary. 474 // Create MediaCrypto if necessary.
477 if (mMediaCrypto == null && !createMediaCrypto()) { 475 if (mMediaCrypto == null && !createMediaCrypto()) {
478 onSessionError(sessionId); 476 onPromiseRejected(promiseId, "MediaCrypto creation failed.");
479 return; 477 return;
480 } 478 }
479 assert mMediaCryptoSession != null;
481 assert mMediaCrypto != null; 480 assert mMediaCrypto != null;
482 assert mSessionIds.containsKey(mMediaCryptoSession);
483 481
484 session = openSession(); 482 sessionId = openSession();
485 if (session == null) { 483 if (sessionId == null) {
486 Log.e(TAG, "Cannot open session in createSession()."); 484 onPromiseRejected(promiseId, "Open session failed.");
487 onSessionError(sessionId);
488 return; 485 return;
489 } 486 }
490 newSessionOpened = true; 487 newSessionOpened = true;
491 assert !mSessionIds.containsKey(session); 488 assert !sessionExists(sessionId);
492 489
493 MediaDrm.KeyRequest request = null; 490 MediaDrm.KeyRequest request = null;
494 request = getKeyRequest(session, initData, mime); 491 request = getKeyRequest(sessionId, initData, mime);
495 if (request == null) { 492 if (request == null) {
496 if (newSessionOpened) { 493 mMediaDrm.closeSession(sessionId);
497 closeSession(session); 494 onPromiseRejected(promiseId, "Generate request failed.");
498 }
499 onSessionError(sessionId);
500 return; 495 return;
501 } 496 }
502 497
503 onSessionCreated(sessionId, getWebSessionId(session)); 498 // Success!
499 Log.d(TAG, "createSession(): Session (" + bytesToHexString(sessionId ) + ") created.");
500 onPromiseResolvedWithSession(promiseId, sessionId);
504 onSessionMessage(sessionId, request); 501 onSessionMessage(sessionId, request);
505 if (newSessionOpened) { 502 mSessionIds.put(ByteBuffer.wrap(sessionId), mime);
506 Log.d(TAG, "createSession(): Session " + getWebSessionId(session )
507 + " (" + sessionId + ") created.");
508 }
509
510 mSessionIds.put(session, sessionId);
511 mSessionMimeTypes.put(session, mime);
512 } catch (android.media.NotProvisionedException e) { 503 } catch (android.media.NotProvisionedException e) {
513 Log.e(TAG, "Device not provisioned", e); 504 Log.e(TAG, "Device not provisioned", e);
514 if (newSessionOpened) { 505 if (newSessionOpened) {
515 closeSession(session); 506 mMediaDrm.closeSession(sessionId);
516 } 507 }
517 savePendingCreateSessionData(sessionId, initData, mime); 508 savePendingCreateSessionData(initData, mime, promiseId);
518 startProvisioning(); 509 startProvisioning();
519 } 510 }
520 } 511 }
521 512
522 /** 513 /**
523 * Returns whether |sessionId| is a valid key session, excluding the media 514 * Check whether |sessionId| is an existing session ID, excluding the media
524 * crypto session. 515 * crypto session.
525 * 516 *
526 * @param sessionId Crypto session Id. 517 * @param sessionId Crypto session Id.
518 * @return true if |sessionId| exists, false otherwise.
527 */ 519 */
528 private boolean sessionExists(ByteBuffer session) { 520 private boolean sessionExists(byte[] sessionId) {
529 if (mMediaCryptoSession == null) { 521 if (mMediaCryptoSession == null) {
530 assert mSessionIds.isEmpty(); 522 assert mSessionIds.isEmpty();
531 Log.e(TAG, "Session doesn't exist because media crypto session is no t created."); 523 Log.e(TAG, "Session doesn't exist because media crypto session is no t created.");
532 return false; 524 return false;
533 } 525 }
534 assert mSessionIds.containsKey(mMediaCryptoSession); 526 return !Arrays.equals(sessionId, mMediaCryptoSession)
535 return !session.equals(mMediaCryptoSession) && mSessionIds.containsKey(s ession); 527 && mSessionIds.containsKey(ByteBuffer.wrap(sessionId));
536 } 528 }
537 529
538 /** 530 /**
539 * Cancel a key request for a session Id. 531 * Close a session that was previously created by createSession().
540 * 532 *
541 * @param sessionId Reference ID of session to be released. 533 * @param sessionId ID of session to be closed.
534 * @param promiseId Promise ID of this call.
542 */ 535 */
543 @CalledByNative 536 @CalledByNative
544 private void releaseSession(int sessionId) { 537 private void closeSession(byte[] sessionId, long promiseId) {
545 Log.d(TAG, "releaseSession(): " + sessionId); 538 Log.d(TAG, "closeSession()");
546 if (mMediaDrm == null) { 539 if (mMediaDrm == null) {
547 Log.e(TAG, "releaseSession() called when MediaDrm is null."); 540 onPromiseRejected(promiseId, "closeSession() called when MediaDrm is null.");
548 return; 541 return;
549 } 542 }
550 543
551 ByteBuffer session = getSession(sessionId); 544 if (!sessionExists(sessionId)) {
552 if (session == null) { 545 onPromiseRejected(promiseId,
553 Log.e(TAG, "Invalid sessionId in releaseSession."); 546 "Invalid sessionId in closeSession(): " + bytesToHexString(s essionId));
554 onSessionError(sessionId);
555 return; 547 return;
556 } 548 }
557 549
558 mMediaDrm.removeKeys(session.array()); 550 mMediaDrm.removeKeys(sessionId);
559 551 mMediaDrm.closeSession(sessionId);
560 Log.d(TAG, "Session " + sessionId + "closed."); 552 mSessionIds.remove(ByteBuffer.wrap(sessionId));
561 closeSession(session); 553 onPromiseResolved(promiseId);
562 mSessionIds.remove(session); 554 Log.d(TAG, "Session " + bytesToHexString(sessionId) + "closed.");
563 onSessionClosed(sessionId);
564 } 555 }
565 556
566 /** 557 /**
567 * Add a key for a session Id. 558 * Update a session with response.
568 * 559 *
569 * @param sessionId Reference ID of session to be updated. 560 * @param sessionId Reference ID of session to be updated.
570 * @param key Response data from the server. 561 * @param response Response data from the server.
562 * @param promiseId Promise ID of this call.
571 */ 563 */
572 @CalledByNative 564 @CalledByNative
573 private void updateSession(int sessionId, byte[] key) { 565 private void updateSession(byte[] sessionId, byte[] response, long promiseId ) {
574 Log.d(TAG, "updateSession(): " + sessionId); 566 Log.d(TAG, "updateSession()");
575 if (mMediaDrm == null) { 567 if (mMediaDrm == null) {
576 Log.e(TAG, "updateSession() called when MediaDrm is null."); 568 onPromiseRejected(promiseId, "closeSession() called when MediaDrm is null.");
577 return; 569 return;
578 } 570 }
579 571
580 // TODO(xhwang): We should be able to DCHECK this when WD EME is impleme nted. 572 // TODO(xhwang): DCHECK this when prefixed EME is deprecated.
581 ByteBuffer session = getSession(sessionId); 573 if (!sessionExists(sessionId)) {
582 if (!sessionExists(session)) { 574 onPromiseRejected(
583 Log.e(TAG, "Invalid session in updateSession."); 575 promiseId, "Invalid session in updateSession: " + bytesToHex String(sessionId));
584 onSessionError(sessionId);
585 return; 576 return;
586 } 577 }
587 578
588 try { 579 try {
589 try { 580 try {
590 mMediaDrm.provideKeyResponse(session.array(), key); 581 mMediaDrm.provideKeyResponse(sessionId, response);
591 } catch (java.lang.IllegalStateException e) { 582 } catch (java.lang.IllegalStateException e) {
592 // This is not really an exception. Some error code are incorrec tly 583 // This is not really an exception. Some error code are incorrec tly
593 // reported as an exception. 584 // reported as an exception.
594 // TODO(qinmin): remove this exception catch when b/10495563 is fixed. 585 // TODO(qinmin): remove this exception catch when b/10495563 is fixed.
595 Log.e(TAG, "Exception intentionally caught when calling provideK eyResponse()", e); 586 Log.e(TAG, "Exception intentionally caught when calling provideK eyResponse()", e);
596 } 587 }
597 onSessionReady(sessionId); 588 Log.d(TAG, "Key successfully added for session " + bytesToHexString( sessionId));
598 Log.d(TAG, "Key successfully added for session " + sessionId); 589 onPromiseResolved(promiseId);
590 onSessionKeysChange(sessionId, true, KEY_STATUS_USABLE);
599 return; 591 return;
600 } catch (android.media.NotProvisionedException e) { 592 } catch (android.media.NotProvisionedException e) {
601 // TODO(xhwang): Should we handle this? 593 // TODO(xhwang): Should we handle this?
602 Log.e(TAG, "failed to provide key response", e); 594 Log.e(TAG, "failed to provide key response", e);
603 } catch (android.media.DeniedByServerException e) { 595 } catch (android.media.DeniedByServerException e) {
604 Log.e(TAG, "failed to provide key response", e); 596 Log.e(TAG, "failed to provide key response", e);
605 } 597 }
606 onSessionError(sessionId); 598 onPromiseRejected(promiseId, "Update session failed.");
607 release(); 599 release();
608 } 600 }
609 601
610 /** 602 /**
611 * Return the security level of this DRM object. 603 * Return the security level of this DRM object.
612 */ 604 */
613 @CalledByNative 605 @CalledByNative
614 private String getSecurityLevel() { 606 private String getSecurityLevel() {
615 if (mMediaDrm == null) { 607 if (mMediaDrm == null) {
616 Log.e(TAG, "getSecurityLevel() called when MediaDrm is null."); 608 Log.e(TAG, "getSecurityLevel() called when MediaDrm is null.");
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 mResetDeviceCredentialsPending = false; 643 mResetDeviceCredentialsPending = false;
652 } 644 }
653 645
654 if (success) { 646 if (success) {
655 resumePendingOperations(); 647 resumePendingOperations();
656 } 648 }
657 } 649 }
658 650
659 /** 651 /**
660 * Provide the provisioning response to MediaDrm. 652 * Provide the provisioning response to MediaDrm.
653 *
661 * @returns false if the response is invalid or on error, true otherwise. 654 * @returns false if the response is invalid or on error, true otherwise.
662 */ 655 */
663 boolean provideProvisionResponse(byte[] response) { 656 boolean provideProvisionResponse(byte[] response) {
664 if (response == null || response.length == 0) { 657 if (response == null || response.length == 0) {
665 Log.e(TAG, "Invalid provision response."); 658 Log.e(TAG, "Invalid provision response.");
666 return false; 659 return false;
667 } 660 }
668 661
669 try { 662 try {
670 mMediaDrm.provideProvisionResponse(response); 663 mMediaDrm.provideProvisionResponse(response);
671 return true; 664 return true;
672 } catch (android.media.DeniedByServerException e) { 665 } catch (android.media.DeniedByServerException e) {
673 Log.e(TAG, "failed to provide provision response", e); 666 Log.e(TAG, "failed to provide provision response", e);
674 } catch (java.lang.IllegalStateException e) { 667 } catch (java.lang.IllegalStateException e) {
675 Log.e(TAG, "failed to provide provision response", e); 668 Log.e(TAG, "failed to provide provision response", e);
676 } 669 }
677 return false; 670 return false;
678 } 671 }
679 672
680 private void onSessionCreated(final int sessionId, final String webSessionId ) { 673 // Helper functions to post native calls to prevent reentrancy.
674
675 private void onPromiseResolved(final long promiseId) {
681 mHandler.post(new Runnable(){ 676 mHandler.post(new Runnable(){
682 @Override 677 @Override
683 public void run() { 678 public void run() {
684 nativeOnSessionCreated(mNativeMediaDrmBridge, sessionId, webSess ionId); 679 nativeOnPromiseResolved(mNativeMediaDrmBridge, promiseId);
685 } 680 }
686 }); 681 });
687 } 682 }
688 683
689 private void onSessionMessage(final int sessionId, final MediaDrm.KeyRequest request) { 684 private void onPromiseResolvedWithSession(final long promiseId, final byte[] sessionId) {
690 mHandler.post(new Runnable(){ 685 mHandler.post(new Runnable(){
691 @Override 686 @Override
692 public void run() { 687 public void run() {
693 nativeOnSessionMessage(mNativeMediaDrmBridge, sessionId, 688 nativeOnPromiseResolvedWithSession(mNativeMediaDrmBridge, promis eId, sessionId);
694 request.getData(), request.getDefaultUrl());
695 } 689 }
696 }); 690 });
697 } 691 }
698 692
699 private void onSessionReady(final int sessionId) { 693 private void onPromiseRejected(final long promiseId, final String errorMessa ge) {
694 Log.e(TAG, "onPromiseRejected: " + errorMessage);
700 mHandler.post(new Runnable() { 695 mHandler.post(new Runnable() {
701 @Override 696 @Override
702 public void run() { 697 public void run() {
703 nativeOnSessionReady(mNativeMediaDrmBridge, sessionId); 698 nativeOnPromiseRejected(mNativeMediaDrmBridge, promiseId, errorM essage);
704 } 699 }
705 }); 700 });
706 } 701 }
707 702
708 private void onSessionClosed(final int sessionId) { 703 private void onSessionMessage(final byte[] sessionId, final MediaDrm.KeyRequ est request) {
709 mHandler.post(new Runnable() { 704 mHandler.post(new Runnable() {
710 @Override 705 @Override
711 public void run() { 706 public void run() {
707 nativeOnSessionMessage(mNativeMediaDrmBridge, sessionId, request .getData(),
708 request.getDefaultUrl());
709 }
710 });
711 }
712
713 private void onSessionClosed(final byte[] sessionId) {
714 mHandler.post(new Runnable() {
715 @Override
716 public void run() {
712 nativeOnSessionClosed(mNativeMediaDrmBridge, sessionId); 717 nativeOnSessionClosed(mNativeMediaDrmBridge, sessionId);
713 } 718 }
714 }); 719 });
715 } 720 }
716 721
717 private void onSessionError(final int sessionId) { 722 private void onSessionKeysChange(
718 // TODO(qinmin): pass the error code to native. 723 final byte[] sessionId, final boolean hasAdditionalUsableKey, final int keyStatus) {
719 mHandler.post(new Runnable() { 724 mHandler.post(new Runnable() {
720 @Override 725 @Override
721 public void run() { 726 public void run() {
722 nativeOnSessionError(mNativeMediaDrmBridge, sessionId); 727 nativeOnSessionKeysChange(
728 mNativeMediaDrmBridge, sessionId, hasAdditionalUsableKey , keyStatus);
723 } 729 }
724 }); 730 });
725 } 731 }
726 732
727 private String getWebSessionId(ByteBuffer session) { 733 private void onLegacySessionError(final byte[] sessionId, final String error Message) {
728 String webSessionId = null; 734 Log.e(TAG, "onLegacySessionError: " + errorMessage);
729 try { 735 mHandler.post(new Runnable() {
730 webSessionId = new String(session.array(), "UTF-8"); 736 @Override
731 } catch (java.io.UnsupportedEncodingException e) { 737 public void run() {
732 Log.e(TAG, "getWebSessionId failed", e); 738 nativeOnLegacySessionError(mNativeMediaDrmBridge, sessionId, err orMessage);
733 } catch (java.lang.NullPointerException e) { 739 }
734 Log.e(TAG, "getWebSessionId failed", e); 740 });
735 }
736 return webSessionId;
737 } 741 }
738 742
739 private class MediaDrmListener implements MediaDrm.OnEventListener { 743 private class MediaDrmListener implements MediaDrm.OnEventListener {
740 @Override 744 @Override
741 public void onEvent( 745 public void onEvent(
742 MediaDrm mediaDrm, byte[] sessionArray, int event, int extra, by te[] data) { 746 MediaDrm mediaDrm, byte[] sessionId, int event, int extra, byte[ ] data) {
743 if (sessionArray == null) { 747 if (sessionId == null) {
744 Log.e(TAG, "MediaDrmListener: Null session."); 748 Log.e(TAG, "MediaDrmListener: Null session.");
745 return; 749 return;
746 } 750 }
747 ByteBuffer session = ByteBuffer.wrap(sessionArray); 751 if (!sessionExists(sessionId)) {
748 if (!sessionExists(session)) { 752 Log.e(TAG, "MediaDrmListener: Invalid session " + bytesToHexStri ng(sessionId));
749 Log.e(TAG, "MediaDrmListener: Invalid session.");
750 return;
751 }
752 Integer sessionId = mSessionIds.get(session);
753 if (sessionId == null || sessionId == INVALID_SESSION_ID) {
754 Log.e(TAG, "MediaDrmListener: Invalid session ID.");
755 return; 753 return;
756 } 754 }
757 switch(event) { 755 switch(event) {
758 case MediaDrm.EVENT_PROVISION_REQUIRED: 756 case MediaDrm.EVENT_PROVISION_REQUIRED:
759 Log.d(TAG, "MediaDrm.EVENT_PROVISION_REQUIRED"); 757 Log.d(TAG, "MediaDrm.EVENT_PROVISION_REQUIRED");
760 break; 758 break;
761 case MediaDrm.EVENT_KEY_REQUIRED: 759 case MediaDrm.EVENT_KEY_REQUIRED:
762 Log.d(TAG, "MediaDrm.EVENT_KEY_REQUIRED"); 760 Log.d(TAG, "MediaDrm.EVENT_KEY_REQUIRED");
763 if (mProvisioningPending) { 761 if (mProvisioningPending) {
764 return; 762 return;
765 } 763 }
766 String mime = mSessionMimeTypes.get(session); 764 String mime = mSessionIds.get(ByteBuffer.wrap(sessionId));
767 MediaDrm.KeyRequest request = null; 765 MediaDrm.KeyRequest request = null;
768 try { 766 try {
769 request = getKeyRequest(session, data, mime); 767 request = getKeyRequest(sessionId, data, mime);
770 } catch (android.media.NotProvisionedException e) { 768 } catch (android.media.NotProvisionedException e) {
771 Log.e(TAG, "Device not provisioned", e); 769 Log.e(TAG, "Device not provisioned", e);
772 startProvisioning(); 770 startProvisioning();
773 return; 771 return;
774 } 772 }
775 if (request != null) { 773 if (request != null) {
776 onSessionMessage(sessionId, request); 774 onSessionMessage(sessionId, request);
777 } else { 775 } else {
778 onSessionError(sessionId); 776 onLegacySessionError(sessionId,
777 "MediaDrm EVENT_KEY_REQUIRED: Failed to generate request.");
778 onSessionKeysChange(sessionId, false, KEY_STATUS_INTERNA L_ERROR);
779 } 779 }
780 break; 780 break;
781 case MediaDrm.EVENT_KEY_EXPIRED: 781 case MediaDrm.EVENT_KEY_EXPIRED:
782 Log.d(TAG, "MediaDrm.EVENT_KEY_EXPIRED"); 782 Log.d(TAG, "MediaDrm.EVENT_KEY_EXPIRED");
783 onSessionError(sessionId); 783 onLegacySessionError(sessionId, "MediaDrm EVENT_KEY_EXPIRED. ");
784 onSessionKeysChange(sessionId, false, KEY_STATUS_EXPIRED);
784 break; 785 break;
785 case MediaDrm.EVENT_VENDOR_DEFINED: 786 case MediaDrm.EVENT_VENDOR_DEFINED:
786 Log.d(TAG, "MediaDrm.EVENT_VENDOR_DEFINED"); 787 Log.d(TAG, "MediaDrm.EVENT_VENDOR_DEFINED");
787 assert false; // Should never happen. 788 assert false; // Should never happen.
788 break; 789 break;
789 default: 790 default:
790 Log.e(TAG, "Invalid DRM event " + event); 791 Log.e(TAG, "Invalid DRM event " + event);
791 return; 792 return;
792 } 793 }
793 } 794 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 ByteBuffer uuidBuffer = ByteBuffer.allocateDirect(16); 854 ByteBuffer uuidBuffer = ByteBuffer.allocateDirect(16);
854 // MSB (byte) should be positioned at the first element. 855 // MSB (byte) should be positioned at the first element.
855 uuidBuffer.order(ByteOrder.BIG_ENDIAN); 856 uuidBuffer.order(ByteOrder.BIG_ENDIAN);
856 uuidBuffer.putLong(uuid.getMostSignificantBits()); 857 uuidBuffer.putLong(uuid.getMostSignificantBits());
857 uuidBuffer.putLong(uuid.getLeastSignificantBits()); 858 uuidBuffer.putLong(uuid.getLeastSignificantBits());
858 nativeAddKeySystemUuidMapping(keySystem, uuidBuffer); 859 nativeAddKeySystemUuidMapping(keySystem, uuidBuffer);
859 } 860 }
860 861
861 private native void nativeOnMediaCryptoReady(long nativeMediaDrmBridge); 862 private native void nativeOnMediaCryptoReady(long nativeMediaDrmBridge);
862 863
863 private native void nativeOnSessionCreated(long nativeMediaDrmBridge, int se ssionId, 864 private native void nativeOnPromiseResolved(long nativeMediaDrmBridge, long promiseId);
864 String webSessionId); 865 private native void nativeOnPromiseResolvedWithSession(
866 long nativeMediaDrmBridge, long promiseId, byte[] sessionId);
867 private native void nativeOnPromiseRejected(
868 long nativeMediaDrmBridge, long promiseId, String errorMessage);
865 869
866 private native void nativeOnSessionMessage(long nativeMediaDrmBridge, int se ssionId, 870 private native void nativeOnSessionMessage(
867 byte[] message, String destinatio nUrl); 871 long nativeMediaDrmBridge, byte[] sessionId, byte[] message, String destinationUrl);
868 872 private native void nativeOnSessionClosed(long nativeMediaDrmBridge, byte[] sessionId);
869 private native void nativeOnSessionReady(long nativeMediaDrmBridge, int sess ionId); 873 private native void nativeOnSessionKeysChange(long nativeMediaDrmBridge, byt e[] sessionId,
870 874 boolean hasAdditionalUsableKey, int keyStatus);
871 private native void nativeOnSessionClosed(long nativeMediaDrmBridge, int ses sionId); 875 private native void nativeOnLegacySessionError(
872 876 long nativeMediaDrmBridge, byte[] sessionId, String errorMessage);
873 private native void nativeOnSessionError(long nativeMediaDrmBridge, int sess ionId);
874 877
875 private native void nativeOnResetDeviceCredentialsCompleted( 878 private native void nativeOnResetDeviceCredentialsCompleted(
876 long nativeMediaDrmBridge, boolean success); 879 long nativeMediaDrmBridge, boolean success);
877 880
878 private static native void nativeAddKeySystemUuidMapping(String keySystem, B yteBuffer uuid); 881 private static native void nativeAddKeySystemUuidMapping(String keySystem, B yteBuffer uuid);
879 } 882 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698