1 /*
2 * Copyright 2013, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MediaDrm-JNI"
19 #include <utils/Log.h>
20
21 #include "android_media_MediaDrm.h"
22 #include "android_media_MediaMetricsJNI.h"
23 #include "android_os_Parcel.h"
24 #include "android_runtime/AndroidRuntime.h"
25 #include "android_runtime/Log.h"
26 #include "android_os_Parcel.h"
27 #include "jni.h"
28 #include <nativehelper/JNIHelp.h>
29
30 #include <android/hardware/drm/1.3/IDrmFactory.h>
31 #include <binder/Parcel.h>
32 #include <binder/PersistableBundle.h>
33 #include <cutils/properties.h>
34 #include <media/stagefright/foundation/ADebug.h>
35 #include <media/stagefright/MediaErrors.h>
36 #include <mediadrm/DrmMetricsConsumer.h>
37 #include <mediadrm/DrmUtils.h>
38 #include <mediadrm/IDrmMetricsConsumer.h>
39 #include <mediadrm/IDrm.h>
40
41 using ::android::os::PersistableBundle;
42 namespace drm = ::android::hardware::drm;
43
44 namespace android {
45
46 #define FIND_CLASS(var, className) \
47 var = env->FindClass(className); \
48 LOG_FATAL_IF(! (var), "Unable to find class %s", className);
49
50 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
51 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
52 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
53
54 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
55 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
56 LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName);
57
58 #define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
59 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
60 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
61
62 #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
63 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
64 LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName);
65
66 #define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \
67 var = env->GetStaticObjectField(clazz, fieldId); \
68 LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId);
69
70
71 struct RequestFields {
72 jfieldID data;
73 jfieldID defaultUrl;
74 jfieldID requestType;
75 };
76
77 struct ArrayListFields {
78 jmethodID init;
79 jmethodID add;
80 };
81
82 struct HashmapFields {
83 jmethodID init;
84 jmethodID get;
85 jmethodID put;
86 jmethodID entrySet;
87 };
88
89 struct SetFields {
90 jmethodID iterator;
91 };
92
93 struct IteratorFields {
94 jmethodID next;
95 jmethodID hasNext;
96 };
97
98 struct EntryFields {
99 jmethodID getKey;
100 jmethodID getValue;
101 };
102
103 struct EventTypes {
104 jint kEventProvisionRequired;
105 jint kEventKeyRequired;
106 jint kEventKeyExpired;
107 jint kEventVendorDefined;
108 jint kEventSessionReclaimed;
109 } gEventTypes;
110
111 struct EventWhat {
112 jint kWhatDrmEvent;
113 jint kWhatExpirationUpdate;
114 jint kWhatKeyStatusChange;
115 jint kWhatSessionLostState;
116 } gEventWhat;
117
118 struct KeyTypes {
119 jint kKeyTypeStreaming;
120 jint kKeyTypeOffline;
121 jint kKeyTypeRelease;
122 } gKeyTypes;
123
124 struct KeyRequestTypes {
125 jint kKeyRequestTypeInitial;
126 jint kKeyRequestTypeRenewal;
127 jint kKeyRequestTypeRelease;
128 jint kKeyRequestTypeNone;
129 jint kKeyRequestTypeUpdate;
130 } gKeyRequestTypes;
131
132 struct CertificateTypes {
133 jint kCertificateTypeNone;
134 jint kCertificateTypeX509;
135 } gCertificateTypes;
136
137 struct CertificateFields {
138 jfieldID wrappedPrivateKey;
139 jfieldID certificateData;
140 };
141
142 struct StateExceptionFields {
143 jmethodID init;
144 jclass classId;
145 };
146
147 struct SessionExceptionFields {
148 jmethodID init;
149 jclass classId;
150 jfieldID errorCode;
151 };
152
153 struct SessionExceptionErrorCodes {
154 jint kErrorUnknown;
155 jint kResourceContention;
156 } gSessionExceptionErrorCodes;
157
158 struct HDCPLevels {
159 jint kHdcpLevelUnknown;
160 jint kHdcpNone;
161 jint kHdcpV1;
162 jint kHdcpV2;
163 jint kHdcpV2_1;
164 jint kHdcpV2_2;
165 jint kHdcpV2_3;
166 jint kHdcpNoOutput;
167 } gHdcpLevels;
168
169 struct SecurityLevels {
170 jint kSecurityLevelUnknown;
171 jint kSecurityLevelMax;
172 jint kSecurityLevelSwSecureCrypto;
173 jint kSecurityLevelSwSecureDecode;
174 jint kSecurityLevelHwSecureCrypto;
175 jint kSecurityLevelHwSecureDecode;
176 jint kSecurityLevelHwSecureAll;
177 } gSecurityLevels;
178
179 struct OfflineLicenseState {
180 jint kOfflineLicenseStateUsable;
181 jint kOfflineLicenseStateReleased;
182 jint kOfflineLicenseStateUnknown;
183 } gOfflineLicenseStates;
184
185 struct KeyStatusFields {
186 jmethodID init;
187 jclass classId;
188 };
189
190 struct fields_t {
191 jfieldID context;
192 jmethodID post_event;
193 RequestFields keyRequest;
194 RequestFields provisionRequest;
195 ArrayListFields arraylist;
196 HashmapFields hashmap;
197 SetFields set;
198 IteratorFields iterator;
199 EntryFields entry;
200 CertificateFields certificate;
201 StateExceptionFields stateException;
202 SessionExceptionFields sessionException;
203 jclass certificateClassId;
204 jclass hashmapClassId;
205 jclass arraylistClassId;
206 jclass stringClassId;
207 jobject bundleCreator;
208 jmethodID createFromParcelId;
209 jclass parcelCreatorClassId;
210 KeyStatusFields keyStatus;
211 };
212
213 static fields_t gFields;
214
215 namespace {
216
hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> & vector)217 jbyteArray hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> &vector) {
218 JNIEnv *env = AndroidRuntime::getJNIEnv();
219 size_t length = vector.size();
220 jbyteArray result = env->NewByteArray(length);
221 if (result != NULL) {
222 env->SetByteArrayRegion(result, 0, length, reinterpret_cast<const jbyte *>(vector.data()));
223 }
224 return result;
225 }
226
227 } // namespace anonymous
228
229 // ----------------------------------------------------------------------------
230 // ref-counted object for callbacks
231 class JNIDrmListener: public DrmListener
232 {
233 public:
234 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
235 ~JNIDrmListener();
236 virtual void notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *arg = NULL);
237 private:
238 JNIDrmListener();
239 jclass mClass; // Reference to MediaDrm class
240 jobject mObject; // Weak ref to MediaDrm Java object to call on
241 };
242
JNIDrmListener(JNIEnv * env,jobject thiz,jobject weak_thiz)243 JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
244 {
245 // Hold onto the MediaDrm class for use in calling the static method
246 // that posts events to the application thread.
247 jclass clazz = env->GetObjectClass(thiz);
248 if (clazz == NULL) {
249 ALOGE("Can't find android/media/MediaDrm");
250 jniThrowException(env, "java/lang/Exception",
251 "Can't find android/media/MediaDrm");
252 return;
253 }
254 mClass = (jclass)env->NewGlobalRef(clazz);
255
256 // We use a weak reference so the MediaDrm object can be garbage collected.
257 // The reference is only used as a proxy for callbacks.
258 mObject = env->NewGlobalRef(weak_thiz);
259 }
260
~JNIDrmListener()261 JNIDrmListener::~JNIDrmListener()
262 {
263 // remove global references
264 JNIEnv *env = AndroidRuntime::getJNIEnv();
265 env->DeleteGlobalRef(mObject);
266 env->DeleteGlobalRef(mClass);
267 }
268
notify(DrmPlugin::EventType eventType,int extra,const ListenerArgs * args)269 void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
270 const ListenerArgs *args)
271 {
272 jint jwhat;
273 jint jeventType = 0;
274
275 // translate DrmPlugin event types into their java equivalents
276 switch (eventType) {
277 case DrmPlugin::kDrmPluginEventProvisionRequired:
278 jwhat = gEventWhat.kWhatDrmEvent;
279 jeventType = gEventTypes.kEventProvisionRequired;
280 break;
281 case DrmPlugin::kDrmPluginEventKeyNeeded:
282 jwhat = gEventWhat.kWhatDrmEvent;
283 jeventType = gEventTypes.kEventKeyRequired;
284 break;
285 case DrmPlugin::kDrmPluginEventKeyExpired:
286 jwhat = gEventWhat.kWhatDrmEvent;
287 jeventType = gEventTypes.kEventKeyExpired;
288 break;
289 case DrmPlugin::kDrmPluginEventVendorDefined:
290 jwhat = gEventWhat.kWhatDrmEvent;
291 jeventType = gEventTypes.kEventVendorDefined;
292 break;
293 case DrmPlugin::kDrmPluginEventSessionReclaimed:
294 jwhat = gEventWhat.kWhatDrmEvent;
295 jeventType = gEventTypes.kEventSessionReclaimed;
296 break;
297 case DrmPlugin::kDrmPluginEventExpirationUpdate:
298 jwhat = gEventWhat.kWhatExpirationUpdate;
299 break;
300 case DrmPlugin::kDrmPluginEventKeysChange:
301 jwhat = gEventWhat.kWhatKeyStatusChange;
302 break;
303 case DrmPlugin::kDrmPluginEventSessionLostState:
304 jwhat = gEventWhat.kWhatSessionLostState;
305 break;
306 default:
307 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
308 return;
309 }
310
311 JNIEnv *env = AndroidRuntime::getJNIEnv();
312 if (args) {
313 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
314 jwhat, jeventType, extra,
315 args->jSessionId, args->jData, args->jExpirationTime,
316 args->jKeyStatusList, args->jHasNewUsableKey);
317 }
318
319 if (env->ExceptionCheck()) {
320 ALOGW("An exception occurred while notifying an event.");
321 LOGW_EX(env);
322 env->ExceptionClear();
323 }
324 }
325
throwStateException(JNIEnv * env,const char * msg,status_t err)326 static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
327 ALOGE("Illegal state exception: %s (%d)", msg, err);
328
329 jobject exception = env->NewObject(gFields.stateException.classId,
330 gFields.stateException.init, static_cast<int>(err),
331 env->NewStringUTF(msg));
332 env->Throw(static_cast<jthrowable>(exception));
333 }
334
throwSessionException(JNIEnv * env,const char * msg,status_t err)335 static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
336 ALOGE("Session exception: %s (%d)", msg, err);
337
338 jint jErrorCode = 0;
339 switch(err) {
340 case ERROR_DRM_RESOURCE_CONTENTION:
341 jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
342 break;
343 default:
344 break;
345 }
346
347 jobject exception = env->NewObject(gFields.sessionException.classId,
348 gFields.sessionException.init, static_cast<int>(err),
349 env->NewStringUTF(msg));
350
351 env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
352 env->Throw(static_cast<jthrowable>(exception));
353 }
354
isSessionException(status_t err)355 static bool isSessionException(status_t err) {
356 return err == ERROR_DRM_RESOURCE_CONTENTION;
357 }
358
throwExceptionAsNecessary(JNIEnv * env,status_t err,const char * msg=NULL)359 static bool throwExceptionAsNecessary(
360 JNIEnv *env, status_t err, const char *msg = NULL) {
361
362 const char *drmMessage = NULL;
363
364 switch (err) {
365 case ERROR_DRM_UNKNOWN:
366 drmMessage = "General DRM error";
367 break;
368 case ERROR_DRM_NO_LICENSE:
369 drmMessage = "No license";
370 break;
371 case ERROR_DRM_LICENSE_EXPIRED:
372 drmMessage = "License expired";
373 break;
374 case ERROR_DRM_SESSION_NOT_OPENED:
375 drmMessage = "Session not opened";
376 break;
377 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
378 drmMessage = "Not initialized";
379 break;
380 case ERROR_DRM_DECRYPT:
381 drmMessage = "Decrypt error";
382 break;
383 case ERROR_DRM_CANNOT_HANDLE:
384 drmMessage = "Invalid parameter or data format";
385 break;
386 case ERROR_DRM_INVALID_STATE:
387 drmMessage = "Invalid state";
388 break;
389 default:
390 break;
391 }
392
393 String8 vendorMessage;
394 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
395 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
396 drmMessage = vendorMessage.string();
397 }
398
399 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
400 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
401 return true;
402 } else if (err == ERROR_UNSUPPORTED) {
403 jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
404 return true;
405 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
406 jniThrowException(env, "android/media/NotProvisionedException", msg);
407 return true;
408 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
409 jniThrowException(env, "android/media/ResourceBusyException", msg);
410 return true;
411 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
412 jniThrowException(env, "android/media/DeniedByServerException", msg);
413 return true;
414 } else if (err == DEAD_OBJECT) {
415 jniThrowException(env, "android/media/MediaDrmResetException",
416 "mediaserver died");
417 return true;
418 } else if (isSessionException(err)) {
419 throwSessionException(env, msg, err);
420 return true;
421 } else if (err != OK) {
422 String8 errbuf;
423 if (drmMessage != NULL) {
424 if (msg == NULL) {
425 msg = drmMessage;
426 } else {
427 errbuf = String8::format("%s: %s", msg, drmMessage);
428 msg = errbuf.string();
429 }
430 }
431 throwStateException(env, msg, err);
432 return true;
433 }
434 return false;
435 }
436
GetDrm(JNIEnv * env,jobject thiz)437 static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
438 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
439 return jdrm ? jdrm->getDrm() : NULL;
440 }
441
JDrm(JNIEnv * env,jobject thiz,const uint8_t uuid[16],const String8 & appPackageName)442 JDrm::JDrm(
443 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
444 const String8 &appPackageName) {
445 mObject = env->NewWeakGlobalRef(thiz);
446 mDrm = MakeDrm(uuid, appPackageName);
447 if (mDrm != NULL) {
448 mDrm->setListener(this);
449 }
450 }
451
~JDrm()452 JDrm::~JDrm() {
453 JNIEnv *env = AndroidRuntime::getJNIEnv();
454
455 env->DeleteWeakGlobalRef(mObject);
456 mObject = NULL;
457 }
458
459 // static
MakeDrm()460 sp<IDrm> JDrm::MakeDrm() {
461 return DrmUtils::MakeDrm();
462 }
463
464 // static
MakeDrm(const uint8_t uuid[16],const String8 & appPackageName)465 sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
466 sp<IDrm> drm = MakeDrm();
467
468 if (drm == NULL) {
469 return NULL;
470 }
471
472 status_t err = drm->createPlugin(uuid, appPackageName);
473
474 if (err != OK) {
475 return NULL;
476 }
477
478 return drm;
479 }
480
setListener(const sp<DrmListener> & listener)481 status_t JDrm::setListener(const sp<DrmListener>& listener) {
482 Mutex::Autolock lock(mLock);
483 mListener = listener;
484 return OK;
485 }
486
notify(DrmPlugin::EventType eventType,int extra,const ListenerArgs * args)487 void JDrm::notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *args) {
488 sp<DrmListener> listener;
489 mLock.lock();
490 listener = mListener;
491 mLock.unlock();
492
493 if (listener != NULL) {
494 Mutex::Autolock lock(mNotifyLock);
495 listener->notify(eventType, extra, args);
496 }
497 }
498
sendEvent(DrmPlugin::EventType eventType,const hardware::hidl_vec<uint8_t> & sessionId,const hardware::hidl_vec<uint8_t> & data)499 void JDrm::sendEvent(
500 DrmPlugin::EventType eventType,
501 const hardware::hidl_vec<uint8_t> &sessionId,
502 const hardware::hidl_vec<uint8_t> &data) {
503 ListenerArgs args{
504 .jSessionId = hidlVectorToJByteArray(sessionId),
505 .jData = hidlVectorToJByteArray(data),
506 };
507 notify(eventType, 0, &args);
508 }
509
sendExpirationUpdate(const hardware::hidl_vec<uint8_t> & sessionId,int64_t expiryTimeInMS)510 void JDrm::sendExpirationUpdate(
511 const hardware::hidl_vec<uint8_t> &sessionId,
512 int64_t expiryTimeInMS) {
513 ListenerArgs args{
514 .jSessionId = hidlVectorToJByteArray(sessionId),
515 .jExpirationTime = expiryTimeInMS,
516 };
517 notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &args);
518 }
519
sendKeysChange(const hardware::hidl_vec<uint8_t> & sessionId,const std::vector<DrmKeyStatus> & keyStatusList,bool hasNewUsableKey)520 void JDrm::sendKeysChange(
521 const hardware::hidl_vec<uint8_t> &sessionId,
522 const std::vector<DrmKeyStatus> &keyStatusList,
523 bool hasNewUsableKey) {
524 JNIEnv *env = AndroidRuntime::getJNIEnv();
525 jclass clazz = gFields.arraylistClassId;
526 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
527 clazz = gFields.keyStatus.classId;
528 for (const auto &keyStatus : keyStatusList) {
529 jbyteArray jKeyId(hidlVectorToJByteArray(keyStatus.keyId));
530 jint jStatusCode(keyStatus.type);
531 jobject jKeyStatus = env->NewObject(clazz, gFields.keyStatus.init, jKeyId, jStatusCode);
532 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jKeyStatus);
533 }
534 ListenerArgs args{
535 .jSessionId = hidlVectorToJByteArray(sessionId),
536 .jKeyStatusList = arrayList,
537 .jHasNewUsableKey = hasNewUsableKey,
538 };
539 notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &args);
540 }
541
sendSessionLostState(const hardware::hidl_vec<uint8_t> & sessionId)542 void JDrm::sendSessionLostState(
543 const hardware::hidl_vec<uint8_t> &sessionId) {
544 ListenerArgs args{
545 .jSessionId = hidlVectorToJByteArray(sessionId),
546 };
547 notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &args);
548 }
549
disconnect()550 void JDrm::disconnect() {
551 if (mDrm != NULL) {
552 mDrm->destroyPlugin();
553 mDrm.clear();
554 }
555 }
556
557
558 // static
IsCryptoSchemeSupported(const uint8_t uuid[16],const String8 & mimeType,DrmPlugin::SecurityLevel securityLevel,bool * isSupported)559 status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
560 DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
561 sp<IDrm> drm = MakeDrm();
562
563 if (drm == NULL) {
564 return BAD_VALUE;
565 }
566
567 return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
568 }
569
initCheck() const570 status_t JDrm::initCheck() const {
571 return mDrm == NULL ? NO_INIT : OK;
572 }
573
574 // JNI conversion utilities
JByteArrayToVector(JNIEnv * env,jbyteArray const & byteArray)575 static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
576 Vector<uint8_t> vector;
577 size_t length = env->GetArrayLength(byteArray);
578 vector.insertAt((size_t)0, length);
579 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
580 return vector;
581 }
582
VectorToJByteArray(JNIEnv * env,Vector<uint8_t> const & vector)583 static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
584 size_t length = vector.size();
585 jbyteArray result = env->NewByteArray(length);
586 if (result != NULL) {
587 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
588 }
589 return result;
590 }
591
JStringToString8(JNIEnv * env,jstring const & jstr)592 static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
593 String8 result;
594
595 const char *s = env->GetStringUTFChars(jstr, NULL);
596 if (s) {
597 result = s;
598 env->ReleaseStringUTFChars(jstr, s);
599 }
600 return result;
601 }
602
603 /*
604 import java.util.HashMap;
605 import java.util.Set;
606 import java.Map.Entry;
607 import jav.util.Iterator;
608
609 HashMap<k, v> hm;
610 Set<Entry<k, v>> s = hm.entrySet();
611 Iterator i = s.iterator();
612 Entry e = s.next();
613 */
614
HashMapToKeyedVector(JNIEnv * env,jobject & hashMap,bool * pIsOK)615 static KeyedVector<String8, String8> HashMapToKeyedVector(
616 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
617 jclass clazz = gFields.stringClassId;
618 KeyedVector<String8, String8> keyedVector;
619 *pIsOK = true;
620
621 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
622 if (entrySet) {
623 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
624 if (iterator) {
625 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
626 while (hasNext) {
627 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
628 if (entry) {
629 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
630 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
631 jniThrowException(env, "java/lang/IllegalArgumentException",
632 "HashMap key is not a String");
633 env->DeleteLocalRef(entry);
634 *pIsOK = false;
635 break;
636 }
637 jstring jkey = static_cast<jstring>(obj);
638
639 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
640 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
641 jniThrowException(env, "java/lang/IllegalArgumentException",
642 "HashMap value is not a String");
643 env->DeleteLocalRef(entry);
644 *pIsOK = false;
645 break;
646 }
647 jstring jvalue = static_cast<jstring>(obj);
648
649 String8 key = JStringToString8(env, jkey);
650 String8 value = JStringToString8(env, jvalue);
651 keyedVector.add(key, value);
652
653 env->DeleteLocalRef(jkey);
654 env->DeleteLocalRef(jvalue);
655 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
656 }
657 env->DeleteLocalRef(entry);
658 }
659 env->DeleteLocalRef(iterator);
660 }
661 env->DeleteLocalRef(entrySet);
662 }
663 return keyedVector;
664 }
665
KeyedVectorToHashMap(JNIEnv * env,KeyedVector<String8,String8> const & map)666 static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
667 jclass clazz = gFields.hashmapClassId;
668 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
669 for (size_t i = 0; i < map.size(); ++i) {
670 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
671 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
672 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
673 env->DeleteLocalRef(jkey);
674 env->DeleteLocalRef(jvalue);
675 }
676 return hashMap;
677 }
678
ListOfVectorsToArrayListOfByteArray(JNIEnv * env,List<Vector<uint8_t>> list)679 static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
680 List<Vector<uint8_t>> list) {
681 jclass clazz = gFields.arraylistClassId;
682 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
683 List<Vector<uint8_t>>::iterator iter = list.begin();
684 while (iter != list.end()) {
685 jbyteArray byteArray = VectorToJByteArray(env, *iter);
686 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
687 env->DeleteLocalRef(byteArray);
688 iter++;
689 }
690
691 return arrayList;
692 }
693
694 } // namespace android
695
696 using namespace android;
697
setDrm(JNIEnv * env,jobject thiz,const sp<JDrm> & drm)698 static sp<JDrm> setDrm(
699 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
700 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
701 if (drm != NULL) {
702 drm->incStrong(thiz);
703 }
704 if (old != NULL) {
705 old->decStrong(thiz);
706 }
707 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
708
709 return old;
710 }
711
CheckDrm(JNIEnv * env,const sp<IDrm> & drm)712 static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
713 if (drm == NULL) {
714 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
715 return false;
716 }
717 return true;
718 }
719
CheckSession(JNIEnv * env,const sp<IDrm> & drm,jbyteArray const & jsessionId)720 static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
721 {
722 if (!CheckDrm(env, drm)) {
723 return false;
724 }
725
726 if (jsessionId == NULL) {
727 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
728 return false;
729 }
730 return true;
731 }
732
android_media_MediaDrm_native_release(JNIEnv * env,jobject thiz)733 static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
734 sp<JDrm> drm = setDrm(env, thiz, NULL);
735 if (drm != NULL) {
736 drm->setListener(NULL);
737 drm->disconnect();
738 }
739 }
740
android_media_MediaDrm_native_init(JNIEnv * env)741 static void android_media_MediaDrm_native_init(JNIEnv *env) {
742 jclass clazz;
743 FIND_CLASS(clazz, "android/media/MediaDrm");
744 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
745 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
746 "(Ljava/lang/Object;III[B[BJLjava/util/List;Z)V");
747
748 jfieldID field;
749 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
750 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
751 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
752 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
753 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
754 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
755 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
756 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
757 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
758 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
759
760 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
761 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
762 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
763 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
764 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
765 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
766 GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
767 gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
768
769 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
770 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
771 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
772 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
773 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
774 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
775
776 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
777 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
778 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
779 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
780
781 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
782 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
783 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
784 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
785 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
786 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
787 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
788 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
789 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
790 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
791 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
792 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
793 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I");
794 gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field);
795 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
796 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
797
798 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
799 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
800 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
801 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
802 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
803 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
804 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
805 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
806 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
807 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
808 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
809 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
810
811 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I");
812 gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
813 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I");
814 gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field);
815 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
816 gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
817
818 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
819
820 jmethodID getMaxSecurityLevel;
821 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
822 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
823
824 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
825 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
826 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
827 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
828
829 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
830 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
831 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
832 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
833 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
834 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
835 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
836 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
837 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
838 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
839
840 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
841 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
842 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
843
844 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
845 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
846 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
847 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
848
849 // Metrics-related fields and classes.
850 FIND_CLASS(clazz, "android/os/PersistableBundle");
851 jfieldID bundleCreatorId;
852 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
853 "Landroid/os/Parcelable$Creator;");
854 jobject bundleCreator;
855 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
856 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
857 FIND_CLASS(clazz, "android/os/Parcelable$Creator");
858 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
859 "(Landroid/os/Parcel;)Ljava/lang/Object;");
860 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
861
862 FIND_CLASS(clazz, "java/util/ArrayList");
863 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
864 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
865
866 FIND_CLASS(clazz, "java/util/HashMap");
867 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
868 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
869 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
870 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
871 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
872
873 FIND_CLASS(clazz, "java/util/Set");
874 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
875
876 FIND_CLASS(clazz, "java/util/Iterator");
877 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
878 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
879
880 FIND_CLASS(clazz, "java/util/Map$Entry");
881 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
882 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
883
884 FIND_CLASS(clazz, "java/util/HashMap");
885 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
886
887 FIND_CLASS(clazz, "java/lang/String");
888 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
889
890 FIND_CLASS(clazz, "java/util/ArrayList");
891 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
892
893 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
894 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
895 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
896
897 FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
898 GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
899 gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
900 GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
901
902 GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I");
903 gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
904 GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
905 gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
906
907 FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
908 gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
909 GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
910 }
911
android_media_MediaDrm_native_setup(JNIEnv * env,jobject thiz,jobject weak_this,jbyteArray uuidObj,jstring jappPackageName)912 static void android_media_MediaDrm_native_setup(
913 JNIEnv *env, jobject thiz,
914 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
915
916 if (uuidObj == NULL) {
917 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
918 return;
919 }
920
921 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
922
923 if (uuid.size() != 16) {
924 jniThrowException(env, "java/lang/IllegalArgumentException",
925 "invalid UUID size, expected 16 bytes");
926 return;
927 }
928
929 String8 packageName;
930 if (jappPackageName == NULL) {
931 jniThrowException(env, "java/lang/IllegalArgumentException",
932 "application package name cannot be null");
933 return;
934 }
935
936 packageName = JStringToString8(env, jappPackageName);
937 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
938
939 status_t err = drm->initCheck();
940
941 if (err != OK) {
942 jniThrowException(
943 env,
944 "android/media/UnsupportedSchemeException",
945 "Failed to instantiate drm object.");
946 return;
947 }
948
949 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
950 drm->setListener(listener);
951 setDrm(env, thiz, drm);
952 }
953
jintToSecurityLevel(jint jlevel)954 DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
955 DrmPlugin::SecurityLevel level;
956
957 if (jlevel == gSecurityLevels.kSecurityLevelMax) {
958 level = DrmPlugin::kSecurityLevelMax;
959 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
960 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
961 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
962 level = DrmPlugin::kSecurityLevelSwSecureDecode;
963 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
964 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
965 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
966 level = DrmPlugin::kSecurityLevelHwSecureDecode;
967 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
968 level = DrmPlugin::kSecurityLevelHwSecureAll;
969 } else {
970 level = DrmPlugin::kSecurityLevelUnknown;
971 }
972 return level;
973 }
974
android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv * env)975 static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
976 std::vector<uint8_t> bv;
977 for (auto &factory : DrmUtils::MakeDrmFactories()) {
978 sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
979 if (factoryV1_3 == nullptr) {
980 continue;
981 }
982 factoryV1_3->getSupportedCryptoSchemes(
983 [&](const hardware::hidl_vec<hardware::hidl_array<uint8_t, 16>>& schemes) {
984 for (const auto &scheme : schemes) {
985 bv.insert(bv.end(), scheme.data(), scheme.data() + scheme.size());
986 }
987 });
988 }
989
990 jbyteArray jUuidBytes = env->NewByteArray(bv.size());
991 env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast<const jbyte *>(bv.data()));
992 return jUuidBytes;
993 }
994
android_media_MediaDrm_isCryptoSchemeSupportedNative(JNIEnv * env,jobject,jbyteArray uuidObj,jstring jmimeType,jint jSecurityLevel)995 static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
996 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType,
997 jint jSecurityLevel) {
998
999 if (uuidObj == NULL) {
1000 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1001 return false;
1002 }
1003
1004 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1005
1006 if (uuid.size() != 16) {
1007 jniThrowException(
1008 env,
1009 "java/lang/IllegalArgumentException",
1010 "invalid UUID size, expected 16 bytes");
1011 return false;
1012 }
1013
1014 String8 mimeType;
1015 if (jmimeType != NULL) {
1016 mimeType = JStringToString8(env, jmimeType);
1017 }
1018 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
1019
1020 bool isSupported;
1021 status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
1022 securityLevel, &isSupported);
1023
1024 if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
1025 return false;
1026 }
1027 return isSupported;
1028 }
1029
android_media_MediaDrm_openSession(JNIEnv * env,jobject thiz,jint jlevel)1030 static jbyteArray android_media_MediaDrm_openSession(
1031 JNIEnv *env, jobject thiz, jint jlevel) {
1032 sp<IDrm> drm = GetDrm(env, thiz);
1033
1034 if (!CheckDrm(env, drm)) {
1035 return NULL;
1036 }
1037
1038 Vector<uint8_t> sessionId;
1039 DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel);
1040 if (level == DrmPlugin::kSecurityLevelUnknown) {
1041 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1042 return NULL;
1043 }
1044
1045 status_t err = drm->openSession(level, sessionId);
1046
1047 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
1048 return NULL;
1049 }
1050
1051 return VectorToJByteArray(env, sessionId);
1052 }
1053
android_media_MediaDrm_closeSession(JNIEnv * env,jobject thiz,jbyteArray jsessionId)1054 static void android_media_MediaDrm_closeSession(
1055 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1056 sp<IDrm> drm = GetDrm(env, thiz);
1057
1058 if (!CheckSession(env, drm, jsessionId)) {
1059 return;
1060 }
1061
1062 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1063
1064 status_t err = drm->closeSession(sessionId);
1065
1066 throwExceptionAsNecessary(env, err, "Failed to close session");
1067 }
1068
android_media_MediaDrm_getKeyRequest(JNIEnv * env,jobject thiz,jbyteArray jsessionId,jbyteArray jinitData,jstring jmimeType,jint jkeyType,jobject joptParams)1069 static jobject android_media_MediaDrm_getKeyRequest(
1070 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
1071 jstring jmimeType, jint jkeyType, jobject joptParams) {
1072 sp<IDrm> drm = GetDrm(env, thiz);
1073
1074 if (!CheckSession(env, drm, jsessionId)) {
1075 return NULL;
1076 }
1077
1078 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1079
1080 Vector<uint8_t> initData;
1081 if (jinitData != NULL) {
1082 initData = JByteArrayToVector(env, jinitData);
1083 }
1084
1085 String8 mimeType;
1086 if (jmimeType != NULL) {
1087 mimeType = JStringToString8(env, jmimeType);
1088 }
1089
1090 DrmPlugin::KeyType keyType;
1091 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
1092 keyType = DrmPlugin::kKeyType_Streaming;
1093 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
1094 keyType = DrmPlugin::kKeyType_Offline;
1095 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
1096 keyType = DrmPlugin::kKeyType_Release;
1097 } else {
1098 jniThrowException(env, "java/lang/IllegalArgumentException",
1099 "invalid keyType");
1100 return NULL;
1101 }
1102
1103 KeyedVector<String8, String8> optParams;
1104 if (joptParams != NULL) {
1105 bool isOK;
1106 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
1107 if (!isOK) {
1108 return NULL;
1109 }
1110 }
1111
1112 Vector<uint8_t> request;
1113 String8 defaultUrl;
1114 DrmPlugin::KeyRequestType keyRequestType;
1115
1116 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
1117 keyType, optParams, request, defaultUrl, &keyRequestType);
1118
1119 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
1120 return NULL;
1121 }
1122
1123 // Fill out return obj
1124 jclass clazz;
1125 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
1126
1127 jobject keyObj = NULL;
1128
1129 if (clazz) {
1130 keyObj = env->AllocObject(clazz);
1131 jbyteArray jrequest = VectorToJByteArray(env, request);
1132 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
1133
1134 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1135 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
1136
1137 switch (keyRequestType) {
1138 case DrmPlugin::kKeyRequestType_Initial:
1139 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1140 gKeyRequestTypes.kKeyRequestTypeInitial);
1141 break;
1142 case DrmPlugin::kKeyRequestType_Renewal:
1143 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1144 gKeyRequestTypes.kKeyRequestTypeRenewal);
1145 break;
1146 case DrmPlugin::kKeyRequestType_Release:
1147 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1148 gKeyRequestTypes.kKeyRequestTypeRelease);
1149 break;
1150 case DrmPlugin::kKeyRequestType_None:
1151 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1152 gKeyRequestTypes.kKeyRequestTypeNone);
1153 break;
1154 case DrmPlugin::kKeyRequestType_Update:
1155 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1156 gKeyRequestTypes.kKeyRequestTypeUpdate);
1157 break;
1158
1159 default:
1160 throwStateException(env, "DRM plugin failure: unknown key request type",
1161 ERROR_DRM_UNKNOWN);
1162 break;
1163 }
1164 }
1165
1166 return keyObj;
1167 }
1168
android_media_MediaDrm_provideKeyResponse(JNIEnv * env,jobject thiz,jbyteArray jsessionId,jbyteArray jresponse)1169 static jbyteArray android_media_MediaDrm_provideKeyResponse(
1170 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
1171 sp<IDrm> drm = GetDrm(env, thiz);
1172
1173 if (!CheckSession(env, drm, jsessionId)) {
1174 return NULL;
1175 }
1176
1177 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1178
1179 if (jresponse == NULL) {
1180 jniThrowException(env, "java/lang/IllegalArgumentException",
1181 "key response is null");
1182 return NULL;
1183 }
1184 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
1185 Vector<uint8_t> keySetId;
1186
1187 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
1188
1189 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
1190 return NULL;
1191 }
1192 return VectorToJByteArray(env, keySetId);
1193 }
1194
android_media_MediaDrm_removeKeys(JNIEnv * env,jobject thiz,jbyteArray jkeysetId)1195 static void android_media_MediaDrm_removeKeys(
1196 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
1197 sp<IDrm> drm = GetDrm(env, thiz);
1198
1199 if (!CheckDrm(env, drm)) {
1200 return;
1201 }
1202
1203 if (jkeysetId == NULL) {
1204 jniThrowException(env, "java/lang/IllegalArgumentException",
1205 "keySetId is null");
1206 return;
1207 }
1208
1209 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1210
1211 status_t err = drm->removeKeys(keySetId);
1212
1213 throwExceptionAsNecessary(env, err, "Failed to remove keys");
1214 }
1215
android_media_MediaDrm_restoreKeys(JNIEnv * env,jobject thiz,jbyteArray jsessionId,jbyteArray jkeysetId)1216 static void android_media_MediaDrm_restoreKeys(
1217 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
1218 jbyteArray jkeysetId) {
1219
1220 sp<IDrm> drm = GetDrm(env, thiz);
1221
1222 if (!CheckSession(env, drm, jsessionId)) {
1223 return;
1224 }
1225
1226 if (jkeysetId == NULL) {
1227 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1228 return;
1229 }
1230
1231 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1232 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1233
1234 status_t err = drm->restoreKeys(sessionId, keySetId);
1235
1236 throwExceptionAsNecessary(env, err, "Failed to restore keys");
1237 }
1238
android_media_MediaDrm_queryKeyStatus(JNIEnv * env,jobject thiz,jbyteArray jsessionId)1239 static jobject android_media_MediaDrm_queryKeyStatus(
1240 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1241 sp<IDrm> drm = GetDrm(env, thiz);
1242
1243 if (!CheckSession(env, drm, jsessionId)) {
1244 return NULL;
1245 }
1246 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1247
1248 KeyedVector<String8, String8> infoMap;
1249
1250 status_t err = drm->queryKeyStatus(sessionId, infoMap);
1251
1252 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
1253 return NULL;
1254 }
1255
1256 return KeyedVectorToHashMap(env, infoMap);
1257 }
1258
android_media_MediaDrm_getProvisionRequestNative(JNIEnv * env,jobject thiz,jint jcertType,jstring jcertAuthority)1259 static jobject android_media_MediaDrm_getProvisionRequestNative(
1260 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
1261 sp<IDrm> drm = GetDrm(env, thiz);
1262
1263 if (!CheckDrm(env, drm)) {
1264 return NULL;
1265 }
1266
1267 Vector<uint8_t> request;
1268 String8 defaultUrl;
1269
1270 String8 certType;
1271 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1272 certType = "X.509";
1273 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1274 certType = "none";
1275 } else {
1276 certType = "invalid";
1277 }
1278
1279 String8 certAuthority = JStringToString8(env, jcertAuthority);
1280 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
1281
1282 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
1283 return NULL;
1284 }
1285
1286 // Fill out return obj
1287 jclass clazz;
1288 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1289
1290 jobject provisionObj = NULL;
1291
1292 if (clazz) {
1293 provisionObj = env->AllocObject(clazz);
1294 jbyteArray jrequest = VectorToJByteArray(env, request);
1295 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1296
1297 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1298 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1299 }
1300
1301 return provisionObj;
1302 }
1303
android_media_MediaDrm_provideProvisionResponseNative(JNIEnv * env,jobject thiz,jbyteArray jresponse)1304 static jobject android_media_MediaDrm_provideProvisionResponseNative(
1305 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1306 sp<IDrm> drm = GetDrm(env, thiz);
1307
1308 if (!CheckDrm(env, drm)) {
1309 return NULL;
1310 }
1311
1312 if (jresponse == NULL) {
1313 jniThrowException(env, "java/lang/IllegalArgumentException",
1314 "provision response is null");
1315 return NULL;
1316 }
1317
1318 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
1319 Vector<uint8_t> certificate, wrappedKey;
1320
1321 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1322
1323 // Fill out return obj
1324 jclass clazz = gFields.certificateClassId;
1325
1326 jobject certificateObj = NULL;
1327
1328 if (clazz && certificate.size() && wrappedKey.size()) {
1329 certificateObj = env->AllocObject(clazz);
1330 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1331 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1332
1333 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1334 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1335 }
1336
1337 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
1338 return certificateObj;
1339 }
1340
android_media_MediaDrm_getSecureStops(JNIEnv * env,jobject thiz)1341 static jobject android_media_MediaDrm_getSecureStops(
1342 JNIEnv *env, jobject thiz) {
1343 sp<IDrm> drm = GetDrm(env, thiz);
1344
1345 if (!CheckDrm(env, drm)) {
1346 return NULL;
1347 }
1348
1349 List<Vector<uint8_t>> secureStops;
1350
1351 status_t err = drm->getSecureStops(secureStops);
1352
1353 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
1354 return NULL;
1355 }
1356
1357 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1358 }
1359
android_media_MediaDrm_getSecureStopIds(JNIEnv * env,jobject thiz)1360 static jobject android_media_MediaDrm_getSecureStopIds(
1361 JNIEnv *env, jobject thiz) {
1362 sp<IDrm> drm = GetDrm(env, thiz);
1363
1364 if (!CheckDrm(env, drm)) {
1365 return NULL;
1366 }
1367
1368 List<Vector<uint8_t>> secureStopIds;
1369
1370 status_t err = drm->getSecureStopIds(secureStopIds);
1371
1372 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
1373 return NULL;
1374 }
1375
1376 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1377 }
1378
android_media_MediaDrm_getSecureStop(JNIEnv * env,jobject thiz,jbyteArray ssid)1379 static jbyteArray android_media_MediaDrm_getSecureStop(
1380 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1381 sp<IDrm> drm = GetDrm(env, thiz);
1382
1383 if (!CheckDrm(env, drm)) {
1384 return NULL;
1385 }
1386
1387 Vector<uint8_t> secureStop;
1388
1389 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1390
1391 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
1392 return NULL;
1393 }
1394
1395 return VectorToJByteArray(env, secureStop);
1396 }
1397
android_media_MediaDrm_releaseSecureStops(JNIEnv * env,jobject thiz,jbyteArray jssRelease)1398 static void android_media_MediaDrm_releaseSecureStops(
1399 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1400 sp<IDrm> drm = GetDrm(env, thiz);
1401
1402 if (!CheckDrm(env, drm)) {
1403 return;
1404 }
1405
1406 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1407
1408 status_t err = drm->releaseSecureStops(ssRelease);
1409
1410 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
1411 }
1412
android_media_MediaDrm_removeSecureStop(JNIEnv * env,jobject thiz,jbyteArray ssid)1413 static void android_media_MediaDrm_removeSecureStop(
1414 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1415 sp<IDrm> drm = GetDrm(env, thiz);
1416
1417 if (!CheckDrm(env, drm)) {
1418 return;
1419 }
1420
1421 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1422
1423 throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
1424 }
1425
android_media_MediaDrm_removeAllSecureStops(JNIEnv * env,jobject thiz)1426 static void android_media_MediaDrm_removeAllSecureStops(
1427 JNIEnv *env, jobject thiz) {
1428 sp<IDrm> drm = GetDrm(env, thiz);
1429
1430 if (!CheckDrm(env, drm)) {
1431 return;
1432 }
1433
1434 status_t err = drm->removeAllSecureStops();
1435
1436 throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
1437 }
1438
1439
HdcpLevelTojint(DrmPlugin::HdcpLevel level)1440 static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1441 switch(level) {
1442 case DrmPlugin::kHdcpLevelUnknown:
1443 return gHdcpLevels.kHdcpLevelUnknown;
1444 case DrmPlugin::kHdcpNone:
1445 return gHdcpLevels.kHdcpNone;
1446 case DrmPlugin::kHdcpV1:
1447 return gHdcpLevels.kHdcpV1;
1448 case DrmPlugin::kHdcpV2:
1449 return gHdcpLevels.kHdcpV2;
1450 case DrmPlugin::kHdcpV2_1:
1451 return gHdcpLevels.kHdcpV2_1;
1452 case DrmPlugin::kHdcpV2_2:
1453 return gHdcpLevels.kHdcpV2_2;
1454 case DrmPlugin::kHdcpV2_3:
1455 return gHdcpLevels.kHdcpV2_3;
1456 case DrmPlugin::kHdcpNoOutput:
1457 return gHdcpLevels.kHdcpNoOutput;
1458 }
1459 return gHdcpLevels.kHdcpNone;
1460 }
1461
android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv * env,jobject thiz)1462 static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1463 jobject thiz) {
1464 sp<IDrm> drm = GetDrm(env, thiz);
1465
1466 if (!CheckDrm(env, drm)) {
1467 return gHdcpLevels.kHdcpNone;
1468 }
1469
1470 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1471 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1472
1473 status_t err = drm->getHdcpLevels(&connected, &max);
1474
1475 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1476 return gHdcpLevels.kHdcpLevelUnknown;
1477 }
1478 return HdcpLevelTojint(connected);
1479 }
1480
android_media_MediaDrm_getMaxHdcpLevel(JNIEnv * env,jobject thiz)1481 static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1482 jobject thiz) {
1483 sp<IDrm> drm = GetDrm(env, thiz);
1484
1485 if (!CheckDrm(env, drm)) {
1486 return gHdcpLevels.kHdcpLevelUnknown;
1487 }
1488
1489 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1490 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1491
1492 status_t err = drm->getHdcpLevels(&connected, &max);
1493
1494 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1495 return gHdcpLevels.kHdcpLevelUnknown;
1496 }
1497 return HdcpLevelTojint(max);
1498 }
1499
android_media_MediaDrm_getOpenSessionCount(JNIEnv * env,jobject thiz)1500 static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1501 jobject thiz) {
1502 sp<IDrm> drm = GetDrm(env, thiz);
1503
1504 if (!CheckDrm(env, drm)) {
1505 return 0;
1506 }
1507
1508 uint32_t open = 0, max = 0;
1509 status_t err = drm->getNumberOfSessions(&open, &max);
1510
1511 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1512 return 0;
1513 }
1514 return open;
1515 }
1516
android_media_MediaDrm_getMaxSessionCount(JNIEnv * env,jobject thiz)1517 static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1518 jobject thiz) {
1519 sp<IDrm> drm = GetDrm(env, thiz);
1520
1521 if (!CheckDrm(env, drm)) {
1522 return 0;
1523 }
1524
1525 uint32_t open = 0, max = 0;
1526 status_t err = drm->getNumberOfSessions(&open, &max);
1527
1528 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1529 return 0;
1530 }
1531 return max;
1532 }
1533
android_media_MediaDrm_getSecurityLevel(JNIEnv * env,jobject thiz,jbyteArray jsessionId)1534 static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1535 jobject thiz, jbyteArray jsessionId) {
1536 sp<IDrm> drm = GetDrm(env, thiz);
1537
1538 if (!CheckSession(env, drm, jsessionId)) {
1539 return gSecurityLevels.kSecurityLevelUnknown;
1540 }
1541
1542 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1543
1544 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1545
1546 status_t err = drm->getSecurityLevel(sessionId, &level);
1547
1548 if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
1549 return gSecurityLevels.kSecurityLevelUnknown;
1550 }
1551
1552 switch(level) {
1553 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1554 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1555 case DrmPlugin::kSecurityLevelSwSecureDecode:
1556 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1557 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1558 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1559 case DrmPlugin::kSecurityLevelHwSecureDecode:
1560 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1561 case DrmPlugin::kSecurityLevelHwSecureAll:
1562 return gSecurityLevels.kSecurityLevelHwSecureAll;
1563 default:
1564 return gSecurityLevels.kSecurityLevelUnknown;
1565 }
1566 }
1567
android_media_MediaDrm_getOfflineLicenseKeySetIds(JNIEnv * env,jobject thiz)1568 static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
1569 JNIEnv *env, jobject thiz) {
1570 sp<IDrm> drm = GetDrm(env, thiz);
1571
1572 if (!CheckDrm(env, drm)) {
1573 return NULL;
1574 }
1575
1576 List<Vector<uint8_t> > keySetIds;
1577
1578 status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
1579
1580 if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
1581 return NULL;
1582 }
1583
1584 return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
1585 }
1586
android_media_MediaDrm_removeOfflineLicense(JNIEnv * env,jobject thiz,jbyteArray keySetId)1587 static void android_media_MediaDrm_removeOfflineLicense(
1588 JNIEnv *env, jobject thiz, jbyteArray keySetId) {
1589 sp<IDrm> drm = GetDrm(env, thiz);
1590
1591 if (!CheckDrm(env, drm)) {
1592 return;
1593 }
1594
1595 status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
1596
1597 throwExceptionAsNecessary(env, err, "Failed to remove offline license");
1598 }
1599
android_media_MediaDrm_getOfflineLicenseState(JNIEnv * env,jobject thiz,jbyteArray jkeySetId)1600 static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
1601 jobject thiz, jbyteArray jkeySetId) {
1602 sp<IDrm> drm = GetDrm(env, thiz);
1603
1604 if (!CheckDrm(env, drm)) {
1605 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1606 }
1607
1608 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
1609
1610 DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
1611
1612 status_t err = drm->getOfflineLicenseState(keySetId, &state);
1613
1614 if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
1615 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1616 }
1617
1618 switch(state) {
1619 case DrmPlugin::kOfflineLicenseStateUsable:
1620 return gOfflineLicenseStates.kOfflineLicenseStateUsable;
1621 case DrmPlugin::kOfflineLicenseStateReleased:
1622 return gOfflineLicenseStates.kOfflineLicenseStateReleased;
1623 default:
1624 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1625 }
1626 }
1627
android_media_MediaDrm_getPropertyString(JNIEnv * env,jobject thiz,jstring jname)1628 static jstring android_media_MediaDrm_getPropertyString(
1629 JNIEnv *env, jobject thiz, jstring jname) {
1630 sp<IDrm> drm = GetDrm(env, thiz);
1631
1632 if (!CheckDrm(env, drm)) {
1633 return NULL;
1634 }
1635
1636 if (jname == NULL) {
1637 jniThrowException(env, "java/lang/IllegalArgumentException",
1638 "property name String is null");
1639 return NULL;
1640 }
1641
1642 String8 name = JStringToString8(env, jname);
1643 String8 value;
1644
1645 status_t err = drm->getPropertyString(name, value);
1646
1647 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1648 return NULL;
1649 }
1650
1651 return env->NewStringUTF(value.string());
1652 }
1653
android_media_MediaDrm_getPropertyByteArray(JNIEnv * env,jobject thiz,jstring jname)1654 static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1655 JNIEnv *env, jobject thiz, jstring jname) {
1656 sp<IDrm> drm = GetDrm(env, thiz);
1657
1658 if (!CheckDrm(env, drm)) {
1659 return NULL;
1660 }
1661
1662 if (jname == NULL) {
1663 jniThrowException(env, "java/lang/IllegalArgumentException",
1664 "property name String is null");
1665 return NULL;
1666 }
1667
1668 String8 name = JStringToString8(env, jname);
1669 Vector<uint8_t> value;
1670
1671 status_t err = drm->getPropertyByteArray(name, value);
1672
1673 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1674 return NULL;
1675 }
1676
1677 return VectorToJByteArray(env, value);
1678 }
1679
android_media_MediaDrm_setPropertyString(JNIEnv * env,jobject thiz,jstring jname,jstring jvalue)1680 static void android_media_MediaDrm_setPropertyString(
1681 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1682 sp<IDrm> drm = GetDrm(env, thiz);
1683
1684 if (!CheckDrm(env, drm)) {
1685 return;
1686 }
1687
1688 if (jname == NULL) {
1689 jniThrowException(env, "java/lang/IllegalArgumentException",
1690 "property name String is null");
1691 return;
1692 }
1693
1694 if (jvalue == NULL) {
1695 jniThrowException(env, "java/lang/IllegalArgumentException",
1696 "property value String is null");
1697 return;
1698 }
1699
1700 String8 name = JStringToString8(env, jname);
1701 String8 value = JStringToString8(env, jvalue);
1702
1703 status_t err = drm->setPropertyString(name, value);
1704
1705 throwExceptionAsNecessary(env, err, "Failed to set property");
1706 }
1707
android_media_MediaDrm_setPropertyByteArray(JNIEnv * env,jobject thiz,jstring jname,jbyteArray jvalue)1708 static void android_media_MediaDrm_setPropertyByteArray(
1709 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1710 sp<IDrm> drm = GetDrm(env, thiz);
1711
1712 if (!CheckDrm(env, drm)) {
1713 return;
1714 }
1715
1716 if (jname == NULL) {
1717 jniThrowException(env, "java/lang/IllegalArgumentException",
1718 "property name String is null");
1719 return;
1720 }
1721
1722 if (jvalue == NULL) {
1723 jniThrowException(env, "java/lang/IllegalArgumentException",
1724 "property value byte array is null");
1725 return;
1726 }
1727
1728 String8 name = JStringToString8(env, jname);
1729 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1730
1731 status_t err = drm->setPropertyByteArray(name, value);
1732
1733 throwExceptionAsNecessary(env, err, "Failed to set property");
1734 }
1735
android_media_MediaDrm_setCipherAlgorithmNative(JNIEnv * env,jobject,jobject jdrm,jbyteArray jsessionId,jstring jalgorithm)1736 static void android_media_MediaDrm_setCipherAlgorithmNative(
1737 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
1738 jstring jalgorithm) {
1739
1740 sp<IDrm> drm = GetDrm(env, jdrm);
1741
1742 if (!CheckSession(env, drm, jsessionId)) {
1743 return;
1744 }
1745
1746 if (jalgorithm == NULL) {
1747 jniThrowException(env, "java/lang/IllegalArgumentException",
1748 "algorithm String is null");
1749 return;
1750 }
1751
1752 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1753 String8 algorithm = JStringToString8(env, jalgorithm);
1754
1755 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1756
1757 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
1758 }
1759
android_media_MediaDrm_setMacAlgorithmNative(JNIEnv * env,jobject,jobject jdrm,jbyteArray jsessionId,jstring jalgorithm)1760 static void android_media_MediaDrm_setMacAlgorithmNative(
1761 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
1762 jstring jalgorithm) {
1763
1764 sp<IDrm> drm = GetDrm(env, jdrm);
1765
1766 if (!CheckSession(env, drm, jsessionId)) {
1767 return;
1768 }
1769
1770 if (jalgorithm == NULL) {
1771 jniThrowException(env, "java/lang/IllegalArgumentException",
1772 "algorithm String is null");
1773 return;
1774 }
1775
1776 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1777 String8 algorithm = JStringToString8(env, jalgorithm);
1778
1779 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1780
1781 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1782 }
1783
1784
android_media_MediaDrm_encryptNative(JNIEnv * env,jobject,jobject jdrm,jbyteArray jsessionId,jbyteArray jkeyId,jbyteArray jinput,jbyteArray jiv)1785 static jbyteArray android_media_MediaDrm_encryptNative(
1786 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
1787 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1788
1789 sp<IDrm> drm = GetDrm(env, jdrm);
1790
1791 if (!CheckSession(env, drm, jsessionId)) {
1792 return NULL;
1793 }
1794
1795 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
1796 jniThrowException(env, "java/lang/IllegalArgumentException",
1797 "required argument is null");
1798 return NULL;
1799 }
1800
1801 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1802 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1803 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1804 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1805 Vector<uint8_t> output;
1806
1807 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1808
1809 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
1810 return NULL;
1811 }
1812
1813 return VectorToJByteArray(env, output);
1814 }
1815
android_media_MediaDrm_decryptNative(JNIEnv * env,jobject,jobject jdrm,jbyteArray jsessionId,jbyteArray jkeyId,jbyteArray jinput,jbyteArray jiv)1816 static jbyteArray android_media_MediaDrm_decryptNative(
1817 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
1818 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1819
1820 sp<IDrm> drm = GetDrm(env, jdrm);
1821
1822 if (!CheckSession(env, drm, jsessionId)) {
1823 return NULL;
1824 }
1825
1826 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
1827 jniThrowException(env, "java/lang/IllegalArgumentException",
1828 "required argument is null");
1829 return NULL;
1830 }
1831
1832 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1833 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1834 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1835 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1836 Vector<uint8_t> output;
1837
1838 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
1839 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
1840 return NULL;
1841 }
1842
1843 return VectorToJByteArray(env, output);
1844 }
1845
android_media_MediaDrm_signNative(JNIEnv * env,jobject,jobject jdrm,jbyteArray jsessionId,jbyteArray jkeyId,jbyteArray jmessage)1846 static jbyteArray android_media_MediaDrm_signNative(
1847 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
1848 jbyteArray jkeyId, jbyteArray jmessage) {
1849
1850 sp<IDrm> drm = GetDrm(env, jdrm);
1851
1852 if (!CheckSession(env, drm, jsessionId)) {
1853 return NULL;
1854 }
1855
1856 if (jkeyId == NULL || jmessage == NULL) {
1857 jniThrowException(env, "java/lang/IllegalArgumentException",
1858 "required argument is null");
1859 return NULL;
1860 }
1861
1862 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1863 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1864 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1865 Vector<uint8_t> signature;
1866
1867 status_t err = drm->sign(sessionId, keyId, message, signature);
1868
1869 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1870 return NULL;
1871 }
1872
1873 return VectorToJByteArray(env, signature);
1874 }
1875
android_media_MediaDrm_verifyNative(JNIEnv * env,jobject,jobject jdrm,jbyteArray jsessionId,jbyteArray jkeyId,jbyteArray jmessage,jbyteArray jsignature)1876 static jboolean android_media_MediaDrm_verifyNative(
1877 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
1878 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1879
1880 sp<IDrm> drm = GetDrm(env, jdrm);
1881
1882 if (!CheckSession(env, drm, jsessionId)) {
1883 return false;
1884 }
1885
1886 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
1887 jniThrowException(env, "java/lang/IllegalArgumentException",
1888 "required argument is null");
1889 return false;
1890 }
1891
1892 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1893 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1894 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1895 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1896 bool match;
1897
1898 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1899
1900 throwExceptionAsNecessary(env, err, "Failed to verify");
1901 return match;
1902 }
1903
1904 static jobject
android_media_MediaDrm_native_getMetrics(JNIEnv * env,jobject thiz)1905 android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1906 {
1907 sp<IDrm> drm = GetDrm(env, thiz);
1908
1909 if (!CheckDrm(env, drm)) {
1910 return NULL;
1911 }
1912
1913 // Retrieve current metrics snapshot from drm.
1914 PersistableBundle metrics;
1915 sp<IDrmMetricsConsumer> consumer(new DrmMetricsConsumer(&metrics));
1916 status_t err = drm->getMetrics(consumer);
1917 if (err != OK) {
1918 ALOGE("getMetrics failed: %d", (int)err);
1919 return (jobject) NULL;
1920 }
1921
1922 return MediaMetricsJNI::nativeToJavaPersistableBundle(env, &metrics);
1923 }
1924
android_media_MediaDrm_signRSANative(JNIEnv * env,jobject,jobject jdrm,jbyteArray jsessionId,jstring jalgorithm,jbyteArray jwrappedKey,jbyteArray jmessage)1925 static jbyteArray android_media_MediaDrm_signRSANative(
1926 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
1927 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1928
1929 sp<IDrm> drm = GetDrm(env, jdrm);
1930
1931 if (!CheckSession(env, drm, jsessionId)) {
1932 return NULL;
1933 }
1934
1935 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1936 jniThrowException(env, "java/lang/IllegalArgumentException",
1937 "required argument is null");
1938 return NULL;
1939 }
1940
1941 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1942 String8 algorithm = JStringToString8(env, jalgorithm);
1943 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1944 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1945 Vector<uint8_t> signature;
1946
1947 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1948
1949 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1950 return NULL;
1951 }
1952
1953 return VectorToJByteArray(env, signature);
1954 }
1955
1956
1957 static const JNINativeMethod gMethods[] = {
1958 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
1959
1960 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
1961
1962 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
1963 (void *)android_media_MediaDrm_native_setup },
1964
1965 { "getSupportedCryptoSchemesNative", "()[B",
1966 (void *)android_media_MediaDrm_getSupportedCryptoSchemesNative },
1967
1968 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z",
1969 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
1970
1971 { "openSession", "(I)[B",
1972 (void *)android_media_MediaDrm_openSession },
1973
1974 { "closeSession", "([B)V",
1975 (void *)android_media_MediaDrm_closeSession },
1976
1977 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
1978 "Landroid/media/MediaDrm$KeyRequest;",
1979 (void *)android_media_MediaDrm_getKeyRequest },
1980
1981 { "provideKeyResponse", "([B[B)[B",
1982 (void *)android_media_MediaDrm_provideKeyResponse },
1983
1984 { "removeKeys", "([B)V",
1985 (void *)android_media_MediaDrm_removeKeys },
1986
1987 { "restoreKeys", "([B[B)V",
1988 (void *)android_media_MediaDrm_restoreKeys },
1989
1990 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
1991 (void *)android_media_MediaDrm_queryKeyStatus },
1992
1993 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
1994 (void *)android_media_MediaDrm_getProvisionRequestNative },
1995
1996 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
1997 (void *)android_media_MediaDrm_provideProvisionResponseNative },
1998
1999 { "getSecureStops", "()Ljava/util/List;",
2000 (void *)android_media_MediaDrm_getSecureStops },
2001
2002 { "getSecureStopIds", "()Ljava/util/List;",
2003 (void *)android_media_MediaDrm_getSecureStopIds },
2004
2005 { "getSecureStop", "([B)[B",
2006 (void *)android_media_MediaDrm_getSecureStop },
2007
2008 { "releaseSecureStops", "([B)V",
2009 (void *)android_media_MediaDrm_releaseSecureStops },
2010
2011 { "removeSecureStop", "([B)V",
2012 (void *)android_media_MediaDrm_removeSecureStop },
2013
2014 { "removeAllSecureStops", "()V",
2015 (void *)android_media_MediaDrm_removeAllSecureStops },
2016
2017 { "getConnectedHdcpLevel", "()I",
2018 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
2019
2020 { "getMaxHdcpLevel", "()I",
2021 (void *)android_media_MediaDrm_getMaxHdcpLevel },
2022
2023 { "getOpenSessionCount", "()I",
2024 (void *)android_media_MediaDrm_getOpenSessionCount },
2025
2026 { "getMaxSessionCount", "()I",
2027 (void *)android_media_MediaDrm_getMaxSessionCount },
2028
2029 { "getSecurityLevel", "([B)I",
2030 (void *)android_media_MediaDrm_getSecurityLevel },
2031
2032 { "removeOfflineLicense", "([B)V",
2033 (void *)android_media_MediaDrm_removeOfflineLicense },
2034
2035 { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
2036 (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
2037
2038 { "getOfflineLicenseState", "([B)I",
2039 (void *)android_media_MediaDrm_getOfflineLicenseState },
2040
2041 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
2042 (void *)android_media_MediaDrm_getPropertyString },
2043
2044 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
2045 (void *)android_media_MediaDrm_getPropertyByteArray },
2046
2047 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
2048 (void *)android_media_MediaDrm_setPropertyString },
2049
2050 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
2051 (void *)android_media_MediaDrm_setPropertyByteArray },
2052
2053 { "setCipherAlgorithmNative",
2054 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2055 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
2056
2057 { "setMacAlgorithmNative",
2058 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2059 (void *)android_media_MediaDrm_setMacAlgorithmNative },
2060
2061 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2062 (void *)android_media_MediaDrm_encryptNative },
2063
2064 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2065 (void *)android_media_MediaDrm_decryptNative },
2066
2067 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
2068 (void *)android_media_MediaDrm_signNative },
2069
2070 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
2071 (void *)android_media_MediaDrm_verifyNative },
2072
2073 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
2074 (void *)android_media_MediaDrm_signRSANative },
2075
2076 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
2077 (void *)android_media_MediaDrm_native_getMetrics },
2078 };
2079
register_android_media_Drm(JNIEnv * env)2080 int register_android_media_Drm(JNIEnv *env) {
2081 return AndroidRuntime::registerNativeMethods(env,
2082 "android/media/MediaDrm", gMethods, NELEM(gMethods));
2083 }
2084