@SuppressWarnings("deprecation") @Override public void handleMessage(Message msg) { if (openCount == 0 || (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS)) { return; } switch (msg.what) { case MediaDrm.EVENT_KEY_REQUIRED: postKeyRequest(); return; case MediaDrm.EVENT_KEY_EXPIRED: state = STATE_OPENED; onError(new KeysExpiredException()); return; case MediaDrm.EVENT_PROVISION_REQUIRED: state = STATE_OPENED; postProvisionRequest(); return; } }
@TargetApi(18) @SuppressWarnings("ResourceType") private static boolean isL1WidevineAvailable(String videoMimeType) { try { // Force L3 if secure decoder is not available. if (MediaCodecUtil.getDecoderInfo(videoMimeType, true) == null) { return false; } MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); mediaDrm.release(); return WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty); } catch (DecoderQueryException | UnsupportedSchemeException e) { throw new IllegalStateException(e); } }
@Override public KeyRequest getKeyRequest(byte[] scope, byte[] init, String mimeType, int keyType, HashMap<String, String> optionalParameters) throws NotProvisionedException { final MediaDrm.KeyRequest request = mediaDrm.getKeyRequest(scope, init, mimeType, keyType, optionalParameters); return new KeyRequest() { @Override public byte[] getData() { return request.getData(); } @Override public String getDefaultUrl() { return request.getDefaultUrl(); } }; }
@SuppressWarnings("deprecation") @Override public void handleMessage(Message msg) { if (openCount == 0 || (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS)) { return; } switch (msg.what) { case MediaDrm.EVENT_KEY_REQUIRED: doLicense(); break; case MediaDrm.EVENT_KEY_EXPIRED: // When an already expired key is loaded MediaDrm sends this event immediately. Ignore // this event if the state isn't STATE_OPENED_WITH_KEYS yet which means we're still // waiting for key response. if (state == STATE_OPENED_WITH_KEYS) { state = STATE_OPENED; onError(new KeysExpiredException()); } break; case MediaDrm.EVENT_PROVISION_REQUIRED: state = STATE_OPENED; postProvisionRequest(); break; } }
@Override public void handleMessage(Message msg) { if (openCount == 0 || (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS)) { return; } switch (msg.what) { case MediaDrm.EVENT_KEY_REQUIRED: postKeyRequest(); return; case MediaDrm.EVENT_KEY_EXPIRED: state = STATE_OPENED; onError(new KeysExpiredException()); return; case MediaDrm.EVENT_PROVISION_REQUIRED: state = STATE_OPENED; postProvisionRequest(); return; } }
private static boolean getBooleanProperty(MediaDrm drm, String propertyName) { String property; try { property = drm.getPropertyString(propertyName); } catch (Exception exc) { property = null; } property = BaseDrmInfo.sanitize(property); if (TextUtils.isEmpty(property)) { return false; } property = property.toLowerCase(); return "true".equals(property) || "1".equals(property) || "yes".equals(property) || Boolean.parseBoolean(property); }
@Override public void handleMessage(Message msg) { if (openCount == 0 || (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS)) { return; } switch (msg.what) { case MediaDrm.EVENT_KEY_REQUIRED: postKeyRequest(); return; case MediaDrm.EVENT_KEY_EXPIRED: state = STATE_OPENED; postKeyRequest(); return; case MediaDrm.EVENT_PROVISION_REQUIRED: state = STATE_OPENED; postProvisionRequest(); return; } }
@TargetApi(Build.VERSION_CODES.M) private void onSessionMessage(final SessionId sessionId, final MediaDrm.KeyRequest request) { if (!isNativeMediaDrmBridgeValid()) return; int requestType = MediaDrm.KeyRequest.REQUEST_TYPE_INITIAL; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { requestType = request.getRequestType(); } else { // Prior to M, getRequestType() is not supported. Do our best guess here: Assume // requests with a URL are renewals and all others are initial requests. requestType = request.getDefaultUrl().isEmpty() ? MediaDrm.KeyRequest.REQUEST_TYPE_INITIAL : MediaDrm.KeyRequest.REQUEST_TYPE_RENEWAL; } nativeOnSessionMessage( mNativeMediaDrmBridge, sessionId.emeId(), requestType, request.getData()); }
@Override public void onKeyStatusChange(MediaDrm md, byte[] drmSessionId, final List<MediaDrm.KeyStatus> keyInformation, final boolean hasNewUsableKey) { final SessionId sessionId = getSessionIdByDrmId(drmSessionId); assert sessionId != null; assert mSessionManager.get(sessionId) != null; final boolean isKeyRelease = mSessionManager.get(sessionId).keyType() == MediaDrm.KEY_TYPE_RELEASE; deferEventHandleIfNeeded(sessionId, new Runnable() { @Override public void run() { Log.d(TAG, "KeysStatusChange: " + sessionId.toHexString() + ", " + hasNewUsableKey); onSessionKeysChange(sessionId, getKeysInfo(keyInformation).toArray(), hasNewUsableKey, isKeyRelease); } }); }
@Override public void onExpirationUpdate( MediaDrm md, byte[] drmSessionId, final long expirationTime) { final SessionId sessionId = getSessionIdByDrmId(drmSessionId); assert sessionId != null; deferEventHandleIfNeeded(sessionId, new Runnable() { @Override public void run() { Log.d(TAG, "ExpirationUpdate: " + sessionId.toHexString() + ", " + expirationTime); onSessionExpirationUpdate(sessionId, expirationTime); } }); }
@Override public void onResult(Boolean success) { if (!success) { onPromiseRejected(mPromiseId, "failed to update key after response accepted"); return; } Log.d(TAG, "Key successfully %s for session %s", mIsKeyRelease ? "released" : "added", mSessionId.toHexString()); onPromiseResolved(mPromiseId); if (!mIsKeyRelease && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { onSessionKeysChange(mSessionId, getDummyKeysInfo(MediaDrm.KeyStatus.STATUS_USABLE).toArray(), true, mIsKeyRelease); } }
@SuppressWarnings("ResourceType") public static boolean isL1WidevineAvailable(String mimeType) { if (Util.SDK_INT >= 18) { try { // Force L3 if secure decoder is not available. if (MediaCodecUtil.getDecoderInfo(mimeType, true) == null) { return false; } MediaDrm mediaDrm = MediaDrmBuilder.build(); String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); mediaDrm.release(); return WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty); } catch (MediaCodecUtil.DecoderQueryException e) { throw new IllegalStateException(e); } } return false; }
@Override public void setOnKeyStatusChangeListener( final ExoMediaDrm.OnKeyStatusChangeListener<? super FrameworkMediaCrypto> listener) { if (Util.SDK_INT < 23) { throw new UnsupportedOperationException(); } mediaDrm.setOnKeyStatusChangeListener(listener == null ? null : new MediaDrm.OnKeyStatusChangeListener() { @Override public void onKeyStatusChange(@NonNull MediaDrm md, @NonNull byte[] sessionId, @NonNull List<MediaDrm.KeyStatus> keyInfo, boolean hasNewUsableKey) { List<KeyStatus> exoKeyInfo = new ArrayList<>(); for (MediaDrm.KeyStatus keyStatus : keyInfo) { exoKeyInfo.add(new DefaultKeyStatus(keyStatus.getStatusCode(), keyStatus.getKeyId())); } listener.onKeyStatusChange(FrameworkMediaDrm.this, sessionId, exoKeyInfo, hasNewUsableKey); } }, null); }
@Override public void onEvent(MediaDrm mediaDrm, byte[] sessionId, int event, int extra, byte[] data) { switch(event) { case MediaDrm.EVENT_PROVISION_REQUIRED: Log.d(TAG, "MediaDrm.EVENT_PROVISION_REQUIRED."); MediaDrm.ProvisionRequest request = mMediaDrm.getProvisionRequest(); PostRequestTask postTask = new PostRequestTask(request.getData()); postTask.execute(request.getDefaultUrl()); break; case MediaDrm.EVENT_KEY_REQUIRED: generateKeyRequest(data, mMimeType); break; case MediaDrm.EVENT_KEY_EXPIRED: onKeyError(); break; case MediaDrm.EVENT_VENDOR_DEFINED: assert(false); break; default: Log.e(TAG, "Invalid DRM event " + (int)event); return; } }
private MediaDrmBridge(UUID schemeUUID, long nativeMediaDrmBridge, boolean singleSessionMode) throws android.media.UnsupportedSchemeException { mSchemeUUID = schemeUUID; mMediaDrm = new MediaDrm(schemeUUID); mNativeMediaDrmBridge = nativeMediaDrmBridge; mHandler = new Handler(); mSingleSessionMode = singleSessionMode; mSessionIds = new HashMap<ByteBuffer, Integer>(); mSessionMimeTypes = new HashMap<ByteBuffer, String>(); mPendingCreateSessionDataQueue = new ArrayDeque<PendingCreateSessionData>(); mResetDeviceCredentialsPending = false; mProvisioningPending = false; mMediaDrm.setOnEventListener(new MediaDrmListener()); mMediaDrm.setPropertyString(PRIVACY_MODE, ENABLE); if (!mSingleSessionMode) { mMediaDrm.setPropertyString(SESSION_SHARING, ENABLE); } // We could open a MediaCrypto session here to support faster start of // clear lead (no need to wait for createSession()). But on // Android, memory and battery resources are precious and we should // only create a session when we are sure we'll use it. // TODO(xhwang): Investigate other options to support fast start. }
OfflineDrmSessionManager(OfflineKeySetStorage storage) throws UnsupportedDrmException { mStorage = storage; try { mMediaDrm = new MediaDrm(WIDEVINE_UUID); OfflineDrmManager.printAllProperties(mMediaDrm); mMediaDrm.setOnEventListener(new MediaDrm.OnEventListener() { @Override public void onEvent(@NonNull MediaDrm md, byte[] sessionId, int event, int extra, byte[] data) { Log.d(TAG, "onEvent:" + toHexString(sessionId) + ":" + event + ":" + extra + ":" + toHexString(data)); } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { setOnKeyStatusChangeListener(); } } catch (UnsupportedSchemeException e) { throw new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME, e); } }
public static Set<KMediaFormat> supportedFormats(Context context) { Set<KMediaFormat> set = new HashSet<>(); // Clear dash and mp4 are always supported by this player. set.add(KMediaFormat.dash_clear); set.add(KMediaFormat.mp4_clear); set.add(KMediaFormat.hls_clear); // Encrypted dash is only supported in Android v4.3 and up -- needs MediaDrm class. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { // Make sure Widevine is supported. if (MediaDrm.isCryptoSchemeSupported(ExoplayerUtil.WIDEVINE_UUID)) { set.add(KMediaFormat.dash_widevine); } } return set; }
private void postKeyRequest() { KeyRequest keyRequest; try { keyRequest = mediaDrm.getKeyRequest(sessionId, schemeInitData.data, schemeInitData.mimeType, MediaDrm.KEY_TYPE_STREAMING, optionalKeyRequestParameters); postRequestHandler.obtainMessage(MSG_KEYS, keyRequest).sendToTarget(); } catch (NotProvisionedException e) { onKeysError(e); } }
@Override public void setOnEventListener( final OnEventListener<? super FrameworkMediaCrypto> listener) { mediaDrm.setOnEventListener(listener == null ? null : new MediaDrm.OnEventListener() { @Override public void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data) { listener.onEvent(FrameworkMediaDrm.this, sessionId, event, extra, data); } }); }
@Override public ProvisionRequest getProvisionRequest() { final MediaDrm.ProvisionRequest provisionRequest = mediaDrm.getProvisionRequest(); return new ProvisionRequest() { @Override public byte[] getData() { return provisionRequest.getData(); } @Override public String getDefaultUrl() { return provisionRequest.getDefaultUrl(); } }; }
@Override public void setOnEventListener( final ExoMediaDrm.OnEventListener<? super FrameworkMediaCrypto> listener) { mediaDrm.setOnEventListener(listener == null ? null : new MediaDrm.OnEventListener() { @Override public void onEvent(@NonNull MediaDrm md, byte[] sessionId, int event, int extra, byte[] data) { listener.onEvent(FrameworkMediaDrm.this, sessionId, event, extra, data); } }); }
private void postKeyRequest() { KeyRequest keyRequest; try { keyRequest = mediaDrm.getKeyRequest(sessionId, schemeData, mimeType, MediaDrm.KEY_TYPE_STREAMING, optionalKeyRequestParameters); postRequestHandler.obtainMessage(MSG_KEYS, keyRequest).sendToTarget(); } catch (NotProvisionedException e) { onKeysError(e); } }
@Override public void setOnEventListener( final ExoMediaDrm.OnEventListener<? super FrameworkMediaCrypto> listener) { mediaDrm.setOnEventListener(listener == null ? null : new MediaDrm.OnEventListener() { @Override public void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data) { listener.onEvent(FrameworkMediaDrm.this, sessionId, event, extra, data); } }); }
private void postKeyRequest() { KeyRequest keyRequest; try { keyRequest = mediaDrm.getKeyRequest(sessionId, schemeData.data, schemeData.mimeType, MediaDrm.KEY_TYPE_STREAMING, optionalKeyRequestParameters); postRequestHandler.obtainMessage(MSG_KEYS, keyRequest).sendToTarget(); } catch (NotProvisionedException e) { onKeysError(e); } }