| 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 |