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 
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 
getStringValue(JNIEnv * env,jobject object,const char * fieldName)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 
getStringValue(JNIEnv * env,jstring string)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 
getByteArrayValue(JNIEnv * env,jobject object,const char * fieldName,int * dataLength)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 
getByteArrayValue(JNIEnv * env,jbyteArray byteArray,int * dataLength)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 
getIntValue(JNIEnv * env,jobject object,const char * fieldName)119 int 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 
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 
JNIOnInfoListener(JNIEnv * env,jobject thiz,jobject weak_thiz)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 
~JNIOnInfoListener()160 JNIOnInfoListener::~JNIOnInfoListener() {
161     JNIEnv *env = AndroidRuntime::getJNIEnv();
162     env->DeleteGlobalRef(mObject);
163     env->DeleteGlobalRef(mClass);
164 }
165 
onInfo(const DrmInfoEvent & event)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 
setDrmManagerClientImpl(JNIEnv * env,jobject thiz,const sp<DrmManagerClientImpl> & client)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 
getDrmManagerClientImpl(JNIEnv * env,jobject thiz)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 
android_drm_DrmManagerClient_initialize(JNIEnv * env,jobject thiz)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 
android_drm_DrmManagerClient_setListeners(JNIEnv * env,jobject thiz,jint uniqueId,jobject weak_thiz)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 
android_drm_DrmManagerClient_release(JNIEnv * env,jobject thiz,jint uniqueId)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 
android_drm_DrmManagerClient_getConstraintsFromContent(JNIEnv * env,jobject thiz,jint uniqueId,jstring jpath,jint usage)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 
android_drm_DrmManagerClient_getMetadataFromContent(JNIEnv * env,jobject thiz,jint uniqueId,jstring jpath)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 
android_drm_DrmManagerClient_getAllSupportInfo(JNIEnv * env,jobject thiz,jint uniqueId)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 
android_drm_DrmManagerClient_installDrmEngine(JNIEnv *,jobject,jint,jstring)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 
android_drm_DrmManagerClient_saveRights(JNIEnv * env,jobject thiz,jint uniqueId,jobject drmRights,jstring rightsPath,jstring contentPath)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 
android_drm_DrmManagerClient_canHandle(JNIEnv * env,jobject thiz,jint uniqueId,jstring path,jstring mimeType)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 
android_drm_DrmManagerClient_processDrmInfo(JNIEnv * env,jobject thiz,jint uniqueId,jobject drmInfoObject)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 
android_drm_DrmManagerClient_acquireDrmInfo(JNIEnv * env,jobject thiz,jint uniqueId,jobject drmInfoRequest)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 
android_drm_DrmManagerClient_getDrmObjectType(JNIEnv * env,jobject thiz,jint uniqueId,jstring path,jstring mimeType)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 
android_drm_DrmManagerClient_getOriginalMimeType(JNIEnv * env,jobject thiz,jint uniqueId,jstring path,jobject fileDescriptor)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 
android_drm_DrmManagerClient_checkRightsStatus(JNIEnv * env,jobject thiz,jint uniqueId,jstring path,int action)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 
android_drm_DrmManagerClient_removeRights(JNIEnv * env,jobject thiz,jint uniqueId,jstring path)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 
android_drm_DrmManagerClient_removeAllRights(JNIEnv * env,jobject thiz,jint uniqueId)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 
android_drm_DrmManagerClient_openConvertSession(JNIEnv * env,jobject thiz,jint uniqueId,jstring mimeType)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 
GetConvertedStatus(JNIEnv * env,DrmConvertedStatus * pDrmConvertedStatus)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 
android_drm_DrmManagerClient_convertData(JNIEnv * env,jobject thiz,jint uniqueId,jint convertId,jbyteArray inputData)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 
android_drm_DrmManagerClient_closeConvertSession(JNIEnv * env,jobject thiz,jint uniqueId,jint convertId)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 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 
registerNativeMethods(JNIEnv * env)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 
JNI_OnLoad(JavaVM * vm,void *)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