18a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker/*
28a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker * Copyright 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 Tinker//#define LOG_NDEBUG 0
188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#define LOG_TAG "MediaDrm-JNI"
198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include <utils/Log.h>
208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include "android_media_MediaDrm.h"
228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include "android_runtime/AndroidRuntime.h"
2487eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include "android_runtime/Log.h"
2554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker#include "android_os_Parcel.h"
268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include "jni.h"
278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include "JNIHelp.h"
288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include <binder/IServiceManager.h>
3054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker#include <binder/Parcel.h>
318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include <media/IDrm.h>
328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include <media/IMediaPlayerService.h>
338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#include <media/stagefright/foundation/ADebug.h>
34f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker#include <media/stagefright/MediaErrors.h>
358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkernamespace android {
378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#define FIND_CLASS(var, className) \
398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    var = env->FindClass(className); \
408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    LOG_FATAL_IF(! var, "Unable to find class " className);
418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    LOG_FATAL_IF(! var, "Unable to find field " fieldName);
458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    LOG_FATAL_IF(! var, "Unable to find method " fieldName);
498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
5154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
5254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    LOG_FATAL_IF(! var, "Unable to find field " fieldName);
5354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
5454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
5554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
5654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    LOG_FATAL_IF(! var, "Unable to find static method " fieldName);
5754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
5854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstruct RequestFields {
608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jfieldID data;
618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jfieldID defaultUrl;
628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker};
638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstruct ArrayListFields {
658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID init;
668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID add;
678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker};
688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstruct HashmapFields {
708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID init;
718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID get;
728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID put;
738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID entrySet;
748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker};
758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstruct SetFields {
778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID iterator;
788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker};
798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstruct IteratorFields {
818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID next;
828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID hasNext;
838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker};
848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstruct EntryFields {
868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID getKey;
878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jmethodID getValue;
888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker};
898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkerstruct EventTypes {
9117b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    jint kEventProvisionRequired;
9217b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    jint kEventKeyRequired;
9317b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    jint kEventKeyExpired;
9417b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    jint kEventVendorDefined;
9554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker} gEventTypes;
9654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
9717b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinkerstruct KeyTypes {
9817b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    jint kKeyTypeStreaming;
9917b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    jint kKeyTypeOffline;
10017b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    jint kKeyTypeRelease;
10117b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker} gKeyTypes;
10217b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker
103e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinkerstruct CertificateTypes {
104e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jint kCertificateTypeNone;
105e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jint kCertificateTypeX509;
106e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker} gCertificateTypes;
107e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
108e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinkerstruct CertificateFields {
109e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jfieldID wrappedPrivateKey;
110e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jfieldID certificateData;
111e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker};
112e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
113d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinkerstruct StateExceptionFields {
114d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    jmethodID init;
115d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    jclass classId;
116d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker};
117d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker
1188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstruct fields_t {
1198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jfieldID context;
12054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    jmethodID post_event;
12116b8cffb2893c10c35788191847500004da466d1Jeff Tinker    RequestFields keyRequest;
1228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    RequestFields provisionRequest;
1238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    ArrayListFields arraylist;
1248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    HashmapFields hashmap;
1258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    SetFields set;
1268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    IteratorFields iterator;
1278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    EntryFields entry;
128e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    CertificateFields certificate;
129d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    StateExceptionFields stateException;
130e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass certificateClassId;
131e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass hashmapClassId;
132e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass arraylistClassId;
133e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass stringClassId;
1348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker};
1358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
1368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic fields_t gFields;
1378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
13854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker// ----------------------------------------------------------------------------
13954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker// ref-counted object for callbacks
14054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkerclass JNIDrmListener: public DrmListener
14154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker{
14254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkerpublic:
14354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
14454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    ~JNIDrmListener();
14554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
14654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkerprivate:
14754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    JNIDrmListener();
14854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    jclass      mClass;     // Reference to MediaDrm class
14954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    jobject     mObject;    // Weak ref to MediaDrm Java object to call on
15054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker};
15154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
15254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff TinkerJNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
15354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker{
15454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    // Hold onto the MediaDrm class for use in calling the static method
15554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    // that posts events to the application thread.
15654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    jclass clazz = env->GetObjectClass(thiz);
15754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    if (clazz == NULL) {
15854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        ALOGE("Can't find android/media/MediaDrm");
159eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/Exception",
160eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "Can't find android/media/MediaDrm");
16154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        return;
16254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    }
16354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    mClass = (jclass)env->NewGlobalRef(clazz);
16454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
16554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    // We use a weak reference so the MediaDrm object can be garbage collected.
16654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    // The reference is only used as a proxy for callbacks.
16754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    mObject  = env->NewGlobalRef(weak_thiz);
16854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker}
16954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
17054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff TinkerJNIDrmListener::~JNIDrmListener()
17154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker{
17254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    // remove global references
17354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    JNIEnv *env = AndroidRuntime::getJNIEnv();
17454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    env->DeleteGlobalRef(mObject);
17554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    env->DeleteGlobalRef(mClass);
17654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker}
17754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
17854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkervoid JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
17954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker                            const Parcel *obj)
18054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker{
18154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    jint jeventType;
18254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
18354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    // translate DrmPlugin event types into their java equivalents
18454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    switch(eventType) {
18554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        case DrmPlugin::kDrmPluginEventProvisionRequired:
18654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            jeventType = gEventTypes.kEventProvisionRequired;
18754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            break;
18854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        case DrmPlugin::kDrmPluginEventKeyNeeded:
18954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            jeventType = gEventTypes.kEventKeyRequired;
19054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            break;
19154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        case DrmPlugin::kDrmPluginEventKeyExpired:
19254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            jeventType = gEventTypes.kEventKeyExpired;
19354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            break;
19454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        case DrmPlugin::kDrmPluginEventVendorDefined:
19554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            jeventType = gEventTypes.kEventVendorDefined;
19654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            break;
19754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        default:
19854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
19954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            return;
20054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    }
20154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
20254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    JNIEnv *env = AndroidRuntime::getJNIEnv();
20354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    if (obj && obj->dataSize() > 0) {
20454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        jobject jParcel = createJavaParcelObject(env);
20554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        if (jParcel != NULL) {
20654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
20754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            nativeParcel->setData(obj->data(), obj->dataSize());
20854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker            env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
20954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker                    jeventType, extra, jParcel);
210265551a164ac7757d1f2dacc0e2ab0afa0f850c7Patrik            env->DeleteLocalRef(jParcel);
21154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        }
21254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    }
21354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
21454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    if (env->ExceptionCheck()) {
21554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        ALOGW("An exception occurred while notifying an event.");
21654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        LOGW_EX(env);
21754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        env->ExceptionClear();
21854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    }
21954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker}
22054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
221d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinkerstatic void throwStateException(JNIEnv *env, const char *msg, status_t err) {
222d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    ALOGE("Illegal state exception: %s (%d)", msg, err);
223d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker
224d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    jobject exception = env->NewObject(gFields.stateException.classId,
225d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker            gFields.stateException.init, static_cast<int>(err),
226d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker            env->NewStringUTF(msg));
227d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    env->Throw(static_cast<jthrowable>(exception));
228d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker}
22954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
2308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic bool throwExceptionAsNecessary(
2318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        JNIEnv *env, status_t err, const char *msg = NULL) {
2328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
233f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    const char *drmMessage = NULL;
234f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker
235f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    switch(err) {
236f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_UNKNOWN:
237f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "General DRM error";
238f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
239f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_NO_LICENSE:
240f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "No license";
241f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
242f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_LICENSE_EXPIRED:
243f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "License expired";
244f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
245f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_SESSION_NOT_OPENED:
246f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "Session not opened";
247f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
248f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
249f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "Not initialized";
250f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
251f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_DECRYPT:
252f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "Decrypt error";
253f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
254f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_CANNOT_HANDLE:
255f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "Unsupported scheme or data format";
256f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
257f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    case ERROR_DRM_TAMPER_DETECTED:
258f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = "Invalid state";
259f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
260f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    default:
261f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        break;
262f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    }
263f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker
264f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    String8 vendorMessage;
265f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
2662979986b576ffbf0e22057cf135626bc54b9880bJeff Tinker        vendorMessage = String8::format("DRM vendor-defined error: %d", err);
267f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        drmMessage = vendorMessage.string();
268f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker    }
269f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker
2708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (err == BAD_VALUE) {
2718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException", msg);
2728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return true;
2731d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker    } else if (err == ERROR_DRM_NOT_PROVISIONED) {
2741d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker        jniThrowException(env, "android/media/NotProvisionedException", msg);
2751d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker        return true;
2763ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    } else if (err == ERROR_DRM_RESOURCE_BUSY) {
2773ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        jniThrowException(env, "android/media/ResourceBusyException", msg);
2783ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        return true;
2791d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker    } else if (err == ERROR_DRM_DEVICE_REVOKED) {
2801d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker        jniThrowException(env, "android/media/DeniedByServerException", msg);
2811d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker        return true;
2828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    } else if (err != OK) {
283f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        String8 errbuf;
284f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        if (drmMessage != NULL) {
285f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker            if (msg == NULL) {
286f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker                msg = drmMessage;
287f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker            } else {
2882979986b576ffbf0e22057cf135626bc54b9880bJeff Tinker                errbuf = String8::format("%s: %s", msg, drmMessage);
289f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker                msg = errbuf.string();
290f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker            }
291f7568b5ee96b3d80721c76ab3d47f1368a99bf98Jeff Tinker        }
292d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker        throwStateException(env, msg, err);
2938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return true;
2948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
2958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return false;
2968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
2978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
2988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
299656fd0402613cec0196d5e2ae0a460d044d2805bAshok Bhat    JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
3008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return jdrm ? jdrm->getDrm() : NULL;
3018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
3028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff TinkerJDrm::JDrm(
3048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        JNIEnv *env, jobject thiz, const uint8_t uuid[16]) {
3058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    mObject = env->NewWeakGlobalRef(thiz);
3068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    mDrm = MakeDrm(uuid);
30754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    if (mDrm != NULL) {
30854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        mDrm->setListener(this);
30954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    }
3108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
3118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff TinkerJDrm::~JDrm() {
3138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env = AndroidRuntime::getJNIEnv();
3148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    env->DeleteWeakGlobalRef(mObject);
3168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    mObject = NULL;
3178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
3188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker// static
3208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkersp<IDrm> JDrm::MakeDrm() {
3218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IServiceManager> sm = defaultServiceManager();
3228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IBinder> binder =
3248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        sm->getService(String16("media.player"));
3258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IMediaPlayerService> service =
3278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        interface_cast<IMediaPlayerService>(binder);
3288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (service == NULL) {
3308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
3318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
3328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = service->makeDrm();
3348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
3368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
3378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
3388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return drm;
3408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
3418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker// static
3438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkersp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) {
3448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = MakeDrm();
3458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
3478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
3488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
3498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    status_t err = drm->createPlugin(uuid);
3518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (err != OK) {
3538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
3548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
3558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return drm;
3578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
3588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
35954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkerstatus_t JDrm::setListener(const sp<DrmListener>& listener) {
36054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    Mutex::Autolock lock(mLock);
36154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    mListener = listener;
36254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    return OK;
36354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker}
36454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
36554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinkervoid JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
36654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    sp<DrmListener> listener;
36754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    mLock.lock();
36854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    listener = mListener;
36954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    mLock.unlock();
37054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
37154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    if (listener != NULL) {
37254cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        Mutex::Autolock lock(mNotifyLock);
37354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        listener->notify(eventType, extra, obj);
37454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    }
37554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker}
37654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
377600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinkervoid JDrm::disconnect() {
378600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinker    if (mDrm != NULL) {
379600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinker        mDrm->destroyPlugin();
380600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinker        mDrm.clear();
381600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinker    }
382600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinker}
383600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinker
38454cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
3858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker// static
3867cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinkerbool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
3878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = MakeDrm();
3888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
3908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return false;
3918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
3928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3937cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker    return drm->isCryptoSchemeSupported(uuid, mimeType);
3948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
3958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
3968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatus_t JDrm::initCheck() const {
3978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return mDrm == NULL ? NO_INIT : OK;
3988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
3998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker// JNI conversion utilities
4018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
4028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> vector;
4038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    size_t length = env->GetArrayLength(byteArray);
4048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    vector.insertAt((size_t)0, length);
4058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
4068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return vector;
4078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
4088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
4108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    size_t length = vector.size();
4118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jbyteArray result = env->NewByteArray(length);
4128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (result != NULL) {
4138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
4148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
4158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return result;
4168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
4178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
4198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    String8 result;
4208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
42154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    const char *s = env->GetStringUTFChars(jstr, NULL);
4228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (s) {
4238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        result = s;
4248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->ReleaseStringUTFChars(jstr, s);
4258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
4268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return result;
4278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
42816b8cffb2893c10c35788191847500004da466d1Jeff Tinker
4298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker/*
4308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    import java.util.HashMap;
4318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    import java.util.Set;
4328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    import java.Map.Entry;
4338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    import jav.util.Iterator;
4348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    HashMap<k, v> hm;
4368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Set<Entry<k, v> > s = hm.entrySet();
4378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Iterator i = s.iterator();
4388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Entry e = s.next();
4398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker*/
4408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
442e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass clazz = gFields.stringClassId;
4438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    KeyedVector<String8, String8> keyedVector;
4448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
4468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (entrySet) {
4478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
4488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        if (iterator) {
4498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
4508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            while (hasNext) {
4518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
4528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                if (entry) {
4538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
4548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    if (!env->IsInstanceOf(obj, clazz)) {
455eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                        jniThrowException(env, "java/lang/IllegalArgumentException",
456eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                                          "HashMap key is not a String");
4578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    }
4588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    jstring jkey = static_cast<jstring>(obj);
4598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    obj = env->CallObjectMethod(entry, gFields.entry.getValue);
4618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    if (!env->IsInstanceOf(obj, clazz)) {
462eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                        jniThrowException(env, "java/lang/IllegalArgumentException",
463eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                                          "HashMap value is not a String");
4648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    }
4658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    jstring jvalue = static_cast<jstring>(obj);
4668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    String8 key = JStringToString8(env, jkey);
4688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    String8 value = JStringToString8(env, jvalue);
4698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    keyedVector.add(key, value);
4708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    env->DeleteLocalRef(jkey);
4728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    env->DeleteLocalRef(jvalue);
4738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                    hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
4748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                }
4758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                env->DeleteLocalRef(entry);
4768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            }
4778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker            env->DeleteLocalRef(iterator);
4788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        }
4798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->DeleteLocalRef(entrySet);
4808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
4818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return keyedVector;
4828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
4838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
485e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass clazz = gFields.hashmapClassId;
4868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
4878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    for (size_t i = 0; i < map.size(); ++i) {
4888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jstring jkey = env->NewStringUTF(map.keyAt(i).string());
4898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
4908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
4918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->DeleteLocalRef(jkey);
4928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->DeleteLocalRef(jvalue);
4938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
4948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return hashMap;
4958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
4968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
4978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
4988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                                                   List<Vector<uint8_t> > list) {
499e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass clazz = gFields.arraylistClassId;
5008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
5018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    List<Vector<uint8_t> >::iterator iter = list.begin();
5028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    while (iter != list.end()) {
5038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jbyteArray byteArray = VectorToJByteArray(env, *iter);
5048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
5058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->DeleteLocalRef(byteArray);
5068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        iter++;
5078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
5088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return arrayList;
5108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
5118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}  // namespace android
5138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerusing namespace android;
5158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic sp<JDrm> setDrm(
5178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
518656fd0402613cec0196d5e2ae0a460d044d2805bAshok Bhat    sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
5198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm != NULL) {
5208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        drm->incStrong(thiz);
5218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
5228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (old != NULL) {
5238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        old->decStrong(thiz);
5248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
525f11dd63e0c5c8cf02d382351004000b243013b5fNarayan Kamath    env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
5268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return old;
5288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
5298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
5318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker{
5328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
533eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
5348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return false;
5358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
5368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (jsessionId == NULL) {
538eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
5398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return false;
5408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
5418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return true;
5428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
5438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) {
54554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    sp<JDrm> drm = setDrm(env, thiz, NULL);
54654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    if (drm != NULL) {
54754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker        drm->setListener(NULL);
548600071ca78bb3fa52b4b3e04112ed6664ffe0e30Jeff Tinker        drm->disconnect();
54954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    }
5508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
5518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic void android_media_MediaDrm_native_init(JNIEnv *env) {
5538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jclass clazz;
5548a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "android/media/MediaDrm");
555656fd0402613cec0196d5e2ae0a460d044d2805bAshok Bhat    GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
55654cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
55754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker                         "(Ljava/lang/Object;IILjava/lang/Object;)V");
55854cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker
55954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    jfieldID field;
560e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
56154cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
562e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
56354cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
564e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
56554cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
566e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
56754cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
5688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
56917b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
57017b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
57117b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
57217b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
57317b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
57417b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
57517b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker
576e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
577e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
578e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
579e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
580e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
58116b8cffb2893c10c35788191847500004da466d1Jeff Tinker    FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
582e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
583e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
5848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
586e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
587e1c76bebef41d362369627ed0c06ea9a01c6bddbJeff Tinker    GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
5888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
589e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
590e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
591e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
59265c94e695929ffa1aaa49d7b5938b34aaf078b6cJeff Tinker    gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
593e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
5948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "java/util/ArrayList");
5958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
5968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
5978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
5988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "java/util/HashMap");
5998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
6008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
6018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
6028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                  "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
6038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
6048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "java/util/Set");
6068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
6078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "java/util/Iterator");
6098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
6108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
6118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "java/util/Map$Entry");
6138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
6148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
615e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
616e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    FIND_CLASS(clazz, "java/util/HashMap");
61765c94e695929ffa1aaa49d7b5938b34aaf078b6cJeff Tinker    gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
618e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
619e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    FIND_CLASS(clazz, "java/lang/String");
62065c94e695929ffa1aaa49d7b5938b34aaf078b6cJeff Tinker    gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
621e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
622e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    FIND_CLASS(clazz, "java/util/ArrayList");
62365c94e695929ffa1aaa49d7b5938b34aaf078b6cJeff Tinker    gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
624d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker
625d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
626d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
627d712e1a387f06fedb33d083730d279b26ed5e399Jeff Tinker    gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
6288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
6298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic void android_media_MediaDrm_native_setup(
6318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        JNIEnv *env, jobject thiz,
6328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jobject weak_this, jbyteArray uuidObj) {
6338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (uuidObj == NULL) {
635eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
6368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return;
6378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
6388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
6408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (uuid.size() != 16) {
642eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException",
643eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "invalid UUID size, expected 16 bytes");
6448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return;
6458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
6468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<JDrm> drm = new JDrm(env, thiz, uuid.array());
6488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    status_t err = drm->initCheck();
6508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6518a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (err != OK) {
6528a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jniThrowException(
6538a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                env,
6541d7c218ba23185c58ae27f59e4ec6b8526b2d04aJeff Tinker                "android/media/UnsupportedSchemeException",
6558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                "Failed to instantiate drm object.");
6568a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return;
6578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
6588a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
65954cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
66054cfbd6dc28334119c33b6a77779bfe244c71e69Jeff Tinker    drm->setListener(listener);
6618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    setDrm(env, thiz, drm);
6628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
6638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic void android_media_MediaDrm_native_finalize(
6658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        JNIEnv *env, jobject thiz) {
6668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    android_media_MediaDrm_release(env, thiz);
6678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
6688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
6707cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray uuidObj, jstring jmimeType) {
6718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (uuidObj == NULL) {
6738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
6748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return false;
6758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
6768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
6788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (uuid.size() != 16) {
6808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jniThrowException(
6818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                env,
6828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker                "java/lang/IllegalArgumentException",
683eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                "invalid UUID size, expected 16 bytes");
6848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return false;
6858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
6868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6877cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker    String8 mimeType;
6887cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker    if (jmimeType != NULL) {
6897cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker        mimeType = JStringToString8(env, jmimeType);
6907cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker    }
6917cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker
6927cda491321b9bd2e8faf956824312ea6a30e6457Jeff Tinker    return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType);
6938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
6948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jbyteArray android_media_MediaDrm_openSession(
6968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz) {
6978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
6988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
6998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
700eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
701eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "MediaDrm obj is null");
7028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
7038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> sessionId;
7068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    status_t err = drm->openSession(sessionId);
7078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
7098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
7108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return VectorToJByteArray(env, sessionId);
7138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
7148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic void android_media_MediaDrm_closeSession(
7168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
7178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
7188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (!CheckSession(env, drm, jsessionId)) {
7208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return;
7218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
7248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    status_t err = drm->closeSession(sessionId);
7268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    throwExceptionAsNecessary(env, err, "Failed to close session");
7288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
7298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
73016b8cffb2893c10c35788191847500004da466d1Jeff Tinkerstatic jobject android_media_MediaDrm_getKeyRequest(
7318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
73216b8cffb2893c10c35788191847500004da466d1Jeff Tinker    jstring jmimeType, jint jkeyType, jobject joptParams) {
7338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
7348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (!CheckSession(env, drm, jsessionId)) {
7368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
7378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
7408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> initData;
7428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (jinitData != NULL) {
7438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        initData = JByteArrayToVector(env, jinitData);
7448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    String8 mimeType;
7478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (jmimeType != NULL) {
7488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        mimeType = JStringToString8(env, jmimeType);
7498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7508a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
75117b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    DrmPlugin::KeyType keyType;
75217b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
75317b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker        keyType = DrmPlugin::kKeyType_Streaming;
75417b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
75517b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker        keyType = DrmPlugin::kKeyType_Offline;
75617b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
75717b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker        keyType = DrmPlugin::kKeyType_Release;
75817b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    } else {
75917b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException",
76017b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker                          "invalid keyType");
76117b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker        return NULL;
76217b8922785987afa002fb5f081781f056e3ca1c7Jeff Tinker    }
7638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    KeyedVector<String8, String8> optParams;
7658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (joptParams != NULL) {
7668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        optParams = HashMapToKeyedVector(env, joptParams);
7678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> request;
7708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    String8 defaultUrl;
7718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
77216b8cffb2893c10c35788191847500004da466d1Jeff Tinker    status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
77316b8cffb2893c10c35788191847500004da466d1Jeff Tinker                                          keyType, optParams, request, defaultUrl);
7748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
77516b8cffb2893c10c35788191847500004da466d1Jeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
7768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
7778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    // Fill out return obj
7808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jclass clazz;
78116b8cffb2893c10c35788191847500004da466d1Jeff Tinker    FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
7828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
78316b8cffb2893c10c35788191847500004da466d1Jeff Tinker    jobject keyObj = NULL;
7848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (clazz) {
78616b8cffb2893c10c35788191847500004da466d1Jeff Tinker        keyObj = env->AllocObject(clazz);
7878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jbyteArray jrequest = VectorToJByteArray(env, request);
78816b8cffb2893c10c35788191847500004da466d1Jeff Tinker        env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
7898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
7908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
79116b8cffb2893c10c35788191847500004da466d1Jeff Tinker        env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
7928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
7938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
79416b8cffb2893c10c35788191847500004da466d1Jeff Tinker    return keyObj;
7958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
7968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
79716b8cffb2893c10c35788191847500004da466d1Jeff Tinkerstatic jbyteArray android_media_MediaDrm_provideKeyResponse(
7988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
7998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
8008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (!CheckSession(env, drm, jsessionId)) {
80216b8cffb2893c10c35788191847500004da466d1Jeff Tinker        return NULL;
8038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
8048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
8068a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (jresponse == NULL) {
808eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException",
809eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "key response is null");
81016b8cffb2893c10c35788191847500004da466d1Jeff Tinker        return NULL;
8118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
8128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
81316b8cffb2893c10c35788191847500004da466d1Jeff Tinker    Vector<uint8_t> keySetId;
8148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
81516b8cffb2893c10c35788191847500004da466d1Jeff Tinker    status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
8168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8178117d8f7023f8981bc4b2651efed5b28104d83d3Jeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
8188117d8f7023f8981bc4b2651efed5b28104d83d3Jeff Tinker        return NULL;
8198117d8f7023f8981bc4b2651efed5b28104d83d3Jeff Tinker    }
82016b8cffb2893c10c35788191847500004da466d1Jeff Tinker    return VectorToJByteArray(env, keySetId);
8218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
8228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
82316b8cffb2893c10c35788191847500004da466d1Jeff Tinkerstatic void android_media_MediaDrm_removeKeys(
82416b8cffb2893c10c35788191847500004da466d1Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
82516b8cffb2893c10c35788191847500004da466d1Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
82616b8cffb2893c10c35788191847500004da466d1Jeff Tinker
82716b8cffb2893c10c35788191847500004da466d1Jeff Tinker    if (jkeysetId == NULL) {
828eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException",
829eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "keySetId is null");
83016b8cffb2893c10c35788191847500004da466d1Jeff Tinker        return;
83116b8cffb2893c10c35788191847500004da466d1Jeff Tinker    }
83216b8cffb2893c10c35788191847500004da466d1Jeff Tinker
83316b8cffb2893c10c35788191847500004da466d1Jeff Tinker    Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
83416b8cffb2893c10c35788191847500004da466d1Jeff Tinker
83516b8cffb2893c10c35788191847500004da466d1Jeff Tinker    status_t err = drm->removeKeys(keySetId);
83616b8cffb2893c10c35788191847500004da466d1Jeff Tinker
83716b8cffb2893c10c35788191847500004da466d1Jeff Tinker    throwExceptionAsNecessary(env, err, "Failed to remove keys");
83816b8cffb2893c10c35788191847500004da466d1Jeff Tinker}
83916b8cffb2893c10c35788191847500004da466d1Jeff Tinker
84016b8cffb2893c10c35788191847500004da466d1Jeff Tinkerstatic void android_media_MediaDrm_restoreKeys(
84116b8cffb2893c10c35788191847500004da466d1Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jsessionId,
84216b8cffb2893c10c35788191847500004da466d1Jeff Tinker    jbyteArray jkeysetId) {
84316b8cffb2893c10c35788191847500004da466d1Jeff Tinker
8448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
8458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (!CheckSession(env, drm, jsessionId)) {
8478a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return;
8488a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
8498a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
85016b8cffb2893c10c35788191847500004da466d1Jeff Tinker    if (jkeysetId == NULL) {
85116b8cffb2893c10c35788191847500004da466d1Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
85216b8cffb2893c10c35788191847500004da466d1Jeff Tinker        return;
85316b8cffb2893c10c35788191847500004da466d1Jeff Tinker    }
85416b8cffb2893c10c35788191847500004da466d1Jeff Tinker
8558a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
85616b8cffb2893c10c35788191847500004da466d1Jeff Tinker    Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
8578a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
85816b8cffb2893c10c35788191847500004da466d1Jeff Tinker    status_t err = drm->restoreKeys(sessionId, keySetId);
8598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
86016b8cffb2893c10c35788191847500004da466d1Jeff Tinker    throwExceptionAsNecessary(env, err, "Failed to restore keys");
8618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
8628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
86316b8cffb2893c10c35788191847500004da466d1Jeff Tinkerstatic jobject android_media_MediaDrm_queryKeyStatus(
8648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
8658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
8668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (!CheckSession(env, drm, jsessionId)) {
8688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
8698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
8708a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
8718a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    KeyedVector<String8, String8> infoMap;
8738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
87416b8cffb2893c10c35788191847500004da466d1Jeff Tinker    status_t err = drm->queryKeyStatus(sessionId, infoMap);
8758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
87616b8cffb2893c10c35788191847500004da466d1Jeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
8778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
8788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
8798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return KeyedVectorToHashMap(env, infoMap);
8818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
8828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
883e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinkerstatic jobject android_media_MediaDrm_getProvisionRequestNative(
884e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
8858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
8868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
888eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
889eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "MediaDrm obj is null");
8908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
8918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
8928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
8938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> request;
8948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    String8 defaultUrl;
8958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
896e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    String8 certType;
897e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    if (jcertType == gCertificateTypes.kCertificateTypeX509) {
898e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        certType = "X.509";
899e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
900e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        certType = "none";
901e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    } else {
902e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        certType = "invalid";
903e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    }
904e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
905e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    String8 certAuthority = JStringToString8(env, jcertAuthority);
906e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
9078a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9088a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
9098a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
9108a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
9118a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9128a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    // Fill out return obj
9138a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jclass clazz;
9148a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
9158a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9168a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    jobject provisionObj = NULL;
9178a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9188a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (clazz) {
9198a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        provisionObj = env->AllocObject(clazz);
9208a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jbyteArray jrequest = VectorToJByteArray(env, request);
9218a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
9228a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9238a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
9248a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
9258a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
9268a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return provisionObj;
9288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
9298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
930e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinkerstatic jobject android_media_MediaDrm_provideProvisionResponseNative(
9318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jresponse) {
9328a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
9338a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
935eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
936eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "MediaDrm obj is null");
937e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        return NULL;
9388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
9398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (jresponse == NULL) {
941eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException",
942eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "provision response is null");
943e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        return NULL;
9448a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
9458a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9468a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
947e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    Vector<uint8_t> certificate, wrappedKey;
948e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
949e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
950e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
951e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    // Fill out return obj
952e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jclass clazz = gFields.certificateClassId;
953e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
954e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    jobject certificateObj = NULL;
955e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker
956e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    if (clazz && certificate.size() && wrappedKey.size()) {
957e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        certificateObj = env->AllocObject(clazz);
958e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        jbyteArray jcertificate = VectorToJByteArray(env, certificate);
959e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
9608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
961e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
962e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker        env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
963e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    }
9648a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9658a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    throwExceptionAsNecessary(env, err, "Failed to handle provision response");
966e4095a80b674642e0e0e8f0883dee3b22f32f19aJeff Tinker    return certificateObj;
9678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
9688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9696bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinkerstatic void android_media_MediaDrm_unprovisionDeviceNative(
9706bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker    JNIEnv *env, jobject thiz) {
9716bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
9726bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker
9736bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker    if (drm == NULL) {
9746bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
9756bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker                          "MediaDrm obj is null");
9766bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker        return;
9776bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker    }
9786bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker
9796bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker    status_t err = drm->unprovisionDevice();
9806bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker
9816bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker    throwExceptionAsNecessary(env, err, "Failed to handle provision response");
9826bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker    return;
9836bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker}
9846bf5b600d6d1e98f7eabbbc884dd286b335acd66Jeff Tinker
9858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jobject android_media_MediaDrm_getSecureStops(
9868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz) {
9878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
9888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
990eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
991eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "MediaDrm obj is null");
9928a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
9938a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
9948a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9958a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    List<Vector<uint8_t> > secureStops;
9968a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9978a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    status_t err = drm->getSecureStops(secureStops);
9988a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
9998a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
10008a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
10018a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
10028a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10038a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return ListOfVectorsToArrayListOfByteArray(env, secureStops);
10048a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
10058a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10061b51c72e910a91e79efe34c6252e01862516e73dJeff Tinkerstatic jbyteArray android_media_MediaDrm_getSecureStop(
10071b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    JNIEnv *env, jobject thiz, jbyteArray ssid) {
10081b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
10091b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10101b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    if (drm == NULL) {
10111b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
10121b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker                          "MediaDrm obj is null");
10131b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker        return NULL;
10141b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    }
10151b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10161b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    Vector<uint8_t> secureStop;
10171b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10181b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
10191b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10201b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
10211b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker        return NULL;
10221b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    }
10231b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10241b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    return VectorToJByteArray(env, secureStop);
10251b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker}
10261b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10278a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic void android_media_MediaDrm_releaseSecureStops(
10288a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
10298a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
10308a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10318a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
1032eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
1033eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "MediaDrm obj is null");
10348a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return;
10358a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
10368a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10378a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
10388a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10398a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    status_t err = drm->releaseSecureStops(ssRelease);
10408a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10418a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    throwExceptionAsNecessary(env, err, "Failed to release secure stops");
10428a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
10438a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10441b51c72e910a91e79efe34c6252e01862516e73dJeff Tinkerstatic void android_media_MediaDrm_releaseAllSecureStops(
10451b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    JNIEnv *env, jobject thiz) {
10461b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
10471b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10481b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    if (drm == NULL) {
10491b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
10501b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker                          "MediaDrm obj is null");
10511b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker        return;
10521b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    }
10531b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10541b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    status_t err = drm->releaseAllSecureStops();
10551b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10561b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker    throwExceptionAsNecessary(env, err, "Failed to release all secure stops");
10571b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker}
10581b51c72e910a91e79efe34c6252e01862516e73dJeff Tinker
10598a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jstring android_media_MediaDrm_getPropertyString(
10608a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jstring jname) {
10618a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
10628a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10638a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
1064eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
1065eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "MediaDrm obj is null");
10668a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
10678a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
10688a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10698a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (jname == NULL) {
1070eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalArgumentException",
1071eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "property name String is null");
10728a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
10738a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
10748a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10758a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    String8 name = JStringToString8(env, jname);
10768a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    String8 value;
10778a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10788a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    status_t err = drm->getPropertyString(name, value);
10798a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10808a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
10818a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker        return NULL;
10828a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    }
10838a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10848a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    return env->NewStringUTF(value.string());
10858a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker}
10868a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10878a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinkerstatic jbyteArray android_media_MediaDrm_getPropertyByteArray(
10888a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    JNIEnv *env, jobject thiz, jstring jname) {
10898a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    sp<IDrm> drm = GetDrm(env, thiz);
10908a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker
10918a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906Jeff Tinker    if (drm == NULL) {
1092eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker        jniThrowException(env, "java/lang/IllegalStateException",
1093eada5376d9c34f77bd3ba86a2ea674e3bde5e961Jeff Tinker                          "MediaDrm obj is null");
1094