blob: fc153669128c32025a3cd5a730e45ca31002dfbc [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>
Robert Shih696989f2021-02-12 23:25:16 -080040#include <utils/Vector.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080041
Adam Stone94395c92018-01-30 12:07:00 -080042using ::android::os::PersistableBundle;
Robert Shihd2e8b432019-11-21 20:27:56 -080043namespace drm = ::android::hardware::drm;
Adam Stone94395c92018-01-30 12:07:00 -080044
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080045namespace android {
46
47#define FIND_CLASS(var, className) \
48 var = env->FindClass(className); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070049 LOG_FATAL_IF(! (var), "Unable to find class %s", className);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080050
51#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
52 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070053 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080054
55#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
56 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070057 LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080058
Jeff Tinker54cfbd62013-04-02 13:14:59 -070059#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
60 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070061 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070062
63#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
64 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070065 LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070066
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070067#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \
68 var = env->GetStaticObjectField(clazz, fieldId); \
69 LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId);
Adam Stone94395c92018-01-30 12:07:00 -080070
Jeff Tinker54cfbd62013-04-02 13:14:59 -070071
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080072struct RequestFields {
73 jfieldID data;
74 jfieldID defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -070075 jfieldID requestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080076};
77
78struct ArrayListFields {
79 jmethodID init;
80 jmethodID add;
81};
82
83struct HashmapFields {
84 jmethodID init;
85 jmethodID get;
86 jmethodID put;
87 jmethodID entrySet;
88};
89
90struct SetFields {
91 jmethodID iterator;
92};
93
94struct IteratorFields {
95 jmethodID next;
96 jmethodID hasNext;
97};
98
99struct EntryFields {
100 jmethodID getKey;
101 jmethodID getValue;
102};
103
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700104struct EventTypes {
Jeff Tinker17b89222013-05-21 12:35:06 -0700105 jint kEventProvisionRequired;
106 jint kEventKeyRequired;
107 jint kEventKeyExpired;
108 jint kEventVendorDefined;
Ronghua Wua6d72092015-03-04 11:16:02 -0800109 jint kEventSessionReclaimed;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700110} gEventTypes;
111
Jeff Tinker74797f82015-03-31 15:44:34 -0700112struct EventWhat {
113 jint kWhatDrmEvent;
114 jint kWhatExpirationUpdate;
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700115 jint kWhatKeyStatusChange;
Jeff Tinker20594d82018-12-12 08:31:22 -0800116 jint kWhatSessionLostState;
Jeff Tinker74797f82015-03-31 15:44:34 -0700117} gEventWhat;
118
Jeff Tinker17b89222013-05-21 12:35:06 -0700119struct KeyTypes {
120 jint kKeyTypeStreaming;
121 jint kKeyTypeOffline;
122 jint kKeyTypeRelease;
123} gKeyTypes;
124
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700125struct KeyRequestTypes {
126 jint kKeyRequestTypeInitial;
127 jint kKeyRequestTypeRenewal;
128 jint kKeyRequestTypeRelease;
Rahul Frias8f761ba2018-01-22 23:43:54 -0800129 jint kKeyRequestTypeNone;
130 jint kKeyRequestTypeUpdate;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700131} gKeyRequestTypes;
132
Jeff Tinkere4095a82014-03-04 13:17:11 -0800133struct CertificateTypes {
134 jint kCertificateTypeNone;
135 jint kCertificateTypeX509;
136} gCertificateTypes;
137
138struct CertificateFields {
139 jfieldID wrappedPrivateKey;
140 jfieldID certificateData;
141};
142
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700143struct StateExceptionFields {
144 jmethodID init;
145 jclass classId;
146};
147
Jeff Tinker20594d82018-12-12 08:31:22 -0800148struct SessionExceptionFields {
149 jmethodID init;
150 jclass classId;
151 jfieldID errorCode;
152};
153
154struct SessionExceptionErrorCodes {
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800155 jint kErrorUnknown;
Jeff Tinker20594d82018-12-12 08:31:22 -0800156 jint kResourceContention;
157} gSessionExceptionErrorCodes;
158
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800159struct HDCPLevels {
160 jint kHdcpLevelUnknown;
161 jint kHdcpNone;
162 jint kHdcpV1;
163 jint kHdcpV2;
164 jint kHdcpV2_1;
165 jint kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800166 jint kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800167 jint kHdcpNoOutput;
168} gHdcpLevels;
169
170struct SecurityLevels {
171 jint kSecurityLevelUnknown;
Jeff Tinker2bca5252018-02-11 18:59:14 +0000172 jint kSecurityLevelMax;
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800173 jint kSecurityLevelSwSecureCrypto;
174 jint kSecurityLevelSwSecureDecode;
175 jint kSecurityLevelHwSecureCrypto;
176 jint kSecurityLevelHwSecureDecode;
177 jint kSecurityLevelHwSecureAll;
178} gSecurityLevels;
179
Jeff Tinker55d26242018-10-10 16:10:43 -0700180struct OfflineLicenseState {
181 jint kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800182 jint kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -0700183 jint kOfflineLicenseStateUnknown;
184} gOfflineLicenseStates;
185
Robert Shih9d4e2d42019-11-08 13:51:49 -0800186struct KeyStatusFields {
187 jmethodID init;
188 jclass classId;
189};
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800190
Robert Shih696989f2021-02-12 23:25:16 -0800191struct LogMessageFields {
192 jmethodID init;
193 jclass classId;
194};
195
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800196struct fields_t {
197 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700198 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700199 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800200 RequestFields provisionRequest;
201 ArrayListFields arraylist;
202 HashmapFields hashmap;
203 SetFields set;
204 IteratorFields iterator;
205 EntryFields entry;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800206 CertificateFields certificate;
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700207 StateExceptionFields stateException;
Jeff Tinker20594d82018-12-12 08:31:22 -0800208 SessionExceptionFields sessionException;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800209 jclass certificateClassId;
210 jclass hashmapClassId;
211 jclass arraylistClassId;
212 jclass stringClassId;
Adam Stone94395c92018-01-30 12:07:00 -0800213 jobject bundleCreator;
214 jmethodID createFromParcelId;
215 jclass parcelCreatorClassId;
Robert Shih9d4e2d42019-11-08 13:51:49 -0800216 KeyStatusFields keyStatus;
Robert Shih696989f2021-02-12 23:25:16 -0800217 LogMessageFields logMessage;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800218};
219
220static fields_t gFields;
221
Adam Stone94395c92018-01-30 12:07:00 -0800222namespace {
223
Robert Shih9d4e2d42019-11-08 13:51:49 -0800224jbyteArray hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> &vector) {
225 JNIEnv *env = AndroidRuntime::getJNIEnv();
226 size_t length = vector.size();
227 jbyteArray result = env->NewByteArray(length);
228 if (result != NULL) {
229 env->SetByteArrayRegion(result, 0, length, reinterpret_cast<const jbyte *>(vector.data()));
230 }
231 return result;
232}
233
Robert Shih696989f2021-02-12 23:25:16 -0800234jobject hidlLogMessagesToJavaList(JNIEnv *env, const Vector<drm::V1_4::LogMessage> &logs) {
235 jclass clazz = gFields.arraylistClassId;
236 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
237 clazz = gFields.logMessage.classId;
238 for (auto log: logs) {
239 jobject jLog = env->NewObject(clazz, gFields.logMessage.init,
240 static_cast<jlong>(log.timeMs),
241 static_cast<jint>(log.priority),
242 env->NewStringUTF(log.message.c_str()));
243 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jLog);
244 }
245 return arrayList;
246}
Adam Stone94395c92018-01-30 12:07:00 -0800247} // namespace anonymous
248
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700249// ----------------------------------------------------------------------------
250// ref-counted object for callbacks
251class JNIDrmListener: public DrmListener
252{
253public:
254 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
255 ~JNIDrmListener();
Robert Shih9d4e2d42019-11-08 13:51:49 -0800256 virtual void notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *arg = NULL);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700257private:
258 JNIDrmListener();
259 jclass mClass; // Reference to MediaDrm class
260 jobject mObject; // Weak ref to MediaDrm Java object to call on
261};
262
263JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
264{
265 // Hold onto the MediaDrm class for use in calling the static method
266 // that posts events to the application thread.
267 jclass clazz = env->GetObjectClass(thiz);
268 if (clazz == NULL) {
269 ALOGE("Can't find android/media/MediaDrm");
Jeff Tinkereada5372013-05-21 12:48:14 -0700270 jniThrowException(env, "java/lang/Exception",
271 "Can't find android/media/MediaDrm");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700272 return;
273 }
274 mClass = (jclass)env->NewGlobalRef(clazz);
275
276 // We use a weak reference so the MediaDrm object can be garbage collected.
277 // The reference is only used as a proxy for callbacks.
278 mObject = env->NewGlobalRef(weak_thiz);
279}
280
281JNIDrmListener::~JNIDrmListener()
282{
283 // remove global references
284 JNIEnv *env = AndroidRuntime::getJNIEnv();
285 env->DeleteGlobalRef(mObject);
286 env->DeleteGlobalRef(mClass);
287}
288
289void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
Robert Shih9d4e2d42019-11-08 13:51:49 -0800290 const ListenerArgs *args)
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700291{
Jeff Tinker74797f82015-03-31 15:44:34 -0700292 jint jwhat;
293 jint jeventType = 0;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700294
295 // translate DrmPlugin event types into their java equivalents
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700296 switch (eventType) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700297 case DrmPlugin::kDrmPluginEventProvisionRequired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700298 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700299 jeventType = gEventTypes.kEventProvisionRequired;
300 break;
301 case DrmPlugin::kDrmPluginEventKeyNeeded:
Jeff Tinker74797f82015-03-31 15:44:34 -0700302 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700303 jeventType = gEventTypes.kEventKeyRequired;
304 break;
305 case DrmPlugin::kDrmPluginEventKeyExpired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700306 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700307 jeventType = gEventTypes.kEventKeyExpired;
308 break;
309 case DrmPlugin::kDrmPluginEventVendorDefined:
Jeff Tinker74797f82015-03-31 15:44:34 -0700310 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700311 jeventType = gEventTypes.kEventVendorDefined;
312 break;
Ronghua Wua6d72092015-03-04 11:16:02 -0800313 case DrmPlugin::kDrmPluginEventSessionReclaimed:
Jeff Tinker74797f82015-03-31 15:44:34 -0700314 jwhat = gEventWhat.kWhatDrmEvent;
Ronghua Wua6d72092015-03-04 11:16:02 -0800315 jeventType = gEventTypes.kEventSessionReclaimed;
316 break;
Jeff Tinker74797f82015-03-31 15:44:34 -0700317 case DrmPlugin::kDrmPluginEventExpirationUpdate:
318 jwhat = gEventWhat.kWhatExpirationUpdate;
319 break;
320 case DrmPlugin::kDrmPluginEventKeysChange:
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700321 jwhat = gEventWhat.kWhatKeyStatusChange;
Jeff Tinker74797f82015-03-31 15:44:34 -0700322 break;
Jeff Tinker20594d82018-12-12 08:31:22 -0800323 case DrmPlugin::kDrmPluginEventSessionLostState:
324 jwhat = gEventWhat.kWhatSessionLostState;
325 break;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700326 default:
327 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
328 return;
329 }
330
331 JNIEnv *env = AndroidRuntime::getJNIEnv();
Robert Shih9d4e2d42019-11-08 13:51:49 -0800332 if (args) {
333 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
334 jwhat, jeventType, extra,
335 args->jSessionId, args->jData, args->jExpirationTime,
336 args->jKeyStatusList, args->jHasNewUsableKey);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700337 }
338
339 if (env->ExceptionCheck()) {
340 ALOGW("An exception occurred while notifying an event.");
341 LOGW_EX(env);
342 env->ExceptionClear();
343 }
344}
345
Robert Shih620f4a62021-02-15 03:28:42 -0800346jint MediaErrorToJavaError(status_t err) {
347#define STATUS_CASE(status) \
348 case status: \
349 return J##status
350
351 switch (err) {
352 STATUS_CASE(ERROR_DRM_UNKNOWN);
353 STATUS_CASE(ERROR_DRM_NO_LICENSE);
354 STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
355 STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
356 STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
357 STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
358 STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
359 STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
360 STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
361 STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
362 STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
363 STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
364 STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
365 STATUS_CASE(ERROR_DRM_GENERIC_OEM);
366 STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
367 STATUS_CASE(ERROR_DRM_INIT_DATA);
368 STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
369 STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
370 STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
371 STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
372 STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
373 STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
374 STATUS_CASE(ERROR_DRM_LICENSE_STATE);
375 STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
376 STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
377 STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
378 STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
379 STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
380 STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
381 STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
382 STATUS_CASE(ERROR_DRM_STORAGE_READ);
383 STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
384 STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
385#undef STATUS_CASE
386 }
387 return static_cast<jint>(err);
388}
389
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700390static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
391 ALOGE("Illegal state exception: %s (%d)", msg, err);
392
Robert Shih620f4a62021-02-15 03:28:42 -0800393 jint jerr = MediaErrorToJavaError(err);
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700394 jobject exception = env->NewObject(gFields.stateException.classId,
Robert Shih620f4a62021-02-15 03:28:42 -0800395 gFields.stateException.init, static_cast<int>(jerr),
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700396 env->NewStringUTF(msg));
397 env->Throw(static_cast<jthrowable>(exception));
398}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700399
Jeff Tinker20594d82018-12-12 08:31:22 -0800400static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
401 ALOGE("Session exception: %s (%d)", msg, err);
402
403 jint jErrorCode = 0;
404 switch(err) {
405 case ERROR_DRM_RESOURCE_CONTENTION:
406 jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
407 break;
408 default:
409 break;
410 }
411
412 jobject exception = env->NewObject(gFields.sessionException.classId,
413 gFields.sessionException.init, static_cast<int>(err),
414 env->NewStringUTF(msg));
415
416 env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
417 env->Throw(static_cast<jthrowable>(exception));
418}
419
420static bool isSessionException(status_t err) {
421 return err == ERROR_DRM_RESOURCE_CONTENTION;
422}
423
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800424static bool throwExceptionAsNecessary(
425 JNIEnv *env, status_t err, const char *msg = NULL) {
426
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700427 const char *drmMessage = NULL;
428
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700429 switch (err) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700430 case ERROR_DRM_UNKNOWN:
431 drmMessage = "General DRM error";
432 break;
433 case ERROR_DRM_NO_LICENSE:
434 drmMessage = "No license";
435 break;
436 case ERROR_DRM_LICENSE_EXPIRED:
437 drmMessage = "License expired";
438 break;
439 case ERROR_DRM_SESSION_NOT_OPENED:
440 drmMessage = "Session not opened";
441 break;
442 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
443 drmMessage = "Not initialized";
444 break;
445 case ERROR_DRM_DECRYPT:
446 drmMessage = "Decrypt error";
447 break;
448 case ERROR_DRM_CANNOT_HANDLE:
Jeff Tinkereb13c762017-11-01 15:29:38 -0700449 drmMessage = "Invalid parameter or data format";
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700450 break;
Jeff Tinker20594d82018-12-12 08:31:22 -0800451 case ERROR_DRM_INVALID_STATE:
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700452 drmMessage = "Invalid state";
453 break;
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700454 default:
455 break;
456 }
457
458 String8 vendorMessage;
459 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
Jeff Tinker29799862014-08-27 11:05:13 -0700460 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700461 drmMessage = vendorMessage.string();
462 }
463
Jeff Tinkereb13c762017-11-01 15:29:38 -0700464 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800465 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
466 return true;
Jeff Tinker5de2e902019-01-25 23:09:36 -0800467 } else if (err == ERROR_UNSUPPORTED) {
468 jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
469 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700470 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
471 jniThrowException(env, "android/media/NotProvisionedException", msg);
472 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700473 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
474 jniThrowException(env, "android/media/ResourceBusyException", msg);
475 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700476 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
477 jniThrowException(env, "android/media/DeniedByServerException", msg);
478 return true;
Jeff Tinker314b7f32015-06-15 17:45:43 -0700479 } else if (err == DEAD_OBJECT) {
480 jniThrowException(env, "android/media/MediaDrmResetException",
481 "mediaserver died");
482 return true;
Jeff Tinker20594d82018-12-12 08:31:22 -0800483 } else if (isSessionException(err)) {
484 throwSessionException(env, msg, err);
485 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800486 } else if (err != OK) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700487 String8 errbuf;
488 if (drmMessage != NULL) {
489 if (msg == NULL) {
490 msg = drmMessage;
491 } else {
Jeff Tinker29799862014-08-27 11:05:13 -0700492 errbuf = String8::format("%s: %s", msg, drmMessage);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700493 msg = errbuf.string();
494 }
495 }
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700496 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800497 return true;
498 }
499 return false;
500}
501
502static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000503 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800504 return jdrm ? jdrm->getDrm() : NULL;
505}
506
507JDrm::JDrm(
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800508 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
509 const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800510 mObject = env->NewWeakGlobalRef(thiz);
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800511 mDrm = MakeDrm(uuid, appPackageName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700512 if (mDrm != NULL) {
513 mDrm->setListener(this);
514 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800515}
516
517JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800518 JNIEnv *env = AndroidRuntime::getJNIEnv();
519
520 env->DeleteWeakGlobalRef(mObject);
521 mObject = NULL;
522}
523
524// static
525sp<IDrm> JDrm::MakeDrm() {
Robert Shih218b9532019-08-15 14:48:11 -0700526 return DrmUtils::MakeDrm();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800527}
528
529// static
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800530sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800531 sp<IDrm> drm = MakeDrm();
532
533 if (drm == NULL) {
534 return NULL;
535 }
536
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800537 status_t err = drm->createPlugin(uuid, appPackageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800538
539 if (err != OK) {
540 return NULL;
541 }
542
543 return drm;
544}
545
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700546status_t JDrm::setListener(const sp<DrmListener>& listener) {
547 Mutex::Autolock lock(mLock);
548 mListener = listener;
549 return OK;
550}
551
Robert Shih9d4e2d42019-11-08 13:51:49 -0800552void JDrm::notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *args) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700553 sp<DrmListener> listener;
554 mLock.lock();
555 listener = mListener;
556 mLock.unlock();
557
558 if (listener != NULL) {
559 Mutex::Autolock lock(mNotifyLock);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800560 listener->notify(eventType, extra, args);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700561 }
562}
563
Robert Shih3a523902019-08-15 14:48:11 -0700564void JDrm::sendEvent(
565 DrmPlugin::EventType eventType,
566 const hardware::hidl_vec<uint8_t> &sessionId,
567 const hardware::hidl_vec<uint8_t> &data) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800568 ListenerArgs args{
569 .jSessionId = hidlVectorToJByteArray(sessionId),
570 .jData = hidlVectorToJByteArray(data),
571 };
572 notify(eventType, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700573}
574
575void JDrm::sendExpirationUpdate(
576 const hardware::hidl_vec<uint8_t> &sessionId,
577 int64_t expiryTimeInMS) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800578 ListenerArgs args{
579 .jSessionId = hidlVectorToJByteArray(sessionId),
580 .jExpirationTime = expiryTimeInMS,
581 };
582 notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700583}
584
585void JDrm::sendKeysChange(
586 const hardware::hidl_vec<uint8_t> &sessionId,
587 const std::vector<DrmKeyStatus> &keyStatusList,
588 bool hasNewUsableKey) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800589 JNIEnv *env = AndroidRuntime::getJNIEnv();
590 jclass clazz = gFields.arraylistClassId;
591 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
592 clazz = gFields.keyStatus.classId;
593 for (const auto &keyStatus : keyStatusList) {
594 jbyteArray jKeyId(hidlVectorToJByteArray(keyStatus.keyId));
595 jint jStatusCode(keyStatus.type);
596 jobject jKeyStatus = env->NewObject(clazz, gFields.keyStatus.init, jKeyId, jStatusCode);
597 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jKeyStatus);
598 }
599 ListenerArgs args{
600 .jSessionId = hidlVectorToJByteArray(sessionId),
601 .jKeyStatusList = arrayList,
602 .jHasNewUsableKey = hasNewUsableKey,
603 };
604 notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700605}
606
607void JDrm::sendSessionLostState(
608 const hardware::hidl_vec<uint8_t> &sessionId) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800609 ListenerArgs args{
610 .jSessionId = hidlVectorToJByteArray(sessionId),
611 };
612 notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700613}
614
Jeff Tinker600071c2014-04-11 16:11:15 -0700615void JDrm::disconnect() {
616 if (mDrm != NULL) {
617 mDrm->destroyPlugin();
618 mDrm.clear();
619 }
620}
621
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700622
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800623// static
Jeff Tinker5de2e902019-01-25 23:09:36 -0800624status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
625 DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800626 sp<IDrm> drm = MakeDrm();
627
628 if (drm == NULL) {
Jeff Tinker5de2e902019-01-25 23:09:36 -0800629 return BAD_VALUE;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800630 }
631
Jeff Tinker5de2e902019-01-25 23:09:36 -0800632 return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800633}
634
635status_t JDrm::initCheck() const {
636 return mDrm == NULL ? NO_INIT : OK;
637}
638
639// JNI conversion utilities
640static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
641 Vector<uint8_t> vector;
642 size_t length = env->GetArrayLength(byteArray);
643 vector.insertAt((size_t)0, length);
644 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
645 return vector;
646}
647
648static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
649 size_t length = vector.size();
650 jbyteArray result = env->NewByteArray(length);
651 if (result != NULL) {
652 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
653 }
654 return result;
655}
656
657static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800658 String8 result;
659
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700660 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800661 if (s) {
662 result = s;
663 env->ReleaseStringUTFChars(jstr, s);
664 }
665 return result;
666}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700667
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800668/*
669 import java.util.HashMap;
670 import java.util.Set;
671 import java.Map.Entry;
672 import jav.util.Iterator;
673
674 HashMap<k, v> hm;
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800675 Set<Entry<k, v>> s = hm.entrySet();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800676 Iterator i = s.iterator();
677 Entry e = s.next();
678*/
679
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200680static KeyedVector<String8, String8> HashMapToKeyedVector(
681 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800682 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800683 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200684 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800685
686 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
687 if (entrySet) {
688 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
689 if (iterator) {
690 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
691 while (hasNext) {
692 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
693 if (entry) {
694 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200695 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700696 jniThrowException(env, "java/lang/IllegalArgumentException",
697 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200698 env->DeleteLocalRef(entry);
699 *pIsOK = false;
700 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800701 }
702 jstring jkey = static_cast<jstring>(obj);
703
704 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200705 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700706 jniThrowException(env, "java/lang/IllegalArgumentException",
707 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200708 env->DeleteLocalRef(entry);
709 *pIsOK = false;
710 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800711 }
712 jstring jvalue = static_cast<jstring>(obj);
713
714 String8 key = JStringToString8(env, jkey);
715 String8 value = JStringToString8(env, jvalue);
716 keyedVector.add(key, value);
717
718 env->DeleteLocalRef(jkey);
719 env->DeleteLocalRef(jvalue);
720 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
721 }
722 env->DeleteLocalRef(entry);
723 }
724 env->DeleteLocalRef(iterator);
725 }
726 env->DeleteLocalRef(entrySet);
727 }
728 return keyedVector;
729}
730
731static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800732 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800733 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
734 for (size_t i = 0; i < map.size(); ++i) {
735 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
736 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
737 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
738 env->DeleteLocalRef(jkey);
739 env->DeleteLocalRef(jvalue);
740 }
741 return hashMap;
742}
743
744static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800745 List<Vector<uint8_t>> list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800746 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800747 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800748 List<Vector<uint8_t>>::iterator iter = list.begin();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800749 while (iter != list.end()) {
750 jbyteArray byteArray = VectorToJByteArray(env, *iter);
751 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
752 env->DeleteLocalRef(byteArray);
753 iter++;
754 }
755
756 return arrayList;
757}
758
759} // namespace android
760
761using namespace android;
762
763static sp<JDrm> setDrm(
764 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000765 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800766 if (drm != NULL) {
767 drm->incStrong(thiz);
768 }
769 if (old != NULL) {
770 old->decStrong(thiz);
771 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000772 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800773
774 return old;
775}
776
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800777static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800778 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700779 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800780 return false;
781 }
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800782 return true;
783}
784
785static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
786{
787 if (!CheckDrm(env, drm)) {
788 return false;
789 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800790
791 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700792 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800793 return false;
794 }
795 return true;
796}
797
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800798static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700799 sp<JDrm> drm = setDrm(env, thiz, NULL);
800 if (drm != NULL) {
801 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700802 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700803 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800804}
805
806static void android_media_MediaDrm_native_init(JNIEnv *env) {
807 jclass clazz;
808 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000809 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700810 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
Robert Shih9d4e2d42019-11-08 13:51:49 -0800811 "(Ljava/lang/Object;III[B[BJLjava/util/List;Z)V");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700812
813 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700814 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700815 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700816 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700817 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700818 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700819 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700820 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700821 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Ronghua Wua6d72092015-03-04 11:16:02 -0800822 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
823 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800824
Jeff Tinker74797f82015-03-31 15:44:34 -0700825 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
826 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
827 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
828 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700829 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
830 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800831 GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
832 gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
Jeff Tinker74797f82015-03-31 15:44:34 -0700833
Jeff Tinker17b89222013-05-21 12:35:06 -0700834 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
835 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
836 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
837 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
838 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
839 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
840
Jeff Tinkere4095a82014-03-04 13:17:11 -0800841 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
842 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
843 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
844 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
845
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800846 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
847 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
848 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
849 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
850 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
851 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
852 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
853 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
854 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
855 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
856 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
857 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800858 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I");
859 gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field);
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800860 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
861 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
862
863 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
864 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700865 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800866 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700867 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800868 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700869 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800870 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700871 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800872 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700873 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800874 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
875
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800876 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I");
Jeff Tinker55d26242018-10-10 16:10:43 -0700877 gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800878 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I");
879 gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field);
Jeff Tinker55d26242018-10-10 16:10:43 -0700880 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
881 gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
882
883 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
884
Jeff Tinker2bca5252018-02-11 18:59:14 +0000885 jmethodID getMaxSecurityLevel;
886 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
887 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
888
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700889 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700890 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
891 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700892 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800893
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700894 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
895 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
896 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
897 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
898 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
899 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
Rahul Frias8f761ba2018-01-22 23:43:54 -0800900 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
901 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
902 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
903 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700904
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800905 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700906 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
907 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800908
Jeff Tinkere4095a82014-03-04 13:17:11 -0800909 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
910 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
911 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700912 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800913
Adam Stone94395c92018-01-30 12:07:00 -0800914 // Metrics-related fields and classes.
915 FIND_CLASS(clazz, "android/os/PersistableBundle");
916 jfieldID bundleCreatorId;
917 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
918 "Landroid/os/Parcelable$Creator;");
919 jobject bundleCreator;
920 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
921 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
922 FIND_CLASS(clazz, "android/os/Parcelable$Creator");
923 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
924 "(Landroid/os/Parcel;)Ljava/lang/Object;");
925 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
926
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800927 FIND_CLASS(clazz, "java/util/ArrayList");
928 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
929 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
930
931 FIND_CLASS(clazz, "java/util/HashMap");
932 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
933 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
934 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
935 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
936 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
937
938 FIND_CLASS(clazz, "java/util/Set");
939 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
940
941 FIND_CLASS(clazz, "java/util/Iterator");
942 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
943 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
944
945 FIND_CLASS(clazz, "java/util/Map$Entry");
946 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
947 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800948
949 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700950 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800951
952 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700953 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800954
955 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700956 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700957
958 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
959 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
960 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker20594d82018-12-12 08:31:22 -0800961
962 FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
963 GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
964 gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
965 GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
966
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800967 GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I");
968 gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800969 GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
970 gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800971
972 FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
973 gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
974 GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
Robert Shih696989f2021-02-12 23:25:16 -0800975
976 FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage");
977 gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
978 GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800979}
980
981static void android_media_MediaDrm_native_setup(
982 JNIEnv *env, jobject thiz,
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800983 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800984
985 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700986 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800987 return;
988 }
989
990 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
991
992 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700993 jniThrowException(env, "java/lang/IllegalArgumentException",
994 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800995 return;
996 }
997
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800998 String8 packageName;
999 if (jappPackageName == NULL) {
1000 jniThrowException(env, "java/lang/IllegalArgumentException",
1001 "application package name cannot be null");
1002 return;
1003 }
1004
1005 packageName = JStringToString8(env, jappPackageName);
1006 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001007
1008 status_t err = drm->initCheck();
1009
1010 if (err != OK) {
1011 jniThrowException(
1012 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -07001013 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001014 "Failed to instantiate drm object.");
1015 return;
1016 }
1017
Jeff Tinker54cfbd62013-04-02 13:14:59 -07001018 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
1019 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001020 setDrm(env, thiz, drm);
1021}
1022
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001023DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
1024 DrmPlugin::SecurityLevel level;
1025
1026 if (jlevel == gSecurityLevels.kSecurityLevelMax) {
1027 level = DrmPlugin::kSecurityLevelMax;
1028 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
1029 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
1030 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
1031 level = DrmPlugin::kSecurityLevelSwSecureDecode;
1032 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
1033 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
1034 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
1035 level = DrmPlugin::kSecurityLevelHwSecureDecode;
1036 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
1037 level = DrmPlugin::kSecurityLevelHwSecureAll;
1038 } else {
1039 level = DrmPlugin::kSecurityLevelUnknown;
1040 }
1041 return level;
1042}
1043
Robert Shihd2e8b432019-11-21 20:27:56 -08001044static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
1045 std::vector<uint8_t> bv;
1046 for (auto &factory : DrmUtils::MakeDrmFactories()) {
1047 sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
1048 if (factoryV1_3 == nullptr) {
1049 continue;
1050 }
1051 factoryV1_3->getSupportedCryptoSchemes(
1052 [&](const hardware::hidl_vec<hardware::hidl_array<uint8_t, 16>>& schemes) {
1053 for (const auto &scheme : schemes) {
1054 bv.insert(bv.end(), scheme.data(), scheme.data() + scheme.size());
1055 }
1056 });
1057 }
1058
1059 jbyteArray jUuidBytes = env->NewByteArray(bv.size());
1060 env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast<const jbyte *>(bv.data()));
1061 return jUuidBytes;
1062}
1063
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001064static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001065 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType,
1066 jint jSecurityLevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001067
1068 if (uuidObj == NULL) {
1069 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1070 return false;
1071 }
1072
1073 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1074
1075 if (uuid.size() != 16) {
1076 jniThrowException(
1077 env,
1078 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -07001079 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001080 return false;
1081 }
1082
Jeff Tinker7cda4912013-08-21 11:52:34 -07001083 String8 mimeType;
1084 if (jmimeType != NULL) {
1085 mimeType = JStringToString8(env, jmimeType);
1086 }
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001087 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
Jeff Tinker7cda4912013-08-21 11:52:34 -07001088
Jeff Tinker5de2e902019-01-25 23:09:36 -08001089 bool isSupported;
1090 status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
1091 securityLevel, &isSupported);
1092
1093 if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
1094 return false;
1095 }
1096 return isSupported;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001097}
1098
1099static jbyteArray android_media_MediaDrm_openSession(
Jeff Tinker2bca5252018-02-11 18:59:14 +00001100 JNIEnv *env, jobject thiz, jint jlevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001101 sp<IDrm> drm = GetDrm(env, thiz);
1102
Jeff Tinker55d26242018-10-10 16:10:43 -07001103 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001104 return NULL;
1105 }
1106
1107 Vector<uint8_t> sessionId;
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001108 DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel);
1109 if (level == DrmPlugin::kSecurityLevelUnknown) {
Jeff Tinker2bca5252018-02-11 18:59:14 +00001110 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1111 return NULL;
1112 }
1113
1114 status_t err = drm->openSession(level, sessionId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001115
1116 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
1117 return NULL;
1118 }
1119
1120 return VectorToJByteArray(env, sessionId);
1121}
1122
1123static void android_media_MediaDrm_closeSession(
1124 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1125 sp<IDrm> drm = GetDrm(env, thiz);
1126
1127 if (!CheckSession(env, drm, jsessionId)) {
1128 return;
1129 }
1130
1131 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1132
1133 status_t err = drm->closeSession(sessionId);
1134
1135 throwExceptionAsNecessary(env, err, "Failed to close session");
1136}
1137
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001138static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001139 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001140 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001141 sp<IDrm> drm = GetDrm(env, thiz);
1142
1143 if (!CheckSession(env, drm, jsessionId)) {
1144 return NULL;
1145 }
1146
1147 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1148
1149 Vector<uint8_t> initData;
1150 if (jinitData != NULL) {
1151 initData = JByteArrayToVector(env, jinitData);
1152 }
1153
1154 String8 mimeType;
1155 if (jmimeType != NULL) {
1156 mimeType = JStringToString8(env, jmimeType);
1157 }
1158
Jeff Tinker17b89222013-05-21 12:35:06 -07001159 DrmPlugin::KeyType keyType;
1160 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
1161 keyType = DrmPlugin::kKeyType_Streaming;
1162 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
1163 keyType = DrmPlugin::kKeyType_Offline;
1164 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
1165 keyType = DrmPlugin::kKeyType_Release;
1166 } else {
1167 jniThrowException(env, "java/lang/IllegalArgumentException",
1168 "invalid keyType");
1169 return NULL;
1170 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001171
1172 KeyedVector<String8, String8> optParams;
1173 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +02001174 bool isOK;
1175 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
1176 if (!isOK) {
1177 return NULL;
1178 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001179 }
1180
1181 Vector<uint8_t> request;
1182 String8 defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001183 DrmPlugin::KeyRequestType keyRequestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001184
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001185 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001186 keyType, optParams, request, defaultUrl, &keyRequestType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001187
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001188 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001189 return NULL;
1190 }
1191
1192 // Fill out return obj
1193 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001194 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001195
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001196 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001197
1198 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001199 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001200 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001201 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001202
1203 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001204 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001205
1206 switch (keyRequestType) {
1207 case DrmPlugin::kKeyRequestType_Initial:
1208 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1209 gKeyRequestTypes.kKeyRequestTypeInitial);
1210 break;
1211 case DrmPlugin::kKeyRequestType_Renewal:
1212 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1213 gKeyRequestTypes.kKeyRequestTypeRenewal);
1214 break;
1215 case DrmPlugin::kKeyRequestType_Release:
1216 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1217 gKeyRequestTypes.kKeyRequestTypeRelease);
1218 break;
Rahul Frias8f761ba2018-01-22 23:43:54 -08001219 case DrmPlugin::kKeyRequestType_None:
1220 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1221 gKeyRequestTypes.kKeyRequestTypeNone);
1222 break;
1223 case DrmPlugin::kKeyRequestType_Update:
1224 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1225 gKeyRequestTypes.kKeyRequestTypeUpdate);
1226 break;
1227
Jeff Tinker74797f82015-03-31 15:44:34 -07001228 default:
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001229 throwStateException(env, "DRM plugin failure: unknown key request type",
1230 ERROR_DRM_UNKNOWN);
1231 break;
1232 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001233 }
1234
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001235 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001236}
1237
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001238static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001239 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
1240 sp<IDrm> drm = GetDrm(env, thiz);
1241
1242 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001243 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001244 }
1245
1246 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1247
1248 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001249 jniThrowException(env, "java/lang/IllegalArgumentException",
1250 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001251 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001252 }
1253 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001254 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001255
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001256 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001257
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001258 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
1259 return NULL;
1260 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001261 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001262}
1263
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001264static void android_media_MediaDrm_removeKeys(
1265 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
1266 sp<IDrm> drm = GetDrm(env, thiz);
1267
Jeff Tinker55d26242018-10-10 16:10:43 -07001268 if (!CheckDrm(env, drm)) {
1269 return;
1270 }
1271
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001272 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001273 jniThrowException(env, "java/lang/IllegalArgumentException",
1274 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001275 return;
1276 }
1277
1278 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1279
1280 status_t err = drm->removeKeys(keySetId);
1281
1282 throwExceptionAsNecessary(env, err, "Failed to remove keys");
1283}
1284
1285static void android_media_MediaDrm_restoreKeys(
1286 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
1287 jbyteArray jkeysetId) {
1288
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001289 sp<IDrm> drm = GetDrm(env, thiz);
1290
1291 if (!CheckSession(env, drm, jsessionId)) {
1292 return;
1293 }
1294
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001295 if (jkeysetId == NULL) {
1296 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1297 return;
1298 }
1299
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001300 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001301 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001302
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001303 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001304
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001305 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001306}
1307
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001308static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001309 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1310 sp<IDrm> drm = GetDrm(env, thiz);
1311
1312 if (!CheckSession(env, drm, jsessionId)) {
1313 return NULL;
1314 }
1315 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1316
1317 KeyedVector<String8, String8> infoMap;
1318
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001319 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001320
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001321 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001322 return NULL;
1323 }
1324
1325 return KeyedVectorToHashMap(env, infoMap);
1326}
1327
Jeff Tinkere4095a82014-03-04 13:17:11 -08001328static jobject android_media_MediaDrm_getProvisionRequestNative(
1329 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001330 sp<IDrm> drm = GetDrm(env, thiz);
1331
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001332 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001333 return NULL;
1334 }
1335
1336 Vector<uint8_t> request;
1337 String8 defaultUrl;
1338
Jeff Tinkere4095a82014-03-04 13:17:11 -08001339 String8 certType;
1340 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1341 certType = "X.509";
1342 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1343 certType = "none";
1344 } else {
1345 certType = "invalid";
1346 }
1347
1348 String8 certAuthority = JStringToString8(env, jcertAuthority);
1349 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001350
1351 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
1352 return NULL;
1353 }
1354
1355 // Fill out return obj
1356 jclass clazz;
1357 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1358
1359 jobject provisionObj = NULL;
1360
1361 if (clazz) {
1362 provisionObj = env->AllocObject(clazz);
1363 jbyteArray jrequest = VectorToJByteArray(env, request);
1364 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1365
1366 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1367 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1368 }
1369
1370 return provisionObj;
1371}
1372
Jeff Tinkere4095a82014-03-04 13:17:11 -08001373static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001374 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1375 sp<IDrm> drm = GetDrm(env, thiz);
1376
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001377 if (!CheckDrm(env, drm)) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001378 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001379 }
1380
1381 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001382 jniThrowException(env, "java/lang/IllegalArgumentException",
1383 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001384 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001385 }
1386
1387 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -08001388 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001389
Jeff Tinkere4095a82014-03-04 13:17:11 -08001390 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1391
1392 // Fill out return obj
1393 jclass clazz = gFields.certificateClassId;
1394
1395 jobject certificateObj = NULL;
1396
1397 if (clazz && certificate.size() && wrappedKey.size()) {
1398 certificateObj = env->AllocObject(clazz);
1399 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1400 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1401
1402 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1403 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1404 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001405
1406 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001407 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001408}
1409
1410static jobject android_media_MediaDrm_getSecureStops(
1411 JNIEnv *env, jobject thiz) {
1412 sp<IDrm> drm = GetDrm(env, thiz);
1413
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001414 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001415 return NULL;
1416 }
1417
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001418 List<Vector<uint8_t>> secureStops;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001419
1420 status_t err = drm->getSecureStops(secureStops);
1421
1422 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
1423 return NULL;
1424 }
1425
1426 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1427}
1428
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001429static jobject android_media_MediaDrm_getSecureStopIds(
1430 JNIEnv *env, jobject thiz) {
1431 sp<IDrm> drm = GetDrm(env, thiz);
1432
Jeff Tinker55d26242018-10-10 16:10:43 -07001433 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001434 return NULL;
1435 }
1436
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001437 List<Vector<uint8_t>> secureStopIds;
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001438
1439 status_t err = drm->getSecureStopIds(secureStopIds);
1440
1441 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
1442 return NULL;
1443 }
1444
1445 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1446}
1447
Jeff Tinker1b51c722014-10-31 00:54:26 -07001448static jbyteArray android_media_MediaDrm_getSecureStop(
1449 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1450 sp<IDrm> drm = GetDrm(env, thiz);
1451
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001452 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001453 return NULL;
1454 }
1455
1456 Vector<uint8_t> secureStop;
1457
1458 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1459
1460 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
1461 return NULL;
1462 }
1463
1464 return VectorToJByteArray(env, secureStop);
1465}
1466
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001467static void android_media_MediaDrm_releaseSecureStops(
1468 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1469 sp<IDrm> drm = GetDrm(env, thiz);
1470
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001471 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001472 return;
1473 }
1474
1475 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1476
1477 status_t err = drm->releaseSecureStops(ssRelease);
1478
1479 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
1480}
1481
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001482static void android_media_MediaDrm_removeSecureStop(
1483 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1484 sp<IDrm> drm = GetDrm(env, thiz);
1485
Jeff Tinker55d26242018-10-10 16:10:43 -07001486 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001487 return;
1488 }
1489
1490 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1491
1492 throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
1493}
1494
1495static void android_media_MediaDrm_removeAllSecureStops(
Jeff Tinker1b51c722014-10-31 00:54:26 -07001496 JNIEnv *env, jobject thiz) {
1497 sp<IDrm> drm = GetDrm(env, thiz);
1498
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001499 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001500 return;
1501 }
1502
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001503 status_t err = drm->removeAllSecureStops();
Jeff Tinker1b51c722014-10-31 00:54:26 -07001504
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001505 throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
Jeff Tinker1b51c722014-10-31 00:54:26 -07001506}
1507
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001508
1509static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1510 switch(level) {
1511 case DrmPlugin::kHdcpLevelUnknown:
1512 return gHdcpLevels.kHdcpLevelUnknown;
1513 case DrmPlugin::kHdcpNone:
1514 return gHdcpLevels.kHdcpNone;
1515 case DrmPlugin::kHdcpV1:
1516 return gHdcpLevels.kHdcpV1;
1517 case DrmPlugin::kHdcpV2:
1518 return gHdcpLevels.kHdcpV2;
1519 case DrmPlugin::kHdcpV2_1:
1520 return gHdcpLevels.kHdcpV2_1;
1521 case DrmPlugin::kHdcpV2_2:
1522 return gHdcpLevels.kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -08001523 case DrmPlugin::kHdcpV2_3:
1524 return gHdcpLevels.kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001525 case DrmPlugin::kHdcpNoOutput:
1526 return gHdcpLevels.kHdcpNoOutput;
1527 }
1528 return gHdcpLevels.kHdcpNone;
1529}
1530
1531static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1532 jobject thiz) {
1533 sp<IDrm> drm = GetDrm(env, thiz);
1534
1535 if (!CheckDrm(env, drm)) {
1536 return gHdcpLevels.kHdcpNone;
1537 }
1538
1539 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1540 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1541
1542 status_t err = drm->getHdcpLevels(&connected, &max);
1543
1544 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1545 return gHdcpLevels.kHdcpLevelUnknown;
1546 }
1547 return HdcpLevelTojint(connected);
1548}
1549
1550static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1551 jobject thiz) {
1552 sp<IDrm> drm = GetDrm(env, thiz);
1553
1554 if (!CheckDrm(env, drm)) {
1555 return gHdcpLevels.kHdcpLevelUnknown;
1556 }
1557
1558 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1559 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1560
1561 status_t err = drm->getHdcpLevels(&connected, &max);
1562
1563 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1564 return gHdcpLevels.kHdcpLevelUnknown;
1565 }
1566 return HdcpLevelTojint(max);
1567}
1568
1569static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1570 jobject thiz) {
1571 sp<IDrm> drm = GetDrm(env, thiz);
1572
1573 if (!CheckDrm(env, drm)) {
1574 return 0;
1575 }
1576
1577 uint32_t open = 0, max = 0;
1578 status_t err = drm->getNumberOfSessions(&open, &max);
1579
1580 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1581 return 0;
1582 }
1583 return open;
1584}
1585
1586static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1587 jobject thiz) {
1588 sp<IDrm> drm = GetDrm(env, thiz);
1589
1590 if (!CheckDrm(env, drm)) {
1591 return 0;
1592 }
1593
1594 uint32_t open = 0, max = 0;
1595 status_t err = drm->getNumberOfSessions(&open, &max);
1596
1597 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1598 return 0;
1599 }
1600 return max;
1601}
1602
1603static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1604 jobject thiz, jbyteArray jsessionId) {
1605 sp<IDrm> drm = GetDrm(env, thiz);
1606
1607 if (!CheckSession(env, drm, jsessionId)) {
1608 return gSecurityLevels.kSecurityLevelUnknown;
1609 }
1610
1611 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1612
1613 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1614
1615 status_t err = drm->getSecurityLevel(sessionId, &level);
1616
1617 if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
1618 return gSecurityLevels.kSecurityLevelUnknown;
1619 }
1620
1621 switch(level) {
1622 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1623 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1624 case DrmPlugin::kSecurityLevelSwSecureDecode:
1625 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1626 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1627 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1628 case DrmPlugin::kSecurityLevelHwSecureDecode:
1629 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1630 case DrmPlugin::kSecurityLevelHwSecureAll:
1631 return gSecurityLevels.kSecurityLevelHwSecureAll;
1632 default:
1633 return gSecurityLevels.kSecurityLevelUnknown;
1634 }
1635}
1636
Jeff Tinker55d26242018-10-10 16:10:43 -07001637static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
1638 JNIEnv *env, jobject thiz) {
1639 sp<IDrm> drm = GetDrm(env, thiz);
1640
1641 if (!CheckDrm(env, drm)) {
1642 return NULL;
1643 }
1644
1645 List<Vector<uint8_t> > keySetIds;
1646
1647 status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
1648
1649 if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
1650 return NULL;
1651 }
1652
1653 return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
1654}
1655
1656static void android_media_MediaDrm_removeOfflineLicense(
1657 JNIEnv *env, jobject thiz, jbyteArray keySetId) {
1658 sp<IDrm> drm = GetDrm(env, thiz);
1659
1660 if (!CheckDrm(env, drm)) {
1661 return;
1662 }
1663
1664 status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
1665
1666 throwExceptionAsNecessary(env, err, "Failed to remove offline license");
1667}
1668
1669static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
1670 jobject thiz, jbyteArray jkeySetId) {
1671 sp<IDrm> drm = GetDrm(env, thiz);
1672
1673 if (!CheckDrm(env, drm)) {
1674 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1675 }
1676
1677 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
1678
1679 DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
1680
1681 status_t err = drm->getOfflineLicenseState(keySetId, &state);
1682
1683 if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
1684 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1685 }
1686
1687 switch(state) {
1688 case DrmPlugin::kOfflineLicenseStateUsable:
1689 return gOfflineLicenseStates.kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -08001690 case DrmPlugin::kOfflineLicenseStateReleased:
1691 return gOfflineLicenseStates.kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -07001692 default:
1693 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1694 }
1695}
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001696
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001697static jstring android_media_MediaDrm_getPropertyString(
1698 JNIEnv *env, jobject thiz, jstring jname) {
1699 sp<IDrm> drm = GetDrm(env, thiz);
1700
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001701 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001702 return NULL;
1703 }
1704
1705 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001706 jniThrowException(env, "java/lang/IllegalArgumentException",
1707 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001708 return NULL;
1709 }
1710
1711 String8 name = JStringToString8(env, jname);
1712 String8 value;
1713
1714 status_t err = drm->getPropertyString(name, value);
1715
1716 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1717 return NULL;
1718 }
1719
1720 return env->NewStringUTF(value.string());
1721}
1722
1723static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1724 JNIEnv *env, jobject thiz, jstring jname) {
1725 sp<IDrm> drm = GetDrm(env, thiz);
1726
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001727 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001728 return NULL;
1729 }
1730
1731 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001732 jniThrowException(env, "java/lang/IllegalArgumentException",
1733 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001734 return NULL;
1735 }
1736
1737 String8 name = JStringToString8(env, jname);
1738 Vector<uint8_t> value;
1739
1740 status_t err = drm->getPropertyByteArray(name, value);
1741
1742 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1743 return NULL;
1744 }
1745
1746 return VectorToJByteArray(env, value);
1747}
1748
1749static void android_media_MediaDrm_setPropertyString(
1750 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1751 sp<IDrm> drm = GetDrm(env, thiz);
1752
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001753 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001754 return;
1755 }
1756
Jeff Tinkereada5372013-05-21 12:48:14 -07001757 if (jname == NULL) {
1758 jniThrowException(env, "java/lang/IllegalArgumentException",
1759 "property name String is null");
1760 return;
1761 }
1762
1763 if (jvalue == NULL) {
1764 jniThrowException(env, "java/lang/IllegalArgumentException",
1765 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001766 return;
1767 }
1768
1769 String8 name = JStringToString8(env, jname);
1770 String8 value = JStringToString8(env, jvalue);
1771
1772 status_t err = drm->setPropertyString(name, value);
1773
1774 throwExceptionAsNecessary(env, err, "Failed to set property");
1775}
1776
1777static void android_media_MediaDrm_setPropertyByteArray(
1778 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1779 sp<IDrm> drm = GetDrm(env, thiz);
1780
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001781 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001782 return;
1783 }
1784
Jeff Tinkereada5372013-05-21 12:48:14 -07001785 if (jname == NULL) {
1786 jniThrowException(env, "java/lang/IllegalArgumentException",
1787 "property name String is null");
1788 return;
1789 }
1790
1791 if (jvalue == NULL) {
1792 jniThrowException(env, "java/lang/IllegalArgumentException",
1793 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001794 return;
1795 }
1796
1797 String8 name = JStringToString8(env, jname);
1798 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1799
1800 status_t err = drm->setPropertyByteArray(name, value);
1801
1802 throwExceptionAsNecessary(env, err, "Failed to set property");
1803}
1804
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001805static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001806 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001807 jstring jalgorithm) {
1808
1809 sp<IDrm> drm = GetDrm(env, jdrm);
1810
1811 if (!CheckSession(env, drm, jsessionId)) {
1812 return;
1813 }
1814
1815 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001816 jniThrowException(env, "java/lang/IllegalArgumentException",
1817 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001818 return;
1819 }
1820
1821 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1822 String8 algorithm = JStringToString8(env, jalgorithm);
1823
1824 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1825
1826 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
1827}
1828
1829static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001830 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001831 jstring jalgorithm) {
1832
1833 sp<IDrm> drm = GetDrm(env, jdrm);
1834
1835 if (!CheckSession(env, drm, jsessionId)) {
1836 return;
1837 }
1838
1839 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001840 jniThrowException(env, "java/lang/IllegalArgumentException",
1841 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001842 return;
1843 }
1844
1845 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1846 String8 algorithm = JStringToString8(env, jalgorithm);
1847
1848 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1849
1850 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1851}
1852
1853
1854static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001855 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001856 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1857
1858 sp<IDrm> drm = GetDrm(env, jdrm);
1859
1860 if (!CheckSession(env, drm, jsessionId)) {
1861 return NULL;
1862 }
1863
1864 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001865 jniThrowException(env, "java/lang/IllegalArgumentException",
1866 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001867 return NULL;
1868 }
1869
1870 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1871 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1872 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1873 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1874 Vector<uint8_t> output;
1875
1876 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1877
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001878 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
1879 return NULL;
1880 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001881
1882 return VectorToJByteArray(env, output);
1883}
1884
1885static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001886 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001887 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1888
1889 sp<IDrm> drm = GetDrm(env, jdrm);
1890
1891 if (!CheckSession(env, drm, jsessionId)) {
1892 return NULL;
1893 }
1894
1895 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001896 jniThrowException(env, "java/lang/IllegalArgumentException",
1897 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001898 return NULL;
1899 }
1900
1901 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1902 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1903 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1904 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1905 Vector<uint8_t> output;
1906
1907 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001908 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
1909 return NULL;
1910 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001911
1912 return VectorToJByteArray(env, output);
1913}
1914
1915static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001916 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001917 jbyteArray jkeyId, jbyteArray jmessage) {
1918
1919 sp<IDrm> drm = GetDrm(env, jdrm);
1920
1921 if (!CheckSession(env, drm, jsessionId)) {
1922 return NULL;
1923 }
1924
1925 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001926 jniThrowException(env, "java/lang/IllegalArgumentException",
1927 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001928 return NULL;
1929 }
1930
1931 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1932 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1933 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1934 Vector<uint8_t> signature;
1935
1936 status_t err = drm->sign(sessionId, keyId, message, signature);
1937
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001938 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1939 return NULL;
1940 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001941
1942 return VectorToJByteArray(env, signature);
1943}
1944
1945static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001946 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001947 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1948
1949 sp<IDrm> drm = GetDrm(env, jdrm);
1950
1951 if (!CheckSession(env, drm, jsessionId)) {
1952 return false;
1953 }
1954
1955 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001956 jniThrowException(env, "java/lang/IllegalArgumentException",
1957 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001958 return false;
1959 }
1960
1961 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1962 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1963 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1964 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1965 bool match;
1966
1967 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1968
1969 throwExceptionAsNecessary(env, err, "Failed to verify");
1970 return match;
1971}
1972
Adam Stonec06e10e2017-12-19 12:54:33 -08001973static jobject
1974android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1975{
1976 sp<IDrm> drm = GetDrm(env, thiz);
Jeff Tinker55d26242018-10-10 16:10:43 -07001977
1978 if (!CheckDrm(env, drm)) {
Adam Stonec06e10e2017-12-19 12:54:33 -08001979 return NULL;
1980 }
1981
1982 // Retrieve current metrics snapshot from drm.
Adam Stone94395c92018-01-30 12:07:00 -08001983 PersistableBundle metrics;
Robert Shihba6777e2019-11-12 13:04:59 -08001984 sp<IDrmMetricsConsumer> consumer(new DrmMetricsConsumer(&metrics));
1985 status_t err = drm->getMetrics(consumer);
Adam Stonec06e10e2017-12-19 12:54:33 -08001986 if (err != OK) {
1987 ALOGE("getMetrics failed: %d", (int)err);
1988 return (jobject) NULL;
1989 }
1990
Robert Shih4354a962019-11-10 12:09:08 -08001991 return MediaMetricsJNI::nativeToJavaPersistableBundle(env, &metrics);
Adam Stonec06e10e2017-12-19 12:54:33 -08001992}
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001993
Jeff Tinkere4095a82014-03-04 13:17:11 -08001994static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001995 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001996 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1997
1998 sp<IDrm> drm = GetDrm(env, jdrm);
1999
2000 if (!CheckSession(env, drm, jsessionId)) {
2001 return NULL;
2002 }
2003
2004 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
2005 jniThrowException(env, "java/lang/IllegalArgumentException",
2006 "required argument is null");
2007 return NULL;
2008 }
2009
2010 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
2011 String8 algorithm = JStringToString8(env, jalgorithm);
2012 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
2013 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
2014 Vector<uint8_t> signature;
2015
2016 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
2017
2018 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
2019 return NULL;
2020 }
2021
2022 return VectorToJByteArray(env, signature);
2023}
2024
Robert Shih205f7a92021-01-19 21:12:10 -08002025static jboolean android_media_MediaDrm_requiresSecureDecoder(
2026 JNIEnv *env, jobject thiz, jstring jmimeType,
2027 jint jSecurityLevel) {
2028 sp<IDrm> drm = GetDrm(env, thiz);
2029 if (!CheckDrm(env, drm)) {
2030 return JNI_FALSE;
2031 }
2032
2033 String8 mimeType;
2034 if (jmimeType != NULL) {
2035 mimeType = JStringToString8(env, jmimeType);
2036 }
2037
2038 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
2039 if (securityLevel == DrmPlugin::kSecurityLevelUnknown) {
2040 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
2041 return JNI_FALSE;
2042 }
2043
2044 if (securityLevel == DrmPlugin::kSecurityLevelMax) {
2045 return drm->requiresSecureDecoder(mimeType.c_str());
2046 }
2047 return drm->requiresSecureDecoder(mimeType.c_str(), securityLevel);
2048}
Jeff Tinkere4095a82014-03-04 13:17:11 -08002049
Robert Shih02937122021-01-20 00:05:20 -08002050static void android_media_MediaDrm_setPlaybackId(
2051 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
2052 jstring jplaybackId) {
2053 sp<IDrm> drm = GetDrm(env, thiz);
2054 if (!CheckSession(env, drm, jsessionId)) {
2055 return;
2056 }
2057
2058 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
2059
2060 String8 playbackId;
2061 if (jplaybackId != NULL) {
2062 playbackId = JStringToString8(env, jplaybackId);
2063 }
2064 status_t err = drm->setPlaybackId(sessionId, playbackId.c_str());
2065 throwExceptionAsNecessary(env, err, "Failed to set playbackId");
2066}
2067
Robert Shih696989f2021-02-12 23:25:16 -08002068static jobject android_media_MediaDrm_getLogMessages(
2069 JNIEnv *env, jobject thiz) {
2070 sp<IDrm> drm = GetDrm(env, thiz);
2071 if (!CheckDrm(env, drm)) {
2072 return NULL;
2073 }
2074
2075 Vector<drm::V1_4::LogMessage> logs;
2076 status_t err = drm->getLogMessages(logs);
2077 ALOGI("drm->getLogMessages %zu logs", logs.size());
2078 if (throwExceptionAsNecessary(env, err, "Failed to get log messages")) {
2079 return NULL;
2080 }
2081 return hidlLogMessagesToJavaList(env, logs);
2082}
2083
Daniel Micay76f6a862015-09-19 17:31:01 -04002084static const JNINativeMethod gMethods[] = {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002085 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
2086
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002087 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
2088
Edwin Wong4d1d84e2017-01-04 09:37:49 -08002089 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002090 (void *)android_media_MediaDrm_native_setup },
2091
Robert Shihd2e8b432019-11-21 20:27:56 -08002092 { "getSupportedCryptoSchemesNative", "()[B",
2093 (void *)android_media_MediaDrm_getSupportedCryptoSchemesNative },
2094
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08002095 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002096 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
2097
Robert Shih02937122021-01-20 00:05:20 -08002098 { "openSessionNative", "(I)[B",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002099 (void *)android_media_MediaDrm_openSession },
2100
Robert Shih02937122021-01-20 00:05:20 -08002101 { "closeSessionNative", "([B)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002102 (void *)android_media_MediaDrm_closeSession },
2103
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002104 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
2105 "Landroid/media/MediaDrm$KeyRequest;",
2106 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002107
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002108 { "provideKeyResponse", "([B[B)[B",
2109 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002110
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002111 { "removeKeys", "([B)V",
2112 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002113
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002114 { "restoreKeys", "([B[B)V",
2115 (void *)android_media_MediaDrm_restoreKeys },
2116
2117 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
2118 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002119
Jeff Tinkere4095a82014-03-04 13:17:11 -08002120 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
2121 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002122
Jeff Tinkere4095a82014-03-04 13:17:11 -08002123 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
2124 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002125
2126 { "getSecureStops", "()Ljava/util/List;",
2127 (void *)android_media_MediaDrm_getSecureStops },
2128
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002129 { "getSecureStopIds", "()Ljava/util/List;",
2130 (void *)android_media_MediaDrm_getSecureStopIds },
2131
Jeff Tinker1b51c722014-10-31 00:54:26 -07002132 { "getSecureStop", "([B)[B",
2133 (void *)android_media_MediaDrm_getSecureStop },
2134
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002135 { "releaseSecureStops", "([B)V",
2136 (void *)android_media_MediaDrm_releaseSecureStops },
2137
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002138 { "removeSecureStop", "([B)V",
2139 (void *)android_media_MediaDrm_removeSecureStop },
2140
2141 { "removeAllSecureStops", "()V",
2142 (void *)android_media_MediaDrm_removeAllSecureStops },
Jeff Tinker1b51c722014-10-31 00:54:26 -07002143
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002144 { "getConnectedHdcpLevel", "()I",
2145 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
2146
2147 { "getMaxHdcpLevel", "()I",
2148 (void *)android_media_MediaDrm_getMaxHdcpLevel },
2149
2150 { "getOpenSessionCount", "()I",
2151 (void *)android_media_MediaDrm_getOpenSessionCount },
2152
2153 { "getMaxSessionCount", "()I",
2154 (void *)android_media_MediaDrm_getMaxSessionCount },
2155
2156 { "getSecurityLevel", "([B)I",
2157 (void *)android_media_MediaDrm_getSecurityLevel },
2158
Jeff Tinker55d26242018-10-10 16:10:43 -07002159 { "removeOfflineLicense", "([B)V",
2160 (void *)android_media_MediaDrm_removeOfflineLicense },
2161
2162 { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
2163 (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
2164
2165 { "getOfflineLicenseState", "([B)I",
2166 (void *)android_media_MediaDrm_getOfflineLicenseState },
2167
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002168 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
2169 (void *)android_media_MediaDrm_getPropertyString },
2170
2171 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
2172 (void *)android_media_MediaDrm_getPropertyByteArray },
2173
2174 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
2175 (void *)android_media_MediaDrm_setPropertyString },
2176
2177 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
2178 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002179
2180 { "setCipherAlgorithmNative",
2181 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2182 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
2183
2184 { "setMacAlgorithmNative",
2185 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2186 (void *)android_media_MediaDrm_setMacAlgorithmNative },
2187
2188 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2189 (void *)android_media_MediaDrm_encryptNative },
2190
2191 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2192 (void *)android_media_MediaDrm_decryptNative },
2193
2194 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
2195 (void *)android_media_MediaDrm_signNative },
2196
2197 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
2198 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08002199
2200 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
2201 (void *)android_media_MediaDrm_signRSANative },
Adam Stonec06e10e2017-12-19 12:54:33 -08002202
2203 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
2204 (void *)android_media_MediaDrm_native_getMetrics },
Robert Shih205f7a92021-01-19 21:12:10 -08002205
2206 { "requiresSecureDecoder", "(Ljava/lang/String;I)Z",
2207 (void *)android_media_MediaDrm_requiresSecureDecoder },
Robert Shih02937122021-01-20 00:05:20 -08002208
2209 { "setPlaybackId", "([BLjava/lang/String;)V",
2210 (void *)android_media_MediaDrm_setPlaybackId },
Robert Shih696989f2021-02-12 23:25:16 -08002211
2212 { "getLogMessages", "()Ljava/util/List;",
2213 (void *)android_media_MediaDrm_getLogMessages },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002214};
2215
2216int register_android_media_Drm(JNIEnv *env) {
2217 return AndroidRuntime::registerNativeMethods(env,
2218 "android/media/MediaDrm", gMethods, NELEM(gMethods));
2219}