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