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