// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.media;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.media.MediaCrypto;
import android.media.MediaDrm;
import android.os.Build;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.Callback;
import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.MainDex;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.media.MediaDrmSessionManager.SessionId;
import org.chromium.media.MediaDrmSessionManager.SessionInfo;

import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Queue;
import java.util.UUID;

// Implementation Notes of MediaDrmBridge:
//
// MediaCrypto Creation: If requiresMediaCrypto is true, the caller is guaranteed to wait until
// MediaCrypto is created to call any other methods. A mMediaCryptoSession is opened after MediaDrm
// is created. This session will NOT be added to mSessionManager and will only be used to create the
// MediaCrypto object. createMediaCrypto() may trigger the provisioning process, where MediaCrypto
// creation will resume after provisioning completes.
//
// Unprovision: If requiresMediaCrypto is false, MediaDrmBridge is not created for playback.
// Instead, it's created to unprovision the device/origin, which is only supported on newer Android
// versions. unprovision() is triggered when user clears media licenses.
//
// NotProvisionedException: If this exception is thrown in operations other than
// createMediaCrypto(), we will fail that operation and not trying to provision again.
//
// Session Manager: Each createSession() call creates a new session. All created sessions are
// managed in mSessionManager except for mMediaCryptoSession.
//
// Error Handling: Whenever an unexpected error occurred, we'll call release() to release all
// resources immediately, clear all states and fail all pending operations. After that all calls to
// this object will fail (e.g. return null or reject the promise). All public APIs and callbacks
// should check mMediaBridge to make sure release() hasn't been called.

/**
 * A wrapper of the android MediaDrm class. Each MediaDrmBridge manages multiple sessions for
 * MediaCodecAudioDecoders or MediaCodecVideoDecoders.
 */
@JNINamespace("media")
@MainDex
@SuppressLint("WrongConstant")
public class MediaDrmBridge {
    private static final String TAG = "media";
    private static final String SECURITY_LEVEL = "securityLevel";
    private static final String SERVER_CERTIFICATE = "serviceCertificate";
    private static final String ORIGIN = "origin";
    private static final String PRIVACY_MODE = "privacyMode";
    private static final String SESSION_SHARING = "sessionSharing";
    private static final String ENABLE = "enable";
    private static final long INVALID_NATIVE_MEDIA_DRM_BRIDGE = 0;
    private static final String FIRST_API_LEVEL = "ro.product.first_api_level";

    // Scheme UUID for Widevine. See http://dashif.org/identifiers/protection/
    private static final UUID WIDEVINE_UUID =
            UUID.fromString("edef8ba9-79d6-4ace-a3c8-27dcd51d21ed");

    // On Android L and before, MediaDrm doesn't support KeyStatus at all. On later Android
    // versions, key IDs are not available on sessions where getKeyRequest() has been called with
    // KEY_TYPE_RELEASE. In these cases, the EME spec recommends to use a one-byte key ID 0:
    // "Some older platforms may contain Key System implementations that do not expose key IDs,
    // making it impossible to provide a compliant user agent implementation. To maximize
    // interoperability, user agent implementations exposing such CDMs should implement this member
    // as follows: Whenever a non-empty list is appropriate, such as when the key session
    // represented by this object may contain key(s), populate the map with a single pair containing
    // the one-byte key ID 0 and the MediaKeyStatus most appropriate for the aggregated status of
    // this object."
    // See details: https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-keystatuses
    private static final byte[] DUMMY_KEY_ID = new byte[] {0};

    // Special provision response to remove the cert.
    private static final byte[] UNPROVISION = ApiCompatibilityUtils.getBytesUtf8("unprovision");

    private MediaDrm mMediaDrm;
    private MediaCrypto mMediaCrypto;
    private long mNativeMediaDrmBridge;
    private UUID mSchemeUUID;
    private final boolean mRequiresMediaCrypto;

    // A session only for the purpose of creating a MediaCrypto object. Created
    // after construction, or after the provisioning process is successfully
    // completed. No getKeyRequest() should be called on |mMediaCryptoSession|.
    private SessionId mMediaCryptoSession;

    // The map of all opened sessions (excluding mMediaCryptoSession) to their
    // associated meta data, e.g. mime types, key types.
    private MediaDrmSessionManager mSessionManager;

    // The persistent storage to record origin provisioning informations.
    private MediaDrmStorageBridge mStorage;

    // Whether the current MediaDrmBridge instance is waiting for provisioning response.
    private boolean mProvisioningPending;

    // Current 'ORIGIN" setting.
    private String mOrigin;

    // Boolean to track if 'ORIGIN' is set in MediaDrm.
    private boolean mOriginSet;

    private SessionEventDeferrer mSessionEventDeferrer;

    // Defer the creation of MediaCryptor creation. Only used when mRequiresMediaCrypto is true.
    private static final MediaCryptoDeferrer sMediaCryptoDeferrer = new MediaCryptoDeferrer();

    private static class MediaCryptoDeferrer {
        // Whether any MediaDrmBridge instance is waiting for provisioning response.
        private boolean mIsProvisioning;

        // Pending events to fire after provisioning is finished.
        private final Queue<Runnable> mEventHandlers;

        MediaCryptoDeferrer() {
            mIsProvisioning = false;
            mEventHandlers = new ArrayDeque<Runnable>();
        }

        boolean isProvisioning() {
            return mIsProvisioning;
        }

        void onProvisionStarted() {
            assert !mIsProvisioning;
            mIsProvisioning = true;
        }

        void defer(Runnable handler) {
            assert mIsProvisioning;
            mEventHandlers.add(handler);
        }

        void onProvisionDone() {
            assert mIsProvisioning;
            mIsProvisioning = false;

            // This will cause createMediaCrypto() on another MediaDrmBridge object and could cause
            // reentrance into the shared static sMediaCryptoDeferrer. For example, during
            // createMediaCrypto(), we could hit NotProvisionedException again, and call
            // isProvisioning() to check whether it can start provisioning or not. If so, it'll
            // call onProvisionStarted(). To avoid the case where we call createMediaCrypto() and
            // then immediately call defer(), we'll return early whenever mIsProvisioning becomes
            // true.
            while (!mEventHandlers.isEmpty()) {
                Log.d(TAG, "run deferred CreateMediaCrypto() calls");
                Runnable r = mEventHandlers.element();
                mEventHandlers.remove();

                r.run();

                if (mIsProvisioning) {
                    Log.d(TAG, "provision triggerred while running deferred CreateMediaCrypto()");
                    return;
                }
            }
        }
    }

