DrmHal.cpp revision 28f27c3bee88b0f47b1086feeaa904bcdec37af6
1/* 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 <iomanip> 20 21#include <utils/Log.h> 22 23#include <binder/IPCThreadState.h> 24#include <binder/IServiceManager.h> 25 26#include <android/hardware/drm/1.0/types.h> 27#include <android/hidl/manager/1.0/IServiceManager.h> 28#include <hidl/ServiceManagement.h> 29 30#include <media/DrmHal.h> 31#include <media/DrmSessionClientInterface.h> 32#include <media/DrmSessionManager.h> 33#include <media/EventMetric.h> 34#include <media/PluginMetricsReporting.h> 35#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 41using drm::V1_0::KeyedVector; 42using drm::V1_0::KeyStatusType; 43using drm::V1_0::KeyType; 44using drm::V1_0::KeyValue; 45using drm::V1_1::HdcpLevel;; 46using drm::V1_0::SecureStop; 47using drm::V1_1::SecureStopRelease; 48using drm::V1_0::SecureStopId; 49using drm::V1_1::SecurityLevel; 50using drm::V1_0::Status; 51using ::android::hardware::drm::V1_1::DrmMetricGroup; 52using ::android::hardware::hidl_array; 53using ::android::hardware::hidl_string; 54using ::android::hardware::hidl_vec; 55using ::android::hardware::Return; 56using ::android::hardware::Void; 57using ::android::hidl::manager::V1_0::IServiceManager; 58using ::android::os::PersistableBundle; 59using ::android::sp; 60 61namespace { 62 63// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant 64// in the MediaDrm API. 65constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId"; 66 67} 68 69namespace android { 70 71#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;} 72 73static 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 104std::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 113static 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 149 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 172static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>& 173 hSecureStops) { 174 List<Vector<uint8_t>> secureStops; 175 for (size_t i = 0; i < hSecureStops.size(); i++) { 176 secureStops.push_back(toVector(hSecureStops[i].opaqueData)); 177 } 178 return secureStops; 179} 180 181static 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 190static 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)), 260 mFactories(makeDrmFactories()), 261 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) { 262} 263 264void DrmHal::closeOpenSessions() { 265 if (mPlugin != NULL) { 266 for (size_t i = 0; i < mOpenSessions.size(); i++) { 267 mPlugin->closeSession(toHidlVec(mOpenSessions[i])); 268 DrmSessionManager::Instance()->removeSession(mOpenSessions[i]); 269 } 270 } 271 mOpenSessions.clear(); 272} 273 274DrmHal::~DrmHal() { 275 closeOpenSessions(); 276 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient); 277} 278 279Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() { 280 Vector<sp<IDrmFactory>> factories; 281 282 auto manager = hardware::defaultServiceManager(); 283 284 if (manager != NULL) { 285 manager->listByInterface(drm::V1_0::IDrmFactory::descriptor, 286 [&factories](const hidl_vec<hidl_string> ®istered) { 287 for (const auto &instance : registered) { 288 auto factory = drm::V1_0::IDrmFactory::getService(instance); 289 if (factory != NULL) { 290 ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str()); 291 factories.push_back(factory); 292 } 293 } 294 } 295 ); 296 manager->listByInterface(drm::V1_1::IDrmFactory::descriptor, 297 [&factories](const hidl_vec<hidl_string> ®istered) { 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); 303 } 304 } 305 } 306 ); 307 } 308 309 if (factories.size() == 0) { 310 // must be in passthrough mode, load the default passthrough service 311 auto passthrough = IDrmFactory::getService(); 312 if (passthrough != NULL) { 313 ALOGI("makeDrmFactories: using default passthrough drm instance"); 314 factories.push_back(passthrough); 315 } else { 316 ALOGE("Failed to find any drm factories"); 317 } 318 } 319 return factories; 320} 321 322sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory, 323 const uint8_t uuid[16], const String8& appPackageName) { 324 mMetrics.SetAppPackageName(appPackageName); 325 326 sp<IDrmPlugin> plugin; 327 Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(), 328 [&](Status status, const sp<IDrmPlugin>& hPlugin) { 329 if (status != Status::OK) { 330 ALOGE("Failed to make drm plugin"); 331 return; 332 } 333 plugin = hPlugin; 334 } 335 ); 336 337 if (!hResult.isOk()) { 338 ALOGE("createPlugin remote call failed"); 339 } 340 341 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) { 363 mMetrics.mEventCounter.Increment(hEventType); 364 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; 389 case EventType::SESSION_RECLAIMED: 390 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed; 391 break; 392 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); 454 mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type); 455 } 456 obj.writeInt32(hasNewUsableKey); 457 458 Mutex::Autolock lock(mNotifyLock); 459 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj); 460 } 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 } 467 } 468 469 return Void(); 470} 471 472bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { 473 Mutex::Autolock autoLock(mLock); 474 475 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 } 484 } 485 } 486 return false; 487} 488 489status_t DrmHal::createPlugin(const uint8_t uuid[16], 490 const String8& appPackageName) { 491 Mutex::Autolock autoLock(mLock); 492 493 for (size_t i = 0; i < mFactories.size(); i++) { 494 if (mFactories[i]->isCryptoSchemeSupported(uuid)) { 495 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName); 496 if (mPlugin != NULL) { 497 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin); 498 } 499 } 500 } 501 502 if (mPlugin == NULL) { 503 mInitCheck = ERROR_UNSUPPORTED; 504 } else { 505 if (!mPlugin->setListener(this).isOk()) { 506 mInitCheck = DEAD_OBJECT; 507 } else { 508 mInitCheck = OK; 509 } 510 } 511 512 return mInitCheck; 513} 514 515status_t DrmHal::destroyPlugin() { 516 Mutex::Autolock autoLock(mLock); 517 INIT_CHECK(); 518 519 closeOpenSessions(); 520 reportPluginMetrics(); 521 reportFrameworkMetrics(); 522 setListener(NULL); 523 mInitCheck = NO_INIT; 524 525 if (mPlugin != NULL) { 526 if (!mPlugin->setListener(NULL).isOk()) { 527 mInitCheck = DEAD_OBJECT; 528 } 529 } 530 mPlugin.clear(); 531 mPluginV1_1.clear(); 532 return OK; 533} 534 535status_t DrmHal::openSession(DrmPlugin::SecurityLevel level, 536 Vector<uint8_t> &sessionId) { 537 Mutex::Autolock autoLock(mLock); 538 INIT_CHECK(); 539 540 SecurityLevel hSecurityLevel; 541 bool setSecurityLevel = true; 542 543 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; 567 bool retry = true; 568 do { 569 hidl_vec<uint8_t> hSessionId; 570 571 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); 579 } 580 ); 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 } 591 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); 611 mOpenSessions.push(sessionId); 612 mMetrics.SetSessionStart(sessionId); 613 } 614 615 mMetrics.mOpenSessionCounter.Increment(err); 616 return err; 617} 618 619status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) { 620 Mutex::Autolock autoLock(mLock); 621 INIT_CHECK(); 622 623 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 } 632 } 633 } 634 status_t response = toStatusT(status); 635 mMetrics.SetSessionEnd(sessionId); 636 mMetrics.mCloseSessionCounter.Increment(response); 637 reportPluginMetrics(); 638 return response; 639 } 640 mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT); 641 return DEAD_OBJECT; 642} 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); 650 INIT_CHECK(); 651 EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs); 652 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 { 663 keyRequestTimer.SetAttribute(BAD_VALUE); 664 return BAD_VALUE; 665 } 666 667 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters); 668 669 status_t err = UNKNOWN_ERROR; 670 671 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 710 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId), 711 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, 712 [&](Status status, const hidl_vec<uint8_t>& hRequest, 713 drm::V1_0::KeyRequestType hKeyRequestType, 714 const hidl_string& hDefaultUrl) { 715 716 if (status == Status::OK) { 717 request = toVector(hRequest); 718 defaultUrl = toString8(hDefaultUrl); 719 720 switch (hKeyRequestType) { 721 case drm::V1_0::KeyRequestType::INITIAL: 722 *keyRequestType = DrmPlugin::kKeyRequestType_Initial; 723 break; 724 case drm::V1_0::KeyRequestType::RENEWAL: 725 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal; 726 break; 727 case drm::V1_0::KeyRequestType::RELEASE: 728 *keyRequestType = DrmPlugin::kKeyRequestType_Release; 729 break; 730 default: 731 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown; 732 break; 733 } 734 err = toStatusT(status); 735 } 736 }); 737 738 err = hResult.isOk() ? err : DEAD_OBJECT; 739 keyRequestTimer.SetAttribute(err); 740 return err; 741} 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); 746 EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs); 747 748 INIT_CHECK(); 749 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 ); 763 err = hResult.isOk() ? err : DEAD_OBJECT; 764 keyResponseTimer.SetAttribute(err); 765 return err; 766} 767 768status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) { 769 Mutex::Autolock autoLock(mLock); 770 INIT_CHECK(); 771 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); 778 INIT_CHECK(); 779 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); 789 INIT_CHECK(); 790 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); 813 INIT_CHECK(); 814 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 829 err = hResult.isOk() ? err : DEAD_OBJECT; 830 mMetrics.mGetProvisionRequestCounter.Increment(err); 831 return err; 832} 833 834status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response, 835 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) { 836 Mutex::Autolock autoLock(mLock); 837 INIT_CHECK(); 838 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 852 err = hResult.isOk() ? err : DEAD_OBJECT; 853 mMetrics.mProvideProvisionResponseCounter.Increment(err); 854 return err; 855} 856 857status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) { 858 Mutex::Autolock autoLock(mLock); 859 INIT_CHECK(); 860 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 876status_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 902status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) { 903 Mutex::Autolock autoLock(mLock); 904 INIT_CHECK(); 905 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); 922 INIT_CHECK(); 923 924 if (mPluginV1_1 != NULL) { 925 SecureStopRelease secureStopRelease; 926 secureStopRelease.opaqueData = toHidlVec(ssRelease); 927 return toStatusT(mPluginV1_1->releaseSecureStops(secureStopRelease)); 928 } 929 930 return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease))); 931} 932 933status_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() { 948 Mutex::Autolock autoLock(mLock); 949 INIT_CHECK(); 950 951 if (mPluginV1_1 != NULL) { 952 return toStatusT(mPluginV1_1->removeAllSecureStops()); 953 } 954 return toStatusT(mPlugin->releaseAllSecureStops()); 955} 956 957status_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 1044status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const { 1045 Mutex::Autolock autoLock(mLock); 1046 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. 1052 INIT_CHECK(); 1053 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); 1070 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. 1076 INIT_CHECK(); 1077 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 1089 err = hResult.isOk() ? err : DEAD_OBJECT; 1090 if (name == kPropertyDeviceUniqueId) { 1091 mMetrics.mGetDeviceUniqueIdCounter.Increment(err); 1092 } 1093 return err; 1094} 1095 1096status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const { 1097 Mutex::Autolock autoLock(mLock); 1098 INIT_CHECK(); 1099 1100 Status status = mPlugin->setPropertyString(toHidlString(name), 1101 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); 1108 INIT_CHECK(); 1109 1110 Status status = mPlugin->setPropertyByteArray(toHidlString(name), 1111 toHidlVec(value)); 1112 return toStatusT(status); 1113} 1114 1115status_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; 1155 } 1156 1157 return OK; 1158} 1159 1160status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId, 1161 String8 const &algorithm) { 1162 Mutex::Autolock autoLock(mLock); 1163 INIT_CHECK(); 1164 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); 1175 INIT_CHECK(); 1176 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, 1185 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input, 1186 Vector<uint8_t> const &iv, Vector<uint8_t> &output) { 1187 Mutex::Autolock autoLock(mLock); 1188 INIT_CHECK(); 1189 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, 1208 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input, 1209 Vector<uint8_t> const &iv, Vector<uint8_t> &output) { 1210 Mutex::Autolock autoLock(mLock); 1211 INIT_CHECK(); 1212 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, 1231 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message, 1232 Vector<uint8_t> &signature) { 1233 Mutex::Autolock autoLock(mLock); 1234 INIT_CHECK(); 1235 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, 1254 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message, 1255 Vector<uint8_t> const &signature, bool &match) { 1256 Mutex::Autolock autoLock(mLock); 1257 INIT_CHECK(); 1258 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, 1279 String8 const &algorithm, Vector<uint8_t> const &message, 1280 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) { 1281 Mutex::Autolock autoLock(mLock); 1282 INIT_CHECK(); 1283 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{ 1307 Mutex::Autolock autoLock(mLock); 1308 closeOpenSessions(); 1309 setListener(NULL); 1310 mInitCheck = NO_INIT; 1311 1312 if (mPlugin != NULL) { 1313 if (!mPlugin->setListener(NULL).isOk()) { 1314 mInitCheck = DEAD_OBJECT; 1315 } 1316 } 1317 mPlugin.clear(); 1318} 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 1330void 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 } 1349 1350 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 1365{ 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 1380} // namespace android 1381