blob: d9d466e75e6c44dfd192a7c184457cb276a14d27 [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>
33
34namespace android {
35
36#define FIND_CLASS(var, className) \
37 var = env->FindClass(className); \
38 LOG_FATAL_IF(! var, "Unable to find class " className);
39
40#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
41 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
42 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
43
44#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
45 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
46 LOG_FATAL_IF(! var, "Unable to find method " fieldName);
47
Jeff Tinker54cfbd62013-04-02 13:14:59 -070048#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
49 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
50 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
51
52#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
53 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
54 LOG_FATAL_IF(! var, "Unable to find static method " fieldName);
55
56
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080057struct RequestFields {
58 jfieldID data;
59 jfieldID defaultUrl;
60};
61
62struct ArrayListFields {
63 jmethodID init;
64 jmethodID add;
65};
66
67struct HashmapFields {
68 jmethodID init;
69 jmethodID get;
70 jmethodID put;
71 jmethodID entrySet;
72};
73
74struct SetFields {
75 jmethodID iterator;
76};
77
78struct IteratorFields {
79 jmethodID next;
80 jmethodID hasNext;
81};
82
83struct EntryFields {
84 jmethodID getKey;
85 jmethodID getValue;
86};
87
Jeff Tinker54cfbd62013-04-02 13:14:59 -070088struct EventTypes {
89 int kEventProvisionRequired;
90 int kEventKeyRequired;
91 int kEventKeyExpired;
92 int kEventVendorDefined;
93} gEventTypes;
94
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080095struct fields_t {
96 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -070097 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -070098 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080099 RequestFields provisionRequest;
100 ArrayListFields arraylist;
101 HashmapFields hashmap;
102 SetFields set;
103 IteratorFields iterator;
104 EntryFields entry;
105};
106
107static fields_t gFields;
108
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700109// ----------------------------------------------------------------------------
110// ref-counted object for callbacks
111class JNIDrmListener: public DrmListener
112{
113public:
114 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
115 ~JNIDrmListener();
116 virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
117private:
118 JNIDrmListener();
119 jclass mClass; // Reference to MediaDrm class
120 jobject mObject; // Weak ref to MediaDrm Java object to call on
121};
122
123JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
124{
125 // Hold onto the MediaDrm class for use in calling the static method
126 // that posts events to the application thread.
127 jclass clazz = env->GetObjectClass(thiz);
128 if (clazz == NULL) {
129 ALOGE("Can't find android/media/MediaDrm");
130 jniThrowException(env, "java/lang/Exception", NULL);
131 return;
132 }
133 mClass = (jclass)env->NewGlobalRef(clazz);
134
135 // We use a weak reference so the MediaDrm object can be garbage collected.
136 // The reference is only used as a proxy for callbacks.
137 mObject = env->NewGlobalRef(weak_thiz);
138}
139
140JNIDrmListener::~JNIDrmListener()
141{
142 // remove global references
143 JNIEnv *env = AndroidRuntime::getJNIEnv();
144 env->DeleteGlobalRef(mObject);
145 env->DeleteGlobalRef(mClass);
146}
147
148void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
149 const Parcel *obj)
150{
151 jint jeventType;
152
153 // translate DrmPlugin event types into their java equivalents
154 switch(eventType) {
155 case DrmPlugin::kDrmPluginEventProvisionRequired:
156 jeventType = gEventTypes.kEventProvisionRequired;
157 break;
158 case DrmPlugin::kDrmPluginEventKeyNeeded:
159 jeventType = gEventTypes.kEventKeyRequired;
160 break;
161 case DrmPlugin::kDrmPluginEventKeyExpired:
162 jeventType = gEventTypes.kEventKeyExpired;
163 break;
164 case DrmPlugin::kDrmPluginEventVendorDefined:
165 jeventType = gEventTypes.kEventVendorDefined;
166 break;
167 default:
168 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
169 return;
170 }
171
172 JNIEnv *env = AndroidRuntime::getJNIEnv();
173 if (obj && obj->dataSize() > 0) {
174 jobject jParcel = createJavaParcelObject(env);
175 if (jParcel != NULL) {
176 Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
177 nativeParcel->setData(obj->data(), obj->dataSize());
178 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
179 jeventType, extra, jParcel);
180 }
181 }
182
183 if (env->ExceptionCheck()) {
184 ALOGW("An exception occurred while notifying an event.");
185 LOGW_EX(env);
186 env->ExceptionClear();
187 }
188}
189
190
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800191static bool throwExceptionAsNecessary(
192 JNIEnv *env, status_t err, const char *msg = NULL) {
193
194 if (err == BAD_VALUE) {
195 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
196 return true;
197 } else if (err != OK) {
198 jniThrowException(env, "java/lang/IllegalStateException", msg);
199 return true;
200 }
201 return false;
202}
203
204static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
205 JDrm *jdrm = (JDrm *)env->GetIntField(thiz, gFields.context);
206 return jdrm ? jdrm->getDrm() : NULL;
207}
208
209JDrm::JDrm(
210 JNIEnv *env, jobject thiz, const uint8_t uuid[16]) {
211 mObject = env->NewWeakGlobalRef(thiz);
212 mDrm = MakeDrm(uuid);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700213 if (mDrm != NULL) {
214 mDrm->setListener(this);
215 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800216}
217
218JDrm::~JDrm() {
219 mDrm.clear();
220
221 JNIEnv *env = AndroidRuntime::getJNIEnv();
222
223 env->DeleteWeakGlobalRef(mObject);
224 mObject = NULL;
225}
226
227// static
228sp<IDrm> JDrm::MakeDrm() {
229 sp<IServiceManager> sm = defaultServiceManager();
230
231 sp<IBinder> binder =
232 sm->getService(String16("media.player"));
233
234 sp<IMediaPlayerService> service =
235 interface_cast<IMediaPlayerService>(binder);
236
237 if (service == NULL) {
238 return NULL;
239 }
240
241 sp<IDrm> drm = service->makeDrm();
242
243 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
244 return NULL;
245 }
246
247 return drm;
248}
249
250// static
251sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) {
252 sp<IDrm> drm = MakeDrm();
253
254 if (drm == NULL) {
255 return NULL;
256 }
257
258 status_t err = drm->createPlugin(uuid);
259
260 if (err != OK) {
261 return NULL;
262 }
263
264 return drm;
265}
266
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700267status_t JDrm::setListener(const sp<DrmListener>& listener) {
268 Mutex::Autolock lock(mLock);
269 mListener = listener;
270 return OK;
271}
272
273void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
274 sp<DrmListener> listener;
275 mLock.lock();
276 listener = mListener;
277 mLock.unlock();
278
279 if (listener != NULL) {
280 Mutex::Autolock lock(mNotifyLock);
281 listener->notify(eventType, extra, obj);
282 }
283}
284
285
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800286// static
287bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) {
288 sp<IDrm> drm = MakeDrm();
289
290 if (drm == NULL) {
291 return false;
292 }
293
294 return drm->isCryptoSchemeSupported(uuid);
295}
296
297status_t JDrm::initCheck() const {
298 return mDrm == NULL ? NO_INIT : OK;
299}
300
301// JNI conversion utilities
302static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
303 Vector<uint8_t> vector;
304 size_t length = env->GetArrayLength(byteArray);
305 vector.insertAt((size_t)0, length);
306 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
307 return vector;
308}
309
310static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
311 size_t length = vector.size();
312 jbyteArray result = env->NewByteArray(length);
313 if (result != NULL) {
314 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
315 }
316 return result;
317}
318
319static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800320 String8 result;
321
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700322 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800323 if (s) {
324 result = s;
325 env->ReleaseStringUTFChars(jstr, s);
326 }
327 return result;
328}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700329
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800330/*
331 import java.util.HashMap;
332 import java.util.Set;
333 import java.Map.Entry;
334 import jav.util.Iterator;
335
336 HashMap<k, v> hm;
337 Set<Entry<k, v> > s = hm.entrySet();
338 Iterator i = s.iterator();
339 Entry e = s.next();
340*/
341
342static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
343 jclass clazz;
344 FIND_CLASS(clazz, "java/lang/String");
345 KeyedVector<String8, String8> keyedVector;
346
347 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
348 if (entrySet) {
349 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
350 if (iterator) {
351 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
352 while (hasNext) {
353 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
354 if (entry) {
355 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
356 if (!env->IsInstanceOf(obj, clazz)) {
357 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
358 }
359 jstring jkey = static_cast<jstring>(obj);
360
361 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
362 if (!env->IsInstanceOf(obj, clazz)) {
363 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
364 }
365 jstring jvalue = static_cast<jstring>(obj);
366
367 String8 key = JStringToString8(env, jkey);
368 String8 value = JStringToString8(env, jvalue);
369 keyedVector.add(key, value);
370
371 env->DeleteLocalRef(jkey);
372 env->DeleteLocalRef(jvalue);
373 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
374 }
375 env->DeleteLocalRef(entry);
376 }
377 env->DeleteLocalRef(iterator);
378 }
379 env->DeleteLocalRef(entrySet);
380 }
381 return keyedVector;
382}
383
384static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
385 jclass clazz;
386 FIND_CLASS(clazz, "java/util/HashMap");
387 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
388 for (size_t i = 0; i < map.size(); ++i) {
389 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
390 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
391 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
392 env->DeleteLocalRef(jkey);
393 env->DeleteLocalRef(jvalue);
394 }
395 return hashMap;
396}
397
398static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
399 List<Vector<uint8_t> > list) {
400 jclass clazz;
401 FIND_CLASS(clazz, "java/util/ArrayList");
402 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
403 List<Vector<uint8_t> >::iterator iter = list.begin();
404 while (iter != list.end()) {
405 jbyteArray byteArray = VectorToJByteArray(env, *iter);
406 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
407 env->DeleteLocalRef(byteArray);
408 iter++;
409 }
410
411 return arrayList;
412}
413
414} // namespace android
415
416using namespace android;
417
418static sp<JDrm> setDrm(
419 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
420 sp<JDrm> old = (JDrm *)env->GetIntField(thiz, gFields.context);
421 if (drm != NULL) {
422 drm->incStrong(thiz);
423 }
424 if (old != NULL) {
425 old->decStrong(thiz);
426 }
427 env->SetIntField(thiz, gFields.context, (int)drm.get());
428
429 return old;
430}
431
432static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
433{
434 if (drm == NULL) {
435 jniThrowException(env, "java/lang/IllegalStateException", NULL);
436 return false;
437 }
438
439 if (jsessionId == NULL) {
440 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
441 return false;
442 }
443 return true;
444}
445
446static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700447 sp<JDrm> drm = setDrm(env, thiz, NULL);
448 if (drm != NULL) {
449 drm->setListener(NULL);
450 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800451}
452
453static void android_media_MediaDrm_native_init(JNIEnv *env) {
454 jclass clazz;
455 FIND_CLASS(clazz, "android/media/MediaDrm");
456 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700457 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
458 "(Ljava/lang/Object;IILjava/lang/Object;)V");
459
460 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700461 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700462 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700463 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700464 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700465 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700466 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700467 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700468 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800469
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700470 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700471 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
472 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800473
474 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700475 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
476 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800477
478 FIND_CLASS(clazz, "java/util/ArrayList");
479 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
480 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
481
482 FIND_CLASS(clazz, "java/util/HashMap");
483 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
484 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
485 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
486 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
487 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
488
489 FIND_CLASS(clazz, "java/util/Set");
490 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
491
492 FIND_CLASS(clazz, "java/util/Iterator");
493 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
494 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
495
496 FIND_CLASS(clazz, "java/util/Map$Entry");
497 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
498 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
499}
500
501static void android_media_MediaDrm_native_setup(
502 JNIEnv *env, jobject thiz,
503 jobject weak_this, jbyteArray uuidObj) {
504
505 if (uuidObj == NULL) {
506 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
507 return;
508 }
509
510 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
511
512 if (uuid.size() != 16) {
513 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
514 return;
515 }
516
517 sp<JDrm> drm = new JDrm(env, thiz, uuid.array());
518
519 status_t err = drm->initCheck();
520
521 if (err != OK) {
522 jniThrowException(
523 env,
524 "android/media/MediaDrmException",
525 "Failed to instantiate drm object.");
526 return;
527 }
528
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700529 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
530 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800531 setDrm(env, thiz, drm);
532}
533
534static void android_media_MediaDrm_native_finalize(
535 JNIEnv *env, jobject thiz) {
536 android_media_MediaDrm_release(env, thiz);
537}
538
539static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
540 JNIEnv *env, jobject thiz, jbyteArray uuidObj) {
541
542 if (uuidObj == NULL) {
543 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
544 return false;
545 }
546
547 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
548
549 if (uuid.size() != 16) {
550 jniThrowException(
551 env,
552 "java/lang/IllegalArgumentException",
553 NULL);
554 return false;
555 }
556
557 return JDrm::IsCryptoSchemeSupported(uuid.array());
558}
559
560static jbyteArray android_media_MediaDrm_openSession(
561 JNIEnv *env, jobject thiz) {
562 sp<IDrm> drm = GetDrm(env, thiz);
563
564 if (drm == NULL) {
565 jniThrowException(env, "java/lang/IllegalStateException", NULL);
566 return NULL;
567 }
568
569 Vector<uint8_t> sessionId;
570 status_t err = drm->openSession(sessionId);
571
572 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
573 return NULL;
574 }
575
576 return VectorToJByteArray(env, sessionId);
577}
578
579static void android_media_MediaDrm_closeSession(
580 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
581 sp<IDrm> drm = GetDrm(env, thiz);
582
583 if (!CheckSession(env, drm, jsessionId)) {
584 return;
585 }
586
587 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
588
589 status_t err = drm->closeSession(sessionId);
590
591 throwExceptionAsNecessary(env, err, "Failed to close session");
592}
593
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700594static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800595 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700596 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800597 sp<IDrm> drm = GetDrm(env, thiz);
598
599 if (!CheckSession(env, drm, jsessionId)) {
600 return NULL;
601 }
602
603 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
604
605 Vector<uint8_t> initData;
606 if (jinitData != NULL) {
607 initData = JByteArrayToVector(env, jinitData);
608 }
609
610 String8 mimeType;
611 if (jmimeType != NULL) {
612 mimeType = JStringToString8(env, jmimeType);
613 }
614
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700615 DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)jkeyType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800616
617 KeyedVector<String8, String8> optParams;
618 if (joptParams != NULL) {
619 optParams = HashMapToKeyedVector(env, joptParams);
620 }
621
622 Vector<uint8_t> request;
623 String8 defaultUrl;
624
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700625 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
626 keyType, optParams, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800627
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700628 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800629 return NULL;
630 }
631
632 // Fill out return obj
633 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700634 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800635
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700636 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800637
638 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700639 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800640 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700641 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800642
643 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700644 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800645 }
646
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700647 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800648}
649
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700650static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800651 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
652 sp<IDrm> drm = GetDrm(env, thiz);
653
654 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700655 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800656 }
657
658 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
659
660 if (jresponse == NULL) {
661 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700662 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800663 }
664 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700665 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800666
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700667 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800668
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700669 throwExceptionAsNecessary(env, err, "Failed to handle key response");
670 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800671}
672
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700673static void android_media_MediaDrm_removeKeys(
674 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
675 sp<IDrm> drm = GetDrm(env, thiz);
676
677 if (jkeysetId == NULL) {
678 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
679 return;
680 }
681
682 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
683
684 status_t err = drm->removeKeys(keySetId);
685
686 throwExceptionAsNecessary(env, err, "Failed to remove keys");
687}
688
689static void android_media_MediaDrm_restoreKeys(
690 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
691 jbyteArray jkeysetId) {
692
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800693 sp<IDrm> drm = GetDrm(env, thiz);
694
695 if (!CheckSession(env, drm, jsessionId)) {
696 return;
697 }
698
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700699 if (jkeysetId == NULL) {
700 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
701 return;
702 }
703
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800704 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700705 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800706
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700707 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800708
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700709 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800710}
711
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700712static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800713 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
714 sp<IDrm> drm = GetDrm(env, thiz);
715
716 if (!CheckSession(env, drm, jsessionId)) {
717 return NULL;
718 }
719 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
720
721 KeyedVector<String8, String8> infoMap;
722
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700723 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800724
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700725 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800726 return NULL;
727 }
728
729 return KeyedVectorToHashMap(env, infoMap);
730}
731
732static jobject android_media_MediaDrm_getProvisionRequest(
733 JNIEnv *env, jobject thiz) {
734 sp<IDrm> drm = GetDrm(env, thiz);
735
736 if (drm == NULL) {
737 jniThrowException(env, "java/lang/IllegalStateException", NULL);
738 return NULL;
739 }
740
741 Vector<uint8_t> request;
742 String8 defaultUrl;
743
744 status_t err = drm->getProvisionRequest(request, defaultUrl);
745
746 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
747 return NULL;
748 }
749
750 // Fill out return obj
751 jclass clazz;
752 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
753
754 jobject provisionObj = NULL;
755
756 if (clazz) {
757 provisionObj = env->AllocObject(clazz);
758 jbyteArray jrequest = VectorToJByteArray(env, request);
759 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
760
761 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
762 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
763 }
764
765 return provisionObj;
766}
767
768static void android_media_MediaDrm_provideProvisionResponse(
769 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
770 sp<IDrm> drm = GetDrm(env, thiz);
771
772 if (drm == NULL) {
773 jniThrowException(env, "java/lang/IllegalStateException", NULL);
774 return;
775 }
776
777 if (jresponse == NULL) {
778 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
779 return;
780 }
781
782 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
783
784 status_t err = drm->provideProvisionResponse(response);
785
786 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
787}
788
789static jobject android_media_MediaDrm_getSecureStops(
790 JNIEnv *env, jobject thiz) {
791 sp<IDrm> drm = GetDrm(env, thiz);
792
793 if (drm == NULL) {
794 jniThrowException(env, "java/lang/IllegalStateException", NULL);
795 return NULL;
796 }
797
798 List<Vector<uint8_t> > secureStops;
799
800 status_t err = drm->getSecureStops(secureStops);
801
802 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
803 return NULL;
804 }
805
806 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
807}
808
809static void android_media_MediaDrm_releaseSecureStops(
810 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
811 sp<IDrm> drm = GetDrm(env, thiz);
812
813 if (drm == NULL) {
814 jniThrowException(env, "java/lang/IllegalStateException", NULL);
815 return;
816 }
817
818 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
819
820 status_t err = drm->releaseSecureStops(ssRelease);
821
822 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
823}
824
825static jstring android_media_MediaDrm_getPropertyString(
826 JNIEnv *env, jobject thiz, jstring jname) {
827 sp<IDrm> drm = GetDrm(env, thiz);
828
829 if (drm == NULL) {
830 jniThrowException(env, "java/lang/IllegalStateException", NULL);
831 return NULL;
832 }
833
834 if (jname == NULL) {
835 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
836 return NULL;
837 }
838
839 String8 name = JStringToString8(env, jname);
840 String8 value;
841
842 status_t err = drm->getPropertyString(name, value);
843
844 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
845 return NULL;
846 }
847
848 return env->NewStringUTF(value.string());
849}
850
851static jbyteArray android_media_MediaDrm_getPropertyByteArray(
852 JNIEnv *env, jobject thiz, jstring jname) {
853 sp<IDrm> drm = GetDrm(env, thiz);
854
855 if (drm == NULL) {
856 jniThrowException(env, "java/lang/IllegalStateException", NULL);
857 return NULL;
858 }
859
860 if (jname == NULL) {
861 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
862 return NULL;
863 }
864
865 String8 name = JStringToString8(env, jname);
866 Vector<uint8_t> value;
867
868 status_t err = drm->getPropertyByteArray(name, value);
869
870 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
871 return NULL;
872 }
873
874 return VectorToJByteArray(env, value);
875}
876
877static void android_media_MediaDrm_setPropertyString(
878 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
879 sp<IDrm> drm = GetDrm(env, thiz);
880
881 if (drm == NULL) {
882 jniThrowException(env, "java/lang/IllegalStateException", NULL);
883 return;
884 }
885
886 if (jname == NULL || jvalue == NULL) {
887 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
888 return;
889 }
890
891 String8 name = JStringToString8(env, jname);
892 String8 value = JStringToString8(env, jvalue);
893
894 status_t err = drm->setPropertyString(name, value);
895
896 throwExceptionAsNecessary(env, err, "Failed to set property");
897}
898
899static void android_media_MediaDrm_setPropertyByteArray(
900 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
901 sp<IDrm> drm = GetDrm(env, thiz);
902
903 if (drm == NULL) {
904 jniThrowException(env, "java/lang/IllegalStateException", NULL);
905 return;
906 }
907
908 if (jname == NULL || jvalue == NULL) {
909 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
910 return;
911 }
912
913 String8 name = JStringToString8(env, jname);
914 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
915
916 status_t err = drm->setPropertyByteArray(name, value);
917
918 throwExceptionAsNecessary(env, err, "Failed to set property");
919}
920
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700921static void android_media_MediaDrm_setCipherAlgorithmNative(
922 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
923 jstring jalgorithm) {
924
925 sp<IDrm> drm = GetDrm(env, jdrm);
926
927 if (!CheckSession(env, drm, jsessionId)) {
928 return;
929 }
930
931 if (jalgorithm == NULL) {
932 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
933 return;
934 }
935
936 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
937 String8 algorithm = JStringToString8(env, jalgorithm);
938
939 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
940
941 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
942}
943
944static void android_media_MediaDrm_setMacAlgorithmNative(
945 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
946 jstring jalgorithm) {
947
948 sp<IDrm> drm = GetDrm(env, jdrm);
949
950 if (!CheckSession(env, drm, jsessionId)) {
951 return;
952 }
953
954 if (jalgorithm == NULL) {
955 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
956 return;
957 }
958
959 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
960 String8 algorithm = JStringToString8(env, jalgorithm);
961
962 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
963
964 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
965}
966
967
968static jbyteArray android_media_MediaDrm_encryptNative(
969 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
970 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
971
972 sp<IDrm> drm = GetDrm(env, jdrm);
973
974 if (!CheckSession(env, drm, jsessionId)) {
975 return NULL;
976 }
977
978 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
979 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
980 return NULL;
981 }
982
983 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
984 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
985 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
986 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
987 Vector<uint8_t> output;
988
989 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
990
991 throwExceptionAsNecessary(env, err, "Failed to encrypt");
992
993 return VectorToJByteArray(env, output);
994}
995
996static jbyteArray android_media_MediaDrm_decryptNative(
997 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
998 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
999
1000 sp<IDrm> drm = GetDrm(env, jdrm);
1001
1002 if (!CheckSession(env, drm, jsessionId)) {
1003 return NULL;
1004 }
1005
1006 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
1007 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1008 return NULL;
1009 }
1010
1011 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1012 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1013 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1014 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1015 Vector<uint8_t> output;
1016
1017 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
1018 throwExceptionAsNecessary(env, err, "Failed to decrypt");
1019
1020 return VectorToJByteArray(env, output);
1021}
1022
1023static jbyteArray android_media_MediaDrm_signNative(
1024 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
1025 jbyteArray jkeyId, jbyteArray jmessage) {
1026
1027 sp<IDrm> drm = GetDrm(env, jdrm);
1028
1029 if (!CheckSession(env, drm, jsessionId)) {
1030 return NULL;
1031 }
1032
1033 if (jkeyId == NULL || jmessage == NULL) {
1034 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1035 return NULL;
1036 }
1037
1038 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1039 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1040 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1041 Vector<uint8_t> signature;
1042
1043 status_t err = drm->sign(sessionId, keyId, message, signature);
1044
1045 throwExceptionAsNecessary(env, err, "Failed to sign");
1046
1047 return VectorToJByteArray(env, signature);
1048}
1049
1050static jboolean android_media_MediaDrm_verifyNative(
1051 JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
1052 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1053
1054 sp<IDrm> drm = GetDrm(env, jdrm);
1055
1056 if (!CheckSession(env, drm, jsessionId)) {
1057 return false;
1058 }
1059
1060 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
1061 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1062 return false;
1063 }
1064
1065 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1066 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1067 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1068 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1069 bool match;
1070
1071 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1072
1073 throwExceptionAsNecessary(env, err, "Failed to verify");
1074 return match;
1075}
1076
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001077
1078static JNINativeMethod gMethods[] = {
1079 { "release", "()V", (void *)android_media_MediaDrm_release },
1080 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
1081
1082 { "native_setup", "(Ljava/lang/Object;[B)V",
1083 (void *)android_media_MediaDrm_native_setup },
1084
1085 { "native_finalize", "()V",
1086 (void *)android_media_MediaDrm_native_finalize },
1087
1088 { "isCryptoSchemeSupportedNative", "([B)Z",
1089 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
1090
1091 { "openSession", "()[B",
1092 (void *)android_media_MediaDrm_openSession },
1093
1094 { "closeSession", "([B)V",
1095 (void *)android_media_MediaDrm_closeSession },
1096
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001097 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
1098 "Landroid/media/MediaDrm$KeyRequest;",
1099 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001100
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001101 { "provideKeyResponse", "([B[B)[B",
1102 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001103
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001104 { "removeKeys", "([B)V",
1105 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001106
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001107 { "restoreKeys", "([B[B)V",
1108 (void *)android_media_MediaDrm_restoreKeys },
1109
1110 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
1111 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001112
1113 { "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
1114 (void *)android_media_MediaDrm_getProvisionRequest },
1115
1116 { "provideProvisionResponse", "([B)V",
1117 (void *)android_media_MediaDrm_provideProvisionResponse },
1118
1119 { "getSecureStops", "()Ljava/util/List;",
1120 (void *)android_media_MediaDrm_getSecureStops },
1121
1122 { "releaseSecureStops", "([B)V",
1123 (void *)android_media_MediaDrm_releaseSecureStops },
1124
1125 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
1126 (void *)android_media_MediaDrm_getPropertyString },
1127
1128 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
1129 (void *)android_media_MediaDrm_getPropertyByteArray },
1130
1131 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
1132 (void *)android_media_MediaDrm_setPropertyString },
1133
1134 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
1135 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001136
1137 { "setCipherAlgorithmNative",
1138 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1139 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
1140
1141 { "setMacAlgorithmNative",
1142 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1143 (void *)android_media_MediaDrm_setMacAlgorithmNative },
1144
1145 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1146 (void *)android_media_MediaDrm_encryptNative },
1147
1148 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1149 (void *)android_media_MediaDrm_decryptNative },
1150
1151 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
1152 (void *)android_media_MediaDrm_signNative },
1153
1154 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
1155 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001156};
1157
1158int register_android_media_Drm(JNIEnv *env) {
1159 return AndroidRuntime::registerNativeMethods(env,
1160 "android/media/MediaDrm", gMethods, NELEM(gMethods));
1161}
1162