    // Block MediaDrm event for |mSessionId|. MediaDrm may fire event before the
    // functions return. This may break Chromium CDM API's assumption. For
    // example, when loading session, 'restoreKeys' will trigger key status
    // change event. But the session isn't known to Chromium CDM because the
    // promise isn't resolved. The class can block and collect these events and
    // fire these events later.
    private static class SessionEventDeferrer {
        private final SessionId mSessionId;
        private final ArrayList<Runnable> mEventHandlers;

        SessionEventDeferrer(SessionId sessionId) {
            mSessionId = sessionId;
            mEventHandlers = new ArrayList<>();
        }

        boolean shouldDefer(SessionId sessionId) {
            return mSessionId.isEqual(sessionId);
        }

        void defer(Runnable handler) {
            mEventHandlers.add(handler);
        }

        void fire() {
            for (Runnable r : mEventHandlers) {
                r.run();
            }

            mEventHandlers.clear();
        }
    }

    /**
     *  An equivalent of MediaDrm.KeyStatus, which is only available on M+.
     */
    private static class KeyStatus {
        private final byte[] mKeyId;
        private final int mStatusCode;

        private KeyStatus(byte[] keyId, int statusCode) {
            mKeyId = keyId;
            mStatusCode = statusCode;
        }

        @CalledByNative("KeyStatus")
        private byte[] getKeyId() {
            return mKeyId;
        }

        @CalledByNative("KeyStatus")
        private int getStatusCode() {
            return mStatusCode;
        }
    }

    /**
     *  Creates a dummy single element list of KeyStatus with a dummy key ID and
     *  the specified keyStatus.
     */
    private static List<KeyStatus> getDummyKeysInfo(int statusCode) {
        List<KeyStatus> keysInfo = new ArrayList<KeyStatus>();
        keysInfo.add(new KeyStatus(DUMMY_KEY_ID, statusCode));
        return keysInfo;
    }

    private static UUID getUUIDFromBytes(byte[] data) {
        if (data.length != 16) {
            return null;
        }
        long mostSigBits = 0;
        long leastSigBits = 0;
        for (int i = 0; i < 8; i++) {
            mostSigBits = (mostSigBits << 8) | (data[i] & 0xff);
        }
        for (int i = 8; i < 16; i++) {
            leastSigBits = (leastSigBits << 8) | (data[i] & 0xff);
        }
        return new UUID(mostSigBits, leastSigBits);
    }

    private boolean isNativeMediaDrmBridgeValid() {
        return mNativeMediaDrmBridge != INVALID_NATIVE_MEDIA_DRM_BRIDGE;
    }

    private boolean isWidevine() {
        return mSchemeUUID.equals(WIDEVINE_UUID);
    }

    @TargetApi(Build.VERSION_CODES.M)
    private MediaDrmBridge(UUID schemeUUID, boolean requiresMediaCrypto, long nativeMediaDrmBridge,
            long nativeMediaDrmStorageBridge) throws android.media.UnsupportedSchemeException {
        mSchemeUUID = schemeUUID;
        mMediaDrm = new MediaDrm(schemeUUID);
        mRequiresMediaCrypto = requiresMediaCrypto;

        mNativeMediaDrmBridge = nativeMediaDrmBridge;
        assert isNativeMediaDrmBridgeValid();

        mStorage = new MediaDrmStorageBridge(nativeMediaDrmStorageBridge);
        mSessionManager = new MediaDrmSessionManager(mStorage);

        mProvisioningPending = false;

        mMediaDrm.setOnEventListener(new EventListener());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mMediaDrm.setOnExpirationUpdateListener(new ExpirationUpdateListener(), null);
            mMediaDrm.setOnKeyStatusChangeListener(new KeyStatusChangeListener(), null);
        }

