blob: 4f06caaea703750cbda4514a96c19fd951eec0c9 [file] [log] [blame]
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001/*
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"
Adam Stonec06e10e2017-12-19 12:54:33 -080022#include "android_media_MediaMetricsJNI.h"
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080023
24#include "android_runtime/AndroidRuntime.h"
Ruben Brunk87eac992013-09-09 17:44:59 -070025#include "android_runtime/Log.h"
Jeff Tinker54cfbd62013-04-02 13:14:59 -070026#include "android_os_Parcel.h"
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080027#include "jni.h"
Steven Moreland2279b252017-07-19 09:50:45 -070028#include <nativehelper/JNIHelp.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080029
30#include <binder/IServiceManager.h>
Jeff Tinker54cfbd62013-04-02 13:14:59 -070031#include <binder/Parcel.h>
Jeff Tinkerdc614f82016-02-12 08:58:32 -080032#include <cutils/properties.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080033#include <media/IDrm.h>
Jeff Tinkerdc614f82016-02-12 08:58:32 -080034#include <media/IMediaDrmService.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080035#include <media/stagefright/foundation/ADebug.h>
Jeff Tinkerf7568b52013-04-17 14:24:40 -070036#include <media/stagefright/MediaErrors.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080037
38namespace android {
39
40#define FIND_CLASS(var, className) \
41 var = env->FindClass(className); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070042 LOG_FATAL_IF(! (var), "Unable to find class " className);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080043
44#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
45 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070046 LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080047
48#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
49 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070050 LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080051
Jeff Tinker54cfbd62013-04-02 13:14:59 -070052#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
53 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070054 LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070055
56#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
57 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070058 LOG_FATAL_IF(! (var), "Unable to find static method " fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070059
60
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080061struct RequestFields {
62 jfieldID data;
63 jfieldID defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -070064 jfieldID requestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080065};
66
67struct ArrayListFields {
68 jmethodID init;
69 jmethodID add;
70};
71
72struct HashmapFields {
73 jmethodID init;
74 jmethodID get;
75 jmethodID put;
76 jmethodID entrySet;
77};
78
79struct SetFields {
80 jmethodID iterator;
81};
82
83struct IteratorFields {
84 jmethodID next;
85 jmethodID hasNext;
86};
87
88struct EntryFields {
89 jmethodID getKey;
90 jmethodID getValue;
91};
92
Jeff Tinker54cfbd62013-04-02 13:14:59 -070093struct EventTypes {
Jeff Tinker17b89222013-05-21 12:35:06 -070094 jint kEventProvisionRequired;
95 jint kEventKeyRequired;
96 jint kEventKeyExpired;
97 jint kEventVendorDefined;
Ronghua Wua6d72092015-03-04 11:16:02 -080098 jint kEventSessionReclaimed;
Jeff Tinker54cfbd62013-04-02 13:14:59 -070099} gEventTypes;
100
Jeff Tinker74797f82015-03-31 15:44:34 -0700101struct EventWhat {
102 jint kWhatDrmEvent;
103 jint kWhatExpirationUpdate;
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700104 jint kWhatKeyStatusChange;
Jeff Tinker74797f82015-03-31 15:44:34 -0700105} gEventWhat;
106
Jeff Tinker17b89222013-05-21 12:35:06 -0700107struct KeyTypes {
108 jint kKeyTypeStreaming;
109 jint kKeyTypeOffline;
110 jint kKeyTypeRelease;
111} gKeyTypes;
112
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700113struct KeyRequestTypes {
114 jint kKeyRequestTypeInitial;
115 jint kKeyRequestTypeRenewal;
116 jint kKeyRequestTypeRelease;
Rahul Frias8f761ba2018-01-22 23:43:54 -0800117 jint kKeyRequestTypeNone;
118 jint kKeyRequestTypeUpdate;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700119} gKeyRequestTypes;
120
Jeff Tinkere4095a82014-03-04 13:17:11 -0800121struct CertificateTypes {
122 jint kCertificateTypeNone;
123 jint kCertificateTypeX509;
124} gCertificateTypes;
125
126struct CertificateFields {
127 jfieldID wrappedPrivateKey;
128 jfieldID certificateData;
129};
130
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700131struct StateExceptionFields {
132 jmethodID init;
133 jclass classId;
134};
135
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800136struct HDCPLevels {
137 jint kHdcpLevelUnknown;
138 jint kHdcpNone;
139 jint kHdcpV1;
140 jint kHdcpV2;
141 jint kHdcpV2_1;
142 jint kHdcpV2_2;
143 jint kHdcpNoOutput;
144} gHdcpLevels;
145
146struct SecurityLevels {
147 jint kSecurityLevelUnknown;
148 jint kSecurityLevelSwSecureCrypto;
149 jint kSecurityLevelSwSecureDecode;
150 jint kSecurityLevelHwSecureCrypto;
151 jint kSecurityLevelHwSecureDecode;
152 jint kSecurityLevelHwSecureAll;
153} gSecurityLevels;
154
155
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800156struct fields_t {
157 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700158 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700159 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800160 RequestFields provisionRequest;
161 ArrayListFields arraylist;
162 HashmapFields hashmap;
163 SetFields set;
164 IteratorFields iterator;
165 EntryFields entry;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800166 CertificateFields certificate;
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700167 StateExceptionFields stateException;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800168 jclass certificateClassId;
169 jclass hashmapClassId;
170 jclass arraylistClassId;
171 jclass stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800172};
173
174static fields_t gFields;
175
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700176// ----------------------------------------------------------------------------
177// ref-counted object for callbacks
178class JNIDrmListener: public DrmListener
179{
180public:
181 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
182 ~JNIDrmListener();
183 virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
184private:
185 JNIDrmListener();
186 jclass mClass; // Reference to MediaDrm class
187 jobject mObject; // Weak ref to MediaDrm Java object to call on
188};
189
190JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
191{
192 // Hold onto the MediaDrm class for use in calling the static method
193 // that posts events to the application thread.
194 jclass clazz = env->GetObjectClass(thiz);
195 if (clazz == NULL) {
196 ALOGE("Can't find android/media/MediaDrm");
Jeff Tinkereada5372013-05-21 12:48:14 -0700197 jniThrowException(env, "java/lang/Exception",
198 "Can't find android/media/MediaDrm");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700199 return;
200 }
201 mClass = (jclass)env->NewGlobalRef(clazz);
202
203 // We use a weak reference so the MediaDrm object can be garbage collected.
204 // The reference is only used as a proxy for callbacks.
205 mObject = env->NewGlobalRef(weak_thiz);
206}
207
208JNIDrmListener::~JNIDrmListener()
209{
210 // remove global references
211 JNIEnv *env = AndroidRuntime::getJNIEnv();
212 env->DeleteGlobalRef(mObject);
213 env->DeleteGlobalRef(mClass);
214}
215
216void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
217 const Parcel *obj)
218{
Jeff Tinker74797f82015-03-31 15:44:34 -0700219 jint jwhat;
220 jint jeventType = 0;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700221
222 // translate DrmPlugin event types into their java equivalents
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700223 switch (eventType) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700224 case DrmPlugin::kDrmPluginEventProvisionRequired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700225 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700226 jeventType = gEventTypes.kEventProvisionRequired;
227 break;
228 case DrmPlugin::kDrmPluginEventKeyNeeded:
Jeff Tinker74797f82015-03-31 15:44:34 -0700229 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700230 jeventType = gEventTypes.kEventKeyRequired;
231 break;
232 case DrmPlugin::kDrmPluginEventKeyExpired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700233 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700234 jeventType = gEventTypes.kEventKeyExpired;
235 break;
236 case DrmPlugin::kDrmPluginEventVendorDefined:
Jeff Tinker74797f82015-03-31 15:44:34 -0700237 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700238 jeventType = gEventTypes.kEventVendorDefined;
239 break;
Ronghua Wua6d72092015-03-04 11:16:02 -0800240 case DrmPlugin::kDrmPluginEventSessionReclaimed:
Jeff Tinker74797f82015-03-31 15:44:34 -0700241 jwhat = gEventWhat.kWhatDrmEvent;
Ronghua Wua6d72092015-03-04 11:16:02 -0800242 jeventType = gEventTypes.kEventSessionReclaimed;
243 break;
Jeff Tinker74797f82015-03-31 15:44:34 -0700244 case DrmPlugin::kDrmPluginEventExpirationUpdate:
245 jwhat = gEventWhat.kWhatExpirationUpdate;
246 break;
247 case DrmPlugin::kDrmPluginEventKeysChange:
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700248 jwhat = gEventWhat.kWhatKeyStatusChange;
Jeff Tinker74797f82015-03-31 15:44:34 -0700249 break;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700250 default:
251 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
252 return;
253 }
254
255 JNIEnv *env = AndroidRuntime::getJNIEnv();
256 if (obj && obj->dataSize() > 0) {
257 jobject jParcel = createJavaParcelObject(env);
258 if (jParcel != NULL) {
259 Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
260 nativeParcel->setData(obj->data(), obj->dataSize());
261 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
Jeff Tinker74797f82015-03-31 15:44:34 -0700262 jwhat, jeventType, extra, jParcel);
Patrik2 Carlsson265551a2013-12-10 14:52:43 +0100263 env->DeleteLocalRef(jParcel);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700264 }
265 }
266
267 if (env->ExceptionCheck()) {
268 ALOGW("An exception occurred while notifying an event.");
269 LOGW_EX(env);
270 env->ExceptionClear();
271 }
272}
273
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700274static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
275 ALOGE("Illegal state exception: %s (%d)", msg, err);
276
277 jobject exception = env->NewObject(gFields.stateException.classId,
278 gFields.stateException.init, static_cast<int>(err),
279 env->NewStringUTF(msg));
280 env->Throw(static_cast<jthrowable>(exception));
281}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700282
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800283static bool throwExceptionAsNecessary(
284 JNIEnv *env, status_t err, const char *msg = NULL) {
285
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700286 const char *drmMessage = NULL;
287
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700288 switch (err) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700289 case ERROR_DRM_UNKNOWN:
290 drmMessage = "General DRM error";
291 break;
292 case ERROR_DRM_NO_LICENSE:
293 drmMessage = "No license";
294 break;
295 case ERROR_DRM_LICENSE_EXPIRED:
296 drmMessage = "License expired";
297 break;
298 case ERROR_DRM_SESSION_NOT_OPENED:
299 drmMessage = "Session not opened";
300 break;
301 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
302 drmMessage = "Not initialized";
303 break;
304 case ERROR_DRM_DECRYPT:
305 drmMessage = "Decrypt error";
306 break;
307 case ERROR_DRM_CANNOT_HANDLE:
Jeff Tinkereb13c762017-11-01 15:29:38 -0700308 drmMessage = "Invalid parameter or data format";
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700309 break;
310 case ERROR_DRM_TAMPER_DETECTED:
311 drmMessage = "Invalid state";
312 break;
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700313 default:
314 break;
315 }
316
317 String8 vendorMessage;
318 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
Jeff Tinker29799862014-08-27 11:05:13 -0700319 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700320 drmMessage = vendorMessage.string();
321 }
322
Jeff Tinkereb13c762017-11-01 15:29:38 -0700323 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800324 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
325 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700326 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
327 jniThrowException(env, "android/media/NotProvisionedException", msg);
328 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700329 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
330 jniThrowException(env, "android/media/ResourceBusyException", msg);
331 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700332 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
333 jniThrowException(env, "android/media/DeniedByServerException", msg);
334 return true;
Jeff Tinker314b7f32015-06-15 17:45:43 -0700335 } else if (err == DEAD_OBJECT) {
336 jniThrowException(env, "android/media/MediaDrmResetException",
337 "mediaserver died");
338 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800339 } else if (err != OK) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700340 String8 errbuf;
341 if (drmMessage != NULL) {
342 if (msg == NULL) {
343 msg = drmMessage;
344 } else {
Jeff Tinker29799862014-08-27 11:05:13 -0700345 errbuf = String8::format("%s: %s", msg, drmMessage);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700346 msg = errbuf.string();
347 }
348 }
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700349 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800350 return true;
351 }
352 return false;
353}
354
355static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000356 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800357 return jdrm ? jdrm->getDrm() : NULL;
358}
359
360JDrm::JDrm(
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800361 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
362 const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800363 mObject = env->NewWeakGlobalRef(thiz);
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800364 mDrm = MakeDrm(uuid, appPackageName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700365 if (mDrm != NULL) {
366 mDrm->setListener(this);
367 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800368}
369
370JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800371 JNIEnv *env = AndroidRuntime::getJNIEnv();
372
373 env->DeleteWeakGlobalRef(mObject);
374 mObject = NULL;
375}
376
377// static
378sp<IDrm> JDrm::MakeDrm() {
379 sp<IServiceManager> sm = defaultServiceManager();
380
Jeff Tinkerd12b7c02016-04-22 17:50:33 -0700381 sp<IBinder> binder = sm->getService(String16("media.drm"));
382 sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
383 if (service == NULL) {
384 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800385 }
386
Jeff Tinkerd12b7c02016-04-22 17:50:33 -0700387 sp<IDrm> drm = service->makeDrm();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800388 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
389 return NULL;
390 }
391
392 return drm;
393}
394
395// static
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800396sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800397 sp<IDrm> drm = MakeDrm();
398
399 if (drm == NULL) {
400 return NULL;
401 }
402
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800403 status_t err = drm->createPlugin(uuid, appPackageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800404
405 if (err != OK) {
406 return NULL;
407 }
408
409 return drm;
410}
411
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700412status_t JDrm::setListener(const sp<DrmListener>& listener) {
413 Mutex::Autolock lock(mLock);
414 mListener = listener;
415 return OK;
416}
417
418void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
419 sp<DrmListener> listener;
420 mLock.lock();
421 listener = mListener;
422 mLock.unlock();
423
424 if (listener != NULL) {
425 Mutex::Autolock lock(mNotifyLock);
426 listener->notify(eventType, extra, obj);
427 }
428}
429
Jeff Tinker600071c2014-04-11 16:11:15 -0700430void JDrm::disconnect() {
431 if (mDrm != NULL) {
432 mDrm->destroyPlugin();
433 mDrm.clear();
434 }
435}
436
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700437
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800438// static
Jeff Tinker7cda4912013-08-21 11:52:34 -0700439bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800440 sp<IDrm> drm = MakeDrm();
441
442 if (drm == NULL) {
443 return false;
444 }
445
Jeff Tinker7cda4912013-08-21 11:52:34 -0700446 return drm->isCryptoSchemeSupported(uuid, mimeType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800447}
448
449status_t JDrm::initCheck() const {
450 return mDrm == NULL ? NO_INIT : OK;
451}
452
453// JNI conversion utilities
454static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
455 Vector<uint8_t> vector;
456 size_t length = env->GetArrayLength(byteArray);
457 vector.insertAt((size_t)0, length);
458 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
459 return vector;
460}
461
462static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
463 size_t length = vector.size();
464 jbyteArray result = env->NewByteArray(length);
465 if (result != NULL) {
466 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
467 }
468 return result;
469}
470
471static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800472 String8 result;
473
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700474 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800475 if (s) {
476 result = s;
477 env->ReleaseStringUTFChars(jstr, s);
478 }
479 return result;
480}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700481
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800482/*
483 import java.util.HashMap;
484 import java.util.Set;
485 import java.Map.Entry;
486 import jav.util.Iterator;
487
488 HashMap<k, v> hm;
489 Set<Entry<k, v> > s = hm.entrySet();
490 Iterator i = s.iterator();
491 Entry e = s.next();
492*/
493
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200494static KeyedVector<String8, String8> HashMapToKeyedVector(
495 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800496 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800497 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200498 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800499
500 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
501 if (entrySet) {
502 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
503 if (iterator) {
504 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
505 while (hasNext) {
506 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
507 if (entry) {
508 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200509 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700510 jniThrowException(env, "java/lang/IllegalArgumentException",
511 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200512 env->DeleteLocalRef(entry);
513 *pIsOK = false;
514 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800515 }
516 jstring jkey = static_cast<jstring>(obj);
517
518 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200519 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700520 jniThrowException(env, "java/lang/IllegalArgumentException",
521 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200522 env->DeleteLocalRef(entry);
523 *pIsOK = false;
524 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800525 }
526 jstring jvalue = static_cast<jstring>(obj);
527
528 String8 key = JStringToString8(env, jkey);
529 String8 value = JStringToString8(env, jvalue);
530 keyedVector.add(key, value);
531
532 env->DeleteLocalRef(jkey);
533 env->DeleteLocalRef(jvalue);
534 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
535 }
536 env->DeleteLocalRef(entry);
537 }
538 env->DeleteLocalRef(iterator);
539 }
540 env->DeleteLocalRef(entrySet);
541 }
542 return keyedVector;
543}
544
545static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800546 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800547 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
548 for (size_t i = 0; i < map.size(); ++i) {
549 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
550 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
551 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
552 env->DeleteLocalRef(jkey);
553 env->DeleteLocalRef(jvalue);
554 }
555 return hashMap;
556}
557
558static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
559 List<Vector<uint8_t> > list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800560 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800561 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
562 List<Vector<uint8_t> >::iterator iter = list.begin();
563 while (iter != list.end()) {
564 jbyteArray byteArray = VectorToJByteArray(env, *iter);
565 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
566 env->DeleteLocalRef(byteArray);
567 iter++;
568 }
569
570 return arrayList;
571}
572
573} // namespace android
574
575using namespace android;
576
577static sp<JDrm> setDrm(
578 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000579 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800580 if (drm != NULL) {
581 drm->incStrong(thiz);
582 }
583 if (old != NULL) {
584 old->decStrong(thiz);
585 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000586 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800587
588 return old;
589}
590
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800591static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800592 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700593 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800594 return false;
595 }
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800596 return true;
597}
598
599static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
600{
601 if (!CheckDrm(env, drm)) {
602 return false;
603 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800604
605 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700606 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800607 return false;
608 }
609 return true;
610}
611
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800612static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700613 sp<JDrm> drm = setDrm(env, thiz, NULL);
614 if (drm != NULL) {
615 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700616 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700617 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800618}
619
620static void android_media_MediaDrm_native_init(JNIEnv *env) {
621 jclass clazz;
622 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000623 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700624 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
Jeff Tinker74797f82015-03-31 15:44:34 -0700625 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700626
627 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700628 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700629 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700630 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700631 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700632 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700633 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700634 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700635 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Ronghua Wua6d72092015-03-04 11:16:02 -0800636 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
637 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800638
Jeff Tinker74797f82015-03-31 15:44:34 -0700639 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
640 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
641 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
642 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700643 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
644 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
Jeff Tinker74797f82015-03-31 15:44:34 -0700645
Jeff Tinker17b89222013-05-21 12:35:06 -0700646 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
647 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
648 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
649 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
650 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
651 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
652
Jeff Tinkere4095a82014-03-04 13:17:11 -0800653 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
654 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
655 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
656 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
657
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800658 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
659 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
660 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
661 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
662 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
663 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
664 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
665 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
666 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
667 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
668 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
669 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
670 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
671 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
672
673 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
674 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
675 GET_STATIC_FIELD_ID(field, clazz, "SW_SECURE_CRYPTO", "I");
676 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
677 GET_STATIC_FIELD_ID(field, clazz, "SW_SECURE_DECODE", "I");
678 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
679 GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_CRYPTO", "I");
680 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
681 GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_DECODE", "I");
682 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
683 GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_ALL", "I");
684 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
685
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700686 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700687 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
688 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700689 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800690
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700691 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
692 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
693 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
694 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
695 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
696 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
Rahul Frias8f761ba2018-01-22 23:43:54 -0800697 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
698 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
699 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
700 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700701
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800702 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700703 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
704 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800705
Jeff Tinkere4095a82014-03-04 13:17:11 -0800706 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
707 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
708 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700709 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800710
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800711 FIND_CLASS(clazz, "java/util/ArrayList");
712 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
713 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
714
715 FIND_CLASS(clazz, "java/util/HashMap");
716 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
717 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
718 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
719 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
720 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
721
722 FIND_CLASS(clazz, "java/util/Set");
723 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
724
725 FIND_CLASS(clazz, "java/util/Iterator");
726 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
727 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
728
729 FIND_CLASS(clazz, "java/util/Map$Entry");
730 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
731 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800732
733 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700734 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800735
736 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700737 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800738
739 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700740 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700741
742 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
743 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
744 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800745}
746
747static void android_media_MediaDrm_native_setup(
748 JNIEnv *env, jobject thiz,
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800749 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800750
751 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700752 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800753 return;
754 }
755
756 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
757
758 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700759 jniThrowException(env, "java/lang/IllegalArgumentException",
760 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800761 return;
762 }
763
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800764 String8 packageName;
765 if (jappPackageName == NULL) {
766 jniThrowException(env, "java/lang/IllegalArgumentException",
767 "application package name cannot be null");
768 return;
769 }
770
771 packageName = JStringToString8(env, jappPackageName);
772 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800773
774 status_t err = drm->initCheck();
775
776 if (err != OK) {
777 jniThrowException(
778 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700779 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800780 "Failed to instantiate drm object.");
781 return;
782 }
783
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700784 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
785 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800786 setDrm(env, thiz, drm);
787}
788
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800789static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800790 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800791
792 if (uuidObj == NULL) {
793 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
794 return false;
795 }
796
797 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
798
799 if (uuid.size() != 16) {
800 jniThrowException(
801 env,
802 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -0700803 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800804 return false;
805 }
806
Jeff Tinker7cda4912013-08-21 11:52:34 -0700807 String8 mimeType;
808 if (jmimeType != NULL) {
809 mimeType = JStringToString8(env, jmimeType);
810 }
811
812 return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800813}
814
815static jbyteArray android_media_MediaDrm_openSession(
816 JNIEnv *env, jobject thiz) {
817 sp<IDrm> drm = GetDrm(env, thiz);
818
819 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700820 jniThrowException(env, "java/lang/IllegalStateException",
821 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800822 return NULL;
823 }
824
825 Vector<uint8_t> sessionId;
826 status_t err = drm->openSession(sessionId);
827
828 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
829 return NULL;
830 }
831
832 return VectorToJByteArray(env, sessionId);
833}
834
835static void android_media_MediaDrm_closeSession(
836 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
837 sp<IDrm> drm = GetDrm(env, thiz);
838
839 if (!CheckSession(env, drm, jsessionId)) {
840 return;
841 }
842
843 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
844
845 status_t err = drm->closeSession(sessionId);
846
847 throwExceptionAsNecessary(env, err, "Failed to close session");
848}
849
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700850static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800851 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700852 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800853 sp<IDrm> drm = GetDrm(env, thiz);
854
855 if (!CheckSession(env, drm, jsessionId)) {
856 return NULL;
857 }
858
859 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
860
861 Vector<uint8_t> initData;
862 if (jinitData != NULL) {
863 initData = JByteArrayToVector(env, jinitData);
864 }
865
866 String8 mimeType;
867 if (jmimeType != NULL) {
868 mimeType = JStringToString8(env, jmimeType);
869 }
870
Jeff Tinker17b89222013-05-21 12:35:06 -0700871 DrmPlugin::KeyType keyType;
872 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
873 keyType = DrmPlugin::kKeyType_Streaming;
874 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
875 keyType = DrmPlugin::kKeyType_Offline;
876 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
877 keyType = DrmPlugin::kKeyType_Release;
878 } else {
879 jniThrowException(env, "java/lang/IllegalArgumentException",
880 "invalid keyType");
881 return NULL;
882 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800883
884 KeyedVector<String8, String8> optParams;
885 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200886 bool isOK;
887 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
888 if (!isOK) {
889 return NULL;
890 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800891 }
892
893 Vector<uint8_t> request;
894 String8 defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700895 DrmPlugin::KeyRequestType keyRequestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800896
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700897 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700898 keyType, optParams, request, defaultUrl, &keyRequestType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800899
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700900 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800901 return NULL;
902 }
903
904 // Fill out return obj
905 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700906 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800907
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700908 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800909
910 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700911 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800912 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700913 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800914
915 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700916 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700917
918 switch (keyRequestType) {
919 case DrmPlugin::kKeyRequestType_Initial:
920 env->SetIntField(keyObj, gFields.keyRequest.requestType,
921 gKeyRequestTypes.kKeyRequestTypeInitial);
922 break;
923 case DrmPlugin::kKeyRequestType_Renewal:
924 env->SetIntField(keyObj, gFields.keyRequest.requestType,
925 gKeyRequestTypes.kKeyRequestTypeRenewal);
926 break;
927 case DrmPlugin::kKeyRequestType_Release:
928 env->SetIntField(keyObj, gFields.keyRequest.requestType,
929 gKeyRequestTypes.kKeyRequestTypeRelease);
930 break;
Rahul Frias8f761ba2018-01-22 23:43:54 -0800931 case DrmPlugin::kKeyRequestType_None:
932 env->SetIntField(keyObj, gFields.keyRequest.requestType,
933 gKeyRequestTypes.kKeyRequestTypeNone);
934 break;
935 case DrmPlugin::kKeyRequestType_Update:
936 env->SetIntField(keyObj, gFields.keyRequest.requestType,
937 gKeyRequestTypes.kKeyRequestTypeUpdate);
938 break;
939
Jeff Tinker74797f82015-03-31 15:44:34 -0700940 default:
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700941 throwStateException(env, "DRM plugin failure: unknown key request type",
942 ERROR_DRM_UNKNOWN);
943 break;
944 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800945 }
946
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700947 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800948}
949
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700950static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800951 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
952 sp<IDrm> drm = GetDrm(env, thiz);
953
954 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700955 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800956 }
957
958 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
959
960 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700961 jniThrowException(env, "java/lang/IllegalArgumentException",
962 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700963 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800964 }
965 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700966 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800967
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700968 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800969
Jeff Tinker8117d8f2013-08-16 13:46:02 -0700970 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
971 return NULL;
972 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700973 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800974}
975
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700976static void android_media_MediaDrm_removeKeys(
977 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
978 sp<IDrm> drm = GetDrm(env, thiz);
979
980 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700981 jniThrowException(env, "java/lang/IllegalArgumentException",
982 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700983 return;
984 }
985
986 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
987
988 status_t err = drm->removeKeys(keySetId);
989
990 throwExceptionAsNecessary(env, err, "Failed to remove keys");
991}
992
993static void android_media_MediaDrm_restoreKeys(
994 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
995 jbyteArray jkeysetId) {
996
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800997 sp<IDrm> drm = GetDrm(env, thiz);
998
999 if (!CheckSession(env, drm, jsessionId)) {
1000 return;
1001 }
1002
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001003 if (jkeysetId == NULL) {
1004 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1005 return;
1006 }
1007
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001008 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001009 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001010
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001011 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001012
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001013 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001014}
1015
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001016static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001017 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1018 sp<IDrm> drm = GetDrm(env, thiz);
1019
1020 if (!CheckSession(env, drm, jsessionId)) {
1021 return NULL;
1022 }
1023 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1024
1025 KeyedVector<String8, String8> infoMap;
1026
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001027 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001028
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001029 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001030 return NULL;
1031 }
1032
1033 return KeyedVectorToHashMap(env, infoMap);
1034}
1035
Jeff Tinkere4095a82014-03-04 13:17:11 -08001036static jobject android_media_MediaDrm_getProvisionRequestNative(
1037 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001038 sp<IDrm> drm = GetDrm(env, thiz);
1039
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001040 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001041 return NULL;
1042 }
1043
1044 Vector<uint8_t> request;
1045 String8 defaultUrl;
1046
Jeff Tinkere4095a82014-03-04 13:17:11 -08001047 String8 certType;
1048 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1049 certType = "X.509";
1050 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1051 certType = "none";
1052 } else {
1053 certType = "invalid";
1054 }
1055
1056 String8 certAuthority = JStringToString8(env, jcertAuthority);
1057 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001058
1059 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
1060 return NULL;
1061 }
1062
1063 // Fill out return obj
1064 jclass clazz;
1065 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1066
1067 jobject provisionObj = NULL;
1068
1069 if (clazz) {
1070 provisionObj = env->AllocObject(clazz);
1071 jbyteArray jrequest = VectorToJByteArray(env, request);
1072 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1073
1074 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1075 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1076 }
1077
1078 return provisionObj;
1079}
1080
Jeff Tinkere4095a82014-03-04 13:17:11 -08001081static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001082 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1083 sp<IDrm> drm = GetDrm(env, thiz);
1084
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001085 if (!CheckDrm(env, drm)) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001086 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001087 }
1088
1089 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001090 jniThrowException(env, "java/lang/IllegalArgumentException",
1091 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001092 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001093 }
1094
1095 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -08001096 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001097
Jeff Tinkere4095a82014-03-04 13:17:11 -08001098 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1099
1100 // Fill out return obj
1101 jclass clazz = gFields.certificateClassId;
1102
1103 jobject certificateObj = NULL;
1104
1105 if (clazz && certificate.size() && wrappedKey.size()) {
1106 certificateObj = env->AllocObject(clazz);
1107 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1108 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1109
1110 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1111 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1112 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001113
1114 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001115 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001116}
1117
1118static jobject android_media_MediaDrm_getSecureStops(
1119 JNIEnv *env, jobject thiz) {
1120 sp<IDrm> drm = GetDrm(env, thiz);
1121
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001122 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001123 return NULL;
1124 }
1125
1126 List<Vector<uint8_t> > secureStops;
1127
1128 status_t err = drm->getSecureStops(secureStops);
1129
1130 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
1131 return NULL;
1132 }
1133
1134 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1135}
1136
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001137static jobject android_media_MediaDrm_getSecureStopIds(
1138 JNIEnv *env, jobject thiz) {
1139 sp<IDrm> drm = GetDrm(env, thiz);
1140
1141 if (drm == NULL) {
1142 jniThrowException(env, "java/lang/IllegalStateException",
1143 "MediaDrm obj is null");
1144 return NULL;
1145 }
1146
1147 List<Vector<uint8_t> > secureStopIds;
1148
1149 status_t err = drm->getSecureStopIds(secureStopIds);
1150
1151 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
1152 return NULL;
1153 }
1154
1155 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1156}
1157
Jeff Tinker1b51c722014-10-31 00:54:26 -07001158static jbyteArray android_media_MediaDrm_getSecureStop(
1159 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1160 sp<IDrm> drm = GetDrm(env, thiz);
1161
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001162 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001163 return NULL;
1164 }
1165
1166 Vector<uint8_t> secureStop;
1167
1168 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1169
1170 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
1171 return NULL;
1172 }
1173
1174 return VectorToJByteArray(env, secureStop);
1175}
1176
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001177static void android_media_MediaDrm_releaseSecureStops(
1178 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1179 sp<IDrm> drm = GetDrm(env, thiz);
1180
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001181 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001182 return;
1183 }
1184
1185 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1186
1187 status_t err = drm->releaseSecureStops(ssRelease);
1188
1189 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
1190}
1191
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001192static void android_media_MediaDrm_removeSecureStop(
1193 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1194 sp<IDrm> drm = GetDrm(env, thiz);
1195
1196 if (drm == NULL) {
1197 jniThrowException(env, "java/lang/IllegalStateException",
1198 "MediaDrm obj is null");
1199 return;
1200 }
1201
1202 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1203
1204 throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
1205}
1206
1207static void android_media_MediaDrm_removeAllSecureStops(
Jeff Tinker1b51c722014-10-31 00:54:26 -07001208 JNIEnv *env, jobject thiz) {
1209 sp<IDrm> drm = GetDrm(env, thiz);
1210
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001211 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001212 return;
1213 }
1214
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001215 status_t err = drm->removeAllSecureStops();
Jeff Tinker1b51c722014-10-31 00:54:26 -07001216
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001217 throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
Jeff Tinker1b51c722014-10-31 00:54:26 -07001218}
1219
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001220
1221static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1222 switch(level) {
1223 case DrmPlugin::kHdcpLevelUnknown:
1224 return gHdcpLevels.kHdcpLevelUnknown;
1225 case DrmPlugin::kHdcpNone:
1226 return gHdcpLevels.kHdcpNone;
1227 case DrmPlugin::kHdcpV1:
1228 return gHdcpLevels.kHdcpV1;
1229 case DrmPlugin::kHdcpV2:
1230 return gHdcpLevels.kHdcpV2;
1231 case DrmPlugin::kHdcpV2_1:
1232 return gHdcpLevels.kHdcpV2_1;
1233 case DrmPlugin::kHdcpV2_2:
1234 return gHdcpLevels.kHdcpV2_2;
1235 case DrmPlugin::kHdcpNoOutput:
1236 return gHdcpLevels.kHdcpNoOutput;
1237 }
1238 return gHdcpLevels.kHdcpNone;
1239}
1240
1241static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1242 jobject thiz) {
1243 sp<IDrm> drm = GetDrm(env, thiz);
1244
1245 if (!CheckDrm(env, drm)) {
1246 return gHdcpLevels.kHdcpNone;
1247 }
1248
1249 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1250 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1251
1252 status_t err = drm->getHdcpLevels(&connected, &max);
1253
1254 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1255 return gHdcpLevels.kHdcpLevelUnknown;
1256 }
1257 return HdcpLevelTojint(connected);
1258}
1259
1260static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1261 jobject thiz) {
1262 sp<IDrm> drm = GetDrm(env, thiz);
1263
1264 if (!CheckDrm(env, drm)) {
1265 return gHdcpLevels.kHdcpLevelUnknown;
1266 }
1267
1268 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1269 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1270
1271 status_t err = drm->getHdcpLevels(&connected, &max);
1272
1273 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1274 return gHdcpLevels.kHdcpLevelUnknown;
1275 }
1276 return HdcpLevelTojint(max);
1277}
1278
1279static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1280 jobject thiz) {
1281 sp<IDrm> drm = GetDrm(env, thiz);
1282
1283 if (!CheckDrm(env, drm)) {
1284 return 0;
1285 }
1286
1287 uint32_t open = 0, max = 0;
1288 status_t err = drm->getNumberOfSessions(&open, &max);
1289
1290 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1291 return 0;
1292 }
1293 return open;
1294}
1295
1296static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1297 jobject thiz) {
1298 sp<IDrm> drm = GetDrm(env, thiz);
1299
1300 if (!CheckDrm(env, drm)) {
1301 return 0;
1302 }
1303
1304 uint32_t open = 0, max = 0;
1305 status_t err = drm->getNumberOfSessions(&open, &max);
1306
1307 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1308 return 0;
1309 }
1310 return max;
1311}
1312
1313static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1314 jobject thiz, jbyteArray jsessionId) {
1315 sp<IDrm> drm = GetDrm(env, thiz);
1316
1317 if (!CheckSession(env, drm, jsessionId)) {
1318 return gSecurityLevels.kSecurityLevelUnknown;
1319 }
1320
1321 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1322
1323 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1324
1325 status_t err = drm->getSecurityLevel(sessionId, &level);
1326
1327 if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
1328 return gSecurityLevels.kSecurityLevelUnknown;
1329 }
1330
1331 switch(level) {
1332 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1333 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1334 case DrmPlugin::kSecurityLevelSwSecureDecode:
1335 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1336 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1337 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1338 case DrmPlugin::kSecurityLevelHwSecureDecode:
1339 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1340 case DrmPlugin::kSecurityLevelHwSecureAll:
1341 return gSecurityLevels.kSecurityLevelHwSecureAll;
1342 default:
1343 return gSecurityLevels.kSecurityLevelUnknown;
1344 }
1345}
1346
1347
1348static void android_media_MediaDrm_setSecurityLevel(JNIEnv *env,
1349 jobject thiz, jbyteArray jsessionId, jint jlevel) {
1350 sp<IDrm> drm = GetDrm(env, thiz);
1351
1352 if (!CheckSession(env, drm, jsessionId)) {
1353 return;
1354 }
1355
1356 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1357 DrmPlugin::SecurityLevel level;
1358
1359 if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
1360 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
1361 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
1362 level = DrmPlugin::kSecurityLevelSwSecureDecode;
1363 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
1364 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
1365 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
1366 level = DrmPlugin::kSecurityLevelHwSecureDecode;
1367 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
1368 level = DrmPlugin::kSecurityLevelHwSecureAll;
1369 } else {
1370 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1371 return;
1372 }
1373
1374 status_t err = drm->setSecurityLevel(sessionId, level);
1375
1376 if (throwExceptionAsNecessary(env, err, "Failed to set security level")) {
1377 return;
1378 }
1379}
1380
1381
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001382static jstring android_media_MediaDrm_getPropertyString(
1383 JNIEnv *env, jobject thiz, jstring jname) {
1384 sp<IDrm> drm = GetDrm(env, thiz);
1385
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001386 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001387 return NULL;
1388 }
1389
1390 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001391 jniThrowException(env, "java/lang/IllegalArgumentException",
1392 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001393 return NULL;
1394 }
1395
1396 String8 name = JStringToString8(env, jname);
1397 String8 value;
1398
1399 status_t err = drm->getPropertyString(name, value);
1400
1401 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1402 return NULL;
1403 }
1404
1405 return env->NewStringUTF(value.string());
1406}
1407
1408static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1409 JNIEnv *env, jobject thiz, jstring jname) {
1410 sp<IDrm> drm = GetDrm(env, thiz);
1411
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001412 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001413 return NULL;
1414 }
1415
1416 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001417 jniThrowException(env, "java/lang/IllegalArgumentException",
1418 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001419 return NULL;
1420 }
1421
1422 String8 name = JStringToString8(env, jname);
1423 Vector<uint8_t> value;
1424
1425 status_t err = drm->getPropertyByteArray(name, value);
1426
1427 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1428 return NULL;
1429 }
1430
1431 return VectorToJByteArray(env, value);
1432}
1433
1434static void android_media_MediaDrm_setPropertyString(
1435 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1436 sp<IDrm> drm = GetDrm(env, thiz);
1437
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001438 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001439 return;
1440 }
1441
Jeff Tinkereada5372013-05-21 12:48:14 -07001442 if (jname == NULL) {
1443 jniThrowException(env, "java/lang/IllegalArgumentException",
1444 "property name String is null");
1445 return;
1446 }
1447
1448 if (jvalue == NULL) {
1449 jniThrowException(env, "java/lang/IllegalArgumentException",
1450 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001451 return;
1452 }
1453
1454 String8 name = JStringToString8(env, jname);
1455 String8 value = JStringToString8(env, jvalue);
1456
1457 status_t err = drm->setPropertyString(name, value);
1458
1459 throwExceptionAsNecessary(env, err, "Failed to set property");
1460}
1461
1462static void android_media_MediaDrm_setPropertyByteArray(
1463 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1464 sp<IDrm> drm = GetDrm(env, thiz);
1465
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001466 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001467 return;
1468 }
1469
Jeff Tinkereada5372013-05-21 12:48:14 -07001470 if (jname == NULL) {
1471 jniThrowException(env, "java/lang/IllegalArgumentException",
1472 "property name String is null");
1473 return;
1474 }
1475
1476 if (jvalue == NULL) {
1477 jniThrowException(env, "java/lang/IllegalArgumentException",
1478 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001479 return;
1480 }
1481
1482 String8 name = JStringToString8(env, jname);
1483 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1484
1485 status_t err = drm->setPropertyByteArray(name, value);
1486
1487 throwExceptionAsNecessary(env, err, "Failed to set property");
1488}
1489
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001490static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001491 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001492 jstring jalgorithm) {
1493
1494 sp<IDrm> drm = GetDrm(env, jdrm);
1495
1496 if (!CheckSession(env, drm, jsessionId)) {
1497 return;
1498 }
1499
1500 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001501 jniThrowException(env, "java/lang/IllegalArgumentException",
1502 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001503 return;
1504 }
1505
1506 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1507 String8 algorithm = JStringToString8(env, jalgorithm);
1508
1509 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1510
1511 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
1512}
1513
1514static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001515 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001516 jstring jalgorithm) {
1517
1518 sp<IDrm> drm = GetDrm(env, jdrm);
1519
1520 if (!CheckSession(env, drm, jsessionId)) {
1521 return;
1522 }
1523
1524 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001525 jniThrowException(env, "java/lang/IllegalArgumentException",
1526 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001527 return;
1528 }
1529
1530 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1531 String8 algorithm = JStringToString8(env, jalgorithm);
1532
1533 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1534
1535 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1536}
1537
1538
1539static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001540 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001541 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1542
1543 sp<IDrm> drm = GetDrm(env, jdrm);
1544
1545 if (!CheckSession(env, drm, jsessionId)) {
1546 return NULL;
1547 }
1548
1549 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001550 jniThrowException(env, "java/lang/IllegalArgumentException",
1551 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001552 return NULL;
1553 }
1554
1555 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1556 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1557 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1558 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1559 Vector<uint8_t> output;
1560
1561 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1562
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001563 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
1564 return NULL;
1565 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001566
1567 return VectorToJByteArray(env, output);
1568}
1569
1570static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001571 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001572 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1573
1574 sp<IDrm> drm = GetDrm(env, jdrm);
1575
1576 if (!CheckSession(env, drm, jsessionId)) {
1577 return NULL;
1578 }
1579
1580 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001581 jniThrowException(env, "java/lang/IllegalArgumentException",
1582 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001583 return NULL;
1584 }
1585
1586 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1587 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1588 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1589 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1590 Vector<uint8_t> output;
1591
1592 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001593 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
1594 return NULL;
1595 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001596
1597 return VectorToJByteArray(env, output);
1598}
1599
1600static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001601 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001602 jbyteArray jkeyId, jbyteArray jmessage) {
1603
1604 sp<IDrm> drm = GetDrm(env, jdrm);
1605
1606 if (!CheckSession(env, drm, jsessionId)) {
1607 return NULL;
1608 }
1609
1610 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001611 jniThrowException(env, "java/lang/IllegalArgumentException",
1612 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001613 return NULL;
1614 }
1615
1616 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1617 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1618 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1619 Vector<uint8_t> signature;
1620
1621 status_t err = drm->sign(sessionId, keyId, message, signature);
1622
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001623 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1624 return NULL;
1625 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001626
1627 return VectorToJByteArray(env, signature);
1628}
1629
1630static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001631 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001632 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1633
1634 sp<IDrm> drm = GetDrm(env, jdrm);
1635
1636 if (!CheckSession(env, drm, jsessionId)) {
1637 return false;
1638 }
1639
1640 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001641 jniThrowException(env, "java/lang/IllegalArgumentException",
1642 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001643 return false;
1644 }
1645
1646 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1647 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1648 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1649 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1650 bool match;
1651
1652 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1653
1654 throwExceptionAsNecessary(env, err, "Failed to verify");
1655 return match;
1656}
1657
Adam Stonec06e10e2017-12-19 12:54:33 -08001658static jobject
1659android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1660{
1661 sp<IDrm> drm = GetDrm(env, thiz);
1662 if (drm == NULL ) {
1663 jniThrowException(env, "java/lang/IllegalStateException",
1664 "MediaDrm obj is null");
1665 return NULL;
1666 }
1667
1668 // Retrieve current metrics snapshot from drm.
1669 MediaAnalyticsItem item ;
1670 status_t err = drm->getMetrics(&item);
1671 if (err != OK) {
1672 ALOGE("getMetrics failed: %d", (int)err);
1673 return (jobject) NULL;
1674 }
1675
1676 jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, &item, NULL);
1677 if (mybundle == NULL) {
1678 ALOGE("getMetrics metric conversion failed");
1679 }
1680
1681 return mybundle;
1682}
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001683
Jeff Tinkere4095a82014-03-04 13:17:11 -08001684static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001685 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001686 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1687
1688 sp<IDrm> drm = GetDrm(env, jdrm);
1689
1690 if (!CheckSession(env, drm, jsessionId)) {
1691 return NULL;
1692 }
1693
1694 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1695 jniThrowException(env, "java/lang/IllegalArgumentException",
1696 "required argument is null");
1697 return NULL;
1698 }
1699
1700 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1701 String8 algorithm = JStringToString8(env, jalgorithm);
1702 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1703 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1704 Vector<uint8_t> signature;
1705
1706 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1707
1708 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1709 return NULL;
1710 }
1711
1712 return VectorToJByteArray(env, signature);
1713}
1714
1715
Daniel Micay76f6a862015-09-19 17:31:01 -04001716static const JNINativeMethod gMethods[] = {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001717 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
1718
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001719 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
1720
Edwin Wong4d1d84e2017-01-04 09:37:49 -08001721 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001722 (void *)android_media_MediaDrm_native_setup },
1723
Jeff Tinker7cda4912013-08-21 11:52:34 -07001724 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001725 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
1726
1727 { "openSession", "()[B",
1728 (void *)android_media_MediaDrm_openSession },
1729
1730 { "closeSession", "([B)V",
1731 (void *)android_media_MediaDrm_closeSession },
1732
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001733 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
1734 "Landroid/media/MediaDrm$KeyRequest;",
1735 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001736
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001737 { "provideKeyResponse", "([B[B)[B",
1738 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001739
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001740 { "removeKeys", "([B)V",
1741 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001742
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001743 { "restoreKeys", "([B[B)V",
1744 (void *)android_media_MediaDrm_restoreKeys },
1745
1746 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
1747 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001748
Jeff Tinkere4095a82014-03-04 13:17:11 -08001749 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
1750 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001751
Jeff Tinkere4095a82014-03-04 13:17:11 -08001752 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
1753 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001754
1755 { "getSecureStops", "()Ljava/util/List;",
1756 (void *)android_media_MediaDrm_getSecureStops },
1757
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001758 { "getSecureStopIds", "()Ljava/util/List;",
1759 (void *)android_media_MediaDrm_getSecureStopIds },
1760
Jeff Tinker1b51c722014-10-31 00:54:26 -07001761 { "getSecureStop", "([B)[B",
1762 (void *)android_media_MediaDrm_getSecureStop },
1763
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001764 { "releaseSecureStops", "([B)V",
1765 (void *)android_media_MediaDrm_releaseSecureStops },
1766
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001767 { "removeSecureStop", "([B)V",
1768 (void *)android_media_MediaDrm_removeSecureStop },
1769
1770 { "removeAllSecureStops", "()V",
1771 (void *)android_media_MediaDrm_removeAllSecureStops },
Jeff Tinker1b51c722014-10-31 00:54:26 -07001772
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001773 { "getConnectedHdcpLevel", "()I",
1774 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
1775
1776 { "getMaxHdcpLevel", "()I",
1777 (void *)android_media_MediaDrm_getMaxHdcpLevel },
1778
1779 { "getOpenSessionCount", "()I",
1780 (void *)android_media_MediaDrm_getOpenSessionCount },
1781
1782 { "getMaxSessionCount", "()I",
1783 (void *)android_media_MediaDrm_getMaxSessionCount },
1784
1785 { "getSecurityLevel", "([B)I",
1786 (void *)android_media_MediaDrm_getSecurityLevel },
1787
1788 { "setSecurityLevel", "([BI)V",
1789 (void *)android_media_MediaDrm_setSecurityLevel },
1790
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001791 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
1792 (void *)android_media_MediaDrm_getPropertyString },
1793
1794 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
1795 (void *)android_media_MediaDrm_getPropertyByteArray },
1796
1797 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
1798 (void *)android_media_MediaDrm_setPropertyString },
1799
1800 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
1801 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001802
1803 { "setCipherAlgorithmNative",
1804 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1805 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
1806
1807 { "setMacAlgorithmNative",
1808 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1809 (void *)android_media_MediaDrm_setMacAlgorithmNative },
1810
1811 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1812 (void *)android_media_MediaDrm_encryptNative },
1813
1814 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1815 (void *)android_media_MediaDrm_decryptNative },
1816
1817 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
1818 (void *)android_media_MediaDrm_signNative },
1819
1820 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
1821 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08001822
1823 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
1824 (void *)android_media_MediaDrm_signRSANative },
Adam Stonec06e10e2017-12-19 12:54:33 -08001825
1826 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
1827 (void *)android_media_MediaDrm_native_getMetrics },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001828};
1829
1830int register_android_media_Drm(JNIEnv *env) {
1831 return AndroidRuntime::registerNativeMethods(env,
1832 "android/media/MediaDrm", gMethods, NELEM(gMethods));
1833}