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