OLD | NEW |
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.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
8 import android.annotation.TargetApi; | 8 import android.annotation.TargetApi; |
9 import android.media.MediaCrypto; | 9 import android.media.MediaCrypto; |
10 import android.media.MediaDrm; | 10 import android.media.MediaDrm; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 | 76 |
77 // A session only for the purpose of creating a MediaCrypto object. Created | 77 // A session only for the purpose of creating a MediaCrypto object. Created |
78 // after construction, or after the provisioning process is successfully | 78 // after construction, or after the provisioning process is successfully |
79 // completed. No getKeyRequest() should be called on |mMediaCryptoSession|. | 79 // completed. No getKeyRequest() should be called on |mMediaCryptoSession|. |
80 private SessionId mMediaCryptoSession; | 80 private SessionId mMediaCryptoSession; |
81 | 81 |
82 // The map of all opened sessions (excluding mMediaCryptoSession) to their | 82 // The map of all opened sessions (excluding mMediaCryptoSession) to their |
83 // associated meta data, e.g. mime types, key types. | 83 // associated meta data, e.g. mime types, key types. |
84 private MediaDrmSessionManager mSessionManager; | 84 private MediaDrmSessionManager mSessionManager; |
85 | 85 |
| 86 // The persistent storage to record origin provisioning informations. |
| 87 private MediaDrmStorageBridge mStorage; |
| 88 |
86 // The queue of all pending createSession() data. | 89 // The queue of all pending createSession() data. |
87 private ArrayDeque<PendingCreateSessionData> mPendingCreateSessionDataQueue; | 90 private ArrayDeque<PendingCreateSessionData> mPendingCreateSessionDataQueue; |
88 | 91 |
89 private boolean mResetDeviceCredentialsPending; | 92 private boolean mResetDeviceCredentialsPending; |
90 | 93 |
91 // MediaDrmBridge is waiting for provisioning response from the server. | 94 // MediaDrmBridge is waiting for provisioning response from the server. |
92 private boolean mProvisioningPending; | 95 private boolean mProvisioningPending; |
93 | 96 |
| 97 // Boolean to track if 'ORIGIN' is set in MediaDrm. |
| 98 private boolean mOriginSet = false; |
| 99 |
94 /** | 100 /** |
95 * An equivalent of MediaDrm.KeyStatus, which is only available on M+. | 101 * An equivalent of MediaDrm.KeyStatus, which is only available on M+. |
96 */ | 102 */ |
97 @MainDex | 103 @MainDex |
98 private static class KeyStatus { | 104 private static class KeyStatus { |
99 private final byte[] mKeyId; | 105 private final byte[] mKeyId; |
100 private final int mStatusCode; | 106 private final int mStatusCode; |
101 | 107 |
102 private KeyStatus(byte[] keyId, int statusCode) { | 108 private KeyStatus(byte[] keyId, int statusCode) { |
103 mKeyId = keyId; | 109 mKeyId = keyId; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 | 195 |
190 private boolean isNativeMediaDrmBridgeValid() { | 196 private boolean isNativeMediaDrmBridgeValid() { |
191 return mNativeMediaDrmBridge != INVALID_NATIVE_MEDIA_DRM_BRIDGE; | 197 return mNativeMediaDrmBridge != INVALID_NATIVE_MEDIA_DRM_BRIDGE; |
192 } | 198 } |
193 | 199 |
194 private boolean isWidevine() { | 200 private boolean isWidevine() { |
195 return mSchemeUUID.equals(WIDEVINE_UUID); | 201 return mSchemeUUID.equals(WIDEVINE_UUID); |
196 } | 202 } |
197 | 203 |
198 @TargetApi(Build.VERSION_CODES.M) | 204 @TargetApi(Build.VERSION_CODES.M) |
199 private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge) | 205 private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge, |
200 throws android.media.UnsupportedSchemeException { | 206 long nativeMediaDrmStorageBridge) throws android.media.UnsupportedSc
hemeException { |
201 mSchemeUUID = schemeUUID; | 207 mSchemeUUID = schemeUUID; |
202 mMediaDrm = new MediaDrm(schemeUUID); | 208 mMediaDrm = new MediaDrm(schemeUUID); |
203 | 209 |
204 mNativeMediaDrmBridge = nativeMediaDrmBridge; | 210 mNativeMediaDrmBridge = nativeMediaDrmBridge; |
205 assert isNativeMediaDrmBridgeValid(); | 211 assert isNativeMediaDrmBridgeValid(); |
206 | 212 |
207 mSessionManager = new MediaDrmSessionManager(); | 213 mStorage = new MediaDrmStorageBridge(nativeMediaDrmStorageBridge); |
| 214 mSessionManager = new MediaDrmSessionManager(mStorage); |
| 215 |
208 mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData
>(); | 216 mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData
>(); |
209 mResetDeviceCredentialsPending = false; | 217 mResetDeviceCredentialsPending = false; |
210 mProvisioningPending = false; | 218 mProvisioningPending = false; |
211 | 219 |
212 mMediaDrm.setOnEventListener(new EventListener()); | 220 mMediaDrm.setOnEventListener(new EventListener()); |
213 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | 221 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
214 mMediaDrm.setOnExpirationUpdateListener(new ExpirationUpdateListener
(), null); | 222 mMediaDrm.setOnExpirationUpdateListener(new ExpirationUpdateListener
(), null); |
215 mMediaDrm.setOnKeyStatusChangeListener(new KeyStatusChangeListener()
, null); | 223 mMediaDrm.setOnKeyStatusChangeListener(new KeyStatusChangeListener()
, null); |
216 } | 224 } |
217 | 225 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 return MediaDrm.isCryptoSchemeSupported(cryptoScheme, containerMimeType)
; | 331 return MediaDrm.isCryptoSchemeSupported(cryptoScheme, containerMimeType)
; |
324 } | 332 } |
325 | 333 |
326 /** | 334 /** |
327 * Create a new MediaDrmBridge from the crypto scheme UUID. | 335 * Create a new MediaDrmBridge from the crypto scheme UUID. |
328 * | 336 * |
329 * @param schemeUUID Crypto scheme UUID. | 337 * @param schemeUUID Crypto scheme UUID. |
330 * @param securityOrigin Security origin. Empty value means no need for orig
in isolated storage. | 338 * @param securityOrigin Security origin. Empty value means no need for orig
in isolated storage. |
331 * @param securityLevel Security level. If empty, the default one should be
used. | 339 * @param securityLevel Security level. If empty, the default one should be
used. |
332 * @param nativeMediaDrmBridge Native object of this class. | 340 * @param nativeMediaDrmBridge Native object of this class. |
| 341 * @param nativeMediaDrmStorageBridge Native object of persistent storage. |
333 */ | 342 */ |
334 @CalledByNative | 343 @CalledByNative |
335 private static MediaDrmBridge create(byte[] schemeUUID, String securityOrigi
n, | 344 private static MediaDrmBridge create(byte[] schemeUUID, String securityOrigi
n, |
336 String securityLevel, long nativeMediaDrmBridge) { | 345 String securityLevel, long nativeMediaDrmBridge, long nativeMediaDrm
StorageBridge) { |
337 UUID cryptoScheme = getUUIDFromBytes(schemeUUID); | 346 UUID cryptoScheme = getUUIDFromBytes(schemeUUID); |
338 if (cryptoScheme == null || !MediaDrm.isCryptoSchemeSupported(cryptoSche
me)) { | 347 if (cryptoScheme == null || !MediaDrm.isCryptoSchemeSupported(cryptoSche
me)) { |
339 return null; | 348 return null; |
340 } | 349 } |
341 | 350 |
342 MediaDrmBridge mediaDrmBridge = null; | 351 MediaDrmBridge mediaDrmBridge = null; |
343 try { | 352 try { |
344 mediaDrmBridge = new MediaDrmBridge(cryptoScheme, nativeMediaDrmBrid
ge); | 353 mediaDrmBridge = new MediaDrmBridge( |
| 354 cryptoScheme, nativeMediaDrmBridge, nativeMediaDrmStorageBri
dge); |
345 Log.d(TAG, "MediaDrmBridge successfully created."); | 355 Log.d(TAG, "MediaDrmBridge successfully created."); |
346 } catch (android.media.UnsupportedSchemeException e) { | 356 } catch (android.media.UnsupportedSchemeException e) { |
347 Log.e(TAG, "Unsupported DRM scheme", e); | 357 Log.e(TAG, "Unsupported DRM scheme", e); |
348 return null; | 358 return null; |
349 } catch (java.lang.IllegalArgumentException e) { | 359 } catch (java.lang.IllegalArgumentException e) { |
350 Log.e(TAG, "Failed to create MediaDrmBridge", e); | 360 Log.e(TAG, "Failed to create MediaDrmBridge", e); |
351 return null; | 361 return null; |
352 } catch (java.lang.IllegalStateException e) { | 362 } catch (java.lang.IllegalStateException e) { |
353 Log.e(TAG, "Failed to create MediaDrmBridge", e); | 363 Log.e(TAG, "Failed to create MediaDrmBridge", e); |
354 return null; | 364 return null; |
(...skipping 24 matching lines...) Expand all Loading... |
379 if (!isWidevine()) { | 389 if (!isWidevine()) { |
380 Log.d(TAG, "Property " + ORIGIN + " isn't supported"); | 390 Log.d(TAG, "Property " + ORIGIN + " isn't supported"); |
381 return true; | 391 return true; |
382 } | 392 } |
383 | 393 |
384 assert mMediaDrm != null; | 394 assert mMediaDrm != null; |
385 assert !origin.isEmpty(); | 395 assert !origin.isEmpty(); |
386 | 396 |
387 try { | 397 try { |
388 mMediaDrm.setPropertyString(ORIGIN, origin); | 398 mMediaDrm.setPropertyString(ORIGIN, origin); |
| 399 mOriginSet = true; |
389 return true; | 400 return true; |
390 } catch (java.lang.IllegalArgumentException e) { | 401 } catch (java.lang.IllegalArgumentException e) { |
391 Log.e(TAG, "Failed to set security origin %s", origin, e); | 402 Log.e(TAG, "Failed to set security origin %s", origin, e); |
392 } catch (java.lang.IllegalStateException e) { | 403 } catch (java.lang.IllegalStateException e) { |
393 Log.e(TAG, "Failed to set security origin %s", origin, e); | 404 Log.e(TAG, "Failed to set security origin %s", origin, e); |
394 } | 405 } |
395 | 406 |
396 Log.e(TAG, "Security origin %s not supported!", origin); | 407 Log.e(TAG, "Security origin %s not supported!", origin); |
397 return false; | 408 return false; |
398 } | 409 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 try { | 517 try { |
507 // Some implementations don't have removeKeys, crbug/475632 | 518 // Some implementations don't have removeKeys, crbug/475632 |
508 mMediaDrm.removeKeys(sessionId.drmId()); | 519 mMediaDrm.removeKeys(sessionId.drmId()); |
509 } catch (Exception e) { | 520 } catch (Exception e) { |
510 Log.e(TAG, "removeKeys failed: ", e); | 521 Log.e(TAG, "removeKeys failed: ", e); |
511 } | 522 } |
512 | 523 |
513 closeSessionNoException(sessionId); | 524 closeSessionNoException(sessionId); |
514 onSessionClosed(sessionId); | 525 onSessionClosed(sessionId); |
515 } | 526 } |
516 mSessionManager = new MediaDrmSessionManager(); | 527 mSessionManager = new MediaDrmSessionManager(mStorage); |
517 | 528 |
518 // Close mMediaCryptoSession if it's open or notify MediaCrypto | 529 // Close mMediaCryptoSession if it's open or notify MediaCrypto |
519 // creation failure if it's never successfully opened. | 530 // creation failure if it's never successfully opened. |
520 if (mMediaCryptoSession == null) { | 531 if (mMediaCryptoSession == null) { |
521 // MediaCrypto never notified. Notify a null one now. | 532 // MediaCrypto never notified. Notify a null one now. |
522 onMediaCryptoReady(null); | 533 onMediaCryptoReady(null); |
523 } else { | 534 } else { |
524 closeSessionNoException(mMediaCryptoSession); | 535 closeSessionNoException(mMediaCryptoSession); |
525 mMediaCryptoSession = null; | 536 mMediaCryptoSession = null; |
526 } | 537 } |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 if (mResetDeviceCredentialsPending) { | 921 if (mResetDeviceCredentialsPending) { |
911 onResetDeviceCredentialsCompleted(success); | 922 onResetDeviceCredentialsCompleted(success); |
912 mResetDeviceCredentialsPending = false; | 923 mResetDeviceCredentialsPending = false; |
913 } | 924 } |
914 | 925 |
915 if (!success || (mMediaCryptoSession == null && !createMediaCrypto())) { | 926 if (!success || (mMediaCryptoSession == null && !createMediaCrypto())) { |
916 release(); | 927 release(); |
917 return; | 928 return; |
918 } | 929 } |
919 | 930 |
920 processPendingCreateSessionData(); | 931 if (!mOriginSet) { |
| 932 processPendingCreateSessionData(); |
| 933 return; |
| 934 } |
| 935 |
| 936 mStorage.onProvisioned(new Callback<Boolean>() { |
| 937 @Override |
| 938 public void onResult(Boolean initSuccess) { |
| 939 if (!initSuccess) { |
| 940 Log.e(TAG, "Failed to initialize storage for origin"); |
| 941 release(); |
| 942 return; |
| 943 } |
| 944 |
| 945 processPendingCreateSessionData(); |
| 946 } |
| 947 }); |
921 } | 948 } |
922 | 949 |
923 /** | 950 /** |
924 * Provides the provision response to MediaDrm. | 951 * Provides the provision response to MediaDrm. |
925 * | 952 * |
926 * @returns false if the response is invalid or on error, true otherwise. | 953 * @returns false if the response is invalid or on error, true otherwise. |
927 */ | 954 */ |
928 boolean provideProvisionResponse(byte[] response) { | 955 boolean provideProvisionResponse(byte[] response) { |
929 if (response == null || response.length == 0) { | 956 if (response == null || response.length == 0) { |
930 Log.e(TAG, "Invalid provision response."); | 957 Log.e(TAG, "Invalid provision response."); |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 long nativeMediaDrmBridge, byte[] emeSessionId, int requestType, byt
e[] message); | 1163 long nativeMediaDrmBridge, byte[] emeSessionId, int requestType, byt
e[] message); |
1137 private native void nativeOnSessionClosed(long nativeMediaDrmBridge, byte[]
emeSessionId); | 1164 private native void nativeOnSessionClosed(long nativeMediaDrmBridge, byte[]
emeSessionId); |
1138 private native void nativeOnSessionKeysChange(long nativeMediaDrmBridge, byt
e[] emeSessionId, | 1165 private native void nativeOnSessionKeysChange(long nativeMediaDrmBridge, byt
e[] emeSessionId, |
1139 Object[] keysInfo, boolean hasAdditionalUsableKey); | 1166 Object[] keysInfo, boolean hasAdditionalUsableKey); |
1140 private native void nativeOnSessionExpirationUpdate( | 1167 private native void nativeOnSessionExpirationUpdate( |
1141 long nativeMediaDrmBridge, byte[] emeSessionId, long expirationTime)
; | 1168 long nativeMediaDrmBridge, byte[] emeSessionId, long expirationTime)
; |
1142 | 1169 |
1143 private native void nativeOnResetDeviceCredentialsCompleted( | 1170 private native void nativeOnResetDeviceCredentialsCompleted( |
1144 long nativeMediaDrmBridge, boolean success); | 1171 long nativeMediaDrmBridge, boolean success); |
1145 } | 1172 } |
OLD | NEW |