Android APIs
public final class

MediaDrm

extends Object
java.lang.Object
   ↳ android.media.MediaDrm

Class Overview

MediaDrm can be used to obtain keys for decrypting protected media streams, in conjunction with 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 MediaExtractor and 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 isCryptoSchemeSupported(UUID) can be used to query if a given scheme is supported on the device.

The app calls 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 configure(MediaFormat, Surface, MediaCrypto, int) method to enable the codec to decrypt content.

When the app has constructed MediaExtractor, MediaCodec and 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.

MediaDrm methods throw MediaDrm.MediaDrmStateException when a method is called on a MediaDrm object that has had an unrecoverable failure in the DRM plugin or security hardware. MediaDrm.MediaDrmStateException extends IllegalStateException with the addition of a developer-readable diagnostic information string associated with the exception.

In the event of a mediaserver process crash or restart while a MediaDrm object is active, MediaDrm methods may throw MediaDrmResetException. To recover, the app must release the MediaDrm object, then create and initialize a new one.

As MediaDrmResetException and MediaDrm.MediaDrmStateException both extend IllegalStateException, they should be in an earlier catch() block than IllegalStateException if handled separately.

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 setOnEventListener(MediaDrm.OnEventListener). 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).

Summary

Nested Classes
class MediaDrm.CryptoSession In addition to supporting decryption of DASH Common Encrypted Media, the MediaDrm APIs provide the ability to securely deliver session keys from an operator's session key server to a client device, based on the factory-installed root of trust, and then perform encrypt, decrypt, sign and verify operations with the session key on arbitrary user data. 
class MediaDrm.KeyRequest Contains the opaque data an app uses to request keys from a license server  
class MediaDrm.KeyStatus Defines the status of a key. 
class MediaDrm.MediaDrmStateException Thrown when an unrecoverable failure occurs during a MediaDrm operation. 
interface MediaDrm.OnEventListener Interface definition for a callback to be invoked when a drm event occurs  
interface MediaDrm.OnExpirationUpdateListener Interface definition for a callback to be invoked when a drm session expiration update occurs  
interface MediaDrm.OnKeyStatusChangeListener Interface definition for a callback to be invoked when the keys in a drm session change states. 
class MediaDrm.ProvisionRequest Contains the opaque data an app uses to request a certificate from a provisioning server  
Constants
int EVENT_KEY_EXPIRED This event type indicates that the licensed usage duration for keys in a session has expired.
int EVENT_KEY_REQUIRED This event type indicates that the app needs to request keys from a license server.
int EVENT_PROVISION_REQUIRED This constant was deprecated in API level 23. Handle provisioning via NotProvisionedException instead.
int EVENT_SESSION_RECLAIMED This event indicates that a session opened by the app has been reclaimed by the resource manager.
int EVENT_VENDOR_DEFINED This event may indicate some specific vendor-defined condition, see your DRM provider documentation for details
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.
int KEY_TYPE_RELEASE This key request type specifies that previously saved offline keys should be released.
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.
String PROPERTY_ALGORITHMS String property name: a comma-separated list of cipher and mac algorithms supported by CryptoSession.
String PROPERTY_DESCRIPTION String property name: describes the DRM engine plugin
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.
String PROPERTY_VENDOR String property name: identifies the maker of the DRM engine plugin
String PROPERTY_VERSION String property name: identifies the version of the DRM engine plugin
Public Constructors
MediaDrm(UUID uuid)
Instantiate a MediaDrm object
Public Methods
void closeSession(byte[] sessionId)
Close a session on the MediaDrm object that was previously opened with openSession().
MediaDrm.CryptoSession getCryptoSession(byte[] sessionId, String cipherAlgorithm, 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 getKeyRequest(byte[], byte[], String, int, HashMap) and provideKeyResponse(byte[], byte[]) using a session key server.
MediaDrm.KeyRequest getKeyRequest(byte[] scope, byte[] init, String mimeType, int keyType, HashMap<StringString> optionalParameters)
A key request/response exchange occurs between the app and a license server to obtain or release keys used to decrypt encrypted content.
byte[] getPropertyByteArray(String propertyName)
Read a DRM engine plugin byte array property value, given the property name string.
String getPropertyString(String propertyName)
Read a DRM engine plugin String property value, given the property name string.
MediaDrm.ProvisionRequest getProvisionRequest()
A provision request/response exchange occurs between the app and a provisioning server to retrieve a device certificate.
byte[] getSecureStop(byte[] ssid)
Access secure stop by secure stop ID.
List<byte[]> getSecureStops()
A means of enforcing limits on the number of concurrent streams per subscriber across devices is provided via SecureStop.
final static boolean isCryptoSchemeSupported(UUID uuid)
Query if the given scheme identified by its UUID is supported on this device.
final static boolean isCryptoSchemeSupported(UUID uuid, 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.
byte[] openSession()
Open a new session with the MediaDrm object.
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.
void provideProvisionResponse(byte[] response)
After a provision response is received by the app, it is provided to the DRM engine plugin using this method.
HashMap<StringString> queryKeyStatus(byte[] sessionId)
Request an informative description of the key status for the session.
final void release()
void releaseAllSecureStops()
Remove all secure stops without requiring interaction with the server.
void releaseSecureStops(byte[] ssRelease)
Process the SecureStop server response message ssRelease.
void removeKeys(byte[] sessionId)
Remove the current keys from a session.
void restoreKeys(byte[] sessionId, byte[] keySetId)
Restore persisted offline keys into a new session.
void setOnEventListener(MediaDrm.OnEventListener listener)
Register a callback to be invoked when an event occurs
void setOnExpirationUpdateListener(MediaDrm.OnExpirationUpdateListener listener, Handler handler)
Register a callback to be invoked when a session expiration update occurs.
void setOnKeyStatusChangeListener(MediaDrm.OnKeyStatusChangeListener listener, Handler handler)
Register a callback to be invoked when the state of keys in a session change, e.g.
void setPropertyByteArray(String propertyName, byte[] value)
Set a DRM engine plugin byte array property value.
void setPropertyString(String propertyName, String value)
Set a DRM engine plugin String property value.
Protected Methods
void finalize()
Invoked when the garbage collector has detected that this instance is no longer reachable.
[Expand]
Inherited Methods
From class java.lang.Object

Constants

public static final int EVENT_KEY_EXPIRED

Added in API level 18

This event type indicates that the licensed usage duration for keys in a session has expired. The keys are no longer valid.

Constant Value: 3 (0x00000003)

public static final int EVENT_KEY_REQUIRED

Added in API level 18

This event type indicates that the app needs to request keys from a license server. The request message data is obtained using getKeyRequest(byte[], byte[], String, int, HashMap).

Constant Value: 2 (0x00000002)

public static final int EVENT_PROVISION_REQUIRED

Added in API level 18

This constant was deprecated in API level 23.
Handle provisioning via NotProvisionedException instead.

This event type indicates that the app needs to request a certificate from the provisioning server. The request message data is obtained using getProvisionRequest()

Constant Value: 1 (0x00000001)

public static final int EVENT_SESSION_RECLAIMED

Added in API level 23

This event indicates that a session opened by the app has been reclaimed by the resource manager.

Constant Value: 5 (0x00000005)

public static final int EVENT_VENDOR_DEFINED

Added in API level 18

This event may indicate some specific vendor-defined condition, see your DRM provider documentation for details

Constant Value: 4 (0x00000004)

public static final int KEY_TYPE_OFFLINE

Added in API level 18

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.

Constant Value: 2 (0x00000002)

public static final int KEY_TYPE_RELEASE

Added in API level 18

This key request type specifies that previously saved offline keys should be released.

Constant Value: 3 (0x00000003)

public static final int KEY_TYPE_STREAMING

Added in API level 18

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.

Constant Value: 1 (0x00000001)

public static final String PROPERTY_ALGORITHMS

Added in API level 18

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.

Constant Value: "algorithms"

public static final String PROPERTY_DESCRIPTION

Added in API level 18

String property name: describes the DRM engine plugin

Constant Value: "description"

public static final String PROPERTY_DEVICE_UNIQUE_ID

Added in API level 18

Byte array property name: the device unique identifier is established during device provisioning and provides a means of uniquely identifying each device.

Constant Value: "deviceUniqueId"

public static final String PROPERTY_VENDOR

Added in API level 18

String property name: identifies the maker of the DRM engine plugin

Constant Value: "vendor"

public static final String PROPERTY_VERSION

Added in API level 18

String property name: identifies the version of the DRM engine plugin

Constant Value: "version"

Public Constructors

public MediaDrm (UUID uuid)

Added in API level 18

Instantiate a MediaDrm object

Parameters
uuid UUID: The UUID of the crypto scheme.
Throws
UnsupportedSchemeException if the device does not support the specified scheme UUID

Public Methods

public void closeSession (byte[] sessionId)

Added in API level 18

Close a session on the MediaDrm object that was previously opened with openSession().

Parameters
sessionId byte

public MediaDrm.CryptoSession getCryptoSession (byte[] sessionId, String cipherAlgorithm, String macAlgorithm)

Added in API level 18

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 getKeyRequest(byte[], byte[], String, int, HashMap) and provideKeyResponse(byte[], byte[]) using a session key server.

Parameters
sessionId byte: the session ID for the session containing keys to be used for encrypt, decrypt, sign and/or verify
cipherAlgorithm String: 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".
macAlgorithm String: 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 getPropertyString(String) with the property name "algorithms".

Returns
MediaDrm.CryptoSession

public MediaDrm.KeyRequest getKeyRequest (byte[] scope, byte[] init, String mimeType, int keyType, HashMap<StringString> optionalParameters)

Added in API level 18

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 provideKeyResponse(byte[], byte[]).

Parameters
scope byte: 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.
init byte: 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.
mimeType String: identifies the mime type of the content
keyType int: 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.
optionalParameters HashMap: are included in the key request message to allow a client application to provide additional message parameters to the server. This may be null if no additional parameters are to be sent.
Returns
MediaDrm.KeyRequest
Throws
NotProvisionedException if reprovisioning is needed, due to a problem with the certifcate

public byte[] getPropertyByteArray (String propertyName)

Added in API level 18

Read a DRM engine plugin byte array property value, given the property name string.

Standard fields names are PROPERTY_DEVICE_UNIQUE_ID

Parameters
propertyName String
Returns
byte[]

public String getPropertyString (String propertyName)

Added in API level 18

Read a DRM engine plugin String property value, given the property name string.

Standard fields names are: PROPERTY_VENDOR, PROPERTY_VERSION, PROPERTY_DESCRIPTION, PROPERTY_ALGORITHMS

Parameters
propertyName String
Returns
String

public MediaDrm.ProvisionRequest getProvisionRequest ()

Added in API level 18

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.

Returns
MediaDrm.ProvisionRequest

public byte[] getSecureStop (byte[] ssid)

Added in API level 22

Access secure stop by secure stop ID.

Parameters
ssid byte: - The secure stop ID provided by the license server.
Returns
byte[]

public List<byte[]> getSecureStops ()

Added in API level 18

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().

Returns
List<byte[]>

public static final boolean isCryptoSchemeSupported (UUID uuid)

Added in API level 18

Query if the given scheme identified by its UUID is supported on this device.

Parameters
uuid UUID: The UUID of the crypto scheme.
Returns
boolean

public static final boolean isCryptoSchemeSupported (UUID uuid, String mimeType)

Added in API level 19

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.

Parameters
uuid UUID: The UUID of the crypto scheme.
mimeType String: The MIME type of the media container, e.g. "video/mp4" or "video/webm"
Returns
boolean

public byte[] openSession ()

Added in API level 18

Open a new session with the MediaDrm object. A session ID is returned.

Returns
byte[]
Throws
NotProvisionedException if provisioning is needed
ResourceBusyException if required resources are in use

public byte[] provideKeyResponse (byte[] scope, byte[] response)

Added in API level 18

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 restoreKeys(byte[], byte[]). When the response is for a streaming or release request, null is returned.

Parameters
scope byte: 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.
response byte: the byte array response from the server
Returns
byte[]
Throws
NotProvisionedException if the response indicates that reprovisioning is required
DeniedByServerException if the response indicates that the server rejected the request

public void provideProvisionResponse (byte[] response)

Added in API level 18

After a provision response is received by the app, it is provided to the DRM engine plugin using this method.

Parameters
response byte: 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

public HashMap<StringString> queryKeyStatus (byte[] sessionId)

Added in API level 18

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.

Parameters
sessionId byte: the session ID for the DRM session
Returns
HashMap<StringString>

public final void release ()

Added in API level 18

public void releaseAllSecureStops ()

Added in API level 22

Remove all secure stops without requiring interaction with the server.

public void releaseSecureStops (byte[] ssRelease)

Added in API level 18

Process the SecureStop server response message ssRelease. After authenticating the message, remove the SecureStops identified in the response.

Parameters
ssRelease byte: the server response indicating which secure stops to release

public void removeKeys (byte[] sessionId)

Added in API level 18

Remove the current keys from a session.

Parameters
sessionId byte: the session ID for the DRM session

public void restoreKeys (byte[] sessionId, byte[] keySetId)

Added in API level 18

Restore persisted offline keys into a new session. keySetId identifies the keys to load, obtained from a prior call to provideKeyResponse(byte[], byte[]).

Parameters
sessionId byte: the session ID for the DRM session
keySetId byte: identifies the saved key set to restore

public void setOnEventListener (MediaDrm.OnEventListener listener)

Added in API level 18

Register a callback to be invoked when an event occurs

Parameters
listener MediaDrm.OnEventListener: the callback that will be run. Use null to stop receiving event callbacks.

public void setOnExpirationUpdateListener (MediaDrm.OnExpirationUpdateListener listener, Handler handler)

Added in API level 23

Register a callback to be invoked when a session expiration update occurs. The app's OnExpirationUpdateListener will be notified when the expiration time of the keys in the session have changed.

Parameters
listener MediaDrm.OnExpirationUpdateListener: the callback that will be run, or null to unregister the previously registered callback.
handler Handler: the handler on which the listener should be invoked, or null if the listener should be invoked on the calling thread's looper.

public void setOnKeyStatusChangeListener (MediaDrm.OnKeyStatusChangeListener listener, Handler handler)

Added in API level 23

Register a callback to be invoked when the state of keys in a session change, e.g. when a license update occurs or when a license expires.

Parameters
listener MediaDrm.OnKeyStatusChangeListener: the callback that will be run when key status changes, or null to unregister the previously registered callback.
handler Handler: the handler on which the listener should be invoked, or null if the listener should be invoked on the calling thread's looper.

public void setPropertyByteArray (String propertyName, byte[] value)

Added in API level 18

Set a DRM engine plugin byte array property value.

Parameters
propertyName String
value byte

public void setPropertyString (String propertyName, String value)

Added in API level 18

Set a DRM engine plugin String property value.

Parameters
propertyName String
value String

Protected Methods

protected void finalize ()

Added in API level 18

Invoked when the garbage collector has detected that this instance is no longer reachable. The default implementation does nothing, but this method can be overridden to free resources.

Note that objects that override finalize are significantly more expensive than objects that don't. Finalizers may be run a long time after the object is no longer reachable, depending on memory pressure, so it's a bad idea to rely on them for cleanup. Note also that finalizers are run on a single VM-wide finalizer thread, so doing blocking work in a finalizer is a bad idea. A finalizer is usually only necessary for a class that has a native peer and needs to call a native method to destroy that peer. Even then, it's better to provide an explicit close method (and implement Closeable), and insist that callers manually dispose of instances. This works well for something like files, but less well for something like a BigInteger where typical calling code would have to deal with lots of temporaries. Unfortunately, code that creates lots of temporaries is the worst kind of code from the point of view of the single finalizer thread.

If you must use finalizers, consider at least providing your own ReferenceQueue and having your own thread process that queue.

Unlike constructors, finalizers are not automatically chained. You are responsible for calling super.finalize() yourself.

Uncaught exceptions thrown by finalizers are ignored and do not terminate the finalizer thread. See Effective Java Item 7, "Avoid finalizers" for more.