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