blob: 03273c254e33ad26357cce6ef9077b04ca0fe095 [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"
Ruben Brunk87eac992013-09-09 17:44:59 -070024#include "android_runtime/Log.h"
Jeff Tinker54cfbd62013-04-02 13:14:59 -070025#include "android_os_Parcel.h"
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080026#include "jni.h"
27#include "JNIHelp.h"
28
29#include <binder/IServiceManager.h>
Jeff Tinker54cfbd62013-04-02 13:14:59 -070030#include <binder/Parcel.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080031#include <media/IDrm.h>
32#include <media/IMediaPlayerService.h>
33#include <media/stagefright/foundation/ADebug.h>
Jeff Tinkerf7568b52013-04-17 14:24:40 -070034#include <media/stagefright/MediaErrors.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080035
36namespace android {
37
38#define FIND_CLASS(var, className) \
39 var = env->FindClass(className); \
40 LOG_FATAL_IF(! var, "Unable to find class " className);
41
42#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
43 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
44 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
45
46#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
47 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
48 LOG_FATAL_IF(! var, "Unable to find method " fieldName);
49
Jeff Tinker54cfbd62013-04-02 13:14:59 -070050#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
51 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
52 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
53
54#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
55 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
56 LOG_FATAL_IF(! var, "Unable to find static method " fieldName);
57
58
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080059struct RequestFields {
60 jfieldID data;
61 jfieldID defaultUrl;
62};
63
64struct ArrayListFields {
65 jmethodID init;
66 jmethodID add;
67};
68
69struct HashmapFields {
70 jmethodID init;
71 jmethodID get;
72 jmethodID put;
73 jmethodID entrySet;
74};
75
76struct SetFields {
77 jmethodID iterator;
78};
79
80struct IteratorFields {
81 jmethodID next;
82 jmethodID hasNext;
83};
84
85struct EntryFields {
86 jmethodID getKey;
87 jmethodID getValue;
88};
89
Jeff Tinker54cfbd62013-04-02 13:14:59 -070090struct EventTypes {
Jeff Tinker17b89222013-05-21 12:35:06 -070091 jint kEventProvisionRequired;
92 jint kEventKeyRequired;
93 jint kEventKeyExpired;
94 jint kEventVendorDefined;
Jeff Tinker54cfbd62013-04-02 13:14:59 -070095} gEventTypes;
96
Jeff Tinker17b89222013-05-21 12:35:06 -070097struct KeyTypes {
98 jint kKeyTypeStreaming;
99 jint kKeyTypeOffline;
100 jint kKeyTypeRelease;
101} gKeyTypes;
102
Jeff Tinkere4095a82014-03-04 13:17:11 -0800103struct CertificateTypes {
104 jint kCertificateTypeNone;
105 jint kCertificateTypeX509;
106} gCertificateTypes;
107
108struct CertificateFields {
109 jfieldID wrappedPrivateKey;
110 jfieldID certificateData;
111};
112
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700113struct StateExceptionFields {
114 jmethodID init;
115 jclass classId;
116};
117
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800118struct fields_t {
119 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700120 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700121 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800122 RequestFields provisionRequest;
123 ArrayListFields arraylist;
124 HashmapFields hashmap;
125 SetFields set;
126 IteratorFields iterator;
127 EntryFields entry;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800128 CertificateFields certificate;
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700129 StateExceptionFields stateException;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800130 jclass certificateClassId;
131 jclass hashmapClassId;
132 jclass arraylistClassId;
133 jclass stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800134};
135
136static fields_t gFields;
137
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700138// ----------------------------------------------------------------------------
139// ref-counted object for callbacks
140class JNIDrmListener: public DrmListener
141{
142public:
143 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
144 ~JNIDrmListener();
145 virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
146private:
147 JNIDrmListener();
148 jclass mClass; // Reference to MediaDrm class
149 jobject mObject; // Weak ref to MediaDrm Java object to call on
150};
151
152JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
153{
154 // Hold onto the MediaDrm class for use in calling the static method
155 // that posts events to the application thread.
156 jclass clazz = env->GetObjectClass(thiz);
157 if (clazz == NULL) {
158 ALOGE("Can't find android/media/MediaDrm");
Jeff Tinkereada5372013-05-21 12:48:14 -0700159 jniThrowException(env, "java/lang/Exception",
160 "Can't find android/media/MediaDrm");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700161 return;
162 }
163 mClass = (jclass)env->NewGlobalRef(clazz);
164
165 // We use a weak reference so the MediaDrm object can be garbage collected.
166 // The reference is only used as a proxy for callbacks.
167 mObject = env->NewGlobalRef(weak_thiz);
168}
169
170JNIDrmListener::~JNIDrmListener()
171{
172 // remove global references
173 JNIEnv *env = AndroidRuntime::getJNIEnv();
174 env->DeleteGlobalRef(mObject);
175 env->DeleteGlobalRef(mClass);
176}
177
178void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
179 const Parcel *obj)
180{
181 jint jeventType;
182
183 // translate DrmPlugin event types into their java equivalents
184 switch(eventType) {
185 case DrmPlugin::kDrmPluginEventProvisionRequired:
186 jeventType = gEventTypes.kEventProvisionRequired;
187 break;
188 case DrmPlugin::kDrmPluginEventKeyNeeded:
189 jeventType = gEventTypes.kEventKeyRequired;
190 break;
191 case DrmPlugin::kDrmPluginEventKeyExpired:
192 jeventType = gEventTypes.kEventKeyExpired;
193 break;
194 case DrmPlugin::kDrmPluginEventVendorDefined:
195 jeventType = gEventTypes.kEventVendorDefined;
196 break;
197 default:
198 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
199 return;
200 }
201
202 JNIEnv *env = AndroidRuntime::getJNIEnv();
203 if (obj && obj->dataSize() > 0) {
204 jobject jParcel = createJavaParcelObject(env);
205 if (jParcel != NULL) {
206 Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
207 nativeParcel->setData(obj->data(), obj->dataSize());
208 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
209 jeventType, extra, jParcel);
Patrik2 Carlsson265551a2013-12-10 14:52:43 +0100210 env->DeleteLocalRef(jParcel);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700211 }
212 }
213
214 if (env->ExceptionCheck()) {
215 ALOGW("An exception occurred while notifying an event.");
216 LOGW_EX(env);
217 env->ExceptionClear();
218 }
219}
220
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700221static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
222 ALOGE("Illegal state exception: %s (%d)", msg, err);
223
224 jobject exception = env->NewObject(gFields.stateException.classId,
225 gFields.stateException.init, static_cast<int>(err),
226 env->NewStringUTF(msg));
227 env->Throw(static_cast<jthrowable>(exception));
228}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700229
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800230static bool throwExceptionAsNecessary(
231 JNIEnv *env, status_t err, const char *msg = NULL) {
232
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700233 const char *drmMessage = NULL;
234
235 switch(err) {
236 case ERROR_DRM_UNKNOWN:
237 drmMessage = "General DRM error";
238 break;
239 case ERROR_DRM_NO_LICENSE:
240 drmMessage = "No license";
241 break;
242 case ERROR_DRM_LICENSE_EXPIRED:
243 drmMessage = "License expired";
244 break;
245 case ERROR_DRM_SESSION_NOT_OPENED:
246 drmMessage = "Session not opened";
247 break;
248 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
249 drmMessage = "Not initialized";
250 break;
251 case ERROR_DRM_DECRYPT:
252 drmMessage = "Decrypt error";
253 break;
254 case ERROR_DRM_CANNOT_HANDLE:
255 drmMessage = "Unsupported scheme or data format";
256 break;
257 case ERROR_DRM_TAMPER_DETECTED:
258 drmMessage = "Invalid state";
259 break;
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700260 default:
261 break;
262 }
263
264 String8 vendorMessage;
265 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
Jeff Tinker29799862014-08-27 11:05:13 -0700266 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700267 drmMessage = vendorMessage.string();
268 }
269
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800270 if (err == BAD_VALUE) {
271 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
272 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700273 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
274 jniThrowException(env, "android/media/NotProvisionedException", msg);
275 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700276 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
277 jniThrowException(env, "android/media/ResourceBusyException", msg);
278 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700279 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
280 jniThrowException(env, "android/media/DeniedByServerException", msg);
281 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800282 } else if (err != OK) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700283 String8 errbuf;
284 if (drmMessage != NULL) {
285 if (msg == NULL) {
286 msg = drmMessage;
287 } else {
Jeff Tinker29799862014-08-27 11:05:13 -0700288 errbuf = String8::format("%s: %s", msg, drmMessage);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700289 msg = errbuf.string();
290 }
291 }
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700292 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800293 return true;
294 }
295 return false;
296}
297
298static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000299 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800300 return jdrm ? jdrm->getDrm() : NULL;
301}
302
303JDrm::JDrm(
304 JNIEnv *env, jobject thiz, const uint8_t uuid[16]) {
305 mObject = env->NewWeakGlobalRef(thiz);
306 mDrm = MakeDrm(uuid);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700307 if (mDrm != NULL) {
308 mDrm->setListener(this);
309 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800310}
311
312JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800313 JNIEnv *env = AndroidRuntime::getJNIEnv();
314
315 env->DeleteWeakGlobalRef(mObject);
316 mObject = NULL;
317}
318
319// static
320sp<IDrm> JDrm::MakeDrm() {
321 sp<IServiceManager> sm = defaultServiceManager();
322
323 sp<IBinder> binder =
324 sm->getService(String16("media.player"));
325
326 sp<IMediaPlayerService> service =
327 interface_cast<IMediaPlayerService>(binder);
328
329 if (service == NULL) {
330 return NULL;
331 }
332
333 sp<IDrm> drm = service->makeDrm();
334
335 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
336 return NULL;
337 }
338
339 return drm;
340}
341
342// static
343sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) {
344 sp<IDrm> drm = MakeDrm();
345
346 if (drm == NULL) {
347 return NULL;
348 }
349
350 status_t err = drm->createPlugin(uuid);
351
352 if (err != OK) {
353 return NULL;
354 }
355
356 return drm;
357}
358
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700359status_t JDrm::setListener(const sp<DrmListener>& listener) {
360 Mutex::Autolock lock(mLock);
361 mListener = listener;
362 return OK;
363}
364
365void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
366 sp<DrmListener> listener;
367 mLock.lock();
368 listener = mListener;
369 mLock.unlock();
370
371 if (listener != NULL) {
372 Mutex::Autolock lock(mNotifyLock);
373 listener->notify(eventType, extra, obj);
374 }
375}
376
Jeff Tinker600071c2014-04-11 16:11:15 -0700377void JDrm::disconnect() {
378 if (mDrm != NULL) {
379 mDrm->destroyPlugin();
380 mDrm.clear();
381 }
382}
383
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700384
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800385// static
Jeff Tinker7cda4912013-08-21 11:52:34 -0700386bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800387 sp<IDrm> drm = MakeDrm();
388
389 if (drm == NULL) {
390 return false;
391 }
392
Jeff Tinker7cda4912013-08-21 11:52:34 -0700393 return drm->isCryptoSchemeSupported(uuid, mimeType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800394}
395
396status_t JDrm::initCheck() const {
397 return mDrm == NULL ? NO_INIT : OK;
398}
399
400// JNI conversion utilities
401static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
402 Vector<uint8_t> vector;
403 size_t length = env->GetArrayLength(byteArray);
404 vector.insertAt((size_t)0, length);
405 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
406 return vector;
407}
408
409static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
410 size_t length = vector.size();
411 jbyteArray result = env->NewByteArray(length);
412 if (result != NULL) {
413 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
414 }
415 return result;
416}
417
418static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800419 String8 result;
420
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700421 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800422 if (s) {
423 result = s;
424 env->ReleaseStringUTFChars(jstr, s);
425 }
426 return result;
427}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700428
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800429/*
430 import java.util.HashMap;
431 import java.util.Set;
432 import java.Map.Entry;
433 import jav.util.Iterator;
434
435 HashMap<k, v> hm;
436 Set<Entry<k, v> > s = hm.entrySet();
437 Iterator i = s.iterator();
438 Entry e = s.next();
439*/
440
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200441static KeyedVector<String8, String8> HashMapToKeyedVector(
442 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800443 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800444 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200445 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800446
447 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
448 if (entrySet) {
449 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
450 if (iterator) {
451 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
452 while (hasNext) {
453 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
454 if (entry) {
455 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200456 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700457 jniThrowException(env, "java/lang/IllegalArgumentException",
458 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200459 env->DeleteLocalRef(entry);
460 *pIsOK = false;
461 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800462 }
463 jstring jkey = static_cast<jstring>(obj);
464
465 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200466 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700467 jniThrowException(env, "java/lang/IllegalArgumentException",
468 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200469 env->DeleteLocalRef(entry);
470 *pIsOK = false;
471 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800472 }
473 jstring jvalue = static_cast<jstring>(obj);
474
475 String8 key = JStringToString8(env, jkey);
476 String8 value = JStringToString8(env, jvalue);
477 keyedVector.add(key, value);
478
479 env->DeleteLocalRef(jkey);
480 env->DeleteLocalRef(jvalue);
481 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
482 }
483 env->DeleteLocalRef(entry);
484 }
485 env->DeleteLocalRef(iterator);
486 }
487 env->DeleteLocalRef(entrySet);
488 }
489 return keyedVector;
490}
491
492static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800493 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800494 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
495 for (size_t i = 0; i < map.size(); ++i) {
496 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
497 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
498 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
499 env->DeleteLocalRef(jkey);
500 env->DeleteLocalRef(jvalue);
501 }
502 return hashMap;
503}
504
505static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
506 List<Vector<uint8_t> > list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800507 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800508 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
509 List<Vector<uint8_t> >::iterator iter = list.begin();
510 while (iter != list.end()) {
511 jbyteArray byteArray = VectorToJByteArray(env, *iter);
512 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
513 env->DeleteLocalRef(byteArray);
514 iter++;
515 }
516
517 return arrayList;
518}
519
520} // namespace android
521
522using namespace android;
523
524static sp<JDrm> setDrm(
525 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000526 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800527 if (drm != NULL) {
528 drm->incStrong(thiz);
529 }
530 if (old != NULL) {
531 old->decStrong(thiz);
532 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000533 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800534
535 return old;
536}
537
538static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
539{
540 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700541 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800542 return false;
543 }
544
545 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700546 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800547 return false;
548 }
549 return true;
550}
551
552static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700553 sp<JDrm> drm = setDrm(env, thiz, NULL);
554 if (drm != NULL) {
555 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700556 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700557 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800558}
559
560static void android_media_MediaDrm_native_init(JNIEnv *env) {
561 jclass clazz;
562 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000563 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700564 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
565 "(Ljava/lang/Object;IILjava/lang/Object;)V");
566
567 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700568 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700569 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700570 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700571 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700572 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700573 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700574 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700575 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800576
Jeff Tinker17b89222013-05-21 12:35:06 -0700577 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
578 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
579 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
580 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
581 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
582 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
583
Jeff Tinkere4095a82014-03-04 13:17:11 -0800584 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
585 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
586 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
587 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
588
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700589 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700590 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
591 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800592
593 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700594 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
595 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800596
Jeff Tinkere4095a82014-03-04 13:17:11 -0800597 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
598 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
599 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700600 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800601
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800602 FIND_CLASS(clazz, "java/util/ArrayList");
603 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
604 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
605
606 FIND_CLASS(clazz, "java/util/HashMap");
607 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
608 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
609 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
610 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
611 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
612
613 FIND_CLASS(clazz, "java/util/Set");
614 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
615
616 FIND_CLASS(clazz, "java/util/Iterator");
617 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
618 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
619
620 FIND_CLASS(clazz, "java/util/Map$Entry");
621 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
622 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800623
624 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700625 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800626
627 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700628 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800629
630 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700631 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700632
633 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
634 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
635 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800636}
637
638static void android_media_MediaDrm_native_setup(
639 JNIEnv *env, jobject thiz,
640 jobject weak_this, jbyteArray uuidObj) {
641
642 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700643 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800644 return;
645 }
646
647 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
648
649 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700650 jniThrowException(env, "java/lang/IllegalArgumentException",
651 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800652 return;
653 }
654
655 sp<JDrm> drm = new JDrm(env, thiz, uuid.array());
656
657 status_t err = drm->initCheck();
658
659 if (err != OK) {
660 jniThrowException(
661 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700662 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800663 "Failed to instantiate drm object.");
664 return;
665 }
666
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700667 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
668 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800669 setDrm(env, thiz, drm);
670}
671
672static void android_media_MediaDrm_native_finalize(
673 JNIEnv *env, jobject thiz) {
674 android_media_MediaDrm_release(env, thiz);
675}
676
677static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800678 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800679
680 if (uuidObj == NULL) {
681 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
682 return false;
683 }
684
685 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
686
687 if (uuid.size() != 16) {
688 jniThrowException(
689 env,
690 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -0700691 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800692 return false;
693 }
694
Jeff Tinker7cda4912013-08-21 11:52:34 -0700695 String8 mimeType;
696 if (jmimeType != NULL) {
697 mimeType = JStringToString8(env, jmimeType);
698 }
699
700 return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800701}
702
703static jbyteArray android_media_MediaDrm_openSession(
704 JNIEnv *env, jobject thiz) {
705 sp<IDrm> drm = GetDrm(env, thiz);
706
707 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700708 jniThrowException(env, "java/lang/IllegalStateException",
709 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800710 return NULL;
711 }
712
713 Vector<uint8_t> sessionId;
714 status_t err = drm->openSession(sessionId);
715
716 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
717 return NULL;
718 }
719
720 return VectorToJByteArray(env, sessionId);
721}
722
723static void android_media_MediaDrm_closeSession(
724 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
725 sp<IDrm> drm = GetDrm(env, thiz);
726
727 if (!CheckSession(env, drm, jsessionId)) {
728 return;
729 }
730
731 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
732
733 status_t err = drm->closeSession(sessionId);
734
735 throwExceptionAsNecessary(env, err, "Failed to close session");
736}
737
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700738static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800739 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700740 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800741 sp<IDrm> drm = GetDrm(env, thiz);
742
743 if (!CheckSession(env, drm, jsessionId)) {
744 return NULL;
745 }
746
747 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
748
749 Vector<uint8_t> initData;
750 if (jinitData != NULL) {
751 initData = JByteArrayToVector(env, jinitData);
752 }
753
754 String8 mimeType;
755 if (jmimeType != NULL) {
756 mimeType = JStringToString8(env, jmimeType);
757 }
758
Jeff Tinker17b89222013-05-21 12:35:06 -0700759 DrmPlugin::KeyType keyType;
760 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
761 keyType = DrmPlugin::kKeyType_Streaming;
762 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
763 keyType = DrmPlugin::kKeyType_Offline;
764 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
765 keyType = DrmPlugin::kKeyType_Release;
766 } else {
767 jniThrowException(env, "java/lang/IllegalArgumentException",
768 "invalid keyType");
769 return NULL;
770 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800771
772 KeyedVector<String8, String8> optParams;
773 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200774 bool isOK;
775 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
776 if (!isOK) {
777 return NULL;
778 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800779 }
780
781 Vector<uint8_t> request;
782 String8 defaultUrl;
783
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700784 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
785 keyType, optParams, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800786
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700787 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800788 return NULL;
789 }
790
791 // Fill out return obj
792 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700793 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800794
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700795 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800796
797 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700798 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800799 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700800 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800801
802 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700803 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800804 }
805
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700806 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800807}
808
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700809static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800810 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
811 sp<IDrm> drm = GetDrm(env, thiz);
812
813 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700814 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800815 }
816
817 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
818
819 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700820 jniThrowException(env, "java/lang/IllegalArgumentException",
821 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700822 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800823 }
824 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700825 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800826
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700827 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800828
Jeff Tinker8117d8f2013-08-16 13:46:02 -0700829 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
830 return NULL;
831 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700832 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800833}
834
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700835static void android_media_MediaDrm_removeKeys(
836 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
837 sp<IDrm> drm = GetDrm(env, thiz);
838
839 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700840 jniThrowException(env, "java/lang/IllegalArgumentException",
841 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700842 return;
843 }
844
845 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
846
847 status_t err = drm->removeKeys(keySetId);
848
849 throwExceptionAsNecessary(env, err, "Failed to remove keys");
850}
851
852static void android_media_MediaDrm_restoreKeys(
853 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
854 jbyteArray jkeysetId) {
855
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800856 sp<IDrm> drm = GetDrm(env, thiz);
857
858 if (!CheckSession(env, drm, jsessionId)) {
859 return;
860 }
861
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700862 if (jkeysetId == NULL) {
863 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
864 return;
865 }
866
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800867 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700868 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800869
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700870 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800871
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700872 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800873}
874
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700875static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800876 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
877 sp<IDrm> drm = GetDrm(env, thiz);
878
879 if (!CheckSession(env, drm, jsessionId)) {
880 return NULL;
881 }
882 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
883
884 KeyedVector<String8, String8> infoMap;
885
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700886 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800887
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700888 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800889 return NULL;
890 }
891
892 return KeyedVectorToHashMap(env, infoMap);
893}
894
Jeff Tinkere4095a82014-03-04 13:17:11 -0800895static jobject android_media_MediaDrm_getProvisionRequestNative(
896 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800897 sp<IDrm> drm = GetDrm(env, thiz);
898
899 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700900 jniThrowException(env, "java/lang/IllegalStateException",
901 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800902 return NULL;
903 }
904
905 Vector<uint8_t> request;
906 String8 defaultUrl;
907
Jeff Tinkere4095a82014-03-04 13:17:11 -0800908 String8 certType;
909 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
910 certType = "X.509";
911 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
912 certType = "none";
913 } else {
914 certType = "invalid";
915 }
916
917 String8 certAuthority = JStringToString8(env, jcertAuthority);
918 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800919
920 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
921 return NULL;
922 }
923
924 // Fill out return obj
925 jclass clazz;
926 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
927
928 jobject provisionObj = NULL;
929
930 if (clazz) {
931 provisionObj = env->AllocObject(clazz);
932 jbyteArray jrequest = VectorToJByteArray(env, request);
933 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
934
935 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
936 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
937 }
938
939 return provisionObj;
940}
941
Jeff Tinkere4095a82014-03-04 13:17:11 -0800942static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800943 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
944 sp<IDrm> drm = GetDrm(env, thiz);
945
946 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700947 jniThrowException(env, "java/lang/IllegalStateException",
948 "MediaDrm obj is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800949 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800950 }
951
952 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700953 jniThrowException(env, "java/lang/IllegalArgumentException",
954 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800955 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800956 }
957
958 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800959 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800960
Jeff Tinkere4095a82014-03-04 13:17:11 -0800961 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
962
963 // Fill out return obj
964 jclass clazz = gFields.certificateClassId;
965
966 jobject certificateObj = NULL;
967
968 if (clazz && certificate.size() && wrappedKey.size()) {
969 certificateObj = env->AllocObject(clazz);
970 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
971 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
972
973 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
974 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
975 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800976
977 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800978 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800979}
980
Jeff Tinker6bf5b602014-04-30 10:02:39 -0700981static void android_media_MediaDrm_unprovisionDeviceNative(
982 JNIEnv *env, jobject thiz) {
983 sp<IDrm> drm = GetDrm(env, thiz);
984
985 if (drm == NULL) {
986 jniThrowException(env, "java/lang/IllegalStateException",
987 "MediaDrm obj is null");
988 return;
989 }
990
991 status_t err = drm->unprovisionDevice();
992
993 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
994 return;
995}
996
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800997static jobject android_media_MediaDrm_getSecureStops(
998 JNIEnv *env, jobject thiz) {
999 sp<IDrm> drm = GetDrm(env, thiz);
1000
1001 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001002 jniThrowException(env, "java/lang/IllegalStateException",
1003 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001004 return NULL;
1005 }
1006
1007 List<Vector<uint8_t> > secureStops;
1008
1009 status_t err = drm->getSecureStops(secureStops);
1010
1011 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
1012 return NULL;
1013 }
1014
1015 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1016}
1017
Jeff Tinker1b51c722014-10-31 00:54:26 -07001018static jbyteArray android_media_MediaDrm_getSecureStop(
1019 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1020 sp<IDrm> drm = GetDrm(env, thiz);
1021
1022 if (drm == NULL) {
1023 jniThrowException(env, "java/lang/IllegalStateException",
1024 "MediaDrm obj is null");
1025 return NULL;
1026 }
1027
1028 Vector<uint8_t> secureStop;
1029
1030 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1031
1032 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
1033 return NULL;
1034 }
1035
1036 return VectorToJByteArray(env, secureStop);
1037}
1038
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001039static void android_media_MediaDrm_releaseSecureStops(
1040 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1041 sp<IDrm> drm = GetDrm(env, thiz);
1042
1043 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001044 jniThrowException(env, "java/lang/IllegalStateException",
1045 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001046 return;
1047 }
1048
1049 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1050
1051 status_t err = drm->releaseSecureStops(ssRelease);
1052
1053 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
1054}
1055
Jeff Tinker1b51c722014-10-31 00:54:26 -07001056static void android_media_MediaDrm_releaseAllSecureStops(
1057 JNIEnv *env, jobject thiz) {
1058 sp<IDrm> drm = GetDrm(env, thiz);
1059
1060 if (drm == NULL) {
1061 jniThrowException(env, "java/lang/IllegalStateException",
1062 "MediaDrm obj is null");
1063 return;
1064 }
1065
1066 status_t err = drm->releaseAllSecureStops();
1067
1068 throwExceptionAsNecessary(env, err, "Failed to release all secure stops");
1069}
1070
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001071static jstring android_media_MediaDrm_getPropertyString(
1072 JNIEnv *env, jobject thiz, jstring jname) {
1073 sp<IDrm> drm = GetDrm(env, thiz);
1074
1075 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001076 jniThrowException(env, "java/lang/IllegalStateException",
1077 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001078 return NULL;
1079 }
1080
1081 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001082 jniThrowException(env, "java/lang/IllegalArgumentException",
1083 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001084 return NULL;
1085 }
1086
1087 String8 name = JStringToString8(env, jname);
1088 String8 value;
1089
1090 status_t err = drm->getPropertyString(name, value);
1091
1092 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1093 return NULL;
1094 }
1095
1096 return env->NewStringUTF(value.string());
1097}
1098
1099static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1100 JNIEnv *env, jobject thiz, jstring jname) {
1101 sp<IDrm> drm = GetDrm(env, thiz);
1102
1103 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001104 jniThrowException(env, "java/lang/IllegalStateException",
1105 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001106 return NULL;
1107 }
1108
1109 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001110 jniThrowException(env, "java/lang/IllegalArgumentException",
1111 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001112 return NULL;
1113 }
1114
1115 String8 name = JStringToString8(env, jname);
1116 Vector<uint8_t> value;
1117
1118 status_t err = drm->getPropertyByteArray(name, value);
1119
1120 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1121 return NULL;
1122 }
1123
1124 return VectorToJByteArray(env, value);
1125}
1126
1127static void android_media_MediaDrm_setPropertyString(
1128 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1129 sp<IDrm> drm = GetDrm(env, thiz);
1130
1131 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001132 jniThrowException(env, "java/lang/IllegalStateException",
1133 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001134 return;
1135 }
1136
Jeff Tinkereada5372013-05-21 12:48:14 -07001137 if (jname == NULL) {
1138 jniThrowException(env, "java/lang/IllegalArgumentException",
1139 "property name String is null");
1140 return;
1141 }
1142
1143 if (jvalue == NULL) {
1144 jniThrowException(env, "java/lang/IllegalArgumentException",
1145 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001146 return;
1147 }
1148
1149 String8 name = JStringToString8(env, jname);
1150 String8 value = JStringToString8(env, jvalue);
1151
1152 status_t err = drm->setPropertyString(name, value);
1153
1154 throwExceptionAsNecessary(env, err, "Failed to set property");
1155}
1156
1157static void android_media_MediaDrm_setPropertyByteArray(
1158 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1159 sp<IDrm> drm = GetDrm(env, thiz);
1160
1161 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001162 jniThrowException(env, "java/lang/IllegalStateException",
1163 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001164 return;
1165 }
1166
Jeff Tinkereada5372013-05-21 12:48:14 -07001167 if (jname == NULL) {
1168 jniThrowException(env, "java/lang/IllegalArgumentException",
1169 "property name String is null");
1170 return;
1171 }
1172
1173 if (jvalue == NULL) {
1174 jniThrowException(env, "java/lang/IllegalArgumentException",
1175 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001176 return;
1177 }
1178
1179 String8 name = JStringToString8(env, jname);
1180 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1181
1182 status_t err = drm->setPropertyByteArray(name, value);
1183
1184 throwExceptionAsNecessary(env, err, "Failed to set property");
1185}
1186
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001187static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001188 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001189 jstring jalgorithm) {
1190
1191 sp<IDrm> drm = GetDrm(env, jdrm);
1192
1193 if (!CheckSession(env, drm, jsessionId)) {
1194 return;
1195 }
1196
1197 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001198 jniThrowException(env, "java/lang/IllegalArgumentException",
1199 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001200 return;
1201 }
1202
1203 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1204 String8 algorithm = JStringToString8(env, jalgorithm);
1205
1206 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1207
1208 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
1209}
1210
1211static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001212 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001213 jstring jalgorithm) {
1214
1215 sp<IDrm> drm = GetDrm(env, jdrm);
1216
1217 if (!CheckSession(env, drm, jsessionId)) {
1218 return;
1219 }
1220
1221 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001222 jniThrowException(env, "java/lang/IllegalArgumentException",
1223 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001224 return;
1225 }
1226
1227 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1228 String8 algorithm = JStringToString8(env, jalgorithm);
1229
1230 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1231
1232 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1233}
1234
1235
1236static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001237 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001238 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1239
1240 sp<IDrm> drm = GetDrm(env, jdrm);
1241
1242 if (!CheckSession(env, drm, jsessionId)) {
1243 return NULL;
1244 }
1245
1246 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001247 jniThrowException(env, "java/lang/IllegalArgumentException",
1248 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001249 return NULL;
1250 }
1251
1252 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1253 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1254 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1255 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1256 Vector<uint8_t> output;
1257
1258 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1259
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001260 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
1261 return NULL;
1262 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001263
1264 return VectorToJByteArray(env, output);
1265}
1266
1267static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001268 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001269 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1270
1271 sp<IDrm> drm = GetDrm(env, jdrm);
1272
1273 if (!CheckSession(env, drm, jsessionId)) {
1274 return NULL;
1275 }
1276
1277 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001278 jniThrowException(env, "java/lang/IllegalArgumentException",
1279 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001280 return NULL;
1281 }
1282
1283 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1284 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1285 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1286 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1287 Vector<uint8_t> output;
1288
1289 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001290 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
1291 return NULL;
1292 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001293
1294 return VectorToJByteArray(env, output);
1295}
1296
1297static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001298 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001299 jbyteArray jkeyId, jbyteArray jmessage) {
1300
1301 sp<IDrm> drm = GetDrm(env, jdrm);
1302
1303 if (!CheckSession(env, drm, jsessionId)) {
1304 return NULL;
1305 }
1306
1307 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001308 jniThrowException(env, "java/lang/IllegalArgumentException",
1309 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001310 return NULL;
1311 }
1312
1313 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1314 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1315 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1316 Vector<uint8_t> signature;
1317
1318 status_t err = drm->sign(sessionId, keyId, message, signature);
1319
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001320 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1321 return NULL;
1322 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001323
1324 return VectorToJByteArray(env, signature);
1325}
1326
1327static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001328 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001329 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1330
1331 sp<IDrm> drm = GetDrm(env, jdrm);
1332
1333 if (!CheckSession(env, drm, jsessionId)) {
1334 return false;
1335 }
1336
1337 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001338 jniThrowException(env, "java/lang/IllegalArgumentException",
1339 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001340 return false;
1341 }
1342
1343 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1344 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1345 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1346 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1347 bool match;
1348
1349 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1350
1351 throwExceptionAsNecessary(env, err, "Failed to verify");
1352 return match;
1353}
1354
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001355
Jeff Tinkere4095a82014-03-04 13:17:11 -08001356static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001357 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001358 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1359
1360 sp<IDrm> drm = GetDrm(env, jdrm);
1361
1362 if (!CheckSession(env, drm, jsessionId)) {
1363 return NULL;
1364 }
1365
1366 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1367 jniThrowException(env, "java/lang/IllegalArgumentException",
1368 "required argument is null");
1369 return NULL;
1370 }
1371
1372 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1373 String8 algorithm = JStringToString8(env, jalgorithm);
1374 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1375 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1376 Vector<uint8_t> signature;
1377
1378 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1379
1380 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1381 return NULL;
1382 }
1383
1384 return VectorToJByteArray(env, signature);
1385}
1386
1387
Daniel Micay76f6a862015-09-19 17:31:01 -04001388static const JNINativeMethod gMethods[] = {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001389 { "release", "()V", (void *)android_media_MediaDrm_release },
1390 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
1391
1392 { "native_setup", "(Ljava/lang/Object;[B)V",
1393 (void *)android_media_MediaDrm_native_setup },
1394
1395 { "native_finalize", "()V",
1396 (void *)android_media_MediaDrm_native_finalize },
1397
Jeff Tinker7cda4912013-08-21 11:52:34 -07001398 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001399 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
1400
1401 { "openSession", "()[B",
1402 (void *)android_media_MediaDrm_openSession },
1403
1404 { "closeSession", "([B)V",
1405 (void *)android_media_MediaDrm_closeSession },
1406
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001407 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
1408 "Landroid/media/MediaDrm$KeyRequest;",
1409 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001410
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001411 { "provideKeyResponse", "([B[B)[B",
1412 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001413
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001414 { "removeKeys", "([B)V",
1415 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001416
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001417 { "restoreKeys", "([B[B)V",
1418 (void *)android_media_MediaDrm_restoreKeys },
1419
1420 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
1421 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001422
Jeff Tinkere4095a82014-03-04 13:17:11 -08001423 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
1424 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001425
Jeff Tinkere4095a82014-03-04 13:17:11 -08001426 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
1427 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001428
Jeff Tinker6bf5b602014-04-30 10:02:39 -07001429 { "unprovisionDevice", "()V",
1430 (void *)android_media_MediaDrm_unprovisionDeviceNative },
1431
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001432 { "getSecureStops", "()Ljava/util/List;",
1433 (void *)android_media_MediaDrm_getSecureStops },
1434
Jeff Tinker1b51c722014-10-31 00:54:26 -07001435 { "getSecureStop", "([B)[B",
1436 (void *)android_media_MediaDrm_getSecureStop },
1437
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001438 { "releaseSecureStops", "([B)V",
1439 (void *)android_media_MediaDrm_releaseSecureStops },
1440
Jeff Tinker1b51c722014-10-31 00:54:26 -07001441 { "releaseAllSecureStops", "()V",
1442 (void *)android_media_MediaDrm_releaseAllSecureStops },
1443
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001444 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
1445 (void *)android_media_MediaDrm_getPropertyString },
1446
1447 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
1448 (void *)android_media_MediaDrm_getPropertyByteArray },
1449
1450 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
1451 (void *)android_media_MediaDrm_setPropertyString },
1452
1453 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
1454 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001455
1456 { "setCipherAlgorithmNative",
1457 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1458 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
1459
1460 { "setMacAlgorithmNative",
1461 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1462 (void *)android_media_MediaDrm_setMacAlgorithmNative },
1463
1464 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1465 (void *)android_media_MediaDrm_encryptNative },
1466
1467 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1468 (void *)android_media_MediaDrm_decryptNative },
1469
1470 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
1471 (void *)android_media_MediaDrm_signNative },
1472
1473 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
1474 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08001475
1476 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
1477 (void *)android_media_MediaDrm_signRSANative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001478};
1479
1480int register_android_media_Drm(JNIEnv *env) {
1481 return AndroidRuntime::registerNativeMethods(env,
1482 "android/media/MediaDrm", gMethods, NELEM(gMethods));
1483}