android_media_MediaDrm.cpp revision 8a0c80fdcc46faa8cb8c9f4dda06f4b63ec2f906
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 "jni.h" 25#include "JNIHelp.h" 26 27#include <binder/IServiceManager.h> 28#include <media/IDrm.h> 29#include <media/IMediaPlayerService.h> 30#include <media/stagefright/foundation/ADebug.h> 31 32namespace android { 33 34#define FIND_CLASS(var, className) \ 35 var = env->FindClass(className); \ 36 LOG_FATAL_IF(! var, "Unable to find class " className); 37 38#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 39 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 40 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 41 42#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ 43 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \ 44 LOG_FATAL_IF(! var, "Unable to find method " fieldName); 45 46struct RequestFields { 47 jfieldID data; 48 jfieldID defaultUrl; 49}; 50 51struct ArrayListFields { 52 jmethodID init; 53 jmethodID add; 54}; 55 56struct HashmapFields { 57 jmethodID init; 58 jmethodID get; 59 jmethodID put; 60 jmethodID entrySet; 61}; 62 63struct SetFields { 64 jmethodID iterator; 65}; 66 67struct IteratorFields { 68 jmethodID next; 69 jmethodID hasNext; 70}; 71 72struct EntryFields { 73 jmethodID getKey; 74 jmethodID getValue; 75}; 76 77struct fields_t { 78 jfieldID context; 79 RequestFields licenseRequest; 80 RequestFields provisionRequest; 81 ArrayListFields arraylist; 82 HashmapFields hashmap; 83 SetFields set; 84 IteratorFields iterator; 85 EntryFields entry; 86}; 87 88static fields_t gFields; 89 90static bool throwExceptionAsNecessary( 91 JNIEnv *env, status_t err, const char *msg = NULL) { 92 93 if (err == BAD_VALUE) { 94 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 95 return true; 96 } else if (err != OK) { 97 jniThrowException(env, "java/lang/IllegalStateException", msg); 98 return true; 99 } 100 return false; 101} 102 103static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) { 104 JDrm *jdrm = (JDrm *)env->GetIntField(thiz, gFields.context); 105 return jdrm ? jdrm->getDrm() : NULL; 106} 107 108JDrm::JDrm( 109 JNIEnv *env, jobject thiz, const uint8_t uuid[16]) { 110 mObject = env->NewWeakGlobalRef(thiz); 111 mDrm = MakeDrm(uuid); 112} 113 114JDrm::~JDrm() { 115 mDrm.clear(); 116 117 JNIEnv *env = AndroidRuntime::getJNIEnv(); 118 119 env->DeleteWeakGlobalRef(mObject); 120 mObject = NULL; 121} 122 123// static 124sp<IDrm> JDrm::MakeDrm() { 125 sp<IServiceManager> sm = defaultServiceManager(); 126 127 sp<IBinder> binder = 128 sm->getService(String16("media.player")); 129 130 sp<IMediaPlayerService> service = 131 interface_cast<IMediaPlayerService>(binder); 132 133 if (service == NULL) { 134 return NULL; 135 } 136 137 sp<IDrm> drm = service->makeDrm(); 138 139 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) { 140 return NULL; 141 } 142 143 return drm; 144} 145 146// static 147sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) { 148 sp<IDrm> drm = MakeDrm(); 149 150 if (drm == NULL) { 151 return NULL; 152 } 153 154 status_t err = drm->createPlugin(uuid); 155 156 if (err != OK) { 157 return NULL; 158 } 159 160 return drm; 161} 162 163// static 164bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) { 165 sp<IDrm> drm = MakeDrm(); 166 167 if (drm == NULL) { 168 return false; 169 } 170 171 return drm->isCryptoSchemeSupported(uuid); 172} 173 174status_t JDrm::initCheck() const { 175 return mDrm == NULL ? NO_INIT : OK; 176} 177 178// JNI conversion utilities 179static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) { 180 Vector<uint8_t> vector; 181 size_t length = env->GetArrayLength(byteArray); 182 vector.insertAt((size_t)0, length); 183 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray()); 184 return vector; 185} 186 187static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) { 188 size_t length = vector.size(); 189 jbyteArray result = env->NewByteArray(length); 190 if (result != NULL) { 191 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array()); 192 } 193 return result; 194} 195 196static String8 JStringToString8(JNIEnv *env, jstring const &jstr) { 197 jboolean isCopy; 198 String8 result; 199 200 const char *s = env->GetStringUTFChars(jstr, &isCopy); 201 if (s) { 202 result = s; 203 env->ReleaseStringUTFChars(jstr, s); 204 } 205 return result; 206} 207/* 208 import java.util.HashMap; 209 import java.util.Set; 210 import java.Map.Entry; 211 import jav.util.Iterator; 212 213 HashMap<k, v> hm; 214 Set<Entry<k, v> > s = hm.entrySet(); 215 Iterator i = s.iterator(); 216 Entry e = s.next(); 217*/ 218 219static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) { 220 jclass clazz; 221 FIND_CLASS(clazz, "java/lang/String"); 222 KeyedVector<String8, String8> keyedVector; 223 224 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet); 225 if (entrySet) { 226 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator); 227 if (iterator) { 228 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 229 while (hasNext) { 230 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next); 231 if (entry) { 232 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey); 233 if (!env->IsInstanceOf(obj, clazz)) { 234 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 235 } 236 jstring jkey = static_cast<jstring>(obj); 237 238 obj = env->CallObjectMethod(entry, gFields.entry.getValue); 239 if (!env->IsInstanceOf(obj, clazz)) { 240 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 241 } 242 jstring jvalue = static_cast<jstring>(obj); 243 244 String8 key = JStringToString8(env, jkey); 245 String8 value = JStringToString8(env, jvalue); 246 keyedVector.add(key, value); 247 248 env->DeleteLocalRef(jkey); 249 env->DeleteLocalRef(jvalue); 250 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 251 } 252 env->DeleteLocalRef(entry); 253 } 254 env->DeleteLocalRef(iterator); 255 } 256 env->DeleteLocalRef(entrySet); 257 } 258 return keyedVector; 259} 260 261static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) { 262 jclass clazz; 263 FIND_CLASS(clazz, "java/util/HashMap"); 264 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init); 265 for (size_t i = 0; i < map.size(); ++i) { 266 jstring jkey = env->NewStringUTF(map.keyAt(i).string()); 267 jstring jvalue = env->NewStringUTF(map.valueAt(i).string()); 268 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue); 269 env->DeleteLocalRef(jkey); 270 env->DeleteLocalRef(jvalue); 271 } 272 return hashMap; 273} 274 275static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env, 276 List<Vector<uint8_t> > list) { 277 jclass clazz; 278 FIND_CLASS(clazz, "java/util/ArrayList"); 279 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init); 280 List<Vector<uint8_t> >::iterator iter = list.begin(); 281 while (iter != list.end()) { 282 jbyteArray byteArray = VectorToJByteArray(env, *iter); 283 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray); 284 env->DeleteLocalRef(byteArray); 285 iter++; 286 } 287 288 return arrayList; 289} 290 291} // namespace android 292 293using namespace android; 294 295static sp<JDrm> setDrm( 296 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) { 297 sp<JDrm> old = (JDrm *)env->GetIntField(thiz, gFields.context); 298 if (drm != NULL) { 299 drm->incStrong(thiz); 300 } 301 if (old != NULL) { 302 old->decStrong(thiz); 303 } 304 env->SetIntField(thiz, gFields.context, (int)drm.get()); 305 306 return old; 307} 308 309static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId) 310{ 311 if (drm == NULL) { 312 jniThrowException(env, "java/lang/IllegalStateException", NULL); 313 return false; 314 } 315 316 if (jsessionId == NULL) { 317 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 318 return false; 319 } 320 return true; 321} 322 323static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) { 324 setDrm(env, thiz, NULL); 325} 326 327static void android_media_MediaDrm_native_init(JNIEnv *env) { 328 jclass clazz; 329 FIND_CLASS(clazz, "android/media/MediaDrm"); 330 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "I"); 331 332 FIND_CLASS(clazz, "android/media/MediaDrm$LicenseRequest"); 333 GET_FIELD_ID(gFields.licenseRequest.data, clazz, "data", "[B"); 334 GET_FIELD_ID(gFields.licenseRequest.defaultUrl, clazz, "defaultUrl", "Ljava/lang/String;"); 335 336 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest"); 337 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "data", "[B"); 338 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "defaultUrl", "Ljava/lang/String;"); 339 340 FIND_CLASS(clazz, "java/util/ArrayList"); 341 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V"); 342 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z"); 343 344 FIND_CLASS(clazz, "java/util/HashMap"); 345 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V"); 346 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); 347 GET_METHOD_ID(gFields.hashmap.put, clazz, "put", 348 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 349 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;"); 350 351 FIND_CLASS(clazz, "java/util/Set"); 352 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;"); 353 354 FIND_CLASS(clazz, "java/util/Iterator"); 355 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;"); 356 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z"); 357 358 FIND_CLASS(clazz, "java/util/Map$Entry"); 359 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;"); 360 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;"); 361} 362 363static void android_media_MediaDrm_native_setup( 364 JNIEnv *env, jobject thiz, 365 jobject weak_this, jbyteArray uuidObj) { 366 367 if (uuidObj == NULL) { 368 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 369 return; 370 } 371 372 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); 373 374 if (uuid.size() != 16) { 375 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 376 return; 377 } 378 379 sp<JDrm> drm = new JDrm(env, thiz, uuid.array()); 380 381 status_t err = drm->initCheck(); 382 383 if (err != OK) { 384 jniThrowException( 385 env, 386 "android/media/MediaDrmException", 387 "Failed to instantiate drm object."); 388 return; 389 } 390 391 setDrm(env, thiz, drm); 392} 393 394static void android_media_MediaDrm_native_finalize( 395 JNIEnv *env, jobject thiz) { 396 android_media_MediaDrm_release(env, thiz); 397} 398 399static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative( 400 JNIEnv *env, jobject thiz, jbyteArray uuidObj) { 401 402 if (uuidObj == NULL) { 403 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 404 return false; 405 } 406 407 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); 408 409 if (uuid.size() != 16) { 410 jniThrowException( 411 env, 412 "java/lang/IllegalArgumentException", 413 NULL); 414 return false; 415 } 416 417 return JDrm::IsCryptoSchemeSupported(uuid.array()); 418} 419 420static jbyteArray android_media_MediaDrm_openSession( 421 JNIEnv *env, jobject thiz) { 422 sp<IDrm> drm = GetDrm(env, thiz); 423 424 if (drm == NULL) { 425 jniThrowException(env, "java/lang/IllegalStateException", NULL); 426 return NULL; 427 } 428 429 Vector<uint8_t> sessionId; 430 status_t err = drm->openSession(sessionId); 431 432 if (throwExceptionAsNecessary(env, err, "Failed to open session")) { 433 return NULL; 434 } 435 436 return VectorToJByteArray(env, sessionId); 437} 438 439static void android_media_MediaDrm_closeSession( 440 JNIEnv *env, jobject thiz, jbyteArray jsessionId) { 441 sp<IDrm> drm = GetDrm(env, thiz); 442 443 if (!CheckSession(env, drm, jsessionId)) { 444 return; 445 } 446 447 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 448 449 status_t err = drm->closeSession(sessionId); 450 451 throwExceptionAsNecessary(env, err, "Failed to close session"); 452} 453 454static jobject android_media_MediaDrm_getLicenseRequest( 455 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData, 456 jstring jmimeType, jint jlicenseType, jobject joptParams) { 457 sp<IDrm> drm = GetDrm(env, thiz); 458 459 if (!CheckSession(env, drm, jsessionId)) { 460 return NULL; 461 } 462 463 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 464 465 Vector<uint8_t> initData; 466 if (jinitData != NULL) { 467 initData = JByteArrayToVector(env, jinitData); 468 } 469 470 String8 mimeType; 471 if (jmimeType != NULL) { 472 mimeType = JStringToString8(env, jmimeType); 473 } 474 475 DrmPlugin::LicenseType licenseType = (DrmPlugin::LicenseType)jlicenseType; 476 477 KeyedVector<String8, String8> optParams; 478 if (joptParams != NULL) { 479 optParams = HashMapToKeyedVector(env, joptParams); 480 } 481 482 Vector<uint8_t> request; 483 String8 defaultUrl; 484 485 status_t err = drm->getLicenseRequest(sessionId, initData, mimeType, 486 licenseType, optParams, request, defaultUrl); 487 488 if (throwExceptionAsNecessary(env, err, "Failed to get license request")) { 489 return NULL; 490 } 491 492 // Fill out return obj 493 jclass clazz; 494 FIND_CLASS(clazz, "android/media/MediaDrm$LicenseRequest"); 495 496 jobject licenseObj = NULL; 497 498 if (clazz) { 499 licenseObj = env->AllocObject(clazz); 500 jbyteArray jrequest = VectorToJByteArray(env, request); 501 env->SetObjectField(licenseObj, gFields.licenseRequest.data, jrequest); 502 503 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string()); 504 env->SetObjectField(licenseObj, gFields.licenseRequest.defaultUrl, jdefaultUrl); 505 } 506 507 return licenseObj; 508} 509 510static void android_media_MediaDrm_provideLicenseResponse( 511 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) { 512 sp<IDrm> drm = GetDrm(env, thiz); 513 514 if (!CheckSession(env, drm, jsessionId)) { 515 return; 516 } 517 518 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 519 520 if (jresponse == NULL) { 521 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 522 return; 523 } 524 Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); 525 526 status_t err = drm->provideLicenseResponse(sessionId, response); 527 528 throwExceptionAsNecessary(env, err, "Failed to handle license response"); 529} 530 531static void android_media_MediaDrm_removeLicense( 532 JNIEnv *env, jobject thiz, jbyteArray jsessionId) { 533 sp<IDrm> drm = GetDrm(env, thiz); 534 535 if (!CheckSession(env, drm, jsessionId)) { 536 return; 537 } 538 539 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 540 541 status_t err = drm->removeLicense(sessionId); 542 543 throwExceptionAsNecessary(env, err, "Failed to remove license"); 544} 545 546static jobject android_media_MediaDrm_queryLicenseStatus( 547 JNIEnv *env, jobject thiz, jbyteArray jsessionId) { 548 sp<IDrm> drm = GetDrm(env, thiz); 549 550 if (!CheckSession(env, drm, jsessionId)) { 551 return NULL; 552 } 553 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); 554 555 KeyedVector<String8, String8> infoMap; 556 557 status_t err = drm->queryLicenseStatus(sessionId, infoMap); 558 559 if (throwExceptionAsNecessary(env, err, "Failed to query license")) { 560 return NULL; 561 } 562 563 return KeyedVectorToHashMap(env, infoMap); 564} 565 566static jobject android_media_MediaDrm_getProvisionRequest( 567 JNIEnv *env, jobject thiz) { 568 sp<IDrm> drm = GetDrm(env, thiz); 569 570 if (drm == NULL) { 571 jniThrowException(env, "java/lang/IllegalStateException", NULL); 572 return NULL; 573 } 574 575 Vector<uint8_t> request; 576 String8 defaultUrl; 577 578 status_t err = drm->getProvisionRequest(request, defaultUrl); 579 580 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) { 581 return NULL; 582 } 583 584 // Fill out return obj 585 jclass clazz; 586 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest"); 587 588 jobject provisionObj = NULL; 589 590 if (clazz) { 591 provisionObj = env->AllocObject(clazz); 592 jbyteArray jrequest = VectorToJByteArray(env, request); 593 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest); 594 595 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string()); 596 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl); 597 } 598 599 return provisionObj; 600} 601 602static void android_media_MediaDrm_provideProvisionResponse( 603 JNIEnv *env, jobject thiz, jbyteArray jresponse) { 604 sp<IDrm> drm = GetDrm(env, thiz); 605 606 if (drm == NULL) { 607 jniThrowException(env, "java/lang/IllegalStateException", NULL); 608 return; 609 } 610 611 if (jresponse == NULL) { 612 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 613 return; 614 } 615 616 Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); 617 618 status_t err = drm->provideProvisionResponse(response); 619 620 throwExceptionAsNecessary(env, err, "Failed to handle provision response"); 621} 622 623static jobject android_media_MediaDrm_getSecureStops( 624 JNIEnv *env, jobject thiz) { 625 sp<IDrm> drm = GetDrm(env, thiz); 626 627 if (drm == NULL) { 628 jniThrowException(env, "java/lang/IllegalStateException", NULL); 629 return NULL; 630 } 631 632 List<Vector<uint8_t> > secureStops; 633 634 status_t err = drm->getSecureStops(secureStops); 635 636 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) { 637 return NULL; 638 } 639 640 return ListOfVectorsToArrayListOfByteArray(env, secureStops); 641} 642 643static void android_media_MediaDrm_releaseSecureStops( 644 JNIEnv *env, jobject thiz, jbyteArray jssRelease) { 645 sp<IDrm> drm = GetDrm(env, thiz); 646 647 if (drm == NULL) { 648 jniThrowException(env, "java/lang/IllegalStateException", NULL); 649 return; 650 } 651 652 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease)); 653 654 status_t err = drm->releaseSecureStops(ssRelease); 655 656 throwExceptionAsNecessary(env, err, "Failed to release secure stops"); 657} 658 659static jstring android_media_MediaDrm_getPropertyString( 660 JNIEnv *env, jobject thiz, jstring jname) { 661 sp<IDrm> drm = GetDrm(env, thiz); 662 663 if (drm == NULL) { 664 jniThrowException(env, "java/lang/IllegalStateException", NULL); 665 return NULL; 666 } 667 668 if (jname == NULL) { 669 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 670 return NULL; 671 } 672 673 String8 name = JStringToString8(env, jname); 674 String8 value; 675 676 status_t err = drm->getPropertyString(name, value); 677 678 if (throwExceptionAsNecessary(env, err, "Failed to get property")) { 679 return NULL; 680 } 681 682 return env->NewStringUTF(value.string()); 683} 684 685static jbyteArray android_media_MediaDrm_getPropertyByteArray( 686 JNIEnv *env, jobject thiz, jstring jname) { 687 sp<IDrm> drm = GetDrm(env, thiz); 688 689 if (drm == NULL) { 690 jniThrowException(env, "java/lang/IllegalStateException", NULL); 691 return NULL; 692 } 693 694 if (jname == NULL) { 695 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 696 return NULL; 697 } 698 699 String8 name = JStringToString8(env, jname); 700 Vector<uint8_t> value; 701 702 status_t err = drm->getPropertyByteArray(name, value); 703 704 if (throwExceptionAsNecessary(env, err, "Failed to get property")) { 705 return NULL; 706 } 707 708 return VectorToJByteArray(env, value); 709} 710 711static void android_media_MediaDrm_setPropertyString( 712 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) { 713 sp<IDrm> drm = GetDrm(env, thiz); 714 715 if (drm == NULL) { 716 jniThrowException(env, "java/lang/IllegalStateException", NULL); 717 return; 718 } 719 720 if (jname == NULL || jvalue == NULL) { 721 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 722 return; 723 } 724 725 String8 name = JStringToString8(env, jname); 726 String8 value = JStringToString8(env, jvalue); 727 728 status_t err = drm->setPropertyString(name, value); 729 730 throwExceptionAsNecessary(env, err, "Failed to set property"); 731} 732 733static void android_media_MediaDrm_setPropertyByteArray( 734 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) { 735 sp<IDrm> drm = GetDrm(env, thiz); 736 737 if (drm == NULL) { 738 jniThrowException(env, "java/lang/IllegalStateException", NULL); 739 return; 740 } 741 742 if (jname == NULL || jvalue == NULL) { 743 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 744 return; 745 } 746 747 String8 name = JStringToString8(env, jname); 748 Vector<uint8_t> value = JByteArrayToVector(env, jvalue); 749 750 status_t err = drm->setPropertyByteArray(name, value); 751 752 throwExceptionAsNecessary(env, err, "Failed to set property"); 753} 754 755 756static JNINativeMethod gMethods[] = { 757 { "release", "()V", (void *)android_media_MediaDrm_release }, 758 { "native_init", "()V", (void *)android_media_MediaDrm_native_init }, 759 760 { "native_setup", "(Ljava/lang/Object;[B)V", 761 (void *)android_media_MediaDrm_native_setup }, 762 763 { "native_finalize", "()V", 764 (void *)android_media_MediaDrm_native_finalize }, 765 766 { "isCryptoSchemeSupportedNative", "([B)Z", 767 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative }, 768 769 { "openSession", "()[B", 770 (void *)android_media_MediaDrm_openSession }, 771 772 { "closeSession", "([B)V", 773 (void *)android_media_MediaDrm_closeSession }, 774 775 { "getLicenseRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)" 776 "Landroid/media/MediaDrm$LicenseRequest;", 777 (void *)android_media_MediaDrm_getLicenseRequest }, 778 779 { "provideLicenseResponse", "([B[B)V", 780 (void *)android_media_MediaDrm_provideLicenseResponse }, 781 782 { "removeLicense", "([B)V", 783 (void *)android_media_MediaDrm_removeLicense }, 784 785 { "queryLicenseStatus", "([B)Ljava/util/HashMap;", 786 (void *)android_media_MediaDrm_queryLicenseStatus }, 787 788 { "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;", 789 (void *)android_media_MediaDrm_getProvisionRequest }, 790 791 { "provideProvisionResponse", "([B)V", 792 (void *)android_media_MediaDrm_provideProvisionResponse }, 793 794 { "getSecureStops", "()Ljava/util/List;", 795 (void *)android_media_MediaDrm_getSecureStops }, 796 797 { "releaseSecureStops", "([B)V", 798 (void *)android_media_MediaDrm_releaseSecureStops }, 799 800 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", 801 (void *)android_media_MediaDrm_getPropertyString }, 802 803 { "getPropertyByteArray", "(Ljava/lang/String;)[B", 804 (void *)android_media_MediaDrm_getPropertyByteArray }, 805 806 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V", 807 (void *)android_media_MediaDrm_setPropertyString }, 808 809 { "setPropertyByteArray", "(Ljava/lang/String;[B)V", 810 (void *)android_media_MediaDrm_setPropertyByteArray }, 811}; 812 813int register_android_media_Drm(JNIEnv *env) { 814 return AndroidRuntime::registerNativeMethods(env, 815 "android/media/MediaDrm", gMethods, NELEM(gMethods)); 816} 817 818