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