blob: d1b499e8d9d0bb99b528a534970e1409ca92482d [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"
Jeff Tinker54cfbd62013-04-02 13:14:59 -070024#include "android_os_Parcel.h"
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080025#include "jni.h"
26#include "JNIHelp.h"
27
28#include <binder/IServiceManager.h>
Jeff Tinker54cfbd62013-04-02 13:14:59 -070029#include <binder/Parcel.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080030#include <media/IDrm.h>
31#include <media/IMediaPlayerService.h>
32#include <media/stagefright/foundation/ADebug.h>
Jeff Tinkerf7568b52013-04-17 14:24:40 -070033#include <media/stagefright/MediaErrors.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080034
35namespace 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
Jeff Tinker54cfbd62013-04-02 13:14:59 -070049#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
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080058struct RequestFields {
59 jfieldID data;
60 jfieldID defaultUrl;
61};
62
63struct ArrayListFields {
64 jmethodID init;
65 jmethodID add;
66};
67
68struct HashmapFields {
69 jmethodID init;
70 jmethodID get;
71 jmethodID put;
72 jmethodID entrySet;
73};
74
75struct SetFields {
76 jmethodID iterator;
77};
78
79struct IteratorFields {
80 jmethodID next;
81 jmethodID hasNext;
82};
83
84struct EntryFields {
85 jmethodID getKey;
86 jmethodID getValue;
87};
88
Jeff Tinker54cfbd62013-04-02 13:14:59 -070089struct EventTypes {
90 int kEventProvisionRequired;
91 int kEventKeyRequired;
92 int kEventKeyExpired;
93 int kEventVendorDefined;
94} gEventTypes;
95
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080096struct fields_t {
97 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -070098 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -070099 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800100 RequestFields provisionRequest;
101 ArrayListFields arraylist;
102 HashmapFields hashmap;
103 SetFields set;
104 IteratorFields iterator;
105 EntryFields entry;
106};
107
108static fields_t gFields;
109
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700110// ----------------------------------------------------------------------------
111// ref-counted object for callbacks
112class JNIDrmListener: public DrmListener
113{
114public:
115 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
116 ~JNIDrmListener();
117 virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
118private:
119 JNIDrmListener();
120 jclass mClass; // Reference to MediaDrm class
121 jobject mObject; // Weak ref to MediaDrm Java object to call on
122};
123
124JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
125{
126 // Hold onto the MediaDrm class for use in calling the static method
127 // that posts events to the application thread.
128 jclass clazz = env->GetObjectClass(thiz);
129 if (clazz == NULL) {
130 ALOGE("Can't find android/media/MediaDrm");
131 jniThrowException(env, "java/lang/Exception", NULL);
132 return;
133 }
134 mClass = (jclass)env->NewGlobalRef(clazz);
135
136 // We use a weak reference so the MediaDrm object can be garbage collected.
137 // The reference is only used as a proxy for callbacks.
138 mObject = env->NewGlobalRef(weak_thiz);
139}
140
141JNIDrmListener::~JNIDrmListener()
142{
143 // remove global references
144 JNIEnv *env = AndroidRuntime::getJNIEnv();
145 env->DeleteGlobalRef(mObject);
146 env->DeleteGlobalRef(mClass);
147}
148
149void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
150 const Parcel *obj)
151{
152 jint jeventType;
153
154 // translate DrmPlugin event types into their java equivalents
155 switch(eventType) {
156 case DrmPlugin::kDrmPluginEventProvisionRequired:
157 jeventType = gEventTypes.kEventProvisionRequired;
158 break;
159 case DrmPlugin::kDrmPluginEventKeyNeeded:
160 jeventType = gEventTypes.kEventKeyRequired;
161 break;
162 case DrmPlugin::kDrmPluginEventKeyExpired:
163 jeventType = gEventTypes.kEventKeyExpired;
164 break;
165 case DrmPlugin::kDrmPluginEventVendorDefined:
166 jeventType = gEventTypes.kEventVendorDefined;
167 break;
168 default:
169 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
170 return;
171 }
172
173 JNIEnv *env = AndroidRuntime::getJNIEnv();
174 if (obj && obj->dataSize() > 0) {
175 jobject jParcel = createJavaParcelObject(env);
176 if (jParcel != NULL) {
177 Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
178 nativeParcel->setData(obj->data(), obj->dataSize());
179 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
180 jeventType, extra, jParcel);
181 }
182 }
183
184 if (env->ExceptionCheck()) {
185 ALOGW("An exception occurred while notifying an event.");
186 LOGW_EX(env);
187 env->ExceptionClear();
188 }
189}
190
191
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800192static bool throwExceptionAsNecessary(
193 JNIEnv *env, status_t err, const char *msg = NULL) {
194
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700195 const char *drmMessage = NULL;
196
197 switch(err) {
198 case ERROR_DRM_UNKNOWN:
199 drmMessage = "General DRM error";
200 break;
201 case ERROR_DRM_NO_LICENSE:
202 drmMessage = "No license";
203 break;
204 case ERROR_DRM_LICENSE_EXPIRED:
205 drmMessage = "License expired";
206 break;
207 case ERROR_DRM_SESSION_NOT_OPENED:
208 drmMessage = "Session not opened";
209 break;
210 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
211 drmMessage = "Not initialized";
212 break;
213 case ERROR_DRM_DECRYPT:
214 drmMessage = "Decrypt error";
215 break;
216 case ERROR_DRM_CANNOT_HANDLE:
217 drmMessage = "Unsupported scheme or data format";
218 break;
219 case ERROR_DRM_TAMPER_DETECTED:
220 drmMessage = "Invalid state";
221 break;
222 case ERROR_DRM_NOT_PROVISIONED:
223 drmMessage = "Not provisioned";
224 break;
225 case ERROR_DRM_DEVICE_REVOKED:
226 drmMessage = "Device revoked";
227 break;
228 default:
229 break;
230 }
231
232 String8 vendorMessage;
233 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
234 vendorMessage.format("DRM vendor-defined error: %d", err);
235 drmMessage = vendorMessage.string();
236 }
237
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800238 if (err == BAD_VALUE) {
239 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
240 return true;
241 } else if (err != OK) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700242 String8 errbuf;
243 if (drmMessage != NULL) {
244 if (msg == NULL) {
245 msg = drmMessage;
246 } else {
247 errbuf.format("%s: %s", msg, drmMessage);
248 msg = errbuf.string();
249 }
250 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800251 jniThrowException(env, "java/lang/IllegalStateException", msg);
252 return true;
253 }
254 return false;
255}
256
257static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
258 JDrm *jdrm = (JDrm *)env->GetIntField(thiz, gFields.context);
259 return jdrm ? jdrm->getDrm() : NULL;
260}
261
262JDrm::JDrm(
263 JNIEnv *env, jobject thiz, const uint8_t uuid[16]) {
264 mObject = env->NewWeakGlobalRef(thiz);
265 mDrm = MakeDrm(uuid);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700266 if (mDrm != NULL) {
267 mDrm->setListener(this);
268 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800269}
270
271JDrm::~JDrm() {
272 mDrm.clear();
273
274 JNIEnv *env = AndroidRuntime::getJNIEnv();
275
276 env->DeleteWeakGlobalRef(mObject);
277 mObject = NULL;
278}
279
280// static
281sp<IDrm> JDrm::MakeDrm() {
282 sp<IServiceManager> sm = defaultServiceManager();
283
284 sp<IBinder> binder =
285 sm->getService(String16("media.player"));
286
287 sp<IMediaPlayerService> service =
288 interface_cast<IMediaPlayerService>(binder);
289
290 if (service == NULL) {
291 return NULL;
292 }
293
294 sp<IDrm> drm = service->makeDrm();
295
296 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
297 return NULL;
298 }
299
300 return drm;
301}
302
303// static
304sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) {
305 sp<IDrm> drm = MakeDrm();
306
307 if (drm == NULL) {
308 return NULL;
309 }
310
311 status_t err = drm->createPlugin(uuid);
312
313 if (err != OK) {
314 return NULL;
315 }
316
317 return drm;
318}
319
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700320status_t JDrm::setListener(const sp<DrmListener>& listener) {
321 Mutex::Autolock lock(mLock);
322 mListener = listener;
323 return OK;
324}
325
326void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
327 sp<DrmListener> listener;
328 mLock.lock();
329 listener = mListener;
330 mLock.unlock();
331
332 if (listener != NULL) {
333 Mutex::Autolock lock(mNotifyLock);
334 listener->notify(eventType, extra, obj);
335 }
336}
337
338
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800339// static
340bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) {
341 sp<IDrm> drm = MakeDrm();
342
343 if (drm == NULL) {
344 return false;
345 }
346
347 return drm->isCryptoSchemeSupported(uuid);
348}
349
350status_t JDrm::initCheck() const {
351 return mDrm == NULL ? NO_INIT : OK;
352}
353
354// JNI conversion utilities
355static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
356 Vector<uint8_t> vector;
357 size_t length = env->GetArrayLength(byteArray);
358 vector.insertAt((size_t)0, length);
359 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
360 return vector;
361}
362
363static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
364 size_t length = vector.size();
365 jbyteArray result = env->NewByteArray(length);
366 if (result != NULL) {
367 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
368 }
369 return result;
370}
371
372static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800373 String8 result;
374
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700375 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800376 if (s) {
377 result = s;
378 env->ReleaseStringUTFChars(jstr, s);
379 }
380 return result;
381}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700382
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800383/*
384 import java.util.HashMap;
385 import java.util.Set;
386 import java.Map.Entry;
387 import jav.util.Iterator;
388
389 HashMap<k, v> hm;
390 Set<Entry<k, v> > s = hm.entrySet();
391 Iterator i = s.iterator();
392 Entry e = s.next();
393*/
394
395static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
396 jclass clazz;
397 FIND_CLASS(clazz, "java/lang/String");
398 KeyedVector<String8, String8> keyedVector;
399
400 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
401 if (entrySet) {
402 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
403 if (iterator) {
404 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
405 while (hasNext) {
406 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
407 if (entry) {
408 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
409 if (!env->IsInstanceOf(obj, clazz)) {
410 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
411 }
412 jstring jkey = static_cast<jstring>(obj);
413
414 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
415 if (!env->IsInstanceOf(obj, clazz)) {
416 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
417 }
418 jstring jvalue = static_cast<jstring>(obj);
419
420 String8 key = JStringToString8(env, jkey);
421 String8 value = JStringToString8(env, jvalue);
422 keyedVector.add(key, value);
423
424 env->DeleteLocalRef(jkey);
425 env->DeleteLocalRef(jvalue);
426 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
427 }
428 env->DeleteLocalRef(entry);
429 }
430 env->DeleteLocalRef(iterator);
431 }
432 env->DeleteLocalRef(entrySet);
433 }
434 return keyedVector;
435}
436
437static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
438 jclass clazz;
439 FIND_CLASS(clazz, "java/util/HashMap");
440 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
441 for (size_t i = 0; i < map.size(); ++i) {
442 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
443 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
444 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
445 env->DeleteLocalRef(jkey);
446 env->DeleteLocalRef(jvalue);
447 }
448 return hashMap;
449}
450
451static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
452 List<Vector<uint8_t> > list) {
453 jclass clazz;
454 FIND_CLASS(clazz, "java/util/ArrayList");
455 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
456 List<Vector<uint8_t> >::iterator iter = list.begin();
457 while (iter != list.end()) {
458 jbyteArray byteArray = VectorToJByteArray(env, *iter);
459 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
460 env->DeleteLocalRef(byteArray);
461 iter++;
462 }
463
464 return arrayList;
465}
466
467} // namespace android
468
469using namespace android;
470
471static sp<JDrm> setDrm(
472 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
473 sp<JDrm> old = (JDrm *)env->GetIntField(thiz, gFields.context);
474 if (drm != NULL) {
475 drm->incStrong(thiz);
476 }
477 if (old != NULL) {
478 old->decStrong(thiz);
479 }
480 env->SetIntField(thiz, gFields.context, (int)drm.get());
481
482 return old;
483}
484
485static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
486{
487 if (drm == NULL) {
488 jniThrowException(env, "java/lang/IllegalStateException", NULL);
489 return false;
490 }
491
492 if (jsessionId == NULL) {
493 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
494 return false;
495 }
496 return true;
497}
498
499static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700500 sp<JDrm> drm = setDrm(env, thiz, NULL);
501 if (drm != NULL) {
502 drm->setListener(NULL);
503 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800504}
505
506static void android_media_MediaDrm_native_init(JNIEnv *env) {
507 jclass clazz;
508 FIND_CLASS(clazz, "android/media/MediaDrm");
509 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700510 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
511 "(Ljava/lang/Object;IILjava/lang/Object;)V");
512
513 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700514 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700515 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700516 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700517 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700518 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700519 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700520 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700521 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800522
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700523 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700524 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
525 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800526
527 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700528 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
529 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800530
531 FIND_CLASS(clazz, "java/util/ArrayList");
532 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
533 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
534
535 FIND_CLASS(clazz, "java/util/HashMap");
536 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
537 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
538 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
539 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
540 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
541
542 FIND_CLASS(clazz, "java/util/Set");
543 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
544
545 FIND_CLASS(clazz, "java/util/Iterator");
546 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
547 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
548
549 FIND_CLASS(clazz, "java/util/Map$Entry");
550 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
551 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
552}
553
554static void android_media_MediaDrm_native_setup(
555 JNIEnv *env, jobject thiz,
556 jobject weak_this, jbyteArray uuidObj) {
557
558 if (uuidObj == NULL) {
559 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
560 return;
561 }
562
563 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
564
565 if (uuid.size() != 16) {
566 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
567 return;
568 }
569
570 sp<JDrm> drm = new JDrm(env, thiz, uuid.array());
571
572 status_t err = drm->initCheck();
573
574 if (err != OK) {
575 jniThrowException(
576 env,
577 "android/media/MediaDrmException",
578 "Failed to instantiate drm object.");
579 return;
580 }
581
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700582 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
583 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800584 setDrm(env, thiz, drm);
585}
586
587static void android_media_MediaDrm_native_finalize(
588 JNIEnv *env, jobject thiz) {
589 android_media_MediaDrm_release(env, thiz);
590}
591
592static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
593 JNIEnv *env, jobject thiz, jbyteArray uuidObj) {
594
595 if (uuidObj == NULL) {
596 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
597 return false;
598 }
599
600 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
601
602 if (uuid.size() != 16) {
603 jniThrowException(
604 env,
605 "java/lang/IllegalArgumentException",
606 NULL);
607 return false;
608 }
609
610 return JDrm::IsCryptoSchemeSupported(uuid.array());
611}
612
613static jbyteArray android_media_MediaDrm_openSession(
614 JNIEnv *env, jobject thiz) {
615 sp<IDrm> drm = GetDrm(env, thiz);
616
617 if (drm == NULL) {
618 jniThrowException(env, "java/lang/IllegalStateException", NULL);
619 return NULL;
620 }
621
622 Vector<uint8_t> sessionId;
623 status_t err = drm->openSession(sessionId);
624
625 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
626 return NULL;
627 }
628
629 return VectorToJByteArray(env, sessionId);
630}
631
632static void android_media_MediaDrm_closeSession(
633 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
634 sp<IDrm> drm = GetDrm(env, thiz);
635
636 if (!CheckSession(env, drm, jsessionId)) {
637 return;
638 }
639
640 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
641
642 status_t err = drm->closeSession(sessionId);
643
644 throwExceptionAsNecessary(env, err, "Failed to close session");
645}
646
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700647static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800648 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700649 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800650 sp<IDrm> drm = GetDrm(env, thiz);
651
652 if (!CheckSession(env, drm, jsessionId)) {
653 return NULL;
654 }
655
656 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
657
658 Vector<uint8_t> initData;
659 if (jinitData != NULL) {
660 initData = JByteArrayToVector(env, jinitData);
661 }
662
663 String8 mimeType;
664 if (jmimeType != NULL) {
665 mimeType = JStringToString8(env, jmimeType);
666 }
667
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700668 DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)jkeyType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800669
670 KeyedVector<String8, String8> optParams;
671 if (joptParams != NULL) {
672 optParams = HashMapToKeyedVector(env, joptParams);
673 }
674
675 Vector<uint8_t> request;
676 String8 defaultUrl;
677
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700678 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
679 keyType, optParams, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800680
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700681 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800682 return NULL;
683 }
684
685 // Fill out return obj
686 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700687 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800688
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700689 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800690
691 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700692 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800693 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700694 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800695
696 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700697 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800698 }
699
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700700 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800701}
702
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700703static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800704 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
705 sp<IDrm> drm = GetDrm(env, thiz);
706
707 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700708 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800709 }
710
711 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
712
713 if (jresponse == NULL) {
714 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700715 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800716 }
717 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700718 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800719
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700720 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800721
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700722 throwExceptionAsNecessary(env, err, "Failed to handle key response");
723 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800724}
725
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700726static void android_media_MediaDrm_removeKeys(
727 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
728 sp<IDrm> drm = GetDrm(env, thiz);
729
730 if (jkeysetId == NULL) {
731 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
732 return;
733 }
734
735 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
736
737 status_t err = drm->removeKeys(keySetId);
738
739 throwExceptionAsNecessary(env, err, "Failed to remove keys");
740}
741
742static void android_media_MediaDrm_restoreKeys(
743 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
744 jbyteArray jkeysetId) {
745
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800746 sp<IDrm> drm = GetDrm(env, thiz);
747
748 if (!CheckSession(env, drm, jsessionId)) {
749 return;
750 }
751
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700752 if (jkeysetId == NULL) {
753 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
754 return;
755 }
756
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800757 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700758 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800759
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700760 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800761
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700762 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800763}
764
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700765static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800766 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
767 sp<IDrm> drm = GetDrm(env, thiz);
768
769 if (!CheckSession(env, drm, jsessionId)) {
770 return NULL;
771 }
772 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
773
774 KeyedVector<String8, String8> infoMap;
775
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700776 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800777
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700778 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800779 return NULL;
780 }
781
782 return KeyedVectorToHashMap(env, infoMap);
783}
784
785static jobject android_media_MediaDrm_getProvisionRequest(
786 JNIEnv *env, jobject thiz) {
787 sp<IDrm> drm = GetDrm(env, thiz);
788
789 if (drm == NULL) {
790 jniThrowException(env, "java/lang/IllegalStateException", NULL);
791 return NULL;
792 }
793
794 Vector<uint8_t> request;
795 String8 defaultUrl;
796
797 status_t err = drm->getProvisionRequest(request, defaultUrl);
798
799 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
800 return NULL;
801 }
802
803 // Fill out return obj
804 jclass clazz;
805 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
806
807 jobject provisionObj = NULL;
808
809 if (clazz) {
810 provisionObj = env->AllocObject(clazz);
811 jbyteArray jrequest = VectorToJByteArray(env, request);
812 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
813
814 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
815 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
816 }
817
818 return provisionObj;
819}
820
821static void android_media_MediaDrm_provideProvisionResponse(
822 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
823 sp<IDrm> drm = GetDrm(env, thiz);
824
825 if (drm == NULL) {
826 jniThrowException(env, "java/lang/IllegalStateException", NULL);
827 return;
828 }
829
830 if (jresponse == NULL) {
831 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
832 return;
833 }
834
835 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
836
837 status_t err = drm->provideProvisionResponse(response);
838
839 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
840}
841
842static jobject android_media_MediaDrm_getSecureStops(
843 JNIEnv *env, jobject thiz) {
844 sp<IDrm> drm = GetDrm(env, thiz);
845
846 if (drm == NULL) {
847 jniThrowException(env, "java/lang/IllegalStateException", NULL);
848 return NULL;
849 }
850
851 List<Vector<uint8_t> > secureStops;
852
853 status_t err = drm->getSecureStops(secureStops);
854
855 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
856 return NULL;
857 }
858
859 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
860}
861
862static void android_media_MediaDrm_releaseSecureStops(
863 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
864 sp<IDrm> drm = GetDrm(env, thiz);
865
866 if (drm == NULL) {
867 jniThrowException(env, "java/lang/IllegalStateException", NULL);
868 return;
869 }
870
871 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
872
873 status_t err = drm->releaseSecureStops(ssRelease);
874
875 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
876}
877
878static jstring android_media_MediaDrm_getPropertyString(
879 JNIEnv *env, jobject thiz, jstring jname) {
880 sp<IDrm> drm = GetDrm(env, thiz);
881
882 if (drm == NULL) {
883 jniThrowException(env, "java/lang/IllegalStateException", NULL);
884 return NULL;
885 }
886
887 if (jname == NULL) {
888 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
889 return NULL;
890 }
891
892 String8 name = JStringToString8(env, jname);
893 String8 value;
894
895 status_t err = drm->getPropertyString(name, value);
896
897 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
898 return NULL;
899 }
900
901 return env->NewStringUTF(value.string());
902}
903
904static jbyteArray android_media_MediaDrm_getPropertyByteArray(
905 JNIEnv *env, jobject thiz, jstring jname) {
906 sp<IDrm> drm = GetDrm(env, thiz);
907
908 if (drm == NULL) {
909 jniThrowException(env, "java/lang/IllegalStateException", NULL);
910 return NULL;
911 }
912
913 if (jname == NULL) {
914 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
915 return NULL;
916 }
917
918 String8 name = JStringToString8(env, jname);
919 Vector<uint8_t> value;
920
921 status_t err = drm->getPropertyByteArray(name, value);
922
923 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
924 return NULL;
925 }
926
927 return VectorToJByteArray(env, value);
928}
929
930static void android_media_MediaDrm_setPropertyString(
931 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
932 sp<IDrm> drm = GetDrm(env, thiz);
933
934 if (drm == NULL) {
935 jniThrowException(env, "java/lang/IllegalStateException", NULL);
936 return;
937 }
938
939 if (jname == NULL || jvalue == NULL) {
940 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
941 return;
942 }
943
944 String8 name = JStringToString8(env, jname);
945 String8 value = JStringToString8(env, jvalue);
946
947 status_t err = drm->setPropertyString(name, value);
948
949 throwExceptionAsNecessary(env, err, "Failed to set property");
950}
951
952static void android_media_MediaDrm_setPropertyByteArray(
953 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
954 sp<IDrm> drm = GetDrm(env, thiz);
955
956 if (drm == NULL) {
957 jniThrowException(env, "java/lang/IllegalStateException", NULL);
958 return;
959 }
960
961 if (jname == NULL || jvalue == NULL) {
962 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
963 return;
964 }
965
966 String8 name = JStringToString8(env, jname);
967 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
968
969 status_t err = drm->setPropertyByteArray(name, value);
970
971 throwExceptionAsNecessary(env, err, "Failed to set property");
972}
973
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700974static void android_media_MediaDrm_setCipherAlgorithmNative(
975 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
976 jstring jalgorithm) {
977
978 sp<IDrm> drm = GetDrm(env, jdrm);
979
980 if (!CheckSession(env, drm, jsessionId)) {
981 return;
982 }
983
984 if (jalgorithm == NULL) {
985 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
986 return;
987 }
988
989 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
990 String8 algorithm = JStringToString8(env, jalgorithm);
991
992 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
993
994 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
995}
996
997static void android_media_MediaDrm_setMacAlgorithmNative(
998 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
999 jstring jalgorithm) {
1000
1001 sp<IDrm> drm = GetDrm(env, jdrm);
1002
1003 if (!CheckSession(env, drm, jsessionId)) {
1004 return;
1005 }
1006
1007 if (jalgorithm == NULL) {
1008 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1009 return;
1010 }
1011
1012 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1013 String8 algorithm = JStringToString8(env, jalgorithm);
1014
1015 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1016
1017 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1018}
1019
1020
1021static jbyteArray android_media_MediaDrm_encryptNative(
1022 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
1023 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1024
1025 sp<IDrm> drm = GetDrm(env, jdrm);
1026
1027 if (!CheckSession(env, drm, jsessionId)) {
1028 return NULL;
1029 }
1030
1031 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
1032 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1033 return NULL;
1034 }
1035
1036 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1037 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1038 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1039 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1040 Vector<uint8_t> output;
1041
1042 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1043
1044 throwExceptionAsNecessary(env, err, "Failed to encrypt");
1045
1046 return VectorToJByteArray(env, output);
1047}
1048
1049static jbyteArray android_media_MediaDrm_decryptNative(
1050 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
1051 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1052
1053 sp<IDrm> drm = GetDrm(env, jdrm);
1054
1055 if (!CheckSession(env, drm, jsessionId)) {
1056 return NULL;
1057 }
1058
1059 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
1060 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1061 return NULL;
1062 }
1063
1064 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1065 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1066 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1067 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1068 Vector<uint8_t> output;
1069
1070 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
1071 throwExceptionAsNecessary(env, err, "Failed to decrypt");
1072
1073 return VectorToJByteArray(env, output);
1074}
1075
1076static jbyteArray android_media_MediaDrm_signNative(
1077 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
1078 jbyteArray jkeyId, jbyteArray jmessage) {
1079
1080 sp<IDrm> drm = GetDrm(env, jdrm);
1081
1082 if (!CheckSession(env, drm, jsessionId)) {
1083 return NULL;
1084 }
1085
1086 if (jkeyId == NULL || jmessage == NULL) {
1087 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1088 return NULL;
1089 }
1090
1091 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1092 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1093 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1094 Vector<uint8_t> signature;
1095
1096 status_t err = drm->sign(sessionId, keyId, message, signature);
1097
1098 throwExceptionAsNecessary(env, err, "Failed to sign");
1099
1100 return VectorToJByteArray(env, signature);
1101}
1102
1103static jboolean android_media_MediaDrm_verifyNative(
1104 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
1105 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1106
1107 sp<IDrm> drm = GetDrm(env, jdrm);
1108
1109 if (!CheckSession(env, drm, jsessionId)) {
1110 return false;
1111 }
1112
1113 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
1114 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1115 return false;
1116 }
1117
1118 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1119 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1120 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1121 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1122 bool match;
1123
1124 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1125
1126 throwExceptionAsNecessary(env, err, "Failed to verify");
1127 return match;
1128}
1129
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001130
1131static JNINativeMethod gMethods[] = {
1132 { "release", "()V", (void *)android_media_MediaDrm_release },
1133 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
1134
1135 { "native_setup", "(Ljava/lang/Object;[B)V",
1136 (void *)android_media_MediaDrm_native_setup },
1137
1138 { "native_finalize", "()V",
1139 (void *)android_media_MediaDrm_native_finalize },
1140
1141 { "isCryptoSchemeSupportedNative", "([B)Z",
1142 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
1143
1144 { "openSession", "()[B",
1145 (void *)android_media_MediaDrm_openSession },
1146
1147 { "closeSession", "([B)V",
1148 (void *)android_media_MediaDrm_closeSession },
1149
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001150 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
1151 "Landroid/media/MediaDrm$KeyRequest;",
1152 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001153
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001154 { "provideKeyResponse", "([B[B)[B",
1155 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001156
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001157 { "removeKeys", "([B)V",
1158 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001159
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001160 { "restoreKeys", "([B[B)V",
1161 (void *)android_media_MediaDrm_restoreKeys },
1162
1163 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
1164 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001165
1166 { "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
1167 (void *)android_media_MediaDrm_getProvisionRequest },
1168
1169 { "provideProvisionResponse", "([B)V",
1170 (void *)android_media_MediaDrm_provideProvisionResponse },
1171
1172 { "getSecureStops", "()Ljava/util/List;",
1173 (void *)android_media_MediaDrm_getSecureStops },
1174
1175 { "releaseSecureStops", "([B)V",
1176 (void *)android_media_MediaDrm_releaseSecureStops },
1177
1178 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
1179 (void *)android_media_MediaDrm_getPropertyString },
1180
1181 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
1182 (void *)android_media_MediaDrm_getPropertyByteArray },
1183
1184 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
1185 (void *)android_media_MediaDrm_setPropertyString },
1186
1187 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
1188 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001189
1190 { "setCipherAlgorithmNative",
1191 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1192 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
1193
1194 { "setMacAlgorithmNative",
1195 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1196 (void *)android_media_MediaDrm_setMacAlgorithmNative },
1197
1198 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1199 (void *)android_media_MediaDrm_encryptNative },
1200
1201 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1202 (void *)android_media_MediaDrm_decryptNative },
1203
1204 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
1205 (void *)android_media_MediaDrm_signNative },
1206
1207 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
1208 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001209};
1210
1211int register_android_media_Drm(JNIEnv *env) {
1212 return AndroidRuntime::registerNativeMethods(env,
1213 "android/media/MediaDrm", gMethods, NELEM(gMethods));
1214}
1215