| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //#define LOG_NDEBUG 0 |
| #define LOG_TAG "DrmHalAidl" |
| |
| #include <array> |
| #include <algorithm> |
| #include <map> |
| #include <android/binder_auto_utils.h> |
| #include <android/binder_manager.h> |
| #include <media/PluginMetricsReporting.h> |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <media/stagefright/foundation/AString.h> |
| #include <media/stagefright/foundation/base64.h> |
| #include <media/stagefright/foundation/hexdump.h> |
| #include <mediadrm/DrmHalAidl.h> |
| #include <mediadrm/DrmSessionManager.h> |
| #include <mediadrm/DrmStatus.h> |
| #include <mediadrm/DrmUtils.h> |
| |
| using ::aidl::android::hardware::drm::CryptoSchemes; |
| using ::aidl::android::hardware::drm::DrmMetricNamedValue; |
| using ::aidl::android::hardware::drm::DrmMetricValue; |
| using ::aidl::android::hardware::drm::HdcpLevel; |
| using ::aidl::android::hardware::drm::HdcpLevels; |
| using ::aidl::android::hardware::drm::KeyRequest; |
| using ::aidl::android::hardware::drm::KeyRequestType; |
| using ::aidl::android::hardware::drm::KeySetId; |
| using ::aidl::android::hardware::drm::KeyStatus; |
| using ::aidl::android::hardware::drm::KeyStatusType; |
| using ::aidl::android::hardware::drm::KeyType; |
| using ::aidl::android::hardware::drm::KeyValue; |
| using ::aidl::android::hardware::drm::NumberOfSessions; |
| using ::aidl::android::hardware::drm::OfflineLicenseState; |
| using ::aidl::android::hardware::drm::OpaqueData; |
| using ::aidl::android::hardware::drm::ProvideProvisionResponseResult; |
| using ::aidl::android::hardware::drm::ProvisionRequest; |
| using ::aidl::android::hardware::drm::SecureStop; |
| using ::aidl::android::hardware::drm::SecureStopId; |
| using ::aidl::android::hardware::drm::SecurityLevel; |
| using ::aidl::android::hardware::drm::Status; |
| using ::aidl::android::hardware::drm::SupportedContentType; |
| using ::aidl::android::hardware::drm::Uuid; |
| using ::android::DrmUtils::statusAidlToDrmStatus; |
| using DrmMetricGroupAidl = ::aidl::android::hardware::drm::DrmMetricGroup; |
| using DrmMetricGroupHidl = ::android::hardware::drm::V1_1::DrmMetricGroup; |
| using DrmMetricAidl = ::aidl::android::hardware::drm::DrmMetric; |
| using DrmMetricHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Metric; |
| using ValueHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Value; |
| using AttributeHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Attribute; |
| using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin; |
| using EventTypeAidl = ::aidl::android::hardware::drm::EventType; |
| using ::android::hardware::hidl_vec; |
| |
| namespace { |
| |
| constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId"; |
| constexpr char kEqualsSign[] = "="; |
| |
| template <typename T> |
| std::string toBase64StringNoPad(const T* data, size_t size) { |
| // Note that the base 64 conversion only works with arrays of single-byte |
| // values. If the source is empty or is not an array of single-byte values, |
| // return empty string. |
| if (size == 0 || sizeof(data[0]) != 1) { |
| return ""; |
| } |
| |
| android::AString outputString; |
| encodeBase64(data, size, &outputString); |
| // Remove trailing equals padding if it exists. |
| while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) { |
| outputString.erase(outputString.size() - 1, 1); |
| } |
| |
| return std::string(outputString.c_str(), outputString.size()); |
| } |
| |
| } // anonymous namespace |
| |
| namespace android { |
| |
| #define INIT_CHECK() \ |
| { \ |
| if (mInitCheck != OK) return mInitCheck; \ |
| } |
| |
| template <typename Byte = uint8_t> |
| static std::vector<Byte> toStdVec(const Vector<uint8_t>& vector) { |
| auto v = reinterpret_cast<const Byte*>(vector.array()); |
| std::vector<Byte> vec(v, v + vector.size()); |
| return vec; |
| } |
| |
| static const Vector<uint8_t> toVector(const std::vector<uint8_t>& vec) { |
| Vector<uint8_t> vector; |
| vector.appendArray(vec.data(), vec.size()); |
| return *const_cast<const Vector<uint8_t>*>(&vector); |
| } |
| |
| static String8 toString8(const std::string& string) { |
| return String8(string.c_str()); |
| } |
| |
| static std::string toStdString(const String8& string8) { |
| return std::string(string8.c_str()); |
| } |
| |
| static std::vector<KeyValue> toKeyValueVector(const KeyedVector<String8, String8>& keyedVector) { |
| std::vector<KeyValue> stdKeyedVector; |
| for (size_t i = 0; i < keyedVector.size(); i++) { |
| KeyValue keyValue; |
| keyValue.key = toStdString(keyedVector.keyAt(i)); |
| keyValue.value = toStdString(keyedVector.valueAt(i)); |
| stdKeyedVector.push_back(keyValue); |
| } |
| return stdKeyedVector; |
| } |
| |
| static KeyedVector<String8, String8> toKeyedVector(const std::vector<KeyValue>& keyValueVec) { |
| KeyedVector<String8, String8> keyedVector; |
| for (size_t i = 0; i < keyValueVec.size(); i++) { |
| keyedVector.add(toString8(keyValueVec[i].key), toString8(keyValueVec[i].value)); |
| } |
| return keyedVector; |
| } |
| |
| static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) { |
| switch (keyRequestType) { |
| case KeyRequestType::INITIAL: |
| return DrmPlugin::kKeyRequestType_Initial; |
| break; |
| case KeyRequestType::RENEWAL: |
| return DrmPlugin::kKeyRequestType_Renewal; |
| break; |
| case KeyRequestType::RELEASE: |
| return DrmPlugin::kKeyRequestType_Release; |
| break; |
| case KeyRequestType::NONE: |
| return DrmPlugin::kKeyRequestType_None; |
| break; |
| case KeyRequestType::UPDATE: |
| return DrmPlugin::kKeyRequestType_Update; |
| break; |
| default: |
| return DrmPlugin::kKeyRequestType_Unknown; |
| break; |
| } |
| } |
| |
| static List<Vector<uint8_t>> toSecureStops(const std::vector<SecureStop>& aSecureStops) { |
| List<Vector<uint8_t>> secureStops; |
| for (size_t i = 0; i < aSecureStops.size(); i++) { |
| secureStops.push_back(toVector(aSecureStops[i].opaqueData)); |
| } |
| return secureStops; |
| } |
| |
| static List<Vector<uint8_t>> toSecureStopIds(const std::vector<SecureStopId>& aSecureStopIds) { |
| List<Vector<uint8_t>> secureStopIds; |
| for (size_t i = 0; i < aSecureStopIds.size(); i++) { |
| secureStopIds.push_back(toVector(aSecureStopIds[i].secureStopId)); |
| } |
| return secureStopIds; |
| } |
| |
| static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) { |
| switch (level) { |
| case HdcpLevel::HDCP_NONE: |
| return DrmPlugin::kHdcpNone; |
| case HdcpLevel::HDCP_V1: |
| return DrmPlugin::kHdcpV1; |
| case HdcpLevel::HDCP_V2: |
| return DrmPlugin::kHdcpV2; |
| case HdcpLevel::HDCP_V2_1: |
| return DrmPlugin::kHdcpV2_1; |
| case HdcpLevel::HDCP_V2_2: |
| return DrmPlugin::kHdcpV2_2; |
| case HdcpLevel::HDCP_V2_3: |
| return DrmPlugin::kHdcpV2_3; |
| case HdcpLevel::HDCP_NO_OUTPUT: |
| return DrmPlugin::kHdcpNoOutput; |
| default: |
| return DrmPlugin::kHdcpLevelUnknown; |
| } |
| } |
| |
| static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) { |
| switch (level) { |
| case SecurityLevel::SW_SECURE_CRYPTO: |
| return DrmPlugin::kSecurityLevelSwSecureCrypto; |
| case SecurityLevel::SW_SECURE_DECODE: |
| return DrmPlugin::kSecurityLevelSwSecureDecode; |
| case SecurityLevel::HW_SECURE_CRYPTO: |
| return DrmPlugin::kSecurityLevelHwSecureCrypto; |
| case SecurityLevel::HW_SECURE_DECODE: |
| return DrmPlugin::kSecurityLevelHwSecureDecode; |
| case SecurityLevel::HW_SECURE_ALL: |
| return DrmPlugin::kSecurityLevelHwSecureAll; |
| case SecurityLevel::DEFAULT: |
| return DrmPlugin::kSecurityLevelMax; |
| default: |
| return DrmPlugin::kSecurityLevelUnknown; |
| } |
| } |
| |
| static SecurityLevel toAidlSecurityLevel(DrmPlugin::SecurityLevel level) { |
| switch (level) { |
| case DrmPlugin::kSecurityLevelSwSecureCrypto: |
| return SecurityLevel::SW_SECURE_CRYPTO; |
| case DrmPlugin::kSecurityLevelSwSecureDecode: |
| return SecurityLevel::SW_SECURE_DECODE; |
| case DrmPlugin::kSecurityLevelHwSecureCrypto: |
| return SecurityLevel::HW_SECURE_CRYPTO; |
| case DrmPlugin::kSecurityLevelHwSecureDecode: |
| return SecurityLevel::HW_SECURE_DECODE; |
| case DrmPlugin::kSecurityLevelHwSecureAll: |
| return SecurityLevel::HW_SECURE_ALL; |
| case DrmPlugin::kSecurityLevelMax: |
| return SecurityLevel::DEFAULT; |
| default: |
| return SecurityLevel::UNKNOWN; |
| } |
| } |
| |
| static List<Vector<uint8_t>> toKeySetIds(const std::vector<KeySetId>& hKeySetIds) { |
| List<Vector<uint8_t>> keySetIds; |
| for (size_t i = 0; i < hKeySetIds.size(); i++) { |
| keySetIds.push_back(toVector(hKeySetIds[i].keySetId)); |
| } |
| return keySetIds; |
| } |
| |
| static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t>& vector) { |
| hidl_vec<uint8_t> vec; |
| vec.setToExternal(const_cast<uint8_t*>(vector.array()), vector.size()); |
| return vec; |
| } |
| |
| static DrmPlugin::OfflineLicenseState toOfflineLicenseState(OfflineLicenseState licenseState) { |
| switch (licenseState) { |
| case OfflineLicenseState::USABLE: |
| return DrmPlugin::kOfflineLicenseStateUsable; |
| case OfflineLicenseState::INACTIVE: |
| return DrmPlugin::kOfflineLicenseStateReleased; |
| default: |
| return DrmPlugin::kOfflineLicenseStateUnknown; |
| } |
| } |
| |
| Mutex DrmHalAidl::mLock; |
| |
| static hidl_vec<DrmMetricGroupHidl> toDrmMetricGroupHidl(std::vector<DrmMetricGroupAidl> result) { |
| std::vector<DrmMetricGroupHidl> resultHidl; |
| for (auto r : result) { |
| DrmMetricGroupHidl re; |
| std::vector<DrmMetricHidl> tmpMetric; |
| for (auto m : r.metrics) { |
| DrmMetricHidl me; |
| me.name = m.name; |
| std::vector<AttributeHidl> aTmp; |
| for (auto attr : m.attributes) { |
| AttributeHidl attrHidl; |
| attrHidl.name = attr.name; |
| |
| switch (attr.value.getTag()) { |
| case DrmMetricValue::Tag::int64Value: |
| attrHidl.type = DrmMetricGroupHidl::ValueType::INT64_TYPE; |
| attrHidl.int64Value = attr.value.get<DrmMetricValue::Tag::int64Value>(); |
| break; |
| case DrmMetricValue::Tag::doubleValue: |
| attrHidl.type = DrmMetricGroupHidl::ValueType::DOUBLE_TYPE; |
| attrHidl.doubleValue = attr.value.get<DrmMetricValue::Tag::doubleValue>(); |
| break; |
| case DrmMetricValue::Tag::stringValue: |
| attrHidl.type = DrmMetricGroupHidl::ValueType::STRING_TYPE; |
| attrHidl.stringValue = attr.value.get<DrmMetricValue::Tag::stringValue>(); |
| break; |
| default: |
| break; |
| } |
| |
| aTmp.push_back(attrHidl); |
| } |
| |
| me.attributes = aTmp; |
| |
| std::vector<ValueHidl> vTmp; |
| for (auto value : m.values) { |
| ValueHidl valueHidl; |
| valueHidl.componentName = value.name; |
| switch (value.value.getTag()) { |
| case DrmMetricValue::Tag::int64Value: |
| valueHidl.type = DrmMetricGroupHidl::ValueType::INT64_TYPE; |
| valueHidl.int64Value = value.value.get<DrmMetricValue::Tag::int64Value>(); |
| break; |
| case DrmMetricValue::Tag::doubleValue: |
| valueHidl.type = DrmMetricGroupHidl::ValueType::DOUBLE_TYPE; |
| valueHidl.doubleValue = value.value.get<DrmMetricValue::Tag::doubleValue>(); |
| break; |
| case DrmMetricValue::Tag::stringValue: |
| valueHidl.type = DrmMetricGroupHidl::ValueType::STRING_TYPE; |
| valueHidl.stringValue = value.value.get<DrmMetricValue::Tag::stringValue>(); |
| break; |
| default: |
| break; |
| } |
| |
| vTmp.push_back(valueHidl); |
| } |
| |
| me.values = vTmp; |
| tmpMetric.push_back(me); |
| } |
| |
| re.metrics = tmpMetric; |
| resultHidl.push_back(re); |
| } |
| |
| return resultHidl; |
| } |
| |
| // DrmSessionClient Definition |
| |
| struct DrmHalAidl::DrmSessionClient : public aidl::android::media::BnResourceManagerClient { |
| explicit DrmSessionClient(DrmHalAidl* drm, const Vector<uint8_t>& sessionId) |
| : mSessionId(sessionId), mDrm(drm) {} |
| |
| ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override; |
| ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override; |
| |
| const Vector<uint8_t> mSessionId; |
| |
| virtual ~DrmSessionClient(); |
| |
| private: |
| wp<DrmHalAidl> mDrm; |
| |
| DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient); |
| }; |
| |
| ::ndk::ScopedAStatus DrmHalAidl::DrmSessionClient::reclaimResource(bool* _aidl_return) { |
| auto sessionId = mSessionId; |
| sp<DrmHalAidl> drm = mDrm.promote(); |
| if (drm == NULL) { |
| *_aidl_return = true; |
| return ::ndk::ScopedAStatus::ok(); |
| } |
| status_t err = drm->closeSession(sessionId); |
| if (err != OK) { |
| *_aidl_return = false; |
| return ::ndk::ScopedAStatus::ok(); |
| } |
| drm->onEvent(EventTypeAidl::SESSION_RECLAIMED, toHidlVec(sessionId), hidl_vec<uint8_t>()); |
| *_aidl_return = true; |
| return ::ndk::ScopedAStatus::ok(); |
| } |
| |
| ::ndk::ScopedAStatus DrmHalAidl::DrmSessionClient::getName(::std::string* _aidl_return) { |
| String8 name; |
| sp<DrmHalAidl> drm = mDrm.promote(); |
| if (drm == NULL) { |
| name.append("<deleted>"); |
| } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.empty()) { |
| name.append("<Get vendor failed or is empty>"); |
| } |
| name.append("["); |
| for (size_t i = 0; i < mSessionId.size(); ++i) { |
| name.appendFormat("%02x", mSessionId[i]); |
| } |
| name.append("]"); |
| *_aidl_return = name; |
| return ::ndk::ScopedAStatus::ok(); |
| } |
| |
| DrmHalAidl::DrmSessionClient::~DrmSessionClient() { |
| DrmSessionManager::Instance()->removeSession(mSessionId); |
| } |
| |
| // DrmHalAidl methods |
| DrmHalAidl::DrmHalAidl() |
| : mMetrics(std::make_shared<MediaDrmMetrics>()), |
| mListener(::ndk::SharedRefBase::make<DrmHalListener>(mMetrics)), |
| mFactories(DrmUtils::makeDrmFactoriesAidl()), |
| mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {} |
| |
| DrmStatus DrmHalAidl::initCheck() const { |
| return DrmStatus(mInitCheck); |
| } |
| |
| DrmHalAidl::~DrmHalAidl() {} |
| |
| DrmStatus DrmHalAidl::setListener(const sp<IDrmClient>& listener) { |
| mListener->setListener(listener); |
| return DrmStatus(NO_ERROR); |
| } |
| |
| DrmStatus DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType, |
| DrmPlugin::SecurityLevel level, bool* isSupported) { |
| Mutex::Autolock autoLock(mLock); |
| *isSupported = false; |
| Uuid uuidAidl = DrmUtils::toAidlUuid(uuid); |
| SecurityLevel levelAidl = toAidlSecurityLevel(level); |
| std::string mimeTypeStr = mimeType.c_str(); |
| |
| for (ssize_t i = mFactories.size() - 1; i >= 0; i--) { |
| CryptoSchemes schemes{}; |
| auto err = mFactories[i]->getSupportedCryptoSchemes(&schemes); |
| if (!err.isOk() || !std::count(schemes.uuids.begin(), schemes.uuids.end(), uuidAidl)) { |
| continue; |
| } |
| |
| ALOGV("supported schemes: %s; query: level %d mime %s", |
| schemes.toString().c_str(), levelAidl, mimeType.c_str()); |
| std::map<std::string, SupportedContentType> contentTypes; |
| for (auto ct : schemes.mimeTypes) { |
| contentTypes[ct.mime] = ct; |
| } |
| |
| // handle default value cases |
| if (levelAidl == SecurityLevel::DEFAULT || levelAidl == SecurityLevel::UNKNOWN) { |
| if (mimeType == "") { |
| // isCryptoSchemeSupported(uuid) |
| *isSupported = true; |
| } else { |
| // isCryptoSchemeSupported(uuid, mimeType) |
| *isSupported = contentTypes.count(mimeTypeStr); |
| } |
| return DrmStatus(OK); |
| } else if (mimeType == "") { |
| return DrmStatus(BAD_VALUE); |
| } |
| |
| auto ct = contentTypes[mimeTypeStr]; |
| if (levelAidl > ct.maxLevel || levelAidl < ct.minLevel) { |
| continue; |
| } |
| |
| *isSupported = true; |
| break; |
| } |
| |
| return DrmStatus(OK); |
| } |
| |
| DrmStatus DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) { |
| Mutex::Autolock autoLock(mLock); |
| if (mInitCheck == ERROR_UNSUPPORTED) return mInitCheck; |
| Uuid uuidAidl = DrmUtils::toAidlUuid(uuid); |
| std::string appPackageNameAidl = toStdString(appPackageName); |
| std::shared_ptr<IDrmPluginAidl> pluginAidl; |
| mMetrics->SetAppPackageName(appPackageName); |
| mMetrics->SetAppUid(AIBinder_getCallingUid()); |
| for (ssize_t i = mFactories.size() - 1; i >= 0; i--) { |
| ::ndk::ScopedAStatus status = |
| mFactories[i]->createDrmPlugin(uuidAidl, appPackageNameAidl, &pluginAidl); |
| if (status.isOk()) { |
| if (pluginAidl != NULL) { |
| mPlugin = pluginAidl; |
| break; |
| } |
| } else { |
| DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", |
| status.getServiceSpecificError()); |
| } |
| } |
| |
| if (mPlugin == NULL) { |
| DrmUtils::LOG2BE(uuid, "No supported hal instance found"); |
| mInitCheck = ERROR_UNSUPPORTED; |
| } else { |
| mInitCheck = OK; |
| // Stored pointer mListener upcast to base BnDrmPluginListener |
| ::ndk::ScopedAStatus status = mPlugin |
| ->setListener(std::static_pointer_cast<BnDrmPluginListener>(mListener)); |
| if (!status.isOk()) { |
| mInitCheck = DEAD_OBJECT; |
| ALOGE("setListener failed: ex %d svc err %d", |
| status.getExceptionCode(), |
| status.getServiceSpecificError()); |
| } |
| |
| if (mInitCheck != OK) { |
| mPlugin.reset(); |
| } |
| } |
| |
| return DrmStatus(mInitCheck); |
| } |
| |
| DrmStatus DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| SecurityLevel aSecurityLevel = toAidlSecurityLevel(level); |
| |
| if (aSecurityLevel == SecurityLevel::UNKNOWN) { |
| return ERROR_DRM_CANNOT_HANDLE; |
| } |
| |
| DrmStatus err = UNKNOWN_ERROR; |
| bool retry = true; |
| do { |
| std::vector<uint8_t> aSessionId; |
| |
| ::ndk::ScopedAStatus status = mPlugin->openSession(aSecurityLevel, &aSessionId); |
| if (status.isOk()) sessionId = toVector(aSessionId); |
| err = statusAidlToDrmStatus(status); |
| |
| if (err == ERROR_DRM_RESOURCE_BUSY && retry) { |
| mLock.unlock(); |
| // reclaimSession may call back to closeSession, since mLock is |
| // shared between Drm instances, we should unlock here to avoid |
| // deadlock. |
| retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid()); |
| mLock.lock(); |
| } else { |
| retry = false; |
| } |
| } while (retry); |
| |
| if (err == OK) { |
| std::shared_ptr<DrmSessionClient> client = |
| ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId); |
| DrmSessionManager::Instance()->addSession( |
| AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client), |
| sessionId); |
| mOpenSessions.push_back(client); |
| mMetrics->SetSessionStart(sessionId); |
| } |
| |
| mMetrics->mOpenSessionCounter.Increment(err); |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId); |
| ::ndk::ScopedAStatus status = mPlugin->closeSession(sessionIdAidl); |
| DrmStatus response = statusAidlToDrmStatus(status); |
| if (status.isOk()) { |
| DrmSessionManager::Instance()->removeSession(sessionId); |
| for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) { |
| if (isEqualSessionId((*i)->mSessionId, sessionId)) { |
| mOpenSessions.erase(i); |
| break; |
| } |
| } |
| |
| mMetrics->SetSessionEnd(sessionId); |
| } |
| |
| mMetrics->mCloseSessionCounter.Increment(response); |
| return response; |
| } |
| |
| DrmStatus DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId, |
| Vector<uint8_t> const& initData, String8 const& mimeType, |
| DrmPlugin::KeyType keyType, |
| KeyedVector<String8, String8> const& optionalParameters, |
| Vector<uint8_t>& request, String8& defaultUrl, |
| DrmPlugin::KeyRequestType* keyRequestType) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| EventTimer<status_t> keyRequestTimer(&mMetrics->mGetKeyRequestTimeUs); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| KeyType aKeyType; |
| if (keyType == DrmPlugin::kKeyType_Streaming) { |
| aKeyType = KeyType::STREAMING; |
| } else if (keyType == DrmPlugin::kKeyType_Offline) { |
| aKeyType = KeyType::OFFLINE; |
| } else if (keyType == DrmPlugin::kKeyType_Release) { |
| aKeyType = KeyType::RELEASE; |
| } else { |
| keyRequestTimer.SetAttribute(BAD_VALUE); |
| return BAD_VALUE; |
| } |
| |
| DrmStatus err = UNKNOWN_ERROR; |
| |
| std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId); |
| std::vector<uint8_t> initDataAidl = toStdVec(initData); |
| KeyRequest keyRequest; |
| |
| ::ndk::ScopedAStatus status = |
| mPlugin->getKeyRequest(sessionIdAidl, initDataAidl, toStdString(mimeType), aKeyType, |
| toKeyValueVector(optionalParameters), &keyRequest); |
| if (status.isOk()) { |
| request = toVector(keyRequest.request); |
| defaultUrl = toString8(keyRequest.defaultUrl); |
| *keyRequestType = toKeyRequestType(keyRequest.requestType); |
| } |
| |
| err = statusAidlToDrmStatus(status); |
| keyRequestTimer.SetAttribute(err); |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId, |
| Vector<uint8_t> const& response, |
| Vector<uint8_t>& keySetId) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| EventTimer<status_t> keyResponseTimer(&mMetrics->mProvideKeyResponseTimeUs); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| DrmStatus err = UNKNOWN_ERROR; |
| |
| std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId); |
| std::vector<uint8_t> responseAidl = toStdVec(response); |
| KeySetId keySetIdsAidl; |
| ::ndk::ScopedAStatus status = |
| mPlugin->provideKeyResponse(sessionIdAidl, responseAidl, &keySetIdsAidl); |
| |
| if (status.isOk()) keySetId = toVector(keySetIdsAidl.keySetId); |
| err = statusAidlToDrmStatus(status); |
| keyResponseTimer.SetAttribute(err); |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| ::ndk::ScopedAStatus status = mPlugin->removeKeys(toStdVec(keySetId)); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId, |
| Vector<uint8_t> const& keySetId) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| KeySetId keySetIdsAidl; |
| keySetIdsAidl.keySetId = toStdVec(keySetId); |
| ::ndk::ScopedAStatus status = mPlugin->restoreKeys(toStdVec(sessionId), keySetIdsAidl); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId, |
| KeyedVector<String8, String8>& infoMap) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| std::vector<KeyValue> infoMapAidl; |
| ::ndk::ScopedAStatus status = mPlugin->queryKeyStatus(toStdVec(sessionId), &infoMapAidl); |
| |
| infoMap = toKeyedVector(infoMapAidl); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority, |
| Vector<uint8_t>& request, String8& defaultUrl) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmStatus err = UNKNOWN_ERROR; |
| |
| ProvisionRequest requestAidl; |
| ::ndk::ScopedAStatus status = mPlugin->getProvisionRequest( |
| toStdString(certType), toStdString(certAuthority), &requestAidl); |
| |
| request = toVector(requestAidl.request); |
| defaultUrl = toString8(requestAidl.defaultUrl); |
| |
| err = statusAidlToDrmStatus(status); |
| mMetrics->mGetProvisionRequestCounter.Increment(err); |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response, |
| Vector<uint8_t>& certificate, |
| Vector<uint8_t>& wrappedKey) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmStatus err = UNKNOWN_ERROR; |
| ProvideProvisionResponseResult result; |
| ::ndk::ScopedAStatus status = mPlugin->provideProvisionResponse(toStdVec(response), &result); |
| |
| certificate = toVector(result.certificate); |
| wrappedKey = toVector(result.wrappedKey); |
| err = statusAidlToDrmStatus(status); |
| mMetrics->mProvideProvisionResponseCounter.Increment(err); |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| std::vector<SecureStop> result; |
| ::ndk::ScopedAStatus status = mPlugin->getSecureStops(&result); |
| |
| secureStops = toSecureStops(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| std::vector<SecureStopId> result; |
| ::ndk::ScopedAStatus status = mPlugin->getSecureStopIds(&result); |
| |
| secureStopIds = toSecureStopIds(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| SecureStopId ssidAidl; |
| ssidAidl.secureStopId = toStdVec(ssid); |
| |
| SecureStop result; |
| ::ndk::ScopedAStatus status = mPlugin->getSecureStop(ssidAidl, &result); |
| |
| secureStop = toVector(result.opaqueData); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| OpaqueData ssId; |
| ssId.opaqueData = toStdVec(ssRelease); |
| ::ndk::ScopedAStatus status = mPlugin->releaseSecureStops(ssId); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) { |
| Mutex::Autolock autoLock(mLock); |
| |
| INIT_CHECK(); |
| |
| SecureStopId ssidAidl; |
| ssidAidl.secureStopId = toStdVec(ssid); |
| ::ndk::ScopedAStatus status = mPlugin->removeSecureStop(ssidAidl); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::removeAllSecureStops() { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| ::ndk::ScopedAStatus status = mPlugin->releaseAllSecureStops(); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected, |
| DrmPlugin::HdcpLevel* max) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| if (connected == NULL || max == NULL) { |
| return BAD_VALUE; |
| } |
| |
| *connected = DrmPlugin::kHdcpLevelUnknown; |
| *max = DrmPlugin::kHdcpLevelUnknown; |
| |
| HdcpLevels lvlsAidl; |
| ::ndk::ScopedAStatus status = mPlugin->getHdcpLevels(&lvlsAidl); |
| |
| *connected = toHdcpLevel(lvlsAidl.connectedLevel); |
| *max = toHdcpLevel(lvlsAidl.maxLevel); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| if (open == NULL || max == NULL) { |
| return BAD_VALUE; |
| } |
| |
| *open = 0; |
| *max = 0; |
| |
| NumberOfSessions result; |
| ::ndk::ScopedAStatus status = mPlugin->getNumberOfSessions(&result); |
| |
| *open = result.currentSessions; |
| *max = result.maxSessions; |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId, |
| DrmPlugin::SecurityLevel* level) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| if (level == NULL) { |
| return BAD_VALUE; |
| } |
| |
| *level = DrmPlugin::kSecurityLevelUnknown; |
| |
| SecurityLevel result; |
| ::ndk::ScopedAStatus status = mPlugin->getSecurityLevel(toStdVec(sessionId), &result); |
| |
| *level = toSecurityLevel(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| std::vector<KeySetId> result; |
| ::ndk::ScopedAStatus status = mPlugin->getOfflineLicenseKeySetIds(&result); |
| |
| keySetIds = toKeySetIds(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| KeySetId keySetIdAidl; |
| keySetIdAidl.keySetId = toStdVec(keySetId); |
| ::ndk::ScopedAStatus status = mPlugin->removeOfflineLicense(keySetIdAidl); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId, |
| DrmPlugin::OfflineLicenseState* licenseState) const { |
| Mutex::Autolock autoLock(mLock); |
| |
| INIT_CHECK(); |
| *licenseState = DrmPlugin::kOfflineLicenseStateUnknown; |
| |
| KeySetId keySetIdAidl; |
| keySetIdAidl.keySetId = toStdVec(keySetId); |
| |
| OfflineLicenseState result; |
| ::ndk::ScopedAStatus status = mPlugin->getOfflineLicenseState(keySetIdAidl, &result); |
| |
| *licenseState = toOfflineLicenseState(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getPropertyString(String8 const& name, String8& value) const { |
| Mutex::Autolock autoLock(mLock); |
| return DrmStatus(getPropertyStringInternal(name, value)); |
| } |
| |
| DrmStatus DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const { |
| // This function is internal to the class and should only be called while |
| // mLock is already held. |
| INIT_CHECK(); |
| |
| std::string result; |
| ::ndk::ScopedAStatus status = mPlugin->getPropertyString(toStdString(name), &result); |
| |
| value = toString8(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const { |
| Mutex::Autolock autoLock(mLock); |
| return DrmStatus(getPropertyByteArrayInternal(name, value)); |
| } |
| |
| DrmStatus DrmHalAidl::getPropertyByteArrayInternal(String8 const& name, |
| Vector<uint8_t>& value) const { |
| // This function is internal to the class and should only be called while |
| // mLock is already held. |
| INIT_CHECK(); |
| |
| DrmStatus err = UNKNOWN_ERROR; |
| |
| std::vector<uint8_t> result; |
| ::ndk::ScopedAStatus status = mPlugin->getPropertyByteArray(toStdString(name), &result); |
| |
| value = toVector(result); |
| err = statusAidlToDrmStatus(status); |
| if (name == kPropertyDeviceUniqueId) { |
| mMetrics->mGetDeviceUniqueIdCounter.Increment(err); |
| } |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| ::ndk::ScopedAStatus status = mPlugin->setPropertyString(toStdString(name), toStdString(value)); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::setPropertyByteArray(String8 const& name, |
| Vector<uint8_t> const& value) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| ::ndk::ScopedAStatus status = mPlugin->setPropertyByteArray(toStdString(name), toStdVec(value)); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) { |
| if (consumer == nullptr) { |
| return DrmStatus(UNEXPECTED_NULL); |
| } |
| consumer->consumeFrameworkMetrics(*mMetrics.get()); |
| |
| // Append vendor metrics if they are supported. |
| |
| String8 vendor; |
| String8 description; |
| if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.empty()) { |
| ALOGE("Get vendor failed or is empty"); |
| vendor = "NONE"; |
| } |
| if (getPropertyStringInternal(String8("description"), description) != OK || |
| description.empty()) { |
| ALOGE("Get description failed or is empty."); |
| description = "NONE"; |
| } |
| vendor += "."; |
| vendor += description; |
| |
| hidl_vec<DrmMetricGroupHidl> pluginMetrics; |
| DrmStatus err = UNKNOWN_ERROR; |
| |
| std::vector<DrmMetricGroupAidl> result; |
| ::ndk::ScopedAStatus status = mPlugin->getMetrics(&result); |
| |
| if (status.isOk()) { |
| pluginMetrics = toDrmMetricGroupHidl(result); |
| consumer->consumeHidlMetrics(vendor, pluginMetrics); |
| } |
| |
| err = statusAidlToDrmStatus(status); |
| |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId, |
| String8 const& algorithm) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| ::ndk::ScopedAStatus status = |
| mPlugin->setCipherAlgorithm(toStdVec(sessionId), toStdString(algorithm)); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| ::ndk::ScopedAStatus status = |
| mPlugin->setMacAlgorithm(toStdVec(sessionId), toStdString(algorithm)); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId, |
| Vector<uint8_t> const& input, Vector<uint8_t> const& iv, |
| Vector<uint8_t>& output) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| std::vector<uint8_t> result; |
| ::ndk::ScopedAStatus status = mPlugin->encrypt(toStdVec(sessionId), toStdVec(keyId), |
| toStdVec(input), toStdVec(iv), &result); |
| |
| output = toVector(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId, |
| Vector<uint8_t> const& input, Vector<uint8_t> const& iv, |
| Vector<uint8_t>& output) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| std::vector<uint8_t> result; |
| ::ndk::ScopedAStatus status = mPlugin->decrypt(toStdVec(sessionId), toStdVec(keyId), |
| toStdVec(input), toStdVec(iv), &result); |
| |
| output = toVector(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId, |
| Vector<uint8_t> const& message, Vector<uint8_t>& signature) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| std::vector<uint8_t> result; |
| ::ndk::ScopedAStatus status = |
| mPlugin->sign(toStdVec(sessionId), toStdVec(keyId), toStdVec(message), &result); |
| |
| signature = toVector(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId, |
| Vector<uint8_t> const& message, Vector<uint8_t> const& signature, |
| bool& match) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| ::ndk::ScopedAStatus status = mPlugin->verify(toStdVec(sessionId), toStdVec(keyId), |
| toStdVec(message), toStdVec(signature), &match); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm, |
| Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey, |
| Vector<uint8_t>& signature) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| DrmSessionManager::Instance()->useSession(sessionId); |
| |
| std::vector<uint8_t> result; |
| ::ndk::ScopedAStatus status = |
| mPlugin->signRSA(toStdVec(sessionId), toStdString(algorithm), toStdVec(message), |
| toStdVec(wrappedKey), &result); |
| |
| signature = toVector(result); |
| |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| std::string mimeAidl(mime); |
| ::ndk::ScopedAStatus status = |
| mPlugin->requiresSecureDecoder(mimeAidl, SecurityLevel::DEFAULT, required); |
| if (!status.isOk()) { |
| DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError()); |
| return DrmStatus(DEAD_OBJECT); |
| } |
| |
| return DrmStatus(OK); |
| } |
| |
| DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime, |
| DrmPlugin::SecurityLevel securityLevel, |
| bool* required) const { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| |
| auto aLevel = toAidlSecurityLevel(securityLevel); |
| std::string mimeAidl(mime); |
| ::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoder(mimeAidl, aLevel, required); |
| |
| DrmStatus err = statusAidlToDrmStatus(status); |
| if (!status.isOk()) { |
| DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError()); |
| } |
| |
| return err; |
| } |
| |
| DrmStatus DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) { |
| Mutex::Autolock autoLock(mLock); |
| INIT_CHECK(); |
| std::string playbackIdAidl(playbackId); |
| ::ndk::ScopedAStatus status = mPlugin->setPlaybackId(toStdVec(sessionId), playbackIdAidl); |
| return statusAidlToDrmStatus(status); |
| } |
| |
| DrmStatus DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const { |
| Mutex::Autolock autoLock(mLock); |
| return DrmStatus(DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs)); |
| } |
| |
| void DrmHalAidl::closeOpenSessions() { |
| Mutex::Autolock autoLock(mLock); |
| auto openSessions = mOpenSessions; |
| for (size_t i = 0; i < openSessions.size(); i++) { |
| mLock.unlock(); |
| closeSession(openSessions[i]->mSessionId); |
| mLock.lock(); |
| } |
| mOpenSessions.clear(); |
| } |
| |
| std::string DrmHalAidl::reportPluginMetrics() const { |
| Vector<uint8_t> metricsVector; |
| String8 vendor; |
| String8 description; |
| std::string metricsString; |
| if (getPropertyStringInternal(String8("vendor"), vendor) == OK && |
| getPropertyStringInternal(String8("description"), description) == OK && |
| getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) { |
| metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size()); |
| status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description, |
| mMetrics->GetAppUid()); |
| if (res != OK) { |
| ALOGE("Metrics were retrieved but could not be reported: %d", res); |
| } |
| } |
| return metricsString; |
| } |
| |
| std::string DrmHalAidl::reportFrameworkMetrics(const std::string& pluginMetrics) const { |
| mediametrics_handle_t item(mediametrics_create("mediadrm")); |
| mediametrics_setUid(item, mMetrics->GetAppUid()); |
| String8 vendor; |
| String8 description; |
| status_t result = getPropertyStringInternal(String8("vendor"), vendor); |
| if (result != OK) { |
| ALOGE("Failed to get vendor from drm plugin: %d", result); |
| } else { |
| mediametrics_setCString(item, "vendor", vendor.c_str()); |
| } |
| result = getPropertyStringInternal(String8("description"), description); |
| if (result != OK) { |
| ALOGE("Failed to get description from drm plugin: %d", result); |
| } else { |
| mediametrics_setCString(item, "description", description.c_str()); |
| } |
| |
| std::string serializedMetrics; |
| result = mMetrics->GetSerializedMetrics(&serializedMetrics); |
| if (result != OK) { |
| ALOGE("Failed to serialize framework metrics: %d", result); |
| } |
| std::string b64EncodedMetrics = |
| toBase64StringNoPad(serializedMetrics.data(), serializedMetrics.size()); |
| if (!b64EncodedMetrics.empty()) { |
| mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str()); |
| } |
| if (!pluginMetrics.empty()) { |
| mediametrics_setCString(item, "plugin_metrics", pluginMetrics.c_str()); |
| } |
| if (!mediametrics_selfRecord(item)) { |
| ALOGE("Failed to self record framework metrics"); |
| } |
| mediametrics_delete(item); |
| return serializedMetrics; |
| } |
| |
| DrmStatus DrmHalAidl::getSupportedSchemes(std::vector<uint8_t>& schemes) const { |
| Mutex::Autolock autoLock(mLock); |
| |
| if (mFactories.empty()) return UNKNOWN_ERROR; |
| for (ssize_t i = mFactories.size() - 1; i >= 0; i--) { |
| CryptoSchemes curSchemes{}; |
| auto err = mFactories[i]->getSupportedCryptoSchemes(&curSchemes); |
| if (!err.isOk()) { |
| continue; |
| } |
| |
| for (auto uuidObj : curSchemes.uuids) { |
| schemes.insert(schemes.end(), uuidObj.uuid.begin(), uuidObj.uuid.end()); |
| } |
| } |
| |
| return DrmStatus(OK); |
| } |
| |
| void DrmHalAidl::cleanup() { |
| closeOpenSessions(); |
| |
| Mutex::Autolock autoLock(mLock); |
| if (mInitCheck == OK) reportFrameworkMetrics(reportPluginMetrics()); |
| |
| setListener(NULL); |
| mInitCheck = NO_INIT; |
| if (mPlugin != NULL) { |
| if (!mPlugin->setListener(NULL).isOk()) { |
| mInitCheck = DEAD_OBJECT; |
| } |
| } |
| |
| mPlugin.reset(); |
| } |
| |
| DrmStatus DrmHalAidl::destroyPlugin() { |
| cleanup(); |
| return DrmStatus(OK); |
| } |
| |
| ::ndk::ScopedAStatus DrmHalAidl::onEvent(EventTypeAidl eventTypeAidl, |
| const std::vector<uint8_t>& sessionId, |
| const std::vector<uint8_t>& data) { |
| return mListener->onEvent(eventTypeAidl, sessionId, data); |
| } |
| |
| ::ndk::ScopedAStatus DrmHalAidl::onExpirationUpdate(const std::vector<uint8_t>& sessionId, |
| int64_t expiryTimeInMS) { |
| return mListener->onExpirationUpdate(sessionId, expiryTimeInMS); |
| } |
| |
| ::ndk::ScopedAStatus DrmHalAidl::onKeysChange(const std::vector<uint8_t>& sessionId, |
| const std::vector<KeyStatus>& keyStatusListAidl, |
| bool hasNewUsableKey) { |
| return mListener->onKeysChange(sessionId, keyStatusListAidl, hasNewUsableKey); |
| } |
| |
| ::ndk::ScopedAStatus DrmHalAidl::onSessionLostState(const std::vector<uint8_t>& sessionId) { |
| return mListener->onSessionLostState(sessionId); |
| } |
| |
| } // namespace android |