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