public final class MediaDrm extends Object
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.
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:
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(java.util.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
MediaCodec.#configure
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.
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(android.media.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).
Modifier and Type | Class and Description |
---|---|
static interface |
MediaDrm.ArrayProperty |
static class |
MediaDrm.Certificate
Contains the wrapped private key and public certificate data associated
with a certificate.
|
static class |
MediaDrm.CertificateRequest
Contains the opaque data an app uses to request a certificate from a provisioning
server
|
static interface |
MediaDrm.CertificateType |
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.
|
static interface |
MediaDrm.DrmEvent |
static class |
MediaDrm.KeyRequest
Contains the opaque data an app uses to request keys from a license server
|
static class |
MediaDrm.KeyStatus
Defines the status of a key.
|
static interface |
MediaDrm.KeyType |
static class |
MediaDrm.MediaDrmStateException
Thrown when an unrecoverable failure occurs during a MediaDrm operation.
|
static interface |
MediaDrm.OnEventListener
Interface definition for a callback to be invoked when a drm event
occurs
|
static interface |
MediaDrm.OnExpirationUpdateListener
Interface definition for a callback to be invoked when a drm session
expiration update occurs
|
static interface |
MediaDrm.OnKeyStatusChangeListener
Interface definition for a callback to be invoked when the keys in a drm
session change states.
|
static class |
MediaDrm.ProvisionRequest
Contains the opaque data an app uses to request a certificate from a provisioning
server
|
static interface |
MediaDrm.StringProperty |
Modifier and Type | Field and Description |
---|---|
static int |
CERTIFICATE_TYPE_NONE
Specify no certificate type
|
static int |
CERTIFICATE_TYPE_X509
Specify X.509 certificate type
|
static int |
EVENT_KEY_EXPIRED
This event type indicates that the licensed usage duration for keys in a session
has expired.
|
static int |
EVENT_KEY_REQUIRED
This event type indicates that the app needs to request keys from a license
server.
|
static int |
EVENT_PROVISION_REQUIRED
Deprecated.
Handle provisioning via
NotProvisionedException
instead. |
static int |
EVENT_SESSION_RECLAIMED
This event indicates that a session opened by the app has been reclaimed by the resource
manager.
|
static int |
EVENT_VENDOR_DEFINED
This event may indicate some specific vendor-defined condition, see your
DRM provider documentation for details
|
static 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.
|
static int |
KEY_TYPE_RELEASE
This key request type specifies that previously saved offline keys should be released.
|
static 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.
|
static String |
PROPERTY_ALGORITHMS
String property name: a comma-separated list of cipher and mac algorithms
supported by CryptoSession.
|
static String |
PROPERTY_DESCRIPTION
String property name: describes the DRM engine plugin
|
static 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.
|
static String |
PROPERTY_VENDOR
String property name: identifies the maker of the DRM engine plugin
|
static String |
PROPERTY_VERSION
String property name: identifies the version of the DRM engine plugin
|
Constructor and Description |
---|
MediaDrm(UUID uuid)
Instantiate a MediaDrm object
|
Modifier and Type | Method and Description |
---|---|
void |
closeSession(byte[] sessionId)
Close a session on the MediaDrm object that was previously opened
with
openSession() . |
protected void |
finalize()
Called by the garbage collector on an object when garbage collection
determines that there are no more references to the object.
|
MediaDrm.CertificateRequest |
getCertificateRequest(int certType,
String certAuthority)
Generate a certificate request, specifying the certificate type
and authority.
|
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[], java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>) and
provideKeyResponse(byte[], byte[]) using a session key server. |
MediaDrm.KeyRequest |
getKeyRequest(byte[] scope,
byte[] init,
String mimeType,
int keyType,
HashMap<String,String> 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.
|
static boolean |
isCryptoSchemeSupported(UUID uuid)
Query if the given scheme identified by its UUID is supported on
this device.
|
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.
|
MediaDrm.Certificate |
provideCertificateResponse(byte[] response)
Process a response from the certificate server.
|
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<String,String> |
queryKeyStatus(byte[] sessionId)
Request an informative description of the key status for the session.
|
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. when a license update occurs or when a license expires.
|
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.
|
byte[] |
signRSA(byte[] sessionId,
String algorithm,
byte[] wrappedKey,
byte[] message)
Sign data using an RSA key
|
public static final int CERTIFICATE_TYPE_NONE
public static final int CERTIFICATE_TYPE_X509
public static final int EVENT_PROVISION_REQUIRED
NotProvisionedException
instead.getProvisionRequest()
public static final int EVENT_KEY_REQUIRED
getKeyRequest(byte[], byte[], java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>)
.public static final int EVENT_KEY_EXPIRED
public static final int EVENT_VENDOR_DEFINED
public static final int EVENT_SESSION_RECLAIMED
public static final int KEY_TYPE_STREAMING
public static final int KEY_TYPE_OFFLINE
public static final int KEY_TYPE_RELEASE
public static final String PROPERTY_VENDOR
public static final String PROPERTY_VERSION
public static final String PROPERTY_DESCRIPTION
public static final String PROPERTY_ALGORITHMS
public static final String PROPERTY_DEVICE_UNIQUE_ID
public MediaDrm(UUID uuid) throws UnsupportedSchemeException
uuid
- The UUID of the crypto scheme.UnsupportedSchemeException
- if the device does not support the
specified scheme UUIDpublic static final boolean isCryptoSchemeSupported(UUID uuid)
uuid
- The UUID of the crypto scheme.public static final boolean isCryptoSchemeSupported(UUID uuid, String mimeType)
uuid
- The UUID of the crypto scheme.mimeType
- The MIME type of the media container, e.g. "video/mp4"
or "video/webm"public void setOnExpirationUpdateListener(MediaDrm.OnExpirationUpdateListener listener, Handler handler)
listener
- the callback that will be run, or null
to unregister the
previously registered callback.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)
listener
- the callback that will be run when key status changes, or
null
to unregister the previously registered callback.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 setOnEventListener(MediaDrm.OnEventListener listener)
listener
- the callback that will be run. Use null
to
stop receiving event callbacks.public byte[] openSession() throws NotProvisionedException, ResourceBusyException
NotProvisionedException
- if provisioning is neededResourceBusyException
- if required resources are in usepublic void closeSession(byte[] sessionId)
openSession()
.public MediaDrm.KeyRequest getKeyRequest(byte[] scope, byte[] init, String mimeType, int keyType, HashMap<String,String> optionalParameters) throws NotProvisionedException
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[])
.
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.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.mimeType
- identifies the mime type of the contentkeyType
- 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
- 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.NotProvisionedException
- if reprovisioning is needed, due to a
problem with the certifcatepublic byte[] provideKeyResponse(byte[] scope, byte[] response) throws NotProvisionedException, DeniedByServerException
restoreKeys(byte[], byte[])
.
When the response is for a streaming or release request, null is returned.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.response
- the byte array response from the serverNotProvisionedException
- if the response indicates that
reprovisioning is requiredDeniedByServerException
- if the response indicates that the
server rejected the requestpublic void restoreKeys(byte[] sessionId, byte[] keySetId)
provideKeyResponse(byte[], byte[])
.sessionId
- the session ID for the DRM sessionkeySetId
- identifies the saved key set to restorepublic void removeKeys(byte[] sessionId)
sessionId
- the session ID for the DRM sessionpublic HashMap<String,String> queryKeyStatus(byte[] sessionId)
sessionId
- the session ID for the DRM sessionpublic MediaDrm.ProvisionRequest getProvisionRequest()
public void provideProvisionResponse(byte[] response) throws DeniedByServerException
response
- the opaque provisioning response byte array to provide to the
DRM engine plugin.DeniedByServerException
- if the response indicates that the
server rejected the requestpublic List<byte[]> getSecureStops()
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 byte[] getSecureStop(byte[] ssid)
ssid
- - The secure stop ID provided by the license server.public void releaseSecureStops(byte[] ssRelease)
ssRelease
- the server response indicating which secure stops to releasepublic void releaseAllSecureStops()
public String getPropertyString(String propertyName)
Standard fields names are:
PROPERTY_VENDOR
, PROPERTY_VERSION
,
PROPERTY_DESCRIPTION
, PROPERTY_ALGORITHMS
public byte[] getPropertyByteArray(String propertyName)
Standard fields names are PROPERTY_DEVICE_UNIQUE_ID
public void setPropertyString(String propertyName, String value)
public void setPropertyByteArray(String propertyName, byte[] value)
public MediaDrm.CryptoSession getCryptoSession(byte[] sessionId, String cipherAlgorithm, String macAlgorithm)
getKeyRequest(byte[], byte[], java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>)
and
provideKeyResponse(byte[], byte[])
using a session key server.sessionId
- the session ID for the session containing keys
to be used for encrypt, decrypt, sign and/or verifycipherAlgorithm
- 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
- 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(java.lang.String)
with the property name
"algorithms".
public MediaDrm.CertificateRequest getCertificateRequest(int certType, String certAuthority)
certType
- Specifies the certificate type.certAuthority
- is passed to the certificate server to specify
the chain of authority.public MediaDrm.Certificate provideCertificateResponse(byte[] response) throws DeniedByServerException
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.
response
- the opaque certificate response byte array to provide to the
DRM engine plugin.DeniedByServerException
- if the response indicates that the
server rejected the requestpublic byte[] signRSA(byte[] sessionId, String algorithm, byte[] wrappedKey, byte[] message)
sessionId
- a sessionId obtained from openSession on the MediaDrm objectalgorithm
- the signing algorithm to use, e.g. "PKCS1-BlockType1"wrappedKey
- - the wrapped (encrypted) RSA private key obtained
from provideCertificateResponsemessage
- the data for which a signature is to be computedprotected void finalize()
Object
finalize
method to dispose of
system resources or to perform other cleanup.
The general contract of finalize
is that it is invoked
if and when the JavaTM virtual
machine has determined that there is no longer any
means by which this object can be accessed by any thread that has
not yet died, except as a result of an action taken by the
finalization of some other object or class which is ready to be
finalized. The finalize
method may take any action, including
making this object available again to other threads; the usual purpose
of finalize
, however, is to perform cleanup actions before
the object is irrevocably discarded. For example, the finalize method
for an object that represents an input/output connection might perform
explicit I/O transactions to break the connection before the object is
permanently discarded.
The finalize
method of class Object
performs no
special action; it simply returns normally. Subclasses of
Object
may override this definition.
The Java programming language does not guarantee which thread will
invoke the finalize
method for any given object. It is
guaranteed, however, that the thread that invokes finalize will not
be holding any user-visible synchronization locks when finalize is
invoked. If an uncaught exception is thrown by the finalize method,
the exception is ignored and finalization of that object terminates.
After the finalize
method has been invoked for an object, no
further action is taken until the Java virtual machine has again
determined that there is no longer any means by which this object can
be accessed by any thread that has not yet died, including possible
actions by other objects or classes which are ready to be finalized,
at which point the object may be discarded.
The finalize
method is never invoked more than once by a Java
virtual machine for any given object.
Any exception thrown by the finalize
method causes
the finalization of this object to be halted, but is otherwise
ignored.
public final void release()