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