blob: babb16b1c880187e4998a82c39a56a9f25071c29 [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
Robert Shihd2e8b432019-11-21 20:27:56 -080030#include <android/hardware/drm/1.3/IDrmFactory.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>
Robert Shihba6777e2019-11-12 13:04:59 -080036#include <mediadrm/DrmMetricsConsumer.h>
Robert Shih218b9532019-08-15 14:48:11 -070037#include <mediadrm/DrmUtils.h>
Robert Shihba6777e2019-11-12 13:04:59 -080038#include <mediadrm/IDrmMetricsConsumer.h>
Jeff Tinkercd4d28f2018-02-16 16:24:49 -080039#include <mediadrm/IDrm.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080040
Adam Stone94395c92018-01-30 12:07:00 -080041using ::android::os::PersistableBundle;
Robert Shihd2e8b432019-11-21 20:27:56 -080042namespace drm = ::android::hardware::drm;
Adam Stone94395c92018-01-30 12:07:00 -080043
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080044namespace android {
45
46#define FIND_CLASS(var, className) \
47 var = env->FindClass(className); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070048 LOG_FATAL_IF(! (var), "Unable to find class %s", className);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080049
50#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
51 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070052 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080053
54#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
55 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070056 LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080057
Jeff Tinker54cfbd62013-04-02 13:14:59 -070058#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
59 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070060 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070061
62#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
63 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070064 LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070065
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070066#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \
67 var = env->GetStaticObjectField(clazz, fieldId); \
68 LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId);
Adam Stone94395c92018-01-30 12:07:00 -080069
Jeff Tinker54cfbd62013-04-02 13:14:59 -070070
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080071struct RequestFields {
72 jfieldID data;
73 jfieldID defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -070074 jfieldID requestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080075};
76
77struct ArrayListFields {
78 jmethodID init;
79 jmethodID add;
80};
81
82struct HashmapFields {
83 jmethodID init;
84 jmethodID get;
85 jmethodID put;
86 jmethodID entrySet;
87};
88
89struct SetFields {
90 jmethodID iterator;
91};
92
93struct IteratorFields {
94 jmethodID next;
95 jmethodID hasNext;
96};
97
98struct EntryFields {
99 jmethodID getKey;
100 jmethodID getValue;
101};
102
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700103struct EventTypes {
Jeff Tinker17b89222013-05-21 12:35:06 -0700104 jint kEventProvisionRequired;
105 jint kEventKeyRequired;
106 jint kEventKeyExpired;
107 jint kEventVendorDefined;
Ronghua Wua6d72092015-03-04 11:16:02 -0800108 jint kEventSessionReclaimed;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700109} gEventTypes;
110
Jeff Tinker74797f82015-03-31 15:44:34 -0700111struct EventWhat {
112 jint kWhatDrmEvent;
113 jint kWhatExpirationUpdate;
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700114 jint kWhatKeyStatusChange;
Jeff Tinker20594d82018-12-12 08:31:22 -0800115 jint kWhatSessionLostState;
Jeff Tinker74797f82015-03-31 15:44:34 -0700116} gEventWhat;
117
Jeff Tinker17b89222013-05-21 12:35:06 -0700118struct KeyTypes {
119 jint kKeyTypeStreaming;
120 jint kKeyTypeOffline;
121 jint kKeyTypeRelease;
122} gKeyTypes;
123
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700124struct KeyRequestTypes {
125 jint kKeyRequestTypeInitial;
126 jint kKeyRequestTypeRenewal;
127 jint kKeyRequestTypeRelease;
Rahul Frias8f761ba2018-01-22 23:43:54 -0800128 jint kKeyRequestTypeNone;
129 jint kKeyRequestTypeUpdate;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700130} gKeyRequestTypes;
131
Jeff Tinkere4095a82014-03-04 13:17:11 -0800132struct CertificateTypes {
133 jint kCertificateTypeNone;
134 jint kCertificateTypeX509;
135} gCertificateTypes;
136
137struct CertificateFields {
138 jfieldID wrappedPrivateKey;
139 jfieldID certificateData;
140};
141
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700142struct StateExceptionFields {
143 jmethodID init;
144 jclass classId;
145};
146
Jeff Tinker20594d82018-12-12 08:31:22 -0800147struct SessionExceptionFields {
148 jmethodID init;
149 jclass classId;
150 jfieldID errorCode;
151};
152
153struct SessionExceptionErrorCodes {
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800154 jint kErrorUnknown;
Jeff Tinker20594d82018-12-12 08:31:22 -0800155 jint kResourceContention;
156} gSessionExceptionErrorCodes;
157
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800158struct HDCPLevels {
159 jint kHdcpLevelUnknown;
160 jint kHdcpNone;
161 jint kHdcpV1;
162 jint kHdcpV2;
163 jint kHdcpV2_1;
164 jint kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800165 jint kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800166 jint kHdcpNoOutput;
167} gHdcpLevels;
168
169struct SecurityLevels {
170 jint kSecurityLevelUnknown;
Jeff Tinker2bca5252018-02-11 18:59:14 +0000171 jint kSecurityLevelMax;
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800172 jint kSecurityLevelSwSecureCrypto;
173 jint kSecurityLevelSwSecureDecode;
174 jint kSecurityLevelHwSecureCrypto;
175 jint kSecurityLevelHwSecureDecode;
176 jint kSecurityLevelHwSecureAll;
177} gSecurityLevels;
178
Jeff Tinker55d26242018-10-10 16:10:43 -0700179struct OfflineLicenseState {
180 jint kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800181 jint kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -0700182 jint kOfflineLicenseStateUnknown;
183} gOfflineLicenseStates;
184
Robert Shih9d4e2d42019-11-08 13:51:49 -0800185struct KeyStatusFields {
186 jmethodID init;
187 jclass classId;
188};
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800189
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800190struct fields_t {
191 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700192 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700193 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800194 RequestFields provisionRequest;
195 ArrayListFields arraylist;
196 HashmapFields hashmap;
197 SetFields set;
198 IteratorFields iterator;
199 EntryFields entry;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800200 CertificateFields certificate;
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700201 StateExceptionFields stateException;
Jeff Tinker20594d82018-12-12 08:31:22 -0800202 SessionExceptionFields sessionException;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800203 jclass certificateClassId;
204 jclass hashmapClassId;
205 jclass arraylistClassId;
206 jclass stringClassId;
Adam Stone94395c92018-01-30 12:07:00 -0800207 jobject bundleCreator;
208 jmethodID createFromParcelId;
209 jclass parcelCreatorClassId;
Robert Shih9d4e2d42019-11-08 13:51:49 -0800210 KeyStatusFields keyStatus;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800211};
212
213static fields_t gFields;
214
Adam Stone94395c92018-01-30 12:07:00 -0800215namespace {
216
Robert Shih9d4e2d42019-11-08 13:51:49 -0800217jbyteArray hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> &vector) {
218 JNIEnv *env = AndroidRuntime::getJNIEnv();
219 size_t length = vector.size();
220 jbyteArray result = env->NewByteArray(length);
221 if (result != NULL) {
222 env->SetByteArrayRegion(result, 0, length, reinterpret_cast<const jbyte *>(vector.data()));
223 }
224 return result;
225}
226
Adam Stone94395c92018-01-30 12:07:00 -0800227} // namespace anonymous
228
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700229// ----------------------------------------------------------------------------
230// ref-counted object for callbacks
231class JNIDrmListener: public DrmListener
232{
233public:
234 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
235 ~JNIDrmListener();
Robert Shih9d4e2d42019-11-08 13:51:49 -0800236 virtual void notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *arg = NULL);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700237private:
238 JNIDrmListener();
239 jclass mClass; // Reference to MediaDrm class
240 jobject mObject; // Weak ref to MediaDrm Java object to call on
241};
242
243JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
244{
245 // Hold onto the MediaDrm class for use in calling the static method
246 // that posts events to the application thread.
247 jclass clazz = env->GetObjectClass(thiz);
248 if (clazz == NULL) {
249 ALOGE("Can't find android/media/MediaDrm");
Jeff Tinkereada5372013-05-21 12:48:14 -0700250 jniThrowException(env, "java/lang/Exception",
251 "Can't find android/media/MediaDrm");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700252 return;
253 }
254 mClass = (jclass)env->NewGlobalRef(clazz);
255
256 // We use a weak reference so the MediaDrm object can be garbage collected.
257 // The reference is only used as a proxy for callbacks.
258 mObject = env->NewGlobalRef(weak_thiz);
259}
260
261JNIDrmListener::~JNIDrmListener()
262{
263 // remove global references
264 JNIEnv *env = AndroidRuntime::getJNIEnv();
265 env->DeleteGlobalRef(mObject);
266 env->DeleteGlobalRef(mClass);
267}
268
269void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
Robert Shih9d4e2d42019-11-08 13:51:49 -0800270 const ListenerArgs *args)
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700271{
Jeff Tinker74797f82015-03-31 15:44:34 -0700272 jint jwhat;
273 jint jeventType = 0;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700274
275 // translate DrmPlugin event types into their java equivalents
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700276 switch (eventType) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700277 case DrmPlugin::kDrmPluginEventProvisionRequired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700278 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700279 jeventType = gEventTypes.kEventProvisionRequired;
280 break;
281 case DrmPlugin::kDrmPluginEventKeyNeeded:
Jeff Tinker74797f82015-03-31 15:44:34 -0700282 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700283 jeventType = gEventTypes.kEventKeyRequired;
284 break;
285 case DrmPlugin::kDrmPluginEventKeyExpired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700286 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700287 jeventType = gEventTypes.kEventKeyExpired;
288 break;
289 case DrmPlugin::kDrmPluginEventVendorDefined:
Jeff Tinker74797f82015-03-31 15:44:34 -0700290 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700291 jeventType = gEventTypes.kEventVendorDefined;
292 break;
Ronghua Wua6d72092015-03-04 11:16:02 -0800293 case DrmPlugin::kDrmPluginEventSessionReclaimed:
Jeff Tinker74797f82015-03-31 15:44:34 -0700294 jwhat = gEventWhat.kWhatDrmEvent;
Ronghua Wua6d72092015-03-04 11:16:02 -0800295 jeventType = gEventTypes.kEventSessionReclaimed;
296 break;
Jeff Tinker74797f82015-03-31 15:44:34 -0700297 case DrmPlugin::kDrmPluginEventExpirationUpdate:
298 jwhat = gEventWhat.kWhatExpirationUpdate;
299 break;
300 case DrmPlugin::kDrmPluginEventKeysChange:
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700301 jwhat = gEventWhat.kWhatKeyStatusChange;
Jeff Tinker74797f82015-03-31 15:44:34 -0700302 break;
Jeff Tinker20594d82018-12-12 08:31:22 -0800303 case DrmPlugin::kDrmPluginEventSessionLostState:
304 jwhat = gEventWhat.kWhatSessionLostState;
305 break;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700306 default:
307 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
308 return;
309 }
310
311 JNIEnv *env = AndroidRuntime::getJNIEnv();
Robert Shih9d4e2d42019-11-08 13:51:49 -0800312 if (args) {
313 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
314 jwhat, jeventType, extra,
315 args->jSessionId, args->jData, args->jExpirationTime,
316 args->jKeyStatusList, args->jHasNewUsableKey);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700317 }
318
319 if (env->ExceptionCheck()) {
320 ALOGW("An exception occurred while notifying an event.");
321 LOGW_EX(env);
322 env->ExceptionClear();
323 }
324}
325
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700326static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
327 ALOGE("Illegal state exception: %s (%d)", msg, err);
328
329 jobject exception = env->NewObject(gFields.stateException.classId,
330 gFields.stateException.init, static_cast<int>(err),
331 env->NewStringUTF(msg));
332 env->Throw(static_cast<jthrowable>(exception));
333}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700334
Jeff Tinker20594d82018-12-12 08:31:22 -0800335static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
336 ALOGE("Session exception: %s (%d)", msg, err);
337
338 jint jErrorCode = 0;
339 switch(err) {
340 case ERROR_DRM_RESOURCE_CONTENTION:
341 jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
342 break;
343 default:
344 break;
345 }
346
347 jobject exception = env->NewObject(gFields.sessionException.classId,
348 gFields.sessionException.init, static_cast<int>(err),
349 env->NewStringUTF(msg));
350
351 env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
352 env->Throw(static_cast<jthrowable>(exception));
353}
354
355static bool isSessionException(status_t err) {
356 return err == ERROR_DRM_RESOURCE_CONTENTION;
357}
358
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800359static bool throwExceptionAsNecessary(
360 JNIEnv *env, status_t err, const char *msg = NULL) {
361
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700362 const char *drmMessage = NULL;
363
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700364 switch (err) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700365 case ERROR_DRM_UNKNOWN:
366 drmMessage = "General DRM error";
367 break;
368 case ERROR_DRM_NO_LICENSE:
369 drmMessage = "No license";
370 break;
371 case ERROR_DRM_LICENSE_EXPIRED:
372 drmMessage = "License expired";
373 break;
374 case ERROR_DRM_SESSION_NOT_OPENED:
375 drmMessage = "Session not opened";
376 break;
377 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
378 drmMessage = "Not initialized";
379 break;
380 case ERROR_DRM_DECRYPT:
381 drmMessage = "Decrypt error";
382 break;
383 case ERROR_DRM_CANNOT_HANDLE:
Jeff Tinkereb13c762017-11-01 15:29:38 -0700384 drmMessage = "Invalid parameter or data format";
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700385 break;
Jeff Tinker20594d82018-12-12 08:31:22 -0800386 case ERROR_DRM_INVALID_STATE:
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700387 drmMessage = "Invalid state";
388 break;
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700389 default:
390 break;
391 }
392
393 String8 vendorMessage;
394 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
Jeff Tinker29799862014-08-27 11:05:13 -0700395 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700396 drmMessage = vendorMessage.string();
397 }
398
Jeff Tinkereb13c762017-11-01 15:29:38 -0700399 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800400 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
401 return true;
Jeff Tinker5de2e902019-01-25 23:09:36 -0800402 } else if (err == ERROR_UNSUPPORTED) {
403 jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
404 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700405 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
406 jniThrowException(env, "android/media/NotProvisionedException", msg);
407 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700408 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
409 jniThrowException(env, "android/media/ResourceBusyException", msg);
410 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700411 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
412 jniThrowException(env, "android/media/DeniedByServerException", msg);
413 return true;
Jeff Tinker314b7f32015-06-15 17:45:43 -0700414 } else if (err == DEAD_OBJECT) {
415 jniThrowException(env, "android/media/MediaDrmResetException",
416 "mediaserver died");
417 return true;
Jeff Tinker20594d82018-12-12 08:31:22 -0800418 } else if (isSessionException(err)) {
419 throwSessionException(env, msg, err);
420 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800421 } else if (err != OK) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700422 String8 errbuf;
423 if (drmMessage != NULL) {
424 if (msg == NULL) {
425 msg = drmMessage;
426 } else {
Jeff Tinker29799862014-08-27 11:05:13 -0700427 errbuf = String8::format("%s: %s", msg, drmMessage);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700428 msg = errbuf.string();
429 }
430 }
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700431 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800432 return true;
433 }
434 return false;
435}
436
437static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000438 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800439 return jdrm ? jdrm->getDrm() : NULL;
440}
441
442JDrm::JDrm(
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800443 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
444 const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800445 mObject = env->NewWeakGlobalRef(thiz);
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800446 mDrm = MakeDrm(uuid, appPackageName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700447 if (mDrm != NULL) {
448 mDrm->setListener(this);
449 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800450}
451
452JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800453 JNIEnv *env = AndroidRuntime::getJNIEnv();
454
455 env->DeleteWeakGlobalRef(mObject);
456 mObject = NULL;
457}
458
459// static
460sp<IDrm> JDrm::MakeDrm() {
Robert Shih218b9532019-08-15 14:48:11 -0700461 return DrmUtils::MakeDrm();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800462}
463
464// static
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800465sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800466 sp<IDrm> drm = MakeDrm();
467
468 if (drm == NULL) {
469 return NULL;
470 }
471
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800472 status_t err = drm->createPlugin(uuid, appPackageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800473
474 if (err != OK) {
475 return NULL;
476 }
477
478 return drm;
479}
480
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700481status_t JDrm::setListener(const sp<DrmListener>& listener) {
482 Mutex::Autolock lock(mLock);
483 mListener = listener;
484 return OK;
485}
486
Robert Shih9d4e2d42019-11-08 13:51:49 -0800487void JDrm::notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *args) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700488 sp<DrmListener> listener;
489 mLock.lock();
490 listener = mListener;
491 mLock.unlock();
492
493 if (listener != NULL) {
494 Mutex::Autolock lock(mNotifyLock);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800495 listener->notify(eventType, extra, args);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700496 }
497}
498
Robert Shih3a523902019-08-15 14:48:11 -0700499void JDrm::sendEvent(
500 DrmPlugin::EventType eventType,
501 const hardware::hidl_vec<uint8_t> &sessionId,
502 const hardware::hidl_vec<uint8_t> &data) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800503 ListenerArgs args{
504 .jSessionId = hidlVectorToJByteArray(sessionId),
505 .jData = hidlVectorToJByteArray(data),
506 };
507 notify(eventType, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700508}
509
510void JDrm::sendExpirationUpdate(
511 const hardware::hidl_vec<uint8_t> &sessionId,
512 int64_t expiryTimeInMS) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800513 ListenerArgs args{
514 .jSessionId = hidlVectorToJByteArray(sessionId),
515 .jExpirationTime = expiryTimeInMS,
516 };
517 notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700518}
519
520void JDrm::sendKeysChange(
521 const hardware::hidl_vec<uint8_t> &sessionId,
522 const std::vector<DrmKeyStatus> &keyStatusList,
523 bool hasNewUsableKey) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800524 JNIEnv *env = AndroidRuntime::getJNIEnv();
525 jclass clazz = gFields.arraylistClassId;
526 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
527 clazz = gFields.keyStatus.classId;
528 for (const auto &keyStatus : keyStatusList) {
529 jbyteArray jKeyId(hidlVectorToJByteArray(keyStatus.keyId));
530 jint jStatusCode(keyStatus.type);
531 jobject jKeyStatus = env->NewObject(clazz, gFields.keyStatus.init, jKeyId, jStatusCode);
532 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jKeyStatus);
533 }
534 ListenerArgs args{
535 .jSessionId = hidlVectorToJByteArray(sessionId),
536 .jKeyStatusList = arrayList,
537 .jHasNewUsableKey = hasNewUsableKey,
538 };
539 notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700540}
541
542void JDrm::sendSessionLostState(
543 const hardware::hidl_vec<uint8_t> &sessionId) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800544 ListenerArgs args{
545 .jSessionId = hidlVectorToJByteArray(sessionId),
546 };
547 notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700548}
549
Jeff Tinker600071c2014-04-11 16:11:15 -0700550void JDrm::disconnect() {
551 if (mDrm != NULL) {
552 mDrm->destroyPlugin();
553 mDrm.clear();
554 }
555}
556
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700557
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800558// static
Jeff Tinker5de2e902019-01-25 23:09:36 -0800559status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
560 DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800561 sp<IDrm> drm = MakeDrm();
562
563 if (drm == NULL) {
Jeff Tinker5de2e902019-01-25 23:09:36 -0800564 return BAD_VALUE;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800565 }
566
Jeff Tinker5de2e902019-01-25 23:09:36 -0800567 return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800568}
569
570status_t JDrm::initCheck() const {
571 return mDrm == NULL ? NO_INIT : OK;
572}
573
574// JNI conversion utilities
575static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
576 Vector<uint8_t> vector;
577 size_t length = env->GetArrayLength(byteArray);
578 vector.insertAt((size_t)0, length);
579 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
580 return vector;
581}
582
583static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
584 size_t length = vector.size();
585 jbyteArray result = env->NewByteArray(length);
586 if (result != NULL) {
587 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
588 }
589 return result;
590}
591
592static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800593 String8 result;
594
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700595 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800596 if (s) {
597 result = s;
598 env->ReleaseStringUTFChars(jstr, s);
599 }
600 return result;
601}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700602
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800603/*
604 import java.util.HashMap;
605 import java.util.Set;
606 import java.Map.Entry;
607 import jav.util.Iterator;
608
609 HashMap<k, v> hm;
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800610 Set<Entry<k, v>> s = hm.entrySet();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800611 Iterator i = s.iterator();
612 Entry e = s.next();
613*/
614
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200615static KeyedVector<String8, String8> HashMapToKeyedVector(
616 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800617 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800618 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200619 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800620
621 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
622 if (entrySet) {
623 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
624 if (iterator) {
625 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
626 while (hasNext) {
627 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
628 if (entry) {
629 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200630 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700631 jniThrowException(env, "java/lang/IllegalArgumentException",
632 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200633 env->DeleteLocalRef(entry);
634 *pIsOK = false;
635 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800636 }
637 jstring jkey = static_cast<jstring>(obj);
638
639 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200640 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700641 jniThrowException(env, "java/lang/IllegalArgumentException",
642 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200643 env->DeleteLocalRef(entry);
644 *pIsOK = false;
645 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800646 }
647 jstring jvalue = static_cast<jstring>(obj);
648
649 String8 key = JStringToString8(env, jkey);
650 String8 value = JStringToString8(env, jvalue);
651 keyedVector.add(key, value);
652
653 env->DeleteLocalRef(jkey);
654 env->DeleteLocalRef(jvalue);
655 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
656 }
657 env->DeleteLocalRef(entry);
658 }
659 env->DeleteLocalRef(iterator);
660 }
661 env->DeleteLocalRef(entrySet);
662 }
663 return keyedVector;
664}
665
666static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800667 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800668 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
669 for (size_t i = 0; i < map.size(); ++i) {
670 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
671 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
672 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
673 env->DeleteLocalRef(jkey);
674 env->DeleteLocalRef(jvalue);
675 }
676 return hashMap;
677}
678
679static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800680 List<Vector<uint8_t>> list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800681 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800682 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800683 List<Vector<uint8_t>>::iterator iter = list.begin();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800684 while (iter != list.end()) {
685 jbyteArray byteArray = VectorToJByteArray(env, *iter);
686 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
687 env->DeleteLocalRef(byteArray);
688 iter++;
689 }
690
691 return arrayList;
692}
693
694} // namespace android
695
696using namespace android;
697
698static sp<JDrm> setDrm(
699 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000700 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800701 if (drm != NULL) {
702 drm->incStrong(thiz);
703 }
704 if (old != NULL) {
705 old->decStrong(thiz);
706 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000707 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800708
709 return old;
710}
711
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800712static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800713 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700714 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800715 return false;
716 }
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800717 return true;
718}
719
720static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
721{
722 if (!CheckDrm(env, drm)) {
723 return false;
724 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800725
726 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700727 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800728 return false;
729 }
730 return true;
731}
732
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800733static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700734 sp<JDrm> drm = setDrm(env, thiz, NULL);
735 if (drm != NULL) {
736 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700737 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700738 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800739}
740
741static void android_media_MediaDrm_native_init(JNIEnv *env) {
742 jclass clazz;
743 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000744 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700745 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
Robert Shih9d4e2d42019-11-08 13:51:49 -0800746 "(Ljava/lang/Object;III[B[BJLjava/util/List;Z)V");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700747
748 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700749 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700750 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700751 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700752 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700753 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700754 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700755 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700756 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Ronghua Wua6d72092015-03-04 11:16:02 -0800757 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
758 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800759
Jeff Tinker74797f82015-03-31 15:44:34 -0700760 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
761 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
762 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
763 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700764 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
765 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800766 GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
767 gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
Jeff Tinker74797f82015-03-31 15:44:34 -0700768
Jeff Tinker17b89222013-05-21 12:35:06 -0700769 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
770 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
771 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
772 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
773 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
774 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
775
Jeff Tinkere4095a82014-03-04 13:17:11 -0800776 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
777 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
778 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
779 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
780
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800781 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
782 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
783 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
784 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
785 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
786 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
787 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
788 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
789 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
790 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
791 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
792 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800793 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I");
794 gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field);
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800795 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
796 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
797
798 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
799 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700800 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800801 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700802 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800803 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700804 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800805 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700806 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800807 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700808 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800809 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
810
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800811 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I");
Jeff Tinker55d26242018-10-10 16:10:43 -0700812 gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800813 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I");
814 gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field);
Jeff Tinker55d26242018-10-10 16:10:43 -0700815 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
816 gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
817
818 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
819
Jeff Tinker2bca5252018-02-11 18:59:14 +0000820 jmethodID getMaxSecurityLevel;
821 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
822 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
823
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700824 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700825 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
826 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700827 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800828
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700829 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
830 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
831 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
832 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
833 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
834 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
Rahul Frias8f761ba2018-01-22 23:43:54 -0800835 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
836 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
837 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
838 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700839
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800840 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700841 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
842 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800843
Jeff Tinkere4095a82014-03-04 13:17:11 -0800844 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
845 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
846 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700847 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800848
Adam Stone94395c92018-01-30 12:07:00 -0800849 // Metrics-related fields and classes.
850 FIND_CLASS(clazz, "android/os/PersistableBundle");
851 jfieldID bundleCreatorId;
852 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
853 "Landroid/os/Parcelable$Creator;");
854 jobject bundleCreator;
855 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
856 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
857 FIND_CLASS(clazz, "android/os/Parcelable$Creator");
858 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
859 "(Landroid/os/Parcel;)Ljava/lang/Object;");
860 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
861
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800862 FIND_CLASS(clazz, "java/util/ArrayList");
863 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
864 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
865
866 FIND_CLASS(clazz, "java/util/HashMap");
867 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
868 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
869 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
870 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
871 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
872
873 FIND_CLASS(clazz, "java/util/Set");
874 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
875
876 FIND_CLASS(clazz, "java/util/Iterator");
877 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
878 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
879
880 FIND_CLASS(clazz, "java/util/Map$Entry");
881 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
882 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800883
884 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700885 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800886
887 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700888 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800889
890 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700891 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700892
893 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
894 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
895 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker20594d82018-12-12 08:31:22 -0800896
897 FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
898 GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
899 gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
900 GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
901
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800902 GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I");
903 gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800904 GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
905 gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800906
907 FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
908 gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
909 GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800910}
911
912static void android_media_MediaDrm_native_setup(
913 JNIEnv *env, jobject thiz,
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800914 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800915
916 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700917 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800918 return;
919 }
920
921 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
922
923 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700924 jniThrowException(env, "java/lang/IllegalArgumentException",
925 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800926 return;
927 }
928
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800929 String8 packageName;
930 if (jappPackageName == NULL) {
931 jniThrowException(env, "java/lang/IllegalArgumentException",
932 "application package name cannot be null");
933 return;
934 }
935
936 packageName = JStringToString8(env, jappPackageName);
937 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800938
939 status_t err = drm->initCheck();
940
941 if (err != OK) {
942 jniThrowException(
943 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700944 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800945 "Failed to instantiate drm object.");
946 return;
947 }
948
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700949 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
950 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800951 setDrm(env, thiz, drm);
952}
953
Jeff Tinkerd571a7c2019-01-17 17:29:30 -0800954DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
955 DrmPlugin::SecurityLevel level;
956
957 if (jlevel == gSecurityLevels.kSecurityLevelMax) {
958 level = DrmPlugin::kSecurityLevelMax;
959 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
960 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
961 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
962 level = DrmPlugin::kSecurityLevelSwSecureDecode;
963 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
964 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
965 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
966 level = DrmPlugin::kSecurityLevelHwSecureDecode;
967 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
968 level = DrmPlugin::kSecurityLevelHwSecureAll;
969 } else {
970 level = DrmPlugin::kSecurityLevelUnknown;
971 }
972 return level;
973}
974
Robert Shihd2e8b432019-11-21 20:27:56 -0800975static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
976 std::vector<uint8_t> bv;
977 for (auto &factory : DrmUtils::MakeDrmFactories()) {
978 sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
979 if (factoryV1_3 == nullptr) {
980 continue;
981 }
982 factoryV1_3->getSupportedCryptoSchemes(
983 [&](const hardware::hidl_vec<hardware::hidl_array<uint8_t, 16>>& schemes) {
984 for (const auto &scheme : schemes) {
985 bv.insert(bv.end(), scheme.data(), scheme.data() + scheme.size());
986 }
987 });
988 }
989
990 jbyteArray jUuidBytes = env->NewByteArray(bv.size());
991 env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast<const jbyte *>(bv.data()));
992 return jUuidBytes;
993}
994
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800995static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Jeff Tinkerd571a7c2019-01-17 17:29:30 -0800996 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType,
997 jint jSecurityLevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800998
999 if (uuidObj == NULL) {
1000 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1001 return false;
1002 }
1003
1004 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1005
1006 if (uuid.size() != 16) {
1007 jniThrowException(
1008 env,
1009 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -07001010 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001011 return false;
1012 }
1013
Jeff Tinker7cda4912013-08-21 11:52:34 -07001014 String8 mimeType;
1015 if (jmimeType != NULL) {
1016 mimeType = JStringToString8(env, jmimeType);
1017 }
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001018 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
Jeff Tinker7cda4912013-08-21 11:52:34 -07001019
Jeff Tinker5de2e902019-01-25 23:09:36 -08001020 bool isSupported;
1021 status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
1022 securityLevel, &isSupported);
1023
1024 if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
1025 return false;
1026 }
1027 return isSupported;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001028}
1029
1030static jbyteArray android_media_MediaDrm_openSession(
Jeff Tinker2bca5252018-02-11 18:59:14 +00001031 JNIEnv *env, jobject thiz, jint jlevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001032 sp<IDrm> drm = GetDrm(env, thiz);
1033
Jeff Tinker55d26242018-10-10 16:10:43 -07001034 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001035 return NULL;
1036 }
1037
1038 Vector<uint8_t> sessionId;
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001039 DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel);
1040 if (level == DrmPlugin::kSecurityLevelUnknown) {
Jeff Tinker2bca5252018-02-11 18:59:14 +00001041 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1042 return NULL;
1043 }
1044
1045 status_t err = drm->openSession(level, sessionId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001046
1047 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
1048 return NULL;
1049 }
1050
1051 return VectorToJByteArray(env, sessionId);
1052}
1053
1054static void android_media_MediaDrm_closeSession(
1055 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1056 sp<IDrm> drm = GetDrm(env, thiz);
1057
1058 if (!CheckSession(env, drm, jsessionId)) {
1059 return;
1060 }
1061
1062 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1063
1064 status_t err = drm->closeSession(sessionId);
1065
1066 throwExceptionAsNecessary(env, err, "Failed to close session");
1067}
1068
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001069static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001070 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001071 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001072 sp<IDrm> drm = GetDrm(env, thiz);
1073
1074 if (!CheckSession(env, drm, jsessionId)) {
1075 return NULL;
1076 }
1077
1078 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1079
1080 Vector<uint8_t> initData;
1081 if (jinitData != NULL) {
1082 initData = JByteArrayToVector(env, jinitData);
1083 }
1084
1085 String8 mimeType;
1086 if (jmimeType != NULL) {
1087 mimeType = JStringToString8(env, jmimeType);
1088 }
1089
Jeff Tinker17b89222013-05-21 12:35:06 -07001090 DrmPlugin::KeyType keyType;
1091 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
1092 keyType = DrmPlugin::kKeyType_Streaming;
1093 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
1094 keyType = DrmPlugin::kKeyType_Offline;
1095 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
1096 keyType = DrmPlugin::kKeyType_Release;
1097 } else {
1098 jniThrowException(env, "java/lang/IllegalArgumentException",
1099 "invalid keyType");
1100 return NULL;
1101 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001102
1103 KeyedVector<String8, String8> optParams;
1104 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +02001105 bool isOK;
1106 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
1107 if (!isOK) {
1108 return NULL;
1109 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001110 }
1111
1112 Vector<uint8_t> request;
1113 String8 defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001114 DrmPlugin::KeyRequestType keyRequestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001115
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001116 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001117 keyType, optParams, request, defaultUrl, &keyRequestType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001118
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001119 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001120 return NULL;
1121 }
1122
1123 // Fill out return obj
1124 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001125 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001126
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001127 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001128
1129 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001130 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001131 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001132 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001133
1134 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001135 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001136
1137 switch (keyRequestType) {
1138 case DrmPlugin::kKeyRequestType_Initial:
1139 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1140 gKeyRequestTypes.kKeyRequestTypeInitial);
1141 break;
1142 case DrmPlugin::kKeyRequestType_Renewal:
1143 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1144 gKeyRequestTypes.kKeyRequestTypeRenewal);
1145 break;
1146 case DrmPlugin::kKeyRequestType_Release:
1147 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1148 gKeyRequestTypes.kKeyRequestTypeRelease);
1149 break;
Rahul Frias8f761ba2018-01-22 23:43:54 -08001150 case DrmPlugin::kKeyRequestType_None:
1151 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1152 gKeyRequestTypes.kKeyRequestTypeNone);
1153 break;
1154 case DrmPlugin::kKeyRequestType_Update:
1155 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1156 gKeyRequestTypes.kKeyRequestTypeUpdate);
1157 break;
1158
Jeff Tinker74797f82015-03-31 15:44:34 -07001159 default:
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001160 throwStateException(env, "DRM plugin failure: unknown key request type",
1161 ERROR_DRM_UNKNOWN);
1162 break;
1163 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001164 }
1165
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001166 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001167}
1168
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001169static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001170 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
1171 sp<IDrm> drm = GetDrm(env, thiz);
1172
1173 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001174 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001175 }
1176
1177 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1178
1179 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001180 jniThrowException(env, "java/lang/IllegalArgumentException",
1181 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001182 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001183 }
1184 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001185 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001186
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001187 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001188
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001189 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
1190 return NULL;
1191 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001192 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001193}
1194
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001195static void android_media_MediaDrm_removeKeys(
1196 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
1197 sp<IDrm> drm = GetDrm(env, thiz);
1198
Jeff Tinker55d26242018-10-10 16:10:43 -07001199 if (!CheckDrm(env, drm)) {
1200 return;
1201 }
1202
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001203 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001204 jniThrowException(env, "java/lang/IllegalArgumentException",
1205 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001206 return;
1207 }
1208
1209 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1210
1211 status_t err = drm->removeKeys(keySetId);
1212
1213 throwExceptionAsNecessary(env, err, "Failed to remove keys");
1214}
1215
1216static void android_media_MediaDrm_restoreKeys(
1217 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
1218 jbyteArray jkeysetId) {
1219
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001220 sp<IDrm> drm = GetDrm(env, thiz);
1221
1222 if (!CheckSession(env, drm, jsessionId)) {
1223 return;
1224 }
1225
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001226 if (jkeysetId == NULL) {
1227 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1228 return;
1229 }
1230
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001231 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001232 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001233
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001234 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001235
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001236 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001237}
1238
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001239static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001240 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1241 sp<IDrm> drm = GetDrm(env, thiz);
1242
1243 if (!CheckSession(env, drm, jsessionId)) {
1244 return NULL;
1245 }
1246 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1247
1248 KeyedVector<String8, String8> infoMap;
1249
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001250 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001251
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001252 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001253 return NULL;
1254 }
1255
1256 return KeyedVectorToHashMap(env, infoMap);
1257}
1258
Jeff Tinkere4095a82014-03-04 13:17:11 -08001259static jobject android_media_MediaDrm_getProvisionRequestNative(
1260 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001261 sp<IDrm> drm = GetDrm(env, thiz);
1262
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001263 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001264 return NULL;
1265 }
1266
1267 Vector<uint8_t> request;
1268 String8 defaultUrl;
1269
Jeff Tinkere4095a82014-03-04 13:17:11 -08001270 String8 certType;
1271 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1272 certType = "X.509";
1273 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1274 certType = "none";
1275 } else {
1276 certType = "invalid";
1277 }
1278
1279 String8 certAuthority = JStringToString8(env, jcertAuthority);
1280 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001281
1282 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
1283 return NULL;
1284 }
1285
1286 // Fill out return obj
1287 jclass clazz;
1288 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1289
1290 jobject provisionObj = NULL;
1291
1292 if (clazz) {
1293 provisionObj = env->AllocObject(clazz);
1294 jbyteArray jrequest = VectorToJByteArray(env, request);
1295 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1296
1297 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1298 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1299 }
1300
1301 return provisionObj;
1302}
1303
Jeff Tinkere4095a82014-03-04 13:17:11 -08001304static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001305 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1306 sp<IDrm> drm = GetDrm(env, thiz);
1307
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001308 if (!CheckDrm(env, drm)) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001309 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001310 }
1311
1312 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001313 jniThrowException(env, "java/lang/IllegalArgumentException",
1314 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001315 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001316 }
1317
1318 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -08001319 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001320
Jeff Tinkere4095a82014-03-04 13:17:11 -08001321 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1322
1323 // Fill out return obj
1324 jclass clazz = gFields.certificateClassId;
1325
1326 jobject certificateObj = NULL;
1327
1328 if (clazz && certificate.size() && wrappedKey.size()) {
1329 certificateObj = env->AllocObject(clazz);
1330 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1331 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1332
1333 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1334 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1335 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001336
1337 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001338 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001339}
1340
1341static jobject android_media_MediaDrm_getSecureStops(
1342 JNIEnv *env, jobject thiz) {
1343 sp<IDrm> drm = GetDrm(env, thiz);
1344
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001345 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001346 return NULL;
1347 }
1348
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001349 List<Vector<uint8_t>> secureStops;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001350
1351 status_t err = drm->getSecureStops(secureStops);
1352
1353 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
1354 return NULL;
1355 }
1356
1357 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1358}
1359
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001360static jobject android_media_MediaDrm_getSecureStopIds(
1361 JNIEnv *env, jobject thiz) {
1362 sp<IDrm> drm = GetDrm(env, thiz);
1363
Jeff Tinker55d26242018-10-10 16:10:43 -07001364 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001365 return NULL;
1366 }
1367
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001368 List<Vector<uint8_t>> secureStopIds;
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001369
1370 status_t err = drm->getSecureStopIds(secureStopIds);
1371
1372 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
1373 return NULL;
1374 }
1375
1376 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1377}
1378
Jeff Tinker1b51c722014-10-31 00:54:26 -07001379static jbyteArray android_media_MediaDrm_getSecureStop(
1380 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1381 sp<IDrm> drm = GetDrm(env, thiz);
1382
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001383 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001384 return NULL;
1385 }
1386
1387 Vector<uint8_t> secureStop;
1388
1389 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1390
1391 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
1392 return NULL;
1393 }
1394
1395 return VectorToJByteArray(env, secureStop);
1396}
1397
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001398static void android_media_MediaDrm_releaseSecureStops(
1399 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1400 sp<IDrm> drm = GetDrm(env, thiz);
1401
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001402 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001403 return;
1404 }
1405
1406 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1407
1408 status_t err = drm->releaseSecureStops(ssRelease);
1409
1410 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
1411}
1412
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001413static void android_media_MediaDrm_removeSecureStop(
1414 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1415 sp<IDrm> drm = GetDrm(env, thiz);
1416
Jeff Tinker55d26242018-10-10 16:10:43 -07001417 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001418 return;
1419 }
1420
1421 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1422
1423 throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
1424}
1425
1426static void android_media_MediaDrm_removeAllSecureStops(
Jeff Tinker1b51c722014-10-31 00:54:26 -07001427 JNIEnv *env, jobject thiz) {
1428 sp<IDrm> drm = GetDrm(env, thiz);
1429
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001430 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001431 return;
1432 }
1433
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001434 status_t err = drm->removeAllSecureStops();
Jeff Tinker1b51c722014-10-31 00:54:26 -07001435
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001436 throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
Jeff Tinker1b51c722014-10-31 00:54:26 -07001437}
1438
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001439
1440static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1441 switch(level) {
1442 case DrmPlugin::kHdcpLevelUnknown:
1443 return gHdcpLevels.kHdcpLevelUnknown;
1444 case DrmPlugin::kHdcpNone:
1445 return gHdcpLevels.kHdcpNone;
1446 case DrmPlugin::kHdcpV1:
1447 return gHdcpLevels.kHdcpV1;
1448 case DrmPlugin::kHdcpV2:
1449 return gHdcpLevels.kHdcpV2;
1450 case DrmPlugin::kHdcpV2_1:
1451 return gHdcpLevels.kHdcpV2_1;
1452 case DrmPlugin::kHdcpV2_2:
1453 return gHdcpLevels.kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -08001454 case DrmPlugin::kHdcpV2_3:
1455 return gHdcpLevels.kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001456 case DrmPlugin::kHdcpNoOutput:
1457 return gHdcpLevels.kHdcpNoOutput;
1458 }
1459 return gHdcpLevels.kHdcpNone;
1460}
1461
1462static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1463 jobject thiz) {
1464 sp<IDrm> drm = GetDrm(env, thiz);
1465
1466 if (!CheckDrm(env, drm)) {
1467 return gHdcpLevels.kHdcpNone;
1468 }
1469
1470 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1471 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1472
1473 status_t err = drm->getHdcpLevels(&connected, &max);
1474
1475 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1476 return gHdcpLevels.kHdcpLevelUnknown;
1477 }
1478 return HdcpLevelTojint(connected);
1479}
1480
1481static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1482 jobject thiz) {
1483 sp<IDrm> drm = GetDrm(env, thiz);
1484
1485 if (!CheckDrm(env, drm)) {
1486 return gHdcpLevels.kHdcpLevelUnknown;
1487 }
1488
1489 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1490 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1491
1492 status_t err = drm->getHdcpLevels(&connected, &max);
1493
1494 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1495 return gHdcpLevels.kHdcpLevelUnknown;
1496 }
1497 return HdcpLevelTojint(max);
1498}
1499
1500static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1501 jobject thiz) {
1502 sp<IDrm> drm = GetDrm(env, thiz);
1503
1504 if (!CheckDrm(env, drm)) {
1505 return 0;
1506 }
1507
1508 uint32_t open = 0, max = 0;
1509 status_t err = drm->getNumberOfSessions(&open, &max);
1510
1511 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1512 return 0;
1513 }
1514 return open;
1515}
1516
1517static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1518 jobject thiz) {
1519 sp<IDrm> drm = GetDrm(env, thiz);
1520
1521 if (!CheckDrm(env, drm)) {
1522 return 0;
1523 }
1524
1525 uint32_t open = 0, max = 0;
1526 status_t err = drm->getNumberOfSessions(&open, &max);
1527
1528 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1529 return 0;
1530 }
1531 return max;
1532}
1533
1534static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1535 jobject thiz, jbyteArray jsessionId) {
1536 sp<IDrm> drm = GetDrm(env, thiz);
1537
1538 if (!CheckSession(env, drm, jsessionId)) {
1539 return gSecurityLevels.kSecurityLevelUnknown;
1540 }
1541
1542 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1543
1544 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1545
1546 status_t err = drm->getSecurityLevel(sessionId, &level);
1547
1548 if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
1549 return gSecurityLevels.kSecurityLevelUnknown;
1550 }
1551
1552 switch(level) {
1553 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1554 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1555 case DrmPlugin::kSecurityLevelSwSecureDecode:
1556 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1557 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1558 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1559 case DrmPlugin::kSecurityLevelHwSecureDecode:
1560 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1561 case DrmPlugin::kSecurityLevelHwSecureAll:
1562 return gSecurityLevels.kSecurityLevelHwSecureAll;
1563 default:
1564 return gSecurityLevels.kSecurityLevelUnknown;
1565 }
1566}
1567
Jeff Tinker55d26242018-10-10 16:10:43 -07001568static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
1569 JNIEnv *env, jobject thiz) {
1570 sp<IDrm> drm = GetDrm(env, thiz);
1571
1572 if (!CheckDrm(env, drm)) {
1573 return NULL;
1574 }
1575
1576 List<Vector<uint8_t> > keySetIds;
1577
1578 status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
1579
1580 if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
1581 return NULL;
1582 }
1583
1584 return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
1585}
1586
1587static void android_media_MediaDrm_removeOfflineLicense(
1588 JNIEnv *env, jobject thiz, jbyteArray keySetId) {
1589 sp<IDrm> drm = GetDrm(env, thiz);
1590
1591 if (!CheckDrm(env, drm)) {
1592 return;
1593 }
1594
1595 status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
1596
1597 throwExceptionAsNecessary(env, err, "Failed to remove offline license");
1598}
1599
1600static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
1601 jobject thiz, jbyteArray jkeySetId) {
1602 sp<IDrm> drm = GetDrm(env, thiz);
1603
1604 if (!CheckDrm(env, drm)) {
1605 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1606 }
1607
1608 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
1609
1610 DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
1611
1612 status_t err = drm->getOfflineLicenseState(keySetId, &state);
1613
1614 if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
1615 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1616 }
1617
1618 switch(state) {
1619 case DrmPlugin::kOfflineLicenseStateUsable:
1620 return gOfflineLicenseStates.kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -08001621 case DrmPlugin::kOfflineLicenseStateReleased:
1622 return gOfflineLicenseStates.kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -07001623 default:
1624 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1625 }
1626}
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001627
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001628static jstring android_media_MediaDrm_getPropertyString(
1629 JNIEnv *env, jobject thiz, jstring jname) {
1630 sp<IDrm> drm = GetDrm(env, thiz);
1631
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001632 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001633 return NULL;
1634 }
1635
1636 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001637 jniThrowException(env, "java/lang/IllegalArgumentException",
1638 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001639 return NULL;
1640 }
1641
1642 String8 name = JStringToString8(env, jname);
1643 String8 value;
1644
1645 status_t err = drm->getPropertyString(name, value);
1646
1647 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1648 return NULL;
1649 }
1650
1651 return env->NewStringUTF(value.string());
1652}
1653
1654static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1655 JNIEnv *env, jobject thiz, jstring jname) {
1656 sp<IDrm> drm = GetDrm(env, thiz);
1657
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001658 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001659 return NULL;
1660 }
1661
1662 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001663 jniThrowException(env, "java/lang/IllegalArgumentException",
1664 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001665 return NULL;
1666 }
1667
1668 String8 name = JStringToString8(env, jname);
1669 Vector<uint8_t> value;
1670
1671 status_t err = drm->getPropertyByteArray(name, value);
1672
1673 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1674 return NULL;
1675 }
1676
1677 return VectorToJByteArray(env, value);
1678}
1679
1680static void android_media_MediaDrm_setPropertyString(
1681 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1682 sp<IDrm> drm = GetDrm(env, thiz);
1683
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001684 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001685 return;
1686 }
1687
Jeff Tinkereada5372013-05-21 12:48:14 -07001688 if (jname == NULL) {
1689 jniThrowException(env, "java/lang/IllegalArgumentException",
1690 "property name String is null");
1691 return;
1692 }
1693
1694 if (jvalue == NULL) {
1695 jniThrowException(env, "java/lang/IllegalArgumentException",
1696 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001697 return;
1698 }
1699
1700 String8 name = JStringToString8(env, jname);
1701 String8 value = JStringToString8(env, jvalue);
1702
1703 status_t err = drm->setPropertyString(name, value);
1704
1705 throwExceptionAsNecessary(env, err, "Failed to set property");
1706}
1707
1708static void android_media_MediaDrm_setPropertyByteArray(
1709 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1710 sp<IDrm> drm = GetDrm(env, thiz);
1711
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001712 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001713 return;
1714 }
1715
Jeff Tinkereada5372013-05-21 12:48:14 -07001716 if (jname == NULL) {
1717 jniThrowException(env, "java/lang/IllegalArgumentException",
1718 "property name String is null");
1719 return;
1720 }
1721
1722 if (jvalue == NULL) {
1723 jniThrowException(env, "java/lang/IllegalArgumentException",
1724 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001725 return;
1726 }
1727
1728 String8 name = JStringToString8(env, jname);
1729 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1730
1731 status_t err = drm->setPropertyByteArray(name, value);
1732
1733 throwExceptionAsNecessary(env, err, "Failed to set property");
1734}
1735
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001736static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001737 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001738 jstring jalgorithm) {
1739
1740 sp<IDrm> drm = GetDrm(env, jdrm);
1741
1742 if (!CheckSession(env, drm, jsessionId)) {
1743 return;
1744 }
1745
1746 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001747 jniThrowException(env, "java/lang/IllegalArgumentException",
1748 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001749 return;
1750 }
1751
1752 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1753 String8 algorithm = JStringToString8(env, jalgorithm);
1754
1755 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1756
1757 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
1758}
1759
1760static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001761 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001762 jstring jalgorithm) {
1763
1764 sp<IDrm> drm = GetDrm(env, jdrm);
1765
1766 if (!CheckSession(env, drm, jsessionId)) {
1767 return;
1768 }
1769
1770 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001771 jniThrowException(env, "java/lang/IllegalArgumentException",
1772 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001773 return;
1774 }
1775
1776 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1777 String8 algorithm = JStringToString8(env, jalgorithm);
1778
1779 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1780
1781 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1782}
1783
1784
1785static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001786 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001787 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1788
1789 sp<IDrm> drm = GetDrm(env, jdrm);
1790
1791 if (!CheckSession(env, drm, jsessionId)) {
1792 return NULL;
1793 }
1794
1795 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001796 jniThrowException(env, "java/lang/IllegalArgumentException",
1797 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001798 return NULL;
1799 }
1800
1801 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1802 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1803 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1804 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1805 Vector<uint8_t> output;
1806
1807 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1808
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001809 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
1810 return NULL;
1811 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001812
1813 return VectorToJByteArray(env, output);
1814}
1815
1816static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001817 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001818 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1819
1820 sp<IDrm> drm = GetDrm(env, jdrm);
1821
1822 if (!CheckSession(env, drm, jsessionId)) {
1823 return NULL;
1824 }
1825
1826 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001827 jniThrowException(env, "java/lang/IllegalArgumentException",
1828 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001829 return NULL;
1830 }
1831
1832 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1833 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1834 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1835 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1836 Vector<uint8_t> output;
1837
1838 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001839 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
1840 return NULL;
1841 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001842
1843 return VectorToJByteArray(env, output);
1844}
1845
1846static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001847 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001848 jbyteArray jkeyId, jbyteArray jmessage) {
1849
1850 sp<IDrm> drm = GetDrm(env, jdrm);
1851
1852 if (!CheckSession(env, drm, jsessionId)) {
1853 return NULL;
1854 }
1855
1856 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001857 jniThrowException(env, "java/lang/IllegalArgumentException",
1858 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001859 return NULL;
1860 }
1861
1862 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1863 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1864 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1865 Vector<uint8_t> signature;
1866
1867 status_t err = drm->sign(sessionId, keyId, message, signature);
1868
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001869 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1870 return NULL;
1871 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001872
1873 return VectorToJByteArray(env, signature);
1874}
1875
1876static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001877 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001878 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1879
1880 sp<IDrm> drm = GetDrm(env, jdrm);
1881
1882 if (!CheckSession(env, drm, jsessionId)) {
1883 return false;
1884 }
1885
1886 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001887 jniThrowException(env, "java/lang/IllegalArgumentException",
1888 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001889 return false;
1890 }
1891
1892 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1893 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1894 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1895 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1896 bool match;
1897
1898 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1899
1900 throwExceptionAsNecessary(env, err, "Failed to verify");
1901 return match;
1902}
1903
Adam Stonec06e10e2017-12-19 12:54:33 -08001904static jobject
1905android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1906{
1907 sp<IDrm> drm = GetDrm(env, thiz);
Jeff Tinker55d26242018-10-10 16:10:43 -07001908
1909 if (!CheckDrm(env, drm)) {
Adam Stonec06e10e2017-12-19 12:54:33 -08001910 return NULL;
1911 }
1912
1913 // Retrieve current metrics snapshot from drm.
Adam Stone94395c92018-01-30 12:07:00 -08001914 PersistableBundle metrics;
Robert Shihba6777e2019-11-12 13:04:59 -08001915 sp<IDrmMetricsConsumer> consumer(new DrmMetricsConsumer(&metrics));
1916 status_t err = drm->getMetrics(consumer);
Adam Stonec06e10e2017-12-19 12:54:33 -08001917 if (err != OK) {
1918 ALOGE("getMetrics failed: %d", (int)err);
1919 return (jobject) NULL;
1920 }
1921
Robert Shih4354a962019-11-10 12:09:08 -08001922 return MediaMetricsJNI::nativeToJavaPersistableBundle(env, &metrics);
Adam Stonec06e10e2017-12-19 12:54:33 -08001923}
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001924
Jeff Tinkere4095a82014-03-04 13:17:11 -08001925static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001926 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001927 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1928
1929 sp<IDrm> drm = GetDrm(env, jdrm);
1930
1931 if (!CheckSession(env, drm, jsessionId)) {
1932 return NULL;
1933 }
1934
1935 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1936 jniThrowException(env, "java/lang/IllegalArgumentException",
1937 "required argument is null");
1938 return NULL;
1939 }
1940
1941 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1942 String8 algorithm = JStringToString8(env, jalgorithm);
1943 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1944 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1945 Vector<uint8_t> signature;
1946
1947 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1948
1949 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1950 return NULL;
1951 }
1952
1953 return VectorToJByteArray(env, signature);
1954}
1955
Robert Shih205f7a92021-01-19 21:12:10 -08001956static jboolean android_media_MediaDrm_requiresSecureDecoder(
1957 JNIEnv *env, jobject thiz, jstring jmimeType,
1958 jint jSecurityLevel) {
1959 sp<IDrm> drm = GetDrm(env, thiz);
1960 if (!CheckDrm(env, drm)) {
1961 return JNI_FALSE;
1962 }
1963
1964 String8 mimeType;
1965 if (jmimeType != NULL) {
1966 mimeType = JStringToString8(env, jmimeType);
1967 }
1968
1969 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
1970 if (securityLevel == DrmPlugin::kSecurityLevelUnknown) {
1971 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1972 return JNI_FALSE;
1973 }
1974
1975 if (securityLevel == DrmPlugin::kSecurityLevelMax) {
1976 return drm->requiresSecureDecoder(mimeType.c_str());
1977 }
1978 return drm->requiresSecureDecoder(mimeType.c_str(), securityLevel);
1979}
Jeff Tinkere4095a82014-03-04 13:17:11 -08001980
Daniel Micay76f6a862015-09-19 17:31:01 -04001981static const JNINativeMethod gMethods[] = {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001982 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
1983
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001984 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
1985
Edwin Wong4d1d84e2017-01-04 09:37:49 -08001986 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001987 (void *)android_media_MediaDrm_native_setup },
1988
Robert Shihd2e8b432019-11-21 20:27:56 -08001989 { "getSupportedCryptoSchemesNative", "()[B",
1990 (void *)android_media_MediaDrm_getSupportedCryptoSchemesNative },
1991
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001992 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001993 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
1994
Jeff Tinker2bca5252018-02-11 18:59:14 +00001995 { "openSession", "(I)[B",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001996 (void *)android_media_MediaDrm_openSession },
1997
1998 { "closeSession", "([B)V",
1999 (void *)android_media_MediaDrm_closeSession },
2000
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002001 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
2002 "Landroid/media/MediaDrm$KeyRequest;",
2003 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002004
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002005 { "provideKeyResponse", "([B[B)[B",
2006 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002007
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002008 { "removeKeys", "([B)V",
2009 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002010
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002011 { "restoreKeys", "([B[B)V",
2012 (void *)android_media_MediaDrm_restoreKeys },
2013
2014 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
2015 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002016
Jeff Tinkere4095a82014-03-04 13:17:11 -08002017 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
2018 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002019
Jeff Tinkere4095a82014-03-04 13:17:11 -08002020 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
2021 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002022
2023 { "getSecureStops", "()Ljava/util/List;",
2024 (void *)android_media_MediaDrm_getSecureStops },
2025
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002026 { "getSecureStopIds", "()Ljava/util/List;",
2027 (void *)android_media_MediaDrm_getSecureStopIds },
2028
Jeff Tinker1b51c722014-10-31 00:54:26 -07002029 { "getSecureStop", "([B)[B",
2030 (void *)android_media_MediaDrm_getSecureStop },
2031
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002032 { "releaseSecureStops", "([B)V",
2033 (void *)android_media_MediaDrm_releaseSecureStops },
2034
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002035 { "removeSecureStop", "([B)V",
2036 (void *)android_media_MediaDrm_removeSecureStop },
2037
2038 { "removeAllSecureStops", "()V",
2039 (void *)android_media_MediaDrm_removeAllSecureStops },
Jeff Tinker1b51c722014-10-31 00:54:26 -07002040
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002041 { "getConnectedHdcpLevel", "()I",
2042 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
2043
2044 { "getMaxHdcpLevel", "()I",
2045 (void *)android_media_MediaDrm_getMaxHdcpLevel },
2046
2047 { "getOpenSessionCount", "()I",
2048 (void *)android_media_MediaDrm_getOpenSessionCount },
2049
2050 { "getMaxSessionCount", "()I",
2051 (void *)android_media_MediaDrm_getMaxSessionCount },
2052
2053 { "getSecurityLevel", "([B)I",
2054 (void *)android_media_MediaDrm_getSecurityLevel },
2055
Jeff Tinker55d26242018-10-10 16:10:43 -07002056 { "removeOfflineLicense", "([B)V",
2057 (void *)android_media_MediaDrm_removeOfflineLicense },
2058
2059 { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
2060 (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
2061
2062 { "getOfflineLicenseState", "([B)I",
2063 (void *)android_media_MediaDrm_getOfflineLicenseState },
2064
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002065 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
2066 (void *)android_media_MediaDrm_getPropertyString },
2067
2068 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
2069 (void *)android_media_MediaDrm_getPropertyByteArray },
2070
2071 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
2072 (void *)android_media_MediaDrm_setPropertyString },
2073
2074 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
2075 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002076
2077 { "setCipherAlgorithmNative",
2078 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2079 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
2080
2081 { "setMacAlgorithmNative",
2082 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2083 (void *)android_media_MediaDrm_setMacAlgorithmNative },
2084
2085 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2086 (void *)android_media_MediaDrm_encryptNative },
2087
2088 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2089 (void *)android_media_MediaDrm_decryptNative },
2090
2091 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
2092 (void *)android_media_MediaDrm_signNative },
2093
2094 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
2095 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08002096
2097 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
2098 (void *)android_media_MediaDrm_signRSANative },
Adam Stonec06e10e2017-12-19 12:54:33 -08002099
2100 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
2101 (void *)android_media_MediaDrm_native_getMetrics },
Robert Shih205f7a92021-01-19 21:12:10 -08002102
2103 { "requiresSecureDecoder", "(Ljava/lang/String;I)Z",
2104 (void *)android_media_MediaDrm_requiresSecureDecoder },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002105};
2106
2107int register_android_media_Drm(JNIEnv *env) {
2108 return AndroidRuntime::registerNativeMethods(env,
2109 "android/media/MediaDrm", gMethods, NELEM(gMethods));
2110}