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 23 #include "android_runtime/AndroidRuntime.h" 24 #include "android_runtime/Log.h" 25 #include "android_os_Parcel.h" 26 #include "jni.h" 27 #include "JNIHelp.h" 28 29 #include <binder/IServiceManager.h> 30 #include <binder/Parcel.h> 31 #include <cutils/properties.h> 32 #include <media/IDrm.h> 33 #include <media/IMediaDrmService.h> 34 #include <media/stagefright/foundation/ADebug.h> 35 #include <media/stagefright/MediaErrors.h> 36 37 namespace android { 38 39 #define FIND_CLASS(var, className) \ 40 var = env->FindClass(className); \ 41 LOG_FATAL_IF(! var, "Unable to find class " className); 42 43 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 44 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 45 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 46 47 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ 48 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \ 49 LOG_FATAL_IF(! var, "Unable to find method " fieldName); 50 51 #define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 52 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \ 53 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 54 55 #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ 56 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \ 57 LOG_FATAL_IF(! var, "Unable to find static method " fieldName); 58 59 60 struct RequestFields { 61 jfieldID data; 62 jfieldID defaultUrl; 63 jfieldID requestType; 64 }; 65 66 struct ArrayListFields { 67 jmethodID init; 68 jmethodID add; 69 }; 70 71 struct HashmapFields { 72 jmethodID init; 73 jmethodID get; 74 jmethodID put; 75 jmethodID entrySet; 76 }; 77 78 struct SetFields { 79 jmethodID iterator; 80 }; 81 82 struct IteratorFields { 83 jmethodID next; 84 jmethodID hasNext; 85 }; 86 87 struct EntryFields { 88 jmethodID getKey; 89 jmethodID getValue; 90 }; 91 92 struct EventTypes { 93 jint kEventProvisionRequired; 94 jint kEventKeyRequired; 95 jint kEventKeyExpired; 96 jint kEventVendorDefined; 97 jint kEventSessionReclaimed; 98 } gEventTypes; 99 100 struct EventWhat { 101 jint kWhatDrmEvent; 102 jint kWhatExpirationUpdate; 103 jint kWhatKeyStatusChange; 104 } gEventWhat; 105 106 struct KeyTypes { 107 jint kKeyTypeStreaming; 108 jint kKeyTypeOffline; 109 jint kKeyTypeRelease; 110 } gKeyTypes; 111 112 struct KeyRequestTypes { 113 jint kKeyRequestTypeInitial; 114 jint kKeyRequestTypeRenewal; 115 jint kKeyRequestTypeRelease; 116 } gKeyRequestTypes; 117 118 struct CertificateTypes { 119 jint kCertificateTypeNone; 120 jint kCertificateTypeX509; 121 } gCertificateTypes; 122 123 struct CertificateFields { 124 jfieldID wrappedPrivateKey; 125 jfieldID certificateData; 126 }; 127 128 struct StateExceptionFields { 129 jmethodID init; 130 jclass classId; 131 }; 132 133 struct fields_t { 134 jfieldID context; 135 jmethodID post_event; 136 RequestFields keyRequest; 137 RequestFields provisionRequest; 138 ArrayListFields arraylist; 139 HashmapFields hashmap; 140 SetFields set; 141 IteratorFields iterator; 142 EntryFields entry; 143 CertificateFields certificate; 144 StateExceptionFields stateException; 145 jclass certificateClassId; 146 jclass hashmapClassId; 147 jclass arraylistClassId; 148 jclass stringClassId; 149 }; 150 151 static fields_t gFields; 152 153 // ---------------------------------------------------------------------------- 154 // ref-counted object for callbacks 155 class JNIDrmListener: public DrmListener 156 { 157 public: 158 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz); 159 ~JNIDrmListener(); 160 virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL); 161 private: 162 JNIDrmListener(); 163 jclass mClass; // Reference to MediaDrm class 164 jobject mObject; // Weak ref to MediaDrm Java object to call on 165 }; 166 167 JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz) 168 { 169 // Hold onto the MediaDrm class for use in calling the static method 170 // that posts events to the application thread. 171 jclass clazz = env->GetObjectClass(thiz); 172 if (clazz == NULL) { 173 ALOGE("Can't find android/media/MediaDrm"); 174 jniThrowException(env, "java/lang/Exception", 175 "Can't find android/media/MediaDrm"); 176 return; 177 } 178 mClass = (jclass)env->NewGlobalRef(clazz); 179 180 // We use a weak reference so the MediaDrm object can be garbage collected. 181 // The reference is only used as a proxy for callbacks. 182 mObject = env->NewGlobalRef(weak_thiz); 183 } 184 185 JNIDrmListener::~JNIDrmListener() 186 { 187 // remove global references 188 JNIEnv *env = AndroidRuntime::getJNIEnv(); 189 env->DeleteGlobalRef(mObject); 190 env->DeleteGlobalRef(mClass); 191 } 192 193 void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra, 194 const Parcel *obj) 195 { 196 jint jwhat; 197 jint jeventType = 0; 198 199 // translate DrmPlugin event types into their java equivalents 200 switch (eventType) { 201 case DrmPlugin::kDrmPluginEventProvisionRequired: 202 jwhat = gEventWhat.kWhatDrmEvent; 203 jeventType = gEventTypes.kEventProvisionRequired; 204 break; 205 case DrmPlugin::kDrmPluginEventKeyNeeded: 206 jwhat = gEventWhat.kWhatDrmEvent; 207 jeventType = gEventTypes.kEventKeyRequired; 208 break; 209 case DrmPlugin::kDrmPluginEventKeyExpired: 210 jwhat = gEventWhat.kWhatDrmEvent; 211 jeventType = gEventTypes.kEventKeyExpired; 212 break; 213 case DrmPlugin::kDrmPluginEventVendorDefined: 214 jwhat = gEventWhat.kWhatDrmEvent; 215 jeventType = gEventTypes.kEventVendorDefined; 216 break; 217 case DrmPlugin::kDrmPluginEventSessionReclaimed: 218 jwhat = gEventWhat.kWhatDrmEvent; 219 jeventType = gEventTypes.kEventSessionReclaimed; 220 break; 221 case DrmPlugin::kDrmPluginEventExpirationUpdate: 222 jwhat = gEventWhat.kWhatExpirationUpdate; 223 break; 224 case DrmPlugin::kDrmPluginEventKeysChange: 225 jwhat = gEventWhat.kWhatKeyStatusChange; 226 break; 227 default: 228 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType); 229 return; 230 } 231 232 JNIEnv *env = AndroidRuntime::getJNIEnv(); 233 if (obj && obj->dataSize() > 0) { 234 jobject jParcel = createJavaParcelObject(env); 235 if (jParcel != NULL) { 236 Parcel* nativeParcel = parcelForJavaObject(env, jParcel); 237 nativeParcel->setData(obj->data(), obj->dataSize()); 238 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject, 239 jwhat, jeventType, extra, jParcel); 240 env->DeleteLocalRef(jParcel); 241 } 242 } 243 244 if (env->ExceptionCheck()) { 245 ALOGW("An exception occurred while notifying an event."); 246 LOGW_EX(env); 247 env->ExceptionClear(); 248 } 249 } 250 251 static void throwStateException(JNIEnv *env, const char *msg, status_t err) { 252 ALOGE("Illegal state exception: %s (%d)", msg, err); 253 254 jobject exception = env->NewObject(gFields.stateException.classId, 255 gFields.stateException.init, static_cast<int>(err), 256 env->NewStringUTF(msg)); 257 env->Throw(static_cast<jthrowable>(exception)); 258 } 259 260 static bool throwExceptionAsNecessary( 261 JNIEnv *env, status_t err, const char *msg = NULL) { 262 263 const char *drmMessage = NULL; 264 265 switch (err) { 266 case ERROR_DRM_UNKNOWN: 267 drmMessage = "General DRM error"; 268 break; 269 case ERROR_DRM_NO_LICENSE: 270 drmMessage = "No license"; 271 break; 272 case ERROR_DRM_LICENSE_EXPIRED: 273 drmMessage = "License expired"; 274 break; 275 case ERROR_DRM_SESSION_NOT_OPENED: 276 drmMessage = "Session not opened"; 277 break; 278 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED: 279 drmMessage = "Not initialized"; 280 break; 281 case ERROR_DRM_DECRYPT: 282 drmMessage = "Decrypt error"; 283 break; 284 case ERROR_DRM_CANNOT_HANDLE: 285 drmMessage = "Unsupported scheme or data format"; 286 break; 287 case ERROR_DRM_TAMPER_DETECTED: 288 drmMessage = "Invalid state"; 289 break; 290 default: 291 break; 292 } 293 294 String8 vendorMessage; 295 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) { 296 vendorMessage = String8::format("DRM vendor-defined error: %d", err); 297 drmMessage = vendorMessage.string(); 298 } 299 300 if (err == BAD_VALUE) { 301 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 302 return true; 303 } else if (err == ERROR_DRM_NOT_PROVISIONED) { 304 jniThrowException(env, "android/media/NotProvisionedException", msg); 305 return true; 306 } else if (err == ERROR_DRM_RESOURCE_BUSY) { 307 jniThrowException(env, "android/media/ResourceBusyException", msg); 308 return true; 309 } else if (err == ERROR_DRM_DEVICE_REVOKED) { 310 jniThrowException(env, "android/media/DeniedByServerException", msg); 311 return true; 312 } else if (err == DEAD_OBJECT) { 313 jniThrowException(env, "android/media/MediaDrmResetException", 314 "mediaserver died"); 315 return true; 316 } else if (err != OK) { 317 String8 errbuf; 318 if (drmMessage != NULL) { 319 if (msg == NULL) { 320 msg = drmMessage; 321 } else { 322 errbuf = String8::format("%s: %s", msg, drmMessage); 323 msg = errbuf.string(); 324 } 325 } 326 throwStateException(env, msg, err); 327 return true; 328 } 329 return false; 330 } 331 332 static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) { 333 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context); 334 return jdrm ? jdrm->getDrm() : NULL; 335 } 336 337 JDrm::JDrm( 338 JNIEnv *env, jobject thiz, const uint8_t uuid[16]) { 339 mObject = env->NewWeakGlobalRef(thiz); 340 mDrm = MakeDrm(uuid); 341 if (mDrm != NULL) { 342 mDrm->setListener(this); 343 } 344 } 345 346 JDrm::~JDrm() { 347 JNIEnv *env = AndroidRuntime::getJNIEnv(); 348 349 env->DeleteWeakGlobalRef(mObject); 350 mObject = NULL; 351 } 352 353 // static 354 sp<IDrm> JDrm::MakeDrm() { 355 sp<IServiceManager> sm = defaultServiceManager(); 356 357 sp<IBinder> binder = sm->getService(String16("media.drm")); 358 sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder); 359 if (service == NULL) { 360 return NULL; 361 } 362 363 sp<IDrm> drm = service->makeDrm(); 364 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) { 365 return NULL; 366 } 367 368 return drm; 369 } 370 371 // static 372 sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) { 373 sp<IDrm> drm = MakeDrm(); 374 375 if (drm == NULL) { 376 return NULL; 377 } 378 379 status_t err = drm->createPlugin(uuid); 380 381 if (err != OK) { 382 return NULL; 383 } 384 385 return drm; 386 } 387 388 status_t JDrm::setListener(const sp<DrmListener>& listener) { 389 Mutex::Autolock lock(mLock); 390 mListener = listener; 391 return OK; 392 } 393 394 void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) { 395 sp<DrmListener> listener; 396 mLock.lock(); 397 listener = mListener; 398 mLock.unlock(); 399 400 if (listener != NULL) { 401 Mutex::Autolock lock(mNotifyLock); 402 listener->notify(eventType, extra, obj); 403 } 404 } 405 406 void JDrm::disconnect() { 407 if (mDrm != NULL) { 408 mDrm->destroyPlugin(); 409 mDrm.clear(); 410 } 411 } 412 413 414 // static 415 bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { 416 sp<IDrm> drm = MakeDrm(); 417 418 if (drm == NULL) { 419 return false; 420 } 421 422 return drm->isCryptoSchemeSupported(uuid, mimeType); 423 } 424 425 status_t JDrm::initCheck() const { 426 return mDrm == NULL ? NO_INIT : OK; 427 } 428 429 // JNI conversion utilities 430 static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) { 431 Vector<uint8_t> vector; 432 size_t length = env->GetArrayLength(byteArray); 433 vector.insertAt((size_t)0, length); 434 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray()); 435 return vector; 436 } 437 438 static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) { 439 size_t length = vector.size(); 440 jbyteArray result = env->NewByteArray(length); 441 if (result != NULL) { 442 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array()); 443 } 444 return result; 445 } 446 447 static String8 JStringToString8(JNIEnv *env, jstring const &jstr) { 448 String8 result; 449 450 const char *s = env->GetStringUTFChars(jstr, NULL); 451 if (s) { 452 result = s; 453 env->ReleaseStringUTFChars(jstr, s); 454 } 455 return result; 456 } 457 458 /* 459 import java.util.HashMap; 460 import java.util.Set; 461 import java.Map.Entry; 462 import jav.util.Iterator; 463 464 HashMap<k, v> hm; 465 Set<Entry<k, v> > s = hm.entrySet(); 466 Iterator i = s.iterator(); 467 Entry e = s.next(); 468 */ 469 470 static KeyedVector<String8, String8> HashMapToKeyedVector( 471 JNIEnv *env, jobject &hashMap, bool* pIsOK) { 472 jclass clazz = gFields.stringClassId; 473 KeyedVector<String8, String8> keyedVector; 474 *pIsOK = true; 475 476 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet); 477 if (entrySet) { 478 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator); 479 if (iterator) { 480 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 481 while (hasNext) { 482 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next); 483 if (entry) { 484 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey); 485 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) { 486 jniThrowException(env, "java/lang/IllegalArgumentException", 487 "HashMap key is not a String"); 488 env->DeleteLocalRef(entry); 489 *pIsOK = false; 490 break; 491 } 492 jstring jkey = static_cast<jstring>(obj); 493 494 obj = env->CallObjectMethod(entry, gFields.entry.getValue); 495 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) { 496 jniThrowException(env, "java/lang/IllegalArgumentException", 497 "HashMap value is not a String"); 498 env->DeleteLocalRef(entry); 499 *pIsOK = false; 500 break; 501 } 502 jstring jvalue = static_cast<jstring>(obj); 503 504 String8 key = JStringToString8(env, jkey); 505 String8 value = JStringToString8(env, jvalue); 506 keyedVector.add(key, value); 507 508 env->DeleteLocalRef(jkey); 509 env->DeleteLocalRef(jvalue); 510 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 511 } 512 env->DeleteLocalRef(entry); 513 } 514 env->DeleteLocalRef(iterator); 515 } 516 env->DeleteLocalRef(entrySet); 517 } 518 return keyedVector; 519 } 520 521 static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) { 522 jclass clazz = gFields.hashmapClassId; 523 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init); 524 for (size_t i = 0; i < map.size(); ++i) { 525 jstring jkey = env->NewStringUTF(map.keyAt(i).string()); 526 jstring jvalue = env->NewStringUTF(map.valueAt(i).string()); 527 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue); 528 env->DeleteLocalRef(jkey); 529 env->DeleteLocalRef(jvalue); 530 } 531 return hashMap; 532 } 533 534 static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env, 535 List<Vector<uint8_t> > list) { 536 jclass clazz = gFields.arraylistClassId; 537 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init); 538 List<Vector<uint8_t> >::iterator iter = list.begin(); 539 while (iter != list.end()) { 540 jbyteArray byteArray = VectorToJByteArray(env, *iter); 541 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray); 542 env->DeleteLocalRef(byteArray); 543 iter++; 544 } 545 546 return arrayList; 547 } 548 549 } // namespace android 550 551 using namespace android; 552 553 static sp<JDrm> setDrm( 554 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) { 555 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context); 556 if (drm != NULL) { 557 drm->incStrong(thiz); 558 } 559 if (old != NULL) { 560 old->decStrong(thiz); 561 } 562 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get())); 563 564 return old; 565 } 566 567 static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId) 568 { 569 if (drm == NULL) { 570 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null"); 571 return false; 572 } 573 574 if (jsessionId == NULL) { 575 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null"); 576 return false; 577 } 578 return true; 579 } 580 581 static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) { 582 sp<JDrm> drm = setDrm(env, thiz, NULL); 583 if (drm != NULL) { 584 drm->setListener(NULL); 585 drm->disconnect(); 586 } 587 } 588 589 static void android_media_MediaDrm_native_init(JNIEnv *env) { 590 jclass clazz; 591 FIND_CLASS(clazz, "android/media/MediaDrm"); 592 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J"); 593 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative", 594 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 595 596 jfieldID field; 597 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I"); 598 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field); 599 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I"); 600 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field); 601 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I"); 602 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field); 603 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I"); 604 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field); 605 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I"); 606 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field); 607 608 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I"); 609 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field); 610 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I"); 611 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field); 612 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I"); 613 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field); 614 615 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I"); 616 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field); 617 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I"); 618 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field); 619 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I"); 620 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field); 621 622 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I"); 623 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field); 624 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I"); 625 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field); 626 627 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); 628 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B"); 629 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;"); 630 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I"); 631 632 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I"); 633 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field); 634 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I"); 635 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field); 636 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I"); 637 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field); 638 639 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest"); 640 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B"); 641 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;"); 642 643 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate"); 644 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B"); 645 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B"); 646 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 647 648 FIND_CLASS(clazz, "java/util/ArrayList"); 649 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V"); 650 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z"); 651 652 FIND_CLASS(clazz, "java/util/HashMap"); 653 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V"); 654 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); 655 GET_METHOD_ID(gFields.hashmap.put, clazz, "put", 656 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 657 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;"); 658 659 FIND_CLASS(clazz, "java/util/Set"); 660 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;"); 661 662 FIND_CLASS(clazz, "java/util/Iterator"); 663 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;"); 664 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z"); 665 666 FIND_CLASS(clazz, "java/util/Map$Entry"); 667 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;"); 668 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;"); 669 670 FIND_CLASS(clazz, "java/util/HashMap"); 671 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 672 673 FIND_CLASS(clazz, "java/lang/String"); 674 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 675 676 FIND_CLASS(clazz, "java/util/ArrayList"); 677 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); 678 679 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException"); 680 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V"); 681 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz)); 682 } 683 684 static void android_media_MediaDrm_native_setup( 685 JNIEnv *env, jobject thiz, 686 jobject weak_this, jbyteArray uuidObj) { 687 688 if (uuidObj == NULL) { 689 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null"); 690 return; 691 } 692 693 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); 694 695 if (uuid.size() != 16) { 696 jniThrowException(env, "java/lang/IllegalArgumentException", 697 "invalid UUID size, expected 16 bytes"); 698 return; 699 } 700 701 sp<JDrm> drm = new JDrm(env, thiz, uuid.array()); 702 703 status_t err = drm->initCheck(); 704 705 if (err != OK) { 706 jniThrowException( 707 env, 708 "android/media/UnsupportedSchemeException", 709 "Failed to instantiate drm object."); 710 return; 711 } 712 713 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this); 714 drm->setListener(listener); 715 setDrm(env, thiz, drm); 716 } 717 718 static void android_media_MediaDrm_native_finalize( 719 JNIEnv *env, jobject thiz) { 720 android_media_MediaDrm_release(env, thiz); 721 } 722 723 static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative( 724 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType) { 725 726 if (uuidObj == NULL) { 727 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 728 return false; 729 } 730 731 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); 732 733 if (uuid.size() != 16) { 734 jniThrowException( 735 env, 736 "java/lang/IllegalArgumentException", 737 "invalid UUID size, expected 16 bytes"); 738 return false; 739 } 740 741 String8 mimeType; 742 if (jmimeType != NULL) { 743 mimeType = JStringToString8(env, jmimeType); 744 } 745 746 return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType); 747 } 748 749 static jbyteArray android_media_MediaDrm_openSession( 750 JNIEnv *env, jobject thiz) { 751 sp<IDrm> drm = GetDrm(env, thiz); 752 753 if (drm == NULL) { 754 jniThrowException(env, "java/lang/IllegalStateException", 755 "MediaDrm obj is null"); 756 return NULL; 757 } 758 759 Vector<uint8_t> sessionId; 760 status_t err = drm->openSession(sessionId); 761 762 if (throwExceptionAsNecessary(env, err, "Failed to open session")) { 763 return NULL; 764 } 765 766 return VectorToJByteArray(env, sessionId); 767 } 768 769 static void android_media_MediaDrm_closeSession( 770 JNIEnv *env, jobject thiz, jbyteArray jsessionId) { 771 sp<IDrm> drm = GetDrm(env, thiz); 772 773 if (!CheckSession(env, drm, jsessionId)) { 774 return; 775 } 776 777 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 778 779 status_t err = drm->closeSession(sessionId); 780 781 throwExceptionAsNecessary(env, err, "Failed to close session"); 782 } 783 784 static jobject android_media_MediaDrm_getKeyRequest( 785 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData, 786 jstring jmimeType, jint jkeyType, jobject joptParams) { 787 sp<IDrm> drm = GetDrm(env, thiz); 788 789 if (!CheckSession(env, drm, jsessionId)) { 790 return NULL; 791 } 792 793 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 794 795 Vector<uint8_t> initData; 796 if (jinitData != NULL) { 797 initData = JByteArrayToVector(env, jinitData); 798 } 799 800 String8 mimeType; 801 if (jmimeType != NULL) { 802 mimeType = JStringToString8(env, jmimeType); 803 } 804 805 DrmPlugin::KeyType keyType; 806 if (jkeyType == gKeyTypes.kKeyTypeStreaming) { 807 keyType = DrmPlugin::kKeyType_Streaming; 808 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) { 809 keyType = DrmPlugin::kKeyType_Offline; 810 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) { 811 keyType = DrmPlugin::kKeyType_Release; 812 } else { 813 jniThrowException(env, "java/lang/IllegalArgumentException", 814 "invalid keyType"); 815 return NULL; 816 } 817 818 KeyedVector<String8, String8> optParams; 819 if (joptParams != NULL) { 820 bool isOK; 821 optParams = HashMapToKeyedVector(env, joptParams, &isOK); 822 if (!isOK) { 823 return NULL; 824 } 825 } 826 827 Vector<uint8_t> request; 828 String8 defaultUrl; 829 DrmPlugin::KeyRequestType keyRequestType; 830 831 status_t err = drm->getKeyRequest(sessionId, initData, mimeType, 832 keyType, optParams, request, defaultUrl, &keyRequestType); 833 834 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) { 835 return NULL; 836 } 837 838 // Fill out return obj 839 jclass clazz; 840 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); 841 842 jobject keyObj = NULL; 843 844 if (clazz) { 845 keyObj = env->AllocObject(clazz); 846 jbyteArray jrequest = VectorToJByteArray(env, request); 847 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest); 848 849 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string()); 850 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl); 851 852 switch (keyRequestType) { 853 case DrmPlugin::kKeyRequestType_Initial: 854 env->SetIntField(keyObj, gFields.keyRequest.requestType, 855 gKeyRequestTypes.kKeyRequestTypeInitial); 856 break; 857 case DrmPlugin::kKeyRequestType_Renewal: 858 env->SetIntField(keyObj, gFields.keyRequest.requestType, 859 gKeyRequestTypes.kKeyRequestTypeRenewal); 860 break; 861 case DrmPlugin::kKeyRequestType_Release: 862 env->SetIntField(keyObj, gFields.keyRequest.requestType, 863 gKeyRequestTypes.kKeyRequestTypeRelease); 864 break; 865 default: 866 throwStateException(env, "DRM plugin failure: unknown key request type", 867 ERROR_DRM_UNKNOWN); 868 break; 869 } 870 } 871 872 return keyObj; 873 } 874 875 static jbyteArray android_media_MediaDrm_provideKeyResponse( 876 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) { 877 sp<IDrm> drm = GetDrm(env, thiz); 878 879 if (!CheckSession(env, drm, jsessionId)) { 880 return NULL; 881 } 882 883 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 884 885 if (jresponse == NULL) { 886 jniThrowException(env, "java/lang/IllegalArgumentException", 887 "key response is null"); 888 return NULL; 889 } 890 Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); 891 Vector<uint8_t> keySetId; 892 893 status_t err = drm->provideKeyResponse(sessionId, response, keySetId); 894 895 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) { 896 return NULL; 897 } 898 return VectorToJByteArray(env, keySetId); 899 } 900 901 static void android_media_MediaDrm_removeKeys( 902 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) { 903 sp<IDrm> drm = GetDrm(env, thiz); 904 905 if (jkeysetId == NULL) { 906 jniThrowException(env, "java/lang/IllegalArgumentException", 907 "keySetId is null"); 908 return; 909 } 910 911 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId)); 912 913 status_t err = drm->removeKeys(keySetId); 914 915 throwExceptionAsNecessary(env, err, "Failed to remove keys"); 916 } 917 918 static void android_media_MediaDrm_restoreKeys( 919 JNIEnv *env, jobject thiz, jbyteArray jsessionId, 920 jbyteArray jkeysetId) { 921 922 sp<IDrm> drm = GetDrm(env, thiz); 923 924 if (!CheckSession(env, drm, jsessionId)) { 925 return; 926 } 927 928 if (jkeysetId == NULL) { 929 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 930 return; 931 } 932 933 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 934 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId)); 935 936 status_t err = drm->restoreKeys(sessionId, keySetId); 937 938 throwExceptionAsNecessary(env, err, "Failed to restore keys"); 939 } 940 941 static jobject android_media_MediaDrm_queryKeyStatus( 942 JNIEnv *env, jobject thiz, jbyteArray jsessionId) { 943 sp<IDrm> drm = GetDrm(env, thiz); 944 945 if (!CheckSession(env, drm, jsessionId)) { 946 return NULL; 947 } 948 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 949 950 KeyedVector<String8, String8> infoMap; 951 952 status_t err = drm->queryKeyStatus(sessionId, infoMap); 953 954 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) { 955 return NULL; 956 } 957 958 return KeyedVectorToHashMap(env, infoMap); 959 } 960 961 static jobject android_media_MediaDrm_getProvisionRequestNative( 962 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) { 963 sp<IDrm> drm = GetDrm(env, thiz); 964 965 if (drm == NULL) { 966 jniThrowException(env, "java/lang/IllegalStateException", 967 "MediaDrm obj is null"); 968 return NULL; 969 } 970 971 Vector<uint8_t> request; 972 String8 defaultUrl; 973 974 String8 certType; 975 if (jcertType == gCertificateTypes.kCertificateTypeX509) { 976 certType = "X.509"; 977 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) { 978 certType = "none"; 979 } else { 980 certType = "invalid"; 981 } 982 983 String8 certAuthority = JStringToString8(env, jcertAuthority); 984 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl); 985 986 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) { 987 return NULL; 988 } 989 990 // Fill out return obj 991 jclass clazz; 992 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest"); 993 994 jobject provisionObj = NULL; 995 996 if (clazz) { 997 provisionObj = env->AllocObject(clazz); 998 jbyteArray jrequest = VectorToJByteArray(env, request); 999 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest); 1000 1001 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string()); 1002 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl); 1003 } 1004 1005 return provisionObj; 1006 } 1007 1008 static jobject android_media_MediaDrm_provideProvisionResponseNative( 1009 JNIEnv *env, jobject thiz, jbyteArray jresponse) { 1010 sp<IDrm> drm = GetDrm(env, thiz); 1011 1012 if (drm == NULL) { 1013 jniThrowException(env, "java/lang/IllegalStateException", 1014 "MediaDrm obj is null"); 1015 return NULL; 1016 } 1017 1018 if (jresponse == NULL) { 1019 jniThrowException(env, "java/lang/IllegalArgumentException", 1020 "provision response is null"); 1021 return NULL; 1022 } 1023 1024 Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); 1025 Vector<uint8_t> certificate, wrappedKey; 1026 1027 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey); 1028 1029 // Fill out return obj 1030 jclass clazz = gFields.certificateClassId; 1031 1032 jobject certificateObj = NULL; 1033 1034 if (clazz && certificate.size() && wrappedKey.size()) { 1035 certificateObj = env->AllocObject(clazz); 1036 jbyteArray jcertificate = VectorToJByteArray(env, certificate); 1037 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate); 1038 1039 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey); 1040 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey); 1041 } 1042 1043 throwExceptionAsNecessary(env, err, "Failed to handle provision response"); 1044 return certificateObj; 1045 } 1046 1047 static jobject android_media_MediaDrm_getSecureStops( 1048 JNIEnv *env, jobject thiz) { 1049 sp<IDrm> drm = GetDrm(env, thiz); 1050 1051 if (drm == NULL) { 1052 jniThrowException(env, "java/lang/IllegalStateException", 1053 "MediaDrm obj is null"); 1054 return NULL; 1055 } 1056 1057 List<Vector<uint8_t> > secureStops; 1058 1059 status_t err = drm->getSecureStops(secureStops); 1060 1061 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) { 1062 return NULL; 1063 } 1064 1065 return ListOfVectorsToArrayListOfByteArray(env, secureStops); 1066 } 1067 1068 static jbyteArray android_media_MediaDrm_getSecureStop( 1069 JNIEnv *env, jobject thiz, jbyteArray ssid) { 1070 sp<IDrm> drm = GetDrm(env, thiz); 1071 1072 if (drm == NULL) { 1073 jniThrowException(env, "java/lang/IllegalStateException", 1074 "MediaDrm obj is null"); 1075 return NULL; 1076 } 1077 1078 Vector<uint8_t> secureStop; 1079 1080 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop); 1081 1082 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) { 1083 return NULL; 1084 } 1085 1086 return VectorToJByteArray(env, secureStop); 1087 } 1088 1089 static void android_media_MediaDrm_releaseSecureStops( 1090 JNIEnv *env, jobject thiz, jbyteArray jssRelease) { 1091 sp<IDrm> drm = GetDrm(env, thiz); 1092 1093 if (drm == NULL) { 1094 jniThrowException(env, "java/lang/IllegalStateException", 1095 "MediaDrm obj is null"); 1096 return; 1097 } 1098 1099 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease)); 1100 1101 status_t err = drm->releaseSecureStops(ssRelease); 1102 1103 throwExceptionAsNecessary(env, err, "Failed to release secure stops"); 1104 } 1105 1106 static void android_media_MediaDrm_releaseAllSecureStops( 1107 JNIEnv *env, jobject thiz) { 1108 sp<IDrm> drm = GetDrm(env, thiz); 1109 1110 if (drm == NULL) { 1111 jniThrowException(env, "java/lang/IllegalStateException", 1112 "MediaDrm obj is null"); 1113 return; 1114 } 1115 1116 status_t err = drm->releaseAllSecureStops(); 1117 1118 throwExceptionAsNecessary(env, err, "Failed to release all secure stops"); 1119 } 1120 1121 static jstring android_media_MediaDrm_getPropertyString( 1122 JNIEnv *env, jobject thiz, jstring jname) { 1123 sp<IDrm> drm = GetDrm(env, thiz); 1124 1125 if (drm == NULL) { 1126 jniThrowException(env, "java/lang/IllegalStateException", 1127 "MediaDrm obj is null"); 1128 return NULL; 1129 } 1130 1131 if (jname == NULL) { 1132 jniThrowException(env, "java/lang/IllegalArgumentException", 1133 "property name String is null"); 1134 return NULL; 1135 } 1136 1137 String8 name = JStringToString8(env, jname); 1138 String8 value; 1139 1140 status_t err = drm->getPropertyString(name, value); 1141 1142 if (throwExceptionAsNecessary(env, err, "Failed to get property")) { 1143 return NULL; 1144 } 1145 1146 return env->NewStringUTF(value.string()); 1147 } 1148 1149 static jbyteArray android_media_MediaDrm_getPropertyByteArray( 1150 JNIEnv *env, jobject thiz, jstring jname) { 1151 sp<IDrm> drm = GetDrm(env, thiz); 1152 1153 if (drm == NULL) { 1154 jniThrowException(env, "java/lang/IllegalStateException", 1155 "MediaDrm obj is null"); 1156 return NULL; 1157 } 1158 1159 if (jname == NULL) { 1160 jniThrowException(env, "java/lang/IllegalArgumentException", 1161 "property name String is null"); 1162 return NULL; 1163 } 1164 1165 String8 name = JStringToString8(env, jname); 1166 Vector<uint8_t> value; 1167 1168 status_t err = drm->getPropertyByteArray(name, value); 1169 1170 if (throwExceptionAsNecessary(env, err, "Failed to get property")) { 1171 return NULL; 1172 } 1173 1174 return VectorToJByteArray(env, value); 1175 } 1176 1177 static void android_media_MediaDrm_setPropertyString( 1178 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) { 1179 sp<IDrm> drm = GetDrm(env, thiz); 1180 1181 if (drm == NULL) { 1182 jniThrowException(env, "java/lang/IllegalStateException", 1183 "MediaDrm obj is null"); 1184 return; 1185 } 1186 1187 if (jname == NULL) { 1188 jniThrowException(env, "java/lang/IllegalArgumentException", 1189 "property name String is null"); 1190 return; 1191 } 1192 1193 if (jvalue == NULL) { 1194 jniThrowException(env, "java/lang/IllegalArgumentException", 1195 "property value String is null"); 1196 return; 1197 } 1198 1199 String8 name = JStringToString8(env, jname); 1200 String8 value = JStringToString8(env, jvalue); 1201 1202 status_t err = drm->setPropertyString(name, value); 1203 1204 throwExceptionAsNecessary(env, err, "Failed to set property"); 1205 } 1206 1207 static void android_media_MediaDrm_setPropertyByteArray( 1208 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) { 1209 sp<IDrm> drm = GetDrm(env, thiz); 1210 1211 if (drm == NULL) { 1212 jniThrowException(env, "java/lang/IllegalStateException", 1213 "MediaDrm obj is null"); 1214 return; 1215 } 1216 1217 if (jname == NULL) { 1218 jniThrowException(env, "java/lang/IllegalArgumentException", 1219 "property name String is null"); 1220 return; 1221 } 1222 1223 if (jvalue == NULL) { 1224 jniThrowException(env, "java/lang/IllegalArgumentException", 1225 "property value byte array is null"); 1226 return; 1227 } 1228 1229 String8 name = JStringToString8(env, jname); 1230 Vector<uint8_t> value = JByteArrayToVector(env, jvalue); 1231 1232 status_t err = drm->setPropertyByteArray(name, value); 1233 1234 throwExceptionAsNecessary(env, err, "Failed to set property"); 1235 } 1236 1237 static void android_media_MediaDrm_setCipherAlgorithmNative( 1238 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1239 jstring jalgorithm) { 1240 1241 sp<IDrm> drm = GetDrm(env, jdrm); 1242 1243 if (!CheckSession(env, drm, jsessionId)) { 1244 return; 1245 } 1246 1247 if (jalgorithm == NULL) { 1248 jniThrowException(env, "java/lang/IllegalArgumentException", 1249 "algorithm String is null"); 1250 return; 1251 } 1252 1253 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1254 String8 algorithm = JStringToString8(env, jalgorithm); 1255 1256 status_t err = drm->setCipherAlgorithm(sessionId, algorithm); 1257 1258 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm"); 1259 } 1260 1261 static void android_media_MediaDrm_setMacAlgorithmNative( 1262 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1263 jstring jalgorithm) { 1264 1265 sp<IDrm> drm = GetDrm(env, jdrm); 1266 1267 if (!CheckSession(env, drm, jsessionId)) { 1268 return; 1269 } 1270 1271 if (jalgorithm == NULL) { 1272 jniThrowException(env, "java/lang/IllegalArgumentException", 1273 "algorithm String is null"); 1274 return; 1275 } 1276 1277 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1278 String8 algorithm = JStringToString8(env, jalgorithm); 1279 1280 status_t err = drm->setMacAlgorithm(sessionId, algorithm); 1281 1282 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm"); 1283 } 1284 1285 1286 static jbyteArray android_media_MediaDrm_encryptNative( 1287 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1288 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) { 1289 1290 sp<IDrm> drm = GetDrm(env, jdrm); 1291 1292 if (!CheckSession(env, drm, jsessionId)) { 1293 return NULL; 1294 } 1295 1296 if (jkeyId == NULL || jinput == NULL || jiv == NULL) { 1297 jniThrowException(env, "java/lang/IllegalArgumentException", 1298 "required argument is null"); 1299 return NULL; 1300 } 1301 1302 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1303 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1304 Vector<uint8_t> input(JByteArrayToVector(env, jinput)); 1305 Vector<uint8_t> iv(JByteArrayToVector(env, jiv)); 1306 Vector<uint8_t> output; 1307 1308 status_t err = drm->encrypt(sessionId, keyId, input, iv, output); 1309 1310 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) { 1311 return NULL; 1312 } 1313 1314 return VectorToJByteArray(env, output); 1315 } 1316 1317 static jbyteArray android_media_MediaDrm_decryptNative( 1318 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1319 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) { 1320 1321 sp<IDrm> drm = GetDrm(env, jdrm); 1322 1323 if (!CheckSession(env, drm, jsessionId)) { 1324 return NULL; 1325 } 1326 1327 if (jkeyId == NULL || jinput == NULL || jiv == NULL) { 1328 jniThrowException(env, "java/lang/IllegalArgumentException", 1329 "required argument is null"); 1330 return NULL; 1331 } 1332 1333 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1334 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1335 Vector<uint8_t> input(JByteArrayToVector(env, jinput)); 1336 Vector<uint8_t> iv(JByteArrayToVector(env, jiv)); 1337 Vector<uint8_t> output; 1338 1339 status_t err = drm->decrypt(sessionId, keyId, input, iv, output); 1340 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) { 1341 return NULL; 1342 } 1343 1344 return VectorToJByteArray(env, output); 1345 } 1346 1347 static jbyteArray android_media_MediaDrm_signNative( 1348 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1349 jbyteArray jkeyId, jbyteArray jmessage) { 1350 1351 sp<IDrm> drm = GetDrm(env, jdrm); 1352 1353 if (!CheckSession(env, drm, jsessionId)) { 1354 return NULL; 1355 } 1356 1357 if (jkeyId == NULL || jmessage == NULL) { 1358 jniThrowException(env, "java/lang/IllegalArgumentException", 1359 "required argument is null"); 1360 return NULL; 1361 } 1362 1363 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1364 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1365 Vector<uint8_t> message(JByteArrayToVector(env, jmessage)); 1366 Vector<uint8_t> signature; 1367 1368 status_t err = drm->sign(sessionId, keyId, message, signature); 1369 1370 if (throwExceptionAsNecessary(env, err, "Failed to sign")) { 1371 return NULL; 1372 } 1373 1374 return VectorToJByteArray(env, signature); 1375 } 1376 1377 static jboolean android_media_MediaDrm_verifyNative( 1378 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1379 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) { 1380 1381 sp<IDrm> drm = GetDrm(env, jdrm); 1382 1383 if (!CheckSession(env, drm, jsessionId)) { 1384 return false; 1385 } 1386 1387 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) { 1388 jniThrowException(env, "java/lang/IllegalArgumentException", 1389 "required argument is null"); 1390 return false; 1391 } 1392 1393 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1394 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId)); 1395 Vector<uint8_t> message(JByteArrayToVector(env, jmessage)); 1396 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature)); 1397 bool match; 1398 1399 status_t err = drm->verify(sessionId, keyId, message, signature, match); 1400 1401 throwExceptionAsNecessary(env, err, "Failed to verify"); 1402 return match; 1403 } 1404 1405 1406 static jbyteArray android_media_MediaDrm_signRSANative( 1407 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId, 1408 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) { 1409 1410 sp<IDrm> drm = GetDrm(env, jdrm); 1411 1412 if (!CheckSession(env, drm, jsessionId)) { 1413 return NULL; 1414 } 1415 1416 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) { 1417 jniThrowException(env, "java/lang/IllegalArgumentException", 1418 "required argument is null"); 1419 return NULL; 1420 } 1421 1422 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 1423 String8 algorithm = JStringToString8(env, jalgorithm); 1424 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey)); 1425 Vector<uint8_t> message(JByteArrayToVector(env, jmessage)); 1426 Vector<uint8_t> signature; 1427 1428 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature); 1429 1430 if (throwExceptionAsNecessary(env, err, "Failed to sign")) { 1431 return NULL; 1432 } 1433 1434 return VectorToJByteArray(env, signature); 1435 } 1436 1437 1438 static const JNINativeMethod gMethods[] = { 1439 { "release", "()V", (void *)android_media_MediaDrm_release }, 1440 { "native_init", "()V", (void *)android_media_MediaDrm_native_init }, 1441 1442 { "native_setup", "(Ljava/lang/Object;[B)V", 1443 (void *)android_media_MediaDrm_native_setup }, 1444 1445 { "native_finalize", "()V", 1446 (void *)android_media_MediaDrm_native_finalize }, 1447 1448 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z", 1449 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative }, 1450 1451 { "openSession", "()[B", 1452 (void *)android_media_MediaDrm_openSession }, 1453 1454 { "closeSession", "([B)V", 1455 (void *)android_media_MediaDrm_closeSession }, 1456 1457 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)" 1458 "Landroid/media/MediaDrm$KeyRequest;", 1459 (void *)android_media_MediaDrm_getKeyRequest }, 1460 1461 { "provideKeyResponse", "([B[B)[B", 1462 (void *)android_media_MediaDrm_provideKeyResponse }, 1463 1464 { "removeKeys", "([B)V", 1465 (void *)android_media_MediaDrm_removeKeys }, 1466 1467 { "restoreKeys", "([B[B)V", 1468 (void *)android_media_MediaDrm_restoreKeys }, 1469 1470 { "queryKeyStatus", "([B)Ljava/util/HashMap;", 1471 (void *)android_media_MediaDrm_queryKeyStatus }, 1472 1473 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;", 1474 (void *)android_media_MediaDrm_getProvisionRequestNative }, 1475 1476 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;", 1477 (void *)android_media_MediaDrm_provideProvisionResponseNative }, 1478 1479 { "getSecureStops", "()Ljava/util/List;", 1480 (void *)android_media_MediaDrm_getSecureStops }, 1481 1482 { "getSecureStop", "([B)[B", 1483 (void *)android_media_MediaDrm_getSecureStop }, 1484 1485 { "releaseSecureStops", "([B)V", 1486 (void *)android_media_MediaDrm_releaseSecureStops }, 1487 1488 { "releaseAllSecureStops", "()V", 1489 (void *)android_media_MediaDrm_releaseAllSecureStops }, 1490 1491 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", 1492 (void *)android_media_MediaDrm_getPropertyString }, 1493 1494 { "getPropertyByteArray", "(Ljava/lang/String;)[B", 1495 (void *)android_media_MediaDrm_getPropertyByteArray }, 1496 1497 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V", 1498 (void *)android_media_MediaDrm_setPropertyString }, 1499 1500 { "setPropertyByteArray", "(Ljava/lang/String;[B)V", 1501 (void *)android_media_MediaDrm_setPropertyByteArray }, 1502 1503 { "setCipherAlgorithmNative", 1504 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V", 1505 (void *)android_media_MediaDrm_setCipherAlgorithmNative }, 1506 1507 { "setMacAlgorithmNative", 1508 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V", 1509 (void *)android_media_MediaDrm_setMacAlgorithmNative }, 1510 1511 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B", 1512 (void *)android_media_MediaDrm_encryptNative }, 1513 1514 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B", 1515 (void *)android_media_MediaDrm_decryptNative }, 1516 1517 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B", 1518 (void *)android_media_MediaDrm_signNative }, 1519 1520 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z", 1521 (void *)android_media_MediaDrm_verifyNative }, 1522 1523 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B", 1524 (void *)android_media_MediaDrm_signRSANative }, 1525 }; 1526 1527 int register_android_media_Drm(JNIEnv *env) { 1528 return AndroidRuntime::registerNativeMethods(env, 1529 "android/media/MediaDrm", gMethods, NELEM(gMethods)); 1530 } 1531