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