Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2013, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "MediaDrm-JNI"
     19 #include <utils/Log.h>
     20 
     21 #include "android_media_MediaDrm.h"
     22 #include "android_media_MediaMetricsJNI.h"
     23 #include "android_os_Parcel.h"
     24 #include "android_runtime/AndroidRuntime.h"
     25 #include "android_runtime/Log.h"
     26 #include "android_os_Parcel.h"
     27 #include "jni.h"
     28 #include <nativehelper/JNIHelp.h>
     29 
     30 #include <binder/IServiceManager.h>
     31 #include <binder/Parcel.h>
     32 #include <binder/PersistableBundle.h>
     33 #include <cutils/properties.h>
     34 #include <media/stagefright/foundation/ADebug.h>
     35 #include <media/stagefright/MediaErrors.h>
     36 #include <mediadrm/IDrm.h>
     37 #include <mediadrm/IMediaDrmService.h>
     38 
     39 using ::android::os::PersistableBundle;
     40 
     41 
     42 namespace android {
     43 
     44 #define FIND_CLASS(var, className) \
     45     var = env->FindClass(className); \
     46     LOG_FATAL_IF(! (var), "Unable to find class " className);
     47 
     48 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
     49     var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
     50     LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
     51 
     52 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
     53     var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
     54     LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
     55 
     56 #define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
     57     var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
     58     LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
     59 
     60 #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
     61     var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
     62     LOG_FATAL_IF(! (var), "Unable to find static method " fieldName);
     63 
     64 #define GET_STATIC_OBJECT_FIELD(var, clazz, fieldName) \
     65     var = env->GetStaticObjectField(clazz, fieldName); \
     66     LOG_FATAL_IF(! (var), "Unable to find static object field " fieldName);
     67 
     68 
     69 struct RequestFields {
     70     jfieldID data;
     71     jfieldID defaultUrl;
     72     jfieldID requestType;
     73 };
     74 
     75 struct ArrayListFields {
     76     jmethodID init;
     77     jmethodID add;
     78 };
     79 
     80 struct HashmapFields {
     81     jmethodID init;
     82     jmethodID get;
     83     jmethodID put;
     84     jmethodID entrySet;
     85 };
     86 
     87 struct SetFields {
     88     jmethodID iterator;
     89 };
     90 
     91 struct IteratorFields {
     92     jmethodID next;
     93     jmethodID hasNext;
     94 };
     95 
     96 struct EntryFields {
     97     jmethodID getKey;
     98     jmethodID getValue;
     99 };
    100 
    101 struct EventTypes {
    102     jint kEventProvisionRequired;
    103     jint kEventKeyRequired;
    104     jint kEventKeyExpired;
    105     jint kEventVendorDefined;
    106     jint kEventSessionReclaimed;
    107 } gEventTypes;
    108 
    109 struct EventWhat {
    110     jint kWhatDrmEvent;
    111     jint kWhatExpirationUpdate;
    112     jint kWhatKeyStatusChange;
    113 } gEventWhat;
    114 
    115 struct KeyTypes {
    116     jint kKeyTypeStreaming;
    117     jint kKeyTypeOffline;
    118     jint kKeyTypeRelease;
    119 } gKeyTypes;
    120 
    121 struct KeyRequestTypes {
    122     jint kKeyRequestTypeInitial;
    123     jint kKeyRequestTypeRenewal;
    124     jint kKeyRequestTypeRelease;
    125     jint kKeyRequestTypeNone;
    126     jint kKeyRequestTypeUpdate;
    127 } gKeyRequestTypes;
    128 
    129 struct CertificateTypes {
    130     jint kCertificateTypeNone;
    131     jint kCertificateTypeX509;
    132 } gCertificateTypes;
    133 
    134 struct CertificateFields {
    135     jfieldID wrappedPrivateKey;
    136     jfieldID certificateData;
    137 };
    138 
    139 struct StateExceptionFields {
    140     jmethodID init;
    141     jclass classId;
    142 };
    143 
    144 struct HDCPLevels {
    145     jint kHdcpLevelUnknown;
    146     jint kHdcpNone;
    147     jint kHdcpV1;
    148     jint kHdcpV2;
    149     jint kHdcpV2_1;
    150     jint kHdcpV2_2;
    151     jint kHdcpNoOutput;
    152 } gHdcpLevels;
    153 
    154 struct SecurityLevels {
    155     jint kSecurityLevelUnknown;
    156     jint kSecurityLevelMax;
    157     jint kSecurityLevelSwSecureCrypto;
    158     jint kSecurityLevelSwSecureDecode;
    159     jint kSecurityLevelHwSecureCrypto;
    160     jint kSecurityLevelHwSecureDecode;
    161     jint kSecurityLevelHwSecureAll;
    162 } gSecurityLevels;
    163 
    164 
    165 struct fields_t {
    166     jfieldID context;
    167     jmethodID post_event;
    168     RequestFields keyRequest;
    169     RequestFields provisionRequest;
    170     ArrayListFields arraylist;
    171     HashmapFields hashmap;
    172     SetFields set;
    173     IteratorFields iterator;
    174     EntryFields entry;
    175     CertificateFields certificate;
    176     StateExceptionFields stateException;
    177     jclass certificateClassId;
    178     jclass hashmapClassId;
    179     jclass arraylistClassId;
    180     jclass stringClassId;
    181     jobject bundleCreator;
    182     jmethodID createFromParcelId;
    183     jclass parcelCreatorClassId;
    184 };
    185 
    186 static fields_t gFields;
    187 
    188 namespace {
    189 
    190 // Helper function to convert a native PersistableBundle to a Java
    191 // PersistableBundle.
    192 jobject nativeToJavaPersistableBundle(JNIEnv *env, jobject thiz,
    193                                       PersistableBundle* nativeBundle) {
    194     if (env == NULL || thiz == NULL || nativeBundle == NULL) {
    195         ALOGE("Unexpected NULL parmeter");
    196         return NULL;
    197     }
    198 
    199     // Create a Java parcel with the native parcel data.
    200     // Then create a new PersistableBundle with that parcel as a parameter.
    201     jobject jParcel = android::createJavaParcelObject(env);
    202     if (jParcel == NULL) {
    203       ALOGE("Failed to create a Java Parcel.");
    204       return NULL;
    205     }
    206 
    207     android::Parcel* nativeParcel = android::parcelForJavaObject(env, jParcel);
    208     if (nativeParcel == NULL) {
    209       ALOGE("Failed to get the native Parcel.");
    210       return NULL;
    211     }
    212 
    213     android::status_t result = nativeBundle->writeToParcel(nativeParcel);
    214     nativeParcel->setDataPosition(0);
    215     if (result != android::OK) {
    216       ALOGE("Failed to write nativeBundle to Parcel: %d.", result);
    217       return NULL;
    218     }
    219 
    220     jobject newBundle = env->CallObjectMethod(gFields.bundleCreator,
    221                                               gFields.createFromParcelId,
    222                                               jParcel);
    223     if (newBundle == NULL) {
    224         ALOGE("Failed to create a new PersistableBundle "
    225               "from the createFromParcel call.");
    226     }
    227 
    228     return newBundle;
    229 }
    230 
    231 }  // namespace anonymous
    232 
    233 // ----------------------------------------------------------------------------
    234 // ref-counted object for callbacks
    235 class JNIDrmListener: public DrmListener
    236 {
    237 public:
    238     JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
    239     ~JNIDrmListener();
    240     virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
    241 private:
    242     JNIDrmListener();
    243     jclass      mClass;     // Reference to MediaDrm class
    244     jobject     mObject;    // Weak ref to MediaDrm Java object to call on
    245 };
    246 
    247 JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
    248 {
    249     // Hold onto the MediaDrm class for use in calling the static method
    250     // that posts events to the application thread.
    251     jclass clazz = env->GetObjectClass(thiz);
    252     if (clazz == NULL) {
    253         ALOGE("Can't find android/media/MediaDrm");
    254         jniThrowException(env, "java/lang/Exception",
    255                           "Can't find android/media/MediaDrm");
    256         return;
    257     }
    258     mClass = (jclass)env->NewGlobalRef(clazz);
    259 
    260     // We use a weak reference so the MediaDrm object can be garbage collected.
    261     // The reference is only used as a proxy for callbacks.
    262     mObject  = env->NewGlobalRef(weak_thiz);
    263 }
    264 
    265 JNIDrmListener::~JNIDrmListener()
    266 {
    267     // remove global references
    268     JNIEnv *env = AndroidRuntime::getJNIEnv();
    269     env->DeleteGlobalRef(mObject);
    270     env->DeleteGlobalRef(mClass);
    271 }
    272 
    273 void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
    274                             const Parcel *obj)
    275 {
    276     jint jwhat;
    277     jint jeventType = 0;
    278 
    279     // translate DrmPlugin event types into their java equivalents
    280     switch (eventType) {
    281         case DrmPlugin::kDrmPluginEventProvisionRequired:
    282             jwhat = gEventWhat.kWhatDrmEvent;
    283             jeventType = gEventTypes.kEventProvisionRequired;
    284             break;
    285         case DrmPlugin::kDrmPluginEventKeyNeeded:
    286             jwhat = gEventWhat.kWhatDrmEvent;
    287             jeventType = gEventTypes.kEventKeyRequired;
    288             break;
    289         case DrmPlugin::kDrmPluginEventKeyExpired:
    290             jwhat = gEventWhat.kWhatDrmEvent;
    291             jeventType = gEventTypes.kEventKeyExpired;
    292             break;
    293         case DrmPlugin::kDrmPluginEventVendorDefined:
    294             jwhat = gEventWhat.kWhatDrmEvent;
    295             jeventType = gEventTypes.kEventVendorDefined;
    296             break;
    297         case DrmPlugin::kDrmPluginEventSessionReclaimed:
    298             jwhat = gEventWhat.kWhatDrmEvent;
    299             jeventType = gEventTypes.kEventSessionReclaimed;
    300             break;
    301         case DrmPlugin::kDrmPluginEventExpirationUpdate:
    302             jwhat = gEventWhat.kWhatExpirationUpdate;
    303             break;
    304          case DrmPlugin::kDrmPluginEventKeysChange:
    305             jwhat = gEventWhat.kWhatKeyStatusChange;
    306             break;
    307         default:
    308             ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
    309             return;
    310     }
    311 
    312     JNIEnv *env = AndroidRuntime::getJNIEnv();
    313     if (obj && obj->dataSize() > 0) {
    314         jobject jParcel = createJavaParcelObject(env);
    315         if (jParcel != NULL) {
    316             Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
    317             nativeParcel->setData(obj->data(), obj->dataSize());
    318             env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
    319                     jwhat, jeventType, extra, jParcel);
    320             env->DeleteLocalRef(jParcel);
    321         }
    322     }
    323 
    324     if (env->ExceptionCheck()) {
    325         ALOGW("An exception occurred while notifying an event.");
    326         LOGW_EX(env);
    327         env->ExceptionClear();
    328     }
    329 }
    330 
    331 static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
    332     ALOGE("Illegal state exception: %s (%d)", msg, err);
    333 
    334     jobject exception = env->NewObject(gFields.stateException.classId,
    335             gFields.stateException.init, static_cast<int>(err),
    336             env->NewStringUTF(msg));
    337     env->Throw(static_cast<jthrowable>(exception));
    338 }
    339 
    340 static bool throwExceptionAsNecessary(
    341         JNIEnv *env, status_t err, const char *msg = NULL) {
    342 
    343     const char *drmMessage = NULL;
    344 
    345     switch (err) {
    346     case ERROR_DRM_UNKNOWN:
    347         drmMessage = "General DRM error";
    348         break;
    349     case ERROR_DRM_NO_LICENSE:
    350         drmMessage = "No license";
    351         break;
    352     case ERROR_DRM_LICENSE_EXPIRED:
    353         drmMessage = "License expired";
    354         break;
    355     case ERROR_DRM_SESSION_NOT_OPENED:
    356         drmMessage = "Session not opened";
    357         break;
    358     case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
    359         drmMessage = "Not initialized";
    360         break;
    361     case ERROR_DRM_DECRYPT:
    362         drmMessage = "Decrypt error";
    363         break;
    364     case ERROR_DRM_CANNOT_HANDLE:
    365         drmMessage = "Invalid parameter or data format";
    366         break;
    367     case ERROR_DRM_TAMPER_DETECTED:
    368         drmMessage = "Invalid state";
    369         break;
    370     default:
    371         break;
    372     }
    373 
    374     String8 vendorMessage;
    375     if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
    376         vendorMessage = String8::format("DRM vendor-defined error: %d", err);
    377         drmMessage = vendorMessage.string();
    378     }
    379 
    380     if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
    381         jniThrowException(env, "java/lang/IllegalArgumentException", msg);
    382         return true;
    383     } else if (err == ERROR_DRM_NOT_PROVISIONED) {
    384         jniThrowException(env, "android/media/NotProvisionedException", msg);
    385         return true;
    386     } else if (err == ERROR_DRM_RESOURCE_BUSY) {
    387         jniThrowException(env, "android/media/ResourceBusyException", msg);
    388         return true;
    389     } else if (err == ERROR_DRM_DEVICE_REVOKED) {
    390         jniThrowException(env, "android/media/DeniedByServerException", msg);
    391         return true;
    392     } else if (err == DEAD_OBJECT) {
    393         jniThrowException(env, "android/media/MediaDrmResetException",
    394                 "mediaserver died");
    395         return true;
    396     } else if (err != OK) {
    397         String8 errbuf;
    398         if (drmMessage != NULL) {
    399             if (msg == NULL) {
    400                 msg = drmMessage;
    401             } else {
    402                 errbuf = String8::format("%s: %s", msg, drmMessage);
    403                 msg = errbuf.string();
    404             }
    405         }
    406         throwStateException(env, msg, err);
    407         return true;
    408     }
    409     return false;
    410 }
    411 
    412 static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
    413     JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
    414     return jdrm ? jdrm->getDrm() : NULL;
    415 }
    416 
    417 JDrm::JDrm(
    418         JNIEnv *env, jobject thiz, const uint8_t uuid[16],
    419         const String8 &appPackageName) {
    420     mObject = env->NewWeakGlobalRef(thiz);
    421     mDrm = MakeDrm(uuid, appPackageName);
    422     if (mDrm != NULL) {
    423         mDrm->setListener(this);
    424     }
    425 }
    426 
    427 JDrm::~JDrm() {
    428     JNIEnv *env = AndroidRuntime::getJNIEnv();
    429 
    430     env->DeleteWeakGlobalRef(mObject);
    431     mObject = NULL;
    432 }
    433 
    434 // static
    435 sp<IDrm> JDrm::MakeDrm() {
    436     sp<IServiceManager> sm = defaultServiceManager();
    437 
    438     sp<IBinder> binder = sm->getService(String16("media.drm"));
    439     sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
    440     if (service == NULL) {
    441         return NULL;
    442     }
    443 
    444     sp<IDrm> drm = service->makeDrm();
    445     if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
    446         return NULL;
    447     }
    448 
    449     return drm;
    450 }
    451 
    452 // static
    453 sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
    454     sp<IDrm> drm = MakeDrm();
    455 
    456     if (drm == NULL) {
    457         return NULL;
    458     }
    459 
    460     status_t err = drm->createPlugin(uuid, appPackageName);
    461 
    462     if (err != OK) {
    463         return NULL;
    464     }
    465 
    466     return drm;
    467 }
    468 
    469 status_t JDrm::setListener(const sp<DrmListener>& listener) {
    470     Mutex::Autolock lock(mLock);
    471     mListener = listener;
    472     return OK;
    473 }
    474 
    475 void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
    476     sp<DrmListener> listener;
    477     mLock.lock();
    478     listener = mListener;
    479     mLock.unlock();
    480 
    481     if (listener != NULL) {
    482         Mutex::Autolock lock(mNotifyLock);
    483         listener->notify(eventType, extra, obj);
    484     }
    485 }
    486 
    487 void JDrm::disconnect() {
    488     if (mDrm != NULL) {
    489         mDrm->destroyPlugin();
    490         mDrm.clear();
    491     }
    492 }
    493 
    494 
    495 // static
    496 bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
    497     sp<IDrm> drm = MakeDrm();
    498 
    499     if (drm == NULL) {
    500         return false;
    501     }
    502 
    503     return drm->isCryptoSchemeSupported(uuid, mimeType);
    504 }
    505 
    506 status_t JDrm::initCheck() const {
    507     return mDrm == NULL ? NO_INIT : OK;
    508 }
    509 
    510 // JNI conversion utilities
    511 static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
    512     Vector<uint8_t> vector;
    513     size_t length = env->GetArrayLength(byteArray);
    514     vector.insertAt((size_t)0, length);
    515     env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
    516     return vector;
    517 }
    518 
    519 static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
    520     size_t length = vector.size();
    521     jbyteArray result = env->NewByteArray(length);
    522     if (result != NULL) {
    523         env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
    524     }
    525     return result;
    526 }
    527 
    528 static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
    529     String8 result;
    530 
    531     const char *s = env->GetStringUTFChars(jstr, NULL);
    532     if (s) {
    533         result = s;
    534         env->ReleaseStringUTFChars(jstr, s);
    535     }
    536     return result;
    537 }
    538 
    539 /*
    540     import java.util.HashMap;
    541     import java.util.Set;
    542     import java.Map.Entry;
    543     import jav.util.Iterator;
    544 
    545     HashMap<k, v> hm;
    546     Set<Entry<k, v> > s = hm.entrySet();
    547     Iterator i = s.iterator();
    548     Entry e = s.next();
    549 */
    550 
    551 static KeyedVector<String8, String8> HashMapToKeyedVector(
    552     JNIEnv *env, jobject &hashMap, bool* pIsOK) {
    553     jclass clazz = gFields.stringClassId;
    554     KeyedVector<String8, String8> keyedVector;
    555     *pIsOK = true;
    556 
    557     jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
    558     if (entrySet) {
    559         jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
    560         if (iterator) {
    561             jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
    562             while (hasNext) {
    563                 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
    564                 if (entry) {
    565                     jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
    566                     if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
    567                         jniThrowException(env, "java/lang/IllegalArgumentException",
    568                                           "HashMap key is not a String");
    569                         env->DeleteLocalRef(entry);
    570                         *pIsOK = false;
    571                         break;
    572                     }
    573                     jstring jkey = static_cast<jstring>(obj);
    574 
    575                     obj = env->CallObjectMethod(entry, gFields.entry.getValue);
    576                     if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
    577                         jniThrowException(env, "java/lang/IllegalArgumentException",
    578                                           "HashMap value is not a String");
    579                         env->DeleteLocalRef(entry);
    580                         *pIsOK = false;
    581                         break;
    582                     }
    583                     jstring jvalue = static_cast<jstring>(obj);
    584 
    585                     String8 key = JStringToString8(env, jkey);
    586                     String8 value = JStringToString8(env, jvalue);
    587                     keyedVector.add(key, value);
    588 
    589                     env->DeleteLocalRef(jkey);
    590                     env->DeleteLocalRef(jvalue);
    591                     hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
    592                 }
    593                 env->DeleteLocalRef(entry);
    594             }
    595             env->DeleteLocalRef(iterator);
    596         }
    597         env->DeleteLocalRef(entrySet);
    598     }
    599     return keyedVector;
    600 }
    601 
    602 static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
    603     jclass clazz = gFields.hashmapClassId;
    604     jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
    605     for (size_t i = 0; i < map.size(); ++i) {
    606         jstring jkey = env->NewStringUTF(map.keyAt(i).string());
    607         jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
    608         env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
    609         env->DeleteLocalRef(jkey);
    610         env->DeleteLocalRef(jvalue);
    611     }
    612     return hashMap;
    613 }
    614 
    615 static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
    616                                                    List<Vector<uint8_t> > list) {
    617     jclass clazz = gFields.arraylistClassId;
    618     jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
    619     List<Vector<uint8_t> >::iterator iter = list.begin();
    620     while (iter != list.end()) {
    621         jbyteArray byteArray = VectorToJByteArray(env, *iter);
    622         env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
    623         env->DeleteLocalRef(byteArray);
    624         iter++;
    625     }
    626 
    627     return arrayList;
    628 }
    629 
    630 }  // namespace android
    631 
    632 using namespace android;
    633 
    634 static sp<JDrm> setDrm(
    635         JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
    636     sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
    637     if (drm != NULL) {
    638         drm->incStrong(thiz);
    639     }
    640     if (old != NULL) {
    641         old->decStrong(thiz);
    642     }
    643     env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
    644 
    645     return old;
    646 }
    647 
    648 static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
    649     if (drm == NULL) {
    650         jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
    651         return false;
    652     }
    653     return true;
    654 }
    655 
    656 static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
    657 {
    658     if (!CheckDrm(env, drm)) {
    659         return false;
    660     }
    661 
    662     if (jsessionId == NULL) {
    663         jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
    664         return false;
    665     }
    666     return true;
    667 }
    668 
    669 static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
    670     sp<JDrm> drm = setDrm(env, thiz, NULL);
    671     if (drm != NULL) {
    672         drm->setListener(NULL);
    673         drm->disconnect();
    674     }
    675 }
    676 
    677 static void android_media_MediaDrm_native_init(JNIEnv *env) {
    678     jclass clazz;
    679     FIND_CLASS(clazz, "android/media/MediaDrm");
    680     GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
    681     GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
    682                          "(Ljava/lang/Object;IIILjava/lang/Object;)V");
    683 
    684     jfieldID field;
    685     GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
    686     gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
    687     GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
    688     gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
    689     GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
    690     gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
    691     GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
    692     gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
    693     GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
    694     gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
    695 
    696     GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
    697     gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
    698     GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
    699     gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
    700     GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
    701     gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
    702 
    703     GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
    704     gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
    705     GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
    706     gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
    707     GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
    708     gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
    709 
    710     GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
    711     gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
    712     GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
    713     gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
    714 
    715     GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
    716     gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
    717     GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
    718     gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
    719     GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
    720     gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
    721     GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
    722     gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
    723     GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
    724     gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
    725     GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
    726     gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
    727     GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
    728     gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
    729 
    730     GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
    731     gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
    732     GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
    733     gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
    734     GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
    735     gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
    736     GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
    737     gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
    738     GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
    739     gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
    740     GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
    741     gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
    742 
    743     jmethodID getMaxSecurityLevel;
    744     GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
    745     gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
    746 
    747     FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
    748     GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
    749     GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
    750     GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
    751 
    752     GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
    753     gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
    754     GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
    755     gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
    756     GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
    757     gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
    758     GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
    759     gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
    760     GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
    761     gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
    762 
    763     FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
    764     GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
    765     GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
    766 
    767     FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
    768     GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
    769     GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
    770     gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
    771 
    772     // Metrics-related fields and classes.
    773     FIND_CLASS(clazz, "android/os/PersistableBundle");
    774     jfieldID bundleCreatorId;
    775     GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
    776                         "Landroid/os/Parcelable$Creator;");
    777     jobject bundleCreator;
    778     GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
    779     gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
    780     FIND_CLASS(clazz, "android/os/Parcelable$Creator");
    781     GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
    782                   "(Landroid/os/Parcel;)Ljava/lang/Object;");
    783     gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
    784 
    785     FIND_CLASS(clazz, "java/util/ArrayList");
    786     GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
    787     GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
    788 
    789     FIND_CLASS(clazz, "java/util/HashMap");
    790     GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
    791     GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
    792     GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
    793                   "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
    794     GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
    795 
    796     FIND_CLASS(clazz, "java/util/Set");
    797     GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
    798 
    799     FIND_CLASS(clazz, "java/util/Iterator");
    800     GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
    801     GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
    802 
    803     FIND_CLASS(clazz, "java/util/Map$Entry");
    804     GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
    805     GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
    806 
    807     FIND_CLASS(clazz, "java/util/HashMap");
    808     gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
    809 
    810     FIND_CLASS(clazz, "java/lang/String");
    811     gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
    812 
    813     FIND_CLASS(clazz, "java/util/ArrayList");
    814     gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
    815 
    816     FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
    817     GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
    818     gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
    819 }
    820 
    821 static void android_media_MediaDrm_native_setup(
    822         JNIEnv *env, jobject thiz,
    823         jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
    824 
    825     if (uuidObj == NULL) {
    826         jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
    827         return;
    828     }
    829 
    830     Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
    831 
    832     if (uuid.size() != 16) {
    833         jniThrowException(env, "java/lang/IllegalArgumentException",
    834                           "invalid UUID size, expected 16 bytes");
    835         return;
    836     }
    837 
    838     String8 packageName;
    839     if (jappPackageName == NULL) {
    840         jniThrowException(env, "java/lang/IllegalArgumentException",
    841                           "application package name cannot be null");
    842         return;
    843     }
    844 
    845     packageName = JStringToString8(env, jappPackageName);
    846     sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
    847 
    848     status_t err = drm->initCheck();
    849 
    850     if (err != OK) {
    851         jniThrowException(
    852                 env,
    853                 "android/media/UnsupportedSchemeException",
    854                 "Failed to instantiate drm object.");
    855         return;
    856     }
    857 
    858     sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
    859     drm->setListener(listener);
    860     setDrm(env, thiz, drm);
    861 }
    862 
    863 static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
    864     JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType) {
    865 
    866     if (uuidObj == NULL) {
    867         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    868         return false;
    869     }
    870 
    871     Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
    872 
    873     if (uuid.size() != 16) {
    874         jniThrowException(
    875                 env,
    876                 "java/lang/IllegalArgumentException",
    877                 "invalid UUID size, expected 16 bytes");
    878         return false;
    879     }
    880 
    881     String8 mimeType;
    882     if (jmimeType != NULL) {
    883         mimeType = JStringToString8(env, jmimeType);
    884     }
    885 
    886     return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType);
    887 }
    888 
    889 static jbyteArray android_media_MediaDrm_openSession(
    890         JNIEnv *env, jobject thiz, jint jlevel) {
    891     sp<IDrm> drm = GetDrm(env, thiz);
    892 
    893     if (drm == NULL) {
    894         jniThrowException(env, "java/lang/IllegalStateException",
    895                           "MediaDrm obj is null");
    896         return NULL;
    897     }
    898 
    899     Vector<uint8_t> sessionId;
    900     DrmPlugin::SecurityLevel level;
    901 
    902     if (jlevel == gSecurityLevels.kSecurityLevelMax) {
    903         level = DrmPlugin::kSecurityLevelMax;
    904     }  else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
    905         level = DrmPlugin::kSecurityLevelSwSecureCrypto;
    906     } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
    907         level = DrmPlugin::kSecurityLevelSwSecureDecode;
    908     } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
    909         level = DrmPlugin::kSecurityLevelHwSecureCrypto;
    910     } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
    911         level = DrmPlugin::kSecurityLevelHwSecureDecode;
    912     } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
    913         level = DrmPlugin::kSecurityLevelHwSecureAll;
    914     } else {
    915         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
    916         return NULL;
    917     }
    918 
    919     status_t err = drm->openSession(level, sessionId);
    920 
    921     if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
    922         return NULL;
    923     }
    924 
    925     return VectorToJByteArray(env, sessionId);
    926 }
    927 
    928 static void android_media_MediaDrm_closeSession(
    929     JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
    930     sp<IDrm> drm = GetDrm(env, thiz);
    931 
    932     if (!CheckSession(env, drm, jsessionId)) {
    933         return;
    934     }
    935 
    936     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
    937 
    938     status_t err = drm->closeSession(sessionId);
    939 
    940     throwExceptionAsNecessary(env, err, "Failed to close session");
    941 }
    942 
    943 static jobject android_media_MediaDrm_getKeyRequest(
    944     JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
    945     jstring jmimeType, jint jkeyType, jobject joptParams) {
    946     sp<IDrm> drm = GetDrm(env, thiz);
    947 
    948     if (!CheckSession(env, drm, jsessionId)) {
    949         return NULL;
    950     }
    951 
    952     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
    953 
    954     Vector<uint8_t> initData;
    955     if (jinitData != NULL) {
    956         initData = JByteArrayToVector(env, jinitData);
    957     }
    958 
    959     String8 mimeType;
    960     if (jmimeType != NULL) {
    961         mimeType = JStringToString8(env, jmimeType);
    962     }
    963 
    964     DrmPlugin::KeyType keyType;
    965     if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
    966         keyType = DrmPlugin::kKeyType_Streaming;
    967     } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
    968         keyType = DrmPlugin::kKeyType_Offline;
    969     } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
    970         keyType = DrmPlugin::kKeyType_Release;
    971     } else {
    972         jniThrowException(env, "java/lang/IllegalArgumentException",
    973                           "invalid keyType");
    974         return NULL;
    975     }
    976 
    977     KeyedVector<String8, String8> optParams;
    978     if (joptParams != NULL) {
    979         bool isOK;
    980         optParams = HashMapToKeyedVector(env, joptParams, &isOK);
    981         if (!isOK) {
    982             return NULL;
    983         }
    984     }
    985 
    986     Vector<uint8_t> request;
    987     String8 defaultUrl;
    988     DrmPlugin::KeyRequestType keyRequestType;
    989 
    990     status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
    991             keyType, optParams, request, defaultUrl, &keyRequestType);
    992 
    993     if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
    994         return NULL;
    995     }
    996 
    997     // Fill out return obj
    998     jclass clazz;
    999     FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
   1000 
   1001     jobject keyObj = NULL;
   1002 
   1003     if (clazz) {
   1004         keyObj = env->AllocObject(clazz);
   1005         jbyteArray jrequest = VectorToJByteArray(env, request);
   1006         env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
   1007 
   1008         jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
   1009         env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
   1010 
   1011         switch (keyRequestType) {
   1012             case DrmPlugin::kKeyRequestType_Initial:
   1013                 env->SetIntField(keyObj, gFields.keyRequest.requestType,
   1014                         gKeyRequestTypes.kKeyRequestTypeInitial);
   1015                 break;
   1016             case DrmPlugin::kKeyRequestType_Renewal:
   1017                 env->SetIntField(keyObj, gFields.keyRequest.requestType,
   1018                         gKeyRequestTypes.kKeyRequestTypeRenewal);
   1019                 break;
   1020             case DrmPlugin::kKeyRequestType_Release:
   1021                 env->SetIntField(keyObj, gFields.keyRequest.requestType,
   1022                         gKeyRequestTypes.kKeyRequestTypeRelease);
   1023                 break;
   1024             case DrmPlugin::kKeyRequestType_None:
   1025                 env->SetIntField(keyObj, gFields.keyRequest.requestType,
   1026                         gKeyRequestTypes.kKeyRequestTypeNone);
   1027                 break;
   1028             case DrmPlugin::kKeyRequestType_Update:
   1029                 env->SetIntField(keyObj, gFields.keyRequest.requestType,
   1030                         gKeyRequestTypes.kKeyRequestTypeUpdate);
   1031                 break;
   1032 
   1033             default:
   1034                 throwStateException(env, "DRM plugin failure: unknown key request type",
   1035                         ERROR_DRM_UNKNOWN);
   1036                 break;
   1037         }
   1038     }
   1039 
   1040     return keyObj;
   1041 }
   1042 
   1043 static jbyteArray android_media_MediaDrm_provideKeyResponse(
   1044     JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
   1045     sp<IDrm> drm = GetDrm(env, thiz);
   1046 
   1047     if (!CheckSession(env, drm, jsessionId)) {
   1048         return NULL;
   1049     }
   1050 
   1051     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1052 
   1053     if (jresponse == NULL) {
   1054         jniThrowException(env, "java/lang/IllegalArgumentException",
   1055                           "key response is null");
   1056         return NULL;
   1057     }
   1058     Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
   1059     Vector<uint8_t> keySetId;
   1060 
   1061     status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
   1062 
   1063     if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
   1064         return NULL;
   1065     }
   1066     return VectorToJByteArray(env, keySetId);
   1067 }
   1068 
   1069 static void android_media_MediaDrm_removeKeys(
   1070     JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
   1071     sp<IDrm> drm = GetDrm(env, thiz);
   1072 
   1073     if (jkeysetId == NULL) {
   1074         jniThrowException(env, "java/lang/IllegalArgumentException",
   1075                           "keySetId is null");
   1076         return;
   1077     }
   1078 
   1079     Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
   1080 
   1081     status_t err = drm->removeKeys(keySetId);
   1082 
   1083     throwExceptionAsNecessary(env, err, "Failed to remove keys");
   1084 }
   1085 
   1086 static void android_media_MediaDrm_restoreKeys(
   1087     JNIEnv *env, jobject thiz, jbyteArray jsessionId,
   1088     jbyteArray jkeysetId) {
   1089 
   1090     sp<IDrm> drm = GetDrm(env, thiz);
   1091 
   1092     if (!CheckSession(env, drm, jsessionId)) {
   1093         return;
   1094     }
   1095 
   1096     if (jkeysetId == NULL) {
   1097         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
   1098         return;
   1099     }
   1100 
   1101     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1102     Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
   1103 
   1104     status_t err = drm->restoreKeys(sessionId, keySetId);
   1105 
   1106     throwExceptionAsNecessary(env, err, "Failed to restore keys");
   1107 }
   1108 
   1109 static jobject android_media_MediaDrm_queryKeyStatus(
   1110     JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
   1111     sp<IDrm> drm = GetDrm(env, thiz);
   1112 
   1113     if (!CheckSession(env, drm, jsessionId)) {
   1114         return NULL;
   1115     }
   1116     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1117 
   1118     KeyedVector<String8, String8> infoMap;
   1119 
   1120     status_t err = drm->queryKeyStatus(sessionId, infoMap);
   1121 
   1122     if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
   1123         return NULL;
   1124     }
   1125 
   1126     return KeyedVectorToHashMap(env, infoMap);
   1127 }
   1128 
   1129 static jobject android_media_MediaDrm_getProvisionRequestNative(
   1130     JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
   1131     sp<IDrm> drm = GetDrm(env, thiz);
   1132 
   1133     if (!CheckDrm(env, drm)) {
   1134         return NULL;
   1135     }
   1136 
   1137     Vector<uint8_t> request;
   1138     String8 defaultUrl;
   1139 
   1140     String8 certType;
   1141     if (jcertType == gCertificateTypes.kCertificateTypeX509) {
   1142         certType = "X.509";
   1143     } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
   1144         certType = "none";
   1145     } else {
   1146         certType = "invalid";
   1147     }
   1148 
   1149     String8 certAuthority = JStringToString8(env, jcertAuthority);
   1150     status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
   1151 
   1152     if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
   1153         return NULL;
   1154     }
   1155 
   1156     // Fill out return obj
   1157     jclass clazz;
   1158     FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
   1159 
   1160     jobject provisionObj = NULL;
   1161 
   1162     if (clazz) {
   1163         provisionObj = env->AllocObject(clazz);
   1164         jbyteArray jrequest = VectorToJByteArray(env, request);
   1165         env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
   1166 
   1167         jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
   1168         env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
   1169     }
   1170 
   1171     return provisionObj;
   1172 }
   1173 
   1174 static jobject android_media_MediaDrm_provideProvisionResponseNative(
   1175     JNIEnv *env, jobject thiz, jbyteArray jresponse) {
   1176     sp<IDrm> drm = GetDrm(env, thiz);
   1177 
   1178     if (!CheckDrm(env, drm)) {
   1179         return NULL;
   1180     }
   1181 
   1182     if (jresponse == NULL) {
   1183         jniThrowException(env, "java/lang/IllegalArgumentException",
   1184                           "provision response is null");
   1185         return NULL;
   1186     }
   1187 
   1188     Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
   1189     Vector<uint8_t> certificate, wrappedKey;
   1190 
   1191     status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
   1192 
   1193     // Fill out return obj
   1194     jclass clazz = gFields.certificateClassId;
   1195 
   1196     jobject certificateObj = NULL;
   1197 
   1198     if (clazz && certificate.size() && wrappedKey.size()) {
   1199         certificateObj = env->AllocObject(clazz);
   1200         jbyteArray jcertificate = VectorToJByteArray(env, certificate);
   1201         env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
   1202 
   1203         jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
   1204         env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
   1205     }
   1206 
   1207     throwExceptionAsNecessary(env, err, "Failed to handle provision response");
   1208     return certificateObj;
   1209 }
   1210 
   1211 static jobject android_media_MediaDrm_getSecureStops(
   1212     JNIEnv *env, jobject thiz) {
   1213     sp<IDrm> drm = GetDrm(env, thiz);
   1214 
   1215     if (!CheckDrm(env, drm)) {
   1216         return NULL;
   1217     }
   1218 
   1219     List<Vector<uint8_t> > secureStops;
   1220 
   1221     status_t err = drm->getSecureStops(secureStops);
   1222 
   1223     if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
   1224         return NULL;
   1225     }
   1226 
   1227     return ListOfVectorsToArrayListOfByteArray(env, secureStops);
   1228 }
   1229 
   1230 static jobject android_media_MediaDrm_getSecureStopIds(
   1231     JNIEnv *env, jobject thiz) {
   1232     sp<IDrm> drm = GetDrm(env, thiz);
   1233 
   1234     if (drm == NULL) {
   1235         jniThrowException(env, "java/lang/IllegalStateException",
   1236                           "MediaDrm obj is null");
   1237         return NULL;
   1238     }
   1239 
   1240     List<Vector<uint8_t> > secureStopIds;
   1241 
   1242     status_t err = drm->getSecureStopIds(secureStopIds);
   1243 
   1244     if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
   1245         return NULL;
   1246     }
   1247 
   1248     return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
   1249 }
   1250 
   1251 static jbyteArray android_media_MediaDrm_getSecureStop(
   1252     JNIEnv *env, jobject thiz, jbyteArray ssid) {
   1253     sp<IDrm> drm = GetDrm(env, thiz);
   1254 
   1255     if (!CheckDrm(env, drm)) {
   1256         return NULL;
   1257     }
   1258 
   1259     Vector<uint8_t> secureStop;
   1260 
   1261     status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
   1262 
   1263     if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
   1264         return NULL;
   1265     }
   1266 
   1267     return VectorToJByteArray(env, secureStop);
   1268 }
   1269 
   1270 static void android_media_MediaDrm_releaseSecureStops(
   1271     JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
   1272     sp<IDrm> drm = GetDrm(env, thiz);
   1273 
   1274     if (!CheckDrm(env, drm)) {
   1275         return;
   1276     }
   1277 
   1278     Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
   1279 
   1280     status_t err = drm->releaseSecureStops(ssRelease);
   1281 
   1282     throwExceptionAsNecessary(env, err, "Failed to release secure stops");
   1283 }
   1284 
   1285 static void android_media_MediaDrm_removeSecureStop(
   1286         JNIEnv *env, jobject thiz, jbyteArray ssid) {
   1287     sp<IDrm> drm = GetDrm(env, thiz);
   1288 
   1289     if (drm == NULL) {
   1290         jniThrowException(env, "java/lang/IllegalStateException",
   1291                           "MediaDrm obj is null");
   1292         return;
   1293     }
   1294 
   1295     status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
   1296 
   1297     throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
   1298 }
   1299 
   1300 static void android_media_MediaDrm_removeAllSecureStops(
   1301     JNIEnv *env, jobject thiz) {
   1302     sp<IDrm> drm = GetDrm(env, thiz);
   1303 
   1304     if (!CheckDrm(env, drm)) {
   1305         return;
   1306     }
   1307 
   1308     status_t err = drm->removeAllSecureStops();
   1309 
   1310     throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
   1311 }
   1312 
   1313 
   1314 static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
   1315     switch(level) {
   1316     case DrmPlugin::kHdcpLevelUnknown:
   1317         return gHdcpLevels.kHdcpLevelUnknown;
   1318     case DrmPlugin::kHdcpNone:
   1319         return gHdcpLevels.kHdcpNone;
   1320     case DrmPlugin::kHdcpV1:
   1321         return gHdcpLevels.kHdcpV1;
   1322     case DrmPlugin::kHdcpV2:
   1323         return gHdcpLevels.kHdcpV2;
   1324     case DrmPlugin::kHdcpV2_1:
   1325         return gHdcpLevels.kHdcpV2_1;
   1326     case DrmPlugin::kHdcpV2_2:
   1327         return gHdcpLevels.kHdcpV2_2;
   1328     case DrmPlugin::kHdcpNoOutput:
   1329         return gHdcpLevels.kHdcpNoOutput;
   1330     }
   1331     return gHdcpLevels.kHdcpNone;
   1332 }
   1333 
   1334 static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
   1335         jobject thiz) {
   1336     sp<IDrm> drm = GetDrm(env, thiz);
   1337 
   1338     if (!CheckDrm(env, drm)) {
   1339         return gHdcpLevels.kHdcpNone;
   1340     }
   1341 
   1342     DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
   1343     DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
   1344 
   1345     status_t err = drm->getHdcpLevels(&connected, &max);
   1346 
   1347     if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
   1348         return gHdcpLevels.kHdcpLevelUnknown;
   1349     }
   1350     return HdcpLevelTojint(connected);
   1351 }
   1352 
   1353 static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
   1354         jobject thiz) {
   1355     sp<IDrm> drm = GetDrm(env, thiz);
   1356 
   1357     if (!CheckDrm(env, drm)) {
   1358         return gHdcpLevels.kHdcpLevelUnknown;
   1359     }
   1360 
   1361     DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
   1362     DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
   1363 
   1364     status_t err = drm->getHdcpLevels(&connected, &max);
   1365 
   1366     if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
   1367         return gHdcpLevels.kHdcpLevelUnknown;
   1368     }
   1369     return HdcpLevelTojint(max);
   1370 }
   1371 
   1372 static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
   1373         jobject thiz) {
   1374     sp<IDrm> drm = GetDrm(env, thiz);
   1375 
   1376     if (!CheckDrm(env, drm)) {
   1377         return 0;
   1378     }
   1379 
   1380     uint32_t open = 0, max = 0;
   1381     status_t err = drm->getNumberOfSessions(&open, &max);
   1382 
   1383     if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
   1384         return 0;
   1385     }
   1386     return open;
   1387 }
   1388 
   1389 static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
   1390         jobject thiz) {
   1391     sp<IDrm> drm = GetDrm(env, thiz);
   1392 
   1393     if (!CheckDrm(env, drm)) {
   1394         return 0;
   1395     }
   1396 
   1397     uint32_t open = 0, max = 0;
   1398     status_t err = drm->getNumberOfSessions(&open, &max);
   1399 
   1400     if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
   1401         return 0;
   1402     }
   1403     return max;
   1404 }
   1405 
   1406 static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
   1407         jobject thiz, jbyteArray jsessionId) {
   1408     sp<IDrm> drm = GetDrm(env, thiz);
   1409 
   1410     if (!CheckSession(env, drm, jsessionId)) {
   1411         return gSecurityLevels.kSecurityLevelUnknown;
   1412     }
   1413 
   1414     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1415 
   1416     DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
   1417 
   1418     status_t err = drm->getSecurityLevel(sessionId, &level);
   1419 
   1420     if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
   1421         return gSecurityLevels.kSecurityLevelUnknown;
   1422     }
   1423 
   1424     switch(level) {
   1425     case DrmPlugin::kSecurityLevelSwSecureCrypto:
   1426         return gSecurityLevels.kSecurityLevelSwSecureCrypto;
   1427     case DrmPlugin::kSecurityLevelSwSecureDecode:
   1428         return gSecurityLevels.kSecurityLevelSwSecureDecode;
   1429     case DrmPlugin::kSecurityLevelHwSecureCrypto:
   1430         return gSecurityLevels.kSecurityLevelHwSecureCrypto;
   1431     case DrmPlugin::kSecurityLevelHwSecureDecode:
   1432         return gSecurityLevels.kSecurityLevelHwSecureDecode;
   1433     case DrmPlugin::kSecurityLevelHwSecureAll:
   1434         return gSecurityLevels.kSecurityLevelHwSecureAll;
   1435     default:
   1436         return gSecurityLevels.kSecurityLevelUnknown;
   1437     }
   1438 }
   1439 
   1440 
   1441 static jstring android_media_MediaDrm_getPropertyString(
   1442     JNIEnv *env, jobject thiz, jstring jname) {
   1443     sp<IDrm> drm = GetDrm(env, thiz);
   1444 
   1445     if (!CheckDrm(env, drm)) {
   1446         return NULL;
   1447     }
   1448 
   1449     if (jname == NULL) {
   1450         jniThrowException(env, "java/lang/IllegalArgumentException",
   1451                           "property name String is null");
   1452         return NULL;
   1453     }
   1454 
   1455     String8 name = JStringToString8(env, jname);
   1456     String8 value;
   1457 
   1458     status_t err = drm->getPropertyString(name, value);
   1459 
   1460     if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
   1461         return NULL;
   1462     }
   1463 
   1464     return env->NewStringUTF(value.string());
   1465 }
   1466 
   1467 static jbyteArray android_media_MediaDrm_getPropertyByteArray(
   1468     JNIEnv *env, jobject thiz, jstring jname) {
   1469     sp<IDrm> drm = GetDrm(env, thiz);
   1470 
   1471     if (!CheckDrm(env, drm)) {
   1472         return NULL;
   1473     }
   1474 
   1475     if (jname == NULL) {
   1476         jniThrowException(env, "java/lang/IllegalArgumentException",
   1477                           "property name String is null");
   1478         return NULL;
   1479     }
   1480 
   1481     String8 name = JStringToString8(env, jname);
   1482     Vector<uint8_t> value;
   1483 
   1484     status_t err = drm->getPropertyByteArray(name, value);
   1485 
   1486     if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
   1487         return NULL;
   1488     }
   1489 
   1490     return VectorToJByteArray(env, value);
   1491 }
   1492 
   1493 static void android_media_MediaDrm_setPropertyString(
   1494     JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
   1495     sp<IDrm> drm = GetDrm(env, thiz);
   1496 
   1497     if (!CheckDrm(env, drm)) {
   1498         return;
   1499     }
   1500 
   1501     if (jname == NULL) {
   1502         jniThrowException(env, "java/lang/IllegalArgumentException",
   1503                           "property name String is null");
   1504         return;
   1505     }
   1506 
   1507     if (jvalue == NULL) {
   1508         jniThrowException(env, "java/lang/IllegalArgumentException",
   1509                           "property value String is null");
   1510         return;
   1511     }
   1512 
   1513     String8 name = JStringToString8(env, jname);
   1514     String8 value = JStringToString8(env, jvalue);
   1515 
   1516     status_t err = drm->setPropertyString(name, value);
   1517 
   1518     throwExceptionAsNecessary(env, err, "Failed to set property");
   1519 }
   1520 
   1521 static void android_media_MediaDrm_setPropertyByteArray(
   1522     JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
   1523     sp<IDrm> drm = GetDrm(env, thiz);
   1524 
   1525     if (!CheckDrm(env, drm)) {
   1526         return;
   1527     }
   1528 
   1529     if (jname == NULL) {
   1530         jniThrowException(env, "java/lang/IllegalArgumentException",
   1531                           "property name String is null");
   1532         return;
   1533     }
   1534 
   1535     if (jvalue == NULL) {
   1536         jniThrowException(env, "java/lang/IllegalArgumentException",
   1537                           "property value byte array is null");
   1538         return;
   1539     }
   1540 
   1541     String8 name = JStringToString8(env, jname);
   1542     Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
   1543 
   1544     status_t err = drm->setPropertyByteArray(name, value);
   1545 
   1546     throwExceptionAsNecessary(env, err, "Failed to set property");
   1547 }
   1548 
   1549 static void android_media_MediaDrm_setCipherAlgorithmNative(
   1550     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
   1551     jstring jalgorithm) {
   1552 
   1553     sp<IDrm> drm = GetDrm(env, jdrm);
   1554 
   1555     if (!CheckSession(env, drm, jsessionId)) {
   1556         return;
   1557     }
   1558 
   1559     if (jalgorithm == NULL) {
   1560         jniThrowException(env, "java/lang/IllegalArgumentException",
   1561                           "algorithm String is null");
   1562         return;
   1563     }
   1564 
   1565     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1566     String8 algorithm = JStringToString8(env, jalgorithm);
   1567 
   1568     status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
   1569 
   1570     throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
   1571 }
   1572 
   1573 static void android_media_MediaDrm_setMacAlgorithmNative(
   1574     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
   1575     jstring jalgorithm) {
   1576 
   1577     sp<IDrm> drm = GetDrm(env, jdrm);
   1578 
   1579     if (!CheckSession(env, drm, jsessionId)) {
   1580         return;
   1581     }
   1582 
   1583     if (jalgorithm == NULL) {
   1584         jniThrowException(env, "java/lang/IllegalArgumentException",
   1585                           "algorithm String is null");
   1586         return;
   1587     }
   1588 
   1589     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1590     String8 algorithm = JStringToString8(env, jalgorithm);
   1591 
   1592     status_t err = drm->setMacAlgorithm(sessionId, algorithm);
   1593 
   1594     throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
   1595 }
   1596 
   1597 
   1598 static jbyteArray android_media_MediaDrm_encryptNative(
   1599     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
   1600     jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
   1601 
   1602     sp<IDrm> drm = GetDrm(env, jdrm);
   1603 
   1604     if (!CheckSession(env, drm, jsessionId)) {
   1605         return NULL;
   1606     }
   1607 
   1608     if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
   1609         jniThrowException(env, "java/lang/IllegalArgumentException",
   1610                           "required argument is null");
   1611         return NULL;
   1612     }
   1613 
   1614     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1615     Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
   1616     Vector<uint8_t> input(JByteArrayToVector(env, jinput));
   1617     Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
   1618     Vector<uint8_t> output;
   1619 
   1620     status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
   1621 
   1622     if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
   1623         return NULL;
   1624     }
   1625 
   1626     return VectorToJByteArray(env, output);
   1627 }
   1628 
   1629 static jbyteArray android_media_MediaDrm_decryptNative(
   1630     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
   1631     jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
   1632 
   1633     sp<IDrm> drm = GetDrm(env, jdrm);
   1634 
   1635     if (!CheckSession(env, drm, jsessionId)) {
   1636         return NULL;
   1637     }
   1638 
   1639     if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
   1640         jniThrowException(env, "java/lang/IllegalArgumentException",
   1641                           "required argument is null");
   1642         return NULL;
   1643     }
   1644 
   1645     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1646     Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
   1647     Vector<uint8_t> input(JByteArrayToVector(env, jinput));
   1648     Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
   1649     Vector<uint8_t> output;
   1650 
   1651     status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
   1652     if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
   1653         return NULL;
   1654     }
   1655 
   1656     return VectorToJByteArray(env, output);
   1657 }
   1658 
   1659 static jbyteArray android_media_MediaDrm_signNative(
   1660     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
   1661     jbyteArray jkeyId, jbyteArray jmessage) {
   1662 
   1663     sp<IDrm> drm = GetDrm(env, jdrm);
   1664 
   1665     if (!CheckSession(env, drm, jsessionId)) {
   1666         return NULL;
   1667     }
   1668 
   1669     if (jkeyId == NULL || jmessage == NULL) {
   1670         jniThrowException(env, "java/lang/IllegalArgumentException",
   1671                           "required argument is null");
   1672         return NULL;
   1673     }
   1674 
   1675     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1676     Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
   1677     Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
   1678     Vector<uint8_t> signature;
   1679 
   1680     status_t err = drm->sign(sessionId, keyId, message, signature);
   1681 
   1682     if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
   1683         return NULL;
   1684     }
   1685 
   1686     return VectorToJByteArray(env, signature);
   1687 }
   1688 
   1689 static jboolean android_media_MediaDrm_verifyNative(
   1690     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
   1691     jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
   1692 
   1693     sp<IDrm> drm = GetDrm(env, jdrm);
   1694 
   1695     if (!CheckSession(env, drm, jsessionId)) {
   1696         return false;
   1697     }
   1698 
   1699     if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
   1700         jniThrowException(env, "java/lang/IllegalArgumentException",
   1701                           "required argument is null");
   1702         return false;
   1703     }
   1704 
   1705     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1706     Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
   1707     Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
   1708     Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
   1709     bool match;
   1710 
   1711     status_t err = drm->verify(sessionId, keyId, message, signature, match);
   1712 
   1713     throwExceptionAsNecessary(env, err, "Failed to verify");
   1714     return match;
   1715 }
   1716 
   1717 static jobject
   1718 android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
   1719 {
   1720     sp<IDrm> drm = GetDrm(env, thiz);
   1721     if (drm == NULL ) {
   1722         jniThrowException(env, "java/lang/IllegalStateException",
   1723                           "MediaDrm obj is null");
   1724         return NULL;
   1725     }
   1726 
   1727     // Retrieve current metrics snapshot from drm.
   1728     PersistableBundle metrics;
   1729     status_t err = drm->getMetrics(&metrics);
   1730     if (err != OK) {
   1731         ALOGE("getMetrics failed: %d", (int)err);
   1732         return (jobject) NULL;
   1733     }
   1734 
   1735     return nativeToJavaPersistableBundle(env, thiz, &metrics);
   1736 }
   1737 
   1738 static jbyteArray android_media_MediaDrm_signRSANative(
   1739     JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
   1740     jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
   1741 
   1742     sp<IDrm> drm = GetDrm(env, jdrm);
   1743 
   1744     if (!CheckSession(env, drm, jsessionId)) {
   1745         return NULL;
   1746     }
   1747 
   1748     if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
   1749         jniThrowException(env, "java/lang/IllegalArgumentException",
   1750                           "required argument is null");
   1751         return NULL;
   1752     }
   1753 
   1754     Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
   1755     String8 algorithm = JStringToString8(env, jalgorithm);
   1756     Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
   1757     Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
   1758     Vector<uint8_t> signature;
   1759 
   1760     status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
   1761 
   1762     if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
   1763         return NULL;
   1764     }
   1765 
   1766     return VectorToJByteArray(env, signature);
   1767 }
   1768 
   1769 
   1770 static const JNINativeMethod gMethods[] = {
   1771     { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
   1772 
   1773     { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
   1774 
   1775     { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
   1776       (void *)android_media_MediaDrm_native_setup },
   1777 
   1778     { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z",
   1779       (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
   1780 
   1781     { "openSession", "(I)[B",
   1782       (void *)android_media_MediaDrm_openSession },
   1783 
   1784     { "closeSession", "([B)V",
   1785       (void *)android_media_MediaDrm_closeSession },
   1786 
   1787     { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
   1788       "Landroid/media/MediaDrm$KeyRequest;",
   1789       (void *)android_media_MediaDrm_getKeyRequest },
   1790 
   1791     { "provideKeyResponse", "([B[B)[B",
   1792       (void *)android_media_MediaDrm_provideKeyResponse },
   1793 
   1794     { "removeKeys", "([B)V",
   1795       (void *)android_media_MediaDrm_removeKeys },
   1796 
   1797     { "restoreKeys", "([B[B)V",
   1798       (void *)android_media_MediaDrm_restoreKeys },
   1799 
   1800     { "queryKeyStatus", "([B)Ljava/util/HashMap;",
   1801       (void *)android_media_MediaDrm_queryKeyStatus },
   1802 
   1803     { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
   1804       (void *)android_media_MediaDrm_getProvisionRequestNative },
   1805 
   1806     { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
   1807       (void *)android_media_MediaDrm_provideProvisionResponseNative },
   1808 
   1809     { "getSecureStops", "()Ljava/util/List;",
   1810       (void *)android_media_MediaDrm_getSecureStops },
   1811 
   1812     { "getSecureStopIds", "()Ljava/util/List;",
   1813       (void *)android_media_MediaDrm_getSecureStopIds },
   1814 
   1815     { "getSecureStop", "([B)[B",
   1816       (void *)android_media_MediaDrm_getSecureStop },
   1817 
   1818     { "releaseSecureStops", "([B)V",
   1819       (void *)android_media_MediaDrm_releaseSecureStops },
   1820 
   1821     { "removeSecureStop", "([B)V",
   1822       (void *)android_media_MediaDrm_removeSecureStop },
   1823 
   1824     { "removeAllSecureStops", "()V",
   1825       (void *)android_media_MediaDrm_removeAllSecureStops },
   1826 
   1827     { "getConnectedHdcpLevel", "()I",
   1828       (void *)android_media_MediaDrm_getConnectedHdcpLevel },
   1829 
   1830     { "getMaxHdcpLevel", "()I",
   1831       (void *)android_media_MediaDrm_getMaxHdcpLevel },
   1832 
   1833     { "getOpenSessionCount", "()I",
   1834       (void *)android_media_MediaDrm_getOpenSessionCount },
   1835 
   1836     { "getMaxSessionCount", "()I",
   1837       (void *)android_media_MediaDrm_getMaxSessionCount },
   1838 
   1839     { "getSecurityLevel", "([B)I",
   1840       (void *)android_media_MediaDrm_getSecurityLevel },
   1841 
   1842     { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
   1843       (void *)android_media_MediaDrm_getPropertyString },
   1844 
   1845     { "getPropertyByteArray", "(Ljava/lang/String;)[B",
   1846       (void *)android_media_MediaDrm_getPropertyByteArray },
   1847 
   1848     { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
   1849       (void *)android_media_MediaDrm_setPropertyString },
   1850 
   1851     { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
   1852       (void *)android_media_MediaDrm_setPropertyByteArray },
   1853 
   1854     { "setCipherAlgorithmNative",
   1855       "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
   1856       (void *)android_media_MediaDrm_setCipherAlgorithmNative },
   1857 
   1858     { "setMacAlgorithmNative",
   1859       "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
   1860       (void *)android_media_MediaDrm_setMacAlgorithmNative },
   1861 
   1862     { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
   1863       (void *)android_media_MediaDrm_encryptNative },
   1864 
   1865     { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
   1866       (void *)android_media_MediaDrm_decryptNative },
   1867 
   1868     { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
   1869       (void *)android_media_MediaDrm_signNative },
   1870 
   1871     { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
   1872       (void *)android_media_MediaDrm_verifyNative },
   1873 
   1874     { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
   1875       (void *)android_media_MediaDrm_signRSANative },
   1876 
   1877     { "getMetricsNative", "()Landroid/os/PersistableBundle;",
   1878       (void *)android_media_MediaDrm_native_getMetrics },
   1879 };
   1880 
   1881 int register_android_media_Drm(JNIEnv *env) {
   1882     return AndroidRuntime::registerNativeMethods(env,
   1883                 "android/media/MediaDrm", gMethods, NELEM(gMethods));
   1884 }
   1885