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