blob: 31344c3bfabe12173ab4a82d7e01eb82734ba160 [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 Tinkerf0e89b02017-08-07 15:58:41 -0700260
261 if (!hResult.isOk()) {
262 ALOGE("createPlugin remote call failed");
263 }
264
Jeff Tinkera53d6552017-01-20 00:31:46 -0800265 return plugin;
266}
267
268status_t DrmHal::initCheck() const {
269 return mInitCheck;
270}
271
272status_t DrmHal::setListener(const sp<IDrmClient>& listener)
273{
274 Mutex::Autolock lock(mEventLock);
275 if (mListener != NULL){
276 IInterface::asBinder(mListener)->unlinkToDeath(this);
277 }
278 if (listener != NULL) {
279 IInterface::asBinder(listener)->linkToDeath(this);
280 }
281 mListener = listener;
282 return NO_ERROR;
283}
284
285Return<void> DrmHal::sendEvent(EventType hEventType,
286 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
287
288 mEventLock.lock();
289 sp<IDrmClient> listener = mListener;
290 mEventLock.unlock();
291
292 if (listener != NULL) {
293 Parcel obj;
294 writeByteArray(obj, sessionId);
295 writeByteArray(obj, data);
296
297 Mutex::Autolock lock(mNotifyLock);
298 DrmPlugin::EventType eventType;
299 switch(hEventType) {
300 case EventType::PROVISION_REQUIRED:
301 eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
302 break;
303 case EventType::KEY_NEEDED:
304 eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
305 break;
306 case EventType::KEY_EXPIRED:
307 eventType = DrmPlugin::kDrmPluginEventKeyExpired;
308 break;
309 case EventType::VENDOR_DEFINED:
310 eventType = DrmPlugin::kDrmPluginEventVendorDefined;
311 break;
Rahul Friasb86f4b32017-03-27 15:13:30 -0700312 case EventType::SESSION_RECLAIMED:
313 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
314 break;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800315 default:
316 return Void();
317 }
318 listener->notify(eventType, 0, &obj);
319 }
320 return Void();
321}
322
323Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
324 int64_t expiryTimeInMS) {
325
326 mEventLock.lock();
327 sp<IDrmClient> listener = mListener;
328 mEventLock.unlock();
329
330 if (listener != NULL) {
331 Parcel obj;
332 writeByteArray(obj, sessionId);
333 obj.writeInt64(expiryTimeInMS);
334
335 Mutex::Autolock lock(mNotifyLock);
336 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
337 }
338 return Void();
339}
340
341Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
342 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
343
344 mEventLock.lock();
345 sp<IDrmClient> listener = mListener;
346 mEventLock.unlock();
347
348 if (listener != NULL) {
349 Parcel obj;
350 writeByteArray(obj, sessionId);
351
352 size_t nKeys = keyStatusList.size();
353 obj.writeInt32(nKeys);
354 for (size_t i = 0; i < nKeys; ++i) {
355 const KeyStatus &keyStatus = keyStatusList[i];
356 writeByteArray(obj, keyStatus.keyId);
357 uint32_t type;
358 switch(keyStatus.type) {
359 case KeyStatusType::USABLE:
360 type = DrmPlugin::kKeyStatusType_Usable;
361 break;
362 case KeyStatusType::EXPIRED:
363 type = DrmPlugin::kKeyStatusType_Expired;
364 break;
365 case KeyStatusType::OUTPUTNOTALLOWED:
366 type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
367 break;
368 case KeyStatusType::STATUSPENDING:
369 type = DrmPlugin::kKeyStatusType_StatusPending;
370 break;
371 case KeyStatusType::INTERNALERROR:
372 default:
373 type = DrmPlugin::kKeyStatusType_InternalError;
374 break;
375 }
376 obj.writeInt32(type);
377 }
378 obj.writeInt32(hasNewUsableKey);
379
380 Mutex::Autolock lock(mNotifyLock);
381 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
382 }
383 return Void();
384}
385
386bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
387 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800388
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800389 for (size_t i = 0; i < mFactories.size(); i++) {
390 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
391 if (mimeType != "") {
392 if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
393 return true;
394 }
395 } else {
396 return true;
397 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800398 }
399 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800400 return false;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800401}
402
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800403status_t DrmHal::createPlugin(const uint8_t uuid[16],
404 const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800405 Mutex::Autolock autoLock(mLock);
406
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800407 for (size_t i = 0; i < mFactories.size(); i++) {
408 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
409 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
410 }
411 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800412
413 if (mPlugin == NULL) {
414 mInitCheck = ERROR_UNSUPPORTED;
415 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700416 if (!mPlugin->setListener(this).isOk()) {
417 mInitCheck = DEAD_OBJECT;
418 } else {
419 mInitCheck = OK;
420 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800421 }
422
423 return mInitCheck;
424}
425
426status_t DrmHal::destroyPlugin() {
427 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800428 if (mInitCheck != OK) {
429 return mInitCheck;
430 }
431
Jeff Tinker61332812017-05-15 16:53:10 -0700432 closeOpenSessions();
John W. Bruce33ecc4f2017-04-03 16:49:05 -0700433 reportMetrics();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800434 setListener(NULL);
Jeff Tinker70367f52017-06-16 12:41:33 -0700435 mInitCheck = NO_INIT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800436
Jeff Tinker319d5f42017-07-26 15:44:33 -0700437 if (mPlugin != NULL) {
438 if (!mPlugin->setListener(NULL).isOk()) {
439 mInitCheck = DEAD_OBJECT;
440 }
441 }
442 mPlugin.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800443 return OK;
444}
445
446status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
447 Mutex::Autolock autoLock(mLock);
448
449 if (mInitCheck != OK) {
450 return mInitCheck;
451 }
452
453 status_t err = UNKNOWN_ERROR;
454
455 bool retry = true;
456 do {
457 hidl_vec<uint8_t> hSessionId;
458
459 Return<void> hResult = mPlugin->openSession(
460 [&](Status status, const hidl_vec<uint8_t>& id) {
461 if (status == Status::OK) {
462 sessionId = toVector(id);
463 }
464 err = toStatusT(status);
465 }
466 );
467
468 if (!hResult.isOk()) {
469 err = DEAD_OBJECT;
470 }
471
472 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
473 mLock.unlock();
474 // reclaimSession may call back to closeSession, since mLock is
475 // shared between Drm instances, we should unlock here to avoid
476 // deadlock.
477 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
478 mLock.lock();
479 } else {
480 retry = false;
481 }
482 } while (retry);
483
484 if (err == OK) {
485 DrmSessionManager::Instance()->addSession(getCallingPid(),
486 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700487 mOpenSessions.push(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800488 }
489 return err;
490}
491
492status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
493 Mutex::Autolock autoLock(mLock);
494
495 if (mInitCheck != OK) {
496 return mInitCheck;
497 }
498
Jeff Tinker319d5f42017-07-26 15:44:33 -0700499 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
500 if (status.isOk()) {
501 if (status == Status::OK) {
502 DrmSessionManager::Instance()->removeSession(sessionId);
503 for (size_t i = 0; i < mOpenSessions.size(); i++) {
504 if (mOpenSessions[i] == sessionId) {
505 mOpenSessions.removeAt(i);
506 break;
507 }
Jeff Tinker61332812017-05-15 16:53:10 -0700508 }
509 }
Jeff Tinker319d5f42017-07-26 15:44:33 -0700510 reportMetrics();
511 return toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800512 }
Jeff Tinker319d5f42017-07-26 15:44:33 -0700513 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800514}
515
516status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
517 Vector<uint8_t> const &initData, String8 const &mimeType,
518 DrmPlugin::KeyType keyType, KeyedVector<String8,
519 String8> const &optionalParameters, Vector<uint8_t> &request,
520 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
521 Mutex::Autolock autoLock(mLock);
522
523 if (mInitCheck != OK) {
524 return mInitCheck;
525 }
526
527 DrmSessionManager::Instance()->useSession(sessionId);
528
529 KeyType hKeyType;
530 if (keyType == DrmPlugin::kKeyType_Streaming) {
531 hKeyType = KeyType::STREAMING;
532 } else if (keyType == DrmPlugin::kKeyType_Offline) {
533 hKeyType = KeyType::OFFLINE;
534 } else if (keyType == DrmPlugin::kKeyType_Release) {
535 hKeyType = KeyType::RELEASE;
536 } else {
537 return BAD_VALUE;
538 }
539
540 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
541
542 status_t err = UNKNOWN_ERROR;
543
544 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
545 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
546 [&](Status status, const hidl_vec<uint8_t>& hRequest,
547 KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
548
549 if (status == Status::OK) {
550 request = toVector(hRequest);
551 defaultUrl = toString8(hDefaultUrl);
552
553 switch (hKeyRequestType) {
554 case KeyRequestType::INITIAL:
555 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
556 break;
557 case KeyRequestType::RENEWAL:
558 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
559 break;
560 case KeyRequestType::RELEASE:
561 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
562 break;
563 default:
564 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
565 break;
566 }
567 err = toStatusT(status);
568 }
569 });
570
571 return hResult.isOk() ? err : DEAD_OBJECT;
572}
573
574status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
575 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
576 Mutex::Autolock autoLock(mLock);
577
578 if (mInitCheck != OK) {
579 return mInitCheck;
580 }
581
582 DrmSessionManager::Instance()->useSession(sessionId);
583
584 status_t err = UNKNOWN_ERROR;
585
586 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
587 toHidlVec(response),
588 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
589 if (status == Status::OK) {
590 keySetId = toVector(hKeySetId);
591 }
592 err = toStatusT(status);
593 }
594 );
595
596 return hResult.isOk() ? err : DEAD_OBJECT;
597}
598
599status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
600 Mutex::Autolock autoLock(mLock);
601
602 if (mInitCheck != OK) {
603 return mInitCheck;
604 }
605
606 return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
607}
608
609status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
610 Vector<uint8_t> const &keySetId) {
611 Mutex::Autolock autoLock(mLock);
612
613 if (mInitCheck != OK) {
614 return mInitCheck;
615 }
616
617 DrmSessionManager::Instance()->useSession(sessionId);
618
619 return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
620 toHidlVec(keySetId)));
621}
622
623status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
624 KeyedVector<String8, String8> &infoMap) const {
625 Mutex::Autolock autoLock(mLock);
626
627 if (mInitCheck != OK) {
628 return mInitCheck;
629 }
630
631 DrmSessionManager::Instance()->useSession(sessionId);
632
633 ::KeyedVector hInfoMap;
634
635 status_t err = UNKNOWN_ERROR;
636
637 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
638 [&](Status status, const hidl_vec<KeyValue>& map) {
639 if (status == Status::OK) {
640 infoMap = toKeyedVector(map);
641 }
642 err = toStatusT(status);
643 }
644 );
645
646 return hResult.isOk() ? err : DEAD_OBJECT;
647}
648
649status_t DrmHal::getProvisionRequest(String8 const &certType,
650 String8 const &certAuthority, Vector<uint8_t> &request,
651 String8 &defaultUrl) {
652 Mutex::Autolock autoLock(mLock);
653
654 if (mInitCheck != OK) {
655 return mInitCheck;
656 }
657
658 status_t err = UNKNOWN_ERROR;
659
660 Return<void> hResult = mPlugin->getProvisionRequest(
661 toHidlString(certType), toHidlString(certAuthority),
662 [&](Status status, const hidl_vec<uint8_t>& hRequest,
663 const hidl_string& hDefaultUrl) {
664 if (status == Status::OK) {
665 request = toVector(hRequest);
666 defaultUrl = toString8(hDefaultUrl);
667 }
668 err = toStatusT(status);
669 }
670 );
671
672 return hResult.isOk() ? err : DEAD_OBJECT;
673}
674
675status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800676 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800677 Mutex::Autolock autoLock(mLock);
678
679 if (mInitCheck != OK) {
680 return mInitCheck;
681 }
682
683 status_t err = UNKNOWN_ERROR;
684
685 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
686 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
687 const hidl_vec<uint8_t>& hWrappedKey) {
688 if (status == Status::OK) {
689 certificate = toVector(hCertificate);
690 wrappedKey = toVector(hWrappedKey);
691 }
692 err = toStatusT(status);
693 }
694 );
695
696 return hResult.isOk() ? err : DEAD_OBJECT;
697}
698
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800699status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800700 Mutex::Autolock autoLock(mLock);
701
702 if (mInitCheck != OK) {
703 return mInitCheck;
704 }
705
706 status_t err = UNKNOWN_ERROR;
707
708 Return<void> hResult = mPlugin->getSecureStops(
709 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
710 if (status == Status::OK) {
711 secureStops = toSecureStops(hSecureStops);
712 }
713 err = toStatusT(status);
714 }
715 );
716
717 return hResult.isOk() ? err : DEAD_OBJECT;
718}
719
720
721status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
722 Mutex::Autolock autoLock(mLock);
723
724 if (mInitCheck != OK) {
725 return mInitCheck;
726 }
727
728 status_t err = UNKNOWN_ERROR;
729
730 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
731 [&](Status status, const SecureStop& hSecureStop) {
732 if (status == Status::OK) {
733 secureStop = toVector(hSecureStop.opaqueData);
734 }
735 err = toStatusT(status);
736 }
737 );
738
739 return hResult.isOk() ? err : DEAD_OBJECT;
740}
741
742status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
743 Mutex::Autolock autoLock(mLock);
744
745 if (mInitCheck != OK) {
746 return mInitCheck;
747 }
748
749 return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
750}
751
752status_t DrmHal::releaseAllSecureStops() {
753 Mutex::Autolock autoLock(mLock);
754
755 if (mInitCheck != OK) {
756 return mInitCheck;
757 }
758
759 return toStatusT(mPlugin->releaseAllSecureStops());
760}
761
762status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
763 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -0700764 return getPropertyStringInternal(name, value);
765}
766
767status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
768 // This function is internal to the class and should only be called while
769 // mLock is already held.
Jeff Tinkera53d6552017-01-20 00:31:46 -0800770
771 if (mInitCheck != OK) {
772 return mInitCheck;
773 }
774
775 status_t err = UNKNOWN_ERROR;
776
777 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
778 [&](Status status, const hidl_string& hValue) {
779 if (status == Status::OK) {
780 value = toString8(hValue);
781 }
782 err = toStatusT(status);
783 }
784 );
785
786 return hResult.isOk() ? err : DEAD_OBJECT;
787}
788
789status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
790 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -0700791 return getPropertyByteArrayInternal(name, value);
792}
793
794status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
795 // This function is internal to the class and should only be called while
796 // mLock is already held.
Jeff Tinkera53d6552017-01-20 00:31:46 -0800797
798 if (mInitCheck != OK) {
799 return mInitCheck;
800 }
801
802 status_t err = UNKNOWN_ERROR;
803
804 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
805 [&](Status status, const hidl_vec<uint8_t>& hValue) {
806 if (status == Status::OK) {
807 value = toVector(hValue);
808 }
809 err = toStatusT(status);
810 }
811 );
812
813 return hResult.isOk() ? err : DEAD_OBJECT;
814}
815
816status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
817 Mutex::Autolock autoLock(mLock);
818
819 if (mInitCheck != OK) {
820 return mInitCheck;
821 }
822
823 Status status = mPlugin->setPropertyString(toHidlString(name),
824 toHidlString(value));
825 return toStatusT(status);
826}
827
828status_t DrmHal::setPropertyByteArray(String8 const &name,
829 Vector<uint8_t> const &value ) const {
830 Mutex::Autolock autoLock(mLock);
831
832 if (mInitCheck != OK) {
833 return mInitCheck;
834 }
835
836 Status status = mPlugin->setPropertyByteArray(toHidlString(name),
837 toHidlVec(value));
838 return toStatusT(status);
839}
840
Adam Stoneab394d12017-12-22 12:34:20 -0800841status_t DrmHal::getMetrics(MediaAnalyticsItem* metrics) {
842 // TODO: Replace this with real metrics.
843 metrics->setCString("/drm/mediadrm/dummymetric", "dummy");
844 return OK;
845}
Jeff Tinkera53d6552017-01-20 00:31:46 -0800846
847status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
848 String8 const &algorithm) {
849 Mutex::Autolock autoLock(mLock);
850
851 if (mInitCheck != OK) {
852 return mInitCheck;
853 }
854
855 DrmSessionManager::Instance()->useSession(sessionId);
856
857 Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
858 toHidlString(algorithm));
859 return toStatusT(status);
860}
861
862status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
863 String8 const &algorithm) {
864 Mutex::Autolock autoLock(mLock);
865
866 if (mInitCheck != OK) {
867 return mInitCheck;
868 }
869
870 DrmSessionManager::Instance()->useSession(sessionId);
871
872 Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
873 toHidlString(algorithm));
874 return toStatusT(status);
875}
876
877status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800878 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
879 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800880 Mutex::Autolock autoLock(mLock);
881
882 if (mInitCheck != OK) {
883 return mInitCheck;
884 }
885
886 DrmSessionManager::Instance()->useSession(sessionId);
887
888 status_t err = UNKNOWN_ERROR;
889
890 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
891 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
892 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
893 if (status == Status::OK) {
894 output = toVector(hOutput);
895 }
896 err = toStatusT(status);
897 }
898 );
899
900 return hResult.isOk() ? err : DEAD_OBJECT;
901}
902
903status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800904 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
905 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800906 Mutex::Autolock autoLock(mLock);
907
908 if (mInitCheck != OK) {
909 return mInitCheck;
910 }
911
912 DrmSessionManager::Instance()->useSession(sessionId);
913
914 status_t err = UNKNOWN_ERROR;
915
916 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
917 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
918 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
919 if (status == Status::OK) {
920 output = toVector(hOutput);
921 }
922 err = toStatusT(status);
923 }
924 );
925
926 return hResult.isOk() ? err : DEAD_OBJECT;
927}
928
929status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800930 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
931 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800932 Mutex::Autolock autoLock(mLock);
933
934 if (mInitCheck != OK) {
935 return mInitCheck;
936 }
937
938 DrmSessionManager::Instance()->useSession(sessionId);
939
940 status_t err = UNKNOWN_ERROR;
941
942 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
943 toHidlVec(keyId), toHidlVec(message),
944 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
945 if (status == Status::OK) {
946 signature = toVector(hSignature);
947 }
948 err = toStatusT(status);
949 }
950 );
951
952 return hResult.isOk() ? err : DEAD_OBJECT;
953}
954
955status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800956 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
957 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800958 Mutex::Autolock autoLock(mLock);
959
960 if (mInitCheck != OK) {
961 return mInitCheck;
962 }
963
964 DrmSessionManager::Instance()->useSession(sessionId);
965
966 status_t err = UNKNOWN_ERROR;
967
968 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
969 toHidlVec(message), toHidlVec(signature),
970 [&](Status status, bool hMatch) {
971 if (status == Status::OK) {
972 match = hMatch;
973 } else {
974 match = false;
975 }
976 err = toStatusT(status);
977 }
978 );
979
980 return hResult.isOk() ? err : DEAD_OBJECT;
981}
982
983status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800984 String8 const &algorithm, Vector<uint8_t> const &message,
985 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800986 Mutex::Autolock autoLock(mLock);
987
988 if (mInitCheck != OK) {
989 return mInitCheck;
990 }
991
992 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
993 return -EPERM;
994 }
995
996 DrmSessionManager::Instance()->useSession(sessionId);
997
998 status_t err = UNKNOWN_ERROR;
999
1000 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1001 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1002 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1003 if (status == Status::OK) {
1004 signature = toVector(hSignature);
1005 }
1006 err = toStatusT(status);
1007 }
1008 );
1009
1010 return hResult.isOk() ? err : DEAD_OBJECT;
1011}
1012
1013void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1014{
Jeff Tinkera53d6552017-01-20 00:31:46 -08001015 Mutex::Autolock autoLock(mLock);
Jeff Tinker61332812017-05-15 16:53:10 -07001016 closeOpenSessions();
Jeff Tinker3e289162017-06-01 11:13:53 -07001017 setListener(NULL);
Jeff Tinker319d5f42017-07-26 15:44:33 -07001018 mInitCheck = NO_INIT;
1019
Jeff Tinker70367f52017-06-16 12:41:33 -07001020 if (mPlugin != NULL) {
Jeff Tinker319d5f42017-07-26 15:44:33 -07001021 if (!mPlugin->setListener(NULL).isOk()) {
1022 mInitCheck = DEAD_OBJECT;
1023 }
Jeff Tinker70367f52017-06-16 12:41:33 -07001024 }
Jeff Tinkera53d6552017-01-20 00:31:46 -08001025 mPlugin.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001026}
1027
1028void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1029{
1030 if (vec.size()) {
1031 obj.writeInt32(vec.size());
1032 obj.write(vec.data(), vec.size());
1033 } else {
1034 obj.writeInt32(0);
1035 }
1036}
1037
Adam Stoneab394d12017-12-22 12:34:20 -08001038
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001039void DrmHal::reportMetrics() const
1040{
1041 Vector<uint8_t> metrics;
1042 String8 vendor;
1043 String8 description;
1044 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1045 getPropertyStringInternal(String8("description"), description) == OK &&
1046 getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
1047 status_t res = android::reportDrmPluginMetrics(
1048 metrics, vendor, description);
1049 if (res != OK) {
1050 ALOGE("Metrics were retrieved but could not be reported: %i", res);
1051 }
1052 }
1053}
1054
Jeff Tinkera53d6552017-01-20 00:31:46 -08001055} // namespace android