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