blob: 56f6c45bb50eea7c03433d0bb31fafb6d667c9b0 [file] [log] [blame]
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001/*
2 * Copyright 2013, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "MediaDrm-JNI"
19#include <utils/Log.h>
20
21#include "android_media_MediaDrm.h"
Adam Stonec06e10e2017-12-19 12:54:33 -080022#include "android_media_MediaMetricsJNI.h"
Adam Stone94395c92018-01-30 12:07:00 -080023#include "android_os_Parcel.h"
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080024#include "android_runtime/AndroidRuntime.h"
Ruben Brunk87eac992013-09-09 17:44:59 -070025#include "android_runtime/Log.h"
Jeff Tinker54cfbd62013-04-02 13:14:59 -070026#include "android_os_Parcel.h"
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080027#include "jni.h"
Steven Moreland2279b252017-07-19 09:50:45 -070028#include <nativehelper/JNIHelp.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080029
Robert Shihd2e8b432019-11-21 20:27:56 -080030#include <android/hardware/drm/1.3/IDrmFactory.h>
Jeff Tinker54cfbd62013-04-02 13:14:59 -070031#include <binder/Parcel.h>
Adam Stone94395c92018-01-30 12:07:00 -080032#include <binder/PersistableBundle.h>
Jeff Tinkerdc614f82016-02-12 08:58:32 -080033#include <cutils/properties.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080034#include <media/stagefright/foundation/ADebug.h>
Jeff Tinkerf7568b52013-04-17 14:24:40 -070035#include <media/stagefright/MediaErrors.h>
Robert Shihba6777e2019-11-12 13:04:59 -080036#include <mediadrm/DrmMetricsConsumer.h>
Robert Shih218b9532019-08-15 14:48:11 -070037#include <mediadrm/DrmUtils.h>
Robert Shihba6777e2019-11-12 13:04:59 -080038#include <mediadrm/IDrmMetricsConsumer.h>
Jeff Tinkercd4d28f2018-02-16 16:24:49 -080039#include <mediadrm/IDrm.h>
Robert Shih696989f2021-02-12 23:25:16 -080040#include <utils/Vector.h>
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080041
Adam Stone94395c92018-01-30 12:07:00 -080042using ::android::os::PersistableBundle;
Robert Shihd2e8b432019-11-21 20:27:56 -080043namespace drm = ::android::hardware::drm;
Adam Stone94395c92018-01-30 12:07:00 -080044
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080045namespace android {
46
47#define FIND_CLASS(var, className) \
48 var = env->FindClass(className); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070049 LOG_FATAL_IF(! (var), "Unable to find class %s", className);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080050
51#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
52 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070053 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080054
55#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
56 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070057 LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080058
Jeff Tinker54cfbd62013-04-02 13:14:59 -070059#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
60 var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070061 LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070062
63#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
64 var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070065 LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -070066
Chih-Hung Hsiehacb1de82018-07-26 15:40:45 -070067#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \
68 var = env->GetStaticObjectField(clazz, fieldId); \
69 LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId);
Adam Stone94395c92018-01-30 12:07:00 -080070
Jeff Tinker54cfbd62013-04-02 13:14:59 -070071
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080072struct RequestFields {
73 jfieldID data;
74 jfieldID defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -070075 jfieldID requestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -080076};
77
78struct ArrayListFields {
79 jmethodID init;
80 jmethodID add;
81};
82
83struct HashmapFields {
84 jmethodID init;
85 jmethodID get;
86 jmethodID put;
87 jmethodID entrySet;
88};
89
90struct SetFields {
91 jmethodID iterator;
92};
93
94struct IteratorFields {
95 jmethodID next;
96 jmethodID hasNext;
97};
98
99struct EntryFields {
100 jmethodID getKey;
101 jmethodID getValue;
102};
103
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700104struct EventTypes {
Jeff Tinker17b89222013-05-21 12:35:06 -0700105 jint kEventProvisionRequired;
106 jint kEventKeyRequired;
107 jint kEventKeyExpired;
108 jint kEventVendorDefined;
Ronghua Wua6d72092015-03-04 11:16:02 -0800109 jint kEventSessionReclaimed;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700110} gEventTypes;
111
Jeff Tinker74797f82015-03-31 15:44:34 -0700112struct EventWhat {
113 jint kWhatDrmEvent;
114 jint kWhatExpirationUpdate;
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700115 jint kWhatKeyStatusChange;
Jeff Tinker20594d82018-12-12 08:31:22 -0800116 jint kWhatSessionLostState;
Jeff Tinker74797f82015-03-31 15:44:34 -0700117} gEventWhat;
118
Jeff Tinker17b89222013-05-21 12:35:06 -0700119struct KeyTypes {
120 jint kKeyTypeStreaming;
121 jint kKeyTypeOffline;
122 jint kKeyTypeRelease;
123} gKeyTypes;
124
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700125struct KeyRequestTypes {
126 jint kKeyRequestTypeInitial;
127 jint kKeyRequestTypeRenewal;
128 jint kKeyRequestTypeRelease;
Rahul Frias8f761ba2018-01-22 23:43:54 -0800129 jint kKeyRequestTypeNone;
130 jint kKeyRequestTypeUpdate;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700131} gKeyRequestTypes;
132
Jeff Tinkere4095a82014-03-04 13:17:11 -0800133struct CertificateTypes {
134 jint kCertificateTypeNone;
135 jint kCertificateTypeX509;
136} gCertificateTypes;
137
138struct CertificateFields {
139 jfieldID wrappedPrivateKey;
140 jfieldID certificateData;
141};
142
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700143struct StateExceptionFields {
144 jmethodID init;
145 jclass classId;
146};
147
Jeff Tinker20594d82018-12-12 08:31:22 -0800148struct SessionExceptionFields {
149 jmethodID init;
150 jclass classId;
151 jfieldID errorCode;
152};
153
154struct SessionExceptionErrorCodes {
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800155 jint kErrorUnknown;
Jeff Tinker20594d82018-12-12 08:31:22 -0800156 jint kResourceContention;
157} gSessionExceptionErrorCodes;
158
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800159struct HDCPLevels {
160 jint kHdcpLevelUnknown;
161 jint kHdcpNone;
162 jint kHdcpV1;
163 jint kHdcpV2;
164 jint kHdcpV2_1;
165 jint kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800166 jint kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800167 jint kHdcpNoOutput;
168} gHdcpLevels;
169
170struct SecurityLevels {
171 jint kSecurityLevelUnknown;
Jeff Tinker2bca5252018-02-11 18:59:14 +0000172 jint kSecurityLevelMax;
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800173 jint kSecurityLevelSwSecureCrypto;
174 jint kSecurityLevelSwSecureDecode;
175 jint kSecurityLevelHwSecureCrypto;
176 jint kSecurityLevelHwSecureDecode;
177 jint kSecurityLevelHwSecureAll;
178} gSecurityLevels;
179
Jeff Tinker55d26242018-10-10 16:10:43 -0700180struct OfflineLicenseState {
181 jint kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800182 jint kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -0700183 jint kOfflineLicenseStateUnknown;
184} gOfflineLicenseStates;
185
Robert Shih9d4e2d42019-11-08 13:51:49 -0800186struct KeyStatusFields {
187 jmethodID init;
188 jclass classId;
189};
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800190
Robert Shih696989f2021-02-12 23:25:16 -0800191struct LogMessageFields {
192 jmethodID init;
193 jclass classId;
194};
195
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800196struct fields_t {
197 jfieldID context;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700198 jmethodID post_event;
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700199 RequestFields keyRequest;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800200 RequestFields provisionRequest;
201 ArrayListFields arraylist;
202 HashmapFields hashmap;
203 SetFields set;
204 IteratorFields iterator;
205 EntryFields entry;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800206 CertificateFields certificate;
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700207 StateExceptionFields stateException;
Jeff Tinker20594d82018-12-12 08:31:22 -0800208 SessionExceptionFields sessionException;
Jeff Tinkere4095a82014-03-04 13:17:11 -0800209 jclass certificateClassId;
210 jclass hashmapClassId;
211 jclass arraylistClassId;
212 jclass stringClassId;
Adam Stone94395c92018-01-30 12:07:00 -0800213 jobject bundleCreator;
214 jmethodID createFromParcelId;
215 jclass parcelCreatorClassId;
Robert Shih9d4e2d42019-11-08 13:51:49 -0800216 KeyStatusFields keyStatus;
Robert Shih696989f2021-02-12 23:25:16 -0800217 LogMessageFields logMessage;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800218};
219
220static fields_t gFields;
221
Adam Stone94395c92018-01-30 12:07:00 -0800222namespace {
223
Robert Shih9d4e2d42019-11-08 13:51:49 -0800224jbyteArray hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> &vector) {
225 JNIEnv *env = AndroidRuntime::getJNIEnv();
226 size_t length = vector.size();
227 jbyteArray result = env->NewByteArray(length);
228 if (result != NULL) {
229 env->SetByteArrayRegion(result, 0, length, reinterpret_cast<const jbyte *>(vector.data()));
230 }
231 return result;
232}
233
Robert Shih696989f2021-02-12 23:25:16 -0800234jobject hidlLogMessagesToJavaList(JNIEnv *env, const Vector<drm::V1_4::LogMessage> &logs) {
235 jclass clazz = gFields.arraylistClassId;
236 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
237 clazz = gFields.logMessage.classId;
238 for (auto log: logs) {
239 jobject jLog = env->NewObject(clazz, gFields.logMessage.init,
240 static_cast<jlong>(log.timeMs),
241 static_cast<jint>(log.priority),
242 env->NewStringUTF(log.message.c_str()));
243 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jLog);
244 }
245 return arrayList;
246}
Adam Stone94395c92018-01-30 12:07:00 -0800247} // namespace anonymous
248
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700249// ----------------------------------------------------------------------------
250// ref-counted object for callbacks
251class JNIDrmListener: public DrmListener
252{
253public:
254 JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
255 ~JNIDrmListener();
Robert Shih9d4e2d42019-11-08 13:51:49 -0800256 virtual void notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *arg = NULL);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700257private:
258 JNIDrmListener();
259 jclass mClass; // Reference to MediaDrm class
260 jobject mObject; // Weak ref to MediaDrm Java object to call on
261};
262
263JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
264{
265 // Hold onto the MediaDrm class for use in calling the static method
266 // that posts events to the application thread.
267 jclass clazz = env->GetObjectClass(thiz);
268 if (clazz == NULL) {
269 ALOGE("Can't find android/media/MediaDrm");
Jeff Tinkereada5372013-05-21 12:48:14 -0700270 jniThrowException(env, "java/lang/Exception",
271 "Can't find android/media/MediaDrm");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700272 return;
273 }
274 mClass = (jclass)env->NewGlobalRef(clazz);
275
276 // We use a weak reference so the MediaDrm object can be garbage collected.
277 // The reference is only used as a proxy for callbacks.
278 mObject = env->NewGlobalRef(weak_thiz);
279}
280
281JNIDrmListener::~JNIDrmListener()
282{
283 // remove global references
284 JNIEnv *env = AndroidRuntime::getJNIEnv();
285 env->DeleteGlobalRef(mObject);
286 env->DeleteGlobalRef(mClass);
287}
288
289void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
Robert Shih9d4e2d42019-11-08 13:51:49 -0800290 const ListenerArgs *args)
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700291{
Jeff Tinker74797f82015-03-31 15:44:34 -0700292 jint jwhat;
293 jint jeventType = 0;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700294
295 // translate DrmPlugin event types into their java equivalents
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700296 switch (eventType) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700297 case DrmPlugin::kDrmPluginEventProvisionRequired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700298 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700299 jeventType = gEventTypes.kEventProvisionRequired;
300 break;
301 case DrmPlugin::kDrmPluginEventKeyNeeded:
Jeff Tinker74797f82015-03-31 15:44:34 -0700302 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700303 jeventType = gEventTypes.kEventKeyRequired;
304 break;
305 case DrmPlugin::kDrmPluginEventKeyExpired:
Jeff Tinker74797f82015-03-31 15:44:34 -0700306 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700307 jeventType = gEventTypes.kEventKeyExpired;
308 break;
309 case DrmPlugin::kDrmPluginEventVendorDefined:
Jeff Tinker74797f82015-03-31 15:44:34 -0700310 jwhat = gEventWhat.kWhatDrmEvent;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700311 jeventType = gEventTypes.kEventVendorDefined;
312 break;
Ronghua Wua6d72092015-03-04 11:16:02 -0800313 case DrmPlugin::kDrmPluginEventSessionReclaimed:
Jeff Tinker74797f82015-03-31 15:44:34 -0700314 jwhat = gEventWhat.kWhatDrmEvent;
Ronghua Wua6d72092015-03-04 11:16:02 -0800315 jeventType = gEventTypes.kEventSessionReclaimed;
316 break;
Jeff Tinker74797f82015-03-31 15:44:34 -0700317 case DrmPlugin::kDrmPluginEventExpirationUpdate:
318 jwhat = gEventWhat.kWhatExpirationUpdate;
319 break;
320 case DrmPlugin::kDrmPluginEventKeysChange:
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700321 jwhat = gEventWhat.kWhatKeyStatusChange;
Jeff Tinker74797f82015-03-31 15:44:34 -0700322 break;
Jeff Tinker20594d82018-12-12 08:31:22 -0800323 case DrmPlugin::kDrmPluginEventSessionLostState:
324 jwhat = gEventWhat.kWhatSessionLostState;
325 break;
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700326 default:
327 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
328 return;
329 }
330
331 JNIEnv *env = AndroidRuntime::getJNIEnv();
Robert Shih9d4e2d42019-11-08 13:51:49 -0800332 if (args) {
333 env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
334 jwhat, jeventType, extra,
335 args->jSessionId, args->jData, args->jExpirationTime,
336 args->jKeyStatusList, args->jHasNewUsableKey);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700337 }
338
339 if (env->ExceptionCheck()) {
340 ALOGW("An exception occurred while notifying an event.");
341 LOGW_EX(env);
342 env->ExceptionClear();
343 }
344}
345
Robert Shih620f4a62021-02-15 03:28:42 -0800346jint MediaErrorToJavaError(status_t err) {
347#define STATUS_CASE(status) \
348 case status: \
349 return J##status
350
351 switch (err) {
352 STATUS_CASE(ERROR_DRM_UNKNOWN);
353 STATUS_CASE(ERROR_DRM_NO_LICENSE);
354 STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
355 STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
356 STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
357 STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
358 STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
359 STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
360 STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
361 STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
362 STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
363 STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
364 STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
365 STATUS_CASE(ERROR_DRM_GENERIC_OEM);
366 STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
367 STATUS_CASE(ERROR_DRM_INIT_DATA);
368 STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
369 STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
370 STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
371 STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
372 STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
373 STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
374 STATUS_CASE(ERROR_DRM_LICENSE_STATE);
375 STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
376 STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
377 STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
378 STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
379 STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
380 STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
381 STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
382 STATUS_CASE(ERROR_DRM_STORAGE_READ);
383 STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
384 STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
385#undef STATUS_CASE
386 }
387 return static_cast<jint>(err);
388}
389
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700390static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
391 ALOGE("Illegal state exception: %s (%d)", msg, err);
392
Robert Shih620f4a62021-02-15 03:28:42 -0800393 jint jerr = MediaErrorToJavaError(err);
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700394 jobject exception = env->NewObject(gFields.stateException.classId,
Robert Shih620f4a62021-02-15 03:28:42 -0800395 gFields.stateException.init, static_cast<int>(jerr),
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700396 env->NewStringUTF(msg));
397 env->Throw(static_cast<jthrowable>(exception));
398}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700399
Jeff Tinker20594d82018-12-12 08:31:22 -0800400static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
401 ALOGE("Session exception: %s (%d)", msg, err);
402
403 jint jErrorCode = 0;
404 switch(err) {
405 case ERROR_DRM_RESOURCE_CONTENTION:
406 jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
407 break;
408 default:
409 break;
410 }
411
412 jobject exception = env->NewObject(gFields.sessionException.classId,
413 gFields.sessionException.init, static_cast<int>(err),
414 env->NewStringUTF(msg));
415
416 env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
417 env->Throw(static_cast<jthrowable>(exception));
418}
419
420static bool isSessionException(status_t err) {
421 return err == ERROR_DRM_RESOURCE_CONTENTION;
422}
423
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800424static bool throwExceptionAsNecessary(
Robert Shih60dab872021-02-13 11:24:59 -0800425 JNIEnv *env, const sp<IDrm> &drm, status_t err, const char *msg = NULL) {
426 std::string msgStr;
Robert Shih13eb27b2021-02-20 00:08:16 -0800427 if (drm != NULL && err != OK) {
Robert Shih60dab872021-02-13 11:24:59 -0800428 msgStr = DrmUtils::GetExceptionMessage(err, msg, drm);
429 msg = msgStr.c_str();
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700430 }
431
Jeff Tinkereb13c762017-11-01 15:29:38 -0700432 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800433 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
434 return true;
Jeff Tinker5de2e902019-01-25 23:09:36 -0800435 } else if (err == ERROR_UNSUPPORTED) {
436 jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
437 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700438 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
439 jniThrowException(env, "android/media/NotProvisionedException", msg);
440 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700441 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
442 jniThrowException(env, "android/media/ResourceBusyException", msg);
443 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700444 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
445 jniThrowException(env, "android/media/DeniedByServerException", msg);
446 return true;
Jeff Tinker314b7f32015-06-15 17:45:43 -0700447 } else if (err == DEAD_OBJECT) {
448 jniThrowException(env, "android/media/MediaDrmResetException",
449 "mediaserver died");
450 return true;
Jeff Tinker20594d82018-12-12 08:31:22 -0800451 } else if (isSessionException(err)) {
452 throwSessionException(env, msg, err);
453 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800454 } else if (err != OK) {
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700455 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800456 return true;
457 }
458 return false;
459}
460
461static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000462 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800463 return jdrm ? jdrm->getDrm() : NULL;
464}
465
466JDrm::JDrm(
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800467 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
468 const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800469 mObject = env->NewWeakGlobalRef(thiz);
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800470 mDrm = MakeDrm(uuid, appPackageName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700471 if (mDrm != NULL) {
472 mDrm->setListener(this);
473 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800474}
475
476JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800477 JNIEnv *env = AndroidRuntime::getJNIEnv();
478
479 env->DeleteWeakGlobalRef(mObject);
480 mObject = NULL;
481}
482
483// static
484sp<IDrm> JDrm::MakeDrm() {
Robert Shih218b9532019-08-15 14:48:11 -0700485 return DrmUtils::MakeDrm();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800486}
487
488// static
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800489sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800490 sp<IDrm> drm = MakeDrm();
491
492 if (drm == NULL) {
493 return NULL;
494 }
495
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800496 status_t err = drm->createPlugin(uuid, appPackageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800497
498 if (err != OK) {
499 return NULL;
500 }
501
502 return drm;
503}
504
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700505status_t JDrm::setListener(const sp<DrmListener>& listener) {
506 Mutex::Autolock lock(mLock);
507 mListener = listener;
508 return OK;
509}
510
Robert Shih9d4e2d42019-11-08 13:51:49 -0800511void JDrm::notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *args) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700512 sp<DrmListener> listener;
513 mLock.lock();
514 listener = mListener;
515 mLock.unlock();
516
517 if (listener != NULL) {
518 Mutex::Autolock lock(mNotifyLock);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800519 listener->notify(eventType, extra, args);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700520 }
521}
522
Robert Shih3a523902019-08-15 14:48:11 -0700523void JDrm::sendEvent(
524 DrmPlugin::EventType eventType,
525 const hardware::hidl_vec<uint8_t> &sessionId,
526 const hardware::hidl_vec<uint8_t> &data) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800527 ListenerArgs args{
528 .jSessionId = hidlVectorToJByteArray(sessionId),
529 .jData = hidlVectorToJByteArray(data),
530 };
531 notify(eventType, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700532}
533
534void JDrm::sendExpirationUpdate(
535 const hardware::hidl_vec<uint8_t> &sessionId,
536 int64_t expiryTimeInMS) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800537 ListenerArgs args{
538 .jSessionId = hidlVectorToJByteArray(sessionId),
539 .jExpirationTime = expiryTimeInMS,
540 };
541 notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700542}
543
544void JDrm::sendKeysChange(
545 const hardware::hidl_vec<uint8_t> &sessionId,
546 const std::vector<DrmKeyStatus> &keyStatusList,
547 bool hasNewUsableKey) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800548 JNIEnv *env = AndroidRuntime::getJNIEnv();
549 jclass clazz = gFields.arraylistClassId;
550 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
551 clazz = gFields.keyStatus.classId;
552 for (const auto &keyStatus : keyStatusList) {
553 jbyteArray jKeyId(hidlVectorToJByteArray(keyStatus.keyId));
554 jint jStatusCode(keyStatus.type);
555 jobject jKeyStatus = env->NewObject(clazz, gFields.keyStatus.init, jKeyId, jStatusCode);
556 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jKeyStatus);
557 }
558 ListenerArgs args{
559 .jSessionId = hidlVectorToJByteArray(sessionId),
560 .jKeyStatusList = arrayList,
561 .jHasNewUsableKey = hasNewUsableKey,
562 };
563 notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700564}
565
566void JDrm::sendSessionLostState(
567 const hardware::hidl_vec<uint8_t> &sessionId) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800568 ListenerArgs args{
569 .jSessionId = hidlVectorToJByteArray(sessionId),
570 };
571 notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700572}
573
Jeff Tinker600071c2014-04-11 16:11:15 -0700574void JDrm::disconnect() {
575 if (mDrm != NULL) {
576 mDrm->destroyPlugin();
577 mDrm.clear();
578 }
579}
580
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700581
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800582// static
Jeff Tinker5de2e902019-01-25 23:09:36 -0800583status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
584 DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800585 sp<IDrm> drm = MakeDrm();
586
587 if (drm == NULL) {
Jeff Tinker5de2e902019-01-25 23:09:36 -0800588 return BAD_VALUE;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800589 }
590
Jeff Tinker5de2e902019-01-25 23:09:36 -0800591 return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800592}
593
594status_t JDrm::initCheck() const {
595 return mDrm == NULL ? NO_INIT : OK;
596}
597
598// JNI conversion utilities
599static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
600 Vector<uint8_t> vector;
601 size_t length = env->GetArrayLength(byteArray);
602 vector.insertAt((size_t)0, length);
603 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
604 return vector;
605}
606
607static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
608 size_t length = vector.size();
609 jbyteArray result = env->NewByteArray(length);
610 if (result != NULL) {
611 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
612 }
613 return result;
614}
615
616static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800617 String8 result;
618
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700619 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800620 if (s) {
621 result = s;
622 env->ReleaseStringUTFChars(jstr, s);
623 }
624 return result;
625}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700626
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800627/*
628 import java.util.HashMap;
629 import java.util.Set;
630 import java.Map.Entry;
631 import jav.util.Iterator;
632
633 HashMap<k, v> hm;
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800634 Set<Entry<k, v>> s = hm.entrySet();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800635 Iterator i = s.iterator();
636 Entry e = s.next();
637*/
638
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200639static KeyedVector<String8, String8> HashMapToKeyedVector(
640 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800641 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800642 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200643 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800644
645 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
646 if (entrySet) {
647 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
648 if (iterator) {
649 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
650 while (hasNext) {
651 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
652 if (entry) {
653 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200654 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700655 jniThrowException(env, "java/lang/IllegalArgumentException",
656 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200657 env->DeleteLocalRef(entry);
658 *pIsOK = false;
659 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800660 }
661 jstring jkey = static_cast<jstring>(obj);
662
663 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200664 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700665 jniThrowException(env, "java/lang/IllegalArgumentException",
666 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200667 env->DeleteLocalRef(entry);
668 *pIsOK = false;
669 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800670 }
671 jstring jvalue = static_cast<jstring>(obj);
672
673 String8 key = JStringToString8(env, jkey);
674 String8 value = JStringToString8(env, jvalue);
675 keyedVector.add(key, value);
676
677 env->DeleteLocalRef(jkey);
678 env->DeleteLocalRef(jvalue);
679 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
680 }
681 env->DeleteLocalRef(entry);
682 }
683 env->DeleteLocalRef(iterator);
684 }
685 env->DeleteLocalRef(entrySet);
686 }
687 return keyedVector;
688}
689
690static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800691 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800692 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
693 for (size_t i = 0; i < map.size(); ++i) {
694 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
695 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
696 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
697 env->DeleteLocalRef(jkey);
698 env->DeleteLocalRef(jvalue);
699 }
700 return hashMap;
701}
702
703static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800704 List<Vector<uint8_t>> list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800705 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800706 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800707 List<Vector<uint8_t>>::iterator iter = list.begin();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800708 while (iter != list.end()) {
709 jbyteArray byteArray = VectorToJByteArray(env, *iter);
710 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
711 env->DeleteLocalRef(byteArray);
712 iter++;
713 }
714
715 return arrayList;
716}
717
718} // namespace android
719
720using namespace android;
721
722static sp<JDrm> setDrm(
723 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000724 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800725 if (drm != NULL) {
726 drm->incStrong(thiz);
727 }
728 if (old != NULL) {
729 old->decStrong(thiz);
730 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000731 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800732
733 return old;
734}
735
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800736static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800737 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700738 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800739 return false;
740 }
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800741 return true;
742}
743
744static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
745{
746 if (!CheckDrm(env, drm)) {
747 return false;
748 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800749
750 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700751 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800752 return false;
753 }
754 return true;
755}
756
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800757static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700758 sp<JDrm> drm = setDrm(env, thiz, NULL);
759 if (drm != NULL) {
760 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700761 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700762 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800763}
764
765static void android_media_MediaDrm_native_init(JNIEnv *env) {
766 jclass clazz;
767 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000768 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700769 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
Robert Shih9d4e2d42019-11-08 13:51:49 -0800770 "(Ljava/lang/Object;III[B[BJLjava/util/List;Z)V");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700771
772 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700773 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700774 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700775 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700776 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700777 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700778 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700779 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700780 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Ronghua Wua6d72092015-03-04 11:16:02 -0800781 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
782 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800783
Jeff Tinker74797f82015-03-31 15:44:34 -0700784 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
785 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
786 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
787 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700788 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
789 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800790 GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
791 gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
Jeff Tinker74797f82015-03-31 15:44:34 -0700792
Jeff Tinker17b89222013-05-21 12:35:06 -0700793 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
794 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
795 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
796 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
797 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
798 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
799
Jeff Tinkere4095a82014-03-04 13:17:11 -0800800 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
801 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
802 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
803 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
804
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800805 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
806 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
807 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
808 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
809 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
810 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
811 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
812 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
813 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
814 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
815 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
816 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800817 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I");
818 gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field);
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800819 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
820 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
821
822 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
823 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700824 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800825 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700826 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800827 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700828 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800829 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700830 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800831 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700832 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800833 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
834
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800835 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I");
Jeff Tinker55d26242018-10-10 16:10:43 -0700836 gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800837 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I");
838 gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field);
Jeff Tinker55d26242018-10-10 16:10:43 -0700839 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
840 gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
841
842 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
843
Jeff Tinker2bca5252018-02-11 18:59:14 +0000844 jmethodID getMaxSecurityLevel;
845 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
846 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
847
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700848 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700849 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
850 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700851 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800852
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700853 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
854 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
855 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
856 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
857 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
858 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
Rahul Frias8f761ba2018-01-22 23:43:54 -0800859 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
860 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
861 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
862 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700863
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800864 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700865 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
866 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800867
Jeff Tinkere4095a82014-03-04 13:17:11 -0800868 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
869 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
870 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700871 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800872
Adam Stone94395c92018-01-30 12:07:00 -0800873 // Metrics-related fields and classes.
874 FIND_CLASS(clazz, "android/os/PersistableBundle");
875 jfieldID bundleCreatorId;
876 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
877 "Landroid/os/Parcelable$Creator;");
878 jobject bundleCreator;
879 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
880 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
881 FIND_CLASS(clazz, "android/os/Parcelable$Creator");
882 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
883 "(Landroid/os/Parcel;)Ljava/lang/Object;");
884 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
885
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800886 FIND_CLASS(clazz, "java/util/ArrayList");
887 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
888 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
889
890 FIND_CLASS(clazz, "java/util/HashMap");
891 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
892 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
893 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
894 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
895 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
896
897 FIND_CLASS(clazz, "java/util/Set");
898 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
899
900 FIND_CLASS(clazz, "java/util/Iterator");
901 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
902 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
903
904 FIND_CLASS(clazz, "java/util/Map$Entry");
905 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
906 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800907
908 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700909 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800910
911 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700912 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800913
914 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700915 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700916
917 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
918 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
919 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker20594d82018-12-12 08:31:22 -0800920
921 FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
922 GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
923 gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
924 GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
925
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800926 GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I");
927 gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800928 GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
929 gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800930
931 FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
932 gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
933 GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
Robert Shih696989f2021-02-12 23:25:16 -0800934
935 FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage");
936 gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
937 GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800938}
939
940static void android_media_MediaDrm_native_setup(
941 JNIEnv *env, jobject thiz,
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800942 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800943
944 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700945 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800946 return;
947 }
948
949 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
950
951 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700952 jniThrowException(env, "java/lang/IllegalArgumentException",
953 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800954 return;
955 }
956
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800957 String8 packageName;
958 if (jappPackageName == NULL) {
959 jniThrowException(env, "java/lang/IllegalArgumentException",
960 "application package name cannot be null");
961 return;
962 }
963
964 packageName = JStringToString8(env, jappPackageName);
965 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800966
967 status_t err = drm->initCheck();
968
969 if (err != OK) {
970 jniThrowException(
971 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700972 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800973 "Failed to instantiate drm object.");
974 return;
975 }
976
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700977 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
978 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800979 setDrm(env, thiz, drm);
980}
981
Jeff Tinkerd571a7c2019-01-17 17:29:30 -0800982DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
983 DrmPlugin::SecurityLevel level;
984
985 if (jlevel == gSecurityLevels.kSecurityLevelMax) {
986 level = DrmPlugin::kSecurityLevelMax;
987 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
988 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
989 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
990 level = DrmPlugin::kSecurityLevelSwSecureDecode;
991 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
992 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
993 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
994 level = DrmPlugin::kSecurityLevelHwSecureDecode;
995 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
996 level = DrmPlugin::kSecurityLevelHwSecureAll;
997 } else {
998 level = DrmPlugin::kSecurityLevelUnknown;
999 }
1000 return level;
1001}
1002
Robert Shihd2e8b432019-11-21 20:27:56 -08001003static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
1004 std::vector<uint8_t> bv;
1005 for (auto &factory : DrmUtils::MakeDrmFactories()) {
1006 sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
1007 if (factoryV1_3 == nullptr) {
1008 continue;
1009 }
1010 factoryV1_3->getSupportedCryptoSchemes(
1011 [&](const hardware::hidl_vec<hardware::hidl_array<uint8_t, 16>>& schemes) {
1012 for (const auto &scheme : schemes) {
1013 bv.insert(bv.end(), scheme.data(), scheme.data() + scheme.size());
1014 }
1015 });
1016 }
1017
1018 jbyteArray jUuidBytes = env->NewByteArray(bv.size());
1019 env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast<const jbyte *>(bv.data()));
1020 return jUuidBytes;
1021}
1022
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001023static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001024 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType,
1025 jint jSecurityLevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001026
1027 if (uuidObj == NULL) {
1028 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1029 return false;
1030 }
1031
1032 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1033
1034 if (uuid.size() != 16) {
1035 jniThrowException(
1036 env,
1037 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -07001038 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001039 return false;
1040 }
1041
Jeff Tinker7cda4912013-08-21 11:52:34 -07001042 String8 mimeType;
1043 if (jmimeType != NULL) {
1044 mimeType = JStringToString8(env, jmimeType);
1045 }
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001046 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
Jeff Tinker7cda4912013-08-21 11:52:34 -07001047
Jeff Tinker5de2e902019-01-25 23:09:36 -08001048 bool isSupported;
1049 status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
1050 securityLevel, &isSupported);
1051
Robert Shih60dab872021-02-13 11:24:59 -08001052 if (throwExceptionAsNecessary(env, NULL, err, "Failed to query crypto scheme support")) {
Jeff Tinker5de2e902019-01-25 23:09:36 -08001053 return false;
1054 }
1055 return isSupported;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001056}
1057
1058static jbyteArray android_media_MediaDrm_openSession(
Jeff Tinker2bca5252018-02-11 18:59:14 +00001059 JNIEnv *env, jobject thiz, jint jlevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001060 sp<IDrm> drm = GetDrm(env, thiz);
1061
Jeff Tinker55d26242018-10-10 16:10:43 -07001062 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001063 return NULL;
1064 }
1065
1066 Vector<uint8_t> sessionId;
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001067 DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel);
1068 if (level == DrmPlugin::kSecurityLevelUnknown) {
Jeff Tinker2bca5252018-02-11 18:59:14 +00001069 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1070 return NULL;
1071 }
1072
1073 status_t err = drm->openSession(level, sessionId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001074
Robert Shih60dab872021-02-13 11:24:59 -08001075 if (throwExceptionAsNecessary(env, drm, err, "Failed to open session")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001076 return NULL;
1077 }
1078
1079 return VectorToJByteArray(env, sessionId);
1080}
1081
1082static void android_media_MediaDrm_closeSession(
1083 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1084 sp<IDrm> drm = GetDrm(env, thiz);
1085
1086 if (!CheckSession(env, drm, jsessionId)) {
1087 return;
1088 }
1089
1090 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1091
1092 status_t err = drm->closeSession(sessionId);
1093
Robert Shih60dab872021-02-13 11:24:59 -08001094 throwExceptionAsNecessary(env, drm, err, "Failed to close session");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001095}
1096
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001097static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001098 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001099 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001100 sp<IDrm> drm = GetDrm(env, thiz);
1101
1102 if (!CheckSession(env, drm, jsessionId)) {
1103 return NULL;
1104 }
1105
1106 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1107
1108 Vector<uint8_t> initData;
1109 if (jinitData != NULL) {
1110 initData = JByteArrayToVector(env, jinitData);
1111 }
1112
1113 String8 mimeType;
1114 if (jmimeType != NULL) {
1115 mimeType = JStringToString8(env, jmimeType);
1116 }
1117
Jeff Tinker17b89222013-05-21 12:35:06 -07001118 DrmPlugin::KeyType keyType;
1119 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
1120 keyType = DrmPlugin::kKeyType_Streaming;
1121 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
1122 keyType = DrmPlugin::kKeyType_Offline;
1123 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
1124 keyType = DrmPlugin::kKeyType_Release;
1125 } else {
1126 jniThrowException(env, "java/lang/IllegalArgumentException",
1127 "invalid keyType");
1128 return NULL;
1129 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001130
1131 KeyedVector<String8, String8> optParams;
1132 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +02001133 bool isOK;
1134 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
1135 if (!isOK) {
1136 return NULL;
1137 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001138 }
1139
1140 Vector<uint8_t> request;
1141 String8 defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001142 DrmPlugin::KeyRequestType keyRequestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001143
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001144 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001145 keyType, optParams, request, defaultUrl, &keyRequestType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001146
Robert Shih60dab872021-02-13 11:24:59 -08001147 if (throwExceptionAsNecessary(env, drm, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001148 return NULL;
1149 }
1150
1151 // Fill out return obj
1152 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001153 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001154
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001155 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001156
1157 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001158 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001159 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001160 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001161
1162 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001163 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001164
1165 switch (keyRequestType) {
1166 case DrmPlugin::kKeyRequestType_Initial:
1167 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1168 gKeyRequestTypes.kKeyRequestTypeInitial);
1169 break;
1170 case DrmPlugin::kKeyRequestType_Renewal:
1171 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1172 gKeyRequestTypes.kKeyRequestTypeRenewal);
1173 break;
1174 case DrmPlugin::kKeyRequestType_Release:
1175 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1176 gKeyRequestTypes.kKeyRequestTypeRelease);
1177 break;
Rahul Frias8f761ba2018-01-22 23:43:54 -08001178 case DrmPlugin::kKeyRequestType_None:
1179 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1180 gKeyRequestTypes.kKeyRequestTypeNone);
1181 break;
1182 case DrmPlugin::kKeyRequestType_Update:
1183 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1184 gKeyRequestTypes.kKeyRequestTypeUpdate);
1185 break;
1186
Jeff Tinker74797f82015-03-31 15:44:34 -07001187 default:
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001188 throwStateException(env, "DRM plugin failure: unknown key request type",
1189 ERROR_DRM_UNKNOWN);
1190 break;
1191 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001192 }
1193
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001194 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001195}
1196
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001197static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001198 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
1199 sp<IDrm> drm = GetDrm(env, thiz);
1200
1201 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001202 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001203 }
1204
1205 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1206
1207 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001208 jniThrowException(env, "java/lang/IllegalArgumentException",
1209 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001210 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001211 }
1212 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001213 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001214
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001215 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001216
Robert Shih60dab872021-02-13 11:24:59 -08001217 if (throwExceptionAsNecessary(env, drm, err, "Failed to handle key response")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001218 return NULL;
1219 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001220 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001221}
1222
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001223static void android_media_MediaDrm_removeKeys(
1224 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
1225 sp<IDrm> drm = GetDrm(env, thiz);
1226
Jeff Tinker55d26242018-10-10 16:10:43 -07001227 if (!CheckDrm(env, drm)) {
1228 return;
1229 }
1230
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001231 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001232 jniThrowException(env, "java/lang/IllegalArgumentException",
1233 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001234 return;
1235 }
1236
1237 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1238
1239 status_t err = drm->removeKeys(keySetId);
1240
Robert Shih60dab872021-02-13 11:24:59 -08001241 throwExceptionAsNecessary(env, drm, err, "Failed to remove keys");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001242}
1243
1244static void android_media_MediaDrm_restoreKeys(
1245 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
1246 jbyteArray jkeysetId) {
1247
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001248 sp<IDrm> drm = GetDrm(env, thiz);
1249
1250 if (!CheckSession(env, drm, jsessionId)) {
1251 return;
1252 }
1253
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001254 if (jkeysetId == NULL) {
1255 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1256 return;
1257 }
1258
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001259 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001260 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001261
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001262 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001263
Robert Shih60dab872021-02-13 11:24:59 -08001264 throwExceptionAsNecessary(env, drm, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001265}
1266
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001267static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001268 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1269 sp<IDrm> drm = GetDrm(env, thiz);
1270
1271 if (!CheckSession(env, drm, jsessionId)) {
1272 return NULL;
1273 }
1274 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1275
1276 KeyedVector<String8, String8> infoMap;
1277
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001278 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001279
Robert Shih60dab872021-02-13 11:24:59 -08001280 if (throwExceptionAsNecessary(env, drm, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001281 return NULL;
1282 }
1283
1284 return KeyedVectorToHashMap(env, infoMap);
1285}
1286
Jeff Tinkere4095a82014-03-04 13:17:11 -08001287static jobject android_media_MediaDrm_getProvisionRequestNative(
1288 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001289 sp<IDrm> drm = GetDrm(env, thiz);
1290
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001291 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001292 return NULL;
1293 }
1294
1295 Vector<uint8_t> request;
1296 String8 defaultUrl;
1297
Jeff Tinkere4095a82014-03-04 13:17:11 -08001298 String8 certType;
1299 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1300 certType = "X.509";
1301 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1302 certType = "none";
1303 } else {
1304 certType = "invalid";
1305 }
1306
1307 String8 certAuthority = JStringToString8(env, jcertAuthority);
1308 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001309
Robert Shih60dab872021-02-13 11:24:59 -08001310 if (throwExceptionAsNecessary(env, drm, err, "Failed to get provision request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001311 return NULL;
1312 }
1313
1314 // Fill out return obj
1315 jclass clazz;
1316 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1317
1318 jobject provisionObj = NULL;
1319
1320 if (clazz) {
1321 provisionObj = env->AllocObject(clazz);
1322 jbyteArray jrequest = VectorToJByteArray(env, request);
1323 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1324
1325 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1326 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1327 }
1328
1329 return provisionObj;
1330}
1331
Jeff Tinkere4095a82014-03-04 13:17:11 -08001332static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001333 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1334 sp<IDrm> drm = GetDrm(env, thiz);
1335
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001336 if (!CheckDrm(env, drm)) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001337 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001338 }
1339
1340 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001341 jniThrowException(env, "java/lang/IllegalArgumentException",
1342 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001343 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001344 }
1345
1346 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -08001347 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001348
Jeff Tinkere4095a82014-03-04 13:17:11 -08001349 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1350
1351 // Fill out return obj
1352 jclass clazz = gFields.certificateClassId;
1353
1354 jobject certificateObj = NULL;
1355
1356 if (clazz && certificate.size() && wrappedKey.size()) {
1357 certificateObj = env->AllocObject(clazz);
1358 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1359 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1360
1361 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1362 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1363 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001364
Robert Shih60dab872021-02-13 11:24:59 -08001365 throwExceptionAsNecessary(env, drm, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001366 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001367}
1368
1369static jobject android_media_MediaDrm_getSecureStops(
1370 JNIEnv *env, jobject thiz) {
1371 sp<IDrm> drm = GetDrm(env, thiz);
1372
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001373 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001374 return NULL;
1375 }
1376
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001377 List<Vector<uint8_t>> secureStops;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001378
1379 status_t err = drm->getSecureStops(secureStops);
1380
Robert Shih60dab872021-02-13 11:24:59 -08001381 if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stops")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001382 return NULL;
1383 }
1384
1385 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1386}
1387
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001388static jobject android_media_MediaDrm_getSecureStopIds(
1389 JNIEnv *env, jobject thiz) {
1390 sp<IDrm> drm = GetDrm(env, thiz);
1391
Jeff Tinker55d26242018-10-10 16:10:43 -07001392 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001393 return NULL;
1394 }
1395
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001396 List<Vector<uint8_t>> secureStopIds;
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001397
1398 status_t err = drm->getSecureStopIds(secureStopIds);
1399
Robert Shih60dab872021-02-13 11:24:59 -08001400 if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop Ids")) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001401 return NULL;
1402 }
1403
1404 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1405}
1406
Jeff Tinker1b51c722014-10-31 00:54:26 -07001407static jbyteArray android_media_MediaDrm_getSecureStop(
1408 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1409 sp<IDrm> drm = GetDrm(env, thiz);
1410
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001411 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001412 return NULL;
1413 }
1414
1415 Vector<uint8_t> secureStop;
1416
1417 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1418
Robert Shih60dab872021-02-13 11:24:59 -08001419 if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop")) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001420 return NULL;
1421 }
1422
1423 return VectorToJByteArray(env, secureStop);
1424}
1425
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001426static void android_media_MediaDrm_releaseSecureStops(
1427 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1428 sp<IDrm> drm = GetDrm(env, thiz);
1429
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001430 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001431 return;
1432 }
1433
1434 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1435
1436 status_t err = drm->releaseSecureStops(ssRelease);
1437
Robert Shih60dab872021-02-13 11:24:59 -08001438 throwExceptionAsNecessary(env, drm, err, "Failed to release secure stops");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001439}
1440
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001441static void android_media_MediaDrm_removeSecureStop(
1442 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1443 sp<IDrm> drm = GetDrm(env, thiz);
1444
Jeff Tinker55d26242018-10-10 16:10:43 -07001445 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001446 return;
1447 }
1448
1449 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1450
Robert Shih60dab872021-02-13 11:24:59 -08001451 throwExceptionAsNecessary(env, drm, err, "Failed to remove secure stop");
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001452}
1453
1454static void android_media_MediaDrm_removeAllSecureStops(
Jeff Tinker1b51c722014-10-31 00:54:26 -07001455 JNIEnv *env, jobject thiz) {
1456 sp<IDrm> drm = GetDrm(env, thiz);
1457
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001458 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001459 return;
1460 }
1461
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001462 status_t err = drm->removeAllSecureStops();
Jeff Tinker1b51c722014-10-31 00:54:26 -07001463
Robert Shih60dab872021-02-13 11:24:59 -08001464 throwExceptionAsNecessary(env, drm, err, "Failed to remove all secure stops");
Jeff Tinker1b51c722014-10-31 00:54:26 -07001465}
1466
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001467
1468static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1469 switch(level) {
1470 case DrmPlugin::kHdcpLevelUnknown:
1471 return gHdcpLevels.kHdcpLevelUnknown;
1472 case DrmPlugin::kHdcpNone:
1473 return gHdcpLevels.kHdcpNone;
1474 case DrmPlugin::kHdcpV1:
1475 return gHdcpLevels.kHdcpV1;
1476 case DrmPlugin::kHdcpV2:
1477 return gHdcpLevels.kHdcpV2;
1478 case DrmPlugin::kHdcpV2_1:
1479 return gHdcpLevels.kHdcpV2_1;
1480 case DrmPlugin::kHdcpV2_2:
1481 return gHdcpLevels.kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -08001482 case DrmPlugin::kHdcpV2_3:
1483 return gHdcpLevels.kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001484 case DrmPlugin::kHdcpNoOutput:
1485 return gHdcpLevels.kHdcpNoOutput;
1486 }
1487 return gHdcpLevels.kHdcpNone;
1488}
1489
1490static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1491 jobject thiz) {
1492 sp<IDrm> drm = GetDrm(env, thiz);
1493
1494 if (!CheckDrm(env, drm)) {
1495 return gHdcpLevels.kHdcpNone;
1496 }
1497
1498 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1499 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1500
1501 status_t err = drm->getHdcpLevels(&connected, &max);
1502
Robert Shih60dab872021-02-13 11:24:59 -08001503 if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001504 return gHdcpLevels.kHdcpLevelUnknown;
1505 }
1506 return HdcpLevelTojint(connected);
1507}
1508
1509static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1510 jobject thiz) {
1511 sp<IDrm> drm = GetDrm(env, thiz);
1512
1513 if (!CheckDrm(env, drm)) {
1514 return gHdcpLevels.kHdcpLevelUnknown;
1515 }
1516
1517 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1518 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1519
1520 status_t err = drm->getHdcpLevels(&connected, &max);
1521
Robert Shih60dab872021-02-13 11:24:59 -08001522 if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001523 return gHdcpLevels.kHdcpLevelUnknown;
1524 }
1525 return HdcpLevelTojint(max);
1526}
1527
1528static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1529 jobject thiz) {
1530 sp<IDrm> drm = GetDrm(env, thiz);
1531
1532 if (!CheckDrm(env, drm)) {
1533 return 0;
1534 }
1535
1536 uint32_t open = 0, max = 0;
1537 status_t err = drm->getNumberOfSessions(&open, &max);
1538
Robert Shih60dab872021-02-13 11:24:59 -08001539 if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001540 return 0;
1541 }
1542 return open;
1543}
1544
1545static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1546 jobject thiz) {
1547 sp<IDrm> drm = GetDrm(env, thiz);
1548
1549 if (!CheckDrm(env, drm)) {
1550 return 0;
1551 }
1552
1553 uint32_t open = 0, max = 0;
1554 status_t err = drm->getNumberOfSessions(&open, &max);
1555
Robert Shih60dab872021-02-13 11:24:59 -08001556 if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001557 return 0;
1558 }
1559 return max;
1560}
1561
1562static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1563 jobject thiz, jbyteArray jsessionId) {
1564 sp<IDrm> drm = GetDrm(env, thiz);
1565
1566 if (!CheckSession(env, drm, jsessionId)) {
1567 return gSecurityLevels.kSecurityLevelUnknown;
1568 }
1569
1570 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1571
1572 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1573
1574 status_t err = drm->getSecurityLevel(sessionId, &level);
1575
Robert Shih60dab872021-02-13 11:24:59 -08001576 if (throwExceptionAsNecessary(env, drm, err, "Failed to get security level")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001577 return gSecurityLevels.kSecurityLevelUnknown;
1578 }
1579
1580 switch(level) {
1581 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1582 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1583 case DrmPlugin::kSecurityLevelSwSecureDecode:
1584 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1585 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1586 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1587 case DrmPlugin::kSecurityLevelHwSecureDecode:
1588 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1589 case DrmPlugin::kSecurityLevelHwSecureAll:
1590 return gSecurityLevels.kSecurityLevelHwSecureAll;
1591 default:
1592 return gSecurityLevels.kSecurityLevelUnknown;
1593 }
1594}
1595
Jeff Tinker55d26242018-10-10 16:10:43 -07001596static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
1597 JNIEnv *env, jobject thiz) {
1598 sp<IDrm> drm = GetDrm(env, thiz);
1599
1600 if (!CheckDrm(env, drm)) {
1601 return NULL;
1602 }
1603
1604 List<Vector<uint8_t> > keySetIds;
1605
1606 status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
1607
Robert Shih60dab872021-02-13 11:24:59 -08001608 if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline key set Ids")) {
Jeff Tinker55d26242018-10-10 16:10:43 -07001609 return NULL;
1610 }
1611
1612 return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
1613}
1614
1615static void android_media_MediaDrm_removeOfflineLicense(
1616 JNIEnv *env, jobject thiz, jbyteArray keySetId) {
1617 sp<IDrm> drm = GetDrm(env, thiz);
1618
1619 if (!CheckDrm(env, drm)) {
1620 return;
1621 }
1622
1623 status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
1624
Robert Shih60dab872021-02-13 11:24:59 -08001625 throwExceptionAsNecessary(env, drm, err, "Failed to remove offline license");
Jeff Tinker55d26242018-10-10 16:10:43 -07001626}
1627
1628static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
1629 jobject thiz, jbyteArray jkeySetId) {
1630 sp<IDrm> drm = GetDrm(env, thiz);
1631
1632 if (!CheckDrm(env, drm)) {
1633 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1634 }
1635
1636 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
1637
1638 DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
1639
1640 status_t err = drm->getOfflineLicenseState(keySetId, &state);
1641
Robert Shih60dab872021-02-13 11:24:59 -08001642 if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline license state")) {
Jeff Tinker55d26242018-10-10 16:10:43 -07001643 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1644 }
1645
1646 switch(state) {
1647 case DrmPlugin::kOfflineLicenseStateUsable:
1648 return gOfflineLicenseStates.kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -08001649 case DrmPlugin::kOfflineLicenseStateReleased:
1650 return gOfflineLicenseStates.kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -07001651 default:
1652 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1653 }
1654}
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001655
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001656static jstring android_media_MediaDrm_getPropertyString(
1657 JNIEnv *env, jobject thiz, jstring jname) {
1658 sp<IDrm> drm = GetDrm(env, thiz);
1659
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001660 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001661 return NULL;
1662 }
1663
1664 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001665 jniThrowException(env, "java/lang/IllegalArgumentException",
1666 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001667 return NULL;
1668 }
1669
1670 String8 name = JStringToString8(env, jname);
1671 String8 value;
1672
1673 status_t err = drm->getPropertyString(name, value);
1674
Robert Shih60dab872021-02-13 11:24:59 -08001675 if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001676 return NULL;
1677 }
1678
1679 return env->NewStringUTF(value.string());
1680}
1681
1682static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1683 JNIEnv *env, jobject thiz, jstring jname) {
1684 sp<IDrm> drm = GetDrm(env, thiz);
1685
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001686 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001687 return NULL;
1688 }
1689
1690 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001691 jniThrowException(env, "java/lang/IllegalArgumentException",
1692 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001693 return NULL;
1694 }
1695
1696 String8 name = JStringToString8(env, jname);
1697 Vector<uint8_t> value;
1698
1699 status_t err = drm->getPropertyByteArray(name, value);
1700
Robert Shih60dab872021-02-13 11:24:59 -08001701 if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001702 return NULL;
1703 }
1704
1705 return VectorToJByteArray(env, value);
1706}
1707
1708static void android_media_MediaDrm_setPropertyString(
1709 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1710 sp<IDrm> drm = GetDrm(env, thiz);
1711
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001712 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001713 return;
1714 }
1715
Jeff Tinkereada5372013-05-21 12:48:14 -07001716 if (jname == NULL) {
1717 jniThrowException(env, "java/lang/IllegalArgumentException",
1718 "property name String is null");
1719 return;
1720 }
1721
1722 if (jvalue == NULL) {
1723 jniThrowException(env, "java/lang/IllegalArgumentException",
1724 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001725 return;
1726 }
1727
1728 String8 name = JStringToString8(env, jname);
1729 String8 value = JStringToString8(env, jvalue);
1730
1731 status_t err = drm->setPropertyString(name, value);
1732
Robert Shih60dab872021-02-13 11:24:59 -08001733 throwExceptionAsNecessary(env, drm, err, "Failed to set property");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001734}
1735
1736static void android_media_MediaDrm_setPropertyByteArray(
1737 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1738 sp<IDrm> drm = GetDrm(env, thiz);
1739
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001740 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001741 return;
1742 }
1743
Jeff Tinkereada5372013-05-21 12:48:14 -07001744 if (jname == NULL) {
1745 jniThrowException(env, "java/lang/IllegalArgumentException",
1746 "property name String is null");
1747 return;
1748 }
1749
1750 if (jvalue == NULL) {
1751 jniThrowException(env, "java/lang/IllegalArgumentException",
1752 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001753 return;
1754 }
1755
1756 String8 name = JStringToString8(env, jname);
1757 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1758
1759 status_t err = drm->setPropertyByteArray(name, value);
1760
Robert Shih60dab872021-02-13 11:24:59 -08001761 throwExceptionAsNecessary(env, drm, err, "Failed to set property");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001762}
1763
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001764static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001765 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001766 jstring jalgorithm) {
1767
1768 sp<IDrm> drm = GetDrm(env, jdrm);
1769
1770 if (!CheckSession(env, drm, jsessionId)) {
1771 return;
1772 }
1773
1774 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001775 jniThrowException(env, "java/lang/IllegalArgumentException",
1776 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001777 return;
1778 }
1779
1780 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1781 String8 algorithm = JStringToString8(env, jalgorithm);
1782
1783 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1784
Robert Shih60dab872021-02-13 11:24:59 -08001785 throwExceptionAsNecessary(env, drm, err, "Failed to set cipher algorithm");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001786}
1787
1788static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001789 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001790 jstring jalgorithm) {
1791
1792 sp<IDrm> drm = GetDrm(env, jdrm);
1793
1794 if (!CheckSession(env, drm, jsessionId)) {
1795 return;
1796 }
1797
1798 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001799 jniThrowException(env, "java/lang/IllegalArgumentException",
1800 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001801 return;
1802 }
1803
1804 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1805 String8 algorithm = JStringToString8(env, jalgorithm);
1806
1807 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1808
Robert Shih60dab872021-02-13 11:24:59 -08001809 throwExceptionAsNecessary(env, drm, err, "Failed to set mac algorithm");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001810}
1811
1812
1813static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001814 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001815 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1816
1817 sp<IDrm> drm = GetDrm(env, jdrm);
1818
1819 if (!CheckSession(env, drm, jsessionId)) {
1820 return NULL;
1821 }
1822
1823 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001824 jniThrowException(env, "java/lang/IllegalArgumentException",
1825 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001826 return NULL;
1827 }
1828
1829 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1830 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1831 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1832 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1833 Vector<uint8_t> output;
1834
1835 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1836
Robert Shih60dab872021-02-13 11:24:59 -08001837 if (throwExceptionAsNecessary(env, drm, err, "Failed to encrypt")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001838 return NULL;
1839 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001840
1841 return VectorToJByteArray(env, output);
1842}
1843
1844static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001845 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001846 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1847
1848 sp<IDrm> drm = GetDrm(env, jdrm);
1849
1850 if (!CheckSession(env, drm, jsessionId)) {
1851 return NULL;
1852 }
1853
1854 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001855 jniThrowException(env, "java/lang/IllegalArgumentException",
1856 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001857 return NULL;
1858 }
1859
1860 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1861 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1862 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1863 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1864 Vector<uint8_t> output;
1865
1866 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Robert Shih60dab872021-02-13 11:24:59 -08001867 if (throwExceptionAsNecessary(env, drm, err, "Failed to decrypt")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001868 return NULL;
1869 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001870
1871 return VectorToJByteArray(env, output);
1872}
1873
1874static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001875 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001876 jbyteArray jkeyId, jbyteArray jmessage) {
1877
1878 sp<IDrm> drm = GetDrm(env, jdrm);
1879
1880 if (!CheckSession(env, drm, jsessionId)) {
1881 return NULL;
1882 }
1883
1884 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001885 jniThrowException(env, "java/lang/IllegalArgumentException",
1886 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001887 return NULL;
1888 }
1889
1890 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1891 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1892 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1893 Vector<uint8_t> signature;
1894
1895 status_t err = drm->sign(sessionId, keyId, message, signature);
1896
Robert Shih60dab872021-02-13 11:24:59 -08001897 if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001898 return NULL;
1899 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001900
1901 return VectorToJByteArray(env, signature);
1902}
1903
1904static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001905 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001906 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1907
1908 sp<IDrm> drm = GetDrm(env, jdrm);
1909
1910 if (!CheckSession(env, drm, jsessionId)) {
1911 return false;
1912 }
1913
1914 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001915 jniThrowException(env, "java/lang/IllegalArgumentException",
1916 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001917 return false;
1918 }
1919
1920 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1921 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1922 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1923 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1924 bool match;
1925
1926 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1927
Robert Shih60dab872021-02-13 11:24:59 -08001928 throwExceptionAsNecessary(env, drm, err, "Failed to verify");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001929 return match;
1930}
1931
Adam Stonec06e10e2017-12-19 12:54:33 -08001932static jobject
1933android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1934{
1935 sp<IDrm> drm = GetDrm(env, thiz);
Jeff Tinker55d26242018-10-10 16:10:43 -07001936
1937 if (!CheckDrm(env, drm)) {
Adam Stonec06e10e2017-12-19 12:54:33 -08001938 return NULL;
1939 }
1940
1941 // Retrieve current metrics snapshot from drm.
Adam Stone94395c92018-01-30 12:07:00 -08001942 PersistableBundle metrics;
Robert Shihba6777e2019-11-12 13:04:59 -08001943 sp<IDrmMetricsConsumer> consumer(new DrmMetricsConsumer(&metrics));
1944 status_t err = drm->getMetrics(consumer);
Adam Stonec06e10e2017-12-19 12:54:33 -08001945 if (err != OK) {
1946 ALOGE("getMetrics failed: %d", (int)err);
1947 return (jobject) NULL;
1948 }
1949
Robert Shih4354a962019-11-10 12:09:08 -08001950 return MediaMetricsJNI::nativeToJavaPersistableBundle(env, &metrics);
Adam Stonec06e10e2017-12-19 12:54:33 -08001951}
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001952
Jeff Tinkere4095a82014-03-04 13:17:11 -08001953static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001954 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001955 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1956
1957 sp<IDrm> drm = GetDrm(env, jdrm);
1958
1959 if (!CheckSession(env, drm, jsessionId)) {
1960 return NULL;
1961 }
1962
1963 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1964 jniThrowException(env, "java/lang/IllegalArgumentException",
1965 "required argument is null");
1966 return NULL;
1967 }
1968
1969 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1970 String8 algorithm = JStringToString8(env, jalgorithm);
1971 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1972 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1973 Vector<uint8_t> signature;
1974
1975 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1976
Robert Shih60dab872021-02-13 11:24:59 -08001977 if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001978 return NULL;
1979 }
1980
1981 return VectorToJByteArray(env, signature);
1982}
1983
Robert Shih205f7a92021-01-19 21:12:10 -08001984static jboolean android_media_MediaDrm_requiresSecureDecoder(
1985 JNIEnv *env, jobject thiz, jstring jmimeType,
1986 jint jSecurityLevel) {
1987 sp<IDrm> drm = GetDrm(env, thiz);
1988 if (!CheckDrm(env, drm)) {
1989 return JNI_FALSE;
1990 }
1991
1992 String8 mimeType;
1993 if (jmimeType != NULL) {
1994 mimeType = JStringToString8(env, jmimeType);
1995 }
1996
1997 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
1998 if (securityLevel == DrmPlugin::kSecurityLevelUnknown) {
1999 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
2000 return JNI_FALSE;
2001 }
2002
2003 if (securityLevel == DrmPlugin::kSecurityLevelMax) {
2004 return drm->requiresSecureDecoder(mimeType.c_str());
2005 }
2006 return drm->requiresSecureDecoder(mimeType.c_str(), securityLevel);
2007}
Jeff Tinkere4095a82014-03-04 13:17:11 -08002008
Robert Shih02937122021-01-20 00:05:20 -08002009static void android_media_MediaDrm_setPlaybackId(
2010 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
2011 jstring jplaybackId) {
2012 sp<IDrm> drm = GetDrm(env, thiz);
2013 if (!CheckSession(env, drm, jsessionId)) {
2014 return;
2015 }
2016
2017 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
2018
2019 String8 playbackId;
2020 if (jplaybackId != NULL) {
2021 playbackId = JStringToString8(env, jplaybackId);
2022 }
2023 status_t err = drm->setPlaybackId(sessionId, playbackId.c_str());
Robert Shih60dab872021-02-13 11:24:59 -08002024 throwExceptionAsNecessary(env, drm, err, "Failed to set playbackId");
Robert Shih02937122021-01-20 00:05:20 -08002025}
2026
Robert Shih696989f2021-02-12 23:25:16 -08002027static jobject android_media_MediaDrm_getLogMessages(
2028 JNIEnv *env, jobject thiz) {
2029 sp<IDrm> drm = GetDrm(env, thiz);
2030 if (!CheckDrm(env, drm)) {
2031 return NULL;
2032 }
2033
2034 Vector<drm::V1_4::LogMessage> logs;
2035 status_t err = drm->getLogMessages(logs);
2036 ALOGI("drm->getLogMessages %zu logs", logs.size());
Robert Shih60dab872021-02-13 11:24:59 -08002037 if (throwExceptionAsNecessary(env, drm, err, "Failed to get log messages")) {
Robert Shih696989f2021-02-12 23:25:16 -08002038 return NULL;
2039 }
2040 return hidlLogMessagesToJavaList(env, logs);
2041}
2042
Daniel Micay76f6a862015-09-19 17:31:01 -04002043static const JNINativeMethod gMethods[] = {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002044 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
2045
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002046 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
2047
Edwin Wong4d1d84e2017-01-04 09:37:49 -08002048 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002049 (void *)android_media_MediaDrm_native_setup },
2050
Robert Shihd2e8b432019-11-21 20:27:56 -08002051 { "getSupportedCryptoSchemesNative", "()[B",
2052 (void *)android_media_MediaDrm_getSupportedCryptoSchemesNative },
2053
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08002054 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002055 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
2056
Robert Shih02937122021-01-20 00:05:20 -08002057 { "openSessionNative", "(I)[B",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002058 (void *)android_media_MediaDrm_openSession },
2059
Robert Shih02937122021-01-20 00:05:20 -08002060 { "closeSessionNative", "([B)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002061 (void *)android_media_MediaDrm_closeSession },
2062
Robert Shih890eb572021-01-19 08:16:39 -08002063 { "getKeyRequestNative", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002064 "Landroid/media/MediaDrm$KeyRequest;",
2065 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002066
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002067 { "provideKeyResponse", "([B[B)[B",
2068 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002069
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002070 { "removeKeys", "([B)V",
2071 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002072
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002073 { "restoreKeys", "([B[B)V",
2074 (void *)android_media_MediaDrm_restoreKeys },
2075
2076 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
2077 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002078
Jeff Tinkere4095a82014-03-04 13:17:11 -08002079 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
2080 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002081
Jeff Tinkere4095a82014-03-04 13:17:11 -08002082 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
2083 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002084
2085 { "getSecureStops", "()Ljava/util/List;",
2086 (void *)android_media_MediaDrm_getSecureStops },
2087
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002088 { "getSecureStopIds", "()Ljava/util/List;",
2089 (void *)android_media_MediaDrm_getSecureStopIds },
2090
Jeff Tinker1b51c722014-10-31 00:54:26 -07002091 { "getSecureStop", "([B)[B",
2092 (void *)android_media_MediaDrm_getSecureStop },
2093
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002094 { "releaseSecureStops", "([B)V",
2095 (void *)android_media_MediaDrm_releaseSecureStops },
2096
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002097 { "removeSecureStop", "([B)V",
2098 (void *)android_media_MediaDrm_removeSecureStop },
2099
2100 { "removeAllSecureStops", "()V",
2101 (void *)android_media_MediaDrm_removeAllSecureStops },
Jeff Tinker1b51c722014-10-31 00:54:26 -07002102
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002103 { "getConnectedHdcpLevel", "()I",
2104 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
2105
2106 { "getMaxHdcpLevel", "()I",
2107 (void *)android_media_MediaDrm_getMaxHdcpLevel },
2108
2109 { "getOpenSessionCount", "()I",
2110 (void *)android_media_MediaDrm_getOpenSessionCount },
2111
2112 { "getMaxSessionCount", "()I",
2113 (void *)android_media_MediaDrm_getMaxSessionCount },
2114
2115 { "getSecurityLevel", "([B)I",
2116 (void *)android_media_MediaDrm_getSecurityLevel },
2117
Jeff Tinker55d26242018-10-10 16:10:43 -07002118 { "removeOfflineLicense", "([B)V",
2119 (void *)android_media_MediaDrm_removeOfflineLicense },
2120
2121 { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
2122 (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
2123
2124 { "getOfflineLicenseState", "([B)I",
2125 (void *)android_media_MediaDrm_getOfflineLicenseState },
2126
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002127 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
2128 (void *)android_media_MediaDrm_getPropertyString },
2129
2130 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
2131 (void *)android_media_MediaDrm_getPropertyByteArray },
2132
2133 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
2134 (void *)android_media_MediaDrm_setPropertyString },
2135
2136 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
2137 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002138
2139 { "setCipherAlgorithmNative",
2140 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2141 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
2142
2143 { "setMacAlgorithmNative",
2144 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2145 (void *)android_media_MediaDrm_setMacAlgorithmNative },
2146
2147 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2148 (void *)android_media_MediaDrm_encryptNative },
2149
2150 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2151 (void *)android_media_MediaDrm_decryptNative },
2152
2153 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
2154 (void *)android_media_MediaDrm_signNative },
2155
2156 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
2157 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08002158
2159 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
2160 (void *)android_media_MediaDrm_signRSANative },
Adam Stonec06e10e2017-12-19 12:54:33 -08002161
2162 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
2163 (void *)android_media_MediaDrm_native_getMetrics },
Robert Shih205f7a92021-01-19 21:12:10 -08002164
2165 { "requiresSecureDecoder", "(Ljava/lang/String;I)Z",
2166 (void *)android_media_MediaDrm_requiresSecureDecoder },
Robert Shih02937122021-01-20 00:05:20 -08002167
2168 { "setPlaybackId", "([BLjava/lang/String;)V",
2169 (void *)android_media_MediaDrm_setPlaybackId },
Robert Shih696989f2021-02-12 23:25:16 -08002170
2171 { "getLogMessages", "()Ljava/util/List;",
2172 (void *)android_media_MediaDrm_getLogMessages },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002173};
2174
2175int register_android_media_Drm(JNIEnv *env) {
2176 return AndroidRuntime::registerNativeMethods(env,
2177 "android/media/MediaDrm", gMethods, NELEM(gMethods));
2178}