blob: 54541f02f575b75dc7b6f8a480f3626fd8cdbe0f [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"
Adam Stone94395c92018-01-30 12:07:00 -080023#include "android_os_Parcel.h"
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080024#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>
Adam Stone94395c92018-01-30 12:07:00 -080032#include <binder/PersistableBundle.h>
Jeff Tinkerdc614f82016-02-12 08:58:32 -080033#include <cutils/properties.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080034#include <media/stagefright/foundation/ADebug.h>
Jeff Tinkerf7568b52013-04-17 14:24:40 -070035#include <media/stagefright/MediaErrors.h>
Jeff Tinkercd4d28f2018-02-16 16:24:49 -080036#include <mediadrm/IDrm.h>
37#include <mediadrm/IMediaDrmService.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080038
Adam Stone94395c92018-01-30 12:07:00 -080039using ::android::os::PersistableBundle;
40
41
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080042namespace android {
43
44#define FIND_CLASS(var, className) \
45 var = env->FindClass(className); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070046 LOG_FATAL_IF(! (var), "Unable to find class " className);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080047
48#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
49 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070050 LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080051
52#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
53 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070054 LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080055
Jeff Tinker54cfbd62013-04-02 13:14:59 -070056#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
57 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070058 LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070059
60#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
61 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070062 LOG_FATAL_IF(! (var), "Unable to find static method " fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070063
Adam Stone94395c92018-01-30 12:07:00 -080064#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldName) \
65 var = env->GetStaticObjectField(clazz, fieldName); \
66 LOG_FATAL_IF(! (var), "Unable to find static object field " fieldName);
67
Jeff Tinker54cfbd62013-04-02 13:14:59 -070068
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080069struct RequestFields {
70 jfieldID data;
71 jfieldID defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -070072 jfieldID requestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080073};
74
75struct ArrayListFields {
76 jmethodID init;
77 jmethodID add;
78};
79
80struct HashmapFields {
81 jmethodID init;
82 jmethodID get;
83 jmethodID put;
84 jmethodID entrySet;
85};
86
87struct SetFields {
88 jmethodID iterator;
89};
90
91struct IteratorFields {
92 jmethodID next;
93 jmethodID hasNext;
94};
95
96struct EntryFields {
97 jmethodID getKey;
98 jmethodID getValue;
99};
100
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700101struct EventTypes {
Jeff Tinker17b89222013-05-21 12:35:06 -0700102 jint kEventProvisionRequired;
103 jint kEventKeyRequired;
104 jint kEventKeyExpired;
105 jint kEventVendorDefined;
Ronghua Wua6d72092015-03-04 11:16:02 -0800106 jint kEventSessionReclaimed;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700107} gEventTypes;
108
Jeff Tinker74797f82015-03-31 15:44:34 -0700109struct EventWhat {
110 jint kWhatDrmEvent;
111 jint kWhatExpirationUpdate;
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700112 jint kWhatKeyStatusChange;
Jeff Tinker74797f82015-03-31 15:44:34 -0700113} gEventWhat;
114
Jeff Tinker17b89222013-05-21 12:35:06 -0700115struct KeyTypes {
116 jint kKeyTypeStreaming;
117 jint kKeyTypeOffline;
118 jint kKeyTypeRelease;
119} gKeyTypes;
120
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700121struct KeyRequestTypes {
122 jint kKeyRequestTypeInitial;
123 jint kKeyRequestTypeRenewal;
124 jint kKeyRequestTypeRelease;
Rahul Frias8f761ba2018-01-22 23:43:54 -0800125 jint kKeyRequestTypeNone;
126 jint kKeyRequestTypeUpdate;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700127} gKeyRequestTypes;
128
Jeff Tinkere4095a82014-03-04 13:17:11 -0800129struct CertificateTypes {
130 jint kCertificateTypeNone;
131 jint kCertificateTypeX509;
132} gCertificateTypes;
133
134struct CertificateFields {
135 jfieldID wrappedPrivateKey;
136 jfieldID certificateData;
137};
138
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700139struct StateExceptionFields {
140 jmethodID init;
141 jclass classId;
142};
143
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800144struct HDCPLevels {
145 jint kHdcpLevelUnknown;
146 jint kHdcpNone;
147 jint kHdcpV1;
148 jint kHdcpV2;
149 jint kHdcpV2_1;
150 jint kHdcpV2_2;
151 jint kHdcpNoOutput;
152} gHdcpLevels;
153
154struct SecurityLevels {
155 jint kSecurityLevelUnknown;
Jeff Tinker2bca5252018-02-11 18:59:14 +0000156 jint kSecurityLevelMax;
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800157 jint kSecurityLevelSwSecureCrypto;
158 jint kSecurityLevelSwSecureDecode;
159 jint kSecurityLevelHwSecureCrypto;
160 jint kSecurityLevelHwSecureDecode;
161 jint kSecurityLevelHwSecureAll;
162} gSecurityLevels;
163
164
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800165struct fields_t {
166 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700167 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700168 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800169 RequestFields provisionRequest;
170 ArrayListFields arraylist;
171 HashmapFields hashmap;
172 SetFields set;
173 IteratorFields iterator;
174 EntryFields entry;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800175 CertificateFields certificate;
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700176 StateExceptionFields stateException;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800177 jclass certificateClassId;
178 jclass hashmapClassId;
179 jclass arraylistClassId;
180 jclass stringClassId;
Adam Stone94395c92018-01-30 12:07:00 -0800181 jobject bundleCreator;
182 jmethodID createFromParcelId;
183 jclass parcelCreatorClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800184};
185
186static fields_t gFields;
187
Adam Stone94395c92018-01-30 12:07:00 -0800188namespace {
189
190// Helper function to convert a native PersistableBundle to a Java
191// PersistableBundle.
192jobject nativeToJavaPersistableBundle(JNIEnv *env, jobject thiz,
193 PersistableBundle* nativeBundle) {
194 if (env == NULL || thiz == NULL || nativeBundle == NULL) {
195 ALOGE("Unexpected NULL parmeter");
196 return NULL;
197 }
198
199 // Create a Java parcel with the native parcel data.
200 // Then create a new PersistableBundle with that parcel as a parameter.
201 jobject jParcel = android::createJavaParcelObject(env);
202 if (jParcel == NULL) {
203 ALOGE("Failed to create a Java Parcel.");
204 return NULL;
205 }
206
207 android::Parcel* nativeParcel = android::parcelForJavaObject(env, jParcel);
208 if (nativeParcel == NULL) {
209 ALOGE("Failed to get the native Parcel.");
210 return NULL;
211 }
212
213 android::status_t result = nativeBundle->writeToParcel(nativeParcel);
214 nativeParcel->setDataPosition(0);
215 if (result != android::OK) {
216 ALOGE("Failed to write nativeBundle to Parcel: %d.", result);
217 return NULL;
218 }
219
220 jobject newBundle = env->CallObjectMethod(gFields.bundleCreator,
221 gFields.createFromParcelId,
222 jParcel);
223 if (newBundle == NULL) {
224 ALOGE("Failed to create a new PersistableBundle "
225 "from the createFromParcel call.");
226 }
227
228 return newBundle;
229}
230
231} // namespace anonymous
232
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700233// ----------------------------------------------------------------------------
234// ref-counted object for callbacks
235class JNIDrmListener: public DrmListener
236{
237public:
238 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
239 ~JNIDrmListener();
240 virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
241private:
242 JNIDrmListener();
243 jclass mClass; // Reference to MediaDrm class
244 jobject mObject; // Weak ref to MediaDrm Java object to call on
245};
246
247JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
248{
249 // Hold onto the MediaDrm class for use in calling the static method
250 // that posts events to the application thread.
251 jclass clazz = env->GetObjectClass(thiz);
252 if (clazz == NULL) {
253 ALOGE("Can't find android/media/MediaDrm");
Jeff Tinkereada5372013-05-21 12:48:14 -0700254 jniThrowException(env, "java/lang/Exception",
255 "Can't find android/media/MediaDrm");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700256 return;
257 }
258 mClass = (jclass)env->NewGlobalRef(clazz);
259
260 // We use a weak reference so the MediaDrm object can be garbage collected.
261 // The reference is only used as a proxy for callbacks.
262 mObject = env->NewGlobalRef(weak_thiz);
263}
264
265JNIDrmListener::~JNIDrmListener()
266{
267 // remove global references
268 JNIEnv *env = AndroidRuntime::getJNIEnv();
269 env->DeleteGlobalRef(mObject);
270 env->DeleteGlobalRef(mClass);
271}
272
273void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
274 const Parcel *obj)
275{
Jeff Tinker74797f82015-03-31 15:44:34 -0700276 jint jwhat;
277 jint jeventType = 0;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700278
279 // translate DrmPlugin event types into their java equivalents
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700280 switch (eventType) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700281 case DrmPlugin::kDrmPluginEventProvisionRequired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700282 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700283 jeventType = gEventTypes.kEventProvisionRequired;
284 break;
285 case DrmPlugin::kDrmPluginEventKeyNeeded:
Jeff Tinker74797f82015-03-31 15:44:34 -0700286 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700287 jeventType = gEventTypes.kEventKeyRequired;
288 break;
289 case DrmPlugin::kDrmPluginEventKeyExpired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700290 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700291 jeventType = gEventTypes.kEventKeyExpired;
292 break;
293 case DrmPlugin::kDrmPluginEventVendorDefined:
Jeff Tinker74797f82015-03-31 15:44:34 -0700294 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700295 jeventType = gEventTypes.kEventVendorDefined;
296 break;
Ronghua Wua6d72092015-03-04 11:16:02 -0800297 case DrmPlugin::kDrmPluginEventSessionReclaimed:
Jeff Tinker74797f82015-03-31 15:44:34 -0700298 jwhat = gEventWhat.kWhatDrmEvent;
Ronghua Wua6d72092015-03-04 11:16:02 -0800299 jeventType = gEventTypes.kEventSessionReclaimed;
300 break;
Jeff Tinker74797f82015-03-31 15:44:34 -0700301 case DrmPlugin::kDrmPluginEventExpirationUpdate:
302 jwhat = gEventWhat.kWhatExpirationUpdate;
303 break;
304 case DrmPlugin::kDrmPluginEventKeysChange:
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700305 jwhat = gEventWhat.kWhatKeyStatusChange;
Jeff Tinker74797f82015-03-31 15:44:34 -0700306 break;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700307 default:
308 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
309 return;
310 }
311
312 JNIEnv *env = AndroidRuntime::getJNIEnv();
313 if (obj && obj->dataSize() > 0) {
314 jobject jParcel = createJavaParcelObject(env);
315 if (jParcel != NULL) {
316 Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
317 nativeParcel->setData(obj->data(), obj->dataSize());
318 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
Jeff Tinker74797f82015-03-31 15:44:34 -0700319 jwhat, jeventType, extra, jParcel);
Patrik2 Carlsson265551a2013-12-10 14:52:43 +0100320 env->DeleteLocalRef(jParcel);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700321 }
322 }
323
324 if (env->ExceptionCheck()) {
325 ALOGW("An exception occurred while notifying an event.");
326 LOGW_EX(env);
327 env->ExceptionClear();
328 }
329}
330
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700331static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
332 ALOGE("Illegal state exception: %s (%d)", msg, err);
333
334 jobject exception = env->NewObject(gFields.stateException.classId,
335 gFields.stateException.init, static_cast<int>(err),
336 env->NewStringUTF(msg));
337 env->Throw(static_cast<jthrowable>(exception));
338}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700339
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800340static bool throwExceptionAsNecessary(
341 JNIEnv *env, status_t err, const char *msg = NULL) {
342
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700343 const char *drmMessage = NULL;
344
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700345 switch (err) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700346 case ERROR_DRM_UNKNOWN:
347 drmMessage = "General DRM error";
348 break;
349 case ERROR_DRM_NO_LICENSE:
350 drmMessage = "No license";
351 break;
352 case ERROR_DRM_LICENSE_EXPIRED:
353 drmMessage = "License expired";
354 break;
355 case ERROR_DRM_SESSION_NOT_OPENED:
356 drmMessage = "Session not opened";
357 break;
358 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
359 drmMessage = "Not initialized";
360 break;
361 case ERROR_DRM_DECRYPT:
362 drmMessage = "Decrypt error";
363 break;
364 case ERROR_DRM_CANNOT_HANDLE:
Jeff Tinkereb13c762017-11-01 15:29:38 -0700365 drmMessage = "Invalid parameter or data format";
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700366 break;
367 case ERROR_DRM_TAMPER_DETECTED:
368 drmMessage = "Invalid state";
369 break;
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700370 default:
371 break;
372 }
373
374 String8 vendorMessage;
375 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
Jeff Tinker29799862014-08-27 11:05:13 -0700376 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700377 drmMessage = vendorMessage.string();
378 }
379
Jeff Tinkereb13c762017-11-01 15:29:38 -0700380 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800381 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
382 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700383 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
384 jniThrowException(env, "android/media/NotProvisionedException", msg);
385 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700386 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
387 jniThrowException(env, "android/media/ResourceBusyException", msg);
388 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700389 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
390 jniThrowException(env, "android/media/DeniedByServerException", msg);
391 return true;
Jeff Tinker314b7f32015-06-15 17:45:43 -0700392 } else if (err == DEAD_OBJECT) {
393 jniThrowException(env, "android/media/MediaDrmResetException",
394 "mediaserver died");
395 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800396 } else if (err != OK) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700397 String8 errbuf;
398 if (drmMessage != NULL) {
399 if (msg == NULL) {
400 msg = drmMessage;
401 } else {
Jeff Tinker29799862014-08-27 11:05:13 -0700402 errbuf = String8::format("%s: %s", msg, drmMessage);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700403 msg = errbuf.string();
404 }
405 }
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700406 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800407 return true;
408 }
409 return false;
410}
411
412static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000413 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800414 return jdrm ? jdrm->getDrm() : NULL;
415}
416
417JDrm::JDrm(
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800418 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
419 const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800420 mObject = env->NewWeakGlobalRef(thiz);
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800421 mDrm = MakeDrm(uuid, appPackageName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700422 if (mDrm != NULL) {
423 mDrm->setListener(this);
424 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800425}
426
427JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800428 JNIEnv *env = AndroidRuntime::getJNIEnv();
429
430 env->DeleteWeakGlobalRef(mObject);
431 mObject = NULL;
432}
433
434// static
435sp<IDrm> JDrm::MakeDrm() {
436 sp<IServiceManager> sm = defaultServiceManager();
437
Jeff Tinkerd12b7c02016-04-22 17:50:33 -0700438 sp<IBinder> binder = sm->getService(String16("media.drm"));
439 sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
440 if (service == NULL) {
441 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800442 }
443
Jeff Tinkerd12b7c02016-04-22 17:50:33 -0700444 sp<IDrm> drm = service->makeDrm();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800445 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
446 return NULL;
447 }
448
449 return drm;
450}
451
452// static
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800453sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800454 sp<IDrm> drm = MakeDrm();
455
456 if (drm == NULL) {
457 return NULL;
458 }
459
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800460 status_t err = drm->createPlugin(uuid, appPackageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800461
462 if (err != OK) {
463 return NULL;
464 }
465
466 return drm;
467}
468
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700469status_t JDrm::setListener(const sp<DrmListener>& listener) {
470 Mutex::Autolock lock(mLock);
471 mListener = listener;
472 return OK;
473}
474
475void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
476 sp<DrmListener> listener;
477 mLock.lock();
478 listener = mListener;
479 mLock.unlock();
480
481 if (listener != NULL) {
482 Mutex::Autolock lock(mNotifyLock);
483 listener->notify(eventType, extra, obj);
484 }
485}
486
Jeff Tinker600071c2014-04-11 16:11:15 -0700487void JDrm::disconnect() {
488 if (mDrm != NULL) {
489 mDrm->destroyPlugin();
490 mDrm.clear();
491 }
492}
493
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700494
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800495// static
Jeff Tinker7cda4912013-08-21 11:52:34 -0700496bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800497 sp<IDrm> drm = MakeDrm();
498
499 if (drm == NULL) {
500 return false;
501 }
502
Jeff Tinker7cda4912013-08-21 11:52:34 -0700503 return drm->isCryptoSchemeSupported(uuid, mimeType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800504}
505
506status_t JDrm::initCheck() const {
507 return mDrm == NULL ? NO_INIT : OK;
508}
509
510// JNI conversion utilities
511static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
512 Vector<uint8_t> vector;
513 size_t length = env->GetArrayLength(byteArray);
514 vector.insertAt((size_t)0, length);
515 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
516 return vector;
517}
518
519static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
520 size_t length = vector.size();
521 jbyteArray result = env->NewByteArray(length);
522 if (result != NULL) {
523 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
524 }
525 return result;
526}
527
528static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800529 String8 result;
530
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700531 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800532 if (s) {
533 result = s;
534 env->ReleaseStringUTFChars(jstr, s);
535 }
536 return result;
537}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700538
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800539/*
540 import java.util.HashMap;
541 import java.util.Set;
542 import java.Map.Entry;
543 import jav.util.Iterator;
544
545 HashMap<k, v> hm;
546 Set<Entry<k, v> > s = hm.entrySet();
547 Iterator i = s.iterator();
548 Entry e = s.next();
549*/
550
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200551static KeyedVector<String8, String8> HashMapToKeyedVector(
552 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800553 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800554 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200555 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800556
557 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
558 if (entrySet) {
559 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
560 if (iterator) {
561 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
562 while (hasNext) {
563 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
564 if (entry) {
565 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200566 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700567 jniThrowException(env, "java/lang/IllegalArgumentException",
568 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200569 env->DeleteLocalRef(entry);
570 *pIsOK = false;
571 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800572 }
573 jstring jkey = static_cast<jstring>(obj);
574
575 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200576 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700577 jniThrowException(env, "java/lang/IllegalArgumentException",
578 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200579 env->DeleteLocalRef(entry);
580 *pIsOK = false;
581 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800582 }
583 jstring jvalue = static_cast<jstring>(obj);
584
585 String8 key = JStringToString8(env, jkey);
586 String8 value = JStringToString8(env, jvalue);
587 keyedVector.add(key, value);
588
589 env->DeleteLocalRef(jkey);
590 env->DeleteLocalRef(jvalue);
591 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
592 }
593 env->DeleteLocalRef(entry);
594 }
595 env->DeleteLocalRef(iterator);
596 }
597 env->DeleteLocalRef(entrySet);
598 }
599 return keyedVector;
600}
601
602static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800603 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800604 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
605 for (size_t i = 0; i < map.size(); ++i) {
606 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
607 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
608 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
609 env->DeleteLocalRef(jkey);
610 env->DeleteLocalRef(jvalue);
611 }
612 return hashMap;
613}
614
615static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
616 List<Vector<uint8_t> > list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800617 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800618 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
619 List<Vector<uint8_t> >::iterator iter = list.begin();
620 while (iter != list.end()) {
621 jbyteArray byteArray = VectorToJByteArray(env, *iter);
622 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
623 env->DeleteLocalRef(byteArray);
624 iter++;
625 }
626
627 return arrayList;
628}
629
630} // namespace android
631
632using namespace android;
633
634static sp<JDrm> setDrm(
635 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000636 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800637 if (drm != NULL) {
638 drm->incStrong(thiz);
639 }
640 if (old != NULL) {
641 old->decStrong(thiz);
642 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000643 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800644
645 return old;
646}
647
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800648static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800649 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700650 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800651 return false;
652 }
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800653 return true;
654}
655
656static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
657{
658 if (!CheckDrm(env, drm)) {
659 return false;
660 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800661
662 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700663 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800664 return false;
665 }
666 return true;
667}
668
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800669static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700670 sp<JDrm> drm = setDrm(env, thiz, NULL);
671 if (drm != NULL) {
672 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700673 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700674 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800675}
676
677static void android_media_MediaDrm_native_init(JNIEnv *env) {
678 jclass clazz;
679 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000680 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700681 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
Jeff Tinker74797f82015-03-31 15:44:34 -0700682 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700683
684 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700685 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700686 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700687 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700688 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700689 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700690 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700691 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700692 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Ronghua Wua6d72092015-03-04 11:16:02 -0800693 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
694 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800695
Jeff Tinker74797f82015-03-31 15:44:34 -0700696 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
697 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
698 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
699 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700700 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
701 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
Jeff Tinker74797f82015-03-31 15:44:34 -0700702
Jeff Tinker17b89222013-05-21 12:35:06 -0700703 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
704 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
705 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
706 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
707 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
708 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
709
Jeff Tinkere4095a82014-03-04 13:17:11 -0800710 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
711 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
712 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
713 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
714
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800715 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
716 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
717 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
718 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
719 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
720 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
721 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
722 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
723 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
724 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
725 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
726 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
727 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
728 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
729
730 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
731 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700732 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800733 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700734 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800735 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700736 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800737 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700738 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800739 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700740 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800741 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
742
Jeff Tinker2bca5252018-02-11 18:59:14 +0000743 jmethodID getMaxSecurityLevel;
744 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
745 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
746
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700747 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700748 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
749 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700750 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800751
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700752 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
753 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
754 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
755 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
756 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
757 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
Rahul Frias8f761ba2018-01-22 23:43:54 -0800758 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
759 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
760 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
761 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700762
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800763 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700764 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
765 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800766
Jeff Tinkere4095a82014-03-04 13:17:11 -0800767 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
768 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
769 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700770 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800771
Adam Stone94395c92018-01-30 12:07:00 -0800772 // Metrics-related fields and classes.
773 FIND_CLASS(clazz, "android/os/PersistableBundle");
774 jfieldID bundleCreatorId;
775 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
776 "Landroid/os/Parcelable$Creator;");
777 jobject bundleCreator;
778 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
779 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
780 FIND_CLASS(clazz, "android/os/Parcelable$Creator");
781 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
782 "(Landroid/os/Parcel;)Ljava/lang/Object;");
783 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
784
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800785 FIND_CLASS(clazz, "java/util/ArrayList");
786 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
787 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
788
789 FIND_CLASS(clazz, "java/util/HashMap");
790 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
791 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
792 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
793 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
794 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
795
796 FIND_CLASS(clazz, "java/util/Set");
797 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
798
799 FIND_CLASS(clazz, "java/util/Iterator");
800 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
801 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
802
803 FIND_CLASS(clazz, "java/util/Map$Entry");
804 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
805 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800806
807 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700808 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800809
810 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700811 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800812
813 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700814 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700815
816 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
817 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
818 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800819}
820
821static void android_media_MediaDrm_native_setup(
822 JNIEnv *env, jobject thiz,
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800823 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800824
825 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700826 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800827 return;
828 }
829
830 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
831
832 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700833 jniThrowException(env, "java/lang/IllegalArgumentException",
834 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800835 return;
836 }
837
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800838 String8 packageName;
839 if (jappPackageName == NULL) {
840 jniThrowException(env, "java/lang/IllegalArgumentException",
841 "application package name cannot be null");
842 return;
843 }
844
845 packageName = JStringToString8(env, jappPackageName);
846 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800847
848 status_t err = drm->initCheck();
849
850 if (err != OK) {
851 jniThrowException(
852 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700853 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800854 "Failed to instantiate drm object.");
855 return;
856 }
857
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700858 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
859 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800860 setDrm(env, thiz, drm);
861}
862
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800863static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800864 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800865
866 if (uuidObj == NULL) {
867 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
868 return false;
869 }
870
871 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
872
873 if (uuid.size() != 16) {
874 jniThrowException(
875 env,
876 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -0700877 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800878 return false;
879 }
880
Jeff Tinker7cda4912013-08-21 11:52:34 -0700881 String8 mimeType;
882 if (jmimeType != NULL) {
883 mimeType = JStringToString8(env, jmimeType);
884 }
885
886 return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800887}
888
889static jbyteArray android_media_MediaDrm_openSession(
Jeff Tinker2bca5252018-02-11 18:59:14 +0000890 JNIEnv *env, jobject thiz, jint jlevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800891 sp<IDrm> drm = GetDrm(env, thiz);
892
893 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700894 jniThrowException(env, "java/lang/IllegalStateException",
895 "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800896 return NULL;
897 }
898
899 Vector<uint8_t> sessionId;
Jeff Tinker2bca5252018-02-11 18:59:14 +0000900 DrmPlugin::SecurityLevel level;
901
902 if (jlevel == gSecurityLevels.kSecurityLevelMax) {
903 level = DrmPlugin::kSecurityLevelMax;
904 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
905 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
906 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
907 level = DrmPlugin::kSecurityLevelSwSecureDecode;
908 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
909 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
910 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
911 level = DrmPlugin::kSecurityLevelHwSecureDecode;
912 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
913 level = DrmPlugin::kSecurityLevelHwSecureAll;
914 } else {
915 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
916 return NULL;
917 }
918
919 status_t err = drm->openSession(level, sessionId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800920
921 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
922 return NULL;
923 }
924
925 return VectorToJByteArray(env, sessionId);
926}
927
928static void android_media_MediaDrm_closeSession(
929 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
930 sp<IDrm> drm = GetDrm(env, thiz);
931
932 if (!CheckSession(env, drm, jsessionId)) {
933 return;
934 }
935
936 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
937
938 status_t err = drm->closeSession(sessionId);
939
940 throwExceptionAsNecessary(env, err, "Failed to close session");
941}
942
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700943static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800944 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700945 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800946 sp<IDrm> drm = GetDrm(env, thiz);
947
948 if (!CheckSession(env, drm, jsessionId)) {
949 return NULL;
950 }
951
952 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
953
954 Vector<uint8_t> initData;
955 if (jinitData != NULL) {
956 initData = JByteArrayToVector(env, jinitData);
957 }
958
959 String8 mimeType;
960 if (jmimeType != NULL) {
961 mimeType = JStringToString8(env, jmimeType);
962 }
963
Jeff Tinker17b89222013-05-21 12:35:06 -0700964 DrmPlugin::KeyType keyType;
965 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
966 keyType = DrmPlugin::kKeyType_Streaming;
967 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
968 keyType = DrmPlugin::kKeyType_Offline;
969 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
970 keyType = DrmPlugin::kKeyType_Release;
971 } else {
972 jniThrowException(env, "java/lang/IllegalArgumentException",
973 "invalid keyType");
974 return NULL;
975 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800976
977 KeyedVector<String8, String8> optParams;
978 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200979 bool isOK;
980 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
981 if (!isOK) {
982 return NULL;
983 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800984 }
985
986 Vector<uint8_t> request;
987 String8 defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700988 DrmPlugin::KeyRequestType keyRequestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800989
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700990 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700991 keyType, optParams, request, defaultUrl, &keyRequestType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800992
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700993 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800994 return NULL;
995 }
996
997 // Fill out return obj
998 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700999 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001000
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001001 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001002
1003 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001004 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001005 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001006 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001007
1008 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001009 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001010
1011 switch (keyRequestType) {
1012 case DrmPlugin::kKeyRequestType_Initial:
1013 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1014 gKeyRequestTypes.kKeyRequestTypeInitial);
1015 break;
1016 case DrmPlugin::kKeyRequestType_Renewal:
1017 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1018 gKeyRequestTypes.kKeyRequestTypeRenewal);
1019 break;
1020 case DrmPlugin::kKeyRequestType_Release:
1021 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1022 gKeyRequestTypes.kKeyRequestTypeRelease);
1023 break;
Rahul Frias8f761ba2018-01-22 23:43:54 -08001024 case DrmPlugin::kKeyRequestType_None:
1025 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1026 gKeyRequestTypes.kKeyRequestTypeNone);
1027 break;
1028 case DrmPlugin::kKeyRequestType_Update:
1029 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1030 gKeyRequestTypes.kKeyRequestTypeUpdate);
1031 break;
1032
Jeff Tinker74797f82015-03-31 15:44:34 -07001033 default:
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001034 throwStateException(env, "DRM plugin failure: unknown key request type",
1035 ERROR_DRM_UNKNOWN);
1036 break;
1037 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001038 }
1039
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001040 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001041}
1042
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001043static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001044 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
1045 sp<IDrm> drm = GetDrm(env, thiz);
1046
1047 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001048 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001049 }
1050
1051 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1052
1053 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001054 jniThrowException(env, "java/lang/IllegalArgumentException",
1055 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001056 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001057 }
1058 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001059 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001060
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001061 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001062
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001063 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
1064 return NULL;
1065 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001066 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001067}
1068
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001069static void android_media_MediaDrm_removeKeys(
1070 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
1071 sp<IDrm> drm = GetDrm(env, thiz);
1072
1073 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001074 jniThrowException(env, "java/lang/IllegalArgumentException",
1075 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001076 return;
1077 }
1078
1079 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1080
1081 status_t err = drm->removeKeys(keySetId);
1082
1083 throwExceptionAsNecessary(env, err, "Failed to remove keys");
1084}
1085
1086static void android_media_MediaDrm_restoreKeys(
1087 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
1088 jbyteArray jkeysetId) {
1089
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001090 sp<IDrm> drm = GetDrm(env, thiz);
1091
1092 if (!CheckSession(env, drm, jsessionId)) {
1093 return;
1094 }
1095
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001096 if (jkeysetId == NULL) {
1097 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1098 return;
1099 }
1100
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001101 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001102 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001103
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001104 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001105
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001106 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001107}
1108
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001109static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001110 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1111 sp<IDrm> drm = GetDrm(env, thiz);
1112
1113 if (!CheckSession(env, drm, jsessionId)) {
1114 return NULL;
1115 }
1116 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1117
1118 KeyedVector<String8, String8> infoMap;
1119
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001120 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001121
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001122 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001123 return NULL;
1124 }
1125
1126 return KeyedVectorToHashMap(env, infoMap);
1127}
1128
Jeff Tinkere4095a82014-03-04 13:17:11 -08001129static jobject android_media_MediaDrm_getProvisionRequestNative(
1130 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001131 sp<IDrm> drm = GetDrm(env, thiz);
1132
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001133 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001134 return NULL;
1135 }
1136
1137 Vector<uint8_t> request;
1138 String8 defaultUrl;
1139
Jeff Tinkere4095a82014-03-04 13:17:11 -08001140 String8 certType;
1141 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1142 certType = "X.509";
1143 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1144 certType = "none";
1145 } else {
1146 certType = "invalid";
1147 }
1148
1149 String8 certAuthority = JStringToString8(env, jcertAuthority);
1150 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001151
1152 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
1153 return NULL;
1154 }
1155
1156 // Fill out return obj
1157 jclass clazz;
1158 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1159
1160 jobject provisionObj = NULL;
1161
1162 if (clazz) {
1163 provisionObj = env->AllocObject(clazz);
1164 jbyteArray jrequest = VectorToJByteArray(env, request);
1165 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1166
1167 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1168 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1169 }
1170
1171 return provisionObj;
1172}
1173
Jeff Tinkere4095a82014-03-04 13:17:11 -08001174static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001175 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1176 sp<IDrm> drm = GetDrm(env, thiz);
1177
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001178 if (!CheckDrm(env, drm)) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001179 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001180 }
1181
1182 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001183 jniThrowException(env, "java/lang/IllegalArgumentException",
1184 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001185 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001186 }
1187
1188 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -08001189 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001190
Jeff Tinkere4095a82014-03-04 13:17:11 -08001191 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1192
1193 // Fill out return obj
1194 jclass clazz = gFields.certificateClassId;
1195
1196 jobject certificateObj = NULL;
1197
1198 if (clazz && certificate.size() && wrappedKey.size()) {
1199 certificateObj = env->AllocObject(clazz);
1200 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1201 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1202
1203 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1204 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1205 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001206
1207 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001208 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001209}
1210
1211static jobject android_media_MediaDrm_getSecureStops(
1212 JNIEnv *env, jobject thiz) {
1213 sp<IDrm> drm = GetDrm(env, thiz);
1214
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001215 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001216 return NULL;
1217 }
1218
1219 List<Vector<uint8_t> > secureStops;
1220
1221 status_t err = drm->getSecureStops(secureStops);
1222
1223 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
1224 return NULL;
1225 }
1226
1227 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1228}
1229
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001230static jobject android_media_MediaDrm_getSecureStopIds(
1231 JNIEnv *env, jobject thiz) {
1232 sp<IDrm> drm = GetDrm(env, thiz);
1233
1234 if (drm == NULL) {
1235 jniThrowException(env, "java/lang/IllegalStateException",
1236 "MediaDrm obj is null");
1237 return NULL;
1238 }
1239
1240 List<Vector<uint8_t> > secureStopIds;
1241
1242 status_t err = drm->getSecureStopIds(secureStopIds);
1243
1244 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
1245 return NULL;
1246 }
1247
1248 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1249}
1250
Jeff Tinker1b51c722014-10-31 00:54:26 -07001251static jbyteArray android_media_MediaDrm_getSecureStop(
1252 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1253 sp<IDrm> drm = GetDrm(env, thiz);
1254
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001255 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001256 return NULL;
1257 }
1258
1259 Vector<uint8_t> secureStop;
1260
1261 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1262
1263 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
1264 return NULL;
1265 }
1266
1267 return VectorToJByteArray(env, secureStop);
1268}
1269
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001270static void android_media_MediaDrm_releaseSecureStops(
1271 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1272 sp<IDrm> drm = GetDrm(env, thiz);
1273
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001274 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001275 return;
1276 }
1277
1278 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1279
1280 status_t err = drm->releaseSecureStops(ssRelease);
1281
1282 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
1283}
1284
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001285static void android_media_MediaDrm_removeSecureStop(
1286 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1287 sp<IDrm> drm = GetDrm(env, thiz);
1288
1289 if (drm == NULL) {
1290 jniThrowException(env, "java/lang/IllegalStateException",
1291 "MediaDrm obj is null");
1292 return;
1293 }
1294
1295 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1296
1297 throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
1298}
1299
1300static void android_media_MediaDrm_removeAllSecureStops(
Jeff Tinker1b51c722014-10-31 00:54:26 -07001301 JNIEnv *env, jobject thiz) {
1302 sp<IDrm> drm = GetDrm(env, thiz);
1303
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001304 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001305 return;
1306 }
1307
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001308 status_t err = drm->removeAllSecureStops();
Jeff Tinker1b51c722014-10-31 00:54:26 -07001309
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001310 throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
Jeff Tinker1b51c722014-10-31 00:54:26 -07001311}
1312
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001313
1314static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1315 switch(level) {
1316 case DrmPlugin::kHdcpLevelUnknown:
1317 return gHdcpLevels.kHdcpLevelUnknown;
1318 case DrmPlugin::kHdcpNone:
1319 return gHdcpLevels.kHdcpNone;
1320 case DrmPlugin::kHdcpV1:
1321 return gHdcpLevels.kHdcpV1;
1322 case DrmPlugin::kHdcpV2:
1323 return gHdcpLevels.kHdcpV2;
1324 case DrmPlugin::kHdcpV2_1:
1325 return gHdcpLevels.kHdcpV2_1;
1326 case DrmPlugin::kHdcpV2_2:
1327 return gHdcpLevels.kHdcpV2_2;
1328 case DrmPlugin::kHdcpNoOutput:
1329 return gHdcpLevels.kHdcpNoOutput;
1330 }
1331 return gHdcpLevels.kHdcpNone;
1332}
1333
1334static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1335 jobject thiz) {
1336 sp<IDrm> drm = GetDrm(env, thiz);
1337
1338 if (!CheckDrm(env, drm)) {
1339 return gHdcpLevels.kHdcpNone;
1340 }
1341
1342 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1343 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1344
1345 status_t err = drm->getHdcpLevels(&connected, &max);
1346
1347 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1348 return gHdcpLevels.kHdcpLevelUnknown;
1349 }
1350 return HdcpLevelTojint(connected);
1351}
1352
1353static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1354 jobject thiz) {
1355 sp<IDrm> drm = GetDrm(env, thiz);
1356
1357 if (!CheckDrm(env, drm)) {
1358 return gHdcpLevels.kHdcpLevelUnknown;
1359 }
1360
1361 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1362 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1363
1364 status_t err = drm->getHdcpLevels(&connected, &max);
1365
1366 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1367 return gHdcpLevels.kHdcpLevelUnknown;
1368 }
1369 return HdcpLevelTojint(max);
1370}
1371
1372static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1373 jobject thiz) {
1374 sp<IDrm> drm = GetDrm(env, thiz);
1375
1376 if (!CheckDrm(env, drm)) {
1377 return 0;
1378 }
1379
1380 uint32_t open = 0, max = 0;
1381 status_t err = drm->getNumberOfSessions(&open, &max);
1382
1383 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1384 return 0;
1385 }
1386 return open;
1387}
1388
1389static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1390 jobject thiz) {
1391 sp<IDrm> drm = GetDrm(env, thiz);
1392
1393 if (!CheckDrm(env, drm)) {
1394 return 0;
1395 }
1396
1397 uint32_t open = 0, max = 0;
1398 status_t err = drm->getNumberOfSessions(&open, &max);
1399
1400 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1401 return 0;
1402 }
1403 return max;
1404}
1405
1406static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1407 jobject thiz, jbyteArray jsessionId) {
1408 sp<IDrm> drm = GetDrm(env, thiz);
1409
1410 if (!CheckSession(env, drm, jsessionId)) {
1411 return gSecurityLevels.kSecurityLevelUnknown;
1412 }
1413
1414 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1415
1416 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1417
1418 status_t err = drm->getSecurityLevel(sessionId, &level);
1419
1420 if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
1421 return gSecurityLevels.kSecurityLevelUnknown;
1422 }
1423
1424 switch(level) {
1425 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1426 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1427 case DrmPlugin::kSecurityLevelSwSecureDecode:
1428 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1429 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1430 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1431 case DrmPlugin::kSecurityLevelHwSecureDecode:
1432 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1433 case DrmPlugin::kSecurityLevelHwSecureAll:
1434 return gSecurityLevels.kSecurityLevelHwSecureAll;
1435 default:
1436 return gSecurityLevels.kSecurityLevelUnknown;
1437 }
1438}
1439
1440
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001441static jstring android_media_MediaDrm_getPropertyString(
1442 JNIEnv *env, jobject thiz, jstring jname) {
1443 sp<IDrm> drm = GetDrm(env, thiz);
1444
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001445 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001446 return NULL;
1447 }
1448
1449 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001450 jniThrowException(env, "java/lang/IllegalArgumentException",
1451 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001452 return NULL;
1453 }
1454
1455 String8 name = JStringToString8(env, jname);
1456 String8 value;
1457
1458 status_t err = drm->getPropertyString(name, value);
1459
1460 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1461 return NULL;
1462 }
1463
1464 return env->NewStringUTF(value.string());
1465}
1466
1467static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1468 JNIEnv *env, jobject thiz, jstring jname) {
1469 sp<IDrm> drm = GetDrm(env, thiz);
1470
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001471 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001472 return NULL;
1473 }
1474
1475 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001476 jniThrowException(env, "java/lang/IllegalArgumentException",
1477 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001478 return NULL;
1479 }
1480
1481 String8 name = JStringToString8(env, jname);
1482 Vector<uint8_t> value;
1483
1484 status_t err = drm->getPropertyByteArray(name, value);
1485
1486 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1487 return NULL;
1488 }
1489
1490 return VectorToJByteArray(env, value);
1491}
1492
1493static void android_media_MediaDrm_setPropertyString(
1494 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1495 sp<IDrm> drm = GetDrm(env, thiz);
1496
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001497 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001498 return;
1499 }
1500
Jeff Tinkereada5372013-05-21 12:48:14 -07001501 if (jname == NULL) {
1502 jniThrowException(env, "java/lang/IllegalArgumentException",
1503 "property name String is null");
1504 return;
1505 }
1506
1507 if (jvalue == NULL) {
1508 jniThrowException(env, "java/lang/IllegalArgumentException",
1509 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001510 return;
1511 }
1512
1513 String8 name = JStringToString8(env, jname);
1514 String8 value = JStringToString8(env, jvalue);
1515
1516 status_t err = drm->setPropertyString(name, value);
1517
1518 throwExceptionAsNecessary(env, err, "Failed to set property");
1519}
1520
1521static void android_media_MediaDrm_setPropertyByteArray(
1522 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1523 sp<IDrm> drm = GetDrm(env, thiz);
1524
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001525 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001526 return;
1527 }
1528
Jeff Tinkereada5372013-05-21 12:48:14 -07001529 if (jname == NULL) {
1530 jniThrowException(env, "java/lang/IllegalArgumentException",
1531 "property name String is null");
1532 return;
1533 }
1534
1535 if (jvalue == NULL) {
1536 jniThrowException(env, "java/lang/IllegalArgumentException",
1537 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001538 return;
1539 }
1540
1541 String8 name = JStringToString8(env, jname);
1542 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1543
1544 status_t err = drm->setPropertyByteArray(name, value);
1545
1546 throwExceptionAsNecessary(env, err, "Failed to set property");
1547}
1548
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001549static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001550 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001551 jstring jalgorithm) {
1552
1553 sp<IDrm> drm = GetDrm(env, jdrm);
1554
1555 if (!CheckSession(env, drm, jsessionId)) {
1556 return;
1557 }
1558
1559 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001560 jniThrowException(env, "java/lang/IllegalArgumentException",
1561 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001562 return;
1563 }
1564
1565 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1566 String8 algorithm = JStringToString8(env, jalgorithm);
1567
1568 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1569
1570 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
1571}
1572
1573static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001574 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001575 jstring jalgorithm) {
1576
1577 sp<IDrm> drm = GetDrm(env, jdrm);
1578
1579 if (!CheckSession(env, drm, jsessionId)) {
1580 return;
1581 }
1582
1583 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001584 jniThrowException(env, "java/lang/IllegalArgumentException",
1585 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001586 return;
1587 }
1588
1589 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1590 String8 algorithm = JStringToString8(env, jalgorithm);
1591
1592 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1593
1594 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1595}
1596
1597
1598static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001599 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001600 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1601
1602 sp<IDrm> drm = GetDrm(env, jdrm);
1603
1604 if (!CheckSession(env, drm, jsessionId)) {
1605 return NULL;
1606 }
1607
1608 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001609 jniThrowException(env, "java/lang/IllegalArgumentException",
1610 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001611 return NULL;
1612 }
1613
1614 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1615 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1616 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1617 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1618 Vector<uint8_t> output;
1619
1620 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1621
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001622 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
1623 return NULL;
1624 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001625
1626 return VectorToJByteArray(env, output);
1627}
1628
1629static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001630 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001631 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1632
1633 sp<IDrm> drm = GetDrm(env, jdrm);
1634
1635 if (!CheckSession(env, drm, jsessionId)) {
1636 return NULL;
1637 }
1638
1639 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001640 jniThrowException(env, "java/lang/IllegalArgumentException",
1641 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001642 return NULL;
1643 }
1644
1645 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1646 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1647 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1648 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1649 Vector<uint8_t> output;
1650
1651 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001652 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
1653 return NULL;
1654 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001655
1656 return VectorToJByteArray(env, output);
1657}
1658
1659static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001660 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001661 jbyteArray jkeyId, jbyteArray jmessage) {
1662
1663 sp<IDrm> drm = GetDrm(env, jdrm);
1664
1665 if (!CheckSession(env, drm, jsessionId)) {
1666 return NULL;
1667 }
1668
1669 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001670 jniThrowException(env, "java/lang/IllegalArgumentException",
1671 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001672 return NULL;
1673 }
1674
1675 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1676 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1677 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1678 Vector<uint8_t> signature;
1679
1680 status_t err = drm->sign(sessionId, keyId, message, signature);
1681
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001682 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1683 return NULL;
1684 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001685
1686 return VectorToJByteArray(env, signature);
1687}
1688
1689static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001690 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001691 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1692
1693 sp<IDrm> drm = GetDrm(env, jdrm);
1694
1695 if (!CheckSession(env, drm, jsessionId)) {
1696 return false;
1697 }
1698
1699 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001700 jniThrowException(env, "java/lang/IllegalArgumentException",
1701 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001702 return false;
1703 }
1704
1705 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1706 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1707 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1708 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1709 bool match;
1710
1711 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1712
1713 throwExceptionAsNecessary(env, err, "Failed to verify");
1714 return match;
1715}
1716
Adam Stonec06e10e2017-12-19 12:54:33 -08001717static jobject
1718android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1719{
1720 sp<IDrm> drm = GetDrm(env, thiz);
1721 if (drm == NULL ) {
1722 jniThrowException(env, "java/lang/IllegalStateException",
1723 "MediaDrm obj is null");
1724 return NULL;
1725 }
1726
1727 // Retrieve current metrics snapshot from drm.
Adam Stone94395c92018-01-30 12:07:00 -08001728 PersistableBundle metrics;
1729 status_t err = drm->getMetrics(&metrics);
Adam Stonec06e10e2017-12-19 12:54:33 -08001730 if (err != OK) {
1731 ALOGE("getMetrics failed: %d", (int)err);
1732 return (jobject) NULL;
1733 }
1734
Adam Stone94395c92018-01-30 12:07:00 -08001735 return nativeToJavaPersistableBundle(env, thiz, &metrics);
Adam Stonec06e10e2017-12-19 12:54:33 -08001736}
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001737
Jeff Tinkere4095a82014-03-04 13:17:11 -08001738static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001739 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001740 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1741
1742 sp<IDrm> drm = GetDrm(env, jdrm);
1743
1744 if (!CheckSession(env, drm, jsessionId)) {
1745 return NULL;
1746 }
1747
1748 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1749 jniThrowException(env, "java/lang/IllegalArgumentException",
1750 "required argument is null");
1751 return NULL;
1752 }
1753
1754 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1755 String8 algorithm = JStringToString8(env, jalgorithm);
1756 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1757 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1758 Vector<uint8_t> signature;
1759
1760 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1761
1762 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1763 return NULL;
1764 }
1765
1766 return VectorToJByteArray(env, signature);
1767}
1768
1769
Daniel Micay76f6a862015-09-19 17:31:01 -04001770static const JNINativeMethod gMethods[] = {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001771 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
1772
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001773 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
1774
Edwin Wong4d1d84e2017-01-04 09:37:49 -08001775 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001776 (void *)android_media_MediaDrm_native_setup },
1777
Jeff Tinker7cda4912013-08-21 11:52:34 -07001778 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001779 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
1780
Jeff Tinker2bca5252018-02-11 18:59:14 +00001781 { "openSession", "(I)[B",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001782 (void *)android_media_MediaDrm_openSession },
1783
1784 { "closeSession", "([B)V",
1785 (void *)android_media_MediaDrm_closeSession },
1786
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001787 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
1788 "Landroid/media/MediaDrm$KeyRequest;",
1789 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001790
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001791 { "provideKeyResponse", "([B[B)[B",
1792 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001793
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001794 { "removeKeys", "([B)V",
1795 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001796
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001797 { "restoreKeys", "([B[B)V",
1798 (void *)android_media_MediaDrm_restoreKeys },
1799
1800 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
1801 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001802
Jeff Tinkere4095a82014-03-04 13:17:11 -08001803 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
1804 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001805
Jeff Tinkere4095a82014-03-04 13:17:11 -08001806 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
1807 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001808
1809 { "getSecureStops", "()Ljava/util/List;",
1810 (void *)android_media_MediaDrm_getSecureStops },
1811
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001812 { "getSecureStopIds", "()Ljava/util/List;",
1813 (void *)android_media_MediaDrm_getSecureStopIds },
1814
Jeff Tinker1b51c722014-10-31 00:54:26 -07001815 { "getSecureStop", "([B)[B",
1816 (void *)android_media_MediaDrm_getSecureStop },
1817
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001818 { "releaseSecureStops", "([B)V",
1819 (void *)android_media_MediaDrm_releaseSecureStops },
1820
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001821 { "removeSecureStop", "([B)V",
1822 (void *)android_media_MediaDrm_removeSecureStop },
1823
1824 { "removeAllSecureStops", "()V",
1825 (void *)android_media_MediaDrm_removeAllSecureStops },
Jeff Tinker1b51c722014-10-31 00:54:26 -07001826
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001827 { "getConnectedHdcpLevel", "()I",
1828 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
1829
1830 { "getMaxHdcpLevel", "()I",
1831 (void *)android_media_MediaDrm_getMaxHdcpLevel },
1832
1833 { "getOpenSessionCount", "()I",
1834 (void *)android_media_MediaDrm_getOpenSessionCount },
1835
1836 { "getMaxSessionCount", "()I",
1837 (void *)android_media_MediaDrm_getMaxSessionCount },
1838
1839 { "getSecurityLevel", "([B)I",
1840 (void *)android_media_MediaDrm_getSecurityLevel },
1841
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001842 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
1843 (void *)android_media_MediaDrm_getPropertyString },
1844
1845 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
1846 (void *)android_media_MediaDrm_getPropertyByteArray },
1847
1848 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
1849 (void *)android_media_MediaDrm_setPropertyString },
1850
1851 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
1852 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001853
1854 { "setCipherAlgorithmNative",
1855 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1856 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
1857
1858 { "setMacAlgorithmNative",
1859 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
1860 (void *)android_media_MediaDrm_setMacAlgorithmNative },
1861
1862 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1863 (void *)android_media_MediaDrm_encryptNative },
1864
1865 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
1866 (void *)android_media_MediaDrm_decryptNative },
1867
1868 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
1869 (void *)android_media_MediaDrm_signNative },
1870
1871 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
1872 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08001873
1874 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
1875 (void *)android_media_MediaDrm_signRSANative },
Adam Stonec06e10e2017-12-19 12:54:33 -08001876
1877 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
1878 (void *)android_media_MediaDrm_native_getMetrics },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001879};
1880
1881int register_android_media_Drm(JNIEnv *env) {
1882 return AndroidRuntime::registerNativeMethods(env,
1883 "android/media/MediaDrm", gMethods, NELEM(gMethods));
1884}