blob: 4eada35983c5348ccbc33f8b4e433f4e67636590 [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);
Robert Shiha37ae8e2021-03-03 03:35:12 -0800379 STATUS_CASE(ERROR_DRM_PROVISIONING_REQUEST_REJECTED);
Robert Shih620f4a62021-02-15 03:28:42 -0800380 STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
381 STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
382 STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
383 STATUS_CASE(ERROR_DRM_STORAGE_READ);
384 STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
385 STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
386#undef STATUS_CASE
387 }
388 return static_cast<jint>(err);
389}
390
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700391static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
392 ALOGE("Illegal state exception: %s (%d)", msg, err);
393
Robert Shih620f4a62021-02-15 03:28:42 -0800394 jint jerr = MediaErrorToJavaError(err);
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700395 jobject exception = env->NewObject(gFields.stateException.classId,
Robert Shih620f4a62021-02-15 03:28:42 -0800396 gFields.stateException.init, static_cast<int>(jerr),
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700397 env->NewStringUTF(msg));
398 env->Throw(static_cast<jthrowable>(exception));
399}
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700400
Jeff Tinker20594d82018-12-12 08:31:22 -0800401static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
402 ALOGE("Session exception: %s (%d)", msg, err);
403
404 jint jErrorCode = 0;
405 switch(err) {
406 case ERROR_DRM_RESOURCE_CONTENTION:
407 jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
408 break;
409 default:
410 break;
411 }
412
413 jobject exception = env->NewObject(gFields.sessionException.classId,
414 gFields.sessionException.init, static_cast<int>(err),
415 env->NewStringUTF(msg));
416
417 env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
418 env->Throw(static_cast<jthrowable>(exception));
419}
420
421static bool isSessionException(status_t err) {
422 return err == ERROR_DRM_RESOURCE_CONTENTION;
423}
424
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800425static bool throwExceptionAsNecessary(
Robert Shih60dab872021-02-13 11:24:59 -0800426 JNIEnv *env, const sp<IDrm> &drm, status_t err, const char *msg = NULL) {
427 std::string msgStr;
Robert Shih13eb27b2021-02-20 00:08:16 -0800428 if (drm != NULL && err != OK) {
Robert Shih60dab872021-02-13 11:24:59 -0800429 msgStr = DrmUtils::GetExceptionMessage(err, msg, drm);
430 msg = msgStr.c_str();
Jeff Tinkerf7568b52013-04-17 14:24:40 -0700431 }
432
Jeff Tinkereb13c762017-11-01 15:29:38 -0700433 if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800434 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
435 return true;
Jeff Tinker5de2e902019-01-25 23:09:36 -0800436 } else if (err == ERROR_UNSUPPORTED) {
437 jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
438 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700439 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
440 jniThrowException(env, "android/media/NotProvisionedException", msg);
441 return true;
Jeff Tinker3ed38262013-08-02 23:24:51 -0700442 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
443 jniThrowException(env, "android/media/ResourceBusyException", msg);
444 return true;
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700445 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
446 jniThrowException(env, "android/media/DeniedByServerException", msg);
447 return true;
Jeff Tinker314b7f32015-06-15 17:45:43 -0700448 } else if (err == DEAD_OBJECT) {
449 jniThrowException(env, "android/media/MediaDrmResetException",
450 "mediaserver died");
451 return true;
Jeff Tinker20594d82018-12-12 08:31:22 -0800452 } else if (isSessionException(err)) {
453 throwSessionException(env, msg, err);
454 return true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800455 } else if (err != OK) {
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700456 throwStateException(env, msg, err);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800457 return true;
458 }
459 return false;
460}
461
462static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000463 JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800464 return jdrm ? jdrm->getDrm() : NULL;
465}
466
467JDrm::JDrm(
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800468 JNIEnv *env, jobject thiz, const uint8_t uuid[16],
469 const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800470 mObject = env->NewWeakGlobalRef(thiz);
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800471 mDrm = MakeDrm(uuid, appPackageName);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700472 if (mDrm != NULL) {
473 mDrm->setListener(this);
474 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800475}
476
477JDrm::~JDrm() {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800478 JNIEnv *env = AndroidRuntime::getJNIEnv();
479
480 env->DeleteWeakGlobalRef(mObject);
481 mObject = NULL;
482}
483
484// static
485sp<IDrm> JDrm::MakeDrm() {
Robert Shih218b9532019-08-15 14:48:11 -0700486 return DrmUtils::MakeDrm();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800487}
488
489// static
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800490sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16], const String8 &appPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800491 sp<IDrm> drm = MakeDrm();
492
493 if (drm == NULL) {
494 return NULL;
495 }
496
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800497 status_t err = drm->createPlugin(uuid, appPackageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800498
499 if (err != OK) {
500 return NULL;
501 }
502
503 return drm;
504}
505
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700506status_t JDrm::setListener(const sp<DrmListener>& listener) {
507 Mutex::Autolock lock(mLock);
508 mListener = listener;
509 return OK;
510}
511
Robert Shih9d4e2d42019-11-08 13:51:49 -0800512void JDrm::notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *args) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700513 sp<DrmListener> listener;
514 mLock.lock();
515 listener = mListener;
516 mLock.unlock();
517
518 if (listener != NULL) {
519 Mutex::Autolock lock(mNotifyLock);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800520 listener->notify(eventType, extra, args);
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700521 }
522}
523
Robert Shih3a523902019-08-15 14:48:11 -0700524void JDrm::sendEvent(
525 DrmPlugin::EventType eventType,
526 const hardware::hidl_vec<uint8_t> &sessionId,
527 const hardware::hidl_vec<uint8_t> &data) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800528 ListenerArgs args{
529 .jSessionId = hidlVectorToJByteArray(sessionId),
530 .jData = hidlVectorToJByteArray(data),
531 };
532 notify(eventType, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700533}
534
535void JDrm::sendExpirationUpdate(
536 const hardware::hidl_vec<uint8_t> &sessionId,
537 int64_t expiryTimeInMS) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800538 ListenerArgs args{
539 .jSessionId = hidlVectorToJByteArray(sessionId),
540 .jExpirationTime = expiryTimeInMS,
541 };
542 notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700543}
544
545void JDrm::sendKeysChange(
546 const hardware::hidl_vec<uint8_t> &sessionId,
547 const std::vector<DrmKeyStatus> &keyStatusList,
548 bool hasNewUsableKey) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800549 JNIEnv *env = AndroidRuntime::getJNIEnv();
550 jclass clazz = gFields.arraylistClassId;
551 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
552 clazz = gFields.keyStatus.classId;
553 for (const auto &keyStatus : keyStatusList) {
554 jbyteArray jKeyId(hidlVectorToJByteArray(keyStatus.keyId));
555 jint jStatusCode(keyStatus.type);
556 jobject jKeyStatus = env->NewObject(clazz, gFields.keyStatus.init, jKeyId, jStatusCode);
557 env->CallBooleanMethod(arrayList, gFields.arraylist.add, jKeyStatus);
558 }
559 ListenerArgs args{
560 .jSessionId = hidlVectorToJByteArray(sessionId),
561 .jKeyStatusList = arrayList,
562 .jHasNewUsableKey = hasNewUsableKey,
563 };
564 notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700565}
566
567void JDrm::sendSessionLostState(
568 const hardware::hidl_vec<uint8_t> &sessionId) {
Robert Shih9d4e2d42019-11-08 13:51:49 -0800569 ListenerArgs args{
570 .jSessionId = hidlVectorToJByteArray(sessionId),
571 };
572 notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &args);
Robert Shih3a523902019-08-15 14:48:11 -0700573}
574
Jeff Tinker600071c2014-04-11 16:11:15 -0700575void JDrm::disconnect() {
576 if (mDrm != NULL) {
577 mDrm->destroyPlugin();
578 mDrm.clear();
579 }
580}
581
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700582
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800583// static
Jeff Tinker5de2e902019-01-25 23:09:36 -0800584status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
585 DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800586 sp<IDrm> drm = MakeDrm();
587
588 if (drm == NULL) {
Jeff Tinker5de2e902019-01-25 23:09:36 -0800589 return BAD_VALUE;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800590 }
591
Jeff Tinker5de2e902019-01-25 23:09:36 -0800592 return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800593}
594
595status_t JDrm::initCheck() const {
596 return mDrm == NULL ? NO_INIT : OK;
597}
598
599// JNI conversion utilities
600static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
601 Vector<uint8_t> vector;
602 size_t length = env->GetArrayLength(byteArray);
603 vector.insertAt((size_t)0, length);
604 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
605 return vector;
606}
607
608static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
609 size_t length = vector.size();
610 jbyteArray result = env->NewByteArray(length);
611 if (result != NULL) {
612 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
613 }
614 return result;
615}
616
617static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800618 String8 result;
619
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700620 const char *s = env->GetStringUTFChars(jstr, NULL);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800621 if (s) {
622 result = s;
623 env->ReleaseStringUTFChars(jstr, s);
624 }
625 return result;
626}
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700627
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800628/*
629 import java.util.HashMap;
630 import java.util.Set;
631 import java.Map.Entry;
632 import jav.util.Iterator;
633
634 HashMap<k, v> hm;
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800635 Set<Entry<k, v>> s = hm.entrySet();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800636 Iterator i = s.iterator();
637 Entry e = s.next();
638*/
639
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200640static KeyedVector<String8, String8> HashMapToKeyedVector(
641 JNIEnv *env, jobject &hashMap, bool* pIsOK) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800642 jclass clazz = gFields.stringClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800643 KeyedVector<String8, String8> keyedVector;
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200644 *pIsOK = true;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800645
646 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
647 if (entrySet) {
648 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
649 if (iterator) {
650 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
651 while (hasNext) {
652 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
653 if (entry) {
654 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200655 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700656 jniThrowException(env, "java/lang/IllegalArgumentException",
657 "HashMap key is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200658 env->DeleteLocalRef(entry);
659 *pIsOK = false;
660 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800661 }
662 jstring jkey = static_cast<jstring>(obj);
663
664 obj = env->CallObjectMethod(entry, gFields.entry.getValue);
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200665 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700666 jniThrowException(env, "java/lang/IllegalArgumentException",
667 "HashMap value is not a String");
Daniel Broms35d6a4f2014-09-29 15:32:03 +0200668 env->DeleteLocalRef(entry);
669 *pIsOK = false;
670 break;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800671 }
672 jstring jvalue = static_cast<jstring>(obj);
673
674 String8 key = JStringToString8(env, jkey);
675 String8 value = JStringToString8(env, jvalue);
676 keyedVector.add(key, value);
677
678 env->DeleteLocalRef(jkey);
679 env->DeleteLocalRef(jvalue);
680 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
681 }
682 env->DeleteLocalRef(entry);
683 }
684 env->DeleteLocalRef(iterator);
685 }
686 env->DeleteLocalRef(entrySet);
687 }
688 return keyedVector;
689}
690
691static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800692 jclass clazz = gFields.hashmapClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800693 jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
694 for (size_t i = 0; i < map.size(); ++i) {
695 jstring jkey = env->NewStringUTF(map.keyAt(i).string());
696 jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
697 env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
698 env->DeleteLocalRef(jkey);
699 env->DeleteLocalRef(jvalue);
700 }
701 return hashMap;
702}
703
704static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800705 List<Vector<uint8_t>> list) {
Jeff Tinkere4095a82014-03-04 13:17:11 -0800706 jclass clazz = gFields.arraylistClassId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800707 jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
Jeff Tinkerb78ee402018-11-05 15:18:53 -0800708 List<Vector<uint8_t>>::iterator iter = list.begin();
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800709 while (iter != list.end()) {
710 jbyteArray byteArray = VectorToJByteArray(env, *iter);
711 env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
712 env->DeleteLocalRef(byteArray);
713 iter++;
714 }
715
716 return arrayList;
717}
718
719} // namespace android
720
721using namespace android;
722
723static sp<JDrm> setDrm(
724 JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
Ashok Bhat656fd042013-11-28 10:56:06 +0000725 sp<JDrm> old = (JDrm *)env->GetLongField(thiz, gFields.context);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800726 if (drm != NULL) {
727 drm->incStrong(thiz);
728 }
729 if (old != NULL) {
730 old->decStrong(thiz);
731 }
Narayan Kamathf11dd632013-12-18 16:53:54 +0000732 env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800733
734 return old;
735}
736
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800737static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800738 if (drm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700739 jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800740 return false;
741 }
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800742 return true;
743}
744
745static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
746{
747 if (!CheckDrm(env, drm)) {
748 return false;
749 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800750
751 if (jsessionId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700752 jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800753 return false;
754 }
755 return true;
756}
757
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800758static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700759 sp<JDrm> drm = setDrm(env, thiz, NULL);
760 if (drm != NULL) {
761 drm->setListener(NULL);
Jeff Tinker600071c2014-04-11 16:11:15 -0700762 drm->disconnect();
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700763 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800764}
765
766static void android_media_MediaDrm_native_init(JNIEnv *env) {
767 jclass clazz;
768 FIND_CLASS(clazz, "android/media/MediaDrm");
Ashok Bhat656fd042013-11-28 10:56:06 +0000769 GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700770 GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
Robert Shih9d4e2d42019-11-08 13:51:49 -0800771 "(Ljava/lang/Object;III[B[BJLjava/util/List;Z)V");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700772
773 jfieldID field;
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700774 GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700775 gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700776 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700777 gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700778 GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700779 gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700780 GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700781 gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
Ronghua Wua6d72092015-03-04 11:16:02 -0800782 GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
783 gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800784
Jeff Tinker74797f82015-03-31 15:44:34 -0700785 GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
786 gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
787 GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
788 gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700789 GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
790 gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800791 GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
792 gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
Jeff Tinker74797f82015-03-31 15:44:34 -0700793
Jeff Tinker17b89222013-05-21 12:35:06 -0700794 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
795 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
796 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
797 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
798 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
799 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
800
Jeff Tinkere4095a82014-03-04 13:17:11 -0800801 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
802 gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
803 GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
804 gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
805
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800806 GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
807 gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
808 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
809 gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
810 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
811 gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
812 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
813 gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
814 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
815 gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
816 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
817 gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
Jeff Tinkerc71c0182019-01-14 10:26:06 -0800818 GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I");
819 gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field);
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800820 GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
821 gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
822
823 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
824 gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700825 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800826 gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700827 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800828 gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700829 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800830 gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700831 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800832 gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
Jeff Tinkercbbab832018-03-28 17:16:50 -0700833 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
Jeff Tinker3eb07f42017-12-08 17:34:53 -0800834 gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
835
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800836 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I");
Jeff Tinker55d26242018-10-10 16:10:43 -0700837 gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
Jeff Tinker8de43ee2018-12-11 01:00:09 -0800838 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I");
839 gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field);
Jeff Tinker55d26242018-10-10 16:10:43 -0700840 GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
841 gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
842
843 GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
844
Jeff Tinker2bca5252018-02-11 18:59:14 +0000845 jmethodID getMaxSecurityLevel;
846 GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
847 gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
848
Jeff Tinker16b8cff2013-03-30 16:26:13 -0700849 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700850 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
851 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker4cdc2de2015-03-16 13:06:33 -0700852 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800853
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700854 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
855 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
856 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
857 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
858 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
859 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
Rahul Frias8f761ba2018-01-22 23:43:54 -0800860 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
861 gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
862 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
863 gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
Jeff Tinker5ffbae642015-05-13 16:53:52 -0700864
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800865 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
Jeff Tinkere1c76be2013-04-03 18:11:33 -0700866 GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
867 GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800868
Jeff Tinkere4095a82014-03-04 13:17:11 -0800869 FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
870 GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
871 GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700872 gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800873
Adam Stone94395c92018-01-30 12:07:00 -0800874 // Metrics-related fields and classes.
875 FIND_CLASS(clazz, "android/os/PersistableBundle");
876 jfieldID bundleCreatorId;
877 GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
878 "Landroid/os/Parcelable$Creator;");
879 jobject bundleCreator;
880 GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
881 gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
882 FIND_CLASS(clazz, "android/os/Parcelable$Creator");
883 GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
884 "(Landroid/os/Parcel;)Ljava/lang/Object;");
885 gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
886
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800887 FIND_CLASS(clazz, "java/util/ArrayList");
888 GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
889 GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
890
891 FIND_CLASS(clazz, "java/util/HashMap");
892 GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
893 GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
894 GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
895 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
896 GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
897
898 FIND_CLASS(clazz, "java/util/Set");
899 GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
900
901 FIND_CLASS(clazz, "java/util/Iterator");
902 GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
903 GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
904
905 FIND_CLASS(clazz, "java/util/Map$Entry");
906 GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
907 GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
Jeff Tinkere4095a82014-03-04 13:17:11 -0800908
909 FIND_CLASS(clazz, "java/util/HashMap");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700910 gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800911
912 FIND_CLASS(clazz, "java/lang/String");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700913 gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkere4095a82014-03-04 13:17:11 -0800914
915 FIND_CLASS(clazz, "java/util/ArrayList");
Jeff Tinker65c94e62014-04-02 12:23:56 -0700916 gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinkerd712e1a2014-06-19 13:58:12 -0700917
918 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
919 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
920 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Jeff Tinker20594d82018-12-12 08:31:22 -0800921
922 FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
923 GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
924 gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
925 GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
926
Jeff Tinkerf11261b2019-02-26 18:11:37 -0800927 GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I");
928 gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
Jeff Tinker20594d82018-12-12 08:31:22 -0800929 GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
930 gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
Robert Shih9d4e2d42019-11-08 13:51:49 -0800931
932 FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
933 gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
934 GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
Robert Shih696989f2021-02-12 23:25:16 -0800935
936 FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage");
937 gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
938 GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800939}
940
941static void android_media_MediaDrm_native_setup(
942 JNIEnv *env, jobject thiz,
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800943 jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800944
945 if (uuidObj == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700946 jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800947 return;
948 }
949
950 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
951
952 if (uuid.size() != 16) {
Jeff Tinkereada5372013-05-21 12:48:14 -0700953 jniThrowException(env, "java/lang/IllegalArgumentException",
954 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800955 return;
956 }
957
Edwin Wong4d1d84e2017-01-04 09:37:49 -0800958 String8 packageName;
959 if (jappPackageName == NULL) {
960 jniThrowException(env, "java/lang/IllegalArgumentException",
961 "application package name cannot be null");
962 return;
963 }
964
965 packageName = JStringToString8(env, jappPackageName);
966 sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800967
968 status_t err = drm->initCheck();
969
970 if (err != OK) {
971 jniThrowException(
972 env,
Jeff Tinker1d7c2182013-04-26 11:12:43 -0700973 "android/media/UnsupportedSchemeException",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800974 "Failed to instantiate drm object.");
975 return;
976 }
977
Jeff Tinker54cfbd62013-04-02 13:14:59 -0700978 sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
979 drm->setListener(listener);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -0800980 setDrm(env, thiz, drm);
981}
982
Jeff Tinkerd571a7c2019-01-17 17:29:30 -0800983DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
984 DrmPlugin::SecurityLevel level;
985
986 if (jlevel == gSecurityLevels.kSecurityLevelMax) {
987 level = DrmPlugin::kSecurityLevelMax;
988 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
989 level = DrmPlugin::kSecurityLevelSwSecureCrypto;
990 } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
991 level = DrmPlugin::kSecurityLevelSwSecureDecode;
992 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
993 level = DrmPlugin::kSecurityLevelHwSecureCrypto;
994 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
995 level = DrmPlugin::kSecurityLevelHwSecureDecode;
996 } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
997 level = DrmPlugin::kSecurityLevelHwSecureAll;
998 } else {
999 level = DrmPlugin::kSecurityLevelUnknown;
1000 }
1001 return level;
1002}
1003
Robert Shihd2e8b432019-11-21 20:27:56 -08001004static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
1005 std::vector<uint8_t> bv;
1006 for (auto &factory : DrmUtils::MakeDrmFactories()) {
1007 sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
1008 if (factoryV1_3 == nullptr) {
1009 continue;
1010 }
1011 factoryV1_3->getSupportedCryptoSchemes(
1012 [&](const hardware::hidl_vec<hardware::hidl_array<uint8_t, 16>>& schemes) {
1013 for (const auto &scheme : schemes) {
1014 bv.insert(bv.end(), scheme.data(), scheme.data() + scheme.size());
1015 }
1016 });
1017 }
1018
1019 jbyteArray jUuidBytes = env->NewByteArray(bv.size());
1020 env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast<const jbyte *>(bv.data()));
1021 return jUuidBytes;
1022}
1023
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001024static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001025 JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType,
1026 jint jSecurityLevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001027
1028 if (uuidObj == NULL) {
1029 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1030 return false;
1031 }
1032
1033 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1034
1035 if (uuid.size() != 16) {
1036 jniThrowException(
1037 env,
1038 "java/lang/IllegalArgumentException",
Jeff Tinkereada5372013-05-21 12:48:14 -07001039 "invalid UUID size, expected 16 bytes");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001040 return false;
1041 }
1042
Jeff Tinker7cda4912013-08-21 11:52:34 -07001043 String8 mimeType;
1044 if (jmimeType != NULL) {
1045 mimeType = JStringToString8(env, jmimeType);
1046 }
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001047 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
Jeff Tinker7cda4912013-08-21 11:52:34 -07001048
Jeff Tinker5de2e902019-01-25 23:09:36 -08001049 bool isSupported;
1050 status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
1051 securityLevel, &isSupported);
1052
Robert Shih60dab872021-02-13 11:24:59 -08001053 if (throwExceptionAsNecessary(env, NULL, err, "Failed to query crypto scheme support")) {
Jeff Tinker5de2e902019-01-25 23:09:36 -08001054 return false;
1055 }
1056 return isSupported;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001057}
1058
1059static jbyteArray android_media_MediaDrm_openSession(
Jeff Tinker2bca5252018-02-11 18:59:14 +00001060 JNIEnv *env, jobject thiz, jint jlevel) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001061 sp<IDrm> drm = GetDrm(env, thiz);
1062
Jeff Tinker55d26242018-10-10 16:10:43 -07001063 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001064 return NULL;
1065 }
1066
1067 Vector<uint8_t> sessionId;
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08001068 DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel);
1069 if (level == DrmPlugin::kSecurityLevelUnknown) {
Jeff Tinker2bca5252018-02-11 18:59:14 +00001070 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
1071 return NULL;
1072 }
1073
1074 status_t err = drm->openSession(level, sessionId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001075
Robert Shih60dab872021-02-13 11:24:59 -08001076 if (throwExceptionAsNecessary(env, drm, err, "Failed to open session")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001077 return NULL;
1078 }
1079
1080 return VectorToJByteArray(env, sessionId);
1081}
1082
1083static void android_media_MediaDrm_closeSession(
1084 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1085 sp<IDrm> drm = GetDrm(env, thiz);
1086
1087 if (!CheckSession(env, drm, jsessionId)) {
1088 return;
1089 }
1090
1091 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1092
1093 status_t err = drm->closeSession(sessionId);
1094
Robert Shih60dab872021-02-13 11:24:59 -08001095 throwExceptionAsNecessary(env, drm, err, "Failed to close session");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001096}
1097
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001098static jobject android_media_MediaDrm_getKeyRequest(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001099 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001100 jstring jmimeType, jint jkeyType, jobject joptParams) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001101 sp<IDrm> drm = GetDrm(env, thiz);
1102
1103 if (!CheckSession(env, drm, jsessionId)) {
1104 return NULL;
1105 }
1106
1107 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1108
1109 Vector<uint8_t> initData;
1110 if (jinitData != NULL) {
1111 initData = JByteArrayToVector(env, jinitData);
1112 }
1113
1114 String8 mimeType;
1115 if (jmimeType != NULL) {
1116 mimeType = JStringToString8(env, jmimeType);
1117 }
1118
Jeff Tinker17b89222013-05-21 12:35:06 -07001119 DrmPlugin::KeyType keyType;
1120 if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
1121 keyType = DrmPlugin::kKeyType_Streaming;
1122 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
1123 keyType = DrmPlugin::kKeyType_Offline;
1124 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
1125 keyType = DrmPlugin::kKeyType_Release;
1126 } else {
1127 jniThrowException(env, "java/lang/IllegalArgumentException",
1128 "invalid keyType");
1129 return NULL;
1130 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001131
1132 KeyedVector<String8, String8> optParams;
1133 if (joptParams != NULL) {
Daniel Broms35d6a4f2014-09-29 15:32:03 +02001134 bool isOK;
1135 optParams = HashMapToKeyedVector(env, joptParams, &isOK);
1136 if (!isOK) {
1137 return NULL;
1138 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001139 }
1140
1141 Vector<uint8_t> request;
1142 String8 defaultUrl;
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001143 DrmPlugin::KeyRequestType keyRequestType;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001144
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001145 status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001146 keyType, optParams, request, defaultUrl, &keyRequestType);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001147
Robert Shih60dab872021-02-13 11:24:59 -08001148 if (throwExceptionAsNecessary(env, drm, err, "Failed to get key request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001149 return NULL;
1150 }
1151
1152 // Fill out return obj
1153 jclass clazz;
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001154 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001155
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001156 jobject keyObj = NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001157
1158 if (clazz) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001159 keyObj = env->AllocObject(clazz);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001160 jbyteArray jrequest = VectorToJByteArray(env, request);
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001161 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001162
1163 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001164 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001165
1166 switch (keyRequestType) {
1167 case DrmPlugin::kKeyRequestType_Initial:
1168 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1169 gKeyRequestTypes.kKeyRequestTypeInitial);
1170 break;
1171 case DrmPlugin::kKeyRequestType_Renewal:
1172 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1173 gKeyRequestTypes.kKeyRequestTypeRenewal);
1174 break;
1175 case DrmPlugin::kKeyRequestType_Release:
1176 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1177 gKeyRequestTypes.kKeyRequestTypeRelease);
1178 break;
Rahul Frias8f761ba2018-01-22 23:43:54 -08001179 case DrmPlugin::kKeyRequestType_None:
1180 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1181 gKeyRequestTypes.kKeyRequestTypeNone);
1182 break;
1183 case DrmPlugin::kKeyRequestType_Update:
1184 env->SetIntField(keyObj, gFields.keyRequest.requestType,
1185 gKeyRequestTypes.kKeyRequestTypeUpdate);
1186 break;
1187
Jeff Tinker74797f82015-03-31 15:44:34 -07001188 default:
Jeff Tinker4cdc2de2015-03-16 13:06:33 -07001189 throwStateException(env, "DRM plugin failure: unknown key request type",
1190 ERROR_DRM_UNKNOWN);
1191 break;
1192 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001193 }
1194
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001195 return keyObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001196}
1197
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001198static jbyteArray android_media_MediaDrm_provideKeyResponse(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001199 JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
1200 sp<IDrm> drm = GetDrm(env, thiz);
1201
1202 if (!CheckSession(env, drm, jsessionId)) {
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001203 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001204 }
1205
1206 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1207
1208 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001209 jniThrowException(env, "java/lang/IllegalArgumentException",
1210 "key response is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001211 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001212 }
1213 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001214 Vector<uint8_t> keySetId;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001215
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001216 status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001217
Robert Shih60dab872021-02-13 11:24:59 -08001218 if (throwExceptionAsNecessary(env, drm, err, "Failed to handle key response")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001219 return NULL;
1220 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001221 return VectorToJByteArray(env, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001222}
1223
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001224static void android_media_MediaDrm_removeKeys(
1225 JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
1226 sp<IDrm> drm = GetDrm(env, thiz);
1227
Jeff Tinker55d26242018-10-10 16:10:43 -07001228 if (!CheckDrm(env, drm)) {
1229 return;
1230 }
1231
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001232 if (jkeysetId == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001233 jniThrowException(env, "java/lang/IllegalArgumentException",
1234 "keySetId is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001235 return;
1236 }
1237
1238 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
1239
1240 status_t err = drm->removeKeys(keySetId);
1241
Robert Shih60dab872021-02-13 11:24:59 -08001242 throwExceptionAsNecessary(env, drm, err, "Failed to remove keys");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001243}
1244
1245static void android_media_MediaDrm_restoreKeys(
1246 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
1247 jbyteArray jkeysetId) {
1248
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001249 sp<IDrm> drm = GetDrm(env, thiz);
1250
1251 if (!CheckSession(env, drm, jsessionId)) {
1252 return;
1253 }
1254
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001255 if (jkeysetId == NULL) {
1256 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1257 return;
1258 }
1259
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001260 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001261 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001262
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001263 status_t err = drm->restoreKeys(sessionId, keySetId);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001264
Robert Shih60dab872021-02-13 11:24:59 -08001265 throwExceptionAsNecessary(env, drm, err, "Failed to restore keys");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001266}
1267
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001268static jobject android_media_MediaDrm_queryKeyStatus(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001269 JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
1270 sp<IDrm> drm = GetDrm(env, thiz);
1271
1272 if (!CheckSession(env, drm, jsessionId)) {
1273 return NULL;
1274 }
1275 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1276
1277 KeyedVector<String8, String8> infoMap;
1278
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001279 status_t err = drm->queryKeyStatus(sessionId, infoMap);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001280
Robert Shih60dab872021-02-13 11:24:59 -08001281 if (throwExceptionAsNecessary(env, drm, err, "Failed to query key status")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001282 return NULL;
1283 }
1284
1285 return KeyedVectorToHashMap(env, infoMap);
1286}
1287
Jeff Tinkere4095a82014-03-04 13:17:11 -08001288static jobject android_media_MediaDrm_getProvisionRequestNative(
1289 JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001290 sp<IDrm> drm = GetDrm(env, thiz);
1291
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001292 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001293 return NULL;
1294 }
1295
1296 Vector<uint8_t> request;
1297 String8 defaultUrl;
1298
Jeff Tinkere4095a82014-03-04 13:17:11 -08001299 String8 certType;
1300 if (jcertType == gCertificateTypes.kCertificateTypeX509) {
1301 certType = "X.509";
1302 } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
1303 certType = "none";
1304 } else {
1305 certType = "invalid";
1306 }
1307
1308 String8 certAuthority = JStringToString8(env, jcertAuthority);
1309 status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001310
Robert Shih60dab872021-02-13 11:24:59 -08001311 if (throwExceptionAsNecessary(env, drm, err, "Failed to get provision request")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001312 return NULL;
1313 }
1314
1315 // Fill out return obj
1316 jclass clazz;
1317 FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
1318
1319 jobject provisionObj = NULL;
1320
1321 if (clazz) {
1322 provisionObj = env->AllocObject(clazz);
1323 jbyteArray jrequest = VectorToJByteArray(env, request);
1324 env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
1325
1326 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
1327 env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
1328 }
1329
1330 return provisionObj;
1331}
1332
Jeff Tinkere4095a82014-03-04 13:17:11 -08001333static jobject android_media_MediaDrm_provideProvisionResponseNative(
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001334 JNIEnv *env, jobject thiz, jbyteArray jresponse) {
1335 sp<IDrm> drm = GetDrm(env, thiz);
1336
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001337 if (!CheckDrm(env, drm)) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001338 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001339 }
1340
1341 if (jresponse == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001342 jniThrowException(env, "java/lang/IllegalArgumentException",
1343 "provision response is null");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001344 return NULL;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001345 }
1346
1347 Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
Jeff Tinkere4095a82014-03-04 13:17:11 -08001348 Vector<uint8_t> certificate, wrappedKey;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001349
Jeff Tinkere4095a82014-03-04 13:17:11 -08001350 status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
1351
1352 // Fill out return obj
1353 jclass clazz = gFields.certificateClassId;
1354
1355 jobject certificateObj = NULL;
1356
1357 if (clazz && certificate.size() && wrappedKey.size()) {
1358 certificateObj = env->AllocObject(clazz);
1359 jbyteArray jcertificate = VectorToJByteArray(env, certificate);
1360 env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
1361
1362 jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
1363 env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
1364 }
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001365
Robert Shih60dab872021-02-13 11:24:59 -08001366 throwExceptionAsNecessary(env, drm, err, "Failed to handle provision response");
Jeff Tinkere4095a82014-03-04 13:17:11 -08001367 return certificateObj;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001368}
1369
1370static jobject android_media_MediaDrm_getSecureStops(
1371 JNIEnv *env, jobject thiz) {
1372 sp<IDrm> drm = GetDrm(env, thiz);
1373
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001374 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001375 return NULL;
1376 }
1377
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001378 List<Vector<uint8_t>> secureStops;
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001379
1380 status_t err = drm->getSecureStops(secureStops);
1381
Robert Shih60dab872021-02-13 11:24:59 -08001382 if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stops")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001383 return NULL;
1384 }
1385
1386 return ListOfVectorsToArrayListOfByteArray(env, secureStops);
1387}
1388
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001389static jobject android_media_MediaDrm_getSecureStopIds(
1390 JNIEnv *env, jobject thiz) {
1391 sp<IDrm> drm = GetDrm(env, thiz);
1392
Jeff Tinker55d26242018-10-10 16:10:43 -07001393 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001394 return NULL;
1395 }
1396
Jeff Tinkerb78ee402018-11-05 15:18:53 -08001397 List<Vector<uint8_t>> secureStopIds;
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001398
1399 status_t err = drm->getSecureStopIds(secureStopIds);
1400
Robert Shih60dab872021-02-13 11:24:59 -08001401 if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop Ids")) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001402 return NULL;
1403 }
1404
1405 return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
1406}
1407
Jeff Tinker1b51c722014-10-31 00:54:26 -07001408static jbyteArray android_media_MediaDrm_getSecureStop(
1409 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1410 sp<IDrm> drm = GetDrm(env, thiz);
1411
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001412 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001413 return NULL;
1414 }
1415
1416 Vector<uint8_t> secureStop;
1417
1418 status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
1419
Robert Shih60dab872021-02-13 11:24:59 -08001420 if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop")) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001421 return NULL;
1422 }
1423
1424 return VectorToJByteArray(env, secureStop);
1425}
1426
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001427static void android_media_MediaDrm_releaseSecureStops(
1428 JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
1429 sp<IDrm> drm = GetDrm(env, thiz);
1430
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001431 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001432 return;
1433 }
1434
1435 Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
1436
1437 status_t err = drm->releaseSecureStops(ssRelease);
1438
Robert Shih60dab872021-02-13 11:24:59 -08001439 throwExceptionAsNecessary(env, drm, err, "Failed to release secure stops");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001440}
1441
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001442static void android_media_MediaDrm_removeSecureStop(
1443 JNIEnv *env, jobject thiz, jbyteArray ssid) {
1444 sp<IDrm> drm = GetDrm(env, thiz);
1445
Jeff Tinker55d26242018-10-10 16:10:43 -07001446 if (!CheckDrm(env, drm)) {
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001447 return;
1448 }
1449
1450 status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
1451
Robert Shih60dab872021-02-13 11:24:59 -08001452 throwExceptionAsNecessary(env, drm, err, "Failed to remove secure stop");
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001453}
1454
1455static void android_media_MediaDrm_removeAllSecureStops(
Jeff Tinker1b51c722014-10-31 00:54:26 -07001456 JNIEnv *env, jobject thiz) {
1457 sp<IDrm> drm = GetDrm(env, thiz);
1458
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001459 if (!CheckDrm(env, drm)) {
Jeff Tinker1b51c722014-10-31 00:54:26 -07001460 return;
1461 }
1462
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08001463 status_t err = drm->removeAllSecureStops();
Jeff Tinker1b51c722014-10-31 00:54:26 -07001464
Robert Shih60dab872021-02-13 11:24:59 -08001465 throwExceptionAsNecessary(env, drm, err, "Failed to remove all secure stops");
Jeff Tinker1b51c722014-10-31 00:54:26 -07001466}
1467
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001468
1469static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
1470 switch(level) {
1471 case DrmPlugin::kHdcpLevelUnknown:
1472 return gHdcpLevels.kHdcpLevelUnknown;
1473 case DrmPlugin::kHdcpNone:
1474 return gHdcpLevels.kHdcpNone;
1475 case DrmPlugin::kHdcpV1:
1476 return gHdcpLevels.kHdcpV1;
1477 case DrmPlugin::kHdcpV2:
1478 return gHdcpLevels.kHdcpV2;
1479 case DrmPlugin::kHdcpV2_1:
1480 return gHdcpLevels.kHdcpV2_1;
1481 case DrmPlugin::kHdcpV2_2:
1482 return gHdcpLevels.kHdcpV2_2;
Jeff Tinkerc71c0182019-01-14 10:26:06 -08001483 case DrmPlugin::kHdcpV2_3:
1484 return gHdcpLevels.kHdcpV2_3;
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001485 case DrmPlugin::kHdcpNoOutput:
1486 return gHdcpLevels.kHdcpNoOutput;
1487 }
1488 return gHdcpLevels.kHdcpNone;
1489}
1490
1491static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
1492 jobject thiz) {
1493 sp<IDrm> drm = GetDrm(env, thiz);
1494
1495 if (!CheckDrm(env, drm)) {
1496 return gHdcpLevels.kHdcpNone;
1497 }
1498
1499 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
1500 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
1501
1502 status_t err = drm->getHdcpLevels(&connected, &max);
1503
Robert Shih60dab872021-02-13 11:24:59 -08001504 if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001505 return gHdcpLevels.kHdcpLevelUnknown;
1506 }
1507 return HdcpLevelTojint(connected);
1508}
1509
1510static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
1511 jobject thiz) {
1512 sp<IDrm> drm = GetDrm(env, thiz);
1513
1514 if (!CheckDrm(env, drm)) {
1515 return gHdcpLevels.kHdcpLevelUnknown;
1516 }
1517
1518 DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
1519 DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
1520
1521 status_t err = drm->getHdcpLevels(&connected, &max);
1522
Robert Shih60dab872021-02-13 11:24:59 -08001523 if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001524 return gHdcpLevels.kHdcpLevelUnknown;
1525 }
1526 return HdcpLevelTojint(max);
1527}
1528
1529static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
1530 jobject thiz) {
1531 sp<IDrm> drm = GetDrm(env, thiz);
1532
1533 if (!CheckDrm(env, drm)) {
1534 return 0;
1535 }
1536
1537 uint32_t open = 0, max = 0;
1538 status_t err = drm->getNumberOfSessions(&open, &max);
1539
Robert Shih60dab872021-02-13 11:24:59 -08001540 if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001541 return 0;
1542 }
1543 return open;
1544}
1545
1546static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
1547 jobject thiz) {
1548 sp<IDrm> drm = GetDrm(env, thiz);
1549
1550 if (!CheckDrm(env, drm)) {
1551 return 0;
1552 }
1553
1554 uint32_t open = 0, max = 0;
1555 status_t err = drm->getNumberOfSessions(&open, &max);
1556
Robert Shih60dab872021-02-13 11:24:59 -08001557 if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001558 return 0;
1559 }
1560 return max;
1561}
1562
1563static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
1564 jobject thiz, jbyteArray jsessionId) {
1565 sp<IDrm> drm = GetDrm(env, thiz);
1566
1567 if (!CheckSession(env, drm, jsessionId)) {
1568 return gSecurityLevels.kSecurityLevelUnknown;
1569 }
1570
1571 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1572
1573 DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
1574
1575 status_t err = drm->getSecurityLevel(sessionId, &level);
1576
Robert Shih60dab872021-02-13 11:24:59 -08001577 if (throwExceptionAsNecessary(env, drm, err, "Failed to get security level")) {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001578 return gSecurityLevels.kSecurityLevelUnknown;
1579 }
1580
1581 switch(level) {
1582 case DrmPlugin::kSecurityLevelSwSecureCrypto:
1583 return gSecurityLevels.kSecurityLevelSwSecureCrypto;
1584 case DrmPlugin::kSecurityLevelSwSecureDecode:
1585 return gSecurityLevels.kSecurityLevelSwSecureDecode;
1586 case DrmPlugin::kSecurityLevelHwSecureCrypto:
1587 return gSecurityLevels.kSecurityLevelHwSecureCrypto;
1588 case DrmPlugin::kSecurityLevelHwSecureDecode:
1589 return gSecurityLevels.kSecurityLevelHwSecureDecode;
1590 case DrmPlugin::kSecurityLevelHwSecureAll:
1591 return gSecurityLevels.kSecurityLevelHwSecureAll;
1592 default:
1593 return gSecurityLevels.kSecurityLevelUnknown;
1594 }
1595}
1596
Jeff Tinker55d26242018-10-10 16:10:43 -07001597static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
1598 JNIEnv *env, jobject thiz) {
1599 sp<IDrm> drm = GetDrm(env, thiz);
1600
1601 if (!CheckDrm(env, drm)) {
1602 return NULL;
1603 }
1604
1605 List<Vector<uint8_t> > keySetIds;
1606
1607 status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
1608
Robert Shih60dab872021-02-13 11:24:59 -08001609 if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline key set Ids")) {
Jeff Tinker55d26242018-10-10 16:10:43 -07001610 return NULL;
1611 }
1612
1613 return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
1614}
1615
1616static void android_media_MediaDrm_removeOfflineLicense(
1617 JNIEnv *env, jobject thiz, jbyteArray keySetId) {
1618 sp<IDrm> drm = GetDrm(env, thiz);
1619
1620 if (!CheckDrm(env, drm)) {
1621 return;
1622 }
1623
1624 status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
1625
Robert Shih60dab872021-02-13 11:24:59 -08001626 throwExceptionAsNecessary(env, drm, err, "Failed to remove offline license");
Jeff Tinker55d26242018-10-10 16:10:43 -07001627}
1628
1629static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
1630 jobject thiz, jbyteArray jkeySetId) {
1631 sp<IDrm> drm = GetDrm(env, thiz);
1632
1633 if (!CheckDrm(env, drm)) {
1634 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1635 }
1636
1637 Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
1638
1639 DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
1640
1641 status_t err = drm->getOfflineLicenseState(keySetId, &state);
1642
Robert Shih60dab872021-02-13 11:24:59 -08001643 if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline license state")) {
Jeff Tinker55d26242018-10-10 16:10:43 -07001644 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1645 }
1646
1647 switch(state) {
1648 case DrmPlugin::kOfflineLicenseStateUsable:
1649 return gOfflineLicenseStates.kOfflineLicenseStateUsable;
Jeff Tinker8de43ee2018-12-11 01:00:09 -08001650 case DrmPlugin::kOfflineLicenseStateReleased:
1651 return gOfflineLicenseStates.kOfflineLicenseStateReleased;
Jeff Tinker55d26242018-10-10 16:10:43 -07001652 default:
1653 return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
1654 }
1655}
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001656
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001657static jstring android_media_MediaDrm_getPropertyString(
1658 JNIEnv *env, jobject thiz, jstring jname) {
1659 sp<IDrm> drm = GetDrm(env, thiz);
1660
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001661 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001662 return NULL;
1663 }
1664
1665 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001666 jniThrowException(env, "java/lang/IllegalArgumentException",
1667 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001668 return NULL;
1669 }
1670
1671 String8 name = JStringToString8(env, jname);
1672 String8 value;
1673
1674 status_t err = drm->getPropertyString(name, value);
1675
Robert Shih60dab872021-02-13 11:24:59 -08001676 if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001677 return NULL;
1678 }
1679
1680 return env->NewStringUTF(value.string());
1681}
1682
1683static jbyteArray android_media_MediaDrm_getPropertyByteArray(
1684 JNIEnv *env, jobject thiz, jstring jname) {
1685 sp<IDrm> drm = GetDrm(env, thiz);
1686
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001687 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001688 return NULL;
1689 }
1690
1691 if (jname == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001692 jniThrowException(env, "java/lang/IllegalArgumentException",
1693 "property name String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001694 return NULL;
1695 }
1696
1697 String8 name = JStringToString8(env, jname);
1698 Vector<uint8_t> value;
1699
1700 status_t err = drm->getPropertyByteArray(name, value);
1701
Robert Shih60dab872021-02-13 11:24:59 -08001702 if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001703 return NULL;
1704 }
1705
1706 return VectorToJByteArray(env, value);
1707}
1708
1709static void android_media_MediaDrm_setPropertyString(
1710 JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
1711 sp<IDrm> drm = GetDrm(env, thiz);
1712
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001713 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001714 return;
1715 }
1716
Jeff Tinkereada5372013-05-21 12:48:14 -07001717 if (jname == NULL) {
1718 jniThrowException(env, "java/lang/IllegalArgumentException",
1719 "property name String is null");
1720 return;
1721 }
1722
1723 if (jvalue == NULL) {
1724 jniThrowException(env, "java/lang/IllegalArgumentException",
1725 "property value String is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001726 return;
1727 }
1728
1729 String8 name = JStringToString8(env, jname);
1730 String8 value = JStringToString8(env, jvalue);
1731
1732 status_t err = drm->setPropertyString(name, value);
1733
Robert Shih60dab872021-02-13 11:24:59 -08001734 throwExceptionAsNecessary(env, drm, err, "Failed to set property");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001735}
1736
1737static void android_media_MediaDrm_setPropertyByteArray(
1738 JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
1739 sp<IDrm> drm = GetDrm(env, thiz);
1740
Jeff Tinker3eb07f42017-12-08 17:34:53 -08001741 if (!CheckDrm(env, drm)) {
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001742 return;
1743 }
1744
Jeff Tinkereada5372013-05-21 12:48:14 -07001745 if (jname == NULL) {
1746 jniThrowException(env, "java/lang/IllegalArgumentException",
1747 "property name String is null");
1748 return;
1749 }
1750
1751 if (jvalue == NULL) {
1752 jniThrowException(env, "java/lang/IllegalArgumentException",
1753 "property value byte array is null");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001754 return;
1755 }
1756
1757 String8 name = JStringToString8(env, jname);
1758 Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
1759
1760 status_t err = drm->setPropertyByteArray(name, value);
1761
Robert Shih60dab872021-02-13 11:24:59 -08001762 throwExceptionAsNecessary(env, drm, err, "Failed to set property");
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001763}
1764
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001765static void android_media_MediaDrm_setCipherAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001766 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001767 jstring jalgorithm) {
1768
1769 sp<IDrm> drm = GetDrm(env, jdrm);
1770
1771 if (!CheckSession(env, drm, jsessionId)) {
1772 return;
1773 }
1774
1775 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001776 jniThrowException(env, "java/lang/IllegalArgumentException",
1777 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001778 return;
1779 }
1780
1781 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1782 String8 algorithm = JStringToString8(env, jalgorithm);
1783
1784 status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
1785
Robert Shih60dab872021-02-13 11:24:59 -08001786 throwExceptionAsNecessary(env, drm, err, "Failed to set cipher algorithm");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001787}
1788
1789static void android_media_MediaDrm_setMacAlgorithmNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001790 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001791 jstring jalgorithm) {
1792
1793 sp<IDrm> drm = GetDrm(env, jdrm);
1794
1795 if (!CheckSession(env, drm, jsessionId)) {
1796 return;
1797 }
1798
1799 if (jalgorithm == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001800 jniThrowException(env, "java/lang/IllegalArgumentException",
1801 "algorithm String is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001802 return;
1803 }
1804
1805 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1806 String8 algorithm = JStringToString8(env, jalgorithm);
1807
1808 status_t err = drm->setMacAlgorithm(sessionId, algorithm);
1809
Robert Shih60dab872021-02-13 11:24:59 -08001810 throwExceptionAsNecessary(env, drm, err, "Failed to set mac algorithm");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001811}
1812
1813
1814static jbyteArray android_media_MediaDrm_encryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001815 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001816 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1817
1818 sp<IDrm> drm = GetDrm(env, jdrm);
1819
1820 if (!CheckSession(env, drm, jsessionId)) {
1821 return NULL;
1822 }
1823
1824 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001825 jniThrowException(env, "java/lang/IllegalArgumentException",
1826 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001827 return NULL;
1828 }
1829
1830 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1831 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1832 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1833 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1834 Vector<uint8_t> output;
1835
1836 status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
1837
Robert Shih60dab872021-02-13 11:24:59 -08001838 if (throwExceptionAsNecessary(env, drm, err, "Failed to encrypt")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001839 return NULL;
1840 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001841
1842 return VectorToJByteArray(env, output);
1843}
1844
1845static jbyteArray android_media_MediaDrm_decryptNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001846 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001847 jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
1848
1849 sp<IDrm> drm = GetDrm(env, jdrm);
1850
1851 if (!CheckSession(env, drm, jsessionId)) {
1852 return NULL;
1853 }
1854
1855 if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001856 jniThrowException(env, "java/lang/IllegalArgumentException",
1857 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001858 return NULL;
1859 }
1860
1861 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1862 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1863 Vector<uint8_t> input(JByteArrayToVector(env, jinput));
1864 Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
1865 Vector<uint8_t> output;
1866
1867 status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
Robert Shih60dab872021-02-13 11:24:59 -08001868 if (throwExceptionAsNecessary(env, drm, err, "Failed to decrypt")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001869 return NULL;
1870 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001871
1872 return VectorToJByteArray(env, output);
1873}
1874
1875static jbyteArray android_media_MediaDrm_signNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001876 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001877 jbyteArray jkeyId, jbyteArray jmessage) {
1878
1879 sp<IDrm> drm = GetDrm(env, jdrm);
1880
1881 if (!CheckSession(env, drm, jsessionId)) {
1882 return NULL;
1883 }
1884
1885 if (jkeyId == NULL || jmessage == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001886 jniThrowException(env, "java/lang/IllegalArgumentException",
1887 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001888 return NULL;
1889 }
1890
1891 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1892 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1893 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1894 Vector<uint8_t> signature;
1895
1896 status_t err = drm->sign(sessionId, keyId, message, signature);
1897
Robert Shih60dab872021-02-13 11:24:59 -08001898 if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
Jeff Tinker8117d8f2013-08-16 13:46:02 -07001899 return NULL;
1900 }
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001901
1902 return VectorToJByteArray(env, signature);
1903}
1904
1905static jboolean android_media_MediaDrm_verifyNative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001906 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001907 jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
1908
1909 sp<IDrm> drm = GetDrm(env, jdrm);
1910
1911 if (!CheckSession(env, drm, jsessionId)) {
1912 return false;
1913 }
1914
1915 if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
Jeff Tinkereada5372013-05-21 12:48:14 -07001916 jniThrowException(env, "java/lang/IllegalArgumentException",
1917 "required argument is null");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001918 return false;
1919 }
1920
1921 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1922 Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
1923 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1924 Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
1925 bool match;
1926
1927 status_t err = drm->verify(sessionId, keyId, message, signature, match);
1928
Robert Shih60dab872021-02-13 11:24:59 -08001929 throwExceptionAsNecessary(env, drm, err, "Failed to verify");
Jeff Tinker16b8cff2013-03-30 16:26:13 -07001930 return match;
1931}
1932
Adam Stonec06e10e2017-12-19 12:54:33 -08001933static jobject
1934android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
1935{
1936 sp<IDrm> drm = GetDrm(env, thiz);
Jeff Tinker55d26242018-10-10 16:10:43 -07001937
1938 if (!CheckDrm(env, drm)) {
Adam Stonec06e10e2017-12-19 12:54:33 -08001939 return NULL;
1940 }
1941
1942 // Retrieve current metrics snapshot from drm.
Adam Stone94395c92018-01-30 12:07:00 -08001943 PersistableBundle metrics;
Robert Shihba6777e2019-11-12 13:04:59 -08001944 sp<IDrmMetricsConsumer> consumer(new DrmMetricsConsumer(&metrics));
1945 status_t err = drm->getMetrics(consumer);
Adam Stonec06e10e2017-12-19 12:54:33 -08001946 if (err != OK) {
1947 ALOGE("getMetrics failed: %d", (int)err);
1948 return (jobject) NULL;
1949 }
1950
Robert Shih4354a962019-11-10 12:09:08 -08001951 return MediaMetricsJNI::nativeToJavaPersistableBundle(env, &metrics);
Adam Stonec06e10e2017-12-19 12:54:33 -08001952}
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001953
Jeff Tinkere4095a82014-03-04 13:17:11 -08001954static jbyteArray android_media_MediaDrm_signRSANative(
Andreas Gampe5a15d0d2014-11-10 18:19:40 -08001955 JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
Jeff Tinkere4095a82014-03-04 13:17:11 -08001956 jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
1957
1958 sp<IDrm> drm = GetDrm(env, jdrm);
1959
1960 if (!CheckSession(env, drm, jsessionId)) {
1961 return NULL;
1962 }
1963
1964 if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
1965 jniThrowException(env, "java/lang/IllegalArgumentException",
1966 "required argument is null");
1967 return NULL;
1968 }
1969
1970 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
1971 String8 algorithm = JStringToString8(env, jalgorithm);
1972 Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
1973 Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
1974 Vector<uint8_t> signature;
1975
1976 status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
1977
Robert Shih60dab872021-02-13 11:24:59 -08001978 if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
Jeff Tinkere4095a82014-03-04 13:17:11 -08001979 return NULL;
1980 }
1981
1982 return VectorToJByteArray(env, signature);
1983}
1984
Robert Shih205f7a92021-01-19 21:12:10 -08001985static jboolean android_media_MediaDrm_requiresSecureDecoder(
1986 JNIEnv *env, jobject thiz, jstring jmimeType,
1987 jint jSecurityLevel) {
1988 sp<IDrm> drm = GetDrm(env, thiz);
1989 if (!CheckDrm(env, drm)) {
1990 return JNI_FALSE;
1991 }
1992
1993 String8 mimeType;
1994 if (jmimeType != NULL) {
1995 mimeType = JStringToString8(env, jmimeType);
1996 }
1997
1998 DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
1999 if (securityLevel == DrmPlugin::kSecurityLevelUnknown) {
2000 jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
2001 return JNI_FALSE;
2002 }
2003
2004 if (securityLevel == DrmPlugin::kSecurityLevelMax) {
2005 return drm->requiresSecureDecoder(mimeType.c_str());
2006 }
2007 return drm->requiresSecureDecoder(mimeType.c_str(), securityLevel);
2008}
Jeff Tinkere4095a82014-03-04 13:17:11 -08002009
Robert Shih02937122021-01-20 00:05:20 -08002010static void android_media_MediaDrm_setPlaybackId(
2011 JNIEnv *env, jobject thiz, jbyteArray jsessionId,
2012 jstring jplaybackId) {
2013 sp<IDrm> drm = GetDrm(env, thiz);
2014 if (!CheckSession(env, drm, jsessionId)) {
2015 return;
2016 }
2017
2018 Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
2019
2020 String8 playbackId;
2021 if (jplaybackId != NULL) {
2022 playbackId = JStringToString8(env, jplaybackId);
2023 }
2024 status_t err = drm->setPlaybackId(sessionId, playbackId.c_str());
Robert Shih60dab872021-02-13 11:24:59 -08002025 throwExceptionAsNecessary(env, drm, err, "Failed to set playbackId");
Robert Shih02937122021-01-20 00:05:20 -08002026}
2027
Robert Shih696989f2021-02-12 23:25:16 -08002028static jobject android_media_MediaDrm_getLogMessages(
2029 JNIEnv *env, jobject thiz) {
2030 sp<IDrm> drm = GetDrm(env, thiz);
2031 if (!CheckDrm(env, drm)) {
2032 return NULL;
2033 }
2034
2035 Vector<drm::V1_4::LogMessage> logs;
2036 status_t err = drm->getLogMessages(logs);
2037 ALOGI("drm->getLogMessages %zu logs", logs.size());
Robert Shih60dab872021-02-13 11:24:59 -08002038 if (throwExceptionAsNecessary(env, drm, err, "Failed to get log messages")) {
Robert Shih696989f2021-02-12 23:25:16 -08002039 return NULL;
2040 }
2041 return hidlLogMessagesToJavaList(env, logs);
2042}
2043
Daniel Micay76f6a862015-09-19 17:31:01 -04002044static const JNINativeMethod gMethods[] = {
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002045 { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
2046
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002047 { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
2048
Edwin Wong4d1d84e2017-01-04 09:37:49 -08002049 { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002050 (void *)android_media_MediaDrm_native_setup },
2051
Robert Shihd2e8b432019-11-21 20:27:56 -08002052 { "getSupportedCryptoSchemesNative", "()[B",
2053 (void *)android_media_MediaDrm_getSupportedCryptoSchemesNative },
2054
Jeff Tinkerd571a7c2019-01-17 17:29:30 -08002055 { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002056 (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
2057
Robert Shih02937122021-01-20 00:05:20 -08002058 { "openSessionNative", "(I)[B",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002059 (void *)android_media_MediaDrm_openSession },
2060
Robert Shih02937122021-01-20 00:05:20 -08002061 { "closeSessionNative", "([B)V",
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002062 (void *)android_media_MediaDrm_closeSession },
2063
Robert Shih890eb572021-01-19 08:16:39 -08002064 { "getKeyRequestNative", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002065 "Landroid/media/MediaDrm$KeyRequest;",
2066 (void *)android_media_MediaDrm_getKeyRequest },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002067
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002068 { "provideKeyResponse", "([B[B)[B",
2069 (void *)android_media_MediaDrm_provideKeyResponse },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002070
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002071 { "removeKeys", "([B)V",
2072 (void *)android_media_MediaDrm_removeKeys },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002073
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002074 { "restoreKeys", "([B[B)V",
2075 (void *)android_media_MediaDrm_restoreKeys },
2076
2077 { "queryKeyStatus", "([B)Ljava/util/HashMap;",
2078 (void *)android_media_MediaDrm_queryKeyStatus },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002079
Jeff Tinkere4095a82014-03-04 13:17:11 -08002080 { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
2081 (void *)android_media_MediaDrm_getProvisionRequestNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002082
Jeff Tinkere4095a82014-03-04 13:17:11 -08002083 { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
2084 (void *)android_media_MediaDrm_provideProvisionResponseNative },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002085
2086 { "getSecureStops", "()Ljava/util/List;",
2087 (void *)android_media_MediaDrm_getSecureStops },
2088
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002089 { "getSecureStopIds", "()Ljava/util/List;",
2090 (void *)android_media_MediaDrm_getSecureStopIds },
2091
Jeff Tinker1b51c722014-10-31 00:54:26 -07002092 { "getSecureStop", "([B)[B",
2093 (void *)android_media_MediaDrm_getSecureStop },
2094
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002095 { "releaseSecureStops", "([B)V",
2096 (void *)android_media_MediaDrm_releaseSecureStops },
2097
Jeff Tinker1bfb3d22018-01-25 11:46:03 -08002098 { "removeSecureStop", "([B)V",
2099 (void *)android_media_MediaDrm_removeSecureStop },
2100
2101 { "removeAllSecureStops", "()V",
2102 (void *)android_media_MediaDrm_removeAllSecureStops },
Jeff Tinker1b51c722014-10-31 00:54:26 -07002103
Jeff Tinker3eb07f42017-12-08 17:34:53 -08002104 { "getConnectedHdcpLevel", "()I",
2105 (void *)android_media_MediaDrm_getConnectedHdcpLevel },
2106
2107 { "getMaxHdcpLevel", "()I",
2108 (void *)android_media_MediaDrm_getMaxHdcpLevel },
2109
2110 { "getOpenSessionCount", "()I",
2111 (void *)android_media_MediaDrm_getOpenSessionCount },
2112
2113 { "getMaxSessionCount", "()I",
2114 (void *)android_media_MediaDrm_getMaxSessionCount },
2115
2116 { "getSecurityLevel", "([B)I",
2117 (void *)android_media_MediaDrm_getSecurityLevel },
2118
Jeff Tinker55d26242018-10-10 16:10:43 -07002119 { "removeOfflineLicense", "([B)V",
2120 (void *)android_media_MediaDrm_removeOfflineLicense },
2121
2122 { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
2123 (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
2124
2125 { "getOfflineLicenseState", "([B)I",
2126 (void *)android_media_MediaDrm_getOfflineLicenseState },
2127
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002128 { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
2129 (void *)android_media_MediaDrm_getPropertyString },
2130
2131 { "getPropertyByteArray", "(Ljava/lang/String;)[B",
2132 (void *)android_media_MediaDrm_getPropertyByteArray },
2133
2134 { "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
2135 (void *)android_media_MediaDrm_setPropertyString },
2136
2137 { "setPropertyByteArray", "(Ljava/lang/String;[B)V",
2138 (void *)android_media_MediaDrm_setPropertyByteArray },
Jeff Tinker16b8cff2013-03-30 16:26:13 -07002139
2140 { "setCipherAlgorithmNative",
2141 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2142 (void *)android_media_MediaDrm_setCipherAlgorithmNative },
2143
2144 { "setMacAlgorithmNative",
2145 "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
2146 (void *)android_media_MediaDrm_setMacAlgorithmNative },
2147
2148 { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2149 (void *)android_media_MediaDrm_encryptNative },
2150
2151 { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
2152 (void *)android_media_MediaDrm_decryptNative },
2153
2154 { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
2155 (void *)android_media_MediaDrm_signNative },
2156
2157 { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
2158 (void *)android_media_MediaDrm_verifyNative },
Jeff Tinkere4095a82014-03-04 13:17:11 -08002159
2160 { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
2161 (void *)android_media_MediaDrm_signRSANative },
Adam Stonec06e10e2017-12-19 12:54:33 -08002162
2163 { "getMetricsNative", "()Landroid/os/PersistableBundle;",
2164 (void *)android_media_MediaDrm_native_getMetrics },
Robert Shih205f7a92021-01-19 21:12:10 -08002165
2166 { "requiresSecureDecoder", "(Ljava/lang/String;I)Z",
2167 (void *)android_media_MediaDrm_requiresSecureDecoder },
Robert Shih02937122021-01-20 00:05:20 -08002168
2169 { "setPlaybackId", "([BLjava/lang/String;)V",
2170 (void *)android_media_MediaDrm_setPlaybackId },
Robert Shih696989f2021-02-12 23:25:16 -08002171
2172 { "getLogMessages", "()Ljava/util/List;",
2173 (void *)android_media_MediaDrm_getLogMessages },
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08002174};
2175
2176int register_android_media_Drm(JNIEnv *env) {
2177 return AndroidRuntime::registerNativeMethods(env,
2178 "android/media/MediaDrm", gMethods, NELEM(gMethods));
2179}