blob: c24db57786414dd7b73620db7956be3e8ebd0965 [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
30#include <media/DrmHal.h>
31#include <media/DrmSessionClientInterface.h>
32#include <media/DrmSessionManager.h>
Adam Stonef0e618d2018-01-17 19:20:41 -080033#include <media/EventMetric.h>
John W. Bruce33ecc4f2017-04-03 16:49:05 -070034#include <media/PluginMetricsReporting.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080035#include <media/drm/DrmAPI.h>
36#include <media/stagefright/foundation/ADebug.h>
37#include <media/stagefright/foundation/AString.h>
38#include <media/stagefright/foundation/hexdump.h>
39#include <media/stagefright/MediaErrors.h>
40
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;
Adam Stone28f27c32018-02-05 15:07:48 -080051using ::android::hardware::drm::V1_1::DrmMetricGroup;
Jeff Tinkera53d6552017-01-20 00:31:46 -080052using ::android::hardware::hidl_array;
53using ::android::hardware::hidl_string;
54using ::android::hardware::hidl_vec;
55using ::android::hardware::Return;
56using ::android::hardware::Void;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -080057using ::android::hidl::manager::V1_0::IServiceManager;
Adam Stone637b7852018-01-30 12:09:36 -080058using ::android::os::PersistableBundle;
Jeff Tinkera53d6552017-01-20 00:31:46 -080059using ::android::sp;
60
Adam Stonecea91ce2018-01-22 19:23:28 -080061namespace {
62
63// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
64// in the MediaDrm API.
65constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
66
67}
68
Jeff Tinkera53d6552017-01-20 00:31:46 -080069namespace android {
70
Jeff Tinker6d998b62017-12-18 14:37:43 -080071#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
72
Jeff Tinkera53d6552017-01-20 00:31:46 -080073static inline int getCallingPid() {
74 return IPCThreadState::self()->getCallingPid();
75}
76
77static bool checkPermission(const char* permissionString) {
78 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
79 bool ok = checkCallingPermission(String16(permissionString));
80 if (!ok) ALOGE("Request requires %s", permissionString);
81 return ok;
82}
83
84static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
85 Vector<uint8_t> vector;
86 vector.appendArray(vec.data(), vec.size());
87 return *const_cast<const Vector<uint8_t> *>(&vector);
88}
89
90static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
91 hidl_vec<uint8_t> vec;
92 vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
93 return vec;
94}
95
96static String8 toString8(const hidl_string &string) {
97 return String8(string.c_str());
98}
99
100static hidl_string toHidlString(const String8& string) {
101 return hidl_string(string.string());
102}
103
Adam Stonefb679e32018-02-07 10:25:48 -0800104std::string ToHexString(const std::string& str) {
105 std::ostringstream out;
106 out << std::hex << std::setfill('0');
107 for (size_t i = 0; i < str.size(); i++) {
108 out << std::setw(2) << (int)(str[i]);
109 }
110 return out.str();
111}
112
Jeff Tinker6d998b62017-12-18 14:37:43 -0800113static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
114 switch(level) {
115 case SecurityLevel::SW_SECURE_CRYPTO:
116 return DrmPlugin::kSecurityLevelSwSecureCrypto;
117 case SecurityLevel::SW_SECURE_DECODE:
118 return DrmPlugin::kSecurityLevelSwSecureDecode;
119 case SecurityLevel::HW_SECURE_CRYPTO:
120 return DrmPlugin::kSecurityLevelHwSecureCrypto;
121 case SecurityLevel::HW_SECURE_DECODE:
122 return DrmPlugin::kSecurityLevelHwSecureDecode;
123 case SecurityLevel::HW_SECURE_ALL:
124 return DrmPlugin::kSecurityLevelHwSecureAll;
125 default:
126 return DrmPlugin::kSecurityLevelUnknown;
127 }
128}
129
130static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
131 switch(level) {
132 case HdcpLevel::HDCP_NONE:
133 return DrmPlugin::kHdcpNone;
134 case HdcpLevel::HDCP_V1:
135 return DrmPlugin::kHdcpV1;
136 case HdcpLevel::HDCP_V2:
137 return DrmPlugin::kHdcpV2;
138 case HdcpLevel::HDCP_V2_1:
139 return DrmPlugin::kHdcpV2_1;
140 case HdcpLevel::HDCP_V2_2:
141 return DrmPlugin::kHdcpV2_2;
142 case HdcpLevel::HDCP_NO_OUTPUT:
143 return DrmPlugin::kHdcpNoOutput;
144 default:
145 return DrmPlugin::kHdcpLevelUnknown;
146 }
147}
148
Jeff Tinkera53d6552017-01-20 00:31:46 -0800149
150static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
151 keyedVector) {
152 std::vector<KeyValue> stdKeyedVector;
153 for (size_t i = 0; i < keyedVector.size(); i++) {
154 KeyValue keyValue;
155 keyValue.key = toHidlString(keyedVector.keyAt(i));
156 keyValue.value = toHidlString(keyedVector.valueAt(i));
157 stdKeyedVector.push_back(keyValue);
158 }
159 return ::KeyedVector(stdKeyedVector);
160}
161
162static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
163 hKeyedVector) {
164 KeyedVector<String8, String8> keyedVector;
165 for (size_t i = 0; i < hKeyedVector.size(); i++) {
166 keyedVector.add(toString8(hKeyedVector[i].key),
167 toString8(hKeyedVector[i].value));
168 }
169 return keyedVector;
170}
171
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800172static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
Jeff Tinkera53d6552017-01-20 00:31:46 -0800173 hSecureStops) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800174 List<Vector<uint8_t>> secureStops;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800175 for (size_t i = 0; i < hSecureStops.size(); i++) {
176 secureStops.push_back(toVector(hSecureStops[i].opaqueData));
177 }
178 return secureStops;
179}
180
Jeff Tinker15177d72018-01-25 12:57:55 -0800181static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
182 hSecureStopIds) {
183 List<Vector<uint8_t>> secureStopIds;
184 for (size_t i = 0; i < hSecureStopIds.size(); i++) {
185 secureStopIds.push_back(toVector(hSecureStopIds[i]));
186 }
187 return secureStopIds;
188}
189
Jeff Tinkera53d6552017-01-20 00:31:46 -0800190static status_t toStatusT(Status status) {
191 switch (status) {
192 case Status::OK:
193 return OK;
194 break;
195 case Status::ERROR_DRM_NO_LICENSE:
196 return ERROR_DRM_NO_LICENSE;
197 break;
198 case Status::ERROR_DRM_LICENSE_EXPIRED:
199 return ERROR_DRM_LICENSE_EXPIRED;
200 break;
201 case Status::ERROR_DRM_SESSION_NOT_OPENED:
202 return ERROR_DRM_SESSION_NOT_OPENED;
203 break;
204 case Status::ERROR_DRM_CANNOT_HANDLE:
205 return ERROR_DRM_CANNOT_HANDLE;
206 break;
207 case Status::ERROR_DRM_INVALID_STATE:
208 return ERROR_DRM_TAMPER_DETECTED;
209 break;
210 case Status::BAD_VALUE:
211 return BAD_VALUE;
212 break;
213 case Status::ERROR_DRM_NOT_PROVISIONED:
214 return ERROR_DRM_NOT_PROVISIONED;
215 break;
216 case Status::ERROR_DRM_RESOURCE_BUSY:
217 return ERROR_DRM_RESOURCE_BUSY;
218 break;
219 case Status::ERROR_DRM_DEVICE_REVOKED:
220 return ERROR_DRM_DEVICE_REVOKED;
221 break;
222 case Status::ERROR_DRM_UNKNOWN:
223 default:
224 return ERROR_DRM_UNKNOWN;
225 break;
226 }
227}
228
229
230Mutex DrmHal::mLock;
231
232struct DrmSessionClient : public DrmSessionClientInterface {
233 explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
234
235 virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
236 sp<DrmHal> drm = mDrm.promote();
237 if (drm == NULL) {
238 return true;
239 }
240 status_t err = drm->closeSession(sessionId);
241 if (err != OK) {
242 return false;
243 }
244 drm->sendEvent(EventType::SESSION_RECLAIMED,
245 toHidlVec(sessionId), hidl_vec<uint8_t>());
246 return true;
247 }
248
249protected:
250 virtual ~DrmSessionClient() {}
251
252private:
253 wp<DrmHal> mDrm;
254
255 DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
256};
257
258DrmHal::DrmHal()
259 : mDrmSessionClient(new DrmSessionClient(this)),
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800260 mFactories(makeDrmFactories()),
261 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800262}
263
Jeff Tinker61332812017-05-15 16:53:10 -0700264void DrmHal::closeOpenSessions() {
265 if (mPlugin != NULL) {
Jeff Tinkerb2b66fa2018-01-30 19:19:34 +0000266 for (size_t i = 0; i < mOpenSessions.size(); i++) {
267 mPlugin->closeSession(toHidlVec(mOpenSessions[i]));
268 DrmSessionManager::Instance()->removeSession(mOpenSessions[i]);
Jeff Tinker61332812017-05-15 16:53:10 -0700269 }
270 }
271 mOpenSessions.clear();
272}
273
Jeff Tinkera53d6552017-01-20 00:31:46 -0800274DrmHal::~DrmHal() {
Jeff Tinker61332812017-05-15 16:53:10 -0700275 closeOpenSessions();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800276 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
277}
278
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800279Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
280 Vector<sp<IDrmFactory>> factories;
281
Jeff Tinker593111f2017-05-25 16:00:21 -0700282 auto manager = hardware::defaultServiceManager();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800283
284 if (manager != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000285 manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800286 [&factories](const hidl_vec<hidl_string> &registered) {
287 for (const auto &instance : registered) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000288 auto factory = drm::V1_0::IDrmFactory::getService(instance);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800289 if (factory != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000290 ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str());
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800291 factories.push_back(factory);
Jeff Tinkere307dc42018-02-11 19:53:54 +0000292 }
293 }
294 }
295 );
296 manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
297 [&factories](const hidl_vec<hidl_string> &registered) {
298 for (const auto &instance : registered) {
299 auto factory = drm::V1_1::IDrmFactory::getService(instance);
300 if (factory != NULL) {
301 ALOGD("found drm@1.1 IDrmFactory %s", instance.c_str());
302 factories.push_back(factory);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800303 }
304 }
305 }
306 );
Jeff Tinkera53d6552017-01-20 00:31:46 -0800307 }
Jeff Tinkerc82b9c32017-02-14 11:39:51 -0800308
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800309 if (factories.size() == 0) {
310 // must be in passthrough mode, load the default passthrough service
Jeff Tinkere309b222017-04-05 08:01:28 -0700311 auto passthrough = IDrmFactory::getService();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800312 if (passthrough != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000313 ALOGI("makeDrmFactories: using default passthrough drm instance");
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800314 factories.push_back(passthrough);
315 } else {
316 ALOGE("Failed to find any drm factories");
317 }
318 }
319 return factories;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800320}
321
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800322sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
323 const uint8_t uuid[16], const String8& appPackageName) {
Adam Stonefb679e32018-02-07 10:25:48 -0800324 mMetrics.SetAppPackageName(appPackageName);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800325
326 sp<IDrmPlugin> plugin;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800327 Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
Jeff Tinkera53d6552017-01-20 00:31:46 -0800328 [&](Status status, const sp<IDrmPlugin>& hPlugin) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800329 if (status != Status::OK) {
330 ALOGE("Failed to make drm plugin");
331 return;
332 }
333 plugin = hPlugin;
334 }
335 );
Jeff Tinkerf0e89b02017-08-07 15:58:41 -0700336
337 if (!hResult.isOk()) {
338 ALOGE("createPlugin remote call failed");
339 }
340
Jeff Tinkera53d6552017-01-20 00:31:46 -0800341 return plugin;
342}
343
344status_t DrmHal::initCheck() const {
345 return mInitCheck;
346}
347
348status_t DrmHal::setListener(const sp<IDrmClient>& listener)
349{
350 Mutex::Autolock lock(mEventLock);
351 if (mListener != NULL){
352 IInterface::asBinder(mListener)->unlinkToDeath(this);
353 }
354 if (listener != NULL) {
355 IInterface::asBinder(listener)->linkToDeath(this);
356 }
357 mListener = listener;
358 return NO_ERROR;
359}
360
361Return<void> DrmHal::sendEvent(EventType hEventType,
362 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
Adam Stonecea91ce2018-01-22 19:23:28 -0800363 mMetrics.mEventCounter.Increment(hEventType);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800364
365 mEventLock.lock();
366 sp<IDrmClient> listener = mListener;
367 mEventLock.unlock();
368
369 if (listener != NULL) {
370 Parcel obj;
371 writeByteArray(obj, sessionId);
372 writeByteArray(obj, data);
373
374 Mutex::Autolock lock(mNotifyLock);
375 DrmPlugin::EventType eventType;
376 switch(hEventType) {
377 case EventType::PROVISION_REQUIRED:
378 eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
379 break;
380 case EventType::KEY_NEEDED:
381 eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
382 break;
383 case EventType::KEY_EXPIRED:
384 eventType = DrmPlugin::kDrmPluginEventKeyExpired;
385 break;
386 case EventType::VENDOR_DEFINED:
387 eventType = DrmPlugin::kDrmPluginEventVendorDefined;
388 break;
Rahul Friasb86f4b32017-03-27 15:13:30 -0700389 case EventType::SESSION_RECLAIMED:
390 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
391 break;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800392 default:
393 return Void();
394 }
395 listener->notify(eventType, 0, &obj);
396 }
397 return Void();
398}
399
400Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
401 int64_t expiryTimeInMS) {
402
403 mEventLock.lock();
404 sp<IDrmClient> listener = mListener;
405 mEventLock.unlock();
406
407 if (listener != NULL) {
408 Parcel obj;
409 writeByteArray(obj, sessionId);
410 obj.writeInt64(expiryTimeInMS);
411
412 Mutex::Autolock lock(mNotifyLock);
413 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
414 }
415 return Void();
416}
417
418Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
419 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
420
421 mEventLock.lock();
422 sp<IDrmClient> listener = mListener;
423 mEventLock.unlock();
424
425 if (listener != NULL) {
426 Parcel obj;
427 writeByteArray(obj, sessionId);
428
429 size_t nKeys = keyStatusList.size();
430 obj.writeInt32(nKeys);
431 for (size_t i = 0; i < nKeys; ++i) {
432 const KeyStatus &keyStatus = keyStatusList[i];
433 writeByteArray(obj, keyStatus.keyId);
434 uint32_t type;
435 switch(keyStatus.type) {
436 case KeyStatusType::USABLE:
437 type = DrmPlugin::kKeyStatusType_Usable;
438 break;
439 case KeyStatusType::EXPIRED:
440 type = DrmPlugin::kKeyStatusType_Expired;
441 break;
442 case KeyStatusType::OUTPUTNOTALLOWED:
443 type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
444 break;
445 case KeyStatusType::STATUSPENDING:
446 type = DrmPlugin::kKeyStatusType_StatusPending;
447 break;
448 case KeyStatusType::INTERNALERROR:
449 default:
450 type = DrmPlugin::kKeyStatusType_InternalError;
451 break;
452 }
453 obj.writeInt32(type);
Adam Stonecea91ce2018-01-22 19:23:28 -0800454 mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800455 }
456 obj.writeInt32(hasNewUsableKey);
457
458 Mutex::Autolock lock(mNotifyLock);
459 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
Adam Stonecea91ce2018-01-22 19:23:28 -0800460 } else {
461 // There's no listener. But we still want to count the key change
462 // events.
463 size_t nKeys = keyStatusList.size();
464 for (size_t i = 0; i < nKeys; i++) {
465 mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
466 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800467 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800468
Jeff Tinkera53d6552017-01-20 00:31:46 -0800469 return Void();
470}
471
472bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
473 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800474
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800475 for (size_t i = 0; i < mFactories.size(); i++) {
476 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
477 if (mimeType != "") {
478 if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
479 return true;
480 }
481 } else {
482 return true;
483 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800484 }
485 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800486 return false;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800487}
488
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800489status_t DrmHal::createPlugin(const uint8_t uuid[16],
490 const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800491 Mutex::Autolock autoLock(mLock);
492
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800493 for (size_t i = 0; i < mFactories.size(); i++) {
494 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
495 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
Edwin Wong5641aa22018-01-30 17:52:21 -0800496 if (mPlugin != NULL) {
497 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
498 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800499 }
500 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800501
502 if (mPlugin == NULL) {
503 mInitCheck = ERROR_UNSUPPORTED;
504 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700505 if (!mPlugin->setListener(this).isOk()) {
506 mInitCheck = DEAD_OBJECT;
507 } else {
508 mInitCheck = OK;
509 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800510 }
511
512 return mInitCheck;
513}
514
515status_t DrmHal::destroyPlugin() {
516 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800517 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800518
Jeff Tinker61332812017-05-15 16:53:10 -0700519 closeOpenSessions();
Adam Stonefb679e32018-02-07 10:25:48 -0800520 reportPluginMetrics();
521 reportFrameworkMetrics();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800522 setListener(NULL);
Jeff Tinker70367f52017-06-16 12:41:33 -0700523 mInitCheck = NO_INIT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800524
Jeff Tinker319d5f42017-07-26 15:44:33 -0700525 if (mPlugin != NULL) {
526 if (!mPlugin->setListener(NULL).isOk()) {
527 mInitCheck = DEAD_OBJECT;
528 }
529 }
530 mPlugin.clear();
Edwin Wong5641aa22018-01-30 17:52:21 -0800531 mPluginV1_1.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800532 return OK;
533}
534
Jeff Tinker41d279a2018-02-11 19:52:08 +0000535status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
536 Vector<uint8_t> &sessionId) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800537 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800538 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800539
Jeff Tinker41d279a2018-02-11 19:52:08 +0000540 SecurityLevel hSecurityLevel;
541 bool setSecurityLevel = true;
Tobias Thierer5f5e43f2018-02-11 15:00:57 +0000542
Jeff Tinker41d279a2018-02-11 19:52:08 +0000543 switch(level) {
544 case DrmPlugin::kSecurityLevelSwSecureCrypto:
545 hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
546 break;
547 case DrmPlugin::kSecurityLevelSwSecureDecode:
548 hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
549 break;
550 case DrmPlugin::kSecurityLevelHwSecureCrypto:
551 hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
552 break;
553 case DrmPlugin::kSecurityLevelHwSecureDecode:
554 hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
555 break;
556 case DrmPlugin::kSecurityLevelHwSecureAll:
557 hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
558 break;
559 case DrmPlugin::kSecurityLevelMax:
560 setSecurityLevel = false;
561 break;
562 default:
563 return ERROR_DRM_CANNOT_HANDLE;
564 }
565
566 status_t err = UNKNOWN_ERROR;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800567 bool retry = true;
568 do {
569 hidl_vec<uint8_t> hSessionId;
570
Jeff Tinker41d279a2018-02-11 19:52:08 +0000571 Return<void> hResult;
572 if (mPluginV1_1 == NULL || !setSecurityLevel) {
573 hResult = mPlugin->openSession(
574 [&](Status status,const hidl_vec<uint8_t>& id) {
575 if (status == Status::OK) {
576 sessionId = toVector(id);
577 }
578 err = toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800579 }
Jeff Tinker41d279a2018-02-11 19:52:08 +0000580 );
581 } else {
582 hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
583 [&](Status status, const hidl_vec<uint8_t>& id) {
584 if (status == Status::OK) {
585 sessionId = toVector(id);
586 }
587 err = toStatusT(status);
588 }
589 );
590 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800591
592 if (!hResult.isOk()) {
593 err = DEAD_OBJECT;
594 }
595
596 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
597 mLock.unlock();
598 // reclaimSession may call back to closeSession, since mLock is
599 // shared between Drm instances, we should unlock here to avoid
600 // deadlock.
601 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
602 mLock.lock();
603 } else {
604 retry = false;
605 }
606 } while (retry);
607
608 if (err == OK) {
609 DrmSessionManager::Instance()->addSession(getCallingPid(),
610 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700611 mOpenSessions.push(sessionId);
Adam Stone568b3c42018-01-31 12:57:16 -0800612 mMetrics.SetSessionStart(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800613 }
Adam Stoneaaf87dd2018-01-08 11:55:06 -0800614
Adam Stonef0e618d2018-01-17 19:20:41 -0800615 mMetrics.mOpenSessionCounter.Increment(err);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800616 return err;
617}
618
619status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
620 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800621 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800622
Jeff Tinker319d5f42017-07-26 15:44:33 -0700623 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
624 if (status.isOk()) {
625 if (status == Status::OK) {
626 DrmSessionManager::Instance()->removeSession(sessionId);
627 for (size_t i = 0; i < mOpenSessions.size(); i++) {
628 if (mOpenSessions[i] == sessionId) {
629 mOpenSessions.removeAt(i);
630 break;
631 }
Jeff Tinker61332812017-05-15 16:53:10 -0700632 }
633 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800634 status_t response = toStatusT(status);
Adam Stone568b3c42018-01-31 12:57:16 -0800635 mMetrics.SetSessionEnd(sessionId);
Adam Stonecea91ce2018-01-22 19:23:28 -0800636 mMetrics.mCloseSessionCounter.Increment(response);
Adam Stonefb679e32018-02-07 10:25:48 -0800637 reportPluginMetrics();
Adam Stonecea91ce2018-01-22 19:23:28 -0800638 return response;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800639 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800640 mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
Jeff Tinker319d5f42017-07-26 15:44:33 -0700641 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800642}
643
644status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
645 Vector<uint8_t> const &initData, String8 const &mimeType,
646 DrmPlugin::KeyType keyType, KeyedVector<String8,
647 String8> const &optionalParameters, Vector<uint8_t> &request,
648 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
649 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800650 INIT_CHECK();
Adam Stonefb679e32018-02-07 10:25:48 -0800651 EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800652
653 DrmSessionManager::Instance()->useSession(sessionId);
654
655 KeyType hKeyType;
656 if (keyType == DrmPlugin::kKeyType_Streaming) {
657 hKeyType = KeyType::STREAMING;
658 } else if (keyType == DrmPlugin::kKeyType_Offline) {
659 hKeyType = KeyType::OFFLINE;
660 } else if (keyType == DrmPlugin::kKeyType_Release) {
661 hKeyType = KeyType::RELEASE;
662 } else {
Adam Stonef0e618d2018-01-17 19:20:41 -0800663 keyRequestTimer.SetAttribute(BAD_VALUE);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800664 return BAD_VALUE;
665 }
666
667 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
668
669 status_t err = UNKNOWN_ERROR;
670
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800671 if (mPluginV1_1 != NULL) {
672 Return<void> hResult =
673 mPluginV1_1->getKeyRequest_1_1(
674 toHidlVec(sessionId), toHidlVec(initData),
675 toHidlString(mimeType), hKeyType, hOptionalParameters,
676 [&](Status status, const hidl_vec<uint8_t>& hRequest,
677 drm::V1_1::KeyRequestType hKeyRequestType,
678 const hidl_string& hDefaultUrl) {
679
680 if (status == Status::OK) {
681 request = toVector(hRequest);
682 defaultUrl = toString8(hDefaultUrl);
683
684 switch (hKeyRequestType) {
685 case drm::V1_1::KeyRequestType::INITIAL:
686 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
687 break;
688 case drm::V1_1::KeyRequestType::RENEWAL:
689 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
690 break;
691 case drm::V1_1::KeyRequestType::RELEASE:
692 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
693 break;
694 case drm::V1_1::KeyRequestType::NONE:
695 *keyRequestType = DrmPlugin::kKeyRequestType_None;
696 break;
697 case drm::V1_1::KeyRequestType::UPDATE:
698 *keyRequestType = DrmPlugin::kKeyRequestType_Update;
699 break;
700 default:
701 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
702 break;
703 }
704 err = toStatusT(status);
705 }
706 });
707 return hResult.isOk() ? err : DEAD_OBJECT;
708 }
709
Jeff Tinkera53d6552017-01-20 00:31:46 -0800710 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
711 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
712 [&](Status status, const hidl_vec<uint8_t>& hRequest,
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800713 drm::V1_0::KeyRequestType hKeyRequestType,
714 const hidl_string& hDefaultUrl) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800715
716 if (status == Status::OK) {
717 request = toVector(hRequest);
718 defaultUrl = toString8(hDefaultUrl);
719
720 switch (hKeyRequestType) {
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800721 case drm::V1_0::KeyRequestType::INITIAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800722 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
723 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800724 case drm::V1_0::KeyRequestType::RENEWAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800725 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
726 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800727 case drm::V1_0::KeyRequestType::RELEASE:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800728 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
729 break;
730 default:
731 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
732 break;
733 }
734 err = toStatusT(status);
735 }
736 });
737
Adam Stonef0e618d2018-01-17 19:20:41 -0800738 err = hResult.isOk() ? err : DEAD_OBJECT;
739 keyRequestTimer.SetAttribute(err);
740 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800741}
742
743status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
744 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
745 Mutex::Autolock autoLock(mLock);
Adam Stonefb679e32018-02-07 10:25:48 -0800746 EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800747
Jeff Tinker6d998b62017-12-18 14:37:43 -0800748 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800749
750 DrmSessionManager::Instance()->useSession(sessionId);
751
752 status_t err = UNKNOWN_ERROR;
753
754 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
755 toHidlVec(response),
756 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
757 if (status == Status::OK) {
758 keySetId = toVector(hKeySetId);
759 }
760 err = toStatusT(status);
761 }
762 );
Adam Stonecea91ce2018-01-22 19:23:28 -0800763 err = hResult.isOk() ? err : DEAD_OBJECT;
764 keyResponseTimer.SetAttribute(err);
765 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800766}
767
768status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
769 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800770 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800771
772 return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
773}
774
775status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
776 Vector<uint8_t> const &keySetId) {
777 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800778 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800779
780 DrmSessionManager::Instance()->useSession(sessionId);
781
782 return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
783 toHidlVec(keySetId)));
784}
785
786status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
787 KeyedVector<String8, String8> &infoMap) const {
788 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800789 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800790
791 DrmSessionManager::Instance()->useSession(sessionId);
792
793 ::KeyedVector hInfoMap;
794
795 status_t err = UNKNOWN_ERROR;
796
797 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
798 [&](Status status, const hidl_vec<KeyValue>& map) {
799 if (status == Status::OK) {
800 infoMap = toKeyedVector(map);
801 }
802 err = toStatusT(status);
803 }
804 );
805
806 return hResult.isOk() ? err : DEAD_OBJECT;
807}
808
809status_t DrmHal::getProvisionRequest(String8 const &certType,
810 String8 const &certAuthority, Vector<uint8_t> &request,
811 String8 &defaultUrl) {
812 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800813 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800814
815 status_t err = UNKNOWN_ERROR;
816
817 Return<void> hResult = mPlugin->getProvisionRequest(
818 toHidlString(certType), toHidlString(certAuthority),
819 [&](Status status, const hidl_vec<uint8_t>& hRequest,
820 const hidl_string& hDefaultUrl) {
821 if (status == Status::OK) {
822 request = toVector(hRequest);
823 defaultUrl = toString8(hDefaultUrl);
824 }
825 err = toStatusT(status);
826 }
827 );
828
Adam Stonecea91ce2018-01-22 19:23:28 -0800829 err = hResult.isOk() ? err : DEAD_OBJECT;
830 mMetrics.mGetProvisionRequestCounter.Increment(err);
831 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800832}
833
834status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800835 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800836 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800837 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800838
839 status_t err = UNKNOWN_ERROR;
840
841 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
842 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
843 const hidl_vec<uint8_t>& hWrappedKey) {
844 if (status == Status::OK) {
845 certificate = toVector(hCertificate);
846 wrappedKey = toVector(hWrappedKey);
847 }
848 err = toStatusT(status);
849 }
850 );
851
Adam Stonecea91ce2018-01-22 19:23:28 -0800852 err = hResult.isOk() ? err : DEAD_OBJECT;
853 mMetrics.mProvideProvisionResponseCounter.Increment(err);
854 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800855}
856
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800857status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800858 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800859 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800860
861 status_t err = UNKNOWN_ERROR;
862
863 Return<void> hResult = mPlugin->getSecureStops(
864 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
865 if (status == Status::OK) {
866 secureStops = toSecureStops(hSecureStops);
867 }
868 err = toStatusT(status);
869 }
870 );
871
872 return hResult.isOk() ? err : DEAD_OBJECT;
873}
874
875
Jeff Tinker15177d72018-01-25 12:57:55 -0800876status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
877 Mutex::Autolock autoLock(mLock);
878
879 if (mInitCheck != OK) {
880 return mInitCheck;
881 }
882
883 if (mPluginV1_1 == NULL) {
884 return ERROR_DRM_CANNOT_HANDLE;
885 }
886
887 status_t err = UNKNOWN_ERROR;
888
889 Return<void> hResult = mPluginV1_1->getSecureStopIds(
890 [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
891 if (status == Status::OK) {
892 secureStopIds = toSecureStopIds(hSecureStopIds);
893 }
894 err = toStatusT(status);
895 }
896 );
897
898 return hResult.isOk() ? err : DEAD_OBJECT;
899}
900
901
Jeff Tinkera53d6552017-01-20 00:31:46 -0800902status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
903 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800904 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800905
906 status_t err = UNKNOWN_ERROR;
907
908 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
909 [&](Status status, const SecureStop& hSecureStop) {
910 if (status == Status::OK) {
911 secureStop = toVector(hSecureStop.opaqueData);
912 }
913 err = toStatusT(status);
914 }
915 );
916
917 return hResult.isOk() ? err : DEAD_OBJECT;
918}
919
920status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
921 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800922 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800923
Jeff Tinker15177d72018-01-25 12:57:55 -0800924 if (mPluginV1_1 != NULL) {
925 SecureStopRelease secureStopRelease;
926 secureStopRelease.opaqueData = toHidlVec(ssRelease);
927 return toStatusT(mPluginV1_1->releaseSecureStops(secureStopRelease));
928 }
929
Jeff Tinkera53d6552017-01-20 00:31:46 -0800930 return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
931}
932
Jeff Tinker15177d72018-01-25 12:57:55 -0800933status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
934 Mutex::Autolock autoLock(mLock);
935
936 if (mInitCheck != OK) {
937 return mInitCheck;
938 }
939
940 if (mPluginV1_1 == NULL) {
941 return ERROR_DRM_CANNOT_HANDLE;
942 }
943
944 return toStatusT(mPluginV1_1->removeSecureStop(toHidlVec(ssid)));
945}
946
947status_t DrmHal::removeAllSecureStops() {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800948 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800949 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800950
Jeff Tinker15177d72018-01-25 12:57:55 -0800951 if (mPluginV1_1 != NULL) {
952 return toStatusT(mPluginV1_1->removeAllSecureStops());
953 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800954 return toStatusT(mPlugin->releaseAllSecureStops());
955}
956
Jeff Tinker6d998b62017-12-18 14:37:43 -0800957status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
958 DrmPlugin::HdcpLevel *max) const {
959 Mutex::Autolock autoLock(mLock);
960 INIT_CHECK();
961
962 if (connected == NULL || max == NULL) {
963 return BAD_VALUE;
964 }
965 status_t err = UNKNOWN_ERROR;
966
967 if (mPluginV1_1 == NULL) {
968 return ERROR_DRM_CANNOT_HANDLE;
969 }
970
971 *connected = DrmPlugin::kHdcpLevelUnknown;
972 *max = DrmPlugin::kHdcpLevelUnknown;
973
974 Return<void> hResult = mPluginV1_1->getHdcpLevels(
975 [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
976 if (status == Status::OK) {
977 *connected = toHdcpLevel(hConnected);
978 *max = toHdcpLevel(hMax);
979 }
980 err = toStatusT(status);
981 }
982 );
983
984 return hResult.isOk() ? err : DEAD_OBJECT;
985}
986
987status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
988 Mutex::Autolock autoLock(mLock);
989 INIT_CHECK();
990
991 if (open == NULL || max == NULL) {
992 return BAD_VALUE;
993 }
994 status_t err = UNKNOWN_ERROR;
995
996 *open = 0;
997 *max = 0;
998
999 if (mPluginV1_1 == NULL) {
1000 return ERROR_DRM_CANNOT_HANDLE;
1001 }
1002
1003 Return<void> hResult = mPluginV1_1->getNumberOfSessions(
1004 [&](Status status, uint32_t hOpen, uint32_t hMax) {
1005 if (status == Status::OK) {
1006 *open = hOpen;
1007 *max = hMax;
1008 }
1009 err = toStatusT(status);
1010 }
1011 );
1012
1013 return hResult.isOk() ? err : DEAD_OBJECT;
1014}
1015
1016status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
1017 DrmPlugin::SecurityLevel *level) const {
1018 Mutex::Autolock autoLock(mLock);
1019 INIT_CHECK();
1020
1021 if (level == NULL) {
1022 return BAD_VALUE;
1023 }
1024 status_t err = UNKNOWN_ERROR;
1025
1026 if (mPluginV1_1 == NULL) {
1027 return ERROR_DRM_CANNOT_HANDLE;
1028 }
1029
1030 *level = DrmPlugin::kSecurityLevelUnknown;
1031
1032 Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
1033 [&](Status status, SecurityLevel hLevel) {
1034 if (status == Status::OK) {
1035 *level = toSecurityLevel(hLevel);
1036 }
1037 err = toStatusT(status);
1038 }
1039 );
1040
1041 return hResult.isOk() ? err : DEAD_OBJECT;
1042}
1043
Jeff Tinkera53d6552017-01-20 00:31:46 -08001044status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
1045 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001046 return getPropertyStringInternal(name, value);
1047}
1048
1049status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
1050 // This function is internal to the class and should only be called while
1051 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001052 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001053
1054 status_t err = UNKNOWN_ERROR;
1055
1056 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
1057 [&](Status status, const hidl_string& hValue) {
1058 if (status == Status::OK) {
1059 value = toString8(hValue);
1060 }
1061 err = toStatusT(status);
1062 }
1063 );
1064
1065 return hResult.isOk() ? err : DEAD_OBJECT;
1066}
1067
1068status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
1069 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001070 return getPropertyByteArrayInternal(name, value);
1071}
1072
1073status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
1074 // This function is internal to the class and should only be called while
1075 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001076 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001077
1078 status_t err = UNKNOWN_ERROR;
1079
1080 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
1081 [&](Status status, const hidl_vec<uint8_t>& hValue) {
1082 if (status == Status::OK) {
1083 value = toVector(hValue);
1084 }
1085 err = toStatusT(status);
1086 }
1087 );
1088
Adam Stonecea91ce2018-01-22 19:23:28 -08001089 err = hResult.isOk() ? err : DEAD_OBJECT;
1090 if (name == kPropertyDeviceUniqueId) {
1091 mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
1092 }
1093 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001094}
1095
1096status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
1097 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001098 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001099
Jeff Tinker6d998b62017-12-18 14:37:43 -08001100 Status status = mPlugin->setPropertyString(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001101 toHidlString(value));
1102 return toStatusT(status);
1103}
1104
1105status_t DrmHal::setPropertyByteArray(String8 const &name,
1106 Vector<uint8_t> const &value ) const {
1107 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001108 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001109
1110 Status status = mPlugin->setPropertyByteArray(toHidlString(name),
1111 toHidlVec(value));
1112 return toStatusT(status);
1113}
1114
Adam Stone28f27c32018-02-05 15:07:48 -08001115status_t DrmHal::getMetrics(PersistableBundle* metrics) {
1116 if (metrics == nullptr) {
1117 return UNEXPECTED_NULL;
1118 }
1119 mMetrics.Export(metrics);
1120
1121 // Append vendor metrics if they are supported.
1122 if (mPluginV1_1 != NULL) {
1123 String8 vendor;
1124 String8 description;
1125 if (getPropertyStringInternal(String8("vendor"), vendor) != OK
1126 || vendor.isEmpty()) {
1127 ALOGE("Get vendor failed or is empty");
1128 vendor = "NONE";
1129 }
1130 if (getPropertyStringInternal(String8("description"), description) != OK
1131 || description.isEmpty()) {
1132 ALOGE("Get description failed or is empty.");
1133 description = "NONE";
1134 }
1135 vendor += ".";
1136 vendor += description;
1137
1138 hidl_vec<DrmMetricGroup> pluginMetrics;
1139 status_t err = UNKNOWN_ERROR;
1140
1141 Return<void> status = mPluginV1_1->getMetrics(
1142 [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
1143 if (status != Status::OK) {
1144 ALOGV("Error getting plugin metrics: %d", status);
1145 } else {
1146 PersistableBundle pluginBundle;
1147 if (MediaDrmMetrics::HidlMetricsToBundle(
1148 pluginMetrics, &pluginBundle) == OK) {
1149 metrics->putPersistableBundle(String16(vendor), pluginBundle);
1150 }
1151 }
1152 err = toStatusT(status);
1153 });
1154 return status.isOk() ? err : DEAD_OBJECT;
Adam Stonef0e618d2018-01-17 19:20:41 -08001155 }
1156
Adam Stoneab394d12017-12-22 12:34:20 -08001157 return OK;
1158}
Jeff Tinkera53d6552017-01-20 00:31:46 -08001159
1160status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
1161 String8 const &algorithm) {
1162 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001163 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001164
1165 DrmSessionManager::Instance()->useSession(sessionId);
1166
1167 Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
1168 toHidlString(algorithm));
1169 return toStatusT(status);
1170}
1171
1172status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
1173 String8 const &algorithm) {
1174 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001175 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001176
1177 DrmSessionManager::Instance()->useSession(sessionId);
1178
1179 Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
1180 toHidlString(algorithm));
1181 return toStatusT(status);
1182}
1183
1184status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001185 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1186 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001187 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001188 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001189
1190 DrmSessionManager::Instance()->useSession(sessionId);
1191
1192 status_t err = UNKNOWN_ERROR;
1193
1194 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
1195 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1196 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1197 if (status == Status::OK) {
1198 output = toVector(hOutput);
1199 }
1200 err = toStatusT(status);
1201 }
1202 );
1203
1204 return hResult.isOk() ? err : DEAD_OBJECT;
1205}
1206
1207status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001208 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1209 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001210 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001211 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001212
1213 DrmSessionManager::Instance()->useSession(sessionId);
1214
1215 status_t err = UNKNOWN_ERROR;
1216
1217 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
1218 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1219 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1220 if (status == Status::OK) {
1221 output = toVector(hOutput);
1222 }
1223 err = toStatusT(status);
1224 }
1225 );
1226
1227 return hResult.isOk() ? err : DEAD_OBJECT;
1228}
1229
1230status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001231 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1232 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001233 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001234 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001235
1236 DrmSessionManager::Instance()->useSession(sessionId);
1237
1238 status_t err = UNKNOWN_ERROR;
1239
1240 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
1241 toHidlVec(keyId), toHidlVec(message),
1242 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1243 if (status == Status::OK) {
1244 signature = toVector(hSignature);
1245 }
1246 err = toStatusT(status);
1247 }
1248 );
1249
1250 return hResult.isOk() ? err : DEAD_OBJECT;
1251}
1252
1253status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001254 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1255 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001256 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001257 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001258
1259 DrmSessionManager::Instance()->useSession(sessionId);
1260
1261 status_t err = UNKNOWN_ERROR;
1262
1263 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
1264 toHidlVec(message), toHidlVec(signature),
1265 [&](Status status, bool hMatch) {
1266 if (status == Status::OK) {
1267 match = hMatch;
1268 } else {
1269 match = false;
1270 }
1271 err = toStatusT(status);
1272 }
1273 );
1274
1275 return hResult.isOk() ? err : DEAD_OBJECT;
1276}
1277
1278status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001279 String8 const &algorithm, Vector<uint8_t> const &message,
1280 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001281 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001282 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001283
1284 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
1285 return -EPERM;
1286 }
1287
1288 DrmSessionManager::Instance()->useSession(sessionId);
1289
1290 status_t err = UNKNOWN_ERROR;
1291
1292 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1293 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1294 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1295 if (status == Status::OK) {
1296 signature = toVector(hSignature);
1297 }
1298 err = toStatusT(status);
1299 }
1300 );
1301
1302 return hResult.isOk() ? err : DEAD_OBJECT;
1303}
1304
1305void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1306{
Jeff Tinkera53d6552017-01-20 00:31:46 -08001307 Mutex::Autolock autoLock(mLock);
Jeff Tinker61332812017-05-15 16:53:10 -07001308 closeOpenSessions();
Jeff Tinker3e289162017-06-01 11:13:53 -07001309 setListener(NULL);
Jeff Tinker319d5f42017-07-26 15:44:33 -07001310 mInitCheck = NO_INIT;
1311
Jeff Tinker70367f52017-06-16 12:41:33 -07001312 if (mPlugin != NULL) {
Jeff Tinker319d5f42017-07-26 15:44:33 -07001313 if (!mPlugin->setListener(NULL).isOk()) {
1314 mInitCheck = DEAD_OBJECT;
1315 }
Jeff Tinker70367f52017-06-16 12:41:33 -07001316 }
Jeff Tinkera53d6552017-01-20 00:31:46 -08001317 mPlugin.clear();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001318}
1319
1320void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1321{
1322 if (vec.size()) {
1323 obj.writeInt32(vec.size());
1324 obj.write(vec.data(), vec.size());
1325 } else {
1326 obj.writeInt32(0);
1327 }
1328}
1329
Adam Stonefb679e32018-02-07 10:25:48 -08001330void DrmHal::reportFrameworkMetrics() const
1331{
1332 MediaAnalyticsItem item("mediadrm");
1333 item.generateSessionID();
1334 item.setPkgName(mMetrics.GetAppPackageName().c_str());
1335 String8 vendor;
1336 String8 description;
1337 status_t result = getPropertyStringInternal(String8("vendor"), vendor);
1338 if (result != OK) {
1339 ALOGE("Failed to get vendor from drm plugin. %d", result);
1340 } else {
1341 item.setCString("vendor", vendor.c_str());
1342 }
1343 result = getPropertyStringInternal(String8("description"), description);
1344 if (result != OK) {
1345 ALOGE("Failed to get description from drm plugin. %d", result);
1346 } else {
1347 item.setCString("description", description.c_str());
1348 }
Adam Stoneab394d12017-12-22 12:34:20 -08001349
Adam Stonefb679e32018-02-07 10:25:48 -08001350 std::string serializedMetrics;
1351 result = mMetrics.GetSerializedMetrics(&serializedMetrics);
1352 if (result != OK) {
1353 ALOGE("Failed to serialize Framework metrics: %d", result);
1354 }
1355 serializedMetrics = ToHexString(serializedMetrics);
1356 if (!serializedMetrics.empty()) {
1357 item.setCString("serialized_metrics", serializedMetrics.c_str());
1358 }
1359 if (!item.selfrecord()) {
1360 ALOGE("Failed to self record framework metrics.");
1361 }
1362}
1363
1364void DrmHal::reportPluginMetrics() const
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001365{
1366 Vector<uint8_t> metrics;
1367 String8 vendor;
1368 String8 description;
1369 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1370 getPropertyStringInternal(String8("description"), description) == OK &&
1371 getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
1372 status_t res = android::reportDrmPluginMetrics(
1373 metrics, vendor, description);
1374 if (res != OK) {
1375 ALOGE("Metrics were retrieved but could not be reported: %i", res);
1376 }
1377 }
1378}
1379
Jeff Tinkera53d6552017-01-20 00:31:46 -08001380} // namespace android