blob: bac60ff0a7d645987b09e97496a6f7502242b1b4 [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"
19#include <utils/Log.h>
20
21#include <binder/IPCThreadState.h>
22#include <binder/IServiceManager.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080023
24#include <android/hardware/drm/1.0/IDrmFactory.h>
25#include <android/hardware/drm/1.0/IDrmPlugin.h>
26#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
30#include <media/DrmHal.h>
31#include <media/DrmSessionClientInterface.h>
32#include <media/DrmSessionManager.h>
John W. Bruce33ecc4f2017-04-03 16:49:05 -070033#include <media/PluginMetricsReporting.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080034#include <media/drm/DrmAPI.h>
35#include <media/stagefright/foundation/ADebug.h>
36#include <media/stagefright/foundation/AString.h>
37#include <media/stagefright/foundation/hexdump.h>
38#include <media/stagefright/MediaErrors.h>
39
40using ::android::hardware::drm::V1_0::EventType;
41using ::android::hardware::drm::V1_0::IDrmFactory;
42using ::android::hardware::drm::V1_0::IDrmPlugin;
43using ::android::hardware::drm::V1_0::KeyedVector;
44using ::android::hardware::drm::V1_0::KeyRequestType;
45using ::android::hardware::drm::V1_0::KeyStatus;
46using ::android::hardware::drm::V1_0::KeyStatusType;
47using ::android::hardware::drm::V1_0::KeyType;
48using ::android::hardware::drm::V1_0::KeyValue;
49using ::android::hardware::drm::V1_0::SecureStop;
50using ::android::hardware::drm::V1_0::Status;
51using ::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;
Jeff Tinkera53d6552017-01-20 00:31:46 -080057using ::android::sp;
58
59namespace android {
60
61static inline int getCallingPid() {
62 return IPCThreadState::self()->getCallingPid();
63}
64
65static bool checkPermission(const char* permissionString) {
66 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
67 bool ok = checkCallingPermission(String16(permissionString));
68 if (!ok) ALOGE("Request requires %s", permissionString);
69 return ok;
70}
71
72static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
73 Vector<uint8_t> vector;
74 vector.appendArray(vec.data(), vec.size());
75 return *const_cast<const Vector<uint8_t> *>(&vector);
76}
77
78static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
79 hidl_vec<uint8_t> vec;
80 vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
81 return vec;
82}
83
84static String8 toString8(const hidl_string &string) {
85 return String8(string.c_str());
86}
87
88static hidl_string toHidlString(const String8& string) {
89 return hidl_string(string.string());
90}
91
92
93static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
94 keyedVector) {
95 std::vector<KeyValue> stdKeyedVector;
96 for (size_t i = 0; i < keyedVector.size(); i++) {
97 KeyValue keyValue;
98 keyValue.key = toHidlString(keyedVector.keyAt(i));
99 keyValue.value = toHidlString(keyedVector.valueAt(i));
100 stdKeyedVector.push_back(keyValue);
101 }
102 return ::KeyedVector(stdKeyedVector);
103}
104
105static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
106 hKeyedVector) {
107 KeyedVector<String8, String8> keyedVector;
108 for (size_t i = 0; i < hKeyedVector.size(); i++) {
109 keyedVector.add(toString8(hKeyedVector[i].key),
110 toString8(hKeyedVector[i].value));
111 }
112 return keyedVector;
113}
114
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800115static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
Jeff Tinkera53d6552017-01-20 00:31:46 -0800116 hSecureStops) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800117 List<Vector<uint8_t>> secureStops;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800118 for (size_t i = 0; i < hSecureStops.size(); i++) {
119 secureStops.push_back(toVector(hSecureStops[i].opaqueData));
120 }
121 return secureStops;
122}
123
124static status_t toStatusT(Status status) {
125 switch (status) {
126 case Status::OK:
127 return OK;
128 break;
129 case Status::ERROR_DRM_NO_LICENSE:
130 return ERROR_DRM_NO_LICENSE;
131 break;
132 case Status::ERROR_DRM_LICENSE_EXPIRED:
133 return ERROR_DRM_LICENSE_EXPIRED;
134 break;
135 case Status::ERROR_DRM_SESSION_NOT_OPENED:
136 return ERROR_DRM_SESSION_NOT_OPENED;
137 break;
138 case Status::ERROR_DRM_CANNOT_HANDLE:
139 return ERROR_DRM_CANNOT_HANDLE;
140 break;
141 case Status::ERROR_DRM_INVALID_STATE:
142 return ERROR_DRM_TAMPER_DETECTED;
143 break;
144 case Status::BAD_VALUE:
145 return BAD_VALUE;
146 break;
147 case Status::ERROR_DRM_NOT_PROVISIONED:
148 return ERROR_DRM_NOT_PROVISIONED;
149 break;
150 case Status::ERROR_DRM_RESOURCE_BUSY:
151 return ERROR_DRM_RESOURCE_BUSY;
152 break;
153 case Status::ERROR_DRM_DEVICE_REVOKED:
154 return ERROR_DRM_DEVICE_REVOKED;
155 break;
156 case Status::ERROR_DRM_UNKNOWN:
157 default:
158 return ERROR_DRM_UNKNOWN;
159 break;
160 }
161}
162
163
164Mutex DrmHal::mLock;
165
166struct DrmSessionClient : public DrmSessionClientInterface {
167 explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
168
169 virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
170 sp<DrmHal> drm = mDrm.promote();
171 if (drm == NULL) {
172 return true;
173 }
174 status_t err = drm->closeSession(sessionId);
175 if (err != OK) {
176 return false;
177 }
178 drm->sendEvent(EventType::SESSION_RECLAIMED,
179 toHidlVec(sessionId), hidl_vec<uint8_t>());
180 return true;
181 }
182
183protected:
184 virtual ~DrmSessionClient() {}
185
186private:
187 wp<DrmHal> mDrm;
188
189 DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
190};
191
192DrmHal::DrmHal()
193 : mDrmSessionClient(new DrmSessionClient(this)),
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800194 mFactories(makeDrmFactories()),
195 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800196}
197
Jeff Tinker61332812017-05-15 16:53:10 -0700198void DrmHal::closeOpenSessions() {
199 if (mPlugin != NULL) {
200 for (size_t i = 0; i < mOpenSessions.size(); i++) {
201 mPlugin->closeSession(toHidlVec(mOpenSessions[i]));
202 DrmSessionManager::Instance()->removeSession(mOpenSessions[i]);
203 }
204 }
205 mOpenSessions.clear();
206}
207
Jeff Tinkera53d6552017-01-20 00:31:46 -0800208DrmHal::~DrmHal() {
Jeff Tinker61332812017-05-15 16:53:10 -0700209 closeOpenSessions();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800210 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
211}
212
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800213Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
214 Vector<sp<IDrmFactory>> factories;
215
Jeff Tinker593111f2017-05-25 16:00:21 -0700216 auto manager = hardware::defaultServiceManager();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800217
218 if (manager != NULL) {
219 manager->listByInterface(IDrmFactory::descriptor,
220 [&factories](const hidl_vec<hidl_string> &registered) {
221 for (const auto &instance : registered) {
222 auto factory = IDrmFactory::getService(instance);
223 if (factory != NULL) {
224 factories.push_back(factory);
225 ALOGI("makeDrmFactories: factory instance %s is %s",
226 instance.c_str(),
227 factory->isRemote() ? "Remote" : "Not Remote");
228 }
229 }
230 }
231 );
Jeff Tinkera53d6552017-01-20 00:31:46 -0800232 }
Jeff Tinkerc82b9c32017-02-14 11:39:51 -0800233
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800234 if (factories.size() == 0) {
235 // must be in passthrough mode, load the default passthrough service
Jeff Tinkere309b222017-04-05 08:01:28 -0700236 auto passthrough = IDrmFactory::getService();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800237 if (passthrough != NULL) {
238 ALOGI("makeDrmFactories: using default drm instance");
239 factories.push_back(passthrough);
240 } else {
241 ALOGE("Failed to find any drm factories");
242 }
243 }
244 return factories;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800245}
246
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800247sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
248 const uint8_t uuid[16], const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800249
250 sp<IDrmPlugin> plugin;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800251 Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
Jeff Tinkera53d6552017-01-20 00:31:46 -0800252 [&](Status status, const sp<IDrmPlugin>& hPlugin) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800253 if (status != Status::OK) {
254 ALOGE("Failed to make drm plugin");
255 return;
256 }
257 plugin = hPlugin;
258 }
259 );
Jeff Tinkera53d6552017-01-20 00:31:46 -0800260 return plugin;
261}
262
263status_t DrmHal::initCheck() const {
264 return mInitCheck;
265}
266
267status_t DrmHal::setListener(const sp<IDrmClient>& listener)
268{
269 Mutex::Autolock lock(mEventLock);
270 if (mListener != NULL){
271 IInterface::asBinder(mListener)->unlinkToDeath(this);
272 }
273 if (listener != NULL) {
274 IInterface::asBinder(listener)->linkToDeath(this);
275 }
276 mListener = listener;
277 return NO_ERROR;
278}
279
280Return<void> DrmHal::sendEvent(EventType hEventType,
281 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
282
283 mEventLock.lock();
284 sp<IDrmClient> listener = mListener;
285 mEventLock.unlock();
286
287 if (listener != NULL) {
288 Parcel obj;
289 writeByteArray(obj, sessionId);
290 writeByteArray(obj, data);
291
292 Mutex::Autolock lock(mNotifyLock);
293 DrmPlugin::EventType eventType;
294 switch(hEventType) {
295 case EventType::PROVISION_REQUIRED:
296 eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
297 break;
298 case EventType::KEY_NEEDED:
299 eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
300 break;
301 case EventType::KEY_EXPIRED:
302 eventType = DrmPlugin::kDrmPluginEventKeyExpired;
303 break;
304 case EventType::VENDOR_DEFINED:
305 eventType = DrmPlugin::kDrmPluginEventVendorDefined;
306 break;
Rahul Friasb86f4b32017-03-27 15:13:30 -0700307 case EventType::SESSION_RECLAIMED:
308 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
309 break;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800310 default:
311 return Void();
312 }
313 listener->notify(eventType, 0, &obj);
314 }
315 return Void();
316}
317
318Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
319 int64_t expiryTimeInMS) {
320
321 mEventLock.lock();
322 sp<IDrmClient> listener = mListener;
323 mEventLock.unlock();
324
325 if (listener != NULL) {
326 Parcel obj;
327 writeByteArray(obj, sessionId);
328 obj.writeInt64(expiryTimeInMS);
329
330 Mutex::Autolock lock(mNotifyLock);
331 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
332 }
333 return Void();
334}
335
336Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
337 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
338
339 mEventLock.lock();
340 sp<IDrmClient> listener = mListener;
341 mEventLock.unlock();
342
343 if (listener != NULL) {
344 Parcel obj;
345 writeByteArray(obj, sessionId);
346
347 size_t nKeys = keyStatusList.size();
348 obj.writeInt32(nKeys);
349 for (size_t i = 0; i < nKeys; ++i) {
350 const KeyStatus &keyStatus = keyStatusList[i];
351 writeByteArray(obj, keyStatus.keyId);
352 uint32_t type;
353 switch(keyStatus.type) {
354 case KeyStatusType::USABLE:
355 type = DrmPlugin::kKeyStatusType_Usable;
356 break;
357 case KeyStatusType::EXPIRED:
358 type = DrmPlugin::kKeyStatusType_Expired;
359 break;
360 case KeyStatusType::OUTPUTNOTALLOWED:
361 type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
362 break;
363 case KeyStatusType::STATUSPENDING:
364 type = DrmPlugin::kKeyStatusType_StatusPending;
365 break;
366 case KeyStatusType::INTERNALERROR:
367 default:
368 type = DrmPlugin::kKeyStatusType_InternalError;
369 break;
370 }
371 obj.writeInt32(type);
372 }
373 obj.writeInt32(hasNewUsableKey);
374
375 Mutex::Autolock lock(mNotifyLock);
376 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
377 }
378 return Void();
379}
380
381bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
382 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800383
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800384 for (size_t i = 0; i < mFactories.size(); i++) {
385 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
386 if (mimeType != "") {
387 if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
388 return true;
389 }
390 } else {
391 return true;
392 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800393 }
394 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800395 return false;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800396}
397
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800398status_t DrmHal::createPlugin(const uint8_t uuid[16],
399 const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800400 Mutex::Autolock autoLock(mLock);
401
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800402 for (size_t i = 0; i < mFactories.size(); i++) {
403 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
404 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
405 }
406 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800407
408 if (mPlugin == NULL) {
409 mInitCheck = ERROR_UNSUPPORTED;
410 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700411 if (!mPlugin->setListener(this).isOk()) {
412 mInitCheck = DEAD_OBJECT;
413 } else {
414 mInitCheck = OK;
415 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800416 }
417
418 return mInitCheck;
419}
420
421status_t DrmHal::destroyPlugin() {
422 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800423 if (mInitCheck != OK) {
424 return mInitCheck;
425 }
426
Jeff Tinker61332812017-05-15 16:53:10 -0700427 closeOpenSessions();
John W. Bruce33ecc4f2017-04-03 16:49:05 -0700428 reportMetrics();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800429 setListener(NULL);
Jeff Tinker70367f52017-06-16 12:41:33 -0700430 mInitCheck = NO_INIT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800431
Jeff Tinker319d5f42017-07-26 15:44:33 -0700432 if (mPlugin != NULL) {
433 if (!mPlugin->setListener(NULL).isOk()) {
434 mInitCheck = DEAD_OBJECT;
435 }
436 }
437 mPlugin.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800438 return OK;
439}
440
441status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
442 Mutex::Autolock autoLock(mLock);
443
444 if (mInitCheck != OK) {
445 return mInitCheck;
446 }
447
448 status_t err = UNKNOWN_ERROR;
449
450 bool retry = true;
451 do {
452 hidl_vec<uint8_t> hSessionId;
453
454 Return<void> hResult = mPlugin->openSession(
455 [&](Status status, const hidl_vec<uint8_t>& id) {
456 if (status == Status::OK) {
457 sessionId = toVector(id);
458 }
459 err = toStatusT(status);
460 }
461 );
462
463 if (!hResult.isOk()) {
464 err = DEAD_OBJECT;
465 }
466
467 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
468 mLock.unlock();
469 // reclaimSession may call back to closeSession, since mLock is
470 // shared between Drm instances, we should unlock here to avoid
471 // deadlock.
472 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
473 mLock.lock();
474 } else {
475 retry = false;
476 }
477 } while (retry);
478
479 if (err == OK) {
480 DrmSessionManager::Instance()->addSession(getCallingPid(),
481 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700482 mOpenSessions.push(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800483 }
484 return err;
485}
486
487status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
488 Mutex::Autolock autoLock(mLock);
489
490 if (mInitCheck != OK) {
491 return mInitCheck;
492 }
493
Jeff Tinker319d5f42017-07-26 15:44:33 -0700494 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
495 if (status.isOk()) {
496 if (status == Status::OK) {
497 DrmSessionManager::Instance()->removeSession(sessionId);
498 for (size_t i = 0; i < mOpenSessions.size(); i++) {
499 if (mOpenSessions[i] == sessionId) {
500 mOpenSessions.removeAt(i);
501 break;
502 }
Jeff Tinker61332812017-05-15 16:53:10 -0700503 }
504 }
Jeff Tinker319d5f42017-07-26 15:44:33 -0700505 reportMetrics();
506 return toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800507 }
Jeff Tinker319d5f42017-07-26 15:44:33 -0700508 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800509}
510
511status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
512 Vector<uint8_t> const &initData, String8 const &mimeType,
513 DrmPlugin::KeyType keyType, KeyedVector<String8,
514 String8> const &optionalParameters, Vector<uint8_t> &request,
515 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
516 Mutex::Autolock autoLock(mLock);
517
518 if (mInitCheck != OK) {
519 return mInitCheck;
520 }
521
522 DrmSessionManager::Instance()->useSession(sessionId);
523
524 KeyType hKeyType;
525 if (keyType == DrmPlugin::kKeyType_Streaming) {
526 hKeyType = KeyType::STREAMING;
527 } else if (keyType == DrmPlugin::kKeyType_Offline) {
528 hKeyType = KeyType::OFFLINE;
529 } else if (keyType == DrmPlugin::kKeyType_Release) {
530 hKeyType = KeyType::RELEASE;
531 } else {
532 return BAD_VALUE;
533 }
534
535 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
536
537 status_t err = UNKNOWN_ERROR;
538
539 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
540 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
541 [&](Status status, const hidl_vec<uint8_t>& hRequest,
542 KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
543
544 if (status == Status::OK) {
545 request = toVector(hRequest);
546 defaultUrl = toString8(hDefaultUrl);
547
548 switch (hKeyRequestType) {
549 case KeyRequestType::INITIAL:
550 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
551 break;
552 case KeyRequestType::RENEWAL:
553 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
554 break;
555 case KeyRequestType::RELEASE:
556 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
557 break;
558 default:
559 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
560 break;
561 }
562 err = toStatusT(status);
563 }
564 });
565
566 return hResult.isOk() ? err : DEAD_OBJECT;
567}
568
569status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
570 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
571 Mutex::Autolock autoLock(mLock);
572
573 if (mInitCheck != OK) {
574 return mInitCheck;
575 }
576
577 DrmSessionManager::Instance()->useSession(sessionId);
578
579 status_t err = UNKNOWN_ERROR;
580
581 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
582 toHidlVec(response),
583 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
584 if (status == Status::OK) {
585 keySetId = toVector(hKeySetId);
586 }
587 err = toStatusT(status);
588 }
589 );
590
591 return hResult.isOk() ? err : DEAD_OBJECT;
592}
593
594status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
595 Mutex::Autolock autoLock(mLock);
596
597 if (mInitCheck != OK) {
598 return mInitCheck;
599 }
600
601 return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
602}
603
604status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
605 Vector<uint8_t> const &keySetId) {
606 Mutex::Autolock autoLock(mLock);
607
608 if (mInitCheck != OK) {
609 return mInitCheck;
610 }
611
612 DrmSessionManager::Instance()->useSession(sessionId);
613
614 return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
615 toHidlVec(keySetId)));
616}
617
618status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
619 KeyedVector<String8, String8> &infoMap) const {
620 Mutex::Autolock autoLock(mLock);
621
622 if (mInitCheck != OK) {
623 return mInitCheck;
624 }
625
626 DrmSessionManager::Instance()->useSession(sessionId);
627
628 ::KeyedVector hInfoMap;
629
630 status_t err = UNKNOWN_ERROR;
631
632 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
633 [&](Status status, const hidl_vec<KeyValue>& map) {
634 if (status == Status::OK) {
635 infoMap = toKeyedVector(map);
636 }
637 err = toStatusT(status);
638 }
639 );
640
641 return hResult.isOk() ? err : DEAD_OBJECT;
642}
643
644status_t DrmHal::getProvisionRequest(String8 const &certType,
645 String8 const &certAuthority, Vector<uint8_t> &request,
646 String8 &defaultUrl) {
647 Mutex::Autolock autoLock(mLock);
648
649 if (mInitCheck != OK) {
650 return mInitCheck;
651 }
652
653 status_t err = UNKNOWN_ERROR;
654
655 Return<void> hResult = mPlugin->getProvisionRequest(
656 toHidlString(certType), toHidlString(certAuthority),
657 [&](Status status, const hidl_vec<uint8_t>& hRequest,
658 const hidl_string& hDefaultUrl) {
659 if (status == Status::OK) {
660 request = toVector(hRequest);
661 defaultUrl = toString8(hDefaultUrl);
662 }
663 err = toStatusT(status);
664 }
665 );
666
667 return hResult.isOk() ? err : DEAD_OBJECT;
668}
669
670status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800671 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800672 Mutex::Autolock autoLock(mLock);
673
674 if (mInitCheck != OK) {
675 return mInitCheck;
676 }
677
678 status_t err = UNKNOWN_ERROR;
679
680 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
681 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
682 const hidl_vec<uint8_t>& hWrappedKey) {
683 if (status == Status::OK) {
684 certificate = toVector(hCertificate);
685 wrappedKey = toVector(hWrappedKey);
686 }
687 err = toStatusT(status);
688 }
689 );
690
691 return hResult.isOk() ? err : DEAD_OBJECT;
692}
693
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800694status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800695 Mutex::Autolock autoLock(mLock);
696
697 if (mInitCheck != OK) {
698 return mInitCheck;
699 }
700
701 status_t err = UNKNOWN_ERROR;
702
703 Return<void> hResult = mPlugin->getSecureStops(
704 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
705 if (status == Status::OK) {
706 secureStops = toSecureStops(hSecureStops);
707 }
708 err = toStatusT(status);
709 }
710 );
711
712 return hResult.isOk() ? err : DEAD_OBJECT;
713}
714
715
716status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
717 Mutex::Autolock autoLock(mLock);
718
719 if (mInitCheck != OK) {
720 return mInitCheck;
721 }
722
723 status_t err = UNKNOWN_ERROR;
724
725 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
726 [&](Status status, const SecureStop& hSecureStop) {
727 if (status == Status::OK) {
728 secureStop = toVector(hSecureStop.opaqueData);
729 }
730 err = toStatusT(status);
731 }
732 );
733
734 return hResult.isOk() ? err : DEAD_OBJECT;
735}
736
737status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
738 Mutex::Autolock autoLock(mLock);
739
740 if (mInitCheck != OK) {
741 return mInitCheck;
742 }
743
744 return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
745}
746
747status_t DrmHal::releaseAllSecureStops() {
748 Mutex::Autolock autoLock(mLock);
749
750 if (mInitCheck != OK) {
751 return mInitCheck;
752 }
753
754 return toStatusT(mPlugin->releaseAllSecureStops());
755}
756
757status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
758 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -0700759 return getPropertyStringInternal(name, value);
760}
761
762status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
763 // This function is internal to the class and should only be called while
764 // mLock is already held.
Jeff Tinkera53d6552017-01-20 00:31:46 -0800765
766 if (mInitCheck != OK) {
767 return mInitCheck;
768 }
769
770 status_t err = UNKNOWN_ERROR;
771
772 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
773 [&](Status status, const hidl_string& hValue) {
774 if (status == Status::OK) {
775 value = toString8(hValue);
776 }
777 err = toStatusT(status);
778 }
779 );
780
781 return hResult.isOk() ? err : DEAD_OBJECT;
782}
783
784status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
785 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -0700786 return getPropertyByteArrayInternal(name, value);
787}
788
789status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
790 // This function is internal to the class and should only be called while
791 // mLock is already held.
Jeff Tinkera53d6552017-01-20 00:31:46 -0800792
793 if (mInitCheck != OK) {
794 return mInitCheck;
795 }
796
797 status_t err = UNKNOWN_ERROR;
798
799 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
800 [&](Status status, const hidl_vec<uint8_t>& hValue) {
801 if (status == Status::OK) {
802 value = toVector(hValue);
803 }
804 err = toStatusT(status);
805 }
806 );
807
808 return hResult.isOk() ? err : DEAD_OBJECT;
809}
810
811status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
812 Mutex::Autolock autoLock(mLock);
813
814 if (mInitCheck != OK) {
815 return mInitCheck;
816 }
817
818 Status status = mPlugin->setPropertyString(toHidlString(name),
819 toHidlString(value));
820 return toStatusT(status);
821}
822
823status_t DrmHal::setPropertyByteArray(String8 const &name,
824 Vector<uint8_t> const &value ) const {
825 Mutex::Autolock autoLock(mLock);
826
827 if (mInitCheck != OK) {
828 return mInitCheck;
829 }
830
831 Status status = mPlugin->setPropertyByteArray(toHidlString(name),
832 toHidlVec(value));
833 return toStatusT(status);
834}
835
836
837status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
838 String8 const &algorithm) {
839 Mutex::Autolock autoLock(mLock);
840
841 if (mInitCheck != OK) {
842 return mInitCheck;
843 }
844
845 DrmSessionManager::Instance()->useSession(sessionId);
846
847 Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
848 toHidlString(algorithm));
849 return toStatusT(status);
850}
851
852status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
853 String8 const &algorithm) {
854 Mutex::Autolock autoLock(mLock);
855
856 if (mInitCheck != OK) {
857 return mInitCheck;
858 }
859
860 DrmSessionManager::Instance()->useSession(sessionId);
861
862 Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
863 toHidlString(algorithm));
864 return toStatusT(status);
865}
866
867status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800868 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
869 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800870 Mutex::Autolock autoLock(mLock);
871
872 if (mInitCheck != OK) {
873 return mInitCheck;
874 }
875
876 DrmSessionManager::Instance()->useSession(sessionId);
877
878 status_t err = UNKNOWN_ERROR;
879
880 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
881 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
882 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
883 if (status == Status::OK) {
884 output = toVector(hOutput);
885 }
886 err = toStatusT(status);
887 }
888 );
889
890 return hResult.isOk() ? err : DEAD_OBJECT;
891}
892
893status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800894 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
895 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800896 Mutex::Autolock autoLock(mLock);
897
898 if (mInitCheck != OK) {
899 return mInitCheck;
900 }
901
902 DrmSessionManager::Instance()->useSession(sessionId);
903
904 status_t err = UNKNOWN_ERROR;
905
906 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
907 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
908 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
909 if (status == Status::OK) {
910 output = toVector(hOutput);
911 }
912 err = toStatusT(status);
913 }
914 );
915
916 return hResult.isOk() ? err : DEAD_OBJECT;
917}
918
919status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800920 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
921 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800922 Mutex::Autolock autoLock(mLock);
923
924 if (mInitCheck != OK) {
925 return mInitCheck;
926 }
927
928 DrmSessionManager::Instance()->useSession(sessionId);
929
930 status_t err = UNKNOWN_ERROR;
931
932 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
933 toHidlVec(keyId), toHidlVec(message),
934 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
935 if (status == Status::OK) {
936 signature = toVector(hSignature);
937 }
938 err = toStatusT(status);
939 }
940 );
941
942 return hResult.isOk() ? err : DEAD_OBJECT;
943}
944
945status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800946 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
947 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800948 Mutex::Autolock autoLock(mLock);
949
950 if (mInitCheck != OK) {
951 return mInitCheck;
952 }
953
954 DrmSessionManager::Instance()->useSession(sessionId);
955
956 status_t err = UNKNOWN_ERROR;
957
958 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
959 toHidlVec(message), toHidlVec(signature),
960 [&](Status status, bool hMatch) {
961 if (status == Status::OK) {
962 match = hMatch;
963 } else {
964 match = false;
965 }
966 err = toStatusT(status);
967 }
968 );
969
970 return hResult.isOk() ? err : DEAD_OBJECT;
971}
972
973status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800974 String8 const &algorithm, Vector<uint8_t> const &message,
975 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800976 Mutex::Autolock autoLock(mLock);
977
978 if (mInitCheck != OK) {
979 return mInitCheck;
980 }
981
982 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
983 return -EPERM;
984 }
985
986 DrmSessionManager::Instance()->useSession(sessionId);
987
988 status_t err = UNKNOWN_ERROR;
989
990 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
991 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
992 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
993 if (status == Status::OK) {
994 signature = toVector(hSignature);
995 }
996 err = toStatusT(status);
997 }
998 );
999
1000 return hResult.isOk() ? err : DEAD_OBJECT;
1001}
1002
1003void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1004{
Jeff Tinkera53d6552017-01-20 00:31:46 -08001005 Mutex::Autolock autoLock(mLock);
Jeff Tinker61332812017-05-15 16:53:10 -07001006 closeOpenSessions();
Jeff Tinker3e289162017-06-01 11:13:53 -07001007 setListener(NULL);
Jeff Tinker319d5f42017-07-26 15:44:33 -07001008 mInitCheck = NO_INIT;
1009
Jeff Tinker70367f52017-06-16 12:41:33 -07001010 if (mPlugin != NULL) {
Jeff Tinker319d5f42017-07-26 15:44:33 -07001011 if (!mPlugin->setListener(NULL).isOk()) {
1012 mInitCheck = DEAD_OBJECT;
1013 }
Jeff Tinker70367f52017-06-16 12:41:33 -07001014 }
Jeff Tinkera53d6552017-01-20 00:31:46 -08001015 mPlugin.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001016}
1017
1018void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1019{
1020 if (vec.size()) {
1021 obj.writeInt32(vec.size());
1022 obj.write(vec.data(), vec.size());
1023 } else {
1024 obj.writeInt32(0);
1025 }
1026}
1027
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001028void DrmHal::reportMetrics() const
1029{
1030 Vector<uint8_t> metrics;
1031 String8 vendor;
1032 String8 description;
1033 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1034 getPropertyStringInternal(String8("description"), description) == OK &&
1035 getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
1036 status_t res = android::reportDrmPluginMetrics(
1037 metrics, vendor, description);
1038 if (res != OK) {
1039 ALOGE("Metrics were retrieved but could not be reported: %i", res);
1040 }
1041 }
1042}
1043
Jeff Tinkera53d6552017-01-20 00:31:46 -08001044} // namespace android