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