• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }