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