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