18a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker/* 28a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Copyright (C) 2013 The Android Open Source Project 38a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 48a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Licensed under the Apache License, Version 2.0 (the "License"); 58a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * you may not use this file except in compliance with the License. 68a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * You may obtain a copy of the License at 78a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 88a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * http://www.apache.org/licenses/LICENSE-2.0 98a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Unless required by applicable law or agreed to in writing, software 118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * distributed under the License is distributed on an "AS IS" BASIS, 128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * See the License for the specific language governing permissions and 148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * limitations under the License. 158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerpackage android.media; 188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.media.MediaDrmException; 208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport java.lang.ref.WeakReference; 218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport java.util.UUID; 228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport java.util.HashMap; 238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport java.util.List; 248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.os.Handler; 258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.os.Looper; 268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.os.Message; 278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.os.Bundle; 2854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkerimport android.os.Parcel; 298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.util.Log; 308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker/** 32e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * MediaDrm can be used to obtain keys for decrypting protected media streams, in 33e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * conjunction with {@link android.media.MediaCrypto}. The MediaDrm APIs 34e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * are designed to support the ISO/IEC 23001-7: Common Encryption standard, but 35e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * may also be used to implement other encryption schemes. 36e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 37e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Encrypted content is prepared using an encryption server and stored in a content 38e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * library. The encrypted content is streamed or downloaded from the content library to 39e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * client devices via content servers. Licenses to view the content are obtained from 40e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * a License Server. 41e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 42e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p><img src="../../../images/mediadrm_overview.png" 43e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * alt="MediaDrm Overview diagram" 44e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * border="0" /></p> 45e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 46e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Keys are requested from the license server using a key request. The key 47e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * response is delivered to the client app, which provides the response to the 48e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * MediaDrm API. 49e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 50e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * A Provisioning server may be required to distribute device-unique credentials to 51e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the devices. 52e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 53e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Enforcing requirements related to the number of devices that may play content 54e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * simultaneously can be performed either through key renewal or using the secure 55e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * stop methods. 56e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 57e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The following sequence diagram shows the interactions between the objects 58e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * involved while playing back encrypted content: 59e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 60e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p><img src="../../../images/mediadrm_decryption_sequence.png" 61e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * alt="MediaDrm Overview diagram" 62e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * border="0" /></p> 63e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 64e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The app first constructs {@link android.media.MediaExtractor} and 65e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link android.media.MediaCodec} objects. It accesses the DRM-scheme-identifying UUID, 66e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * typically from metadata in the content, and uses this UUID to construct an instance 67e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * of a MediaDrm object that is able to support the DRM scheme required by the content. 68e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Crypto schemes are assigned 16 byte UUIDs. The method {@link #isCryptoSchemeSupported} 69e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * can be used to query if a given scheme is supported on the device. 70e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 71e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The app calls {@link #openSession} to generate a sessionId that will uniquely identify 72e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the session in subsequent interactions. The app next uses the MediaDrm object to 73e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * obtain a key request message and send it to the license server, then provide 74e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the server's response to the MediaDrm object. 75e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 76e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Once the app has a sessionId, it can construct a MediaCrypto object from the UUID and 77e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * sessionId. The MediaCrypto object is registered with the MediaCodec in the 78e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link MediaCodec.#configure} method to enable the codec to decrypt content. 79e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 80e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * When the app has constructed {@link android.media.MediaExtractor}, 81e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link android.media.MediaCodec} and {@link android.media.MediaCrypto} objects, 82e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * it proceeds to pull samples from the extractor and queue them into the decoder. For 83e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * encrypted content, the samples returned from the extractor remain encrypted, they 84e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * are only decrypted when the samples are delivered to the decoder. 85e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * <a name="Callbacks"></a> 878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * <h3>Callbacks</h3> 88e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p>Applications should register for informational events in order 89e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to be informed of key state updates during playback or streaming. 908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Registration for these events is done via a call to 91e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #setOnEventListener}. In order to receive the respective 92e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * callback associated with this listener, applications are required to create 938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * MediaDrm objects on a thread with its own Looper running (main UI 948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * thread by default has a Looper running). 958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerpublic final class MediaDrm { 978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private final static String TAG = "MediaDrm"; 998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private EventHandler mEventHandler; 1018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private OnEventListener mOnEventListener; 1028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private int mNativeContext; 1048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 1068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Query if the given scheme identified by its UUID is supported on 1078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * this device. 1088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param uuid The UUID of the crypto scheme. 1098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public static final boolean isCryptoSchemeSupported(UUID uuid) { 1117cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), null); 1127cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker } 1137cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker 1147cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker /** 1157cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * Query if the given scheme identified by its UUID is supported on 1167cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * this device, and whether the drm plugin is able to handle the 1177cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * media container format specified by mimeType. 1187cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * @param uuid The UUID of the crypto scheme. 1197cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * @param mimeType The MIME type of the media container, e.g. "video/mp4" 1207cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * or "video/webm" 1217cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker */ 1227cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker public static final boolean isCryptoSchemeSupported(UUID uuid, String mimeType) { 1237cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType); 1248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static final byte[] getByteArrayFromUUID(UUID uuid) { 1278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker long msb = uuid.getMostSignificantBits(); 1288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker long lsb = uuid.getLeastSignificantBits(); 1298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker byte[] uuidBytes = new byte[16]; 1318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker for (int i = 0; i < 8; ++i) { 1328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker uuidBytes[i] = (byte)(msb >>> (8 * (7 - i))); 1338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i))); 1348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return uuidBytes; 1378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1397cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid, 1407cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker String mimeType); 1418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 1431d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * Instantiate a MediaDrm object 1441d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 1458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param uuid The UUID of the crypto scheme. 1461d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 1471d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws UnsupportedSchemeException if the device does not support the 1481d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * specified scheme UUID 1498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1501d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker public MediaDrm(UUID uuid) throws UnsupportedSchemeException { 1518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Looper looper; 1528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if ((looper = Looper.myLooper()) != null) { 1538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mEventHandler = new EventHandler(this, looper); 1548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } else if ((looper = Looper.getMainLooper()) != null) { 1558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mEventHandler = new EventHandler(this, looper); 1568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } else { 1578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mEventHandler = null; 1588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /* Native setup requires a weak reference to our object. 1618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * It's easier to create it here than in C++. 1628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker native_setup(new WeakReference<MediaDrm>(this), 1648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker getByteArrayFromUUID(uuid)); 1658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 1688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Register a callback to be invoked when an event occurs 1698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 1708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param listener the callback that will be run 1718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public void setOnEventListener(OnEventListener listener) 1738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 1748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mOnEventListener = listener; 1758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 1788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Interface definition for a callback to be invoked when a drm event 179e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * occurs 1808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public interface OnEventListener 1828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 1838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 1848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Called when an event occurs that requires the app to be notified 1858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 1868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param md the MediaDrm object on which the event occurred 1878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param sessionId the DRM session ID on which the event occurred 1888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param event indicates the event type 1898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param extra an secondary error code 1908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param data optional byte array of data that may be associated with the event 1918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data); 1938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 195e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 196e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event type indicates that the app needs to request a certificate from 197e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the provisioning server. The request message data is obtained using 198e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #getProvisionRequest} 199e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 200e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_PROVISION_REQUIRED = 1; 201e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 202e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 203e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event type indicates that the app needs to request keys from a license 204e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server. The request message data is obtained using {@link #getKeyRequest}. 205e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 206e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_KEY_REQUIRED = 2; 207e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 208e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 209e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event type indicates that the licensed usage duration for keys in a session 210e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * has expired. The keys are no longer valid. 211e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 212e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_KEY_EXPIRED = 3; 213e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 214e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 215e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event may indicate some specific vendor-defined condition, see your 216e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * DRM provider documentation for details 217e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 218e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_VENDOR_DEFINED = 4; 21916b8cffb2893c10c35788191847500004da466d1Jeff Tinker 2208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static final int DRM_EVENT = 200; 22154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker 2228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private class EventHandler extends Handler 2238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 2248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private MediaDrm mMediaDrm; 2258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public EventHandler(MediaDrm md, Looper looper) { 2278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker super(looper); 2288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mMediaDrm = md; 2298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker @Override 2328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public void handleMessage(Message msg) { 2338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (mMediaDrm.mNativeContext == 0) { 2348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Log.w(TAG, "MediaDrm went away with unhandled events"); 2358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 2368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker switch(msg.what) { 2388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker case DRM_EVENT: 2408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")"); 2418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (mOnEventListener != null) { 24354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker if (msg.obj != null && msg.obj instanceof Parcel) { 24454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker Parcel parcel = (Parcel)msg.obj; 24554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker byte[] sessionId = parcel.createByteArray(); 24654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker if (sessionId.length == 0) { 24754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker sessionId = null; 24854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker } 24954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker byte[] data = parcel.createByteArray(); 25054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker if (data.length == 0) { 25154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker data = null; 25254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker } 25354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data); 25454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker } 2558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 2578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker default: 2598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Log.e(TAG, "Unknown message type " + msg.what); 2608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 2618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /* 266e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This method is called from native code when an event occurs. This method 2678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * just uses the EventHandler system to post the event back to the main app thread. 2688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * We use a weak reference to the original MediaPlayer object so that the native 2698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * code is safe from the object disappearing from underneath it. (This is 2708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * the cookie passed to native_setup().) 2718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 2728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static void postEventFromNative(Object mediadrm_ref, 27354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker int eventType, int extra, Object obj) 2748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 2758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get(); 2768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (md == null) { 2778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 2788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (md.mEventHandler != null) { 28054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj); 2818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker md.mEventHandler.sendMessage(m); 2828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 286e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Open a new session with the MediaDrm object. A session ID is returned. 2871d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 2881d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws NotProvisionedException if provisioning is needed 2893ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker * @throws ResourceBusyException if required resources are in use 2908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 2911d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker public native byte[] openSession() throws NotProvisionedException; 2928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 294e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Close a session on the MediaDrm object that was previously opened 295e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * with {@link #openSession}. 2968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 297e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void closeSession(byte[] sessionId); 2988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 299e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 300e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This key request type species that the keys will be for online use, they will 301e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * not be saved to the device for subsequent use when the device is not connected 302e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to a network. 303e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 304e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int KEY_TYPE_STREAMING = 1; 305e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 306e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 307e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This key request type specifies that the keys will be for offline use, they 308e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * will be saved to the device for use when the device is not connected to a network. 309e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 310e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int KEY_TYPE_OFFLINE = 2; 311e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 312e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 313e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This key request type specifies that previously saved offline keys should be released. 314e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 315e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int KEY_TYPE_RELEASE = 3; 316e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 317e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 318e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Contains the opaque data an app uses to request keys from a license server 319e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 320e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public final static class KeyRequest { 321e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker KeyRequest() {} 322e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 323e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 324e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the opaque message data 325e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 326e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public byte[] getData() { return mData; } 327e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 328e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 329e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the default URL to use when sending the key request message to a 330e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server, if known. The app may prefer to use a different license 331e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server URL from other sources. 332e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 333e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public String getDefaultUrl() { return mDefaultUrl; } 3348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 335e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private byte[] mData; 336e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private String mDefaultUrl; 3378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker }; 3388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 3398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 340d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * A key request/response exchange occurs between the app and a license server 341d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * to obtain or release keys used to decrypt encrypted content. 342e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 343d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * getKeyRequest() is used to obtain an opaque key request byte array that is 344d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * delivered to the license server. The opaque key request byte array is returned 345d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * in KeyRequest.data. The recommended URL to deliver the key request to is 34616b8cffb2893c10c35788191847500004da466d1Jeff Tinker * returned in KeyRequest.defaultUrl. 347e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 34816b8cffb2893c10c35788191847500004da466d1Jeff Tinker * After the app has received the key request response from the server, 34916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * it should deliver to the response to the DRM engine plugin using the method 35016b8cffb2893c10c35788191847500004da466d1Jeff Tinker * {@link #provideKeyResponse}. 3518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 352d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * @param scope may be a sessionId or a keySetId, depending on the specified keyType. 353e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, 354d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * scope should be set to the sessionId the keys will be provided to. When the keyType 355e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * is KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys 356d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * being released. Releasing keys from a device invalidates them for all sessions. 3578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param init container-specific data, its meaning is interpreted based on the 3588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * mime type provided in the mimeType parameter. It could contain, for example, 3598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * the content ID, key ID or other data obtained from the content metadata that is 360d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * required in generating the key request. init may be null when keyType is 361e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * KEY_TYPE_RELEASE. 3628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param mimeType identifies the mime type of the content 363d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * @param keyType specifes the type of the request. The request may be to acquire 364d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * keys for streaming or offline content, or to release previously acquired 365d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * keys, which are identified by a keySetId. 36616b8cffb2893c10c35788191847500004da466d1Jeff Tinker * @param optionalParameters are included in the key request message to 3678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * allow a client application to provide additional message parameters to the server. 3681d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 3691d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws NotProvisionedException if reprovisioning is needed, due to a 3701d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * problem with the certifcate 3718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 372d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker public native KeyRequest getKeyRequest(byte[] scope, byte[] init, 37316b8cffb2893c10c35788191847500004da466d1Jeff Tinker String mimeType, int keyType, 3741d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker HashMap<String, String> optionalParameters) 3751d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker throws NotProvisionedException; 376e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 3778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 3788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 37916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * A key response is received from the license server by the app, then it is 380ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * provided to the DRM engine plugin using provideKeyResponse. When the 381ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * response is for an offline key request, a keySetId is returned that can be 382ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * used to later restore the keys to a new session with the method 383ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * {@link #restoreKeys}. 384ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * When the response is for a streaming or release request, null is returned. 3858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 386ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * @param scope may be a sessionId or keySetId depending on the type of the 387ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * response. Scope should be set to the sessionId when the response is for either 388ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * streaming or offline key requests. Scope should be set to the keySetId when 389ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * the response is for a release request. 3908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param response the byte array response from the server 3911d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 3921d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws NotProvisionedException if the response indicates that 3931d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * reprovisioning is required 3941d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws DeniedByServerException if the response indicates that the 3951d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * server rejected the request 3963ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker * @throws ResourceBusyException if required resources are in use 3978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 398ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker public native byte[] provideKeyResponse(byte[] scope, byte[] response) 3991d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker throws NotProvisionedException, DeniedByServerException; 4001d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker 4018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 40316b8cffb2893c10c35788191847500004da466d1Jeff Tinker * Restore persisted offline keys into a new session. keySetId identifies the 404e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * keys to load, obtained from a prior call to {@link #provideKeyResponse}. 40516b8cffb2893c10c35788191847500004da466d1Jeff Tinker * 4068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param sessionId the session ID for the DRM session 40716b8cffb2893c10c35788191847500004da466d1Jeff Tinker * @param keySetId identifies the saved key set to restore 4088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 409e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void restoreKeys(byte[] sessionId, byte[] keySetId); 4108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 412d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * Remove the current keys from a session. 41316b8cffb2893c10c35788191847500004da466d1Jeff Tinker * 414d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * @param sessionId the session ID for the DRM session 41516b8cffb2893c10c35788191847500004da466d1Jeff Tinker */ 416e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void removeKeys(byte[] sessionId); 41716b8cffb2893c10c35788191847500004da466d1Jeff Tinker 41816b8cffb2893c10c35788191847500004da466d1Jeff Tinker /** 41916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * Request an informative description of the key status for the session. The status is 4208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * in the form of {name, value} pairs. Since DRM license policies vary by vendor, 4218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * the specific status field names are determined by each DRM vendor. Refer to your 4228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * DRM provider documentation for definitions of the field names for a particular 42316b8cffb2893c10c35788191847500004da466d1Jeff Tinker * DRM engine plugin. 4248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 4258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param sessionId the session ID for the DRM session 4268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 427e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native HashMap<String, String> queryKeyStatus(byte[] sessionId); 428e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 429e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 430e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Contains the opaque data an app uses to request a certificate from a provisioning 431e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server 432e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 433e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public final static class ProvisionRequest { 434e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker ProvisionRequest() {} 435e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 436e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 437e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the opaque message data 438e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 439e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public byte[] getData() { return mData; } 440e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 441e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 442e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the default URL to use when sending the provision request 443e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * message to a server, if known. The app may prefer to use a different 444e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * provisioning server URL obtained from other sources. 445e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 446e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public String getDefaultUrl() { return mDefaultUrl; } 4478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 448e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private byte[] mData; 449e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private String mDefaultUrl; 4508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 4518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 4538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * A provision request/response exchange occurs between the app and a provisioning 45416b8cffb2893c10c35788191847500004da466d1Jeff Tinker * server to retrieve a device certificate. If provisionining is required, the 455e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * EVENT_PROVISION_REQUIRED event will be sent to the event handler. 45616b8cffb2893c10c35788191847500004da466d1Jeff Tinker * getProvisionRequest is used to obtain the opaque provision request byte array that 45716b8cffb2893c10c35788191847500004da466d1Jeff Tinker * should be delivered to the provisioning server. The provision request byte array 45816b8cffb2893c10c35788191847500004da466d1Jeff Tinker * is returned in ProvisionRequest.data. The recommended URL to deliver the provision 45916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * request to is returned in ProvisionRequest.defaultUrl. 4608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 461e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native ProvisionRequest getProvisionRequest(); 4628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 4648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * After a provision response is received by the app, it is provided to the DRM 46516b8cffb2893c10c35788191847500004da466d1Jeff Tinker * engine plugin using this method. 4668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 4678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param response the opaque provisioning response byte array to provide to the 46816b8cffb2893c10c35788191847500004da466d1Jeff Tinker * DRM engine plugin. 4691d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 4701d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws DeniedByServerException if the response indicates that the 4711d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * server rejected the request 4728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 4731d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker public native void provideProvisionResponse(byte[] response) 4741d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker throws DeniedByServerException; 4758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 477e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * A means of enforcing limits on the number of concurrent streams per subscriber 478e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * across devices is provided via SecureStop. This is achieved by securely 479e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * monitoring the lifetime of sessions. 480e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 481e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Information from the server related to the current playback session is written 482e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to persistent storage on the device when each MediaCrypto object is created. 483e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 4848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * In the normal case, playback will be completed, the session destroyed and the 485e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Secure Stops will be queried. The app queries secure stops and forwards the 4868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * secure stop message to the server which verifies the signature and notifies the 4878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * server side database that the session destruction has been confirmed. The persisted 4888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * record on the client is only removed after positive confirmation that the server 4898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * received the message using releaseSecureStops(). 4908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 491e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native List<byte[]> getSecureStops(); 4928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 4958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Process the SecureStop server response message ssRelease. After authenticating 496e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the message, remove the SecureStops identified in the response. 4978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 4988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param ssRelease the server response indicating which secure stops to release 4998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 500e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void releaseSecureStops(byte[] ssRelease); 5018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 504e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: identifies the maker of the DRM engine plugin 505e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 506e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_VENDOR = "vendor"; 507e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 508e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 509e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: identifies the version of the DRM engine plugin 510e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 511e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_VERSION = "version"; 512e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 513e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 514e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: describes the DRM engine plugin 515e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 516e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_DESCRIPTION = "description"; 517e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 518e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 519e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: a comma-separated list of cipher and mac algorithms 520e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * supported by CryptoSession. The list may be empty if the DRM engine 521e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * plugin does not support CryptoSession operations. 522e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 523f0d4777473f25847d67fc17fc082fada08cf678dJeff Tinker public static final String PROPERTY_ALGORITHMS = "algorithms"; 524e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 525e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 526e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Read a DRM engine plugin String property value, given the property name string. 527e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 5288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Standard fields names are: 529e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION}, 530b5ec8c145d467abbc6eaf3306a5f6725e348ceecKenny Root * {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS} 5318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 532e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native String getPropertyString(String propertyName); 5338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 536f0d4777473f25847d67fc17fc082fada08cf678dJeff Tinker * Byte array property name: the device unique identifier is established during 537f0d4777473f25847d67fc17fc082fada08cf678dJeff Tinker * device provisioning and provides a means of uniquely identifying each device. 5388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 539e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId"; 540e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 541e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 542e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Read a DRM engine plugin byte array property value, given the property name string. 543e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 544e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID} 545e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 546e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native byte[] getPropertyByteArray(String propertyName); 5478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 54916b8cffb2893c10c35788191847500004da466d1Jeff Tinker /** 550e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Set a DRM engine plugin String property value. 551e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 552e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void setPropertyString(String propertyName, String value); 553e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 554e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 555e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Set a DRM engine plugin byte array property value. 55616b8cffb2893c10c35788191847500004da466d1Jeff Tinker */ 557e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void setPropertyByteArray(String propertyName, byte[] value); 558e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 55916b8cffb2893c10c35788191847500004da466d1Jeff Tinker 56016b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native void setCipherAlgorithmNative(MediaDrm drm, byte[] sessionId, 56116b8cffb2893c10c35788191847500004da466d1Jeff Tinker String algorithm); 56216b8cffb2893c10c35788191847500004da466d1Jeff Tinker 56316b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native void setMacAlgorithmNative(MediaDrm drm, byte[] sessionId, 56416b8cffb2893c10c35788191847500004da466d1Jeff Tinker String algorithm); 56516b8cffb2893c10c35788191847500004da466d1Jeff Tinker 56616b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native byte[] encryptNative(MediaDrm drm, byte[] sessionId, 56716b8cffb2893c10c35788191847500004da466d1Jeff Tinker byte[] keyId, byte[] input, byte[] iv); 56816b8cffb2893c10c35788191847500004da466d1Jeff Tinker 56916b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native byte[] decryptNative(MediaDrm drm, byte[] sessionId, 57016b8cffb2893c10c35788191847500004da466d1Jeff Tinker byte[] keyId, byte[] input, byte[] iv); 57116b8cffb2893c10c35788191847500004da466d1Jeff Tinker 57216b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native byte[] signNative(MediaDrm drm, byte[] sessionId, 57316b8cffb2893c10c35788191847500004da466d1Jeff Tinker byte[] keyId, byte[] message); 57416b8cffb2893c10c35788191847500004da466d1Jeff Tinker 57516b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native boolean verifyNative(MediaDrm drm, byte[] sessionId, 57616b8cffb2893c10c35788191847500004da466d1Jeff Tinker byte[] keyId, byte[] message, 57716b8cffb2893c10c35788191847500004da466d1Jeff Tinker byte[] signature); 57816b8cffb2893c10c35788191847500004da466d1Jeff Tinker 579e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 580e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * In addition to supporting decryption of DASH Common Encrypted Media, the 581e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * MediaDrm APIs provide the ability to securely deliver session keys from 582e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * an operator's session key server to a client device, based on the factory-installed 583e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * root of trust, and then perform encrypt, decrypt, sign and verify operations 584e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * with the session key on arbitrary user data. 585e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 586e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The CryptoSession class implements generic encrypt/decrypt/sign/verify methods 587e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * based on the established session keys. These keys are exchanged using the 588e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * getKeyRequest/provideKeyResponse methods. 589e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 590e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Applications of this capability could include securing various types of 591e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * purchased or private content, such as applications, books and other media, 592e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * photos or media delivery protocols. 593e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 594e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Operators can create session key servers that are functionally similar to a 595e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * license key server, except that instead of receiving license key requests and 596e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * providing encrypted content keys which are used specifically to decrypt A/V media 597e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * content, the session key server receives session key requests and provides 598e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * encrypted session keys which can be used for general purpose crypto operations. 599e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 600e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * A CryptoSession is obtained using {@link #getCryptoSession} 601e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 60216b8cffb2893c10c35788191847500004da466d1Jeff Tinker public final class CryptoSession { 60316b8cffb2893c10c35788191847500004da466d1Jeff Tinker private MediaDrm mDrm; 60416b8cffb2893c10c35788191847500004da466d1Jeff Tinker private byte[] mSessionId; 60516b8cffb2893c10c35788191847500004da466d1Jeff Tinker 606e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker CryptoSession(MediaDrm drm, byte[] sessionId, 607e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker String cipherAlgorithm, String macAlgorithm) 608e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker { 60916b8cffb2893c10c35788191847500004da466d1Jeff Tinker mSessionId = sessionId; 61016b8cffb2893c10c35788191847500004da466d1Jeff Tinker mDrm = drm; 61116b8cffb2893c10c35788191847500004da466d1Jeff Tinker setCipherAlgorithmNative(drm, sessionId, cipherAlgorithm); 61216b8cffb2893c10c35788191847500004da466d1Jeff Tinker setMacAlgorithmNative(drm, sessionId, macAlgorithm); 61316b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 61416b8cffb2893c10c35788191847500004da466d1Jeff Tinker 615e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 616e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Encrypt data using the CryptoSession's cipher algorithm 617e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 618e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 619e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param input the data to encrypt 620e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param iv the initialization vector to use for the cipher 621e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 62216b8cffb2893c10c35788191847500004da466d1Jeff Tinker public byte[] encrypt(byte[] keyid, byte[] input, byte[] iv) { 62316b8cffb2893c10c35788191847500004da466d1Jeff Tinker return encryptNative(mDrm, mSessionId, keyid, input, iv); 62416b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 62516b8cffb2893c10c35788191847500004da466d1Jeff Tinker 626e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 627e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Decrypt data using the CryptoSessions's cipher algorithm 628e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 629e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 630e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param input the data to encrypt 631e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param iv the initialization vector to use for the cipher 632e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 63316b8cffb2893c10c35788191847500004da466d1Jeff Tinker public byte[] decrypt(byte[] keyid, byte[] input, byte[] iv) { 63416b8cffb2893c10c35788191847500004da466d1Jeff Tinker return decryptNative(mDrm, mSessionId, keyid, input, iv); 63516b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 63616b8cffb2893c10c35788191847500004da466d1Jeff Tinker 637e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 638e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Sign data using the CryptoSessions's mac algorithm. 639e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 640e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 641e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param message the data for which a signature is to be computed 642e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 64316b8cffb2893c10c35788191847500004da466d1Jeff Tinker public byte[] sign(byte[] keyid, byte[] message) { 64416b8cffb2893c10c35788191847500004da466d1Jeff Tinker return signNative(mDrm, mSessionId, keyid, message); 64516b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 646e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 647e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 648e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Verify a signature using the CryptoSessions's mac algorithm. Return true 649e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * if the signatures match, false if they do no. 650e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 651e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 652e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param message the data to verify 653e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param signature the reference signature which will be compared with the 654e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * computed signature 655e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 65616b8cffb2893c10c35788191847500004da466d1Jeff Tinker public boolean verify(byte[] keyid, byte[] message, byte[] signature) { 65716b8cffb2893c10c35788191847500004da466d1Jeff Tinker return verifyNative(mDrm, mSessionId, keyid, message, signature); 65816b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 65916b8cffb2893c10c35788191847500004da466d1Jeff Tinker }; 66016b8cffb2893c10c35788191847500004da466d1Jeff Tinker 661e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 662e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Obtain a CryptoSession object which can be used to encrypt, decrypt, 663e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * sign and verify messages or data using the session keys established 664e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * for the session using methods {@link #getKeyRequest} and 665e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #provideKeyResponse} using a session key server. 666e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 667e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param sessionId the session ID for the session containing keys 668e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to be used for encrypt, decrypt, sign and/or verify 669e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param cipherAlgorithm the algorithm to use for encryption and 670e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * decryption ciphers. The algorithm string conforms to JCA Standard 671e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Names for Cipher Transforms and is case insensitive. For example 672e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * "AES/CBC/NoPadding". 673e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param macAlgorithm the algorithm to use for sign and verify 674e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The algorithm string conforms to JCA Standard Names for Mac 675e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Algorithms and is case insensitive. For example "HmacSHA256". 676e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 677e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The list of supported algorithms for a DRM engine plugin can be obtained 678e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * using the method {@link #getPropertyString} with the property name 679e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * "algorithms". 680e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 68116b8cffb2893c10c35788191847500004da466d1Jeff Tinker public CryptoSession getCryptoSession(byte[] sessionId, 68216b8cffb2893c10c35788191847500004da466d1Jeff Tinker String cipherAlgorithm, 68316b8cffb2893c10c35788191847500004da466d1Jeff Tinker String macAlgorithm) 684e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker { 68516b8cffb2893c10c35788191847500004da466d1Jeff Tinker return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm); 68616b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 68716b8cffb2893c10c35788191847500004da466d1Jeff Tinker 6888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker @Override 6898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker protected void finalize() { 6908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker native_finalize(); 6918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 6928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 6938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public native final void release(); 6948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static native final void native_init(); 6958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 696e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private native final void native_setup(Object mediadrm_this, byte[] uuid); 6978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 6988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private native final void native_finalize(); 6998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 7008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker static { 7018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker System.loadLibrary("media_jni"); 7028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker native_init(); 7038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 7048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker} 705