        if (isWidevine()) {
            mMediaDrm.setPropertyString(PRIVACY_MODE, ENABLE);
            mMediaDrm.setPropertyString(SESSION_SHARING, ENABLE);
        }
    }

    /**
     * Create a MediaCrypto object.
     *
     * @return false upon fatal error in creating MediaCrypto. Returns true
     * otherwise, including the following two cases:
     *   1. MediaCrypto is successfully created and notified.
     *   2. Device is not provisioned and MediaCrypto creation will be tried
     *      again after the provisioning process is completed.
     *
     *  When false is returned, release() is called within the function, which
     *  will notify the native code with a null MediaCrypto, if needed.
     */
    private boolean createMediaCrypto() {
        assert mMediaDrm != null;
        assert !mProvisioningPending;
        assert mMediaCryptoSession == null;

        // Open media crypto session.
        byte[] mediaCryptoSessionDrmId = null;
        try {
            mediaCryptoSessionDrmId = openSession();
        } catch (android.media.NotProvisionedException e) {
            Log.d(TAG, "Not provisioned during openSession()");

            if (!sMediaCryptoDeferrer.isProvisioning()) {
                return startProvisioning();
            }

            // Cannot provision. Defer MediaCrypto creation and try again later.
            Log.d(TAG, "defer CreateMediaCrypto() calls");
            sMediaCryptoDeferrer.defer(new Runnable() {
                @Override
                public void run() {
                    createMediaCrypto();
                }
            });

            return true;
        }

        if (mediaCryptoSessionDrmId == null) {
            Log.e(TAG, "Cannot create MediaCrypto Session.");
            // No need to release() here since openSession() does so on failure.
            return false;
        }

        mMediaCryptoSession = SessionId.createTemporarySessionId(mediaCryptoSessionDrmId);

        Log.d(TAG, "MediaCrypto Session created: %s", mMediaCryptoSession.toHexString());

        // Create MediaCrypto object.
        try {
            if (MediaCrypto.isCryptoSchemeSupported(mSchemeUUID)) {
                mMediaCrypto = new MediaCrypto(mSchemeUUID, mMediaCryptoSession.drmId());
                Log.d(TAG, "MediaCrypto successfully created!");
                onMediaCryptoReady(mMediaCrypto);
                return true;
            } else {
                Log.e(TAG, "Cannot create MediaCrypto for unsupported scheme.");
            }
        } catch (android.media.MediaCryptoException e) {
            Log.e(TAG, "Cannot create MediaCrypto", e);
        }

        release();
        return false;
    }

    /**
     * Open a new session.
     *
     * @return ID of the session opened. Returns null if unexpected error happened.
     */
    private byte[] openSession() throws android.media.NotProvisionedException {
        assert mMediaDrm != null;
        try {
            byte[] sessionId = mMediaDrm.openSession();
            // Make a clone here in case the underlying byte[] is modified.
            return sessionId.clone();
        } catch (java.lang.RuntimeException e) { // TODO(xhwang): Drop this?
            Log.e(TAG, "Cannot open a new session", e);
            release();
            return null;
        } catch (android.media.NotProvisionedException e) {
            // Throw NotProvisionedException so that we can startProvisioning().
            throw e;
        } catch (android.media.MediaDrmException e) {
            // Other MediaDrmExceptions (e.g. ResourceBusyException) are not
            // recoverable.
            Log.e(TAG, "Cannot open a new session", e);
            release();
            return null;
        }
    }

    /**
     * Check whether the crypto scheme is supported for the given container.
     * If |containerMimeType| is an empty string, we just return whether
     * the crypto scheme is supported.
     *
     * @return true if the container and the crypto scheme is supported, or
     * false otherwise.
     */
    @CalledByNative
    private static boolean isCryptoSchemeSupported(byte[] schemeUUID, String containerMimeType) {
        UUID cryptoScheme = getUUIDFromBytes(schemeUUID);

        if (containerMimeType.isEmpty()) {
            return MediaDrm.isCryptoSchemeSupported(cryptoScheme);
        }

        return MediaDrm.isCryptoSchemeSupported(cryptoScheme, containerMimeType);
    }

    /**
     * Returns the first API level for this product.
     *
     * @return the converted value for FIRST_API_LEVEL if available,
     * 0 otherwise.
     */
    @CalledByNative
    private static int getFirstApiLevel() {
        int firstApiLevel = 0;
        try {
            final Class<?> systemProperties = Class.forName("android.os.SystemProperties");
            final Method getInt = systemProperties.getMethod("getInt", String.class, int.class);
            firstApiLevel = (Integer) getInt.invoke(null, FIRST_API_LEVEL, 0);
        } catch (Exception e) {
            Log.e(TAG, "Exception while getting system property %s. Using default.",
                    FIRST_API_LEVEL, e);
            firstApiLevel = 0;
        }
        return firstApiLevel;
    }

    /**
     * Create a new MediaDrmBridge from the crypto scheme UUID.
     *
     * @param schemeUUID Crypto scheme UUID.
     * @param securityOrigin Security origin. Empty value means no need for origin isolated storage.
     * @param securityLevel Security level. If empty, the default one should be used.
     * @param nativeMediaDrmBridge Native object of this class.
     * @param nativeMediaDrmStorageBridge Native object of persistent storage.
     */
    @CalledByNative
    private static MediaDrmBridge create(byte[] schemeUUID, String securityOrigin,
            String securityLevel, boolean requiresMediaCrypto, long nativeMediaDrmBridge,
            long nativeMediaDrmStorageBridge) {
        Log.i(TAG, "Create MediaDrmBridge with level %s and origin %s", securityLevel,
                securityOrigin);

        MediaDrmBridge mediaDrmBridge = null;
        try {
            UUID cryptoScheme = getUUIDFromBytes(schemeUUID);
            if (cryptoScheme == null || !MediaDrm.isCryptoSchemeSupported(cryptoScheme)) {
                return null;
            }

            mediaDrmBridge = new MediaDrmBridge(cryptoScheme, requiresMediaCrypto,
                    nativeMediaDrmBridge, nativeMediaDrmStorageBridge);
        } catch (android.media.UnsupportedSchemeException e) {
            Log.e(TAG, "Unsupported DRM scheme", e);
            return null;
        } catch (java.lang.IllegalArgumentException e) {
            Log.e(TAG, "Failed to create MediaDrmBridge", e);
            return null;
        } catch (java.lang.IllegalStateException e) {
            Log.e(TAG, "Failed to create MediaDrmBridge", e);
            return null;
        }

        if (!securityLevel.isEmpty() && !mediaDrmBridge.setSecurityLevel(securityLevel)) {
            mediaDrmBridge.release();
            return null;
        }

        if (!securityOrigin.isEmpty() && !mediaDrmBridge.setOrigin(securityOrigin)) {
            mediaDrmBridge.release();
            return null;
        }

        // When session support is required, we need to create MediaCrypto to
        // finish the CDM creation process. This may trigger the provisioning
        // process, in which case MediaCrypto will be created after provision
        // is finished.
        if (requiresMediaCrypto && !mediaDrmBridge.createMediaCrypto()) {
            // No need to call release() as createMediaCrypto() does if it fails.
            return null;
        }

        return mediaDrmBridge;
    }

    /**
     * Set the security origin for the MediaDrm. All information should be isolated for different
     * origins, e.g. certificates, licenses.
     */
    private boolean setOrigin(String origin) {
        assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
        Log.d(TAG, "Set origin: %s", origin);

        if (!isWidevine()) {
            Log.d(TAG, "Property " + ORIGIN + " isn't supported");
            return true;
        }

        assert mMediaDrm != null;
        assert !origin.isEmpty();

        try {
            mMediaDrm.setPropertyString(ORIGIN, origin);
            mOrigin = origin;
            mOriginSet = true;
            return true;
        } catch (java.lang.IllegalArgumentException e) {
            Log.e(TAG, "Failed to set security origin %s", origin, e);
        } catch (java.lang.IllegalStateException e) {
            Log.e(TAG, "Failed to set security origin %s", origin, e);
        }

        Log.e(TAG, "Security origin %s not supported!", origin);
        return false;
    }

    /**
     * Set the security level that the MediaDrm object uses.
     * This function should be called right after we construct MediaDrmBridge
     * and before we make any other calls.
     *
     * @param securityLevel Security level to be set.
     * @return whether the security level was successfully set.
     */
    private boolean setSecurityLevel(String securityLevel) {
        if (!isWidevine()) {
            Log.d(TAG, "Security level is not supported.");
            return true;
        }

        assert mMediaDrm != null;
        assert !securityLevel.isEmpty();

        String currentSecurityLevel = getSecurityLevel();
        if (currentSecurityLevel.equals("")) {
            // Failure logged by getSecurityLevel().
            return false;
        }

        Log.d(TAG, "Security level: current %s, new %s", currentSecurityLevel, securityLevel);
        if (securityLevel.equals(currentSecurityLevel)) {
            // No need to set the same security level again. This is not just
            // a shortcut! Setting the same security level actually causes an
            // exception in MediaDrm!
            return true;
        }

        try {
            mMediaDrm.setPropertyString(SECURITY_LEVEL, securityLevel);
            return true;
        } catch (java.lang.IllegalArgumentException e) {
        } catch (java.lang.IllegalStateException e) {
        }

        Log.e(TAG, "Security level %s not supported!", securityLevel);
        return false;
    }

    /**
     * Set the server certificate.
     *
     * @param certificate Server certificate to be set.
     * @return whether the server certificate was successfully set.
     */
    @CalledByNative
    private boolean setServerCertificate(byte[] certificate) {
        if (!isWidevine()) {
            Log.d(TAG, "Setting server certificate is not supported.");
            return true;
        }

        try {
            mMediaDrm.setPropertyByteArray(SERVER_CERTIFICATE, certificate);
            return true;
        } catch (java.lang.IllegalArgumentException e) {
            Log.e(TAG, "Failed to set server certificate", e);
        } catch (java.lang.IllegalStateException e) {
            Log.e(TAG, "Failed to set server certificate", e);
        }

        return false;
    }

    /**
     * Provision the current origin. Normally provisioning will be triggered
     * automatically when MediaCrypto is needed (in the constructor).
     * However, this is available to preprovision an origin separately.
     * MediaDrmBridgeJni.get().onProvisioningComplete() will be called indicating success/failure.
     */
    @CalledByNative
    private void provision() {
        // This should only be called if no MediaCrypto needed.
        assert mMediaDrm != null;
        assert !mProvisioningPending;
        assert !mRequiresMediaCrypto;

        // Provision only works for origin isolated storage.
        if (!mOriginSet) {
            Log.e(TAG, "Calling provision() without an origin.");
            MediaDrmBridgeJni.get().onProvisioningComplete(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, false);
            return;
        }

        // The security level used for provisioning cannot be set and is cached from when a need for
        // provisioning is last detected. So if we call startProvisioning() it will use the default
        // security level, which may not match the security level needed. As a result this code must
        // call openSession(), which will result in the security level being cached. We don't care
        // about the session, so if it opens simply close it.
        try {
            // This will throw a NotProvisionedException if provisioning needed. If it succeeds,
            // assume this origin ID is already provisioned.
            byte[] drmId = openSession();

            // Provisioning is not required. If a session was actually opened, close it.
            if (drmId != null) {
                SessionId sessionId = SessionId.createTemporarySessionId(drmId);
                closeSessionNoException(sessionId);
            }

            // Indicate that provisioning succeeded.
            MediaDrmBridgeJni.get().onProvisioningComplete(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, true);

        } catch (android.media.NotProvisionedException e) {
            if (!startProvisioning()) {
                // Indicate that provisioning failed.
                MediaDrmBridgeJni.get().onProvisioningComplete(
                        mNativeMediaDrmBridge, MediaDrmBridge.this, false);
            }
        }
    }

    /**
     * Unprovision the current origin, a.k.a removing the cert for current origin.
     */
    @CalledByNative
    private void unprovision() {
        if (mMediaDrm == null) {
            return;
        }

        // Unprovision only works for origin isolated storage.
        if (!mOriginSet) {
            return;
        }

        provideProvisionResponse(UNPROVISION);
    }

    /**
     * Destroy the MediaDrmBridge object.
     */
    @CalledByNative
    private void destroy() {
        mNativeMediaDrmBridge = INVALID_NATIVE_MEDIA_DRM_BRIDGE;
        if (mMediaDrm != null) {
            release();
        }
    }

    /**
     * Release all allocated resources and finish all pending operations.
     */
    private void release() {
        // Note that mNativeMediaDrmBridge may have already been reset (see destroy()).

        assert mMediaDrm != null;

        // Close all open sessions.
        for (SessionId sessionId : mSessionManager.getAllSessionIds()) {
            try {
                // Some implementations don't have removeKeys, crbug/475632
                mMediaDrm.removeKeys(sessionId.drmId());
            } catch (Exception e) {
                Log.e(TAG, "removeKeys failed: ", e);
            }

            closeSessionNoException(sessionId);
            onSessionClosed(sessionId);
        }
        mSessionManager = new MediaDrmSessionManager(mStorage);

        // Close mMediaCryptoSession if it's open.
        if (mMediaCryptoSession != null) {
            closeSessionNoException(mMediaCryptoSession);
            mMediaCryptoSession = null;
        }

        if (mMediaDrm != null) {
            mMediaDrm.release();
            mMediaDrm = null;
        }

        if (mMediaCrypto != null) {
            mMediaCrypto.release();
            mMediaCrypto = null;
        } else {
            // MediaCrypto never notified. Notify a null one now.
            onMediaCryptoReady(null);
        }
    }

    /**
     * Get a key request.
     *
     * @param sessionId ID of session on which we need to get the key request.
     * @param data Data needed to get the key request.
     * @param mime Mime type to get the key request.
     * @param keyType Key type for the requested key.
     * @param optionalParameters Optional parameters to pass to the DRM plugin.
     *
     * @return the key request.
     */
    private MediaDrm.KeyRequest getKeyRequest(SessionId sessionId, byte[] data, String mime,
            int keyType, HashMap<String, String> optionalParameters)
            throws android.media.NotProvisionedException {
        assert mMediaDrm != null;
        assert mMediaCryptoSession != null;
        assert !mProvisioningPending;

        if (optionalParameters == null) {
            optionalParameters = new HashMap<String, String>();
        }

        MediaDrm.KeyRequest request = null;

        try {
            byte[] scopeId =
                    keyType == MediaDrm.KEY_TYPE_RELEASE ? sessionId.keySetId() : sessionId.drmId();
            assert scopeId != null;
            request = mMediaDrm.getKeyRequest(scopeId, data, mime, keyType, optionalParameters);
        } catch (java.lang.IllegalStateException e) {
            // We've seen both MediaDrmStateException and MediaDrmResetException happening.
            // Since both are IllegalStateExceptions, so they will be handled here.
            // See b/21307186 and crbug.com/1169050 for details.
            Log.e(TAG, "Failed to getKeyRequest().", e);
        }

        String result = (request != null) ? "successed" : "failed";
        Log.d(TAG, "getKeyRequest %s!", result);

        return request;
    }

    /**
     * createSession interface to be called from native using primitive types.
     * @see createSession(byte[], String, HashMap<String, String>, long)
     */
    @CalledByNative
    private void createSessionFromNative(byte[] initData, String mime, int keyType,
            String[] optionalParamsArray, long promiseId) {
        HashMap<String, String> optionalParameters = new HashMap<String, String>();
        if (optionalParamsArray != null) {
            if (optionalParamsArray.length % 2 != 0) {
                throw new IllegalArgumentException(
                        "Additional data array doesn't have equal keys/values");
            }
            for (int i = 0; i < optionalParamsArray.length; i += 2) {
                optionalParameters.put(optionalParamsArray[i], optionalParamsArray[i + 1]);
            }
        }
        createSession(initData, mime, keyType, optionalParameters, promiseId);
    }

    /**
     * Create a session, and generate a request with |initData| and |mime|.
     *
     * @param initData Data needed to generate the key request.
     * @param mime Mime type.
     * @param keyType Key type.
     * @param optionalParameters Additional data to pass to getKeyRequest.
     * @param promiseId Promise ID for this call.
     */
    private void createSession(byte[] initData, String mime, int keyType,
            HashMap<String, String> optionalParameters, long promiseId) {
        Log.d(TAG, "createSession()");

        if (mMediaDrm == null) {
            Log.e(TAG, "createSession() called when MediaDrm is null.");
            onPromiseRejected(promiseId, "MediaDrm released previously.");
            return;
        }

        assert mMediaCryptoSession != null;
        assert !mProvisioningPending;

        boolean newSessionOpened = false;
        SessionId sessionId = null;
        try {
            byte[] drmId = openSession();
            if (drmId == null) {
                onPromiseRejected(promiseId, "Open session failed.");
                return;
            }
            newSessionOpened = true;
            assert keyType == MediaDrm.KEY_TYPE_STREAMING || keyType == MediaDrm.KEY_TYPE_OFFLINE;
            sessionId = (keyType == MediaDrm.KEY_TYPE_OFFLINE)
                    ? SessionId.createPersistentSessionId(drmId)
                    : SessionId.createTemporarySessionId(drmId);

            MediaDrm.KeyRequest request =
                    getKeyRequest(sessionId, initData, mime, keyType, optionalParameters);
            if (request == null) {
                closeSessionNoException(sessionId);
                onPromiseRejected(promiseId, "Generate request failed.");
                return;
            }

            // Success!
            Log.d(TAG, "createSession(): Session (%s) created.", sessionId.toHexString());
            onPromiseResolvedWithSession(promiseId, sessionId);
            onSessionMessage(sessionId, request);
            mSessionManager.put(sessionId, mime, keyType);
        } catch (android.media.NotProvisionedException e) {
            Log.e(TAG, "Device not provisioned", e);
            if (newSessionOpened) {
                closeSessionNoException(sessionId);
            }
            onPromiseRejected(promiseId, "Device not provisioned during createSession().");
        }
    }

    /**
     * Search and return the SessionId for raw EME/DRM session id.
     *
     * @param emeId Raw EME session Id.
     * @return SessionId of |emeId| if exists and isn't a MediaCryptoSession, null otherwise.
     */
    private SessionId getSessionIdByEmeId(byte[] emeId) {
        if (mMediaCryptoSession == null) {
            Log.e(TAG, "Session doesn't exist because media crypto session is not created.");
            return null;
        }

        SessionId sessionId = mSessionManager.getSessionIdByEmeId(emeId);
        if (sessionId == null) {
            return null;
        }

        assert !mMediaCryptoSession.isEqual(sessionId);

        return sessionId;
    }

    /**
     * Similar with getSessionIdByEmeId, just search for raw DRM session id.
     */
    private SessionId getSessionIdByDrmId(byte[] drmId) {
        if (mMediaCryptoSession == null) {
            Log.e(TAG, "Session doesn't exist because media crypto session is not created.");
            return null;
        }

        SessionId sessionId = mSessionManager.getSessionIdByDrmId(drmId);
        if (sessionId == null) {
            return null;
        }

        assert !mMediaCryptoSession.isEqual(sessionId);

        return sessionId;
    }

    /**
     * Close a session that was previously created by createSession().
     *
     * @param emeSessionId ID of session to be closed.
     * @param promiseId Promise ID of this call.
     */
    @CalledByNative
    private void closeSession(byte[] emeSessionId, long promiseId) {
        Log.d(TAG, "closeSession()");
        if (mMediaDrm == null) {
            onPromiseRejected(promiseId, "closeSession() called when MediaDrm is null.");
            return;
        }

        SessionId sessionId = getSessionIdByEmeId(emeSessionId);
        if (sessionId == null) {
            onPromiseRejected(promiseId,
                    "Invalid sessionId in closeSession(): " + SessionId.toHexString(emeSessionId));
            return;
        }

        try {
            // Some implementations don't have removeKeys, crbug/475632
            mMediaDrm.removeKeys(sessionId.drmId());
        } catch (Exception e) {
            Log.e(TAG, "removeKeys failed: ", e);
        }

        closeSessionNoException(sessionId);
        mSessionManager.remove(sessionId);
        onPromiseResolved(promiseId);
        onSessionClosed(sessionId);
        Log.d(TAG, "Session %s closed", sessionId.toHexString());
    }

    /**
     * Close the session without worry about the exception, because some
     * implementations let this method throw exception, crbug/611865.
     */
    private void closeSessionNoException(SessionId sessionId) {
        try {
            mMediaDrm.closeSession(sessionId.drmId());
        } catch (Exception e) {
            Log.e(TAG, "closeSession failed: ", e);
        }
    }

    /**
     * Update a session with response.
     *
     * @param emeSessionId Reference ID of session to be updated.
     * @param response Response data from the server.
     * @param promiseId Promise ID of this call.
     */
    @CalledByNative
    private void updateSession(byte[] emeSessionId, byte[] response, final long promiseId) {
        Log.d(TAG, "updateSession()");
        if (mMediaDrm == null) {
            onPromiseRejected(promiseId, "updateSession() called when MediaDrm is null.");
            return;
        }

        final SessionId sessionId = getSessionIdByEmeId(emeSessionId);
        if (sessionId == null) {
            assert false; // Should never happen.
            onPromiseRejected(promiseId,
                    "Invalid session in updateSession: " + SessionId.toHexString(emeSessionId));
            return;
        }

        try {
            SessionInfo sessionInfo = mSessionManager.get(sessionId);
            boolean isKeyRelease = sessionInfo.keyType() == MediaDrm.KEY_TYPE_RELEASE;

            byte[] keySetId = null;
            if (isKeyRelease) {
                Log.d(TAG, "updateSession() for key release");
                assert sessionId.keySetId() != null;
                mMediaDrm.provideKeyResponse(sessionId.keySetId(), response);
            } else {
                keySetId = mMediaDrm.provideKeyResponse(sessionId.drmId(), response);
            }

            KeyUpdatedCallback cb = new KeyUpdatedCallback(sessionId, promiseId, isKeyRelease);

            if (isKeyRelease) {
                mSessionManager.clearPersistentSessionInfo(sessionId, cb);
            } else if (sessionInfo.keyType() == MediaDrm.KEY_TYPE_OFFLINE && keySetId != null
                    && keySetId.length > 0) {
                mSessionManager.setKeySetId(sessionId, keySetId, cb);
            } else {
                // This can be either temporary license update or server certificate update.
                cb.onResult(true);
            }

            return;
        } catch (android.media.NotProvisionedException e) {
            // TODO(xhwang): Should we handle this?
            Log.e(TAG, "failed to provide key response", e);
        } catch (android.media.DeniedByServerException e) {
            Log.e(TAG, "failed to provide key response", e);
        } catch (java.lang.IllegalStateException e) {
            Log.e(TAG, "failed to provide key response", e);
        }
        onPromiseRejected(promiseId, "Update session failed.");
        release();
    }

    /**
     * Load persistent license from storage.
     */
    @CalledByNative
    @TargetApi(Build.VERSION_CODES.M)
    private void loadSession(byte[] emeId, final long promiseId) {
        Log.d(TAG, "loadSession()");
        assert !mProvisioningPending;

        mSessionManager.load(emeId, new Callback<SessionId>() {
            @Override
            public void onResult(SessionId sessionId) {
                if (sessionId == null) {
                    onPersistentLicenseNoExist(promiseId);
                    return;
                }

                loadSessionWithLoadedStorage(sessionId, promiseId);
            }
        });
    }

    /**
     * Load session back to memory with MediaDrm. Load persistent storage
     * before calling this. It will fail if persistent storage isn't loaded.
     */
    @TargetApi(Build.VERSION_CODES.M)
    private void loadSessionWithLoadedStorage(SessionId sessionId, final long promiseId) {
        byte[] drmId = null;
        try {
            drmId = openSession();
            if (drmId == null) {
                onPromiseRejected(promiseId, "Failed to open session to load license.");
                return;
            }

            mSessionManager.setDrmId(sessionId, drmId);
            assert Arrays.equals(sessionId.drmId(), drmId);

            SessionInfo sessionInfo = mSessionManager.get(sessionId);

            // If persistent license (KEY_TYPE_OFFLINE) is released but we don't receive the ack
            // from the server, we should avoid restoring the keys. Report success to JS so that
            // they can release it again.
            if (sessionInfo.keyType() == MediaDrm.KEY_TYPE_RELEASE) {
                Log.w(TAG, "Persistent license is waiting for release ack.");
                onPromiseResolvedWithSession(promiseId, sessionId);

                // Report keystatuseschange event to JS. Ideally we should report the event with
                // list of known key IDs. However we can't get the key IDs from MediaDrm. Just
                // report with dummy key IDs.
                onSessionKeysChange(sessionId,
                        getDummyKeysInfo(MediaDrm.KeyStatus.STATUS_EXPIRED).toArray(),
                        false /* hasAdditionalUsableKey */, true /* isKeyRelease */);
                return;
            }

            assert sessionInfo.keyType() == MediaDrm.KEY_TYPE_OFFLINE;

            // Defer event handlers until license is loaded.
            assert mSessionEventDeferrer == null;
            mSessionEventDeferrer = new SessionEventDeferrer(sessionId);

            assert sessionId.keySetId() != null;
            mMediaDrm.restoreKeys(sessionId.drmId(), sessionId.keySetId());

            onPromiseResolvedWithSession(promiseId, sessionId);

            mSessionEventDeferrer.fire();
            mSessionEventDeferrer = null;
        } catch (android.media.NotProvisionedException e) {
            // If device isn't provisioned, storage loading should fail.
            Log.w(TAG, "Persistent license load fail because origin isn't provisioned.");
            onPersistentLicenseLoadFail(sessionId, promiseId);
        } catch (java.lang.IllegalStateException e) {
            assert sessionId.drmId() != null;
            onPersistentLicenseLoadFail(sessionId, promiseId);
        }
    }

    private void onPersistentLicenseNoExist(long promiseId) {
        // Chromium CDM API requires resolve the promise with empty session id for non-exist
        // license. See media/base/content_decryption_module.h LoadSession for more details.
        onPromiseResolvedWithSession(promiseId, SessionId.createNoExistSessionId());
    }

    // If persistent license load fails, we want to clean the storage and report it to JS as license
    // doesn't exist.
    private void onPersistentLicenseLoadFail(SessionId sessionId, final long promiseId) {
        closeSessionNoException(sessionId);
        mSessionManager.clearPersistentSessionInfo(sessionId, new Callback<Boolean>() {
            @Override
            public void onResult(Boolean success) {
                if (!success) {
                    Log.w(TAG, "Failed to clear persistent storage for non-exist license");
                }

                onPersistentLicenseNoExist(promiseId);
            }
        });
    }

    /**
     * Remove session from device. This will mark the key as released and
     * generate a key release request. The license is removed from the device
     * when the session is updated with a license release response.
     */
    @CalledByNative
    private void removeSession(byte[] emeId, final long promiseId) {
        Log.d(TAG, "removeSession()");
        SessionId sessionId = getSessionIdByEmeId(emeId);

        if (sessionId == null) {
            onPromiseRejected(promiseId, "Session doesn't exist");
            return;
        }

        final SessionInfo sessionInfo = mSessionManager.get(sessionId);
        if (sessionInfo.keyType() == MediaDrm.KEY_TYPE_STREAMING) {
            // TODO(yucliu): Support 'remove' of temporary session.
            onPromiseRejected(promiseId, "Removing temporary session isn't implemented");
            return;
        }

        assert sessionId.keySetId() != null;

        // Persist the key type before removing the keys completely.
        // 1. If we fails to persist the key type, both the persistent storage and MediaDrm think
        // the keys are alive. JS can just remove the session again.
        // 2. If we are able to persist the key type but don't get the callback, persistent storage
        // thinks keys are removed but MediaDrm thinks keys are alive. JS thinks keys are removed
        // next time it loads the keys, which matches the expectation of this function.
        mSessionManager.setKeyType(sessionId, MediaDrm.KEY_TYPE_RELEASE, new Callback<Boolean>() {
            @Override
            public void onResult(Boolean success) {
                if (!success) {
                    onPromiseRejected(promiseId, "Fail to update persistent storage");
                    return;
                }

                doRemoveSession(sessionId, sessionInfo.mimeType(), promiseId);
            }
        });
    }

    private void doRemoveSession(SessionId sessionId, String mimeType, long promiseId) {
        try {
            // Get key release request.
            MediaDrm.KeyRequest request =
                    getKeyRequest(sessionId, null, mimeType, MediaDrm.KEY_TYPE_RELEASE, null);

            if (request == null) {
                onPromiseRejected(promiseId, "Fail to generate key release request");
                return;
            }

            // According to EME spec:
            // https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-remove
            // 5.5 ... run the Queue a "message" Event ...
            // 5.6 Resolve promise
            // Since event is queued, JS will receive event after promise is
            // resolved. So resolve the promise before firing the event here.
            onPromiseResolved(promiseId);
            onSessionMessage(sessionId, request);
        } catch (android.media.NotProvisionedException e) {
            Log.e(TAG, "removeSession called on unprovisioned device");
            onPromiseRejected(promiseId, "Unknown failure");
        }
    }

    /**
     * Return the security level of this DRM object. In case of failure this
     * returns the empty string, which is treated by the native side as
     * "DEFAULT".
     * TODO(jrummell): Revisit this in the future if the security level gets
     * used for more things.
     */
    @CalledByNative
    private String getSecurityLevel() {
        if (mMediaDrm == null || !isWidevine()) {
            Log.e(TAG, "getSecurityLevel(): MediaDrm is null or security level is not supported.");
            return "";
        }

        // Any failure in getPropertyString() means we don't know what the current security level
        // is.
        try {
            return mMediaDrm.getPropertyString(SECURITY_LEVEL);
        } catch (java.lang.IllegalStateException e) {
            // getPropertyString() may fail with android.media.MediaDrmResetException or
            // android.media.MediaDrm.MediaDrmStateException. As MediaDrmStateException was added in
            // API 21, we can't use it directly. However, both of these are IllegalStateExceptions,
            // so both will be handled here.
            Log.e(TAG, "Failed to get current security level", e);
            return "";
        } catch (Exception e) {
            // getPropertyString() has been failing with android.media.ResourceBusyException on some
            // devices. ResourceBusyException is not mentioned as a possible exception nor a runtime
            // exception and thus can not be listed, so catching all exceptions to handle it here.
            Log.e(TAG, "Failed to get current security level", e);
            return "";
        }
    }

    /**
     * Start provisioning. Returns true if a provisioning request can be
     * generated and has been forwarded to C++ code for handling, false
     * otherwise.
     */
    private boolean startProvisioning() {
        Log.d(TAG, "startProvisioning");
        assert !mProvisioningPending;
        mProvisioningPending = true;
        assert mMediaDrm != null;

        if (!isNativeMediaDrmBridgeValid()) {
            return false;
        }

        if (mRequiresMediaCrypto) {
            sMediaCryptoDeferrer.onProvisionStarted();
        }

        // getProvisionRequest() may fail with android.media.MediaDrm.MediaDrmStateException or
        // android.media.MediaDrmResetException, both of which extend IllegalStateException. As
        // these specific exceptions are only available in API 21 and 23 respectively, using the
        // base exception so that this will work for all API versions.
        MediaDrm.ProvisionRequest request;
        try {
            request = mMediaDrm.getProvisionRequest();
        } catch (java.lang.IllegalStateException e) {
            Log.e(TAG, "Failed to get provisioning request", e);
            return false;
        }

        Log.i(TAG, "Provisioning origin ID %s", mOriginSet ? mOrigin : "<none>");
        MediaDrmBridgeJni.get().onProvisionRequest(mNativeMediaDrmBridge, MediaDrmBridge.this,
                request.getDefaultUrl(), request.getData());
        return true;
    }

    /**
     * Called when the provision response is received.
     *
     * @param isResponseReceived Flag set to true if communication with
     * provision server was successful.
     * @param response Response data from the provision server.
     */
    @CalledByNative
    private void processProvisionResponse(boolean isResponseReceived, byte[] response) {
        Log.d(TAG, "processProvisionResponse()");
        assert mMediaCryptoSession == null;

        assert mProvisioningPending;
        mProvisioningPending = false;

        boolean success = false;

        // If |mMediaDrm| is released, there is no need to callback native.
        if (mMediaDrm != null) {
            success = isResponseReceived ? provideProvisionResponse(response) : false;
        }

        // This may call release() internally. However, sMediaCryptoDeferrer.onProvisionDone() will
        // still be called below to ensure provisioning failure here doesn't block other
        // MediaDrmBridge instances from proceeding.
        onProvisioned(success);

        if (mRequiresMediaCrypto) {
            sMediaCryptoDeferrer.onProvisionDone();
        }
    }

    /**
     * Provides the provision response to MediaDrm.
     *
     * @returns false if the response is invalid or on error, true otherwise.
     */
    boolean provideProvisionResponse(byte[] response) {
        if (response == null || response.length == 0) {
            Log.e(TAG, "Invalid provision response.");
            return false;
        }

        try {
            mMediaDrm.provideProvisionResponse(response);
            return true;
        } catch (android.media.DeniedByServerException e) {
            Log.e(TAG, "failed to provide provision response", e);
        } catch (java.lang.IllegalStateException e) {
            Log.e(TAG, "failed to provide provision response", e);
        }
        return false;
    }

    /*
     *  Provisioning complete. Continue to createMediaCrypto() if required.
     *
     * @param success Whether provisioning has succeeded or not.
     */
    void onProvisioned(boolean success) {
        if (!mRequiresMediaCrypto) {
            // No MediaCrypto required, so notify provisioning complete.
            MediaDrmBridgeJni.get().onProvisioningComplete(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, success);
            if (!success) {
                release();
            }
            return;
        }

        if (!success) {
            release();
            return;
        }

        if (!mOriginSet) {
            createMediaCrypto();
            return;
        }

        // When |mOriginSet|, notify the storage onProvisioned, and continue
        // creating MediaCrypto after that.
        mStorage.onProvisioned(new Callback<Boolean>() {
            @Override
            public void onResult(Boolean initSuccess) {
                assert mMediaCryptoSession == null;

                if (!initSuccess) {
                    Log.e(TAG, "Failed to initialize storage for origin");
                    release();
                    return;
                }

                createMediaCrypto();
            }
        });
    }

    /**
     * Delay session event handler if |mSessionEventDeferrer| exists and
     * matches |sessionId|. Otherwise run the handler immediately.
     */
    private void deferEventHandleIfNeeded(SessionId sessionId, Runnable handler) {
        if (mSessionEventDeferrer != null && mSessionEventDeferrer.shouldDefer(sessionId)) {
            mSessionEventDeferrer.defer(handler);
            return;
        }

        handler.run();
    }

    // Helper functions to make native calls.

    private void onMediaCryptoReady(MediaCrypto mediaCrypto) {
        if (isNativeMediaDrmBridgeValid()) {
            MediaDrmBridgeJni.get().onMediaCryptoReady(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, mediaCrypto);
        }
    }

    private void onPromiseResolved(final long promiseId) {
        if (isNativeMediaDrmBridgeValid()) {
            MediaDrmBridgeJni.get().onPromiseResolved(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, promiseId);
        }
    }

    private void onPromiseResolvedWithSession(final long promiseId, final SessionId sessionId) {
        if (isNativeMediaDrmBridgeValid()) {
            MediaDrmBridgeJni.get().onPromiseResolvedWithSession(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, promiseId, sessionId.emeId());
        }
    }

    private void onPromiseRejected(final long promiseId, final String errorMessage) {
        Log.e(TAG, "onPromiseRejected: %s", errorMessage);
        if (isNativeMediaDrmBridgeValid()) {
            MediaDrmBridgeJni.get().onPromiseRejected(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, promiseId, errorMessage);
        }
    }

    @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;
        }

        MediaDrmBridgeJni.get().onSessionMessage(mNativeMediaDrmBridge, MediaDrmBridge.this,
                sessionId.emeId(), requestType, request.getData());
    }

    private void onSessionClosed(final SessionId sessionId) {
        if (isNativeMediaDrmBridgeValid()) {
            MediaDrmBridgeJni.get().onSessionClosed(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, sessionId.emeId());
        }
    }

    private void onSessionKeysChange(final SessionId sessionId, final Object[] keysInfo,
            final boolean hasAdditionalUsableKey, final boolean isKeyRelease) {
        if (isNativeMediaDrmBridgeValid()) {
            MediaDrmBridgeJni.get().onSessionKeysChange(mNativeMediaDrmBridge, MediaDrmBridge.this,
                    sessionId.emeId(), keysInfo, hasAdditionalUsableKey, isKeyRelease);
        }
    }

    private void onSessionExpirationUpdate(final SessionId sessionId, final long expirationTime) {
        if (isNativeMediaDrmBridgeValid()) {
            MediaDrmBridgeJni.get().onSessionExpirationUpdate(
                    mNativeMediaDrmBridge, MediaDrmBridge.this, sessionId.emeId(), expirationTime);
        }
    }

    private class EventListener implements MediaDrm.OnEventListener {
        @Override
        public void onEvent(
                MediaDrm mediaDrm, byte[] drmSessionId, int event, int extra, byte[] data) {
            if (drmSessionId == null) {
                Log.e(TAG, "EventListener: No session for event %d.", event);
                return;
            }
            SessionId sessionId = getSessionIdByDrmId(drmSessionId);

            if (sessionId == null) {
                Log.e(TAG, "EventListener: Invalid session %s",
                        SessionId.toHexString(drmSessionId));
                return;
            }

            SessionInfo sessionInfo = mSessionManager.get(sessionId);
            switch (event) {
                case MediaDrm.EVENT_KEY_REQUIRED:
                    Log.d(TAG, "MediaDrm.EVENT_KEY_REQUIRED");
                    MediaDrm.KeyRequest request = null;
                    try {
                        request = getKeyRequest(sessionId, data, sessionInfo.mimeType(),
                                sessionInfo.keyType(), null);
                    } catch (android.media.NotProvisionedException e) {
                        Log.e(TAG, "Device not provisioned", e);
                        return;
                    }
                    if (request != null) {
                        onSessionMessage(sessionId, request);
                    } else {
                        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                            onSessionKeysChange(sessionId,
                                    getDummyKeysInfo(MediaDrm.KeyStatus.STATUS_INTERNAL_ERROR)
                                            .toArray(),
                                    false, false);
                        }
                        Log.e(TAG, "EventListener: getKeyRequest failed.");
                        return;
                    }
                    break;
                case MediaDrm.EVENT_KEY_EXPIRED:
                    Log.d(TAG, "MediaDrm.EVENT_KEY_EXPIRED");
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                        onSessionKeysChange(sessionId,
                                getDummyKeysInfo(MediaDrm.KeyStatus.STATUS_EXPIRED).toArray(),
                                false, sessionInfo.keyType() == MediaDrm.KEY_TYPE_RELEASE);
                    }
                    break;
                case MediaDrm.EVENT_VENDOR_DEFINED:
                    Log.d(TAG, "MediaDrm.EVENT_VENDOR_DEFINED");
                    assert false; // Should never happen.
                    break;
                default:
                    Log.e(TAG, "Invalid DRM event " + event);
                    return;
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    private class KeyStatusChangeListener implements MediaDrm.OnKeyStatusChangeListener {
        private List<KeyStatus> getKeysInfo(List<MediaDrm.KeyStatus> keyInformation) {
            List<KeyStatus> keysInfo = new ArrayList<KeyStatus>();
            for (MediaDrm.KeyStatus keyStatus : keyInformation) {
                keysInfo.add(new KeyStatus(keyStatus.getKeyId(), keyStatus.getStatusCode()));
            }
            return keysInfo;
        }

        @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);
                }
            });
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    private class ExpirationUpdateListener implements MediaDrm.OnExpirationUpdateListener {
        @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);
                }
            });
        }
    }

    private class KeyUpdatedCallback implements Callback<Boolean> {
        private final SessionId mSessionId;
        private final long mPromiseId;
        private final boolean mIsKeyRelease;

        KeyUpdatedCallback(SessionId sessionId, long promiseId, boolean isKeyRelease) {
            mSessionId = sessionId;
            mPromiseId = promiseId;
            mIsKeyRelease = isKeyRelease;
        }

        @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);
            }
        }
    }

    // At the native side, must post the task immediately to avoid reentrancy issues.
    @NativeMethods
    interface Natives {
        void onMediaCryptoReady(
                long nativeMediaDrmBridge, MediaDrmBridge caller, MediaCrypto mediaCrypto);

        void onProvisionRequest(long nativeMediaDrmBridge, MediaDrmBridge caller, String defaultUrl,
                byte[] requestData);
        void onProvisioningComplete(
                long nativeMediaDrmBridge, MediaDrmBridge caller, boolean success);

        void onPromiseResolved(long nativeMediaDrmBridge, MediaDrmBridge caller, long promiseId);
        void onPromiseResolvedWithSession(long nativeMediaDrmBridge, MediaDrmBridge caller,
                long promiseId, byte[] emeSessionId);
        void onPromiseRejected(long nativeMediaDrmBridge, MediaDrmBridge caller, long promiseId,
                String errorMessage);

        void onSessionMessage(long nativeMediaDrmBridge, MediaDrmBridge caller, byte[] emeSessionId,
                int requestType, byte[] message);
        void onSessionClosed(long nativeMediaDrmBridge, MediaDrmBridge caller, byte[] emeSessionId);
        void onSessionKeysChange(long nativeMediaDrmBridge, MediaDrmBridge caller,
                byte[] emeSessionId, Object[] keysInfo, boolean hasAdditionalUsableKey,
                boolean isKeyRelease);
        void onSessionExpirationUpdate(long nativeMediaDrmBridge, MediaDrmBridge caller,
                byte[] emeSessionId, long expirationTime);
    }
}
