Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2010 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 "android_drm_DrmManagerClient"
     19 #include <utils/Log.h>
     20 
     21 #include <jni.h>
     22 #include <nativehelper/JNIHelp.h>
     23 #include <nativehelper/ScopedLocalRef.h>
     24 #include <android_runtime/AndroidRuntime.h>
     25 
     26 #include <drm/DrmInfo.h>
     27 #include <drm/DrmRights.h>
     28 #include <drm/DrmInfoEvent.h>
     29 #include <drm/DrmInfoStatus.h>
     30 #include <drm/DrmInfoRequest.h>
     31 #include <drm/DrmSupportInfo.h>
     32 #include <drm/DrmConstraints.h>
     33 #include <drm/DrmMetadata.h>
     34 #include <drm/DrmConvertedStatus.h>
     35 #include <drm/drm_framework_common.h>
     36 
     37 #include <DrmManagerClientImpl.h>
     38 
     39 using namespace android;
     40 
     41 /**
     42  * Utility class used to extract the value from the provided java object.
     43  * May need to add some utility function to create java object.
     44  */
     45 class Utility {
     46 public:
     47     static String8 getStringValue(JNIEnv* env, jobject object, const char* fieldName);
     48 
     49     static char* getByteArrayValue(
     50             JNIEnv* env, jobject object, const char* fieldName, int* dataLength);
     51 
     52     static char* getByteArrayValue(
     53             JNIEnv* env, jbyteArray byteArray, int* dataLength);
     54 
     55     static String8 getStringValue(JNIEnv* env, jstring string);
     56 
     57     static int getIntValue(JNIEnv* env, jobject object, const char* fieldName);
     58 };
     59 
     60 String8 Utility::getStringValue(JNIEnv* env, jobject object, const char* fieldName) {
     61     /* Look for the instance field with the name fieldName */
     62     jfieldID fieldID
     63         = env->GetFieldID(env->GetObjectClass(object), fieldName , "Ljava/lang/String;");
     64 
     65     if (NULL != fieldID) {
     66         jstring valueString = (jstring) env->GetObjectField(object, fieldID);
     67         return Utility::getStringValue(env, valueString);
     68     }
     69 
     70     String8 dataString("");
     71     return dataString;
     72 }
     73 
     74 String8 Utility::getStringValue(JNIEnv* env, jstring string) {
     75     String8 dataString("");
     76 
     77     if (NULL != string && string != env->NewStringUTF("")) {
     78         char* bytes = const_cast< char* > (env->GetStringUTFChars(string, NULL));
     79 
     80         const int length = strlen(bytes) + 1;
     81         char *data = new char[length];
     82         strncpy(data, bytes, length);
     83         dataString = String8(data);
     84 
     85         env->ReleaseStringUTFChars(string, bytes);
     86         delete [] data; data = NULL;
     87     }
     88     return dataString;
     89 }
     90 
     91 char* Utility::getByteArrayValue(
     92             JNIEnv* env, jobject object, const char* fieldName, int* dataLength) {
     93 
     94     *dataLength = 0;
     95 
     96     jfieldID fieldID = env->GetFieldID(env->GetObjectClass(object), fieldName , "[B");
     97 
     98     if (NULL != fieldID) {
     99         jbyteArray byteArray = (jbyteArray) env->GetObjectField(object, fieldID);
    100         return Utility::getByteArrayValue(env, byteArray, dataLength);
    101     }
    102     return NULL;
    103 }
    104 
    105 char* Utility::getByteArrayValue(JNIEnv* env, jbyteArray byteArray, int* dataLength) {
    106     char* data = NULL;
    107     if (NULL != byteArray) {
    108         jint length = env->GetArrayLength(byteArray);
    109 
    110         *dataLength = length;
    111         if (0 < *dataLength) {
    112             data = new char[length];
    113             env->GetByteArrayRegion(byteArray, (jint)0, length, (jbyte *) data);
    114         }
    115     }
    116     return data;
    117 }
    118 
    119 int Utility::getIntValue(JNIEnv* env, jobject object, const char* fieldName) {
    120     jfieldID fieldID;
    121     int intValue = -1;
    122 
    123     /* Get a reference to objs class */
    124     jclass clazz = env->GetObjectClass(object);
    125     /* Look for the instance field with the name fieldName */
    126     fieldID = env->GetFieldID(clazz, fieldName , "I");
    127 
    128     if (NULL != fieldID) {
    129         intValue = (int) env->GetIntField(object, fieldID);
    130     }
    131 
    132     return intValue;
    133 }
    134 
    135 class JNIOnInfoListener : public DrmManagerClient::OnInfoListener {
    136 public:
    137     JNIOnInfoListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
    138 
    139     virtual ~JNIOnInfoListener();
    140     void onInfo(const DrmInfoEvent& event);
    141 
    142 private:
    143     JNIOnInfoListener();
    144     jclass mClass;
    145     jobject mObject;
    146 };
    147 
    148 JNIOnInfoListener::JNIOnInfoListener(JNIEnv* env, jobject thiz, jobject weak_thiz) {
    149     jclass clazz = env->GetObjectClass(thiz);
    150 
    151     if (clazz == NULL) {
    152         ALOGE("Can't find android/drm/DrmManagerClient");
    153         jniThrowException(env, "java/lang/Exception", NULL);
    154         return;
    155     }
    156     mClass = (jclass)env->NewGlobalRef(clazz);
    157     mObject  = env->NewGlobalRef(weak_thiz);
    158 }
    159 
    160 JNIOnInfoListener::~JNIOnInfoListener() {
    161     JNIEnv *env = AndroidRuntime::getJNIEnv();
    162     env->DeleteGlobalRef(mObject);
    163     env->DeleteGlobalRef(mClass);
    164 }
    165 
    166 void JNIOnInfoListener::onInfo(const DrmInfoEvent& event) {
    167     jint uniqueId = event.getUniqueId();
    168     jint type = event.getType();
    169     JNIEnv *env = AndroidRuntime::getJNIEnv();
    170     jstring message = env->NewStringUTF(event.getMessage().string());
    171     ALOGV("JNIOnInfoListener::onInfo => %d | %d | %s", uniqueId, type, event.getMessage().string());
    172 
    173     env->CallStaticVoidMethod(
    174             mClass,
    175             env->GetStaticMethodID(mClass, "notify", "(Ljava/lang/Object;IILjava/lang/String;)V"),
    176             mObject, uniqueId, type, message);
    177 }
    178 
    179 static Mutex sLock;
    180 
    181 static sp<DrmManagerClientImpl> setDrmManagerClientImpl(
    182             JNIEnv* env, jobject thiz, const sp<DrmManagerClientImpl>& client) {
    183     Mutex::Autolock l(sLock);
    184     jclass clazz = env->FindClass("android/drm/DrmManagerClient");
    185     jfieldID fieldId = env->GetFieldID(clazz, "mNativeContext", "J");
    186 
    187     jlong oldHandle = env->GetLongField(thiz, fieldId);
    188     sp<DrmManagerClientImpl> old = reinterpret_cast<DrmManagerClientImpl*>(oldHandle);
    189     if (client.get()) {
    190         client->incStrong(thiz);
    191     }
    192     if (old != 0) {
    193         old->decStrong(thiz);
    194     }
    195     env->SetLongField(thiz, fieldId, reinterpret_cast<jlong>(client.get()));
    196     return old;
    197 }
    198 
    199 static sp<DrmManagerClientImpl> getDrmManagerClientImpl(JNIEnv* env, jobject thiz) {
    200     Mutex::Autolock l(sLock);
    201     jclass clazz = env->FindClass("android/drm/DrmManagerClient");
    202     jfieldID fieldId = env->GetFieldID(clazz, "mNativeContext", "J");
    203 
    204     jlong clientHandle = env->GetLongField(thiz, fieldId);
    205     DrmManagerClientImpl* const client = reinterpret_cast<DrmManagerClientImpl*>(clientHandle);
    206     return sp<DrmManagerClientImpl>(client);
    207 }
    208 
    209 static jint android_drm_DrmManagerClient_initialize(
    210         JNIEnv* env, jobject thiz) {
    211     ALOGV("initialize - Enter");
    212 
    213     int uniqueId = 0;
    214     sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false);
    215     drmManager->addClient(uniqueId);
    216 
    217     setDrmManagerClientImpl(env, thiz, drmManager);
    218     ALOGV("initialize - Exit");
    219     return static_cast<jint>(uniqueId);
    220 }
    221 
    222 static void android_drm_DrmManagerClient_setListeners(
    223         JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) {
    224     ALOGV("setListeners - Enter");
    225 
    226     // Set the listener to DrmManager
    227     sp<DrmManagerClient::OnInfoListener> listener = new JNIOnInfoListener(env, thiz, weak_thiz);
    228     getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, listener);
    229 
    230     ALOGV("setListeners - Exit");
    231 }
    232 
    233 static void android_drm_DrmManagerClient_release(
    234         JNIEnv* env, jobject thiz, jint uniqueId) {
    235     ALOGV("release - Enter");
    236     getDrmManagerClientImpl(env, thiz)->remove(uniqueId);
    237     getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, NULL);
    238 
    239     sp<DrmManagerClientImpl> oldClient = setDrmManagerClientImpl(env, thiz, NULL);
    240     if (oldClient != NULL) {
    241         oldClient->setOnInfoListener(uniqueId, NULL);
    242         oldClient->removeClient(uniqueId);
    243     }
    244     ALOGV("release - Exit");
    245 }
    246 
    247 static jobject android_drm_DrmManagerClient_getConstraintsFromContent(
    248             JNIEnv* env, jobject thiz, jint uniqueId, jstring jpath, jint usage) {
    249     ALOGV("GetConstraints - Enter");
    250 
    251     const String8 pathString = Utility::getStringValue(env, jpath);
    252     DrmConstraints* pConstraints
    253         = getDrmManagerClientImpl(env, thiz)->getConstraints(uniqueId, &pathString, usage);
    254 
    255     jclass localRef = env->FindClass("android/content/ContentValues");
    256     jmethodID ContentValues_putByteArray =
    257             env->GetMethodID(localRef, "put", "(Ljava/lang/String;[B)V");
    258     jmethodID ContentValues_putString =
    259             env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");
    260     jmethodID ContentValues_constructor = env->GetMethodID(localRef, "<init>", "()V");
    261     jobject constraints = NULL;
    262 
    263     if (NULL != localRef && NULL != pConstraints) {
    264         // create the java DrmConstraints object
    265         constraints = env->NewObject(localRef, ContentValues_constructor);
    266 
    267         DrmConstraints::KeyIterator keyIt = pConstraints->keyIterator();
    268         while (keyIt.hasNext()) {
    269             String8 key = keyIt.next();
    270 
    271             // insert the entry<constraintKey, constraintValue> to newly created java object
    272             if (DrmConstraints::EXTENDED_METADATA == key) {
    273                 const char* value = pConstraints->getAsByteArray(&key);
    274                 if (NULL != value) {
    275                     ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(strlen(value)));
    276                     ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
    277                     env->SetByteArrayRegion(dataArray.get(), 0, strlen(value), (jbyte*)value);
    278                     env->CallVoidMethod(constraints, ContentValues_putByteArray,
    279                                         keyString.get(), dataArray.get());
    280                 }
    281             } else {
    282                 String8 value = pConstraints->get(key);
    283                 ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
    284                 ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
    285                 env->CallVoidMethod(constraints, ContentValues_putString,
    286                                     keyString.get(), valueString.get());
    287             }
    288         }
    289     }
    290 
    291     delete pConstraints; pConstraints = NULL;
    292     ALOGV("GetConstraints - Exit");
    293     return constraints;
    294 }
    295 
    296 static jobject android_drm_DrmManagerClient_getMetadataFromContent(
    297             JNIEnv* env, jobject thiz, jint uniqueId, jstring jpath) {
    298     ALOGV("GetMetadata - Enter");
    299     const String8 pathString = Utility::getStringValue(env, jpath);
    300     DrmMetadata* pMetadata =
    301             getDrmManagerClientImpl(env, thiz)->getMetadata(uniqueId, &pathString);
    302 
    303     jobject metadata = NULL;
    304 
    305     jclass localRef = env->FindClass("android/content/ContentValues");
    306     jmethodID ContentValues_putString =
    307             env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");
    308 
    309     if (NULL != localRef && NULL != pMetadata) {
    310         // Get the constructor id
    311         jmethodID constructorId = NULL;
    312         constructorId = env->GetMethodID(localRef, "<init>", "()V");
    313         if (NULL != constructorId) {
    314             // create the java DrmMetadata object
    315             metadata = env->NewObject(localRef, constructorId);
    316             if (NULL != metadata) {
    317                 DrmMetadata::KeyIterator keyIt = pMetadata->keyIterator();
    318                 while (keyIt.hasNext()) {
    319                     String8 key = keyIt.next();
    320                     // insert the entry<constraintKey, constraintValue>
    321                     // to newly created java object
    322                     String8 value = pMetadata->get(key);
    323                     ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
    324                     ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
    325                     env->CallVoidMethod(metadata, ContentValues_putString,
    326                                         keyString.get(), valueString.get());
    327                 }
    328             }
    329         }
    330     }
    331     delete pMetadata; pMetadata = NULL;
    332     ALOGV("GetMetadata - Exit");
    333     return metadata;
    334 }
    335 
    336 static jobjectArray android_drm_DrmManagerClient_getAllSupportInfo(
    337             JNIEnv* env, jobject thiz, jint uniqueId) {
    338     ALOGV("GetAllSupportInfo - Enter");
    339     DrmSupportInfo* drmSupportInfoArray = NULL;
    340 
    341     int length = 0;
    342     getDrmManagerClientImpl(env, thiz)->getAllSupportInfo(uniqueId, &length, &drmSupportInfoArray);
    343 
    344     jclass clazz = env->FindClass("android/drm/DrmSupportInfo");
    345 
    346     jobjectArray array = (jobjectArray)env->NewObjectArray(length, clazz, NULL);
    347 
    348     for (int i = 0; i < length; i++) {
    349         DrmSupportInfo info = drmSupportInfoArray[i];
    350 
    351         jobject drmSupportInfo = env->NewObject(clazz, env->GetMethodID(clazz, "<init>", "()V"));
    352 
    353         jmethodID addMimeTypeId
    354             = env->GetMethodID(clazz, "addMimeType", "(Ljava/lang/String;)V");
    355         jmethodID addFileSuffixId
    356             = env->GetMethodID(clazz, "addFileSuffix", "(Ljava/lang/String;)V");
    357 
    358         env->CallVoidMethod(
    359             drmSupportInfo, env->GetMethodID(clazz, "setDescription", "(Ljava/lang/String;)V"),
    360             env->NewStringUTF(info.getDescription().string()));
    361 
    362         DrmSupportInfo::MimeTypeIterator iterator = info.getMimeTypeIterator();
    363         while (iterator.hasNext()) {
    364             String8  value = iterator.next();
    365             env->CallVoidMethod(drmSupportInfo, addMimeTypeId, env->NewStringUTF(value.string()));
    366         }
    367 
    368         DrmSupportInfo::FileSuffixIterator it = info.getFileSuffixIterator();
    369         while (it.hasNext()) {
    370             String8 value = it.next();
    371             env->CallVoidMethod(
    372                 drmSupportInfo, addFileSuffixId, env->NewStringUTF(value.string()));
    373         }
    374 
    375         env->SetObjectArrayElement(array, i, drmSupportInfo);
    376     }
    377 
    378     delete [] drmSupportInfoArray; drmSupportInfoArray = NULL;
    379     ALOGV("GetAllSupportInfo - Exit");
    380     return array;
    381 }
    382 
    383 static void android_drm_DrmManagerClient_installDrmEngine(
    384             JNIEnv* /* env */, jobject /* thiz */, jint /* uniqueId */,
    385             jstring /* engineFilePath */) {
    386     ALOGV("installDrmEngine - Enter");
    387     //getDrmManagerClient(env, thiz)
    388     //  ->installDrmEngine(uniqueId, Utility::getStringValue(env, engineFilePath));
    389     ALOGV("installDrmEngine - Exit");
    390 }
    391 
    392 static jint android_drm_DrmManagerClient_saveRights(
    393             JNIEnv* env, jobject thiz, jint uniqueId,
    394             jobject drmRights, jstring rightsPath, jstring contentPath) {
    395     ALOGV("saveRights - Enter");
    396     int result = DRM_ERROR_UNKNOWN;
    397     int dataLength = 0;
    398     char* mData =  Utility::getByteArrayValue(env, drmRights, "mData", &dataLength);
    399 
    400     if (NULL != mData) {
    401         DrmRights rights(DrmBuffer(mData, dataLength),
    402                 Utility::getStringValue(env, drmRights, "mMimeType"),
    403                 Utility::getStringValue(env, drmRights, "mAccountId"),
    404                 Utility::getStringValue(env, drmRights, "mSubscriptionId"));
    405         result = getDrmManagerClientImpl(env, thiz)
    406             ->saveRights(uniqueId, rights, Utility::getStringValue(env, rightsPath),
    407                                 Utility::getStringValue(env, contentPath));
    408     }
    409 
    410     delete[] mData; mData = NULL;
    411     ALOGV("saveRights - Exit");
    412     return static_cast<jint>(result);
    413 }
    414 
    415 static jboolean android_drm_DrmManagerClient_canHandle(
    416             JNIEnv* env, jobject thiz, jint uniqueId, jstring path, jstring mimeType) {
    417     ALOGV("canHandle - Enter");
    418     jboolean result
    419         = getDrmManagerClientImpl(env, thiz)
    420             ->canHandle(uniqueId, Utility::getStringValue(env, path),
    421                     Utility::getStringValue(env, mimeType));
    422     ALOGV("canHandle - Exit");
    423     return result;
    424 }
    425 
    426 static jobject android_drm_DrmManagerClient_processDrmInfo(
    427             JNIEnv* env, jobject thiz, jint uniqueId, jobject drmInfoObject) {
    428     ALOGV("processDrmInfo - Enter");
    429     int dataLength = 0;
    430     const String8 mMimeType =  Utility::getStringValue(env, drmInfoObject, "mMimeType");
    431     char* mData =  Utility::getByteArrayValue(env, drmInfoObject, "mData", &dataLength);
    432     int mInfoType = Utility::getIntValue(env, drmInfoObject, "mInfoType");
    433 
    434     const DrmBuffer buffer(mData, dataLength);
    435     DrmInfo drmInfo(mInfoType, buffer, mMimeType);
    436 
    437     jclass clazz = env->FindClass("android/drm/DrmInfo");
    438     jmethodID DrmInfo_get = env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;");
    439     jobject keyIterator
    440         = env->CallObjectMethod(drmInfoObject,
    441                 env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));
    442 
    443     jclass Iterator_class = env->FindClass("java/util/Iterator");
    444     jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
    445     jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");
    446 
    447     jclass Object_class = env->FindClass("java/lang/Object");
    448     jmethodID Object_toString = env->GetMethodID(Object_class, "toString", "()Ljava/lang/String;");
    449 
    450     while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
    451         ScopedLocalRef<jstring> key(env,
    452                 (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
    453         ScopedLocalRef<jobject> valueObject(env,
    454                 env->CallObjectMethod(drmInfoObject, DrmInfo_get, key.get()));
    455         ScopedLocalRef<jstring> valString(env, NULL);
    456         if (NULL != valueObject.get()) {
    457             valString.reset((jstring) env->CallObjectMethod(valueObject.get(), Object_toString));
    458         }
    459 
    460         String8 keyString = Utility::getStringValue(env, key.get());
    461         String8 valueString = Utility::getStringValue(env, valString.get());
    462         ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());
    463 
    464         drmInfo.put(keyString, valueString);
    465     }
    466 
    467     DrmInfoStatus* pDrmInfoStatus
    468         = getDrmManagerClientImpl(env, thiz)->processDrmInfo(uniqueId, &drmInfo);
    469 
    470     jclass localRef = env->FindClass("android/drm/DrmInfoStatus");
    471     jobject drmInfoStatus = NULL;
    472 
    473     if (NULL != localRef && NULL != pDrmInfoStatus) {
    474         int statusCode = pDrmInfoStatus->statusCode;
    475         int infoType = pDrmInfoStatus->infoType;
    476 
    477         jbyteArray dataArray = NULL;
    478         if (NULL != pDrmInfoStatus->drmBuffer) {
    479             int length = pDrmInfoStatus->drmBuffer->length;
    480             dataArray = env->NewByteArray(length);
    481             env->SetByteArrayRegion(
    482                 dataArray, 0, length, (jbyte*) pDrmInfoStatus->drmBuffer->data);
    483 
    484             delete [] pDrmInfoStatus->drmBuffer->data;
    485             delete pDrmInfoStatus->drmBuffer; pDrmInfoStatus->drmBuffer = NULL;
    486         }
    487         jclass clazz = env->FindClass("android/drm/ProcessedData");
    488         jmethodID constructorId
    489             = env->GetMethodID(clazz, "<init>", "([BLjava/lang/String;Ljava/lang/String;)V");
    490         jobject processedData = env->NewObject(clazz, constructorId, dataArray,
    491                     env->NewStringUTF((drmInfo.get(DrmInfoRequest::ACCOUNT_ID)).string()),
    492                     env->NewStringUTF((drmInfo.get(DrmInfoRequest::SUBSCRIPTION_ID)).string()));
    493 
    494         constructorId
    495             = env->GetMethodID(localRef,
    496                 "<init>", "(IILandroid/drm/ProcessedData;Ljava/lang/String;)V");
    497 
    498         drmInfoStatus = env->NewObject(localRef, constructorId, statusCode, infoType,
    499                 processedData, env->NewStringUTF(pDrmInfoStatus->mimeType.string()));
    500     }
    501 
    502     delete[] mData; mData = NULL;
    503     delete pDrmInfoStatus; pDrmInfoStatus = NULL;
    504 
    505     ALOGV("processDrmInfo - Exit");
    506     return drmInfoStatus;
    507 }
    508 
    509 static jobject android_drm_DrmManagerClient_acquireDrmInfo(
    510             JNIEnv* env, jobject thiz, jint uniqueId, jobject drmInfoRequest) {
    511     ALOGV("acquireDrmInfo Enter");
    512     const String8 mMimeType =  Utility::getStringValue(env, drmInfoRequest, "mMimeType");
    513     int mInfoType = Utility::getIntValue(env, drmInfoRequest, "mInfoType");
    514 
    515     DrmInfoRequest drmInfoReq(mInfoType, mMimeType);
    516 
    517     jclass clazz = env->FindClass("android/drm/DrmInfoRequest");
    518     jobject keyIterator
    519         = env->CallObjectMethod(drmInfoRequest,
    520                 env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));
    521     jmethodID DrmInfoRequest_get = env->GetMethodID(clazz,
    522             "get", "(Ljava/lang/String;)Ljava/lang/Object;");
    523 
    524     jclass Iterator_class = env->FindClass("java/util/Iterator");
    525     jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
    526     jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");
    527 
    528     while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
    529         ScopedLocalRef<jstring> key(env,
    530                 (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
    531         ScopedLocalRef<jstring> value(env,
    532                 (jstring) env->CallObjectMethod(drmInfoRequest, DrmInfoRequest_get, key.get()));
    533 
    534         String8 keyString = Utility::getStringValue(env, key.get());
    535         String8 valueString = Utility::getStringValue(env, value.get());
    536         ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());
    537 
    538         drmInfoReq.put(keyString, valueString);
    539     }
    540 
    541     DrmInfo* pDrmInfo = getDrmManagerClientImpl(env, thiz)->acquireDrmInfo(uniqueId, &drmInfoReq);
    542 
    543     jobject drmInfoObject = NULL;
    544 
    545     if (NULL != pDrmInfo) {
    546         jclass localRef = env->FindClass("android/drm/DrmInfo");
    547 
    548         if (NULL != localRef) {
    549             int length = pDrmInfo->getData().length;
    550 
    551             jbyteArray dataArray = env->NewByteArray(length);
    552             env->SetByteArrayRegion(dataArray, 0, length, (jbyte*)pDrmInfo->getData().data);
    553 
    554             drmInfoObject
    555                 = env->NewObject(localRef,
    556                     env->GetMethodID(localRef, "<init>", "(I[BLjava/lang/String;)V"),
    557                     mInfoType, dataArray, env->NewStringUTF(pDrmInfo->getMimeType().string()));
    558 
    559             DrmInfo::KeyIterator it = pDrmInfo->keyIterator();
    560             jmethodID putMethodId
    561                 = env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/Object;)V");
    562 
    563             while (it.hasNext()) {
    564                 String8 key = it.next();
    565                 String8 value = pDrmInfo->get(key);
    566                 ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
    567                 ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
    568                 env->CallVoidMethod(drmInfoObject, putMethodId,
    569                     keyString.get(), valueString.get());
    570             }
    571         }
    572         delete [] pDrmInfo->getData().data;
    573     }
    574 
    575     delete pDrmInfo; pDrmInfo = NULL;
    576 
    577     ALOGV("acquireDrmInfo Exit");
    578     return drmInfoObject;
    579 }
    580 
    581 static jint android_drm_DrmManagerClient_getDrmObjectType(
    582             JNIEnv* env, jobject thiz, jint uniqueId, jstring path, jstring mimeType) {
    583     ALOGV("getDrmObjectType Enter");
    584     int drmObjectType
    585         = getDrmManagerClientImpl(env, thiz)
    586             ->getDrmObjectType(uniqueId, Utility::getStringValue(env, path),
    587                                 Utility::getStringValue(env, mimeType));
    588     ALOGV("getDrmObjectType Exit");
    589     return static_cast<jint>(drmObjectType);
    590 }
    591 
    592 static jstring android_drm_DrmManagerClient_getOriginalMimeType(
    593             JNIEnv* env, jobject thiz, jint uniqueId, jstring path, jobject fileDescriptor) {
    594     ALOGV("getOriginalMimeType Enter");
    595 
    596     int fd = (fileDescriptor == NULL)
    597                 ? -1
    598                 : jniGetFDFromFileDescriptor(env, fileDescriptor);
    599 
    600     String8 mimeType
    601         = getDrmManagerClientImpl(env, thiz)
    602             ->getOriginalMimeType(uniqueId,
    603                                   Utility::getStringValue(env, path), fd);
    604     ALOGV("getOriginalMimeType Exit");
    605     return env->NewStringUTF(mimeType.string());
    606 }
    607 
    608 static jint android_drm_DrmManagerClient_checkRightsStatus(
    609             JNIEnv* env, jobject thiz, jint uniqueId, jstring path, int action) {
    610     ALOGV("checkRightsStatus Enter");
    611     int rightsStatus
    612         = getDrmManagerClientImpl(env, thiz)
    613             ->checkRightsStatus(uniqueId, Utility::getStringValue(env, path), action);
    614     ALOGV("checkRightsStatus Exit");
    615     return static_cast<jint>(rightsStatus);
    616 }
    617 
    618 static jint android_drm_DrmManagerClient_removeRights(
    619             JNIEnv* env, jobject thiz, jint uniqueId, jstring path) {
    620     ALOGV("removeRights");
    621     return static_cast<jint>(getDrmManagerClientImpl(env, thiz)
    622                ->removeRights(uniqueId, Utility::getStringValue(env, path)));
    623 }
    624 
    625 static jint android_drm_DrmManagerClient_removeAllRights(
    626             JNIEnv* env, jobject thiz, jint uniqueId) {
    627     ALOGV("removeAllRights");
    628     return static_cast<jint>(getDrmManagerClientImpl(env, thiz)
    629                 ->removeAllRights(uniqueId));
    630 }
    631 
    632 static jint android_drm_DrmManagerClient_openConvertSession(
    633             JNIEnv* env, jobject thiz, jint uniqueId, jstring mimeType) {
    634     ALOGV("openConvertSession Enter");
    635     int convertId
    636         = getDrmManagerClientImpl(env, thiz)
    637             ->openConvertSession(uniqueId, Utility::getStringValue(env, mimeType));
    638     ALOGV("openConvertSession Exit");
    639     return static_cast<jint>(convertId);
    640 }
    641 
    642 static jobject GetConvertedStatus(JNIEnv* env, DrmConvertedStatus* pDrmConvertedStatus) {
    643     ALOGV("GetConvertedStatus - Enter");
    644     jclass localRef = env->FindClass("android/drm/DrmConvertedStatus");
    645 
    646     jobject drmConvertedStatus = NULL;
    647 
    648     if (NULL != localRef && NULL != pDrmConvertedStatus) {
    649         int statusCode = pDrmConvertedStatus->statusCode;
    650 
    651         jbyteArray dataArray = NULL;
    652         if (NULL != pDrmConvertedStatus->convertedData) {
    653             int length = pDrmConvertedStatus->convertedData->length;
    654             dataArray = env->NewByteArray(length);
    655             env->SetByteArrayRegion(
    656                 dataArray, 0, length, (jbyte*) pDrmConvertedStatus->convertedData->data);
    657 
    658             delete [] pDrmConvertedStatus->convertedData->data;
    659             delete pDrmConvertedStatus->convertedData; pDrmConvertedStatus->convertedData = NULL;
    660         }
    661         jmethodID constructorId = env->GetMethodID(localRef, "<init>", "(I[BI)V");
    662         drmConvertedStatus
    663             = env->NewObject(localRef, constructorId,
    664                              statusCode, dataArray, pDrmConvertedStatus->offset);
    665     }
    666 
    667     delete pDrmConvertedStatus; pDrmConvertedStatus = NULL;
    668 
    669     ALOGV("GetConvertedStatus - Exit");
    670     return drmConvertedStatus;
    671 }
    672 
    673 static jobject android_drm_DrmManagerClient_convertData(
    674             JNIEnv* env, jobject thiz, jint uniqueId, jint convertId, jbyteArray inputData) {
    675     ALOGV("convertData Enter");
    676 
    677     int dataLength = 0;
    678     char* mData = Utility::getByteArrayValue(env, inputData, &dataLength);
    679     const DrmBuffer buffer(mData, dataLength);
    680 
    681     DrmConvertedStatus* pDrmConvertedStatus
    682             = getDrmManagerClientImpl(env, thiz)->convertData(uniqueId, convertId, &buffer);
    683     jobject status = GetConvertedStatus(env, pDrmConvertedStatus);
    684 
    685     delete[] mData;
    686     mData = NULL;
    687 
    688     ALOGV("convertData - Exit");
    689     return status;
    690 }
    691 
    692 static jobject android_drm_DrmManagerClient_closeConvertSession(
    693             JNIEnv* env, jobject thiz, jint uniqueId, jint convertId) {
    694 
    695     ALOGV("closeConvertSession Enter");
    696 
    697     DrmConvertedStatus* pDrmConvertedStatus
    698                 = getDrmManagerClientImpl(env, thiz)->closeConvertSession(uniqueId, convertId);
    699     jobject status = GetConvertedStatus(env, pDrmConvertedStatus);
    700 
    701     ALOGV("closeConvertSession - Exit");
    702     return status;
    703 }
    704 
    705 static const JNINativeMethod nativeMethods[] = {
    706 
    707     {"_initialize", "()I",
    708                                     (void*)android_drm_DrmManagerClient_initialize},
    709 
    710     {"_setListeners", "(ILjava/lang/Object;)V",
    711                                     (void*)android_drm_DrmManagerClient_setListeners},
    712 
    713     {"_release", "(I)V",
    714                                     (void*)android_drm_DrmManagerClient_release},
    715 
    716     {"_getConstraints", "(ILjava/lang/String;I)Landroid/content/ContentValues;",
    717                                     (void*)android_drm_DrmManagerClient_getConstraintsFromContent},
    718 
    719     {"_getMetadata", "(ILjava/lang/String;)Landroid/content/ContentValues;",
    720                                     (void*)android_drm_DrmManagerClient_getMetadataFromContent},
    721 
    722     {"_getAllSupportInfo", "(I)[Landroid/drm/DrmSupportInfo;",
    723                                     (void*)android_drm_DrmManagerClient_getAllSupportInfo},
    724 
    725     {"_installDrmEngine", "(ILjava/lang/String;)V",
    726                                     (void*)android_drm_DrmManagerClient_installDrmEngine},
    727 
    728     {"_canHandle", "(ILjava/lang/String;Ljava/lang/String;)Z",
    729                                     (void*)android_drm_DrmManagerClient_canHandle},
    730 
    731     {"_processDrmInfo", "(ILandroid/drm/DrmInfo;)Landroid/drm/DrmInfoStatus;",
    732                                     (void*)android_drm_DrmManagerClient_processDrmInfo},
    733 
    734     {"_acquireDrmInfo", "(ILandroid/drm/DrmInfoRequest;)Landroid/drm/DrmInfo;",
    735                                     (void*)android_drm_DrmManagerClient_acquireDrmInfo},
    736 
    737     {"_saveRights", "(ILandroid/drm/DrmRights;Ljava/lang/String;Ljava/lang/String;)I",
    738                                     (void*)android_drm_DrmManagerClient_saveRights},
    739 
    740     {"_getDrmObjectType", "(ILjava/lang/String;Ljava/lang/String;)I",
    741                                     (void*)android_drm_DrmManagerClient_getDrmObjectType},
    742 
    743     {"_getOriginalMimeType", "(ILjava/lang/String;Ljava/io/FileDescriptor;)Ljava/lang/String;",
    744                                     (void*)android_drm_DrmManagerClient_getOriginalMimeType},
    745 
    746     {"_checkRightsStatus", "(ILjava/lang/String;I)I",
    747                                     (void*)android_drm_DrmManagerClient_checkRightsStatus},
    748 
    749     {"_removeRights", "(ILjava/lang/String;)I",
    750                                     (void*)android_drm_DrmManagerClient_removeRights},
    751 
    752     {"_removeAllRights", "(I)I",
    753                                     (void*)android_drm_DrmManagerClient_removeAllRights},
    754 
    755     {"_openConvertSession", "(ILjava/lang/String;)I",
    756                                     (void*)android_drm_DrmManagerClient_openConvertSession},
    757 
    758     {"_convertData", "(II[B)Landroid/drm/DrmConvertedStatus;",
    759                                     (void*)android_drm_DrmManagerClient_convertData},
    760 
    761     {"_closeConvertSession", "(II)Landroid/drm/DrmConvertedStatus;",
    762                                     (void*)android_drm_DrmManagerClient_closeConvertSession},
    763 };
    764 
    765 static int registerNativeMethods(JNIEnv* env) {
    766     int result = -1;
    767 
    768     /* look up the class */
    769     jclass clazz = env->FindClass("android/drm/DrmManagerClient");
    770 
    771     if (NULL != clazz) {
    772         if (env->RegisterNatives(clazz, nativeMethods, sizeof(nativeMethods)
    773                 / sizeof(nativeMethods[0])) == JNI_OK) {
    774             result = 0;
    775         }
    776     }
    777     return result;
    778 }
    779 
    780 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
    781     JNIEnv* env = NULL;
    782     jint result = -1;
    783 
    784     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
    785         if (NULL != env && registerNativeMethods(env) == 0) {
    786             result = JNI_VERSION_1_4;
    787         }
    788     }
    789     return result;
    790 }
    791 
    792