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