blob: 00784fbadf0807bb09cf52ca5c1f38e24d1f67c1 [file] [log] [blame]
Jeff Tinkera53d6552017-01-20 00:31:46 -08001/*
2 * Copyright (C) 2017 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 "DrmHal"
Adam Stonefb679e32018-02-07 10:25:48 -080019#include <iomanip>
20
Jeff Tinkera53d6552017-01-20 00:31:46 -080021#include <utils/Log.h>
22
23#include <binder/IPCThreadState.h>
24#include <binder/IServiceManager.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080025
Jeff Tinkera53d6552017-01-20 00:31:46 -080026#include <android/hardware/drm/1.0/types.h>
Jeff Tinkerabeb36a2017-02-17 09:42:46 -080027#include <android/hidl/manager/1.0/IServiceManager.h>
Jeff Tinker593111f2017-05-25 16:00:21 -070028#include <hidl/ServiceManagement.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080029
Adam Stonef0e618d2018-01-17 19:20:41 -080030#include <media/EventMetric.h>
John W. Bruce33ecc4f2017-04-03 16:49:05 -070031#include <media/PluginMetricsReporting.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080032#include <media/drm/DrmAPI.h>
33#include <media/stagefright/foundation/ADebug.h>
34#include <media/stagefright/foundation/AString.h>
35#include <media/stagefright/foundation/hexdump.h>
36#include <media/stagefright/MediaErrors.h>
Jeff Tinker7d2c6e82018-02-16 16:14:59 -080037#include <mediadrm/DrmHal.h>
38#include <mediadrm/DrmSessionClientInterface.h>
39#include <mediadrm/DrmSessionManager.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080040
Jeff Tinker6d998b62017-12-18 14:37:43 -080041using drm::V1_0::KeyedVector;
Jeff Tinker6d998b62017-12-18 14:37:43 -080042using drm::V1_0::KeyStatusType;
43using drm::V1_0::KeyType;
44using drm::V1_0::KeyValue;
45using drm::V1_1::HdcpLevel;;
46using drm::V1_0::SecureStop;
Jeff Tinker15177d72018-01-25 12:57:55 -080047using drm::V1_1::SecureStopRelease;
48using drm::V1_0::SecureStopId;
Jeff Tinker6d998b62017-12-18 14:37:43 -080049using drm::V1_1::SecurityLevel;
50using drm::V1_0::Status;
Jeff Tinkera53d6552017-01-20 00:31:46 -080051using ::android::hardware::hidl_array;
52using ::android::hardware::hidl_string;
53using ::android::hardware::hidl_vec;
54using ::android::hardware::Return;
55using ::android::hardware::Void;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -080056using ::android::hidl::manager::V1_0::IServiceManager;
Adam Stone637b7852018-01-30 12:09:36 -080057using ::android::os::PersistableBundle;
Jeff Tinkera53d6552017-01-20 00:31:46 -080058using ::android::sp;
59
Adam Stonecea91ce2018-01-22 19:23:28 -080060namespace {
61
62// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
63// in the MediaDrm API.
64constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
65
66}
67
Jeff Tinkera53d6552017-01-20 00:31:46 -080068namespace android {
69
Jeff Tinker6d998b62017-12-18 14:37:43 -080070#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
71
Jeff Tinkera53d6552017-01-20 00:31:46 -080072static inline int getCallingPid() {
73 return IPCThreadState::self()->getCallingPid();
74}
75
76static bool checkPermission(const char* permissionString) {
77 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
78 bool ok = checkCallingPermission(String16(permissionString));
79 if (!ok) ALOGE("Request requires %s", permissionString);
80 return ok;
81}
82
83static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
84 Vector<uint8_t> vector;
85 vector.appendArray(vec.data(), vec.size());
86 return *const_cast<const Vector<uint8_t> *>(&vector);
87}
88
89static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
90 hidl_vec<uint8_t> vec;
91 vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
92 return vec;
93}
94
95static String8 toString8(const hidl_string &string) {
96 return String8(string.c_str());
97}
98
99static hidl_string toHidlString(const String8& string) {
100 return hidl_string(string.string());
101}
102
Jeff Tinker987ac702018-02-15 17:02:22 -0800103std::string toHexString(const std::string& str) {
Adam Stonefb679e32018-02-07 10:25:48 -0800104 std::ostringstream out;
105 out << std::hex << std::setfill('0');
106 for (size_t i = 0; i < str.size(); i++) {
107 out << std::setw(2) << (int)(str[i]);
108 }
109 return out.str();
110}
111
Jeff Tinker6d998b62017-12-18 14:37:43 -0800112static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
113 switch(level) {
114 case SecurityLevel::SW_SECURE_CRYPTO:
115 return DrmPlugin::kSecurityLevelSwSecureCrypto;
116 case SecurityLevel::SW_SECURE_DECODE:
117 return DrmPlugin::kSecurityLevelSwSecureDecode;
118 case SecurityLevel::HW_SECURE_CRYPTO:
119 return DrmPlugin::kSecurityLevelHwSecureCrypto;
120 case SecurityLevel::HW_SECURE_DECODE:
121 return DrmPlugin::kSecurityLevelHwSecureDecode;
122 case SecurityLevel::HW_SECURE_ALL:
123 return DrmPlugin::kSecurityLevelHwSecureAll;
124 default:
125 return DrmPlugin::kSecurityLevelUnknown;
126 }
127}
128
129static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
130 switch(level) {
131 case HdcpLevel::HDCP_NONE:
132 return DrmPlugin::kHdcpNone;
133 case HdcpLevel::HDCP_V1:
134 return DrmPlugin::kHdcpV1;
135 case HdcpLevel::HDCP_V2:
136 return DrmPlugin::kHdcpV2;
137 case HdcpLevel::HDCP_V2_1:
138 return DrmPlugin::kHdcpV2_1;
139 case HdcpLevel::HDCP_V2_2:
140 return DrmPlugin::kHdcpV2_2;
141 case HdcpLevel::HDCP_NO_OUTPUT:
142 return DrmPlugin::kHdcpNoOutput;
143 default:
144 return DrmPlugin::kHdcpLevelUnknown;
145 }
146}
147
Jeff Tinkera53d6552017-01-20 00:31:46 -0800148
149static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
150 keyedVector) {
151 std::vector<KeyValue> stdKeyedVector;
152 for (size_t i = 0; i < keyedVector.size(); i++) {
153 KeyValue keyValue;
154 keyValue.key = toHidlString(keyedVector.keyAt(i));
155 keyValue.value = toHidlString(keyedVector.valueAt(i));
156 stdKeyedVector.push_back(keyValue);
157 }
158 return ::KeyedVector(stdKeyedVector);
159}
160
161static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
162 hKeyedVector) {
163 KeyedVector<String8, String8> keyedVector;
164 for (size_t i = 0; i < hKeyedVector.size(); i++) {
165 keyedVector.add(toString8(hKeyedVector[i].key),
166 toString8(hKeyedVector[i].value));
167 }
168 return keyedVector;
169}
170
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800171static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
Jeff Tinkera53d6552017-01-20 00:31:46 -0800172 hSecureStops) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800173 List<Vector<uint8_t>> secureStops;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800174 for (size_t i = 0; i < hSecureStops.size(); i++) {
175 secureStops.push_back(toVector(hSecureStops[i].opaqueData));
176 }
177 return secureStops;
178}
179
Jeff Tinker15177d72018-01-25 12:57:55 -0800180static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
181 hSecureStopIds) {
182 List<Vector<uint8_t>> secureStopIds;
183 for (size_t i = 0; i < hSecureStopIds.size(); i++) {
184 secureStopIds.push_back(toVector(hSecureStopIds[i]));
185 }
186 return secureStopIds;
187}
188
Jeff Tinkera53d6552017-01-20 00:31:46 -0800189static status_t toStatusT(Status status) {
190 switch (status) {
191 case Status::OK:
192 return OK;
193 break;
194 case Status::ERROR_DRM_NO_LICENSE:
195 return ERROR_DRM_NO_LICENSE;
196 break;
197 case Status::ERROR_DRM_LICENSE_EXPIRED:
198 return ERROR_DRM_LICENSE_EXPIRED;
199 break;
200 case Status::ERROR_DRM_SESSION_NOT_OPENED:
201 return ERROR_DRM_SESSION_NOT_OPENED;
202 break;
203 case Status::ERROR_DRM_CANNOT_HANDLE:
204 return ERROR_DRM_CANNOT_HANDLE;
205 break;
206 case Status::ERROR_DRM_INVALID_STATE:
207 return ERROR_DRM_TAMPER_DETECTED;
208 break;
209 case Status::BAD_VALUE:
210 return BAD_VALUE;
211 break;
212 case Status::ERROR_DRM_NOT_PROVISIONED:
213 return ERROR_DRM_NOT_PROVISIONED;
214 break;
215 case Status::ERROR_DRM_RESOURCE_BUSY:
216 return ERROR_DRM_RESOURCE_BUSY;
217 break;
218 case Status::ERROR_DRM_DEVICE_REVOKED:
219 return ERROR_DRM_DEVICE_REVOKED;
220 break;
221 case Status::ERROR_DRM_UNKNOWN:
222 default:
223 return ERROR_DRM_UNKNOWN;
224 break;
225 }
226}
227
228
229Mutex DrmHal::mLock;
230
231struct DrmSessionClient : public DrmSessionClientInterface {
232 explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
233
234 virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
235 sp<DrmHal> drm = mDrm.promote();
236 if (drm == NULL) {
237 return true;
238 }
239 status_t err = drm->closeSession(sessionId);
240 if (err != OK) {
241 return false;
242 }
243 drm->sendEvent(EventType::SESSION_RECLAIMED,
244 toHidlVec(sessionId), hidl_vec<uint8_t>());
245 return true;
246 }
247
248protected:
249 virtual ~DrmSessionClient() {}
250
251private:
252 wp<DrmHal> mDrm;
253
254 DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
255};
256
257DrmHal::DrmHal()
258 : mDrmSessionClient(new DrmSessionClient(this)),
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800259 mFactories(makeDrmFactories()),
260 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800261}
262
Jeff Tinker61332812017-05-15 16:53:10 -0700263void DrmHal::closeOpenSessions() {
264 if (mPlugin != NULL) {
Jeff Tinkerb2b66fa2018-01-30 19:19:34 +0000265 for (size_t i = 0; i < mOpenSessions.size(); i++) {
266 mPlugin->closeSession(toHidlVec(mOpenSessions[i]));
267 DrmSessionManager::Instance()->removeSession(mOpenSessions[i]);
Jeff Tinker61332812017-05-15 16:53:10 -0700268 }
269 }
270 mOpenSessions.clear();
271}
272
Jeff Tinkera53d6552017-01-20 00:31:46 -0800273DrmHal::~DrmHal() {
Jeff Tinker61332812017-05-15 16:53:10 -0700274 closeOpenSessions();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800275 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
276}
277
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800278Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
279 Vector<sp<IDrmFactory>> factories;
280
Jeff Tinker593111f2017-05-25 16:00:21 -0700281 auto manager = hardware::defaultServiceManager();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800282
283 if (manager != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000284 manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800285 [&factories](const hidl_vec<hidl_string> &registered) {
286 for (const auto &instance : registered) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000287 auto factory = drm::V1_0::IDrmFactory::getService(instance);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800288 if (factory != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000289 ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str());
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800290 factories.push_back(factory);
Jeff Tinkere307dc42018-02-11 19:53:54 +0000291 }
292 }
293 }
294 );
295 manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
296 [&factories](const hidl_vec<hidl_string> &registered) {
297 for (const auto &instance : registered) {
298 auto factory = drm::V1_1::IDrmFactory::getService(instance);
299 if (factory != NULL) {
300 ALOGD("found drm@1.1 IDrmFactory %s", instance.c_str());
301 factories.push_back(factory);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800302 }
303 }
304 }
305 );
Jeff Tinkera53d6552017-01-20 00:31:46 -0800306 }
Jeff Tinkerc82b9c32017-02-14 11:39:51 -0800307
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800308 if (factories.size() == 0) {
309 // must be in passthrough mode, load the default passthrough service
Jeff Tinkere309b222017-04-05 08:01:28 -0700310 auto passthrough = IDrmFactory::getService();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800311 if (passthrough != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000312 ALOGI("makeDrmFactories: using default passthrough drm instance");
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800313 factories.push_back(passthrough);
314 } else {
315 ALOGE("Failed to find any drm factories");
316 }
317 }
318 return factories;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800319}
320
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800321sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
322 const uint8_t uuid[16], const String8& appPackageName) {
Adam Stonefb679e32018-02-07 10:25:48 -0800323 mMetrics.SetAppPackageName(appPackageName);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800324
325 sp<IDrmPlugin> plugin;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800326 Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
Jeff Tinkera53d6552017-01-20 00:31:46 -0800327 [&](Status status, const sp<IDrmPlugin>& hPlugin) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800328 if (status != Status::OK) {
329 ALOGE("Failed to make drm plugin");
330 return;
331 }
332 plugin = hPlugin;
333 }
334 );
Jeff Tinkerf0e89b02017-08-07 15:58:41 -0700335
336 if (!hResult.isOk()) {
337 ALOGE("createPlugin remote call failed");
338 }
339
Jeff Tinkera53d6552017-01-20 00:31:46 -0800340 return plugin;
341}
342
343status_t DrmHal::initCheck() const {
344 return mInitCheck;
345}
346
347status_t DrmHal::setListener(const sp<IDrmClient>& listener)
348{
349 Mutex::Autolock lock(mEventLock);
350 if (mListener != NULL){
351 IInterface::asBinder(mListener)->unlinkToDeath(this);
352 }
353 if (listener != NULL) {
354 IInterface::asBinder(listener)->linkToDeath(this);
355 }
356 mListener = listener;
357 return NO_ERROR;
358}
359
360Return<void> DrmHal::sendEvent(EventType hEventType,
361 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
Adam Stonecea91ce2018-01-22 19:23:28 -0800362 mMetrics.mEventCounter.Increment(hEventType);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800363
364 mEventLock.lock();
365 sp<IDrmClient> listener = mListener;
366 mEventLock.unlock();
367
368 if (listener != NULL) {
369 Parcel obj;
370 writeByteArray(obj, sessionId);
371 writeByteArray(obj, data);
372
373 Mutex::Autolock lock(mNotifyLock);
374 DrmPlugin::EventType eventType;
375 switch(hEventType) {
376 case EventType::PROVISION_REQUIRED:
377 eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
378 break;
379 case EventType::KEY_NEEDED:
380 eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
381 break;
382 case EventType::KEY_EXPIRED:
383 eventType = DrmPlugin::kDrmPluginEventKeyExpired;
384 break;
385 case EventType::VENDOR_DEFINED:
386 eventType = DrmPlugin::kDrmPluginEventVendorDefined;
387 break;
Rahul Friasb86f4b32017-03-27 15:13:30 -0700388 case EventType::SESSION_RECLAIMED:
389 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
390 break;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800391 default:
392 return Void();
393 }
394 listener->notify(eventType, 0, &obj);
395 }
396 return Void();
397}
398
399Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
400 int64_t expiryTimeInMS) {
401
402 mEventLock.lock();
403 sp<IDrmClient> listener = mListener;
404 mEventLock.unlock();
405
406 if (listener != NULL) {
407 Parcel obj;
408 writeByteArray(obj, sessionId);
409 obj.writeInt64(expiryTimeInMS);
410
411 Mutex::Autolock lock(mNotifyLock);
412 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
413 }
414 return Void();
415}
416
417Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
418 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
419
420 mEventLock.lock();
421 sp<IDrmClient> listener = mListener;
422 mEventLock.unlock();
423
424 if (listener != NULL) {
425 Parcel obj;
426 writeByteArray(obj, sessionId);
427
428 size_t nKeys = keyStatusList.size();
429 obj.writeInt32(nKeys);
430 for (size_t i = 0; i < nKeys; ++i) {
431 const KeyStatus &keyStatus = keyStatusList[i];
432 writeByteArray(obj, keyStatus.keyId);
433 uint32_t type;
434 switch(keyStatus.type) {
435 case KeyStatusType::USABLE:
436 type = DrmPlugin::kKeyStatusType_Usable;
437 break;
438 case KeyStatusType::EXPIRED:
439 type = DrmPlugin::kKeyStatusType_Expired;
440 break;
441 case KeyStatusType::OUTPUTNOTALLOWED:
442 type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
443 break;
444 case KeyStatusType::STATUSPENDING:
445 type = DrmPlugin::kKeyStatusType_StatusPending;
446 break;
447 case KeyStatusType::INTERNALERROR:
448 default:
449 type = DrmPlugin::kKeyStatusType_InternalError;
450 break;
451 }
452 obj.writeInt32(type);
Adam Stonecea91ce2018-01-22 19:23:28 -0800453 mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800454 }
455 obj.writeInt32(hasNewUsableKey);
456
457 Mutex::Autolock lock(mNotifyLock);
458 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
Adam Stonecea91ce2018-01-22 19:23:28 -0800459 } else {
460 // There's no listener. But we still want to count the key change
461 // events.
462 size_t nKeys = keyStatusList.size();
463 for (size_t i = 0; i < nKeys; i++) {
464 mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
465 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800466 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800467
Jeff Tinkera53d6552017-01-20 00:31:46 -0800468 return Void();
469}
470
471bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
472 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800473
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800474 for (size_t i = 0; i < mFactories.size(); i++) {
475 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
476 if (mimeType != "") {
477 if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
478 return true;
479 }
480 } else {
481 return true;
482 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800483 }
484 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800485 return false;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800486}
487
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800488status_t DrmHal::createPlugin(const uint8_t uuid[16],
489 const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800490 Mutex::Autolock autoLock(mLock);
491
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800492 for (size_t i = 0; i < mFactories.size(); i++) {
493 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
494 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
Edwin Wong5641aa22018-01-30 17:52:21 -0800495 if (mPlugin != NULL) {
496 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
497 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800498 }
499 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800500
501 if (mPlugin == NULL) {
502 mInitCheck = ERROR_UNSUPPORTED;
503 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700504 if (!mPlugin->setListener(this).isOk()) {
505 mInitCheck = DEAD_OBJECT;
506 } else {
507 mInitCheck = OK;
508 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800509 }
510
511 return mInitCheck;
512}
513
514status_t DrmHal::destroyPlugin() {
515 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800516 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800517
Jeff Tinker61332812017-05-15 16:53:10 -0700518 closeOpenSessions();
Adam Stonefb679e32018-02-07 10:25:48 -0800519 reportPluginMetrics();
520 reportFrameworkMetrics();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800521 setListener(NULL);
Jeff Tinker70367f52017-06-16 12:41:33 -0700522 mInitCheck = NO_INIT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800523
Jeff Tinker319d5f42017-07-26 15:44:33 -0700524 if (mPlugin != NULL) {
525 if (!mPlugin->setListener(NULL).isOk()) {
526 mInitCheck = DEAD_OBJECT;
527 }
528 }
529 mPlugin.clear();
Edwin Wong5641aa22018-01-30 17:52:21 -0800530 mPluginV1_1.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800531 return OK;
532}
533
Jeff Tinker41d279a2018-02-11 19:52:08 +0000534status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
535 Vector<uint8_t> &sessionId) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800536 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800537 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800538
Jeff Tinker41d279a2018-02-11 19:52:08 +0000539 SecurityLevel hSecurityLevel;
540 bool setSecurityLevel = true;
Tobias Thierer5f5e43f2018-02-11 15:00:57 +0000541
Jeff Tinker41d279a2018-02-11 19:52:08 +0000542 switch(level) {
543 case DrmPlugin::kSecurityLevelSwSecureCrypto:
544 hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
545 break;
546 case DrmPlugin::kSecurityLevelSwSecureDecode:
547 hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
548 break;
549 case DrmPlugin::kSecurityLevelHwSecureCrypto:
550 hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
551 break;
552 case DrmPlugin::kSecurityLevelHwSecureDecode:
553 hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
554 break;
555 case DrmPlugin::kSecurityLevelHwSecureAll:
556 hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
557 break;
558 case DrmPlugin::kSecurityLevelMax:
559 setSecurityLevel = false;
560 break;
561 default:
562 return ERROR_DRM_CANNOT_HANDLE;
563 }
564
565 status_t err = UNKNOWN_ERROR;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800566 bool retry = true;
567 do {
568 hidl_vec<uint8_t> hSessionId;
569
Jeff Tinker41d279a2018-02-11 19:52:08 +0000570 Return<void> hResult;
571 if (mPluginV1_1 == NULL || !setSecurityLevel) {
572 hResult = mPlugin->openSession(
573 [&](Status status,const hidl_vec<uint8_t>& id) {
574 if (status == Status::OK) {
575 sessionId = toVector(id);
576 }
577 err = toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800578 }
Jeff Tinker41d279a2018-02-11 19:52:08 +0000579 );
580 } else {
581 hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
582 [&](Status status, const hidl_vec<uint8_t>& id) {
583 if (status == Status::OK) {
584 sessionId = toVector(id);
585 }
586 err = toStatusT(status);
587 }
588 );
589 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800590
591 if (!hResult.isOk()) {
592 err = DEAD_OBJECT;
593 }
594
595 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
596 mLock.unlock();
597 // reclaimSession may call back to closeSession, since mLock is
598 // shared between Drm instances, we should unlock here to avoid
599 // deadlock.
600 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
601 mLock.lock();
602 } else {
603 retry = false;
604 }
605 } while (retry);
606
607 if (err == OK) {
608 DrmSessionManager::Instance()->addSession(getCallingPid(),
609 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700610 mOpenSessions.push(sessionId);
Adam Stone568b3c42018-01-31 12:57:16 -0800611 mMetrics.SetSessionStart(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800612 }
Adam Stoneaaf87dd2018-01-08 11:55:06 -0800613
Adam Stonef0e618d2018-01-17 19:20:41 -0800614 mMetrics.mOpenSessionCounter.Increment(err);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800615 return err;
616}
617
618status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
619 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800620 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800621
Jeff Tinker319d5f42017-07-26 15:44:33 -0700622 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
623 if (status.isOk()) {
624 if (status == Status::OK) {
625 DrmSessionManager::Instance()->removeSession(sessionId);
626 for (size_t i = 0; i < mOpenSessions.size(); i++) {
627 if (mOpenSessions[i] == sessionId) {
628 mOpenSessions.removeAt(i);
629 break;
630 }
Jeff Tinker61332812017-05-15 16:53:10 -0700631 }
632 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800633 status_t response = toStatusT(status);
Adam Stone568b3c42018-01-31 12:57:16 -0800634 mMetrics.SetSessionEnd(sessionId);
Adam Stonecea91ce2018-01-22 19:23:28 -0800635 mMetrics.mCloseSessionCounter.Increment(response);
Adam Stonefb679e32018-02-07 10:25:48 -0800636 reportPluginMetrics();
Adam Stonecea91ce2018-01-22 19:23:28 -0800637 return response;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800638 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800639 mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
Jeff Tinker319d5f42017-07-26 15:44:33 -0700640 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800641}
642
643status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
644 Vector<uint8_t> const &initData, String8 const &mimeType,
645 DrmPlugin::KeyType keyType, KeyedVector<String8,
646 String8> const &optionalParameters, Vector<uint8_t> &request,
647 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
648 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800649 INIT_CHECK();
Adam Stonefb679e32018-02-07 10:25:48 -0800650 EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800651
652 DrmSessionManager::Instance()->useSession(sessionId);
653
654 KeyType hKeyType;
655 if (keyType == DrmPlugin::kKeyType_Streaming) {
656 hKeyType = KeyType::STREAMING;
657 } else if (keyType == DrmPlugin::kKeyType_Offline) {
658 hKeyType = KeyType::OFFLINE;
659 } else if (keyType == DrmPlugin::kKeyType_Release) {
660 hKeyType = KeyType::RELEASE;
661 } else {
Adam Stonef0e618d2018-01-17 19:20:41 -0800662 keyRequestTimer.SetAttribute(BAD_VALUE);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800663 return BAD_VALUE;
664 }
665
666 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
667
668 status_t err = UNKNOWN_ERROR;
669
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800670 if (mPluginV1_1 != NULL) {
671 Return<void> hResult =
672 mPluginV1_1->getKeyRequest_1_1(
673 toHidlVec(sessionId), toHidlVec(initData),
674 toHidlString(mimeType), hKeyType, hOptionalParameters,
675 [&](Status status, const hidl_vec<uint8_t>& hRequest,
676 drm::V1_1::KeyRequestType hKeyRequestType,
677 const hidl_string& hDefaultUrl) {
678
679 if (status == Status::OK) {
680 request = toVector(hRequest);
681 defaultUrl = toString8(hDefaultUrl);
682
683 switch (hKeyRequestType) {
684 case drm::V1_1::KeyRequestType::INITIAL:
685 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
686 break;
687 case drm::V1_1::KeyRequestType::RENEWAL:
688 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
689 break;
690 case drm::V1_1::KeyRequestType::RELEASE:
691 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
692 break;
693 case drm::V1_1::KeyRequestType::NONE:
694 *keyRequestType = DrmPlugin::kKeyRequestType_None;
695 break;
696 case drm::V1_1::KeyRequestType::UPDATE:
697 *keyRequestType = DrmPlugin::kKeyRequestType_Update;
698 break;
699 default:
700 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
701 break;
702 }
703 err = toStatusT(status);
704 }
705 });
706 return hResult.isOk() ? err : DEAD_OBJECT;
707 }
708
Jeff Tinkera53d6552017-01-20 00:31:46 -0800709 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
710 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
711 [&](Status status, const hidl_vec<uint8_t>& hRequest,
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800712 drm::V1_0::KeyRequestType hKeyRequestType,
713 const hidl_string& hDefaultUrl) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800714
715 if (status == Status::OK) {
716 request = toVector(hRequest);
717 defaultUrl = toString8(hDefaultUrl);
718
719 switch (hKeyRequestType) {
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800720 case drm::V1_0::KeyRequestType::INITIAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800721 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
722 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800723 case drm::V1_0::KeyRequestType::RENEWAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800724 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
725 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800726 case drm::V1_0::KeyRequestType::RELEASE:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800727 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
728 break;
729 default:
730 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
731 break;
732 }
733 err = toStatusT(status);
734 }
735 });
736
Adam Stonef0e618d2018-01-17 19:20:41 -0800737 err = hResult.isOk() ? err : DEAD_OBJECT;
738 keyRequestTimer.SetAttribute(err);
739 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800740}
741
742status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
743 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
744 Mutex::Autolock autoLock(mLock);
Adam Stonefb679e32018-02-07 10:25:48 -0800745 EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800746
Jeff Tinker6d998b62017-12-18 14:37:43 -0800747 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800748
749 DrmSessionManager::Instance()->useSession(sessionId);
750
751 status_t err = UNKNOWN_ERROR;
752
753 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
754 toHidlVec(response),
755 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
756 if (status == Status::OK) {
757 keySetId = toVector(hKeySetId);
758 }
759 err = toStatusT(status);
760 }
761 );
Adam Stonecea91ce2018-01-22 19:23:28 -0800762 err = hResult.isOk() ? err : DEAD_OBJECT;
763 keyResponseTimer.SetAttribute(err);
764 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800765}
766
767status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
768 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800769 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800770
771 return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
772}
773
774status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
775 Vector<uint8_t> const &keySetId) {
776 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800777 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800778
779 DrmSessionManager::Instance()->useSession(sessionId);
780
781 return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
782 toHidlVec(keySetId)));
783}
784
785status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
786 KeyedVector<String8, String8> &infoMap) const {
787 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800788 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800789
790 DrmSessionManager::Instance()->useSession(sessionId);
791
792 ::KeyedVector hInfoMap;
793
794 status_t err = UNKNOWN_ERROR;
795
796 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
797 [&](Status status, const hidl_vec<KeyValue>& map) {
798 if (status == Status::OK) {
799 infoMap = toKeyedVector(map);
800 }
801 err = toStatusT(status);
802 }
803 );
804
805 return hResult.isOk() ? err : DEAD_OBJECT;
806}
807
808status_t DrmHal::getProvisionRequest(String8 const &certType,
809 String8 const &certAuthority, Vector<uint8_t> &request,
810 String8 &defaultUrl) {
811 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800812 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800813
814 status_t err = UNKNOWN_ERROR;
815
816 Return<void> hResult = mPlugin->getProvisionRequest(
817 toHidlString(certType), toHidlString(certAuthority),
818 [&](Status status, const hidl_vec<uint8_t>& hRequest,
819 const hidl_string& hDefaultUrl) {
820 if (status == Status::OK) {
821 request = toVector(hRequest);
822 defaultUrl = toString8(hDefaultUrl);
823 }
824 err = toStatusT(status);
825 }
826 );
827
Adam Stonecea91ce2018-01-22 19:23:28 -0800828 err = hResult.isOk() ? err : DEAD_OBJECT;
829 mMetrics.mGetProvisionRequestCounter.Increment(err);
830 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800831}
832
833status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800834 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800835 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800836 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800837
838 status_t err = UNKNOWN_ERROR;
839
840 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
841 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
842 const hidl_vec<uint8_t>& hWrappedKey) {
843 if (status == Status::OK) {
844 certificate = toVector(hCertificate);
845 wrappedKey = toVector(hWrappedKey);
846 }
847 err = toStatusT(status);
848 }
849 );
850
Adam Stonecea91ce2018-01-22 19:23:28 -0800851 err = hResult.isOk() ? err : DEAD_OBJECT;
852 mMetrics.mProvideProvisionResponseCounter.Increment(err);
853 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800854}
855
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800856status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800857 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800858 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800859
860 status_t err = UNKNOWN_ERROR;
861
862 Return<void> hResult = mPlugin->getSecureStops(
863 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
864 if (status == Status::OK) {
865 secureStops = toSecureStops(hSecureStops);
866 }
867 err = toStatusT(status);
868 }
869 );
870
871 return hResult.isOk() ? err : DEAD_OBJECT;
872}
873
874
Jeff Tinker15177d72018-01-25 12:57:55 -0800875status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
876 Mutex::Autolock autoLock(mLock);
877
878 if (mInitCheck != OK) {
879 return mInitCheck;
880 }
881
882 if (mPluginV1_1 == NULL) {
883 return ERROR_DRM_CANNOT_HANDLE;
884 }
885
886 status_t err = UNKNOWN_ERROR;
887
888 Return<void> hResult = mPluginV1_1->getSecureStopIds(
889 [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
890 if (status == Status::OK) {
891 secureStopIds = toSecureStopIds(hSecureStopIds);
892 }
893 err = toStatusT(status);
894 }
895 );
896
897 return hResult.isOk() ? err : DEAD_OBJECT;
898}
899
900
Jeff Tinkera53d6552017-01-20 00:31:46 -0800901status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
902 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800903 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800904
905 status_t err = UNKNOWN_ERROR;
906
907 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
908 [&](Status status, const SecureStop& hSecureStop) {
909 if (status == Status::OK) {
910 secureStop = toVector(hSecureStop.opaqueData);
911 }
912 err = toStatusT(status);
913 }
914 );
915
916 return hResult.isOk() ? err : DEAD_OBJECT;
917}
918
919status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
920 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800921 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800922
Jeff Tinker15177d72018-01-25 12:57:55 -0800923 if (mPluginV1_1 != NULL) {
924 SecureStopRelease secureStopRelease;
925 secureStopRelease.opaqueData = toHidlVec(ssRelease);
926 return toStatusT(mPluginV1_1->releaseSecureStops(secureStopRelease));
927 }
928
Jeff Tinkera53d6552017-01-20 00:31:46 -0800929 return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
930}
931
Jeff Tinker15177d72018-01-25 12:57:55 -0800932status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
933 Mutex::Autolock autoLock(mLock);
934
935 if (mInitCheck != OK) {
936 return mInitCheck;
937 }
938
939 if (mPluginV1_1 == NULL) {
940 return ERROR_DRM_CANNOT_HANDLE;
941 }
942
943 return toStatusT(mPluginV1_1->removeSecureStop(toHidlVec(ssid)));
944}
945
946status_t DrmHal::removeAllSecureStops() {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800947 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800948 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800949
Jeff Tinker15177d72018-01-25 12:57:55 -0800950 if (mPluginV1_1 != NULL) {
951 return toStatusT(mPluginV1_1->removeAllSecureStops());
952 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800953 return toStatusT(mPlugin->releaseAllSecureStops());
954}
955
Jeff Tinker6d998b62017-12-18 14:37:43 -0800956status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
957 DrmPlugin::HdcpLevel *max) const {
958 Mutex::Autolock autoLock(mLock);
959 INIT_CHECK();
960
961 if (connected == NULL || max == NULL) {
962 return BAD_VALUE;
963 }
964 status_t err = UNKNOWN_ERROR;
965
966 if (mPluginV1_1 == NULL) {
967 return ERROR_DRM_CANNOT_HANDLE;
968 }
969
970 *connected = DrmPlugin::kHdcpLevelUnknown;
971 *max = DrmPlugin::kHdcpLevelUnknown;
972
973 Return<void> hResult = mPluginV1_1->getHdcpLevels(
974 [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
975 if (status == Status::OK) {
976 *connected = toHdcpLevel(hConnected);
977 *max = toHdcpLevel(hMax);
978 }
979 err = toStatusT(status);
980 }
981 );
982
983 return hResult.isOk() ? err : DEAD_OBJECT;
984}
985
986status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
987 Mutex::Autolock autoLock(mLock);
988 INIT_CHECK();
989
990 if (open == NULL || max == NULL) {
991 return BAD_VALUE;
992 }
993 status_t err = UNKNOWN_ERROR;
994
995 *open = 0;
996 *max = 0;
997
998 if (mPluginV1_1 == NULL) {
999 return ERROR_DRM_CANNOT_HANDLE;
1000 }
1001
1002 Return<void> hResult = mPluginV1_1->getNumberOfSessions(
1003 [&](Status status, uint32_t hOpen, uint32_t hMax) {
1004 if (status == Status::OK) {
1005 *open = hOpen;
1006 *max = hMax;
1007 }
1008 err = toStatusT(status);
1009 }
1010 );
1011
1012 return hResult.isOk() ? err : DEAD_OBJECT;
1013}
1014
1015status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
1016 DrmPlugin::SecurityLevel *level) const {
1017 Mutex::Autolock autoLock(mLock);
1018 INIT_CHECK();
1019
1020 if (level == NULL) {
1021 return BAD_VALUE;
1022 }
1023 status_t err = UNKNOWN_ERROR;
1024
1025 if (mPluginV1_1 == NULL) {
1026 return ERROR_DRM_CANNOT_HANDLE;
1027 }
1028
1029 *level = DrmPlugin::kSecurityLevelUnknown;
1030
1031 Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
1032 [&](Status status, SecurityLevel hLevel) {
1033 if (status == Status::OK) {
1034 *level = toSecurityLevel(hLevel);
1035 }
1036 err = toStatusT(status);
1037 }
1038 );
1039
1040 return hResult.isOk() ? err : DEAD_OBJECT;
1041}
1042
Jeff Tinkera53d6552017-01-20 00:31:46 -08001043status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
1044 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001045 return getPropertyStringInternal(name, value);
1046}
1047
1048status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
1049 // This function is internal to the class and should only be called while
1050 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001051 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001052
1053 status_t err = UNKNOWN_ERROR;
1054
1055 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
1056 [&](Status status, const hidl_string& hValue) {
1057 if (status == Status::OK) {
1058 value = toString8(hValue);
1059 }
1060 err = toStatusT(status);
1061 }
1062 );
1063
1064 return hResult.isOk() ? err : DEAD_OBJECT;
1065}
1066
1067status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
1068 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001069 return getPropertyByteArrayInternal(name, value);
1070}
1071
1072status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
1073 // This function is internal to the class and should only be called while
1074 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001075 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001076
1077 status_t err = UNKNOWN_ERROR;
1078
1079 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
1080 [&](Status status, const hidl_vec<uint8_t>& hValue) {
1081 if (status == Status::OK) {
1082 value = toVector(hValue);
1083 }
1084 err = toStatusT(status);
1085 }
1086 );
1087
Adam Stonecea91ce2018-01-22 19:23:28 -08001088 err = hResult.isOk() ? err : DEAD_OBJECT;
1089 if (name == kPropertyDeviceUniqueId) {
1090 mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
1091 }
1092 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001093}
1094
1095status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
1096 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001097 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001098
Jeff Tinker6d998b62017-12-18 14:37:43 -08001099 Status status = mPlugin->setPropertyString(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001100 toHidlString(value));
1101 return toStatusT(status);
1102}
1103
1104status_t DrmHal::setPropertyByteArray(String8 const &name,
1105 Vector<uint8_t> const &value ) const {
1106 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001107 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001108
1109 Status status = mPlugin->setPropertyByteArray(toHidlString(name),
1110 toHidlVec(value));
1111 return toStatusT(status);
1112}
1113
Adam Stone637b7852018-01-30 12:09:36 -08001114status_t DrmHal::getMetrics(PersistableBundle* item) {
Adam Stonef0e618d2018-01-17 19:20:41 -08001115 if (item == nullptr) {
1116 return UNEXPECTED_NULL;
1117 }
1118
1119 mMetrics.Export(item);
Adam Stoneab394d12017-12-22 12:34:20 -08001120 return OK;
1121}
Jeff Tinkera53d6552017-01-20 00:31:46 -08001122
1123status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
1124 String8 const &algorithm) {
1125 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001126 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001127
1128 DrmSessionManager::Instance()->useSession(sessionId);
1129
1130 Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
1131 toHidlString(algorithm));
1132 return toStatusT(status);
1133}
1134
1135status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
1136 String8 const &algorithm) {
1137 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001138 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001139
1140 DrmSessionManager::Instance()->useSession(sessionId);
1141
1142 Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
1143 toHidlString(algorithm));
1144 return toStatusT(status);
1145}
1146
1147status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001148 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1149 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001150 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001151 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001152
1153 DrmSessionManager::Instance()->useSession(sessionId);
1154
1155 status_t err = UNKNOWN_ERROR;
1156
1157 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
1158 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1159 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1160 if (status == Status::OK) {
1161 output = toVector(hOutput);
1162 }
1163 err = toStatusT(status);
1164 }
1165 );
1166
1167 return hResult.isOk() ? err : DEAD_OBJECT;
1168}
1169
1170status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001171 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1172 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001173 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001174 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001175
1176 DrmSessionManager::Instance()->useSession(sessionId);
1177
1178 status_t err = UNKNOWN_ERROR;
1179
1180 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
1181 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1182 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1183 if (status == Status::OK) {
1184 output = toVector(hOutput);
1185 }
1186 err = toStatusT(status);
1187 }
1188 );
1189
1190 return hResult.isOk() ? err : DEAD_OBJECT;
1191}
1192
1193status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001194 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1195 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001196 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001197 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001198
1199 DrmSessionManager::Instance()->useSession(sessionId);
1200
1201 status_t err = UNKNOWN_ERROR;
1202
1203 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
1204 toHidlVec(keyId), toHidlVec(message),
1205 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1206 if (status == Status::OK) {
1207 signature = toVector(hSignature);
1208 }
1209 err = toStatusT(status);
1210 }
1211 );
1212
1213 return hResult.isOk() ? err : DEAD_OBJECT;
1214}
1215
1216status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001217 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1218 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001219 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001220 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001221
1222 DrmSessionManager::Instance()->useSession(sessionId);
1223
1224 status_t err = UNKNOWN_ERROR;
1225
1226 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
1227 toHidlVec(message), toHidlVec(signature),
1228 [&](Status status, bool hMatch) {
1229 if (status == Status::OK) {
1230 match = hMatch;
1231 } else {
1232 match = false;
1233 }
1234 err = toStatusT(status);
1235 }
1236 );
1237
1238 return hResult.isOk() ? err : DEAD_OBJECT;
1239}
1240
1241status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001242 String8 const &algorithm, Vector<uint8_t> const &message,
1243 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001244 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001245 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001246
1247 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
1248 return -EPERM;
1249 }
1250
1251 DrmSessionManager::Instance()->useSession(sessionId);
1252
1253 status_t err = UNKNOWN_ERROR;
1254
1255 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1256 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1257 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1258 if (status == Status::OK) {
1259 signature = toVector(hSignature);
1260 }
1261 err = toStatusT(status);
1262 }
1263 );
1264
1265 return hResult.isOk() ? err : DEAD_OBJECT;
1266}
1267
1268void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1269{
Jeff Tinkera53d6552017-01-20 00:31:46 -08001270 Mutex::Autolock autoLock(mLock);
Jeff Tinker61332812017-05-15 16:53:10 -07001271 closeOpenSessions();
Jeff Tinker3e289162017-06-01 11:13:53 -07001272 setListener(NULL);
Jeff Tinker319d5f42017-07-26 15:44:33 -07001273 mInitCheck = NO_INIT;
1274
Jeff Tinker70367f52017-06-16 12:41:33 -07001275 if (mPlugin != NULL) {
Jeff Tinker319d5f42017-07-26 15:44:33 -07001276 if (!mPlugin->setListener(NULL).isOk()) {
1277 mInitCheck = DEAD_OBJECT;
1278 }
Jeff Tinker70367f52017-06-16 12:41:33 -07001279 }
Jeff Tinkera53d6552017-01-20 00:31:46 -08001280 mPlugin.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001281}
1282
1283void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1284{
1285 if (vec.size()) {
1286 obj.writeInt32(vec.size());
1287 obj.write(vec.data(), vec.size());
1288 } else {
1289 obj.writeInt32(0);
1290 }
1291}
1292
Adam Stonefb679e32018-02-07 10:25:48 -08001293void DrmHal::reportFrameworkMetrics() const
1294{
1295 MediaAnalyticsItem item("mediadrm");
1296 item.generateSessionID();
1297 item.setPkgName(mMetrics.GetAppPackageName().c_str());
1298 String8 vendor;
1299 String8 description;
1300 status_t result = getPropertyStringInternal(String8("vendor"), vendor);
1301 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001302 ALOGE("Failed to get vendor from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001303 } else {
1304 item.setCString("vendor", vendor.c_str());
1305 }
1306 result = getPropertyStringInternal(String8("description"), description);
1307 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001308 ALOGE("Failed to get description from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001309 } else {
1310 item.setCString("description", description.c_str());
1311 }
Adam Stoneab394d12017-12-22 12:34:20 -08001312
Adam Stonefb679e32018-02-07 10:25:48 -08001313 std::string serializedMetrics;
1314 result = mMetrics.GetSerializedMetrics(&serializedMetrics);
1315 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001316 ALOGE("Failed to serialize framework metrics: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001317 }
Jeff Tinker987ac702018-02-15 17:02:22 -08001318 serializedMetrics = toHexString(serializedMetrics);
Adam Stonefb679e32018-02-07 10:25:48 -08001319 if (!serializedMetrics.empty()) {
1320 item.setCString("serialized_metrics", serializedMetrics.c_str());
1321 }
1322 if (!item.selfrecord()) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001323 ALOGE("Failed to self record framework metrics");
Adam Stonefb679e32018-02-07 10:25:48 -08001324 }
1325}
1326
1327void DrmHal::reportPluginMetrics() const
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001328{
1329 Vector<uint8_t> metrics;
1330 String8 vendor;
1331 String8 description;
1332 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1333 getPropertyStringInternal(String8("description"), description) == OK &&
1334 getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
1335 status_t res = android::reportDrmPluginMetrics(
1336 metrics, vendor, description);
1337 if (res != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001338 ALOGE("Metrics were retrieved but could not be reported: %d", res);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001339 }
1340 }
1341}
1342
Jeff Tinkera53d6552017-01-20 00:31:46 -08001343} // namespace android