19de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff 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 java.lang.ref.WeakReference; 208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport java.util.UUID; 218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport java.util.HashMap; 228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport java.util.List; 236bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinkerimport android.annotation.SystemApi; 24e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinkerimport android.os.Binder; 25e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinkerimport android.os.Debug; 268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.os.Handler; 278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.os.Looper; 288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.os.Message; 2954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkerimport android.os.Parcel; 308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.util.Log; 318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker/** 33e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * MediaDrm can be used to obtain keys for decrypting protected media streams, in 34e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * conjunction with {@link android.media.MediaCrypto}. The MediaDrm APIs 35e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * are designed to support the ISO/IEC 23001-7: Common Encryption standard, but 36e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * may also be used to implement other encryption schemes. 37e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 38e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Encrypted content is prepared using an encryption server and stored in a content 39e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * library. The encrypted content is streamed or downloaded from the content library to 40e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * client devices via content servers. Licenses to view the content are obtained from 41e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * a License Server. 42e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 43e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p><img src="../../../images/mediadrm_overview.png" 44e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * alt="MediaDrm Overview diagram" 45e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * border="0" /></p> 46e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 47e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Keys are requested from the license server using a key request. The key 48e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * response is delivered to the client app, which provides the response to the 49e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * MediaDrm API. 50e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 51e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * A Provisioning server may be required to distribute device-unique credentials to 52e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the devices. 53e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 54e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Enforcing requirements related to the number of devices that may play content 55e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * simultaneously can be performed either through key renewal or using the secure 56e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * stop methods. 57e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 58e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The following sequence diagram shows the interactions between the objects 59e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * involved while playing back encrypted content: 60e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 61e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p><img src="../../../images/mediadrm_decryption_sequence.png" 62e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * alt="MediaDrm Overview diagram" 63e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * border="0" /></p> 64e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 65e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The app first constructs {@link android.media.MediaExtractor} and 66e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link android.media.MediaCodec} objects. It accesses the DRM-scheme-identifying UUID, 67e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * typically from metadata in the content, and uses this UUID to construct an instance 68e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * of a MediaDrm object that is able to support the DRM scheme required by the content. 69e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Crypto schemes are assigned 16 byte UUIDs. The method {@link #isCryptoSchemeSupported} 70e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * can be used to query if a given scheme is supported on the device. 71e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 72e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The app calls {@link #openSession} to generate a sessionId that will uniquely identify 73e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the session in subsequent interactions. The app next uses the MediaDrm object to 74e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * obtain a key request message and send it to the license server, then provide 75e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the server's response to the MediaDrm object. 76e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 77e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Once the app has a sessionId, it can construct a MediaCrypto object from the UUID and 78e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * sessionId. The MediaCrypto object is registered with the MediaCodec in the 79e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link MediaCodec.#configure} method to enable the codec to decrypt content. 80e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 81e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * When the app has constructed {@link android.media.MediaExtractor}, 82e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link android.media.MediaCodec} and {@link android.media.MediaCrypto} objects, 83e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * it proceeds to pull samples from the extractor and queue them into the decoder. For 84e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * encrypted content, the samples returned from the extractor remain encrypted, they 85e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * are only decrypted when the samples are delivered to the decoder. 86e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * <a name="Callbacks"></a> 888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * <h3>Callbacks</h3> 89e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p>Applications should register for informational events in order 90e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to be informed of key state updates during playback or streaming. 918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Registration for these events is done via a call to 92e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #setOnEventListener}. In order to receive the respective 93e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * callback associated with this listener, applications are required to create 948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * MediaDrm objects on a thread with its own Looper running (main UI 958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * thread by default has a Looper running). 968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerpublic final class MediaDrm { 988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private final static String TAG = "MediaDrm"; 1008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1019de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES; 1029de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker 1038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private EventHandler mEventHandler; 1048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private OnEventListener mOnEventListener; 1058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 106656fd0402613cec0196d5e2ae0a460d044d2805bAshok Bhat private long mNativeContext; 1078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 109e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Specify no certificate type 110e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 111e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @hide - not part of the public API at this time 112e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 113e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public static final int CERTIFICATE_TYPE_NONE = 0; 114e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 115e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 116e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Specify X.509 certificate type 117e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 118e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @hide - not part of the public API at this time 119e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 120e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public static final int CERTIFICATE_TYPE_X509 = 1; 121e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 122e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 1238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Query if the given scheme identified by its UUID is supported on 1248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * this device. 1258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param uuid The UUID of the crypto scheme. 1268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public static final boolean isCryptoSchemeSupported(UUID uuid) { 1287cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), null); 1297cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker } 1307cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker 1317cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker /** 1327cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * Query if the given scheme identified by its UUID is supported on 1337cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * this device, and whether the drm plugin is able to handle the 1347cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * media container format specified by mimeType. 1357cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * @param uuid The UUID of the crypto scheme. 1367cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * @param mimeType The MIME type of the media container, e.g. "video/mp4" 1377cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker * or "video/webm" 1387cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker */ 1397cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker public static final boolean isCryptoSchemeSupported(UUID uuid, String mimeType) { 1407cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType); 1418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static final byte[] getByteArrayFromUUID(UUID uuid) { 1448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker long msb = uuid.getMostSignificantBits(); 1458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker long lsb = uuid.getLeastSignificantBits(); 1468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker byte[] uuidBytes = new byte[16]; 1488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker for (int i = 0; i < 8; ++i) { 1498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker uuidBytes[i] = (byte)(msb >>> (8 * (7 - i))); 1508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i))); 1518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return uuidBytes; 1548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1567cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid, 1579de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String mimeType); 1588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 1601d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * Instantiate a MediaDrm object 1611d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 1628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param uuid The UUID of the crypto scheme. 1631d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 1641d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws UnsupportedSchemeException if the device does not support the 1651d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * specified scheme UUID 1668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1671d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker public MediaDrm(UUID uuid) throws UnsupportedSchemeException { 1688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Looper looper; 1698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if ((looper = Looper.myLooper()) != null) { 1708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mEventHandler = new EventHandler(this, looper); 1718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } else if ((looper = Looper.getMainLooper()) != null) { 1728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mEventHandler = new EventHandler(this, looper); 1738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } else { 1748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mEventHandler = null; 1758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /* Native setup requires a weak reference to our object. 1788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * It's easier to create it here than in C++. 1798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 1808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker native_setup(new WeakReference<MediaDrm>(this), 1819de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker getByteArrayFromUUID(uuid)); 1828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 1838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 1848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 185d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker * Thrown when an unrecoverable failure occurs during a MediaDrm operation. 186d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker * Extends java.lang.IllegalStateException with the addition of an error 187d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker * code that may be useful in diagnosing the failure. 188d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker */ 189d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker public static final class MediaDrmStateException extends java.lang.IllegalStateException { 190d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker private final int mErrorCode; 191d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar private final String mDiagnosticInfo; 192d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker 19321069d1914ae7ef07e3edf6bea435e7569f28d64Jeff Tinker /** 19421069d1914ae7ef07e3edf6bea435e7569f28d64Jeff Tinker * @hide 19521069d1914ae7ef07e3edf6bea435e7569f28d64Jeff Tinker */ 196d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker public MediaDrmStateException(int errorCode, String detailMessage) { 197d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker super(detailMessage); 198d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker mErrorCode = errorCode; 199d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar 200d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar // TODO get this from DRM session 201d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar final String sign = errorCode < 0 ? "neg_" : ""; 202d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar mDiagnosticInfo = 203d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar "android.media.MediaDrm.error_" + sign + Math.abs(errorCode); 204d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar 205d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker } 206d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker 207d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker /** 208d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker * Retrieve the associated error code 209d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar * 210d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar * @hide 211d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker */ 212d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker public int getErrorCode() { 213d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker return mErrorCode; 214d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker } 215d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar 216d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar /** 21721069d1914ae7ef07e3edf6bea435e7569f28d64Jeff Tinker * Retrieve a developer-readable diagnostic information string 21821069d1914ae7ef07e3edf6bea435e7569f28d64Jeff Tinker * associated with the exception. Do not show this to end-users, 21921069d1914ae7ef07e3edf6bea435e7569f28d64Jeff Tinker * since this string will not be localized or generally comprehensible 220d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar * to end-users. 221d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar */ 222d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar public String getDiagnosticInfo() { 223d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar return mDiagnosticInfo; 224d7e5f680fa64b76c3d1c2a67572896705a0588edLajos Molnar } 225d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker } 226d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker 227d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker /** 2288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Register a callback to be invoked when an event occurs 2298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 2308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param listener the callback that will be run 2318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 2328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public void setOnEventListener(OnEventListener listener) 2338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 2348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mOnEventListener = listener; 2358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 2388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Interface definition for a callback to be invoked when a drm event 239e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * occurs 2408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 2418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public interface OnEventListener 2428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 2438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 2448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Called when an event occurs that requires the app to be notified 2458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 2468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param md the MediaDrm object on which the event occurred 2478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param sessionId the DRM session ID on which the event occurred 2488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param event indicates the event type 2498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param extra an secondary error code 2508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param data optional byte array of data that may be associated with the event 2518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 2528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data); 2538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 255e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 256e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event type indicates that the app needs to request a certificate from 257e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the provisioning server. The request message data is obtained using 258e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #getProvisionRequest} 259e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 260e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_PROVISION_REQUIRED = 1; 261e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 262e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 263e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event type indicates that the app needs to request keys from a license 264e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server. The request message data is obtained using {@link #getKeyRequest}. 265e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 266e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_KEY_REQUIRED = 2; 267e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 268e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 269e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event type indicates that the licensed usage duration for keys in a session 270e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * has expired. The keys are no longer valid. 271e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 272e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_KEY_EXPIRED = 3; 273e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 274e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 275e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This event may indicate some specific vendor-defined condition, see your 276e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * DRM provider documentation for details 277e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 278e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int EVENT_VENDOR_DEFINED = 4; 27916b8cffb2893c10c35788191847500004da466d1Jeff Tinker 2808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static final int DRM_EVENT = 200; 28154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker 2828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private class EventHandler extends Handler 2838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 2848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private MediaDrm mMediaDrm; 2858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public EventHandler(MediaDrm md, Looper looper) { 2878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker super(looper); 2888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker mMediaDrm = md; 2898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker @Override 2928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public void handleMessage(Message msg) { 2938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (mMediaDrm.mNativeContext == 0) { 2948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Log.w(TAG, "MediaDrm went away with unhandled events"); 2958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 2968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 2978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker switch(msg.what) { 2988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 2998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker case DRM_EVENT: 3008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")"); 3018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 3028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (mOnEventListener != null) { 30354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker if (msg.obj != null && msg.obj instanceof Parcel) { 30454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker Parcel parcel = (Parcel)msg.obj; 30554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker byte[] sessionId = parcel.createByteArray(); 30654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker if (sessionId.length == 0) { 30754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker sessionId = null; 30854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker } 30954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker byte[] data = parcel.createByteArray(); 31054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker if (data.length == 0) { 31154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker data = null; 31254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker } 31354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data); 31454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker } 3158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 3168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 3178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 3188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker default: 3198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker Log.e(TAG, "Unknown message type " + msg.what); 3208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 3218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 3228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 3238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 3248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 3258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /* 326e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This method is called from native code when an event occurs. This method 3278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * just uses the EventHandler system to post the event back to the main app thread. 3288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * We use a weak reference to the original MediaPlayer object so that the native 3298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * code is safe from the object disappearing from underneath it. (This is 3308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * the cookie passed to native_setup().) 3318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 3328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static void postEventFromNative(Object mediadrm_ref, 3339de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker int eventType, int extra, Object obj) 3348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker { 3358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get(); 3368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (md == null) { 3378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker return; 3388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 3398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker if (md.mEventHandler != null) { 34054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj); 3418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker md.mEventHandler.sendMessage(m); 3428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 3438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 3448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 3458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 346e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Open a new session with the MediaDrm object. A session ID is returned. 3471d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 3481d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws NotProvisionedException if provisioning is needed 3493ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker * @throws ResourceBusyException if required resources are in use 3508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 3513b6ec30bff1749766a0d25770aa42d3a013c09d3Jeff Tinker public native byte[] openSession() throws NotProvisionedException, 3523b6ec30bff1749766a0d25770aa42d3a013c09d3Jeff Tinker ResourceBusyException; 3538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 3548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 355e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Close a session on the MediaDrm object that was previously opened 356e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * with {@link #openSession}. 3578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 358e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void closeSession(byte[] sessionId); 3598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 360e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 361e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This key request type species that the keys will be for online use, they will 362e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * not be saved to the device for subsequent use when the device is not connected 363e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to a network. 364e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 365e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int KEY_TYPE_STREAMING = 1; 366e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 367e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 368e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This key request type specifies that the keys will be for offline use, they 369e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * will be saved to the device for use when the device is not connected to a network. 370e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 371e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int KEY_TYPE_OFFLINE = 2; 372e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 373e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 374e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * This key request type specifies that previously saved offline keys should be released. 375e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 376e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final int KEY_TYPE_RELEASE = 3; 377e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 378e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 379e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Contains the opaque data an app uses to request keys from a license server 380e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 381e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public final static class KeyRequest { 382e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private byte[] mData; 383e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private String mDefaultUrl; 384e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 385e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker KeyRequest() {} 386e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 387e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 388e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the opaque message data 389e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 390e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public byte[] getData() { return mData; } 391e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 392e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 393e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the default URL to use when sending the key request message to a 394e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server, if known. The app may prefer to use a different license 395e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server URL from other sources. 396e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 397e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public String getDefaultUrl() { return mDefaultUrl; } 3988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker }; 3998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 401d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * A key request/response exchange occurs between the app and a license server 402d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * to obtain or release keys used to decrypt encrypted content. 403e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 404d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * getKeyRequest() is used to obtain an opaque key request byte array that is 405d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * delivered to the license server. The opaque key request byte array is returned 406d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * in KeyRequest.data. The recommended URL to deliver the key request to is 40716b8cffb2893c10c35788191847500004da466d1Jeff Tinker * returned in KeyRequest.defaultUrl. 408e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 40916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * After the app has received the key request response from the server, 41016b8cffb2893c10c35788191847500004da466d1Jeff Tinker * it should deliver to the response to the DRM engine plugin using the method 41116b8cffb2893c10c35788191847500004da466d1Jeff Tinker * {@link #provideKeyResponse}. 4128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 413d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * @param scope may be a sessionId or a keySetId, depending on the specified keyType. 414e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, 415d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * scope should be set to the sessionId the keys will be provided to. When the keyType 416e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * is KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys 417d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * being released. Releasing keys from a device invalidates them for all sessions. 4188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param init container-specific data, its meaning is interpreted based on the 4198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * mime type provided in the mimeType parameter. It could contain, for example, 4208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * the content ID, key ID or other data obtained from the content metadata that is 421d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * required in generating the key request. init may be null when keyType is 422e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * KEY_TYPE_RELEASE. 4238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param mimeType identifies the mime type of the content 424d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * @param keyType specifes the type of the request. The request may be to acquire 425d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * keys for streaming or offline content, or to release previously acquired 426d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * keys, which are identified by a keySetId. 42716b8cffb2893c10c35788191847500004da466d1Jeff Tinker * @param optionalParameters are included in the key request message to 4288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * allow a client application to provide additional message parameters to the server. 4291d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 4301d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws NotProvisionedException if reprovisioning is needed, due to a 4311d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * problem with the certifcate 4328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 433d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker public native KeyRequest getKeyRequest(byte[] scope, byte[] init, 4349de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String mimeType, int keyType, HashMap<String, String> optionalParameters) 4359de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker throws NotProvisionedException; 436e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 4378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 43916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * A key response is received from the license server by the app, then it is 440ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * provided to the DRM engine plugin using provideKeyResponse. When the 441ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * response is for an offline key request, a keySetId is returned that can be 442ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * used to later restore the keys to a new session with the method 443ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * {@link #restoreKeys}. 444ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * When the response is for a streaming or release request, null is returned. 4458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 446ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * @param scope may be a sessionId or keySetId depending on the type of the 447ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * response. Scope should be set to the sessionId when the response is for either 448ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * streaming or offline key requests. Scope should be set to the keySetId when 449ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker * the response is for a release request. 4508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param response the byte array response from the server 4511d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 4521d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws NotProvisionedException if the response indicates that 4531d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * reprovisioning is required 4541d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws DeniedByServerException if the response indicates that the 4551d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * server rejected the request 4563ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker * @throws ResourceBusyException if required resources are in use 4578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 458ea824eddbcaf24cde1c2388ff73e7c5c5e4afb26Jeff Tinker public native byte[] provideKeyResponse(byte[] scope, byte[] response) 4599de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker throws NotProvisionedException, DeniedByServerException; 4601d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker 4618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 46316b8cffb2893c10c35788191847500004da466d1Jeff Tinker * Restore persisted offline keys into a new session. keySetId identifies the 464e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * keys to load, obtained from a prior call to {@link #provideKeyResponse}. 46516b8cffb2893c10c35788191847500004da466d1Jeff Tinker * 4668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param sessionId the session ID for the DRM session 46716b8cffb2893c10c35788191847500004da466d1Jeff Tinker * @param keySetId identifies the saved key set to restore 4688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 469e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void restoreKeys(byte[] sessionId, byte[] keySetId); 4708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 4718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 472d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * Remove the current keys from a session. 47316b8cffb2893c10c35788191847500004da466d1Jeff Tinker * 474d8bbfc2750fa24a0374dd3525d2759692e6b9285Jeff Tinker * @param sessionId the session ID for the DRM session 47516b8cffb2893c10c35788191847500004da466d1Jeff Tinker */ 476e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void removeKeys(byte[] sessionId); 47716b8cffb2893c10c35788191847500004da466d1Jeff Tinker 47816b8cffb2893c10c35788191847500004da466d1Jeff Tinker /** 47916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * Request an informative description of the key status for the session. The status is 4808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * in the form of {name, value} pairs. Since DRM license policies vary by vendor, 4818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * the specific status field names are determined by each DRM vendor. Refer to your 4828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * DRM provider documentation for definitions of the field names for a particular 48316b8cffb2893c10c35788191847500004da466d1Jeff Tinker * DRM engine plugin. 4848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 4858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param sessionId the session ID for the DRM session 4868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 487e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native HashMap<String, String> queryKeyStatus(byte[] sessionId); 488e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 489e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 490e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Contains the opaque data an app uses to request a certificate from a provisioning 491e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * server 492e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 493e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public final static class ProvisionRequest { 494e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker ProvisionRequest() {} 495e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 496e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 497e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the opaque message data 498e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 499e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public byte[] getData() { return mData; } 500e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 501e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 502e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Get the default URL to use when sending the provision request 503e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * message to a server, if known. The app may prefer to use a different 504e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * provisioning server URL obtained from other sources. 505e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 506e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public String getDefaultUrl() { return mDefaultUrl; } 5078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 508e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private byte[] mData; 509e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private String mDefaultUrl; 5108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 5118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 5138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * A provision request/response exchange occurs between the app and a provisioning 51416b8cffb2893c10c35788191847500004da466d1Jeff Tinker * server to retrieve a device certificate. If provisionining is required, the 515e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * EVENT_PROVISION_REQUIRED event will be sent to the event handler. 51616b8cffb2893c10c35788191847500004da466d1Jeff Tinker * getProvisionRequest is used to obtain the opaque provision request byte array that 51716b8cffb2893c10c35788191847500004da466d1Jeff Tinker * should be delivered to the provisioning server. The provision request byte array 51816b8cffb2893c10c35788191847500004da466d1Jeff Tinker * is returned in ProvisionRequest.data. The recommended URL to deliver the provision 51916b8cffb2893c10c35788191847500004da466d1Jeff Tinker * request to is returned in ProvisionRequest.defaultUrl. 5208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 521e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public ProvisionRequest getProvisionRequest() { 522e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, ""); 523e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 524e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 525e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private native ProvisionRequest getProvisionRequestNative(int certType, 5269de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String certAuthority); 5278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 5298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * After a provision response is received by the app, it is provided to the DRM 53016b8cffb2893c10c35788191847500004da466d1Jeff Tinker * engine plugin using this method. 5318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 5328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param response the opaque provisioning response byte array to provide to the 53316b8cffb2893c10c35788191847500004da466d1Jeff Tinker * DRM engine plugin. 5341d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * 5351d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * @throws DeniedByServerException if the response indicates that the 5361d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker * server rejected the request 5378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 538e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public void provideProvisionResponse(byte[] response) 5399de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker throws DeniedByServerException { 540e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker provideProvisionResponseNative(response); 541e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 542e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 543e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private native Certificate provideProvisionResponseNative(byte[] response) 5449de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker throws DeniedByServerException; 5458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 5476bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker * Remove provisioning from a device. Only system apps may unprovision a 5486bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker * device. Note that removing provisioning will invalidate any keys saved 5496bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker * for offline use (KEY_TYPE_OFFLINE), which may render downloaded content 5506bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker * unplayable until new licenses are acquired. Since provisioning is global 5516bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker * to the device, license invalidation will apply to all content downloaded 5526bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker * by any app, so appropriate warnings should be given to the user. 5536bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker * @hide 5546bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker */ 5556bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker @SystemApi 5566bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker public native void unprovisionDevice(); 5576bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker 5586bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker /** 559e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * A means of enforcing limits on the number of concurrent streams per subscriber 560e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * across devices is provided via SecureStop. This is achieved by securely 561e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * monitoring the lifetime of sessions. 562e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 563e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Information from the server related to the current playback session is written 564e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to persistent storage on the device when each MediaCrypto object is created. 565e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 5668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * In the normal case, playback will be completed, the session destroyed and the 567e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Secure Stops will be queried. The app queries secure stops and forwards the 5688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * secure stop message to the server which verifies the signature and notifies the 5698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * server side database that the session destruction has been confirmed. The persisted 5708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * record on the client is only removed after positive confirmation that the server 5718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * received the message using releaseSecureStops(). 5728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 573e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native List<byte[]> getSecureStops(); 5748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5751b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker /** 5761b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker * Access secure stop by secure stop ID. 5771b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker * 5781b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker * @param ssid - The secure stop ID provided by the license server. 5791b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker */ 5801b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker public native byte[] getSecureStop(byte[] ssid); 5818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 5838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Process the SecureStop server response message ssRelease. After authenticating 584e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * the message, remove the SecureStops identified in the response. 5858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * 5868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @param ssRelease the server response indicating which secure stops to release 5878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 588e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void releaseSecureStops(byte[] ssRelease); 5898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5901b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker /** 5911b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker * Remove all secure stops without requiring interaction with the server. 5921b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker */ 5931b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker public native void releaseAllSecureStops(); 5948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 5958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 596e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: identifies the maker of the DRM engine plugin 597e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 598e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_VENDOR = "vendor"; 599e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 600e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 601e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: identifies the version of the DRM engine plugin 602e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 603e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_VERSION = "version"; 604e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 605e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 606e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: describes the DRM engine plugin 607e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 608e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_DESCRIPTION = "description"; 609e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 610e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 611e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * String property name: a comma-separated list of cipher and mac algorithms 612e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * supported by CryptoSession. The list may be empty if the DRM engine 613e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * plugin does not support CryptoSession operations. 614e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 615f0d4777473f25847d67fc17fc082fada08cf678dJeff Tinker public static final String PROPERTY_ALGORITHMS = "algorithms"; 616e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 617e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 618e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Read a DRM engine plugin String property value, given the property name string. 619e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 6208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Standard fields names are: 621e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION}, 622b5ec8c145d467abbc6eaf3306a5f6725e348ceecKenny Root * {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS} 6238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 624e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native String getPropertyString(String propertyName); 6258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 6268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 6278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker /** 628f0d4777473f25847d67fc17fc082fada08cf678dJeff Tinker * Byte array property name: the device unique identifier is established during 629f0d4777473f25847d67fc17fc082fada08cf678dJeff Tinker * device provisioning and provides a means of uniquely identifying each device. 6308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */ 631e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId"; 632e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 633e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 634e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Read a DRM engine plugin byte array property value, given the property name string. 635e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 636e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID} 637e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 638e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native byte[] getPropertyByteArray(String propertyName); 6398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 6408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 64116b8cffb2893c10c35788191847500004da466d1Jeff Tinker /** 642e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Set a DRM engine plugin String property value. 643e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 644e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void setPropertyString(String propertyName, String value); 645e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 646e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 647e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Set a DRM engine plugin byte array property value. 64816b8cffb2893c10c35788191847500004da466d1Jeff Tinker */ 649e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker public native void setPropertyByteArray(String propertyName, byte[] value); 650e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 65116b8cffb2893c10c35788191847500004da466d1Jeff Tinker 65216b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native void setCipherAlgorithmNative(MediaDrm drm, byte[] sessionId, 6539de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String algorithm); 65416b8cffb2893c10c35788191847500004da466d1Jeff Tinker 65516b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native void setMacAlgorithmNative(MediaDrm drm, byte[] sessionId, 6569de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String algorithm); 65716b8cffb2893c10c35788191847500004da466d1Jeff Tinker 65816b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native byte[] encryptNative(MediaDrm drm, byte[] sessionId, 6599de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker byte[] keyId, byte[] input, byte[] iv); 66016b8cffb2893c10c35788191847500004da466d1Jeff Tinker 66116b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native byte[] decryptNative(MediaDrm drm, byte[] sessionId, 6629de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker byte[] keyId, byte[] input, byte[] iv); 66316b8cffb2893c10c35788191847500004da466d1Jeff Tinker 66416b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native byte[] signNative(MediaDrm drm, byte[] sessionId, 6659de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker byte[] keyId, byte[] message); 66616b8cffb2893c10c35788191847500004da466d1Jeff Tinker 66716b8cffb2893c10c35788191847500004da466d1Jeff Tinker private static final native boolean verifyNative(MediaDrm drm, byte[] sessionId, 6689de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker byte[] keyId, byte[] message, byte[] signature); 66916b8cffb2893c10c35788191847500004da466d1Jeff Tinker 670e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 671e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * In addition to supporting decryption of DASH Common Encrypted Media, the 672e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * MediaDrm APIs provide the ability to securely deliver session keys from 673e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * an operator's session key server to a client device, based on the factory-installed 674e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * root of trust, and then perform encrypt, decrypt, sign and verify operations 675e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * with the session key on arbitrary user data. 676e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 677e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The CryptoSession class implements generic encrypt/decrypt/sign/verify methods 678e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * based on the established session keys. These keys are exchanged using the 679e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * getKeyRequest/provideKeyResponse methods. 680e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 681e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Applications of this capability could include securing various types of 682e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * purchased or private content, such as applications, books and other media, 683e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * photos or media delivery protocols. 684e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 685e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Operators can create session key servers that are functionally similar to a 686e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * license key server, except that instead of receiving license key requests and 687e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * providing encrypted content keys which are used specifically to decrypt A/V media 688e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * content, the session key server receives session key requests and provides 689e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * encrypted session keys which can be used for general purpose crypto operations. 690e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 691e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * A CryptoSession is obtained using {@link #getCryptoSession} 692e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 69316b8cffb2893c10c35788191847500004da466d1Jeff Tinker public final class CryptoSession { 69416b8cffb2893c10c35788191847500004da466d1Jeff Tinker private MediaDrm mDrm; 69516b8cffb2893c10c35788191847500004da466d1Jeff Tinker private byte[] mSessionId; 69616b8cffb2893c10c35788191847500004da466d1Jeff Tinker 697e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker CryptoSession(MediaDrm drm, byte[] sessionId, 6989de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String cipherAlgorithm, String macAlgorithm) 699e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker { 70016b8cffb2893c10c35788191847500004da466d1Jeff Tinker mSessionId = sessionId; 70116b8cffb2893c10c35788191847500004da466d1Jeff Tinker mDrm = drm; 70216b8cffb2893c10c35788191847500004da466d1Jeff Tinker setCipherAlgorithmNative(drm, sessionId, cipherAlgorithm); 70316b8cffb2893c10c35788191847500004da466d1Jeff Tinker setMacAlgorithmNative(drm, sessionId, macAlgorithm); 70416b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 70516b8cffb2893c10c35788191847500004da466d1Jeff Tinker 706e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 707e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Encrypt data using the CryptoSession's cipher algorithm 708e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 709e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 710e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param input the data to encrypt 711e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param iv the initialization vector to use for the cipher 712e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 71316b8cffb2893c10c35788191847500004da466d1Jeff Tinker public byte[] encrypt(byte[] keyid, byte[] input, byte[] iv) { 71416b8cffb2893c10c35788191847500004da466d1Jeff Tinker return encryptNative(mDrm, mSessionId, keyid, input, iv); 71516b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 71616b8cffb2893c10c35788191847500004da466d1Jeff Tinker 717e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 718e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Decrypt data using the CryptoSessions's cipher algorithm 719e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 720e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 721e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param input the data to encrypt 722e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param iv the initialization vector to use for the cipher 723e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 72416b8cffb2893c10c35788191847500004da466d1Jeff Tinker public byte[] decrypt(byte[] keyid, byte[] input, byte[] iv) { 72516b8cffb2893c10c35788191847500004da466d1Jeff Tinker return decryptNative(mDrm, mSessionId, keyid, input, iv); 72616b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 72716b8cffb2893c10c35788191847500004da466d1Jeff Tinker 728e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 729e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Sign data using the CryptoSessions's mac algorithm. 730e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 731e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 732e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param message the data for which a signature is to be computed 733e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 73416b8cffb2893c10c35788191847500004da466d1Jeff Tinker public byte[] sign(byte[] keyid, byte[] message) { 73516b8cffb2893c10c35788191847500004da466d1Jeff Tinker return signNative(mDrm, mSessionId, keyid, message); 73616b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 737e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker 738e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 739e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Verify a signature using the CryptoSessions's mac algorithm. Return true 740e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * if the signatures match, false if they do no. 741e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 742e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param keyid specifies which key to use 743e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param message the data to verify 744e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param signature the reference signature which will be compared with the 745e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * computed signature 746e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 74716b8cffb2893c10c35788191847500004da466d1Jeff Tinker public boolean verify(byte[] keyid, byte[] message, byte[] signature) { 74816b8cffb2893c10c35788191847500004da466d1Jeff Tinker return verifyNative(mDrm, mSessionId, keyid, message, signature); 74916b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 75016b8cffb2893c10c35788191847500004da466d1Jeff Tinker }; 75116b8cffb2893c10c35788191847500004da466d1Jeff Tinker 752e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker /** 753e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Obtain a CryptoSession object which can be used to encrypt, decrypt, 754e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * sign and verify messages or data using the session keys established 755e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * for the session using methods {@link #getKeyRequest} and 756e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * {@link #provideKeyResponse} using a session key server. 757e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * 758e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param sessionId the session ID for the session containing keys 759e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * to be used for encrypt, decrypt, sign and/or verify 760e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param cipherAlgorithm the algorithm to use for encryption and 761e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * decryption ciphers. The algorithm string conforms to JCA Standard 762e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Names for Cipher Transforms and is case insensitive. For example 763e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * "AES/CBC/NoPadding". 764e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * @param macAlgorithm the algorithm to use for sign and verify 765e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The algorithm string conforms to JCA Standard Names for Mac 766e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * Algorithms and is case insensitive. For example "HmacSHA256". 767e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * <p> 768e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * The list of supported algorithms for a DRM engine plugin can be obtained 769e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * using the method {@link #getPropertyString} with the property name 770e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker * "algorithms". 771e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker */ 77216b8cffb2893c10c35788191847500004da466d1Jeff Tinker public CryptoSession getCryptoSession(byte[] sessionId, 7739de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String cipherAlgorithm, String macAlgorithm) 774e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker { 77516b8cffb2893c10c35788191847500004da466d1Jeff Tinker return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm); 77616b8cffb2893c10c35788191847500004da466d1Jeff Tinker } 77716b8cffb2893c10c35788191847500004da466d1Jeff Tinker 778e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 779e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Contains the opaque data an app uses to request a certificate from a provisioning 780e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * server 781e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 782e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @hide - not part of the public API at this time 783e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 784e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public final static class CertificateRequest { 785e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private byte[] mData; 786e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private String mDefaultUrl; 787e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 788e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker CertificateRequest(byte[] data, String defaultUrl) { 789e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker mData = data; 790e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker mDefaultUrl = defaultUrl; 791e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 792e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 793e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 794e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Get the opaque message data 795e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 796e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public byte[] getData() { return mData; } 797e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 798e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 799e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Get the default URL to use when sending the certificate request 800e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * message to a server, if known. The app may prefer to use a different 801e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * certificate server URL obtained from other sources. 802e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 803e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public String getDefaultUrl() { return mDefaultUrl; } 804e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 805e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 806e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 807e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Generate a certificate request, specifying the certificate type 808e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * and authority. The response received should be passed to 809e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * provideCertificateResponse. 810e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 811e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @param certType Specifies the certificate type. 812e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 813e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @param certAuthority is passed to the certificate server to specify 814e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * the chain of authority. 815e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 816e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @hide - not part of the public API at this time 817e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 818e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public CertificateRequest getCertificateRequest(int certType, 8199de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String certAuthority) 820e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker { 821e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority); 822e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker return new CertificateRequest(provisionRequest.getData(), 8239de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker provisionRequest.getDefaultUrl()); 824e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 825e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 826e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 827e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Contains the wrapped private key and public certificate data associated 828e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * with a certificate. 829e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 830e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @hide - not part of the public API at this time 831e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 832e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public final static class Certificate { 833e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker Certificate() {} 834e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 835e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 836e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Get the wrapped private key data 837e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 838e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public byte[] getWrappedPrivateKey() { return mWrappedKey; } 839e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 840e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 841e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Get the PEM-encoded certificate chain 842e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 843e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public byte[] getContent() { return mCertificateData; } 844e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 845e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private byte[] mWrappedKey; 846e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private byte[] mCertificateData; 847e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 848e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 849e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 850e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 851e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Process a response from the certificate server. The response 852e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * is obtained from an HTTP Post to the url provided by getCertificateRequest. 853e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * <p> 854e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * The public X509 certificate chain and wrapped private key are returned 855e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * in the returned Certificate objec. The certificate chain is in PEM format. 856e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * The wrapped private key should be stored in application private 857e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * storage, and used when invoking the signRSA method. 858e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 859e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @param response the opaque certificate response byte array to provide to the 860e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * DRM engine plugin. 861e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 862e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @throws DeniedByServerException if the response indicates that the 863e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * server rejected the request 864e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 865e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @hide - not part of the public API at this time 866e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 867e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker public Certificate provideCertificateResponse(byte[] response) 8689de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker throws DeniedByServerException { 869e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker return provideProvisionResponseNative(response); 870e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 871e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 872e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId, 8739de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker String algorithm, byte[] wrappedKey, byte[] message); 874e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 875e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker /** 876e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * Sign data using an RSA key 877e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 878e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @param sessionId a sessionId obtained from openSession on the MediaDrm object 879e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1" 880e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @param wrappedKey - the wrapped (encrypted) RSA private key obtained 881e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * from provideCertificateResponse 882e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @param message the data for which a signature is to be computed 883e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * 884e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker * @hide - not part of the public API at this time 885e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker */ 8869de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker public byte[] signRSA(byte[] sessionId, String algorithm, 8879de8c1d82b6bf2b70e854a3349c9f1da60a23e83Jeff Tinker byte[] wrappedKey, byte[] message) { 888e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker return signRSANative(this, sessionId, algorithm, wrappedKey, message); 889e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker } 890e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker 8918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker @Override 8928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker protected void finalize() { 8938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker native_finalize(); 8948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 8958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 8968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker public native final void release(); 8978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private static native final void native_init(); 8988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 899e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker private native final void native_setup(Object mediadrm_this, byte[] uuid); 9008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 9018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker private native final void native_finalize(); 9028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker 9038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker static { 9048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker System.loadLibrary("media_jni"); 9058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker native_init(); 9068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker } 9078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker} 908