blob: 22c3572e963b07b8d1725f513d54ea136a67b2a3 [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
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700346static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
347 ALOGE("Illegal state exception: %s (%d)", msg, err);
348
349 jobject exception = env->NewObject(gFields.stateException.classId,
350 gFields.stateException.init, static_cast<int>(err),
351 env->NewStringUTF(msg));
352 env->Throw(static_cast<jthrowable>(exception));
353}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700354
Jeff Tinker20594d82018-12-12 08:31:22 -0800355static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
356 ALOGE("Session exception: %s (%d)", msg, err);
357
358 jint jErrorCode = 0;
359 switch(err) {
360 case ERROR_DRM_RESOURCE_CONTENTION:
361 jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
362 break;
363 default:
364 break;
365 }
366
367 jobject exception = env->NewObject(gFields.sessionException.classId,
368 gFields.sessionException.init, static_cast<int>(err),
369 env->NewStringUTF(msg));
370
371 env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
372 env->Throw(static_cast<jthrowable>(exception));
373}
374
375static bool isSessionException(status_t err) {
376 return err == ERROR_DRM_RESOURCE_CONTENTION;
377}
378
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800379static bool throwExceptionAsNecessary(
380 JNIEnv *env, status_t err, const char *msg = NULL) {
381
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700382 const char *drmMessage = NULL;
383
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700384 switch (err) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700385 case ERROR_DRM_UNKNOWN:
386 drmMessage = "General DRM error";
387 break;
388 case ERROR_DRM_NO_LICENSE:
389 drmMessage = "No license";
390 break;
391 case ERROR_DRM_LICENSE_EXPIRED:
392 drmMessage = "License expired";
393 break;
394 case ERROR_DRM_SESSION_NOT_OPENED:
395 drmMessage = "Session not opened";
396 break;
397 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
398 drmMessage = "Not initialized";
399 break;
400 case ERROR_DRM_DECRYPT:
401 drmMessage = "Decrypt error";
402 break;
403 case ERROR_DRM_CANNOT_HANDLE:
Jeff Tinkereb13c762017-11-01 15:29:38 -0700404 drmMessage = "Invalid parameter or data format";
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700405 break;
Jeff Tinker20594d82018-12-12 08:31:22 -0800406 case ERROR_DRM_INVALID_STATE:
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700407 drmMessage = "Invalid state";
408 break;
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700409 default:
410 break;
411 }
412
413 String8 vendorMessage;
414 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
Jeff Tinker29799862014-08-27 11:05:13 -0700415 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700416 drmMessage = vendorMessage.string();
417 }
418
Jeff Tinkereb13c762017-11-01 15:29:38 -0700419 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800420 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
421 return true;
Jeff Tinker5de2e902019-01-25 23:09:36 -0800422 } else if (err == ERROR_UNSUPPORTED) {
423 jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
424 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700425 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
426 jniThrowException(env, "android/media/NotProvisionedException", msg);
427 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700428 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
429 jniThrowException(env, "android/media/ResourceBusyException", msg);
430 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700431 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
432 jniThrowException(env, "android/media/DeniedByServerException", msg);
433 return true;
Jeff Tinker314b7f32015-06-15 17:45:43 -0700434 } else if (err == DEAD_OBJECT) {
435 jniThrowException(env, "android/media/MediaDrmResetException",
436 "mediaserver died");
437 return true;
Jeff Tinker20594d82018-12-12 08:31:22 -0800438 } else if (isSessionException(err)) {
439 throwSessionException(env, msg, err);
440 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800441 } else if (err != OK) {
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700442 String8 errbuf;
443 if (drmMessage != NULL) {
444 if (msg == NULL) {
445 msg = drmMessage;
446 } else {
Jeff Tinker29799862014-08-27 11:05:13 -0700447 errbuf = String8::format("%s: %s", msg, drmMessage);
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700448 msg = errbuf.string();
449 }
450 }
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700451 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800452 return true;
453 }
454 return false;
455}
456
457static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000458 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800459 return jdrm ? jdrm->getDrm() : NULL;
460}
461
462JDrm::JDrm(
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800463 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
464 const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800465 mObject = env->NewWeakGlobalRef(thiz);
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800466 mDrm = MakeDrm(uuid, appPackageName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700467 if (mDrm != NULL) {
468 mDrm->setListener(this);
469 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800470}
471
472JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800473 JNIEnv *env = AndroidRuntime::getJNIEnv();
474
475 env->DeleteWeakGlobalRef(mObject);
476 mObject = NULL;
477}
478
479// static
480sp<IDrm> JDrm::MakeDrm() {
Robert Shih218b9532019-08-15 14:48:11 -0700481 return DrmUtils::MakeDrm();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800482}
483
484// static
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800485sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800486 sp<IDrm> drm = MakeDrm();
487
488 if (drm == NULL) {
489 return NULL;
490 }
491
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800492 status_t err = drm->createPlugin(uuid, appPackageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800493
494 if (err != OK) {
495 return NULL;
496 }
497
498 return drm;
499}
500
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700501status_t JDrm::setListener(const sp<DrmListener>& listener) {
502 Mutex::Autolock lock(mLock);
503 mListener = listener;
504 return OK;
505}
506
Robert Shih9d4e2d42019-11-08 13:51:49 -0800507void JDrm::notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *args) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700508 sp<DrmListener> listener;
509 mLock.lock();
510 listener = mListener;
511 mLock.unlock();
512
513 if (listener != NULL) {
514 Mutex::Autolock lock(mNotifyLock);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800515 listener->notify(eventType, extra, args);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700516 }
517}
518
Robert Shih3a523902019-08-15 14:48:11 -0700519void JDrm::sendEvent(
520 DrmPlugin::EventType eventType,
521 const hardware::hidl_vec<uint8_t> &sessionId,
522 const hardware::hidl_vec<uint8_t> &data) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800523 ListenerArgs args{
524 .jSessionId = hidlVectorToJByteArray(sessionId),
525 .jData = hidlVectorToJByteArray(data),
526 };
527 notify(eventType, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700528}
529
530void JDrm::sendExpirationUpdate(
531 const hardware::hidl_vec<uint8_t> &sessionId,
532 int64_t expiryTimeInMS) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800533 ListenerArgs args{
534 .jSessionId = hidlVectorToJByteArray(sessionId),
535 .jExpirationTime = expiryTimeInMS,
536 };
537 notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700538}
539
540void JDrm::sendKeysChange(
541 const hardware::hidl_vec<uint8_t> &sessionId,
542 const std::vector<DrmKeyStatus> &keyStatusList,
543 bool hasNewUsableKey) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800544 JNIEnv *env = AndroidRuntime::getJNIEnv();
545 jclass clazz = gFields.arraylistClassId;
546 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
547 clazz = gFields.keyStatus.classId;
548 for (const auto &keyStatus : keyStatusList) {
549 jbyteArray jKeyId(hidlVectorToJByteArray(keyStatus.keyId));
550 jint jStatusCode(keyStatus.type);
551 jobject jKeyStatus = env->NewObject(clazz, gFields.keyStatus.init, jKeyId, jStatusCode);
552 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jKeyStatus);
553 }
554 ListenerArgs args{
555 .jSessionId = hidlVectorToJByteArray(sessionId),
556 .jKeyStatusList = arrayList,
557 .jHasNewUsableKey = hasNewUsableKey,
558 };
559 notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700560}
561
562void JDrm::sendSessionLostState(
563 const hardware::hidl_vec<uint8_t> &sessionId) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800564 ListenerArgs args{
565 .jSessionId = hidlVectorToJByteArray(sessionId),
566 };
567 notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700568}
569
Jeff Tinker600071c2014-04-11 16:11:15 -0700570void JDrm::disconnect() {
571 if (mDrm != NULL) {
572 mDrm->destroyPlugin();
573 mDrm.clear();
574 }
575}
576
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700577
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800578// static
Jeff Tinker5de2e902019-01-25 23:09:36 -0800579status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
580 DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800581 sp<IDrm> drm = MakeDrm();
582
583 if (drm == NULL) {
Jeff Tinker5de2e902019-01-25 23:09:36 -0800584 return BAD_VALUE;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800585 }
586
Jeff Tinker5de2e902019-01-25 23:09:36 -0800587 return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800588}
589
590status_t JDrm::initCheck() const {
591 return mDrm == NULL ? NO_INIT : OK;
592}
593
594// JNI conversion utilities
595static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
596 Vector<uint8_t> vector;
597 size_t length = env->GetArrayLength(byteArray);
598 vector.insertAt((size_t)0, length);
599 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
600 return vector;
601}
602
603static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
604 size_t length = vector.size();
605 jbyteArray result = env->NewByteArray(length);
606 if (result != NULL) {
607 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
608 }
609 return result;
610}
611
612static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800613 String8 result;
614
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700615 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800616 if (s) {
617 result = s;
618 env->ReleaseStringUTFChars(jstr, s);
619 }
620 return result;
621}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700622
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800623/*
624 import java.util.HashMap;
625 import java.util.Set;
626 import java.Map.Entry;
627 import jav.util.Iterator;
628
629 HashMap<k, v> hm;
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800630 Set<Entry<k, v>> s = hm.entrySet();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800631 Iterator i = s.iterator();
632 Entry e = s.next();
633*/
634
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200635static KeyedVector<String8, String8> HashMapToKeyedVector(
636 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800637 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800638 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200639 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800640
641 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
642 if (entrySet) {
643 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
644 if (iterator) {
645 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
646 while (hasNext) {
647 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
648 if (entry) {
649 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200650 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700651 jniThrowException(env, "java/lang/IllegalArgumentException",
652 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200653 env->DeleteLocalRef(entry);
654 *pIsOK = false;
655 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800656 }
657 jstring jkey = static_cast<jstring>(obj);
658
659 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200660 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700661 jniThrowException(env, "java/lang/IllegalArgumentException",
662 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200663 env->DeleteLocalRef(entry);
664 *pIsOK = false;
665 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800666 }
667 jstring jvalue = static_cast<jstring>(obj);
668
669 String8 key = JStringToString8(env, jkey);
670 String8 value = JStringToString8(env, jvalue);
671 keyedVector.add(key, value);
672
673 env->DeleteLocalRef(jkey);
674 env->DeleteLocalRef(jvalue);
675 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
676 }
677 env->DeleteLocalRef(entry);
678 }
679 env->DeleteLocalRef(iterator);
680 }
681 env->DeleteLocalRef(entrySet);
682 }
683 return keyedVector;
684}
685
686static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800687 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800688 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
689 for (size_t i = 0; i < map.size(); ++i) {
690 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
691 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
692 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
693 env->DeleteLocalRef(jkey);
694 env->DeleteLocalRef(jvalue);
695 }
696 return hashMap;
697}
698
699static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800700 List<Vector<uint8_t>> list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800701 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800702 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800703 List<Vector<uint8_t>>::iterator iter = list.begin();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800704 while (iter != list.end()) {
705 jbyteArray byteArray = VectorToJByteArray(env, *iter);
706 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
707 env->DeleteLocalRef(byteArray);
708 iter++;
709 }
710
711 return arrayList;
712}
713
714} // namespace android
715
716using namespace android;
717
718static sp<JDrm> setDrm(
719 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000720 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800721 if (drm != NULL) {
722 drm->incStrong(thiz);
723 }
724 if (old != NULL) {
725 old->decStrong(thiz);
726 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000727 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800728
729 return old;
730}
731
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800732static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800733 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700734 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800735 return false;
736 }
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800737 return true;
738}
739
740static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
741{
742 if (!CheckDrm(env, drm)) {
743 return false;
744 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800745
746 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700747 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800748 return false;
749 }
750 return true;
751}
752
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800753static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700754 sp<JDrm> drm = setDrm(env, thiz, NULL);
755 if (drm != NULL) {
756 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700757 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700758 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800759}
760
761static void android_media_MediaDrm_native_init(JNIEnv *env) {
762 jclass clazz;
763 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000764 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700765 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
Robert Shih9d4e2d42019-11-08 13:51:49 -0800766 "(Ljava/lang/Object;III[B[BJLjava/util/List;Z)V");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700767
768 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700769 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700770 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700771 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700772 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700773 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700774 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700775 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700776 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Ronghua Wua6d72092015-03-04 11:16:02 -0800777 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
778 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800779
Jeff Tinker74797f82015-03-31 15:44:34 -0700780 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
781 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
782 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
783 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700784 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
785 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800786 GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
787 gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
Jeff Tinker74797f82015-03-31 15:44:34 -0700788
Jeff Tinker17b89222013-05-21 12:35:06 -0700789 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
790 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
791 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
792 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
793 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
794 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
795
Jeff Tinkere4095a82014-03-04 13:17:11 -0800796 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
797 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
798 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
799 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
800
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800801 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
802 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
803 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
804 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
805 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
806 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
807 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
808 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
809 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
810 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
811 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
812 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800813 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I");
814 gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field);
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800815 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
816 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
817
818 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
819 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700820 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800821 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700822 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800823 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700824 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800825 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700826 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800827 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700828 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800829 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
830
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800831 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I");
Jeff Tinker55d26242018-10-10 16:10:43 -0700832 gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800833 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I");
834 gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field);
Jeff Tinker55d26242018-10-10 16:10:43 -0700835 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
836 gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
837
838 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
839
Jeff Tinker2bca5252018-02-11 18:59:14 +0000840 jmethodID getMaxSecurityLevel;
841 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
842 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
843
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700844 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700845 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
846 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700847 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800848
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700849 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
850 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
851 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
852 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
853 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
854 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
Rahul Frias8f761ba2018-01-22 23:43:54 -0800855 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
856 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
857 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
858 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700859
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800860 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700861 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
862 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800863
Jeff Tinkere4095a82014-03-04 13:17:11 -0800864 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
865 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
866 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700867 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800868
Adam Stone94395c92018-01-30 12:07:00 -0800869 // Metrics-related fields and classes.
870 FIND_CLASS(clazz, "android/os/PersistableBundle");
871 jfieldID bundleCreatorId;
872 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
873 "Landroid/os/Parcelable$Creator;");
874 jobject bundleCreator;
875 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
876 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
877 FIND_CLASS(clazz, "android/os/Parcelable$Creator");
878 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
879 "(Landroid/os/Parcel;)Ljava/lang/Object;");
880 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
881
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800882 FIND_CLASS(clazz, "java/util/ArrayList");
883 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
884 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
885
886 FIND_CLASS(clazz, "java/util/HashMap");
887 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
888 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
889 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
890 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
891 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
892
893 FIND_CLASS(clazz, "java/util/Set");
894 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
895
896 FIND_CLASS(clazz, "java/util/Iterator");
897 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
898 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
899
900 FIND_CLASS(clazz, "java/util/Map$Entry");
901 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
902 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800903
904 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700905 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800906
907 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700908 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800909
910 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700911 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700912
913 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
914 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
915 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker20594d82018-12-12 08:31:22 -0800916
917 FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
918 GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
919 gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
920 GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
921
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800922 GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I");
923 gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800924 GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
925 gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800926
927 FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
928 gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
929 GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
Robert Shih696989f2021-02-12 23:25:16 -0800930
931 FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage");
932 gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
933 GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800934}
935
936static void android_media_MediaDrm_native_setup(
937 JNIEnv *env, jobject thiz,
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800938 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800939
940 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700941 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800942 return;
943 }
944
945 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
946
947 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700948 jniThrowException(env, "java/lang/IllegalArgumentException",
949 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800950 return;
951 }
952
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800953 String8 packageName;
954 if (jappPackageName == NULL) {
955 jniThrowException(env, "java/lang/IllegalArgumentException",
956 "application package name cannot be null");
957 return;
958 }
959
960 packageName = JStringToString8(env, jappPackageName);
961 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800962
963 status_t err = drm->initCheck();
964
965 if (err != OK) {
966 jniThrowException(
967 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700968 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800969 "Failed to instantiate drm object.");
970 return;
971 }
972
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700973 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
974 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800975 setDrm(env, thiz, drm);
976}
977
Jeff Tinkerd571a7c2019-01-17 17:29:30 -0800978DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
979 DrmPlugin::SecurityLevel level;
980
981 if (jlevel == gSecurityLevels.kSecurityLevelMax) {
982 level = DrmPlugin::kSecurityLevelMax;
983 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
984 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
985 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
986 level = DrmPlugin::kSecurityLevelSwSecureDecode;
987 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
988 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
989 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
990 level = DrmPlugin::kSecurityLevelHwSecureDecode;
991 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
992 level = DrmPlugin::kSecurityLevelHwSecureAll;
993 } else {
994 level = DrmPlugin::kSecurityLevelUnknown;
995 }
996 return level;
997}
998
Robert Shihd2e8b432019-11-21 20:27:56 -0800999static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
1000 std::vector<uint8_t> bv;
1001 for (auto &factory : DrmUtils::MakeDrmFactories()) {
1002 sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
1003 if (factoryV1_3 == nullptr) {
1004 continue;
1005 }
1006 factoryV1_3->getSupportedCryptoSchemes(
1007 [&](const hardware::hidl_vec<hardware::hidl_array<uint8_t, 16>>& schemes) {
1008 for (const auto &scheme : schemes) {
1009 bv.insert(bv.end(), scheme.data(), scheme.data() + scheme.size());
1010 }
1011 });
1012 }
1013
1014 jbyteArray jUuidBytes = env->NewByteArray(bv.size());
1015 env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast<const jbyte *>(bv.data()));
1016 return jUuidBytes;
1017}
1018
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001019static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001020 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType,
1021 jint jSecurityLevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001022
1023 if (uuidObj == NULL) {
1024 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1025 return false;
1026 }
1027
1028 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1029
1030 if (uuid.size() != 16) {
1031 jniThrowException(
1032 env,
1033 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -07001034 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001035 return false;
1036 }
1037
Jeff Tinker7cda4912013-08-21 11:52:34 -07001038 String8 mimeType;
1039 if (jmimeType != NULL) {
1040 mimeType = JStringToString8(env, jmimeType);
1041 }
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001042 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
Jeff Tinker7cda4912013-08-21 11:52:34 -07001043
Jeff Tinker5de2e902019-01-25 23:09:36 -08001044 bool isSupported;
1045 status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
1046 securityLevel, &isSupported);
1047
1048 if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
1049 return false;
1050 }
1051 return isSupported;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001052}
1053
1054static jbyteArray android_media_MediaDrm_openSession(
Jeff Tinker2bca5252018-02-11 18:59:14 +00001055 JNIEnv *env, jobject thiz, jint jlevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001056 sp<IDrm> drm = GetDrm(env, thiz);
1057
Jeff Tinker55d26242018-10-10 16:10:43 -07001058 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001059 return NULL;
1060 }
1061
1062 Vector<uint8_t> sessionId;
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001063 DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel);
1064 if (level == DrmPlugin::kSecurityLevelUnknown) {
Jeff Tinker2bca5252018-02-11 18:59:14 +00001065 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1066 return NULL;
1067 }
1068
1069 status_t err = drm->openSession(level, sessionId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001070
1071 if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
1072 return NULL;
1073 }
1074
1075 return VectorToJByteArray(env, sessionId);
1076}
1077
1078static void android_media_MediaDrm_closeSession(
1079 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1080 sp<IDrm> drm = GetDrm(env, thiz);
1081
1082 if (!CheckSession(env, drm, jsessionId)) {
1083 return;
1084 }
1085
1086 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1087
1088 status_t err = drm->closeSession(sessionId);
1089
1090 throwExceptionAsNecessary(env, err, "Failed to close session");
1091}
1092
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001093static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001094 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001095 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001096 sp<IDrm> drm = GetDrm(env, thiz);
1097
1098 if (!CheckSession(env, drm, jsessionId)) {
1099 return NULL;
1100 }
1101
1102 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1103
1104 Vector<uint8_t> initData;
1105 if (jinitData != NULL) {
1106 initData = JByteArrayToVector(env, jinitData);
1107 }
1108
1109 String8 mimeType;
1110 if (jmimeType != NULL) {
1111 mimeType = JStringToString8(env, jmimeType);
1112 }
1113
Jeff Tinker17b89222013-05-21 12:35:06 -07001114 DrmPlugin::KeyType keyType;
1115 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
1116 keyType = DrmPlugin::kKeyType_Streaming;
1117 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
1118 keyType = DrmPlugin::kKeyType_Offline;
1119 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
1120 keyType = DrmPlugin::kKeyType_Release;
1121 } else {
1122 jniThrowException(env, "java/lang/IllegalArgumentException",
1123 "invalid keyType");
1124 return NULL;
1125 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001126
1127 KeyedVector<String8, String8> optParams;
1128 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +02001129 bool isOK;
1130 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
1131 if (!isOK) {
1132 return NULL;
1133 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001134 }
1135
1136 Vector<uint8_t> request;
1137 String8 defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001138 DrmPlugin::KeyRequestType keyRequestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001139
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001140 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001141 keyType, optParams, request, defaultUrl, &keyRequestType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001142
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001143 if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001144 return NULL;
1145 }
1146
1147 // Fill out return obj
1148 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001149 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001150
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001151 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001152
1153 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001154 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001155 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001156 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001157
1158 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001159 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001160
1161 switch (keyRequestType) {
1162 case DrmPlugin::kKeyRequestType_Initial:
1163 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1164 gKeyRequestTypes.kKeyRequestTypeInitial);
1165 break;
1166 case DrmPlugin::kKeyRequestType_Renewal:
1167 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1168 gKeyRequestTypes.kKeyRequestTypeRenewal);
1169 break;
1170 case DrmPlugin::kKeyRequestType_Release:
1171 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1172 gKeyRequestTypes.kKeyRequestTypeRelease);
1173 break;
Rahul Frias8f761ba2018-01-22 23:43:54 -08001174 case DrmPlugin::kKeyRequestType_None:
1175 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1176 gKeyRequestTypes.kKeyRequestTypeNone);
1177 break;
1178 case DrmPlugin::kKeyRequestType_Update:
1179 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1180 gKeyRequestTypes.kKeyRequestTypeUpdate);
1181 break;
1182
Jeff Tinker74797f82015-03-31 15:44:34 -07001183 default:
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001184 throwStateException(env, "DRM plugin failure: unknown key request type",
1185 ERROR_DRM_UNKNOWN);
1186 break;
1187 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001188 }
1189
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001190 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001191}
1192
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001193static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001194 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
1195 sp<IDrm> drm = GetDrm(env, thiz);
1196
1197 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001198 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001199 }
1200
1201 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1202
1203 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001204 jniThrowException(env, "java/lang/IllegalArgumentException",
1205 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001206 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001207 }
1208 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001209 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001210
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001211 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001212
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001213 if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
1214 return NULL;
1215 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001216 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001217}
1218
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001219static void android_media_MediaDrm_removeKeys(
1220 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
1221 sp<IDrm> drm = GetDrm(env, thiz);
1222
Jeff Tinker55d26242018-10-10 16:10:43 -07001223 if (!CheckDrm(env, drm)) {
1224 return;
1225 }
1226
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001227 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001228 jniThrowException(env, "java/lang/IllegalArgumentException",
1229 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001230 return;
1231 }
1232
1233 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1234
1235 status_t err = drm->removeKeys(keySetId);
1236
1237 throwExceptionAsNecessary(env, err, "Failed to remove keys");
1238}
1239
1240static void android_media_MediaDrm_restoreKeys(
1241 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
1242 jbyteArray jkeysetId) {
1243
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001244 sp<IDrm> drm = GetDrm(env, thiz);
1245
1246 if (!CheckSession(env, drm, jsessionId)) {
1247 return;
1248 }
1249
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001250 if (jkeysetId == NULL) {
1251 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1252 return;
1253 }
1254
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001255 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001256 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001257
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001258 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001259
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001260 throwExceptionAsNecessary(env, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001261}
1262
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001263static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001264 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1265 sp<IDrm> drm = GetDrm(env, thiz);
1266
1267 if (!CheckSession(env, drm, jsessionId)) {
1268 return NULL;
1269 }
1270 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1271
1272 KeyedVector<String8, String8> infoMap;
1273
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001274 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001275
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001276 if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001277 return NULL;
1278 }
1279
1280 return KeyedVectorToHashMap(env, infoMap);
1281}
1282
Jeff Tinkere4095a82014-03-04 13:17:11 -08001283static jobject android_media_MediaDrm_getProvisionRequestNative(
1284 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001285 sp<IDrm> drm = GetDrm(env, thiz);
1286
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001287 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001288 return NULL;
1289 }
1290
1291 Vector<uint8_t> request;
1292 String8 defaultUrl;
1293
Jeff Tinkere4095a82014-03-04 13:17:11 -08001294 String8 certType;
1295 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1296 certType = "X.509";
1297 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1298 certType = "none";
1299 } else {
1300 certType = "invalid";
1301 }
1302
1303 String8 certAuthority = JStringToString8(env, jcertAuthority);
1304 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001305
1306 if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
1307 return NULL;
1308 }
1309
1310 // Fill out return obj
1311 jclass clazz;
1312 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1313
1314 jobject provisionObj = NULL;
1315
1316 if (clazz) {
1317 provisionObj = env->AllocObject(clazz);
1318 jbyteArray jrequest = VectorToJByteArray(env, request);
1319 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1320
1321 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1322 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1323 }
1324
1325 return provisionObj;
1326}
1327
Jeff Tinkere4095a82014-03-04 13:17:11 -08001328static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001329 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1330 sp<IDrm> drm = GetDrm(env, thiz);
1331
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001332 if (!CheckDrm(env, drm)) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001333 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001334 }
1335
1336 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001337 jniThrowException(env, "java/lang/IllegalArgumentException",
1338 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001339 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001340 }
1341
1342 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -08001343 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001344
Jeff Tinkere4095a82014-03-04 13:17:11 -08001345 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1346
1347 // Fill out return obj
1348 jclass clazz = gFields.certificateClassId;
1349
1350 jobject certificateObj = NULL;
1351
1352 if (clazz && certificate.size() && wrappedKey.size()) {
1353 certificateObj = env->AllocObject(clazz);
1354 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1355 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1356
1357 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1358 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1359 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001360
1361 throwExceptionAsNecessary(env, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001362 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001363}
1364
1365static jobject android_media_MediaDrm_getSecureStops(
1366 JNIEnv *env, jobject thiz) {
1367 sp<IDrm> drm = GetDrm(env, thiz);
1368
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001369 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001370 return NULL;
1371 }
1372
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001373 List<Vector<uint8_t>> secureStops;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001374
1375 status_t err = drm->getSecureStops(secureStops);
1376
1377 if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
1378 return NULL;
1379 }
1380
1381 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1382}
1383
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001384static jobject android_media_MediaDrm_getSecureStopIds(
1385 JNIEnv *env, jobject thiz) {
1386 sp<IDrm> drm = GetDrm(env, thiz);
1387
Jeff Tinker55d26242018-10-10 16:10:43 -07001388 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001389 return NULL;
1390 }
1391
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001392 List<Vector<uint8_t>> secureStopIds;
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001393
1394 status_t err = drm->getSecureStopIds(secureStopIds);
1395
1396 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
1397 return NULL;
1398 }
1399
1400 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1401}
1402
Jeff Tinker1b51c722014-10-31 00:54:26 -07001403static jbyteArray android_media_MediaDrm_getSecureStop(
1404 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1405 sp<IDrm> drm = GetDrm(env, thiz);
1406
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001407 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001408 return NULL;
1409 }
1410
1411 Vector<uint8_t> secureStop;
1412
1413 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1414
1415 if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
1416 return NULL;
1417 }
1418
1419 return VectorToJByteArray(env, secureStop);
1420}
1421
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001422static void android_media_MediaDrm_releaseSecureStops(
1423 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1424 sp<IDrm> drm = GetDrm(env, thiz);
1425
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001426 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001427 return;
1428 }
1429
1430 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1431
1432 status_t err = drm->releaseSecureStops(ssRelease);
1433
1434 throwExceptionAsNecessary(env, err, "Failed to release secure stops");
1435}
1436
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001437static void android_media_MediaDrm_removeSecureStop(
1438 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1439 sp<IDrm> drm = GetDrm(env, thiz);
1440
Jeff Tinker55d26242018-10-10 16:10:43 -07001441 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001442 return;
1443 }
1444
1445 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1446
1447 throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
1448}
1449
1450static void android_media_MediaDrm_removeAllSecureStops(
Jeff Tinker1b51c722014-10-31 00:54:26 -07001451 JNIEnv *env, jobject thiz) {
1452 sp<IDrm> drm = GetDrm(env, thiz);
1453
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001454 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001455 return;
1456 }
1457
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001458 status_t err = drm->removeAllSecureStops();
Jeff Tinker1b51c722014-10-31 00:54:26 -07001459
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001460 throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
Jeff Tinker1b51c722014-10-31 00:54:26 -07001461}
1462
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001463
1464static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1465 switch(level) {
1466 case DrmPlugin::kHdcpLevelUnknown:
1467 return gHdcpLevels.kHdcpLevelUnknown;
1468 case DrmPlugin::kHdcpNone:
1469 return gHdcpLevels.kHdcpNone;
1470 case DrmPlugin::kHdcpV1:
1471 return gHdcpLevels.kHdcpV1;
1472 case DrmPlugin::kHdcpV2:
1473 return gHdcpLevels.kHdcpV2;
1474 case DrmPlugin::kHdcpV2_1:
1475 return gHdcpLevels.kHdcpV2_1;
1476 case DrmPlugin::kHdcpV2_2:
1477 return gHdcpLevels.kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -08001478 case DrmPlugin::kHdcpV2_3:
1479 return gHdcpLevels.kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001480 case DrmPlugin::kHdcpNoOutput:
1481 return gHdcpLevels.kHdcpNoOutput;
1482 }
1483 return gHdcpLevels.kHdcpNone;
1484}
1485
1486static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1487 jobject thiz) {
1488 sp<IDrm> drm = GetDrm(env, thiz);
1489
1490 if (!CheckDrm(env, drm)) {
1491 return gHdcpLevels.kHdcpNone;
1492 }
1493
1494 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1495 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1496
1497 status_t err = drm->getHdcpLevels(&connected, &max);
1498
1499 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1500 return gHdcpLevels.kHdcpLevelUnknown;
1501 }
1502 return HdcpLevelTojint(connected);
1503}
1504
1505static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1506 jobject thiz) {
1507 sp<IDrm> drm = GetDrm(env, thiz);
1508
1509 if (!CheckDrm(env, drm)) {
1510 return gHdcpLevels.kHdcpLevelUnknown;
1511 }
1512
1513 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1514 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1515
1516 status_t err = drm->getHdcpLevels(&connected, &max);
1517
1518 if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
1519 return gHdcpLevels.kHdcpLevelUnknown;
1520 }
1521 return HdcpLevelTojint(max);
1522}
1523
1524static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1525 jobject thiz) {
1526 sp<IDrm> drm = GetDrm(env, thiz);
1527
1528 if (!CheckDrm(env, drm)) {
1529 return 0;
1530 }
1531
1532 uint32_t open = 0, max = 0;
1533 status_t err = drm->getNumberOfSessions(&open, &max);
1534
1535 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1536 return 0;
1537 }
1538 return open;
1539}
1540
1541static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1542 jobject thiz) {
1543 sp<IDrm> drm = GetDrm(env, thiz);
1544
1545 if (!CheckDrm(env, drm)) {
1546 return 0;
1547 }
1548
1549 uint32_t open = 0, max = 0;
1550 status_t err = drm->getNumberOfSessions(&open, &max);
1551
1552 if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
1553 return 0;
1554 }
1555 return max;
1556}
1557
1558static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1559 jobject thiz, jbyteArray jsessionId) {
1560 sp<IDrm> drm = GetDrm(env, thiz);
1561
1562 if (!CheckSession(env, drm, jsessionId)) {
1563 return gSecurityLevels.kSecurityLevelUnknown;
1564 }
1565
1566 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1567
1568 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1569
1570 status_t err = drm->getSecurityLevel(sessionId, &level);
1571
1572 if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
1573 return gSecurityLevels.kSecurityLevelUnknown;
1574 }
1575
1576 switch(level) {
1577 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1578 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1579 case DrmPlugin::kSecurityLevelSwSecureDecode:
1580 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1581 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1582 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1583 case DrmPlugin::kSecurityLevelHwSecureDecode:
1584 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1585 case DrmPlugin::kSecurityLevelHwSecureAll:
1586 return gSecurityLevels.kSecurityLevelHwSecureAll;
1587 default:
1588 return gSecurityLevels.kSecurityLevelUnknown;
1589 }
1590}
1591
Jeff Tinker55d26242018-10-10 16:10:43 -07001592static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
1593 JNIEnv *env, jobject thiz) {
1594 sp<IDrm> drm = GetDrm(env, thiz);
1595
1596 if (!CheckDrm(env, drm)) {
1597 return NULL;
1598 }
1599
1600 List<Vector<uint8_t> > keySetIds;
1601
1602 status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
1603
1604 if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
1605 return NULL;
1606 }
1607
1608 return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
1609}
1610
1611static void android_media_MediaDrm_removeOfflineLicense(
1612 JNIEnv *env, jobject thiz, jbyteArray keySetId) {
1613 sp<IDrm> drm = GetDrm(env, thiz);
1614
1615 if (!CheckDrm(env, drm)) {
1616 return;
1617 }
1618
1619 status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
1620
1621 throwExceptionAsNecessary(env, err, "Failed to remove offline license");
1622}
1623
1624static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
1625 jobject thiz, jbyteArray jkeySetId) {
1626 sp<IDrm> drm = GetDrm(env, thiz);
1627
1628 if (!CheckDrm(env, drm)) {
1629 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1630 }
1631
1632 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
1633
1634 DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
1635
1636 status_t err = drm->getOfflineLicenseState(keySetId, &state);
1637
1638 if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
1639 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1640 }
1641
1642 switch(state) {
1643 case DrmPlugin::kOfflineLicenseStateUsable:
1644 return gOfflineLicenseStates.kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -08001645 case DrmPlugin::kOfflineLicenseStateReleased:
1646 return gOfflineLicenseStates.kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -07001647 default:
1648 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1649 }
1650}
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001651
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001652static jstring android_media_MediaDrm_getPropertyString(
1653 JNIEnv *env, jobject thiz, jstring jname) {
1654 sp<IDrm> drm = GetDrm(env, thiz);
1655
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001656 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001657 return NULL;
1658 }
1659
1660 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001661 jniThrowException(env, "java/lang/IllegalArgumentException",
1662 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001663 return NULL;
1664 }
1665
1666 String8 name = JStringToString8(env, jname);
1667 String8 value;
1668
1669 status_t err = drm->getPropertyString(name, value);
1670
1671 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1672 return NULL;
1673 }
1674
1675 return env->NewStringUTF(value.string());
1676}
1677
1678static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1679 JNIEnv *env, jobject thiz, jstring jname) {
1680 sp<IDrm> drm = GetDrm(env, thiz);
1681
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001682 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001683 return NULL;
1684 }
1685
1686 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001687 jniThrowException(env, "java/lang/IllegalArgumentException",
1688 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001689 return NULL;
1690 }
1691
1692 String8 name = JStringToString8(env, jname);
1693 Vector<uint8_t> value;
1694
1695 status_t err = drm->getPropertyByteArray(name, value);
1696
1697 if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
1698 return NULL;
1699 }
1700
1701 return VectorToJByteArray(env, value);
1702}
1703
1704static void android_media_MediaDrm_setPropertyString(
1705 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1706 sp<IDrm> drm = GetDrm(env, thiz);
1707
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001708 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001709 return;
1710 }
1711
Jeff Tinkereada5372013-05-21 12:48:14 -07001712 if (jname == NULL) {
1713 jniThrowException(env, "java/lang/IllegalArgumentException",
1714 "property name String is null");
1715 return;
1716 }
1717
1718 if (jvalue == NULL) {
1719 jniThrowException(env, "java/lang/IllegalArgumentException",
1720 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001721 return;
1722 }
1723
1724 String8 name = JStringToString8(env, jname);
1725 String8 value = JStringToString8(env, jvalue);
1726
1727 status_t err = drm->setPropertyString(name, value);
1728
1729 throwExceptionAsNecessary(env, err, "Failed to set property");
1730}
1731
1732static void android_media_MediaDrm_setPropertyByteArray(
1733 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1734 sp<IDrm> drm = GetDrm(env, thiz);
1735
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001736 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001737 return;
1738 }
1739
Jeff Tinkereada5372013-05-21 12:48:14 -07001740 if (jname == NULL) {
1741 jniThrowException(env, "java/lang/IllegalArgumentException",
1742 "property name String is null");
1743 return;
1744 }
1745
1746 if (jvalue == NULL) {
1747 jniThrowException(env, "java/lang/IllegalArgumentException",
1748 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001749 return;
1750 }
1751
1752 String8 name = JStringToString8(env, jname);
1753 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1754
1755 status_t err = drm->setPropertyByteArray(name, value);
1756
1757 throwExceptionAsNecessary(env, err, "Failed to set property");
1758}
1759
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001760static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001761 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001762 jstring jalgorithm) {
1763
1764 sp<IDrm> drm = GetDrm(env, jdrm);
1765
1766 if (!CheckSession(env, drm, jsessionId)) {
1767 return;
1768 }
1769
1770 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001771 jniThrowException(env, "java/lang/IllegalArgumentException",
1772 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001773 return;
1774 }
1775
1776 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1777 String8 algorithm = JStringToString8(env, jalgorithm);
1778
1779 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1780
1781 throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
1782}
1783
1784static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001785 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001786 jstring jalgorithm) {
1787
1788 sp<IDrm> drm = GetDrm(env, jdrm);
1789
1790 if (!CheckSession(env, drm, jsessionId)) {
1791 return;
1792 }
1793
1794 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001795 jniThrowException(env, "java/lang/IllegalArgumentException",
1796 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001797 return;
1798 }
1799
1800 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1801 String8 algorithm = JStringToString8(env, jalgorithm);
1802
1803 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1804
1805 throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
1806}
1807
1808
1809static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001810 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001811 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1812
1813 sp<IDrm> drm = GetDrm(env, jdrm);
1814
1815 if (!CheckSession(env, drm, jsessionId)) {
1816 return NULL;
1817 }
1818
1819 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001820 jniThrowException(env, "java/lang/IllegalArgumentException",
1821 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001822 return NULL;
1823 }
1824
1825 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1826 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1827 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1828 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1829 Vector<uint8_t> output;
1830
1831 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1832
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001833 if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
1834 return NULL;
1835 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001836
1837 return VectorToJByteArray(env, output);
1838}
1839
1840static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001841 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001842 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1843
1844 sp<IDrm> drm = GetDrm(env, jdrm);
1845
1846 if (!CheckSession(env, drm, jsessionId)) {
1847 return NULL;
1848 }
1849
1850 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001851 jniThrowException(env, "java/lang/IllegalArgumentException",
1852 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001853 return NULL;
1854 }
1855
1856 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1857 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1858 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1859 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1860 Vector<uint8_t> output;
1861
1862 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001863 if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
1864 return NULL;
1865 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001866
1867 return VectorToJByteArray(env, output);
1868}
1869
1870static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001871 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001872 jbyteArray jkeyId, jbyteArray jmessage) {
1873
1874 sp<IDrm> drm = GetDrm(env, jdrm);
1875
1876 if (!CheckSession(env, drm, jsessionId)) {
1877 return NULL;
1878 }
1879
1880 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001881 jniThrowException(env, "java/lang/IllegalArgumentException",
1882 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001883 return NULL;
1884 }
1885
1886 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1887 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1888 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1889 Vector<uint8_t> signature;
1890
1891 status_t err = drm->sign(sessionId, keyId, message, signature);
1892
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001893 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1894 return NULL;
1895 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001896
1897 return VectorToJByteArray(env, signature);
1898}
1899
1900static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001901 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001902 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1903
1904 sp<IDrm> drm = GetDrm(env, jdrm);
1905
1906 if (!CheckSession(env, drm, jsessionId)) {
1907 return false;
1908 }
1909
1910 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001911 jniThrowException(env, "java/lang/IllegalArgumentException",
1912 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001913 return false;
1914 }
1915
1916 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1917 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1918 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1919 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1920 bool match;
1921
1922 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1923
1924 throwExceptionAsNecessary(env, err, "Failed to verify");
1925 return match;
1926}
1927
Adam Stonec06e10e2017-12-19 12:54:33 -08001928static jobject
1929android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1930{
1931 sp<IDrm> drm = GetDrm(env, thiz);
Jeff Tinker55d26242018-10-10 16:10:43 -07001932
1933 if (!CheckDrm(env, drm)) {
Adam Stonec06e10e2017-12-19 12:54:33 -08001934 return NULL;
1935 }
1936
1937 // Retrieve current metrics snapshot from drm.
Adam Stone94395c92018-01-30 12:07:00 -08001938 PersistableBundle metrics;
Robert Shihba6777e2019-11-12 13:04:59 -08001939 sp<IDrmMetricsConsumer> consumer(new DrmMetricsConsumer(&metrics));
1940 status_t err = drm->getMetrics(consumer);
Adam Stonec06e10e2017-12-19 12:54:33 -08001941 if (err != OK) {
1942 ALOGE("getMetrics failed: %d", (int)err);
1943 return (jobject) NULL;
1944 }
1945
Robert Shih4354a962019-11-10 12:09:08 -08001946 return MediaMetricsJNI::nativeToJavaPersistableBundle(env, &metrics);
Adam Stonec06e10e2017-12-19 12:54:33 -08001947}
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001948
Jeff Tinkere4095a82014-03-04 13:17:11 -08001949static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001950 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001951 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1952
1953 sp<IDrm> drm = GetDrm(env, jdrm);
1954
1955 if (!CheckSession(env, drm, jsessionId)) {
1956 return NULL;
1957 }
1958
1959 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1960 jniThrowException(env, "java/lang/IllegalArgumentException",
1961 "required argument is null");
1962 return NULL;
1963 }
1964
1965 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1966 String8 algorithm = JStringToString8(env, jalgorithm);
1967 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1968 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1969 Vector<uint8_t> signature;
1970
1971 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1972
1973 if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
1974 return NULL;
1975 }
1976
1977 return VectorToJByteArray(env, signature);
1978}
1979
Robert Shih205f7a92021-01-19 21:12:10 -08001980static jboolean android_media_MediaDrm_requiresSecureDecoder(
1981 JNIEnv *env, jobject thiz, jstring jmimeType,
1982 jint jSecurityLevel) {
1983 sp<IDrm> drm = GetDrm(env, thiz);
1984 if (!CheckDrm(env, drm)) {
1985 return JNI_FALSE;
1986 }
1987
1988 String8 mimeType;
1989 if (jmimeType != NULL) {
1990 mimeType = JStringToString8(env, jmimeType);
1991 }
1992
1993 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
1994 if (securityLevel == DrmPlugin::kSecurityLevelUnknown) {
1995 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1996 return JNI_FALSE;
1997 }
1998
1999 if (securityLevel == DrmPlugin::kSecurityLevelMax) {
2000 return drm->requiresSecureDecoder(mimeType.c_str());
2001 }
2002 return drm->requiresSecureDecoder(mimeType.c_str(), securityLevel);
2003}
Jeff Tinkere4095a82014-03-04 13:17:11 -08002004
Robert Shih02937122021-01-20 00:05:20 -08002005static void android_media_MediaDrm_setPlaybackId(
2006 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
2007 jstring jplaybackId) {
2008 sp<IDrm> drm = GetDrm(env, thiz);
2009 if (!CheckSession(env, drm, jsessionId)) {
2010 return;
2011 }
2012
2013 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
2014
2015 String8 playbackId;
2016 if (jplaybackId != NULL) {
2017 playbackId = JStringToString8(env, jplaybackId);
2018 }
2019 status_t err = drm->setPlaybackId(sessionId, playbackId.c_str());
2020 throwExceptionAsNecessary(env, err, "Failed to set playbackId");
2021}
2022
Robert Shih696989f2021-02-12 23:25:16 -08002023static jobject android_media_MediaDrm_getLogMessages(
2024 JNIEnv *env, jobject thiz) {
2025 sp<IDrm> drm = GetDrm(env, thiz);
2026 if (!CheckDrm(env, drm)) {
2027 return NULL;
2028 }
2029
2030 Vector<drm::V1_4::LogMessage> logs;
2031 status_t err = drm->getLogMessages(logs);
2032 ALOGI("drm->getLogMessages %zu logs", logs.size());
2033 if (throwExceptionAsNecessary(env, err, "Failed to get log messages")) {
2034 return NULL;
2035 }
2036 return hidlLogMessagesToJavaList(env, logs);
2037}
2038
Daniel Micay76f6a862015-09-19 17:31:01 -04002039static const JNINativeMethod gMethods[] = {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002040 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
2041
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002042 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
2043
Edwin Wong4d1d84e2017-01-04 09:37:49 -08002044 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002045 (void *)android_media_MediaDrm_native_setup },
2046
Robert Shihd2e8b432019-11-21 20:27:56 -08002047 { "getSupportedCryptoSchemesNative", "()[B",
2048 (void *)android_media_MediaDrm_getSupportedCryptoSchemesNative },
2049
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08002050 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002051 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
2052
Robert Shih02937122021-01-20 00:05:20 -08002053 { "openSessionNative", "(I)[B",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002054 (void *)android_media_MediaDrm_openSession },
2055
Robert Shih02937122021-01-20 00:05:20 -08002056 { "closeSessionNative", "([B)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002057 (void *)android_media_MediaDrm_closeSession },
2058
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002059 { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
2060 "Landroid/media/MediaDrm$KeyRequest;",
2061 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002062
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002063 { "provideKeyResponse", "([B[B)[B",
2064 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002065
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002066 { "removeKeys", "([B)V",
2067 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002068
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002069 { "restoreKeys", "([B[B)V",
2070 (void *)android_media_MediaDrm_restoreKeys },
2071
2072 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
2073 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002074
Jeff Tinkere4095a82014-03-04 13:17:11 -08002075 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
2076 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002077
Jeff Tinkere4095a82014-03-04 13:17:11 -08002078 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
2079 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002080
2081 { "getSecureStops", "()Ljava/util/List;",
2082 (void *)android_media_MediaDrm_getSecureStops },
2083
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002084 { "getSecureStopIds", "()Ljava/util/List;",
2085 (void *)android_media_MediaDrm_getSecureStopIds },
2086
Jeff Tinker1b51c722014-10-31 00:54:26 -07002087 { "getSecureStop", "([B)[B",
2088 (void *)android_media_MediaDrm_getSecureStop },
2089
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002090 { "releaseSecureStops", "([B)V",
2091 (void *)android_media_MediaDrm_releaseSecureStops },
2092
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002093 { "removeSecureStop", "([B)V",
2094 (void *)android_media_MediaDrm_removeSecureStop },
2095
2096 { "removeAllSecureStops", "()V",
2097 (void *)android_media_MediaDrm_removeAllSecureStops },
Jeff Tinker1b51c722014-10-31 00:54:26 -07002098
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002099 { "getConnectedHdcpLevel", "()I",
2100 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
2101
2102 { "getMaxHdcpLevel", "()I",
2103 (void *)android_media_MediaDrm_getMaxHdcpLevel },
2104
2105 { "getOpenSessionCount", "()I",
2106 (void *)android_media_MediaDrm_getOpenSessionCount },
2107
2108 { "getMaxSessionCount", "()I",
2109 (void *)android_media_MediaDrm_getMaxSessionCount },
2110
2111 { "getSecurityLevel", "([B)I",
2112 (void *)android_media_MediaDrm_getSecurityLevel },
2113
Jeff Tinker55d26242018-10-10 16:10:43 -07002114 { "removeOfflineLicense", "([B)V",
2115 (void *)android_media_MediaDrm_removeOfflineLicense },
2116
2117 { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
2118 (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
2119
2120 { "getOfflineLicenseState", "([B)I",
2121 (void *)android_media_MediaDrm_getOfflineLicenseState },
2122
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002123 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
2124 (void *)android_media_MediaDrm_getPropertyString },
2125
2126 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
2127 (void *)android_media_MediaDrm_getPropertyByteArray },
2128
2129 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
2130 (void *)android_media_MediaDrm_setPropertyString },
2131
2132 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
2133 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002134
2135 { "setCipherAlgorithmNative",
2136 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2137 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
2138
2139 { "setMacAlgorithmNative",
2140 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2141 (void *)android_media_MediaDrm_setMacAlgorithmNative },
2142
2143 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2144 (void *)android_media_MediaDrm_encryptNative },
2145
2146 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2147 (void *)android_media_MediaDrm_decryptNative },
2148
2149 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
2150 (void *)android_media_MediaDrm_signNative },
2151
2152 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
2153 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08002154
2155 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
2156 (void *)android_media_MediaDrm_signRSANative },
Adam Stonec06e10e2017-12-19 12:54:33 -08002157
2158 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
2159 (void *)android_media_MediaDrm_native_getMetrics },
Robert Shih205f7a92021-01-19 21:12:10 -08002160
2161 { "requiresSecureDecoder", "(Ljava/lang/String;I)Z",
2162 (void *)android_media_MediaDrm_requiresSecureDecoder },
Robert Shih02937122021-01-20 00:05:20 -08002163
2164 { "setPlaybackId", "([BLjava/lang/String;)V",
2165 (void *)android_media_MediaDrm_setPlaybackId },
Robert Shih696989f2021-02-12 23:25:16 -08002166
2167 { "getLogMessages", "()Ljava/util/List;",
2168 (void *)android_media_MediaDrm_getLogMessages },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002169};
2170
2171int register_android_media_Drm(JNIEnv *env) {
2172 return AndroidRuntime::registerNativeMethods(env,
2173 "android/media/MediaDrm", gMethods, NELEM(gMethods));
2174}