blob: 9938f7633b140d544dd94de3e6bec29445621f41 [file] [log] [blame]
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001/*
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