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 |
94 /** | 97 /** |
95 * An equivalent of MediaDrm.KeyStatus, which is only available on M+. | 98 * An equivalent of MediaDrm.KeyStatus, which is only available on M+. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
189 | 192 |
190 private boolean isNativeMediaDrmBridgeValid() { | 193 private boolean isNativeMediaDrmBridgeValid() { |
191 return mNativeMediaDrmBridge != INVALID_NATIVE_MEDIA_DRM_BRIDGE; | 194 return mNativeMediaDrmBridge != INVALID_NATIVE_MEDIA_DRM_BRIDGE; |
192 } | 195 } |
193 | 196 |
194 private boolean isWidevine() { | 197 private boolean isWidevine() { |
195 return mSchemeUUID.equals(WIDEVINE_UUID); | 198 return mSchemeUUID.equals(WIDEVINE_UUID); |
196 } | 199 } |
197 | 200 |
198 @TargetApi(Build.VERSION_CODES.M) | 201 @TargetApi(Build.VERSION_CODES.M) |
199 private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge) | 202 private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge, |
200 throws android.media.UnsupportedSchemeException { | 203 long nativeMediaDrmStorageBridge) throws android.media.UnsupportedSc hemeException { |
201 mSchemeUUID = schemeUUID; | 204 mSchemeUUID = schemeUUID; |
202 mMediaDrm = new MediaDrm(schemeUUID); | 205 mMediaDrm = new MediaDrm(schemeUUID); |
203 | 206 |
204 mNativeMediaDrmBridge = nativeMediaDrmBridge; | 207 mNativeMediaDrmBridge = nativeMediaDrmBridge; |
205 assert isNativeMediaDrmBridgeValid(); | 208 assert isNativeMediaDrmBridgeValid(); |
206 | 209 |
207 mSessionManager = new MediaDrmSessionManager(); | 210 mStorage = new MediaDrmStorageBridge(nativeMediaDrmStorageBridge); |
211 mSessionManager = new MediaDrmSessionManager(mStorage); | |
212 | |
208 mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData >(); | 213 mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData >(); |
209 mResetDeviceCredentialsPending = false; | 214 mResetDeviceCredentialsPending = false; |
210 mProvisioningPending = false; | 215 mProvisioningPending = false; |
211 | 216 |
212 mMediaDrm.setOnEventListener(new EventListener()); | 217 mMediaDrm.setOnEventListener(new EventListener()); |
213 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | 218 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
214 mMediaDrm.setOnExpirationUpdateListener(new ExpirationUpdateListener (), null); | 219 mMediaDrm.setOnExpirationUpdateListener(new ExpirationUpdateListener (), null); |
215 mMediaDrm.setOnKeyStatusChangeListener(new KeyStatusChangeListener() , null); | 220 mMediaDrm.setOnKeyStatusChangeListener(new KeyStatusChangeListener() , null); |
216 } | 221 } |
217 | 222 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 return MediaDrm.isCryptoSchemeSupported(cryptoScheme, containerMimeType) ; | 328 return MediaDrm.isCryptoSchemeSupported(cryptoScheme, containerMimeType) ; |
324 } | 329 } |
325 | 330 |
326 /** | 331 /** |
327 * Create a new MediaDrmBridge from the crypto scheme UUID. | 332 * Create a new MediaDrmBridge from the crypto scheme UUID. |
328 * | 333 * |
329 * @param schemeUUID Crypto scheme UUID. | 334 * @param schemeUUID Crypto scheme UUID. |
330 * @param securityOrigin Security origin. Empty value means no need for orig in isolated storage. | 335 * @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. | 336 * @param securityLevel Security level. If empty, the default one should be used. |
332 * @param nativeMediaDrmBridge Native object of this class. | 337 * @param nativeMediaDrmBridge Native object of this class. |
338 * @param nativeMediaDrmStorageBridge Native object of persistent storage. | |
333 */ | 339 */ |
334 @CalledByNative | 340 @CalledByNative |
335 private static MediaDrmBridge create(byte[] schemeUUID, String securityOrigi n, | 341 private static MediaDrmBridge create(byte[] schemeUUID, String securityOrigi n, |
336 String securityLevel, long nativeMediaDrmBridge) { | 342 String securityLevel, long nativeMediaDrmBridge, long nativeMediaDrm StorageBridge) { |
337 UUID cryptoScheme = getUUIDFromBytes(schemeUUID); | 343 UUID cryptoScheme = getUUIDFromBytes(schemeUUID); |
338 if (cryptoScheme == null || !MediaDrm.isCryptoSchemeSupported(cryptoSche me)) { | 344 if (cryptoScheme == null || !MediaDrm.isCryptoSchemeSupported(cryptoSche me)) { |
339 return null; | 345 return null; |
340 } | 346 } |
341 | 347 |
342 MediaDrmBridge mediaDrmBridge = null; | 348 MediaDrmBridge mediaDrmBridge = null; |
343 try { | 349 try { |
344 mediaDrmBridge = new MediaDrmBridge(cryptoScheme, nativeMediaDrmBrid ge); | 350 mediaDrmBridge = new MediaDrmBridge( |
351 cryptoScheme, nativeMediaDrmBridge, nativeMediaDrmStorageBri dge); | |
345 Log.d(TAG, "MediaDrmBridge successfully created."); | 352 Log.d(TAG, "MediaDrmBridge successfully created."); |
346 } catch (android.media.UnsupportedSchemeException e) { | 353 } catch (android.media.UnsupportedSchemeException e) { |
347 Log.e(TAG, "Unsupported DRM scheme", e); | 354 Log.e(TAG, "Unsupported DRM scheme", e); |
348 return null; | 355 return null; |
349 } catch (java.lang.IllegalArgumentException e) { | 356 } catch (java.lang.IllegalArgumentException e) { |
350 Log.e(TAG, "Failed to create MediaDrmBridge", e); | 357 Log.e(TAG, "Failed to create MediaDrmBridge", e); |
351 return null; | 358 return null; |
352 } catch (java.lang.IllegalStateException e) { | 359 } catch (java.lang.IllegalStateException e) { |
353 Log.e(TAG, "Failed to create MediaDrmBridge", e); | 360 Log.e(TAG, "Failed to create MediaDrmBridge", e); |
354 return null; | 361 return null; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
506 try { | 513 try { |
507 // Some implementations don't have removeKeys, crbug/475632 | 514 // Some implementations don't have removeKeys, crbug/475632 |
508 mMediaDrm.removeKeys(sessionId.drmId()); | 515 mMediaDrm.removeKeys(sessionId.drmId()); |
509 } catch (Exception e) { | 516 } catch (Exception e) { |
510 Log.e(TAG, "removeKeys failed: ", e); | 517 Log.e(TAG, "removeKeys failed: ", e); |
511 } | 518 } |
512 | 519 |
513 closeSessionNoException(sessionId); | 520 closeSessionNoException(sessionId); |
514 onSessionClosed(sessionId); | 521 onSessionClosed(sessionId); |
515 } | 522 } |
516 mSessionManager = new MediaDrmSessionManager(); | 523 mSessionManager = new MediaDrmSessionManager(mStorage); |
517 | 524 |
518 // Close mMediaCryptoSession if it's open or notify MediaCrypto | 525 // Close mMediaCryptoSession if it's open or notify MediaCrypto |
519 // creation failure if it's never successfully opened. | 526 // creation failure if it's never successfully opened. |
520 if (mMediaCryptoSession == null) { | 527 if (mMediaCryptoSession == null) { |
521 // MediaCrypto never notified. Notify a null one now. | 528 // MediaCrypto never notified. Notify a null one now. |
522 onMediaCryptoReady(null); | 529 onMediaCryptoReady(null); |
523 } else { | 530 } else { |
524 closeSessionNoException(mMediaCryptoSession); | 531 closeSessionNoException(mMediaCryptoSession); |
525 mMediaCryptoSession = null; | 532 mMediaCryptoSession = null; |
526 } | 533 } |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
910 if (mResetDeviceCredentialsPending) { | 917 if (mResetDeviceCredentialsPending) { |
911 onResetDeviceCredentialsCompleted(success); | 918 onResetDeviceCredentialsCompleted(success); |
912 mResetDeviceCredentialsPending = false; | 919 mResetDeviceCredentialsPending = false; |
913 } | 920 } |
914 | 921 |
915 if (!success || (mMediaCryptoSession == null && !createMediaCrypto())) { | 922 if (!success || (mMediaCryptoSession == null && !createMediaCrypto())) { |
916 release(); | 923 release(); |
917 return; | 924 return; |
918 } | 925 } |
919 | 926 |
920 processPendingCreateSessionData(); | 927 if (!useOriginIsolatedStorage()) { |
928 processPendingCreateSessionData(); | |
929 return; | |
930 } | |
931 | |
932 mStorage.onProvisioned(new Callback<Boolean>() { | |
933 @Override | |
934 public void onResult(Boolean initSuccess) { | |
935 if (!initSuccess) { | |
936 Log.e(TAG, "Failed to initialize storage for origin"); | |
937 release(); | |
938 return; | |
939 } | |
940 | |
941 processPendingCreateSessionData(); | |
942 } | |
943 }); | |
944 } | |
945 | |
946 private boolean useOriginIsolatedStorage() { | |
947 assert mMediaDrm != null; | |
948 | |
949 boolean isMOrHigher = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; | |
950 boolean isOriginSet = !isWidevine() || !mMediaDrm.getPropertyString(ORIG IN).isEmpty(); | |
xhwang
2017/03/31 03:47:57
Is it ever possible that getPropertyString(ORIGIN)
yucliu1
2017/03/31 05:38:17
We should check origin only for M or higher device
xhwang
2017/03/31 06:25:50
At least for now, per-origin provisioning is a req
yucliu1
2017/03/31 18:42:30
Good point! And I think we want to disable the fea
| |
951 | |
952 return isMOrHigher && isOriginSet; | |
921 } | 953 } |
922 | 954 |
923 /** | 955 /** |
924 * Provides the provision response to MediaDrm. | 956 * Provides the provision response to MediaDrm. |
925 * | 957 * |
926 * @returns false if the response is invalid or on error, true otherwise. | 958 * @returns false if the response is invalid or on error, true otherwise. |
927 */ | 959 */ |
928 boolean provideProvisionResponse(byte[] response) { | 960 boolean provideProvisionResponse(byte[] response) { |
929 if (response == null || response.length == 0) { | 961 if (response == null || response.length == 0) { |
930 Log.e(TAG, "Invalid provision response."); | 962 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); | 1168 long nativeMediaDrmBridge, byte[] emeSessionId, int requestType, byt e[] message); |
1137 private native void nativeOnSessionClosed(long nativeMediaDrmBridge, byte[] emeSessionId); | 1169 private native void nativeOnSessionClosed(long nativeMediaDrmBridge, byte[] emeSessionId); |
1138 private native void nativeOnSessionKeysChange(long nativeMediaDrmBridge, byt e[] emeSessionId, | 1170 private native void nativeOnSessionKeysChange(long nativeMediaDrmBridge, byt e[] emeSessionId, |
1139 Object[] keysInfo, boolean hasAdditionalUsableKey); | 1171 Object[] keysInfo, boolean hasAdditionalUsableKey); |
1140 private native void nativeOnSessionExpirationUpdate( | 1172 private native void nativeOnSessionExpirationUpdate( |
1141 long nativeMediaDrmBridge, byte[] emeSessionId, long expirationTime) ; | 1173 long nativeMediaDrmBridge, byte[] emeSessionId, long expirationTime) ; |
1142 | 1174 |
1143 private native void nativeOnResetDeviceCredentialsCompleted( | 1175 private native void nativeOnResetDeviceCredentialsCompleted( |
1144 long nativeMediaDrmBridge, boolean success); | 1176 long nativeMediaDrmBridge, boolean success); |
1145 } | 1177 } |
OLD | NEW |