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