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