1 /* 2 * Copyright 2013, 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 "MediaDrm-JNI" 19 #include <utils/Log.h> 20 21 #include "android_media_MediaDrm.h" 22 #include "android_media_MediaMetricsJNI.h" 23 #include "android_os_Parcel.h" 24 #include "android_runtime/AndroidRuntime.h" 25 #include "android_runtime/Log.h" 26 #include "android_os_Parcel.h" 27 #include "jni.h" 28 #include <nativehelper/JNIHelp.h> 29 30 #include <binder/IServiceManager.h> 31 #include <binder/Parcel.h> 32 #include <binder/PersistableBundle.h> 33 #include <cutils/properties.h> 34 #include <media/stagefright/foundation/ADebug.h> 35 #include <media/stagefright/MediaErrors.h> 36 #include <mediadrm/IDrm.h> 37 #include <mediadrm/IMediaDrmService.h> 38 39 using ::android::os::PersistableBundle; 40 41 42 namespace android { 43 44 #define FIND_CLASS(var, className) \ 45 var = env->FindClass(className); \ 46 LOG_FATAL_IF(! (var), "Unable to find class %s", className); 47 48 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 49 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 50 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName); 51 52 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ 53 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \ 54 LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName); 55 56 #define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 57 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \ 58 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName); 59 60 #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ 61 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \ 62 LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName); 63 64 #define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \ 65 var = env->GetStaticObjectField(clazz, fieldId); \ 66 LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId); 67 68 69 struct RequestFields { 70 jfieldID data; 71 jfieldID defaultUrl; 72 jfieldID requestType; 73 }; 74 75 struct ArrayListFields { 76 jmethodID init; 77 jmethodID add; 78 }; 79 80 struct HashmapFields { 81 jmethodID init; 82 jmethodID get; 83 jmethodID put; 84 jmethodID entrySet; 85 }; 86 87 struct SetFields { 88 jmethodID iterator; 89 }; 90 91 struct IteratorFields { 92 jmethodID next; 93 jmethodID hasNext; 94 }; 95 96 struct EntryFields { 97 jmethodID getKey; 98 jmethodID getValue; 99 }; 100 101 struct EventTypes { 102 jint kEventProvisionRequired; 103 jint kEventKeyRequired; 104 jint kEventKeyExpired; 105 jint kEventVendorDefined; 106 jint kEventSessionReclaimed; 107 } gEventTypes; 108 109 struct EventWhat { 110 jint kWhatDrmEvent; 111 jint kWhatExpirationUpdate; 112 jint kWhatKeyStatusChange; 113 jint kWhatSessionLostState; 114 } gEventWhat; 115 116 struct KeyTypes { 117 jint kKeyTypeStreaming; 118 jint kKeyTypeOffline; 119 jint kKeyTypeRelease; 120 } gKeyTypes; 121 122 struct KeyRequestTypes { 123 jint kKeyRequestTypeInitial; 124 jint kKeyRequestTypeRenewal; 125 jint kKeyRequestTypeRelease; 126 jint kKeyRequestTypeNone; 127 jint kKeyRequestTypeUpdate; 128 } gKeyRequestTypes; 129 130 struct CertificateTypes { 131 jint kCertificateTypeNone; 132 jint kCertificateTypeX509; 133 } gCertificateTypes; 134 135 struct CertificateFields { 136 jfieldID wrappedPrivateKey; 137 jfieldID certificateData; 138 }; 139 140 struct StateExceptionFields { 141 jmethodID init; 142 jclass classId; 143 }; 144 145 struct SessionExceptionFields { 146 jmethodID init; 147 jclass classId; 148 jfieldID errorCode; 149 }; 150 151 struct SessionExceptionErrorCodes { 152 jint kErrorUnknown; 153 jint kResourceContention; 154 } gSessionExceptionErrorCodes; 155 156 struct HDCPLevels { 157 jint kHdcpLevelUnknown; 158 jint kHdcpNone; 159 jint kHdcpV1; 160 jint kHdcpV2; 161 jint kHdcpV2_1; 162 jint kHdcpV2_2; 163 jint kHdcpV2_3; 164 jint kHdcpNoOutput; 165 } gHdcpLevels; 166 167 struct SecurityLevels { 168 jint kSecurityLevelUnknown; 169 jint kSecurityLevelMax; 170 jint kSecurityLevelSwSecureCrypto; 171 jint kSecurityLevelSwSecureDecode; 172 jint kSecurityLevelHwSecureCrypto; 173 jint kSecurityLevelHwSecureDecode; 174 jint kSecurityLevelHwSecureAll; 175 } gSecurityLevels; 176 177 struct OfflineLicenseState { 178 jint kOfflineLicenseStateUsable; 179 jint kOfflineLicenseStateReleased; 180 jint kOfflineLicenseStateUnknown; 181 } gOfflineLicenseStates; 182 183 184 struct fields_t { 185 jfieldID context; 186 jmethodID post_event; 187 RequestFields keyRequest; 188 RequestFields provisionRequest; 189 ArrayListFields arraylist; 190 HashmapFields hashmap; 191 SetFields set; 192 IteratorFields iterator; 193 EntryFields entry; 194 CertificateFields certificate; 195 StateExceptionFields stateException; 196 SessionExceptionFields sessionException; 197 jclass certificateClassId; 198 jclass hashmapClassId; 199 jclass arraylistClassId; 200 jclass stringClassId; 201 jobject bundleCreator; 202 jmethodID createFromParcelId; 203 jclass parcelCreatorClassId; 204 }; 205 206 static fields_t gFields; 207 208 namespace { 209 210 // Helper function to convert a native PersistableBundle to a Java 211 // PersistableBundle. 212 jobject nativeToJavaPersistableBundle(JNIEnv *env, jobject thiz, 213 PersistableBundle* nativeBundle) { 214 if (env == NULL || thiz == NULL || nativeBundle == NULL) { 215 ALOGE("Unexpected NULL parmeter"); 216 return NULL; 217 } 218 219 // Create a Java parcel with the native parcel data. 220 // Then create a new PersistableBundle with that parcel as a parameter. 221 jobject jParcel = android::createJavaParcelObject(env); 222 if (jParcel == NULL) { 223 ALOGE("Failed to create a Java Parcel."); 224 return NULL; 225 } 226 227 android::Parcel* nativeParcel = android::parcelForJavaObject(env, jParcel); 228 if (nativeParcel == NULL) { 229 ALOGE("Failed to get the native Parcel."); 230 return NULL; 231 } 232 233 android::status_t result = nativeBundle->writeToParcel(nativeParcel); 234 nativeParcel->setDataPosition(0); 235 if (result != android::OK) { 236 ALOGE("Failed to write nativeBundle to Parcel: %d.", result); 237 return NULL; 238 } 239 240 jobject newBundle = env->CallObjectMethod(gFields.bundleCreator, 241 gFields.createFromParcelId, 242 jParcel); 243 if (newBundle == NULL) { 244 ALOGE("Failed to create a new PersistableBundle " 245 "from the createFromParcel call."); 246 } 247 248 return newBundle; 249 } 250 251 } // namespace anonymous 252 253 // ---------------------------------------------------------------------------- 254 // ref-counted object for callbacks 255 class JNIDrmListener: public DrmListener 256 { 257 public: 258 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz); 259 ~JNIDrmListener(); 260 virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL); 261 private: 262 JNIDrmListener(); 263 jclass mClass; // Reference to MediaDrm class 264 jobject mObject; // Weak ref to MediaDrm Java object to call on 265 }; 266 267 JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz) 268 { 269 // Hold onto the MediaDrm class for use in calling the static method 270 // that posts events to the application thread. 271 jclass clazz = env->GetObjectClass(thiz); 272 if (clazz == NULL) { 273 ALOGE("Can't find android/media/MediaDrm"); 274 jniThrowException(env, "java/lang/Exception", 275 "Can't find android/media/MediaDrm"); 276 return; 277 } 278 mClass = (jclass)env->NewGlobalRef(clazz); 279 280 // We use a weak reference so the MediaDrm object can be garbage collected. 281 // The reference is only used as a proxy for callbacks. 282 mObject = env->NewGlobalRef(weak_thiz); 283 } 284 285 JNIDrmListener::~JNIDrmListener() 286 { 287 // remove global references 288 JNIEnv *env = AndroidRuntime::getJNIEnv(); 289 env->DeleteGlobalRef(mObject); 290 env->DeleteGlobalRef(mClass); 291 } 292 293 void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra, 294 const Parcel *obj) 295 { 296 jint jwhat; 297 jint jeventType = 0; 298 299 // translate DrmPlugin event types into their java equivalents 300 switch (eventType) { 301 case DrmPlugin::kDrmPluginEventProvisionRequired: 302 jwhat = gEventWhat.kWhatDrmEvent; 303 jeventType = gEventTypes.kEventProvisionRequired; 304 break; 305 case DrmPlugin::kDrmPluginEventKeyNeeded: 306 jwhat = gEventWhat.kWhatDrmEvent; 307 jeventType = gEventTypes.kEventKeyRequired; 308 break; 309 case DrmPlugin::kDrmPluginEventKeyExpired: 310 jwhat = gEventWhat.kWhatDrmEvent; 311 jeventType = gEventTypes.kEventKeyExpired; 312 break; 313 case DrmPlugin::kDrmPluginEventVendorDefined: 314 jwhat = gEventWhat.kWhatDrmEvent; 315 jeventType = gEventTypes.kEventVendorDefined; 316 break; 317 case DrmPlugin::kDrmPluginEventSessionReclaimed: 318 jwhat = gEventWhat.kWhatDrmEvent; 319 jeventType = gEventTypes.kEventSessionReclaimed; 320 break; 321 case DrmPlugin::kDrmPluginEventExpirationUpdate: 322 jwhat = gEventWhat.kWhatExpirationUpdate; 323 break; 324 case DrmPlugin::kDrmPluginEventKeysChange: 325 jwhat = gEventWhat.kWhatKeyStatusChange; 326 break; 327 case DrmPlugin::kDrmPluginEventSessionLostState: 328 jwhat = gEventWhat.kWhatSessionLostState; 329 break; 330 default: 331 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType); 332 return; 333 } 334 335 JNIEnv *env = AndroidRuntime::getJNIEnv(); 336 if (obj && obj->dataSize() > 0) { 337 jobject jParcel = createJavaParcelObject(env); 338 if (jParcel != NULL) { 339 Parcel* nativeParcel = parcelForJavaObject(env, jParcel); 340 nativeParcel->setData(obj->data(), obj->dataSize()); 341 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject, 342 jwhat, jeventType, extra, jParcel); 343 env->DeleteLocalRef(jParcel); 344 } 345 } 346 347 if (env->ExceptionCheck()) { 348 ALOGW("An exception occurred while notifying an event."); 349 LOGW_EX(env); 350 env->ExceptionClear(); 351 } 352 } 353 354 static void throwStateException(JNIEnv *env, const char *msg, status_t err) { 355 ALOGE("Illegal state exception: %s (%d)", msg, err); 356 357 jobject exception = env->NewObject(gFields.stateException.classId, 358 gFields.stateException.init, static_cast<int>(err), 359 env->NewStringUTF(msg)); 360 env->Throw(static_cast<jthrowable>(exception)); 361 } 362 363 static void throwSessionException(JNIEnv *env, const char *msg, status_t err) { 364 ALOGE("Session exception: %s (%d)", msg, err); 365 366 jint jErrorCode = 0; 367 switch(err) { 368 case ERROR_DRM_RESOURCE_CONTENTION: 369 jErrorCode = gSessionExceptionErrorCodes.kResourceContention; 370 break; 371 default: 372 break; 373 } 374 375 jobject exception = env->NewObject(gFields.sessionException.classId, 376 gFields.sessionException.init, static_cast<int>(err), 377 env->NewStringUTF(msg)); 378 379 env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode); 380 env->Throw(static_cast<jthrowable>(exception)); 381 } 382 383 static bool isSessionException(status_t err) { 384 return err == ERROR_DRM_RESOURCE_CONTENTION; 385 } 386 387 static bool throwExceptionAsNecessary( 388 JNIEnv *env, status_t err, const char *msg = NULL) { 389 390 const char *drmMessage = NULL; 391 392 switch (err) { 393 case ERROR_DRM_UNKNOWN: 394 drmMessage = "General DRM error"; 395 break; 396 case ERROR_DRM_NO_LICENSE: 397 drmMessage = "No license"; 398 break; 399 case ERROR_DRM_LICENSE_EXPIRED: 400 drmMessage = "License expired"; 401 break; 402 case ERROR_DRM_SESSION_NOT_OPENED: 403 drmMessage = "Session not opened"; 404 break; 405 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED: 406 drmMessage = "Not initialized"; 407 break; 408 case ERROR_DRM_DECRYPT: 409 drmMessage = "Decrypt error"; 410 break; 411 case ERROR_DRM_CANNOT_HANDLE: 412 drmMessage = "Invalid parameter or data format"; 413 break; 414 case ERROR_DRM_INVALID_STATE: 415 drmMessage = "Invalid state"; 416 break; 417 default: 418 break; 419 } 420 421 String8 vendorMessage; 422 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) { 423 vendorMessage = String8::format("DRM vendor-defined error: %d", err); 424 drmMessage = vendorMessage.string(); 425 } 426 427 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) { 428 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 429 return true; 430 } else if (err == ERROR_UNSUPPORTED) { 431 jniThrowException(env, "java/lang/UnsupportedOperationException", msg); 432 return true; 433 } else if (err == ERROR_DRM_NOT_PROVISIONED) { 434 jniThrowException(env, "android/media/NotProvisionedException", msg); 435 return true; 436 } else if (err == ERROR_DRM_RESOURCE_BUSY) { 437 jniThrowException(env, "android/media/ResourceBusyException", msg); 438 return true; 439 } else if (err == ERROR_DRM_DEVICE_REVOKED) { 440 jniThrowException(env, "android/media/DeniedByServerException", msg); 441 return true; 442 } else if (err == DEAD_OBJECT) { 443 jniThrowException(env, "android/media/MediaDrmResetException", 444 "mediaserver died"); 445 return true; 446 } else if (isSessionException(err)) { 447 throwSessionException(env, msg, err); 448 return true; 449 } else if (err != OK) { 450 String8 errbuf; 451 if (drmMessage != NULL) { 452 if (msg == NULL) { 453 msg = drmMessage; 454 } else { 455 errbuf = String8::format("%s: %s", msg, drmMessage); 456 msg = errbuf.string(); 457 } 458 } 459 throwStateException(env, msg, err); 460 return true; 461 } 462 return false; 463 } 464 465 static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) { 466 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context); 467 return jdrm ? jdrm->getDrm() : NULL; 468 } 469 470 JDrm::JDrm( 471 JNIEnv *env, jobject thiz, const uint8_t uuid[16], 472 const String8 &appPackageName) { 473 mObject = env->NewWeakGlobalRef(thiz); 474 mDrm = MakeDrm(uuid, appPackageName); 475 if (mDrm != NULL) { 476 mDrm->setListener(this); 477 } 478 } 479 480 JDrm::~JDrm() { 481 JNIEnv *env = AndroidRuntime::getJNIEnv(); 482 483 env->DeleteWeakGlobalRef(mObject); 484 mObject = NULL; 485 } 486 487 // static 488 sp<IDrm> JDrm::MakeDrm() { 489 sp<IServiceManager> sm = defaultServiceManager(); 490 491 sp<IBinder> binder = sm->getService(String16("media.drm")); 492 sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder); 493 if (service == NULL) { 494 return NULL; 495 } 496 497 sp<IDrm> drm = service->makeDrm(); 498 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) { 499 return NULL; 500 } 501 502 return drm; 503 } 504 505 // static 506 sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) { 507 sp<IDrm> drm = MakeDrm(); 508 509 if (drm == NULL) { 510 return NULL; 511 } 512 513 status_t err = drm->createPlugin(uuid, appPackageName); 514 515 if (err != OK) { 516 return NULL; 517 } 518 519 return drm; 520 } 521 522 status_t JDrm::setListener(const sp<DrmListener>& listener) { 523 Mutex::Autolock lock(mLock); 524 mListener = listener; 525 return OK; 526 } 527 528 void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) { 529 sp<DrmListener> listener; 530 mLock.lock(); 531 listener = mListener; 532 mLock.unlock(); 533 534 if (listener != NULL) { 535 Mutex::Autolock lock(mNotifyLock); 536 listener->notify(eventType, extra, obj); 537 } 538 } 539 540 void JDrm::disconnect() { 541 if (mDrm != NULL) { 542 mDrm->destroyPlugin(); 543 mDrm.clear(); 544 } 545 } 546 547 548 // static 549 status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType, 550 DrmPlugin::SecurityLevel securityLevel, bool *isSupported) { 551 sp<IDrm> drm = MakeDrm(); 552 553 if (drm == NULL) { 554 return BAD_VALUE; 555 } 556 557 return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported); 558 } 559 560 status_t JDrm::initCheck() const { 561 return mDrm == NULL ? NO_INIT : OK; 562 } 563 564 // JNI conversion utilities 565 static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) { 566 Vector<uint8_t> vector; 567 size_t length = env->GetArrayLength(byteArray); 568 vector.insertAt((size_t)0, length); 569 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray()); 570 return vector; 571 } 572 573 static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) { 574 size_t length = vector.size(); 575 jbyteArray result = env->NewByteArray(length); 576 if (result != NULL) { 577 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array()); 578 } 579 return result; 580 } 581 582 static String8 JStringToString8(JNIEnv *env, jstring const &jstr) { 583 String8 result; 584 585 const char *s = env->GetStringUTFChars(jstr, NULL); 586 if (s) { 587 result = s; 588 env->ReleaseStringUTFChars(jstr, s); 589 } 590 return result; 591 } 592 593 /* 594 import java.util.HashMap; 595 import java.util.Set; 596 import java.Map.Entry; 597 import jav.util.Iterator; 598 599 HashMap<k, v> hm; 600 Set<Entry<k, v>> s = hm.entrySet(); 601 Iterator i = s.iterator(); 602 Entry e = s.next(); 603 */ 604 605 static KeyedVector<String8, String8> HashMapToKeyedVector( 606 JNIEnv *env, jobject &hashMap, bool* pIsOK) { 607 jclass clazz = gFields.stringClassId; 608 KeyedVector<String8, String8> keyedVector; 609 *pIsOK = true; 610 611 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet); 612 if (entrySet) { 613 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator); 614 if (iterator) { 615 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 616 while (hasNext) { 617 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next); 618 if (entry) { 619 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey); 620 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) { 621 jniThrowException(env, "java/lang/IllegalArgumentException", 622 "HashMap key is not a String"); 623 env->DeleteLocalRef(entry); 624 *pIsOK = false; 625 break; 626 } 627 jstring jkey = static_cast<jstring>(obj); 628 629 obj = env->CallObjectMethod(entry, gFields.entry.getValue); 630 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) { 631 jniThrowException(env, "java/lang/IllegalArgumentException", 632 "HashMap value is not a String"); 633 env->DeleteLocalRef(entry); 634 *pIsOK = false; 635 break; 636 } 637 jstring jvalue = static_cast<jstring>(obj); 638 639 String8 key = JStringToString8(env, jkey); 640 String8 value = JStringToString8(env, jvalue); 641 keyedVector.add(key, value); 642 643 env->DeleteLocalRef(jkey); 644 env->DeleteLocalRef(jvalue); 645 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 646 } 647 env->DeleteLocalRef(entry); 648 } 649 env->DeleteLocalRef(iterator); 650 } 651 env->DeleteLocalRef(entrySet); 652 } 653 return keyedVector; 654 } 655 656 static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) { 657 jclass clazz = gFields.hashmapClassId; 658 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init); 659 for (size_t i = 0; i < map.size(); ++i) { 660 jstring jkey = env->NewStringUTF(map.keyAt(i).string()); 661 jstring jvalue = env->NewStringUTF(map.valueAt(i).string()); 662 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue); 663 env->DeleteLocalRef(jkey); 664 env->DeleteLocalRef(jvalue); 665 } 666 return hashMap; 667 } 668 669 static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env, 670 List<Vector<uint8_t>> list) { 671 jclass clazz = gFields.arraylistClassId; 672 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init); 673 List<Vector<uint8_t>>::iterator iter = list.begin(); 674 while (iter != list.end()) { 675 jbyteArray byteArray = VectorToJByteArray(env, *iter); 676 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray); 677 env->DeleteLocalRef(byteArray); 678 iter++; 679 } 680 681 return arrayList; 682 } 683 684 } // namespace android 685 686 using namespace android; 687 688 static sp<JDrm> setDrm( 689 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) { 690 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context); 691 if (drm != NULL) { 692 drm->incStrong(thiz); 693 } 694 if (old != NULL) { 695 old->decStrong(thiz); 696 } 697 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get())); 698 699 return old; 700 } 701 702 static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) { 703 if (drm == NULL) { 704 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null"); 705 return false; 706 } 707 return true; 708 } 709 710 static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId) 711 { 712 if (!CheckDrm(env, drm)) { 713 return false; 714 } 715 716 if (jsessionId == NULL) { 717 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null"); 718 return false; 719 } 720 return true; 721 } 722 723 static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) { 724 sp<JDrm> drm = setDrm(env, thiz, NULL); 725 if (drm != NULL) { 726 drm->setListener(NULL); 727 drm->disconnect(); 728 } 729 } 730 731 static void android_media_MediaDrm_native_init(JNIEnv *env) { 732 jclass clazz; 733 FIND_CLASS(clazz, "android/media/MediaDrm"); 734 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J"); 735 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative", 736 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 737 738 jfieldID field; 739 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I"); 740 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field); 741 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I"); 742 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field); 743 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I"); 744 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field); 745 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I"); 746 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field); 747 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I"); 748 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field); 749 750 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I"); 751 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field); 752 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I"); 753 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field); 754 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I"); 755 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field); 756 GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I"); 757 gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field); 758 759 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I"); 760 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field); 761 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I"); 762 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field); 763 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I"); 764 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field); 765 766 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I"); 767 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field); 768 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I"); 769 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field); 770 771 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I"); 772 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field); 773 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I"); 774 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field); 775 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I"); 776 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field); 777 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I"); 778 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field); 779 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I"); 780 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field); 781 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I"); 782 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field); 783 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I"); 784 gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field); 785 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I"); 786 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field); 787 788 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I"); 789 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field); 790 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I"); 791 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field); 792 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I"); 793 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field); 794 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I"); 795 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field); 796 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I"); 797 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field); 798 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I"); 799 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field); 800 801 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I"); 802 gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field); 803 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I"); 804 gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field); 805 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I"); 806 gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field); 807 808 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I"); 809 810 jmethodID getMaxSecurityLevel; 811 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I"); 812 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel); 813 814 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); 815 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B"); 816 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;"); 817 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I"); 818 819 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I"); 820 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field); 821 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I"); 822 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field); 823 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I"); 824 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field); 825 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I"); 826 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field); 827 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I"); 828 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field); 829 830 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest"); 831 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B"); 832 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;"); 833 834 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate"); 835 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B"); 836 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B"); 837 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 838 839 // Metrics-related fields and classes. 840 FIND_CLASS(clazz, "android/os/PersistableBundle"); 841 jfieldID bundleCreatorId; 842 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR", 843 "Landroid/os/Parcelable$Creator;"); 844 jobject bundleCreator; 845 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId); 846 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator)); 847 FIND_CLASS(clazz, "android/os/Parcelable$Creator"); 848 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel", 849 "(Landroid/os/Parcel;)Ljava/lang/Object;"); 850 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 851 852 FIND_CLASS(clazz, "java/util/ArrayList"); 853 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V"); 854 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z"); 855 856 FIND_CLASS(clazz, "java/util/HashMap"); 857 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V"); 858 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); 859 GET_METHOD_ID(gFields.hashmap.put, clazz, "put", 860 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 861 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;"); 862 863 FIND_CLASS(clazz, "java/util/Set"); 864 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;"); 865 866 FIND_CLASS(clazz, "java/util/Iterator"); 867 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;"); 868 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z"); 869 870 FIND_CLASS(clazz, "java/util/Map$Entry"); 871 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;"); 872 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;"); 873 874 FIND_CLASS(clazz, "java/util/HashMap"); 875 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 876 877 FIND_CLASS(clazz, "java/lang/String"); 878 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 879 880 FIND_CLASS(clazz, "java/util/ArrayList"); 881 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 882 883 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException"); 884 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V"); 885 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz)); 886 887 FIND_CLASS(clazz, "android/media/MediaDrm$SessionException"); 888 GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V"); 889 gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz)); 890 GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I"); 891 892 GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I"); 893 gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field); 894 GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I"); 895 gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field); 896 } 897 898 static void android_media_MediaDrm_native_setup( 899 JNIEnv *env, jobject thiz, 900 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) { 901 902 if (uuidObj == NULL) { 903 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null"); 904 return; 905 } 906 907 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); 908 909 if (uuid.size() != 16) { 910 jniThrowException(env, "java/lang/IllegalArgumentException", 911 "invalid UUID size, expected 16 bytes"); 912 return; 913 } 914 915 String8 packageName; 916 if (jappPackageName == NULL) { 917 jniThrowException(env, "java/lang/IllegalArgumentException", 918 "application package name cannot be null"); 919 return; 920 } 921 922 packageName = JStringToString8(env, jappPackageName); 923 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName); 924 925 status_t err = drm->initCheck(); 926 927 if (err != OK) { 928 jniThrowException( 929 env, 930 "android/media/UnsupportedSchemeException", 931 "Failed to instantiate drm object."); 932 return; 933 } 934 935 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this); 936 drm->setListener(listener); 937 setDrm(env, thiz, drm); 938 } 939 940 DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) { 941 DrmPlugin::SecurityLevel level; 942 943 if (jlevel == gSecurityLevels.kSecurityLevelMax) { 944 level = DrmPlugin::kSecurityLevelMax; 945 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) { 946 level = DrmPlugin::kSecurityLevelSwSecureCrypto; 947 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) { 948 level = DrmPlugin::kSecurityLevelSwSecureDecode; 949 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) { 950 level = DrmPlugin::kSecurityLevelHwSecureCrypto; 951 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) { 952 level = DrmPlugin::kSecurityLevelHwSecureDecode; 953 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) { 954 level = DrmPlugin::kSecurityLevelHwSecureAll; 955 } else { 956 level = DrmPlugin::kSecurityLevelUnknown; 957 } 958 return level; 959 } 960 961 static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative( 962 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType, 963 jint jSecurityLevel) { 964 965 if (uuidObj == NULL) { 966 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 967 return false; 968 } 969 970 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); 971 972 if (uuid.size() != 16) { 973 jniThrowException( 974 env, 975 "java/lang/IllegalArgumentException", 976 "invalid UUID size, expected 16 bytes"); 977 return false; 978 } 979 980 String8 mimeType; 981 if (jmimeType != NULL) { 982 mimeType = JStringToString8(env, jmimeType); 983 } 984 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel); 985 986 bool isSupported; 987 status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType, 988 securityLevel, &isSupported); 989 990 if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) { 991 return false; 992 } 993 return isSupported; 994 } 995 996 static jbyteArray android_media_MediaDrm_openSession( 997 JNIEnv *env, jobject thiz, jint jlevel) { 998 sp<IDrm> drm = GetDrm(env, thiz); 999 1000 if (!CheckDrm(env, drm)) { 1001 return NULL; 1002 } 1003 1004 Vector<uint8_t> sessionId; 1005 DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel); 1006 if (level == DrmPlugin::kSecurityLevelUnknown) { 1007 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level"); 1008 return NULL; 1009 } 1010 1011 status_t err = drm->openSession(level, sessionId); 1012 1013 if (throwExceptionAsNecessary(env, err, "Failed to open session")) { 1014 return NULL; 1015 } 1016 1017 return VectorToJByteArray(env, sessionId); 1018 } 1019 1020 static void android_media_MediaDrm_closeSession( 1021 JNIEnv *env, jobject thiz, jbyteArray jsessionId) { 1022 sp<IDrm> drm = GetDrm(env, thiz); 1023 1024 if (!CheckSession(env, drm, jsessionId)) { 1025 return; 1026 } 1027 1028 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1029 1030 status_t err = drm->closeSession(sessionId); 1031 1032 throwExceptionAsNecessary(env, err, "Failed to close session"); 1033 } 1034 1035 static jobject android_media_MediaDrm_getKeyRequest( 1036 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData, 1037 jstring jmimeType, jint jkeyType, jobject joptParams) { 1038 sp<IDrm> drm = GetDrm(env, thiz); 1039 1040 if (!CheckSession(env, drm, jsessionId)) { 1041 return NULL; 1042 } 1043 1044 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1045 1046 Vector<uint8_t> initData; 1047 if (jinitData != NULL) { 1048 initData = JByteArrayToVector(env, jinitData); 1049 } 1050 1051 String8 mimeType; 1052 if (jmimeType != NULL) { 1053 mimeType = JStringToString8(env, jmimeType); 1054 } 1055 1056 DrmPlugin::KeyType keyType; 1057 if (jkeyType == gKeyTypes.kKeyTypeStreaming) { 1058 keyType = DrmPlugin::kKeyType_Streaming; 1059 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) { 1060 keyType = DrmPlugin::kKeyType_Offline; 1061 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) { 1062 keyType = DrmPlugin::kKeyType_Release; 1063 } else { 1064 jniThrowException(env, "java/lang/IllegalArgumentException", 1065 "invalid keyType"); 1066 return NULL; 1067 } 1068 1069 KeyedVector<String8, String8> optParams; 1070 if (joptParams != NULL) { 1071 bool isOK; 1072 optParams = HashMapToKeyedVector(env, joptParams, &isOK); 1073 if (!isOK) { 1074 return NULL; 1075 } 1076 } 1077 1078 Vector<uint8_t> request; 1079 String8 defaultUrl; 1080 DrmPlugin::KeyRequestType keyRequestType; 1081 1082 status_t err = drm->getKeyRequest(sessionId, initData, mimeType, 1083 keyType, optParams, request, defaultUrl, &keyRequestType); 1084 1085 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) { 1086 return NULL; 1087 } 1088 1089 // Fill out return obj 1090 jclass clazz; 1091 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); 1092 1093 jobject keyObj = NULL; 1094 1095 if (clazz) { 1096 keyObj = env->AllocObject(clazz); 1097 jbyteArray jrequest = VectorToJByteArray(env, request); 1098 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest); 1099 1100 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string()); 1101 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl); 1102 1103 switch (keyRequestType) { 1104 case DrmPlugin::kKeyRequestType_Initial: 1105 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1106 gKeyRequestTypes.kKeyRequestTypeInitial); 1107 break; 1108 case DrmPlugin::kKeyRequestType_Renewal: 1109 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1110 gKeyRequestTypes.kKeyRequestTypeRenewal); 1111 break; 1112 case DrmPlugin::kKeyRequestType_Release: 1113 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1114 gKeyRequestTypes.kKeyRequestTypeRelease); 1115 break; 1116 case DrmPlugin::kKeyRequestType_None: 1117 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1118 gKeyRequestTypes.kKeyRequestTypeNone); 1119 break; 1120 case DrmPlugin::kKeyRequestType_Update: 1121 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1122 gKeyRequestTypes.kKeyRequestTypeUpdate); 1123 break; 1124 1125 default: 1126 throwStateException(env, "DRM plugin failure: unknown key request type", 1127 ERROR_DRM_UNKNOWN); 1128 break; 1129 } 1130 } 1131 1132 return keyObj; 1133 } 1134 1135 static jbyteArray android_media_MediaDrm_provideKeyResponse( 1136 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) { 1137 sp<IDrm> drm = GetDrm(env, thiz); 1138 1139 if (!CheckSession(env, drm, jsessionId)) { 1140 return NULL; 1141 } 1142 1143 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1144 1145 if (jresponse == NULL) { 1146 jniThrowException(env, "java/lang/IllegalArgumentException", 1147 "key response is null"); 1148 return NULL; 1149 } 1150 Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); 1151 Vector<uint8_t> keySetId; 1152 1153 status_t err = drm->provideKeyResponse(sessionId, response, keySetId); 1154 1155 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) { 1156 return NULL; 1157 } 1158 return VectorToJByteArray(env, keySetId); 1159 } 1160 1161 static void android_media_MediaDrm_removeKeys( 1162 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) { 1163 sp<IDrm> drm = GetDrm(env, thiz); 1164 1165 if (!CheckDrm(env, drm)) { 1166 return; 1167 } 1168 1169 if (jkeysetId == NULL) { 1170 jniThrowException(env, "java/lang/IllegalArgumentException", 1171 "keySetId is null"); 1172 return; 1173 } 1174 1175 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId)); 1176 1177 status_t err = drm->removeKeys(keySetId); 1178 1179 throwExceptionAsNecessary(env, err, "Failed to remove keys"); 1180 } 1181 1182 static void android_media_MediaDrm_restoreKeys( 1183 JNIEnv *env, jobject thiz, jbyteArray jsessionId, 1184 jbyteArray jkeysetId) { 1185 1186 sp<IDrm> drm = GetDrm(env, thiz); 1187 1188 if (!CheckSession(env, drm, jsessionId)) { 1189 return; 1190 } 1191 1192 if (jkeysetId == NULL) { 1193 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 1194 return; 1195 } 1196 1197 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1198 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId)); 1199 1200 status_t err = drm->restoreKeys(sessionId, keySetId); 1201 1202 throwExceptionAsNecessary(env, err, "Failed to restore keys"); 1203 } 1204 1205 static jobject android_media_MediaDrm_queryKeyStatus( 1206 JNIEnv *env, jobject thiz, jbyteArray jsessionId) { 1207 sp<IDrm> drm = GetDrm(env, thiz); 1208 1209 if (!CheckSession(env, drm, jsessionId)) { 1210 return NULL; 1211 } 1212 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1213 1214 KeyedVector<String8, String8> infoMap; 1215 1216 status_t err = drm->queryKeyStatus(sessionId, infoMap); 1217 1218 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) { 1219 return NULL; 1220 } 1221 1222 return KeyedVectorToHashMap(env, infoMap); 1223 } 1224 1225 static jobject android_media_MediaDrm_getProvisionRequestNative( 1226 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) { 1227 sp<IDrm> drm = GetDrm(env, thiz); 1228 1229 if (!CheckDrm(env, drm)) { 1230 return NULL; 1231 } 1232 1233 Vector<uint8_t> request; 1234 String8 defaultUrl; 1235 1236 String8 certType; 1237 if (jcertType == gCertificateTypes.kCertificateTypeX509) { 1238 certType = "X.509"; 1239 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) { 1240 certType = "none"; 1241 } else { 1242 certType = "invalid"; 1243 } 1244 1245 String8 certAuthority = JStringToString8(env, jcertAuthority); 1246 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl); 1247 1248 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) { 1249 return NULL; 1250 } 1251 1252 // Fill out return obj 1253 jclass clazz; 1254 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest"); 1255 1256 jobject provisionObj = NULL; 1257 1258 if (clazz) { 1259 provisionObj = env->AllocObject(clazz); 1260 jbyteArray jrequest = VectorToJByteArray(env, request); 1261 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest); 1262 1263 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string()); 1264 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl); 1265 } 1266 1267 return provisionObj; 1268 } 1269 1270 static jobject android_media_MediaDrm_provideProvisionResponseNative( 1271 JNIEnv *env, jobject thiz, jbyteArray jresponse) { 1272 sp<IDrm> drm = GetDrm(env, thiz); 1273 1274 if (!CheckDrm(env, drm)) { 1275 return NULL; 1276 } 1277 1278 if (jresponse == NULL) { 1279 jniThrowException(env, "java/lang/IllegalArgumentException", 1280 "provision response is null"); 1281 return NULL; 1282 } 1283 1284 Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); 1285 Vector<uint8_t> certificate, wrappedKey; 1286 1287 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey); 1288 1289 // Fill out return obj 1290 jclass clazz = gFields.certificateClassId; 1291 1292 jobject certificateObj = NULL; 1293 1294 if (clazz && certificate.size() && wrappedKey.size()) { 1295 certificateObj = env->AllocObject(clazz); 1296 jbyteArray jcertificate = VectorToJByteArray(env, certificate); 1297 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate); 1298 1299 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey); 1300 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey); 1301 } 1302 1303 throwExceptionAsNecessary(env, err, "Failed to handle provision response"); 1304 return certificateObj; 1305 } 1306 1307 static jobject android_media_MediaDrm_getSecureStops( 1308 JNIEnv *env, jobject thiz) { 1309 sp<IDrm> drm = GetDrm(env, thiz); 1310 1311 if (!CheckDrm(env, drm)) { 1312 return NULL; 1313 } 1314 1315 List<Vector<uint8_t>> secureStops; 1316 1317 status_t err = drm->getSecureStops(secureStops); 1318 1319 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) { 1320 return NULL; 1321 } 1322 1323 return ListOfVectorsToArrayListOfByteArray(env, secureStops); 1324 } 1325 1326 static jobject android_media_MediaDrm_getSecureStopIds( 1327 JNIEnv *env, jobject thiz) { 1328 sp<IDrm> drm = GetDrm(env, thiz); 1329 1330 if (!CheckDrm(env, drm)) { 1331 return NULL; 1332 } 1333 1334 List<Vector<uint8_t>> secureStopIds; 1335 1336 status_t err = drm->getSecureStopIds(secureStopIds); 1337 1338 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) { 1339 return NULL; 1340 } 1341 1342 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds); 1343 } 1344 1345 static jbyteArray android_media_MediaDrm_getSecureStop( 1346 JNIEnv *env, jobject thiz, jbyteArray ssid) { 1347 sp<IDrm> drm = GetDrm(env, thiz); 1348 1349 if (!CheckDrm(env, drm)) { 1350 return NULL; 1351 } 1352 1353 Vector<uint8_t> secureStop; 1354 1355 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop); 1356 1357 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) { 1358 return NULL; 1359 } 1360 1361 return VectorToJByteArray(env, secureStop); 1362 } 1363 1364 static void android_media_MediaDrm_releaseSecureStops( 1365 JNIEnv *env, jobject thiz, jbyteArray jssRelease) { 1366 sp<IDrm> drm = GetDrm(env, thiz); 1367 1368 if (!CheckDrm(env, drm)) { 1369 return; 1370 } 1371 1372 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease)); 1373 1374 status_t err = drm->releaseSecureStops(ssRelease); 1375 1376 throwExceptionAsNecessary(env, err, "Failed to release secure stops"); 1377 } 1378 1379 static void android_media_MediaDrm_removeSecureStop( 1380 JNIEnv *env, jobject thiz, jbyteArray ssid) { 1381 sp<IDrm> drm = GetDrm(env, thiz); 1382 1383 if (!CheckDrm(env, drm)) { 1384 return; 1385 } 1386 1387 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid)); 1388 1389 throwExceptionAsNecessary(env, err, "Failed to remove secure stop"); 1390 } 1391 1392 static void android_media_MediaDrm_removeAllSecureStops( 1393 JNIEnv *env, jobject thiz) { 1394 sp<IDrm> drm = GetDrm(env, thiz); 1395 1396 if (!CheckDrm(env, drm)) { 1397 return; 1398 } 1399 1400 status_t err = drm->removeAllSecureStops(); 1401 1402 throwExceptionAsNecessary(env, err, "Failed to remove all secure stops"); 1403 } 1404 1405 1406 static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) { 1407 switch(level) { 1408 case DrmPlugin::kHdcpLevelUnknown: 1409 return gHdcpLevels.kHdcpLevelUnknown; 1410 case DrmPlugin::kHdcpNone: 1411 return gHdcpLevels.kHdcpNone; 1412 case DrmPlugin::kHdcpV1: 1413 return gHdcpLevels.kHdcpV1; 1414 case DrmPlugin::kHdcpV2: 1415 return gHdcpLevels.kHdcpV2; 1416 case DrmPlugin::kHdcpV2_1: 1417 return gHdcpLevels.kHdcpV2_1; 1418 case DrmPlugin::kHdcpV2_2: 1419 return gHdcpLevels.kHdcpV2_2; 1420 case DrmPlugin::kHdcpV2_3: 1421 return gHdcpLevels.kHdcpV2_3; 1422 case DrmPlugin::kHdcpNoOutput: 1423 return gHdcpLevels.kHdcpNoOutput; 1424 } 1425 return gHdcpLevels.kHdcpNone; 1426 } 1427 1428 static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env, 1429 jobject thiz) { 1430 sp<IDrm> drm = GetDrm(env, thiz); 1431 1432 if (!CheckDrm(env, drm)) { 1433 return gHdcpLevels.kHdcpNone; 1434 } 1435 1436 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone; 1437 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone; 1438 1439 status_t err = drm->getHdcpLevels(&connected, &max); 1440 1441 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) { 1442 return gHdcpLevels.kHdcpLevelUnknown; 1443 } 1444 return HdcpLevelTojint(connected); 1445 } 1446 1447 static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env, 1448 jobject thiz) { 1449 sp<IDrm> drm = GetDrm(env, thiz); 1450 1451 if (!CheckDrm(env, drm)) { 1452 return gHdcpLevels.kHdcpLevelUnknown; 1453 } 1454 1455 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown; 1456 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown; 1457 1458 status_t err = drm->getHdcpLevels(&connected, &max); 1459 1460 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) { 1461 return gHdcpLevels.kHdcpLevelUnknown; 1462 } 1463 return HdcpLevelTojint(max); 1464 } 1465 1466 static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env, 1467 jobject thiz) { 1468 sp<IDrm> drm = GetDrm(env, thiz); 1469 1470 if (!CheckDrm(env, drm)) { 1471 return 0; 1472 } 1473 1474 uint32_t open = 0, max = 0; 1475 status_t err = drm->getNumberOfSessions(&open, &max); 1476 1477 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) { 1478 return 0; 1479 } 1480 return open; 1481 } 1482 1483 static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env, 1484 jobject thiz) { 1485 sp<IDrm> drm = GetDrm(env, thiz); 1486 1487 if (!CheckDrm(env, drm)) { 1488 return 0; 1489 } 1490 1491 uint32_t open = 0, max = 0; 1492 status_t err = drm->getNumberOfSessions(&open, &max); 1493 1494 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) { 1495 return 0; 1496 } 1497 return max; 1498 } 1499 1500 static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env, 1501 jobject thiz, jbyteArray jsessionId) { 1502 sp<IDrm> drm = GetDrm(env, thiz); 1503 1504 if (!CheckSession(env, drm, jsessionId)) { 1505 return gSecurityLevels.kSecurityLevelUnknown; 1506 } 1507 1508 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1509 1510 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown; 1511 1512 status_t err = drm->getSecurityLevel(sessionId, &level); 1513 1514 if (throwExceptionAsNecessary(env, err, "Failed to get security level")) { 1515 return gSecurityLevels.kSecurityLevelUnknown; 1516 } 1517 1518 switch(level) { 1519 case DrmPlugin::kSecurityLevelSwSecureCrypto: 1520 return gSecurityLevels.kSecurityLevelSwSecureCrypto; 1521 case DrmPlugin::kSecurityLevelSwSecureDecode: 1522 return gSecurityLevels.kSecurityLevelSwSecureDecode; 1523 case DrmPlugin::kSecurityLevelHwSecureCrypto: 1524 return gSecurityLevels.kSecurityLevelHwSecureCrypto; 1525 case DrmPlugin::kSecurityLevelHwSecureDecode: 1526 return gSecurityLevels.kSecurityLevelHwSecureDecode; 1527 case DrmPlugin::kSecurityLevelHwSecureAll: 1528 return gSecurityLevels.kSecurityLevelHwSecureAll; 1529 default: 1530 return gSecurityLevels.kSecurityLevelUnknown; 1531 } 1532 } 1533 1534 static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds( 1535 JNIEnv *env, jobject thiz) { 1536 sp<IDrm> drm = GetDrm(env, thiz); 1537 1538 if (!CheckDrm(env, drm)) { 1539 return NULL; 1540 } 1541 1542 List<Vector<uint8_t> > keySetIds; 1543 1544 status_t err = drm->getOfflineLicenseKeySetIds(keySetIds); 1545 1546 if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) { 1547 return NULL; 1548 } 1549 1550 return ListOfVectorsToArrayListOfByteArray(env, keySetIds); 1551 } 1552 1553 static void android_media_MediaDrm_removeOfflineLicense( 1554 JNIEnv *env, jobject thiz, jbyteArray keySetId) { 1555 sp<IDrm> drm = GetDrm(env, thiz); 1556 1557 if (!CheckDrm(env, drm)) { 1558 return; 1559 } 1560 1561 status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId)); 1562 1563 throwExceptionAsNecessary(env, err, "Failed to remove offline license"); 1564 } 1565 1566 static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env, 1567 jobject thiz, jbyteArray jkeySetId) { 1568 sp<IDrm> drm = GetDrm(env, thiz); 1569 1570 if (!CheckDrm(env, drm)) { 1571 return gOfflineLicenseStates.kOfflineLicenseStateUnknown; 1572 } 1573 1574 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId)); 1575 1576 DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown; 1577 1578 status_t err = drm->getOfflineLicenseState(keySetId, &state); 1579 1580 if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) { 1581 return gOfflineLicenseStates.kOfflineLicenseStateUnknown; 1582 } 1583 1584 switch(state) { 1585 case DrmPlugin::kOfflineLicenseStateUsable: 1586 return gOfflineLicenseStates.kOfflineLicenseStateUsable; 1587 case DrmPlugin::kOfflineLicenseStateReleased: 1588 return gOfflineLicenseStates.kOfflineLicenseStateReleased; 1589 default: 1590 return gOfflineLicenseStates.kOfflineLicenseStateUnknown; 1591 } 1592 } 1593 1594 static jstring android_media_MediaDrm_getPropertyString( 1595 JNIEnv *env, jobject thiz, jstring jname) { 1596 sp<IDrm> drm = GetDrm(env, thiz); 1597 1598 if (!CheckDrm(env, drm)) { 1599 return NULL; 1600 } 1601 1602 if (jname == NULL) { 1603 jniThrowException(env, "java/lang/IllegalArgumentException", 1604 "property name String is null"); 1605 return NULL; 1606 } 1607 1608 String8 name = JStringToString8(env, jname); 1609 String8 value; 1610 1611 status_t err = drm->getPropertyString(name, value); 1612 1613 if (throwExceptionAsNecessary(env, err, "Failed to get property")) { 1614 return NULL; 1615 } 1616 1617 return env->NewStringUTF(value.string()); 1618 } 1619 1620 static jbyteArray android_media_MediaDrm_getPropertyByteArray( 1621 JNIEnv *env, jobject thiz, jstring jname) { 1622 sp<IDrm> drm = GetDrm(env, thiz); 1623 1624 if (!CheckDrm(env, drm)) { 1625 return NULL; 1626 } 1627 1628 if (jname == NULL) { 1629 jniThrowException(env, "java/lang/IllegalArgumentException", 1630 "property name String is null"); 1631 return NULL; 1632 } 1633 1634 String8 name = JStringToString8(env, jname); 1635 Vector<uint8_t> value; 1636 1637 status_t err = drm->getPropertyByteArray(name, value); 1638 1639 if (throwExceptionAsNecessary(env, err, "Failed to get property")) { 1640 return NULL; 1641 } 1642 1643 return VectorToJByteArray(env, value); 1644 } 1645 1646 static void android_media_MediaDrm_setPropertyString( 1647 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) { 1648 sp<IDrm> drm = GetDrm(env, thiz); 1649 1650 if (!CheckDrm(env, drm)) { 1651 return; 1652 } 1653 1654 if (jname == NULL) { 1655 jniThrowException(env, "java/lang/IllegalArgumentException", 1656 "property name String is null"); 1657 return; 1658 } 1659 1660 if (jvalue == NULL) { 1661 jniThrowException(env, "java/lang/IllegalArgumentException", 1662 "property value String is null"); 1663 return; 1664 } 1665 1666 String8 name = JStringToString8(env, jname); 1667 String8 value = JStringToString8(env, jvalue); 1668 1669 status_t err = drm->setPropertyString(name, value); 1670 1671 throwExceptionAsNecessary(env, err, "Failed to set property"); 1672 } 1673 1674 static void android_media_MediaDrm_setPropertyByteArray( 1675 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) { 1676 sp<IDrm> drm = GetDrm(env, thiz); 1677 1678 if (!CheckDrm(env, drm)) { 1679 return; 1680 } 1681 1682 if (jname == NULL) { 1683 jniThrowException(env, "java/lang/IllegalArgumentException", 1684 "property name String is null"); 1685 return; 1686 } 1687 1688 if (jvalue == NULL) { 1689 jniThrowException(env, "java/lang/IllegalArgumentException", 1690 "property value byte array is null"); 1691 return; 1692 } 1693 1694 String8 name = JStringToString8(env, jname); 1695 Vector<uint8_t> value = JByteArrayToVector(env, jvalue); 1696 1697 status_t err = drm->setPropertyByteArray(name, value); 1698 1699 throwExceptionAsNecessary(env, err, "Failed to set property"); 1700 } 1701 1702 static void android_media_MediaDrm_setCipherAlgorithmNative( 1703 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1704 jstring jalgorithm) { 1705 1706 sp<IDrm> drm = GetDrm(env, jdrm); 1707 1708 if (!CheckSession(env, drm, jsessionId)) { 1709 return; 1710 } 1711 1712 if (jalgorithm == NULL) { 1713 jniThrowException(env, "java/lang/IllegalArgumentException", 1714 "algorithm String is null"); 1715 return; 1716 } 1717 1718 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1719 String8 algorithm = JStringToString8(env, jalgorithm); 1720 1721 status_t err = drm->setCipherAlgorithm(sessionId, algorithm); 1722 1723 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm"); 1724 } 1725 1726 static void android_media_MediaDrm_setMacAlgorithmNative( 1727 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1728 jstring jalgorithm) { 1729 1730 sp<IDrm> drm = GetDrm(env, jdrm); 1731 1732 if (!CheckSession(env, drm, jsessionId)) { 1733 return; 1734 } 1735 1736 if (jalgorithm == NULL) { 1737 jniThrowException(env, "java/lang/IllegalArgumentException", 1738 "algorithm String is null"); 1739 return; 1740 } 1741 1742 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1743 String8 algorithm = JStringToString8(env, jalgorithm); 1744 1745 status_t err = drm->setMacAlgorithm(sessionId, algorithm); 1746 1747 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm"); 1748 } 1749 1750 1751 static jbyteArray android_media_MediaDrm_encryptNative( 1752 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1753 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) { 1754 1755 sp<IDrm> drm = GetDrm(env, jdrm); 1756 1757 if (!CheckSession(env, drm, jsessionId)) { 1758 return NULL; 1759 } 1760 1761 if (jkeyId == NULL || jinput == NULL || jiv == NULL) { 1762 jniThrowException(env, "java/lang/IllegalArgumentException", 1763 "required argument is null"); 1764 return NULL; 1765 } 1766 1767 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1768 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1769 Vector<uint8_t> input(JByteArrayToVector(env, jinput)); 1770 Vector<uint8_t> iv(JByteArrayToVector(env, jiv)); 1771 Vector<uint8_t> output; 1772 1773 status_t err = drm->encrypt(sessionId, keyId, input, iv, output); 1774 1775 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) { 1776 return NULL; 1777 } 1778 1779 return VectorToJByteArray(env, output); 1780 } 1781 1782 static jbyteArray android_media_MediaDrm_decryptNative( 1783 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1784 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) { 1785 1786 sp<IDrm> drm = GetDrm(env, jdrm); 1787 1788 if (!CheckSession(env, drm, jsessionId)) { 1789 return NULL; 1790 } 1791 1792 if (jkeyId == NULL || jinput == NULL || jiv == NULL) { 1793 jniThrowException(env, "java/lang/IllegalArgumentException", 1794 "required argument is null"); 1795 return NULL; 1796 } 1797 1798 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1799 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1800 Vector<uint8_t> input(JByteArrayToVector(env, jinput)); 1801 Vector<uint8_t> iv(JByteArrayToVector(env, jiv)); 1802 Vector<uint8_t> output; 1803 1804 status_t err = drm->decrypt(sessionId, keyId, input, iv, output); 1805 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) { 1806 return NULL; 1807 } 1808 1809 return VectorToJByteArray(env, output); 1810 } 1811 1812 static jbyteArray android_media_MediaDrm_signNative( 1813 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1814 jbyteArray jkeyId, jbyteArray jmessage) { 1815 1816 sp<IDrm> drm = GetDrm(env, jdrm); 1817 1818 if (!CheckSession(env, drm, jsessionId)) { 1819 return NULL; 1820 } 1821 1822 if (jkeyId == NULL || jmessage == NULL) { 1823 jniThrowException(env, "java/lang/IllegalArgumentException", 1824 "required argument is null"); 1825 return NULL; 1826 } 1827 1828 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1829 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1830 Vector<uint8_t> message(JByteArrayToVector(env, jmessage)); 1831 Vector<uint8_t> signature; 1832 1833 status_t err = drm->sign(sessionId, keyId, message, signature); 1834 1835 if (throwExceptionAsNecessary(env, err, "Failed to sign")) { 1836 return NULL; 1837 } 1838 1839 return VectorToJByteArray(env, signature); 1840 } 1841 1842 static jboolean android_media_MediaDrm_verifyNative( 1843 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1844 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) { 1845 1846 sp<IDrm> drm = GetDrm(env, jdrm); 1847 1848 if (!CheckSession(env, drm, jsessionId)) { 1849 return false; 1850 } 1851 1852 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) { 1853 jniThrowException(env, "java/lang/IllegalArgumentException", 1854 "required argument is null"); 1855 return false; 1856 } 1857 1858 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1859 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1860 Vector<uint8_t> message(JByteArrayToVector(env, jmessage)); 1861 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature)); 1862 bool match; 1863 1864 status_t err = drm->verify(sessionId, keyId, message, signature, match); 1865 1866 throwExceptionAsNecessary(env, err, "Failed to verify"); 1867 return match; 1868 } 1869 1870 static jobject 1871 android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz) 1872 { 1873 sp<IDrm> drm = GetDrm(env, thiz); 1874 1875 if (!CheckDrm(env, drm)) { 1876 return NULL; 1877 } 1878 1879 // Retrieve current metrics snapshot from drm. 1880 PersistableBundle metrics; 1881 status_t err = drm->getMetrics(&metrics); 1882 if (err != OK) { 1883 ALOGE("getMetrics failed: %d", (int)err); 1884 return (jobject) NULL; 1885 } 1886 1887 return nativeToJavaPersistableBundle(env, thiz, &metrics); 1888 } 1889 1890 static jbyteArray android_media_MediaDrm_signRSANative( 1891 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1892 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) { 1893 1894 sp<IDrm> drm = GetDrm(env, jdrm); 1895 1896 if (!CheckSession(env, drm, jsessionId)) { 1897 return NULL; 1898 } 1899 1900 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) { 1901 jniThrowException(env, "java/lang/IllegalArgumentException", 1902 "required argument is null"); 1903 return NULL; 1904 } 1905 1906 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1907 String8 algorithm = JStringToString8(env, jalgorithm); 1908 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey)); 1909 Vector<uint8_t> message(JByteArrayToVector(env, jmessage)); 1910 Vector<uint8_t> signature; 1911 1912 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature); 1913 1914 if (throwExceptionAsNecessary(env, err, "Failed to sign")) { 1915 return NULL; 1916 } 1917 1918 return VectorToJByteArray(env, signature); 1919 } 1920 1921 1922 static const JNINativeMethod gMethods[] = { 1923 { "native_release", "()V", (void *)android_media_MediaDrm_native_release }, 1924 1925 { "native_init", "()V", (void *)android_media_MediaDrm_native_init }, 1926 1927 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V", 1928 (void *)android_media_MediaDrm_native_setup }, 1929 1930 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z", 1931 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative }, 1932 1933 { "openSession", "(I)[B", 1934 (void *)android_media_MediaDrm_openSession }, 1935 1936 { "closeSession", "([B)V", 1937 (void *)android_media_MediaDrm_closeSession }, 1938 1939 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)" 1940 "Landroid/media/MediaDrm$KeyRequest;", 1941 (void *)android_media_MediaDrm_getKeyRequest }, 1942 1943 { "provideKeyResponse", "([B[B)[B", 1944 (void *)android_media_MediaDrm_provideKeyResponse }, 1945 1946 { "removeKeys", "([B)V", 1947 (void *)android_media_MediaDrm_removeKeys }, 1948 1949 { "restoreKeys", "([B[B)V", 1950 (void *)android_media_MediaDrm_restoreKeys }, 1951 1952 { "queryKeyStatus", "([B)Ljava/util/HashMap;", 1953 (void *)android_media_MediaDrm_queryKeyStatus }, 1954 1955 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;", 1956 (void *)android_media_MediaDrm_getProvisionRequestNative }, 1957 1958 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;", 1959 (void *)android_media_MediaDrm_provideProvisionResponseNative }, 1960 1961 { "getSecureStops", "()Ljava/util/List;", 1962 (void *)android_media_MediaDrm_getSecureStops }, 1963 1964 { "getSecureStopIds", "()Ljava/util/List;", 1965 (void *)android_media_MediaDrm_getSecureStopIds }, 1966 1967 { "getSecureStop", "([B)[B", 1968 (void *)android_media_MediaDrm_getSecureStop }, 1969 1970 { "releaseSecureStops", "([B)V", 1971 (void *)android_media_MediaDrm_releaseSecureStops }, 1972 1973 { "removeSecureStop", "([B)V", 1974 (void *)android_media_MediaDrm_removeSecureStop }, 1975 1976 { "removeAllSecureStops", "()V", 1977 (void *)android_media_MediaDrm_removeAllSecureStops }, 1978 1979 { "getConnectedHdcpLevel", "()I", 1980 (void *)android_media_MediaDrm_getConnectedHdcpLevel }, 1981 1982 { "getMaxHdcpLevel", "()I", 1983 (void *)android_media_MediaDrm_getMaxHdcpLevel }, 1984 1985 { "getOpenSessionCount", "()I", 1986 (void *)android_media_MediaDrm_getOpenSessionCount }, 1987 1988 { "getMaxSessionCount", "()I", 1989 (void *)android_media_MediaDrm_getMaxSessionCount }, 1990 1991 { "getSecurityLevel", "([B)I", 1992 (void *)android_media_MediaDrm_getSecurityLevel }, 1993 1994 { "removeOfflineLicense", "([B)V", 1995 (void *)android_media_MediaDrm_removeOfflineLicense }, 1996 1997 { "getOfflineLicenseKeySetIds", "()Ljava/util/List;", 1998 (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds }, 1999 2000 { "getOfflineLicenseState", "([B)I", 2001 (void *)android_media_MediaDrm_getOfflineLicenseState }, 2002 2003 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", 2004 (void *)android_media_MediaDrm_getPropertyString }, 2005 2006 { "getPropertyByteArray", "(Ljava/lang/String;)[B", 2007 (void *)android_media_MediaDrm_getPropertyByteArray }, 2008 2009 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V", 2010 (void *)android_media_MediaDrm_setPropertyString }, 2011 2012 { "setPropertyByteArray", "(Ljava/lang/String;[B)V", 2013 (void *)android_media_MediaDrm_setPropertyByteArray }, 2014 2015 { "setCipherAlgorithmNative", 2016 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V", 2017 (void *)android_media_MediaDrm_setCipherAlgorithmNative }, 2018 2019 { "setMacAlgorithmNative", 2020 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V", 2021 (void *)android_media_MediaDrm_setMacAlgorithmNative }, 2022 2023 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B", 2024 (void *)android_media_MediaDrm_encryptNative }, 2025 2026 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B", 2027 (void *)android_media_MediaDrm_decryptNative }, 2028 2029 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B", 2030 (void *)android_media_MediaDrm_signNative }, 2031 2032 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z", 2033 (void *)android_media_MediaDrm_verifyNative }, 2034 2035 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B", 2036 (void *)android_media_MediaDrm_signRSANative }, 2037 2038 { "getMetricsNative", "()Landroid/os/PersistableBundle;", 2039 (void *)android_media_MediaDrm_native_getMetrics }, 2040 }; 2041 2042 int register_android_media_Drm(JNIEnv *env) { 2043 return AndroidRuntime::registerNativeMethods(env, 2044 "android/media/MediaDrm", gMethods, NELEM(gMethods)); 2045 } 2046