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