FileDocCategorySizeDatePackage
MediaDrm.javaAPI DocAndroid 5.1 API35485Thu Mar 12 22:22:30 GMT 2015android.media

MediaDrm

public final class MediaDrm extends Object
MediaDrm can be used to obtain keys for decrypting protected media streams, in conjunction with {@link android.media.MediaCrypto}. The MediaDrm APIs are designed to support the ISO/IEC 23001-7: Common Encryption standard, but may also be used to implement other encryption schemes.

Encrypted content is prepared using an encryption server and stored in a content library. The encrypted content is streamed or downloaded from the content library to client devices via content servers. Licenses to view the content are obtained from a License Server.

MediaDrm Overview diagram

Keys are requested from the license server using a key request. The key response is delivered to the client app, which provides the response to the MediaDrm API.

A Provisioning server may be required to distribute device-unique credentials to the devices.

Enforcing requirements related to the number of devices that may play content simultaneously can be performed either through key renewal or using the secure stop methods.

The following sequence diagram shows the interactions between the objects involved while playing back encrypted content:

MediaDrm Overview diagram

The app first constructs {@link android.media.MediaExtractor} and {@link android.media.MediaCodec} objects. It accesses the DRM-scheme-identifying UUID, typically from metadata in the content, and uses this UUID to construct an instance of a MediaDrm object that is able to support the DRM scheme required by the content. Crypto schemes are assigned 16 byte UUIDs. The method {@link #isCryptoSchemeSupported} can be used to query if a given scheme is supported on the device.

The app calls {@link #openSession} to generate a sessionId that will uniquely identify the session in subsequent interactions. The app next uses the MediaDrm object to obtain a key request message and send it to the license server, then provide the server's response to the MediaDrm object.

Once the app has a sessionId, it can construct a MediaCrypto object from the UUID and sessionId. The MediaCrypto object is registered with the MediaCodec in the {@link MediaCodec.#configure} method to enable the codec to decrypt content.

When the app has constructed {@link android.media.MediaExtractor}, {@link android.media.MediaCodec} and {@link android.media.MediaCrypto} objects, it proceeds to pull samples from the extractor and queue them into the decoder. For encrypted content, the samples returned from the extractor remain encrypted, they are only decrypted when the samples are delivered to the decoder.

Callbacks

Applications should register for informational events in order to be informed of key state updates during playback or streaming. Registration for these events is done via a call to {@link #setOnEventListener}. In order to receive the respective callback associated with this listener, applications are required to create MediaDrm objects on a thread with its own Looper running (main UI thread by default has a Looper running).

Fields Summary
private static final String
TAG
private static final String
PERMISSION
private EventHandler
mEventHandler
private OnEventListener
mOnEventListener
private long
mNativeContext
public static final int
CERTIFICATE_TYPE_NONE
Specify no certificate type
public static final int
CERTIFICATE_TYPE_X509
Specify X.509 certificate type
public static final int
EVENT_PROVISION_REQUIRED
This event type indicates that the app needs to request a certificate from the provisioning server. The request message data is obtained using {@link #getProvisionRequest}
public static final int
EVENT_KEY_REQUIRED
This event type indicates that the app needs to request keys from a license server. The request message data is obtained using {@link #getKeyRequest}.
public static final int
EVENT_KEY_EXPIRED
This event type indicates that the licensed usage duration for keys in a session has expired. The keys are no longer valid.
public static final int
EVENT_VENDOR_DEFINED
This event may indicate some specific vendor-defined condition, see your DRM provider documentation for details
private static final int
DRM_EVENT
public static final int
KEY_TYPE_STREAMING
This key request type species that the keys will be for online use, they will not be saved to the device for subsequent use when the device is not connected to a network.
public static final int
KEY_TYPE_OFFLINE
This key request type specifies that the keys will be for offline use, they will be saved to the device for use when the device is not connected to a network.
public static final int
KEY_TYPE_RELEASE
This key request type specifies that previously saved offline keys should be released.
public static final String
PROPERTY_VENDOR
String property name: identifies the maker of the DRM engine plugin
public static final String
PROPERTY_VERSION
String property name: identifies the version of the DRM engine plugin
public static final String
PROPERTY_DESCRIPTION
String property name: describes the DRM engine plugin
public static final String
PROPERTY_ALGORITHMS
String property name: a comma-separated list of cipher and mac algorithms supported by CryptoSession. The list may be empty if the DRM engine plugin does not support CryptoSession operations.
public static final String
PROPERTY_DEVICE_UNIQUE_ID
Byte array property name: the device unique identifier is established during device provisioning and provides a means of uniquely identifying each device.
Constructors Summary
public MediaDrm(UUID uuid)
Instantiate a MediaDrm object

param
uuid The UUID of the crypto scheme.
throws
UnsupportedSchemeException if the device does not support the specified scheme UUID

        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else if ((looper = Looper.getMainLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else {
            mEventHandler = null;
        }

        /* Native setup requires a weak reference to our object.
         * It's easier to create it here than in C++.
         */
        native_setup(new WeakReference<MediaDrm>(this),
                getByteArrayFromUUID(uuid));
    
Methods Summary
public native voidcloseSession(byte[] sessionId)
Close a session on the MediaDrm object that was previously opened with {@link #openSession}.

private static final native byte[]decryptNative(android.media.MediaDrm drm, byte[] sessionId, byte[] keyId, byte[] input, byte[] iv)

private static final native byte[]encryptNative(android.media.MediaDrm drm, byte[] sessionId, byte[] keyId, byte[] input, byte[] iv)

protected voidfinalize()

        native_finalize();
    
private static final byte[]getByteArrayFromUUID(java.util.UUID uuid)

        long msb = uuid.getMostSignificantBits();
        long lsb = uuid.getLeastSignificantBits();

        byte[] uuidBytes = new byte[16];
        for (int i = 0; i < 8; ++i) {
            uuidBytes[i] = (byte)(msb >>> (8 * (7 - i)));
            uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i)));
        }

        return uuidBytes;
    
public android.media.MediaDrm$CertificateRequestgetCertificateRequest(int certType, java.lang.String certAuthority)
Generate a certificate request, specifying the certificate type and authority. The response received should be passed to provideCertificateResponse.

param
certType Specifies the certificate type.
param
certAuthority is passed to the certificate server to specify the chain of authority.
hide
- not part of the public API at this time

        ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
        return new CertificateRequest(provisionRequest.getData(),
                provisionRequest.getDefaultUrl());
    
public android.media.MediaDrm$CryptoSessiongetCryptoSession(byte[] sessionId, java.lang.String cipherAlgorithm, java.lang.String macAlgorithm)
Obtain a CryptoSession object which can be used to encrypt, decrypt, sign and verify messages or data using the session keys established for the session using methods {@link #getKeyRequest} and {@link #provideKeyResponse} using a session key server.

param
sessionId the session ID for the session containing keys to be used for encrypt, decrypt, sign and/or verify
param
cipherAlgorithm the algorithm to use for encryption and decryption ciphers. The algorithm string conforms to JCA Standard Names for Cipher Transforms and is case insensitive. For example "AES/CBC/NoPadding".
param
macAlgorithm the algorithm to use for sign and verify The algorithm string conforms to JCA Standard Names for Mac Algorithms and is case insensitive. For example "HmacSHA256".

The list of supported algorithms for a DRM engine plugin can be obtained using the method {@link #getPropertyString} with the property name "algorithms".

        return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
    
public native android.media.MediaDrm$KeyRequestgetKeyRequest(byte[] scope, byte[] init, java.lang.String mimeType, int keyType, java.util.HashMap optionalParameters)
A key request/response exchange occurs between the app and a license server to obtain or release keys used to decrypt encrypted content.

getKeyRequest() is used to obtain an opaque key request byte array that is delivered to the license server. The opaque key request byte array is returned in KeyRequest.data. The recommended URL to deliver the key request to is returned in KeyRequest.defaultUrl.

After the app has received the key request response from the server, it should deliver to the response to the DRM engine plugin using the method {@link #provideKeyResponse}.

param
scope may be a sessionId or a keySetId, depending on the specified keyType. When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, scope should be set to the sessionId the keys will be provided to. When the keyType is KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys being released. Releasing keys from a device invalidates them for all sessions.
param
init container-specific data, its meaning is interpreted based on the mime type provided in the mimeType parameter. It could contain, for example, the content ID, key ID or other data obtained from the content metadata that is required in generating the key request. init may be null when keyType is KEY_TYPE_RELEASE.
param
mimeType identifies the mime type of the content
param
keyType specifes the type of the request. The request may be to acquire keys for streaming or offline content, or to release previously acquired keys, which are identified by a keySetId.
param
optionalParameters are included in the key request message to allow a client application to provide additional message parameters to the server.
throws
NotProvisionedException if reprovisioning is needed, due to a problem with the certifcate

public native byte[]getPropertyByteArray(java.lang.String propertyName)
Read a DRM engine plugin byte array property value, given the property name string.

Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID}

public native java.lang.StringgetPropertyString(java.lang.String propertyName)
Read a DRM engine plugin String property value, given the property name string.

Standard fields names are: {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION}, {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS}

public android.media.MediaDrm$ProvisionRequestgetProvisionRequest()
A provision request/response exchange occurs between the app and a provisioning server to retrieve a device certificate. If provisionining is required, the EVENT_PROVISION_REQUIRED event will be sent to the event handler. getProvisionRequest is used to obtain the opaque provision request byte array that should be delivered to the provisioning server. The provision request byte array is returned in ProvisionRequest.data. The recommended URL to deliver the provision request to is returned in ProvisionRequest.defaultUrl.

        return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, "");
    
private native android.media.MediaDrm$ProvisionRequestgetProvisionRequestNative(int certType, java.lang.String certAuthority)

public native byte[]getSecureStop(byte[] ssid)
Access secure stop by secure stop ID.

param
ssid - The secure stop ID provided by the license server.

public native java.util.ListgetSecureStops()
A means of enforcing limits on the number of concurrent streams per subscriber across devices is provided via SecureStop. This is achieved by securely monitoring the lifetime of sessions.

Information from the server related to the current playback session is written to persistent storage on the device when each MediaCrypto object is created.

In the normal case, playback will be completed, the session destroyed and the Secure Stops will be queried. The app queries secure stops and forwards the secure stop message to the server which verifies the signature and notifies the server side database that the session destruction has been confirmed. The persisted record on the client is only removed after positive confirmation that the server received the message using releaseSecureStops().

public static final booleanisCryptoSchemeSupported(java.util.UUID uuid)
Query if the given scheme identified by its UUID is supported on this device.

param
uuid The UUID of the crypto scheme.


                               
          
        return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), null);
    
public static final booleanisCryptoSchemeSupported(java.util.UUID uuid, java.lang.String mimeType)
Query if the given scheme identified by its UUID is supported on this device, and whether the drm plugin is able to handle the media container format specified by mimeType.

param
uuid The UUID of the crypto scheme.
param
mimeType The MIME type of the media container, e.g. "video/mp4" or "video/webm"

        return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType);
    
private static final native booleanisCryptoSchemeSupportedNative(byte[] uuid, java.lang.String mimeType)

private final native voidnative_finalize()

private static final native voidnative_init()

private final native voidnative_setup(java.lang.Object mediadrm_this, byte[] uuid)

public native byte[]openSession()
Open a new session with the MediaDrm object. A session ID is returned.

throws
NotProvisionedException if provisioning is needed
throws
ResourceBusyException if required resources are in use

private static voidpostEventFromNative(java.lang.Object mediadrm_ref, int eventType, int extra, java.lang.Object obj)

        MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get();
        if (md == null) {
            return;
        }
        if (md.mEventHandler != null) {
            Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj);
            md.mEventHandler.sendMessage(m);
        }
    
public android.media.MediaDrm$CertificateprovideCertificateResponse(byte[] response)
Process a response from the certificate server. The response is obtained from an HTTP Post to the url provided by getCertificateRequest.

The public X509 certificate chain and wrapped private key are returned in the returned Certificate objec. The certificate chain is in PEM format. The wrapped private key should be stored in application private storage, and used when invoking the signRSA method.

param
response the opaque certificate response byte array to provide to the DRM engine plugin.
throws
DeniedByServerException if the response indicates that the server rejected the request
hide
- not part of the public API at this time

        return provideProvisionResponseNative(response);
    
public native byte[]provideKeyResponse(byte[] scope, byte[] response)
A key response is received from the license server by the app, then it is provided to the DRM engine plugin using provideKeyResponse. When the response is for an offline key request, a keySetId is returned that can be used to later restore the keys to a new session with the method {@link #restoreKeys}. When the response is for a streaming or release request, null is returned.

param
scope may be a sessionId or keySetId depending on the type of the response. Scope should be set to the sessionId when the response is for either streaming or offline key requests. Scope should be set to the keySetId when the response is for a release request.
param
response the byte array response from the server
throws
NotProvisionedException if the response indicates that reprovisioning is required
throws
DeniedByServerException if the response indicates that the server rejected the request
throws
ResourceBusyException if required resources are in use

public voidprovideProvisionResponse(byte[] response)
After a provision response is received by the app, it is provided to the DRM engine plugin using this method.

param
response the opaque provisioning response byte array to provide to the DRM engine plugin.
throws
DeniedByServerException if the response indicates that the server rejected the request

        provideProvisionResponseNative(response);
    
private native android.media.MediaDrm$CertificateprovideProvisionResponseNative(byte[] response)

public native java.util.HashMapqueryKeyStatus(byte[] sessionId)
Request an informative description of the key status for the session. The status is in the form of {name, value} pairs. Since DRM license policies vary by vendor, the specific status field names are determined by each DRM vendor. Refer to your DRM provider documentation for definitions of the field names for a particular DRM engine plugin.

param
sessionId the session ID for the DRM session

public final native voidrelease()

public native voidreleaseAllSecureStops()
Remove all secure stops without requiring interaction with the server.

public native voidreleaseSecureStops(byte[] ssRelease)
Process the SecureStop server response message ssRelease. After authenticating the message, remove the SecureStops identified in the response.

param
ssRelease the server response indicating which secure stops to release

public native voidremoveKeys(byte[] sessionId)
Remove the current keys from a session.

param
sessionId the session ID for the DRM session

public native voidrestoreKeys(byte[] sessionId, byte[] keySetId)
Restore persisted offline keys into a new session. keySetId identifies the keys to load, obtained from a prior call to {@link #provideKeyResponse}.

param
sessionId the session ID for the DRM session
param
keySetId identifies the saved key set to restore

private static final native voidsetCipherAlgorithmNative(android.media.MediaDrm drm, byte[] sessionId, java.lang.String algorithm)

private static final native voidsetMacAlgorithmNative(android.media.MediaDrm drm, byte[] sessionId, java.lang.String algorithm)

public voidsetOnEventListener(android.media.MediaDrm$OnEventListener listener)
Register a callback to be invoked when an event occurs

param
listener the callback that will be run

        mOnEventListener = listener;
    
public native voidsetPropertyByteArray(java.lang.String propertyName, byte[] value)
Set a DRM engine plugin byte array property value.

public native voidsetPropertyString(java.lang.String propertyName, java.lang.String value)
Set a DRM engine plugin String property value.

private static final native byte[]signNative(android.media.MediaDrm drm, byte[] sessionId, byte[] keyId, byte[] message)

public byte[]signRSA(byte[] sessionId, java.lang.String algorithm, byte[] wrappedKey, byte[] message)
Sign data using an RSA key

param
sessionId a sessionId obtained from openSession on the MediaDrm object
param
algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
param
wrappedKey - the wrapped (encrypted) RSA private key obtained from provideCertificateResponse
param
message the data for which a signature is to be computed
hide
- not part of the public API at this time

        return signRSANative(this, sessionId, algorithm, wrappedKey, message);
    
private static final native byte[]signRSANative(android.media.MediaDrm drm, byte[] sessionId, java.lang.String algorithm, byte[] wrappedKey, byte[] message)

public native voidunprovisionDevice()
Remove provisioning from a device. Only system apps may unprovision a device. Note that removing provisioning will invalidate any keys saved for offline use (KEY_TYPE_OFFLINE), which may render downloaded content unplayable until new licenses are acquired. Since provisioning is global to the device, license invalidation will apply to all content downloaded by any app, so appropriate warnings should be given to the user.

hide

private static final native booleanverifyNative(android.media.MediaDrm drm, byte[] sessionId, byte[] keyId, byte[] message, byte[] signature)