MediaDrm.java revision 8a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906
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;
288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerimport android.util.Log;
298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker/**
318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * MediaDrm class can be used in conjunction with {@link android.media.MediaCrypto}
328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * to obtain licenses for decoding encrypted media data.
338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker *
348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Crypto schemes are assigned 16 byte UUIDs,
358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * the method {@link #isCryptoSchemeSupported} can be used to query if a given
368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * scheme is supported on the device.
378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker *
388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * <a name="Callbacks"></a>
398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * <h3>Callbacks</h3>
408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * <p>Applications may want to register for informational events in order
418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * to be informed of some internal state update during playback or streaming.
428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Registration for these events is done via a call to
438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * {@link #setOnEventListener(OnInfoListener)}setOnInfoListener,
448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * In order to receive the respective callback
458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * associated with this listener, applications are required to create
468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * MediaDrm objects on a thread with its own Looper running (main UI
478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * thread by default has a Looper running).
488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker *
498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * @hide -- don't expose yet
508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker */
518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerpublic final class MediaDrm {
528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private final static String TAG = "MediaDrm";
548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private EventHandler mEventHandler;
568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private OnEventListener mOnEventListener;
578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private int mNativeContext;
598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Query if the given scheme identified by its UUID is supported on
628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * this device.
638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param uuid The UUID of the crypto scheme.
648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public static final boolean isCryptoSchemeSupported(UUID uuid) {
668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid));
678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private static final byte[] getByteArrayFromUUID(UUID uuid) {
708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        long msb = uuid.getMostSignificantBits();
718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        long lsb = uuid.getLeastSignificantBits();
728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        byte[] uuidBytes = new byte[16];
748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        for (int i = 0; i < 8; ++i) {
758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            uuidBytes[i] = (byte)(msb >>> (8 * (7 - i)));
768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i)));
778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        }
788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return uuidBytes;
808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid);
838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Instantiate a MediaDrm object using opaque, crypto scheme specific
868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * data.
878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param uuid The UUID of the crypto scheme.
888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public MediaDrm(UUID uuid) throws MediaDrmException {
908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        Looper looper;
918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        if ((looper = Looper.myLooper()) != null) {
928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            mEventHandler = new EventHandler(this, looper);
938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        } else if ((looper = Looper.getMainLooper()) != null) {
948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            mEventHandler = new EventHandler(this, looper);
958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        } else {
968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            mEventHandler = null;
978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        }
988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        /* Native setup requires a weak reference to our object.
1008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         * It's easier to create it here than in C++.
1018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         */
1028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        native_setup(new WeakReference<MediaDrm>(this),
1038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                     getByteArrayFromUUID(uuid));
1048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
1058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
1078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Register a callback to be invoked when an event occurs
1088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
1098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param listener the callback that will be run
1108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
1118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public void setOnEventListener(OnEventListener listener)
1128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    {
1138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        mOnEventListener = listener;
1148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
1158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
1178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Interface definition for a callback to be invoked when a drm event
1188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * occurs.
1198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
1208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public interface OnEventListener
1218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    {
1228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        /**
1238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         * Called when an event occurs that requires the app to be notified
1248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         *
1258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         * @param md the MediaDrm object on which the event occurred
1268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         * @param sessionId the DRM session ID on which the event occurred
1278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         * @param event indicates the event type
1288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         * @param extra an secondary error code
1298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         * @param data optional byte array of data that may be associated with the event
1308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker         */
1318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data);
1328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
1338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /* Do not change these values without updating their counterparts
1358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * in include/media/mediadrm.h!
1368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
1378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private static final int DRM_EVENT = 200;
1388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private class EventHandler extends Handler
1408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    {
1418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        private MediaDrm mMediaDrm;
1428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public EventHandler(MediaDrm md, Looper looper) {
1448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            super(looper);
1458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            mMediaDrm = md;
1468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        }
1478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        @Override
1498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public void handleMessage(Message msg) {
1508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            if (mMediaDrm.mNativeContext == 0) {
1518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                Log.w(TAG, "MediaDrm went away with unhandled events");
1528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                return;
1538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            }
1548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            switch(msg.what) {
1558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            case DRM_EVENT:
1578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")");
1588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                if (mOnEventListener != null) {
1608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    Bundle bundle = msg.getData();
1618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    byte[] sessionId = bundle.getByteArray("sessionId");
1628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    byte[] data = bundle.getByteArray("data");
1638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
1648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                }
1658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                return;
1668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            default:
1688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                Log.e(TAG, "Unknown message type " + msg.what);
1698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                return;
1708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            }
1718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        }
1728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
1738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /*
1758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Called from native code when an interesting event happens.  This method
1768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * just uses the EventHandler system to post the event back to the main app thread.
1778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * We use a weak reference to the original MediaPlayer object so that the native
1788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * code is safe from the object disappearing from underneath it.  (This is
1798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * the cookie passed to native_setup().)
1808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
1818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private static void postEventFromNative(Object mediadrm_ref,
1828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                                            int what, int arg1, int arg2, Object obj)
1838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    {
1848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get();
1858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        if (md == null) {
1868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            return;
1878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        }
1888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        if (md.mEventHandler != null) {
1898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            Message m = md.mEventHandler.obtainMessage(what, arg1, arg2, obj);
1908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            md.mEventHandler.sendMessage(m);
1918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        }
1928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
1938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
1958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *  Open a new session with the MediaDrm object.  A session ID is returned.
1968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
1978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native byte[] openSession() throws MediaDrmException;
1988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *  Close a session on the MediaDrm object.
2018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
2028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native void closeSession(byte[] sessionId) throws MediaDrmException;
2038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public static final int MEDIA_DRM_LICENSE_TYPE_STREAMING = 1;
2058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public static final int MEDIA_DRM_LICENSE_TYPE_OFFLINE = 2;
2068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public final class LicenseRequest {
2088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public LicenseRequest() {}
2098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public byte[] data;
2108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public String defaultUrl;
2118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    };
2128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * A license request/response exchange occurs between the app and a License
2158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Server to obtain the keys required to decrypt the content.  getLicenseRequest()
2168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * is used to obtain an opaque license request byte array that is delivered to the
2178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * license server.  The opaque license request byte array is returned in
2188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * LicenseReqeust.data.  The recommended URL to deliver the license request to is
2198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * returned in LicenseRequest.defaultUrl
2208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
2218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param sessonId the session ID for the drm session
2228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param init container-specific data, its meaning is interpreted based on the
2238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * mime type provided in the mimeType parameter.  It could contain, for example,
2248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * the content ID, key ID or other data obtained from the content metadata that is
2258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * required in generating the license request.
2268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param mimeType identifies the mime type of the content
2278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param licenseType specifes if the license is for streaming or offline content
2288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param optionalParameters are included in the license server request message to
2298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * allow a client application to provide additional message parameters to the server.
2308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
2318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native LicenseRequest getLicenseRequest( byte[] sessionId, byte[] init,
2328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                                                    String mimeType, int licenseType,
2338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                                                    HashMap<String, String> optionalParameters )
2348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
2358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * After a license response is received by the app, it is provided to the DRM plugin
2388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * using provideLicenseResponse.
2398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
2408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param sessionId the session ID for the DRM session
2418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param response the byte array response from the server
2428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
2438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native void provideLicenseResponse( byte[] sessionId, byte[] response )
2448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
2458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Remove the keys associated with a license for a session
2488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param sessionId the session ID for the DRM session
2498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
2508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native void removeLicense( byte[] sessionId ) throws MediaDrmException;
2518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Request an informative description of the license for the session.  The status is
2548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * in the form of {name, value} pairs.  Since DRM license policies vary by vendor,
2558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * the specific status field names are determined by each DRM vendor.  Refer to your
2568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * DRM provider documentation for definitions of the field names for a particular
2578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * DrmEngine.
2588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
2598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param sessionId the session ID for the DRM session
2608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
2618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native HashMap<String, String> queryLicenseStatus( byte[] sessionId )
2628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
2638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public final class ProvisionRequest {
2658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public ProvisionRequest() {}
2668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public byte[] data;
2678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        public String defaultUrl;
2688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
2698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * A provision request/response exchange occurs between the app and a provisioning
2728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * server to retrieve a device certificate.  getProvisionRequest is used to obtain
2738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * an opaque license request byte array that is delivered to the provisioning server.
2748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * The opaque provision request byte array is returned in ProvisionRequest.data
2758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * The recommended URL to deliver the license request to is returned in
2768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * ProvisionRequest.defaultUrl.
2778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
2788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native ProvisionRequest getProvisionRequest() throws MediaDrmException;
2798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * After a provision response is received by the app, it is provided to the DRM
2828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * plugin using this method.
2838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
2848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param response the opaque provisioning response byte array to provide to the
2858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * DrmEngine.
2868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
2878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native void provideProvisionResponse( byte[] response )
2888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
2898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
2918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * A means of enforcing the contractual requirement for a concurrent stream limit
2928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * per subscriber across devices is provided via SecureStop.  SecureStop is a means
2938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * of securely monitoring the lifetime of sessions. Since playback on a device can
2948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * be interrupted due to reboot, power failure, etc. a means of persisting the
2958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * lifetime information on the device is needed.
2968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
2978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * A signed version of the sessionID is written to persistent storage on the device
2988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * when each MediaCrypto object is created. The sessionID is signed by the device
2998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * private key to prevent tampering.
3008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
3018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * In the normal case, playback will be completed, the session destroyed and the
3028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Secure Stops will be queried. The App queries secure stops and forwards the
3038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * secure stop message to the server which verifies the signature and notifies the
3048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * server side database that the session destruction has been confirmed. The persisted
3058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * record on the client is only removed after positive confirmation that the server
3068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * received the message using releaseSecureStops().
3078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
3088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native List<byte[]> getSecureStops() throws MediaDrmException;
3098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
3128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Process the SecureStop server response message ssRelease.  After authenticating
3138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * the message, remove the SecureStops identiied in the response.
3148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
3158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * @param ssRelease the server response indicating which secure stops to release
3168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
3178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native void releaseSecureStops( byte[] ssRelease )
3188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
3198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
3228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Read a Drm plugin property value, given the property name string.  There are several
3238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * forms of property access functions, depending on the data type returned.
3248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *
3258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Standard fields names are:
3268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *   vendor         String - identifies the maker of the plugin
3278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *   version        String - identifies the version of the plugin
3288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *   description    String - describes the plugin
3298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *   deviceUniqueId byte[] - The device unique identifier is established during device
3308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *                             provisioning and provides a means of uniquely identifying
3318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     *                             each device
3328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
3338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native String getPropertyString( String propertyName )
3348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
3358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native byte[] getPropertyByteArray( String propertyName )
3378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
3388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    /**
3408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * Write a Drm plugin property value.  There are several forms of property setting
3418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     * functions, depending on the data type being set.
3428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker     */
3438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native void setPropertyString( String propertyName, String value )
3448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
3458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native void setPropertyByteArray( String propertyName, byte[] value )
3478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
3488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    @Override
3508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    protected void finalize() {
3518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        native_finalize();
3528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
3538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    public native final void release();
3558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private static native final void native_init();
3568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private native final void native_setup(Object mediadrm_this, byte[] uuid)
3588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        throws MediaDrmException;
3598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    private native final void native_finalize();
3618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    static {
3638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        System.loadLibrary("media_jni");
3648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        native_init();
3658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
3668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
367