summaryrefslogtreecommitdiffstats
path: root/drm/libmediadrm/DrmHal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drm/libmediadrm/DrmHal.cpp')
-rw-r--r--drm/libmediadrm/DrmHal.cpp710
1 files changed, 529 insertions, 181 deletions
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index bc37557ed5..cf08610173 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -16,48 +16,81 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "DrmHal"
+#include <iomanip>
+
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
-#include <android/hardware/drm/1.0/IDrmFactory.h>
-#include <android/hardware/drm/1.0/IDrmPlugin.h>
#include <android/hardware/drm/1.0/types.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <hidl/ServiceManagement.h>
-#include <media/DrmHal.h>
-#include <media/DrmSessionClientInterface.h>
-#include <media/DrmSessionManager.h>
+#include <media/EventMetric.h>
#include <media/PluginMetricsReporting.h>
#include <media/drm/DrmAPI.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 <media/stagefright/MediaErrors.h>
-
-using ::android::hardware::drm::V1_0::EventType;
-using ::android::hardware::drm::V1_0::IDrmFactory;
-using ::android::hardware::drm::V1_0::IDrmPlugin;
-using ::android::hardware::drm::V1_0::KeyedVector;
-using ::android::hardware::drm::V1_0::KeyRequestType;
-using ::android::hardware::drm::V1_0::KeyStatus;
-using ::android::hardware::drm::V1_0::KeyStatusType;
-using ::android::hardware::drm::V1_0::KeyType;
-using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::SecureStop;
-using ::android::hardware::drm::V1_0::Status;
+#include <mediadrm/DrmHal.h>
+#include <mediadrm/DrmSessionClientInterface.h>
+#include <mediadrm/DrmSessionManager.h>
+
+using drm::V1_0::KeyedVector;
+using drm::V1_0::KeyStatusType;
+using drm::V1_0::KeyType;
+using drm::V1_0::KeyValue;
+using drm::V1_1::HdcpLevel;;
+using drm::V1_0::SecureStop;
+using drm::V1_1::SecureStopRelease;
+using drm::V1_0::SecureStopId;
+using drm::V1_1::SecurityLevel;
+using drm::V1_0::Status;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::os::PersistableBundle;
using ::android::sp;
+namespace {
+
+// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
+// in the MediaDrm API.
+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;}
+
static inline int getCallingPid() {
return IPCThreadState::self()->getCallingPid();
}
@@ -89,6 +122,42 @@ static hidl_string toHidlString(const String8& string) {
return hidl_string(string.string());
}
+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;
+ default:
+ return DrmPlugin::kSecurityLevelUnknown;
+ }
+}
+
+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_NO_OUTPUT:
+ return DrmPlugin::kHdcpNoOutput;
+ default:
+ return DrmPlugin::kHdcpLevelUnknown;
+ }
+}
+
static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
keyedVector) {
@@ -121,6 +190,15 @@ static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
return secureStops;
}
+static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
+ hSecureStopIds) {
+ List<Vector<uint8_t>> secureStopIds;
+ for (size_t i = 0; i < hSecureStopIds.size(); i++) {
+ secureStopIds.push_back(toVector(hSecureStopIds[i]));
+ }
+ return secureStopIds;
+}
+
static status_t toStatusT(Status status) {
switch (status) {
case Status::OK:
@@ -196,35 +274,63 @@ DrmHal::DrmHal()
}
void DrmHal::closeOpenSessions() {
- if (mPlugin != NULL) {
- for (size_t i = 0; i < mOpenSessions.size(); i++) {
- mPlugin->closeSession(toHidlVec(mOpenSessions[i]));
- DrmSessionManager::Instance()->removeSession(mOpenSessions[i]);
- }
+ Mutex::Autolock autoLock(mLock);
+ auto openSessions = mOpenSessions;
+ for (size_t i = 0; i < openSessions.size(); i++) {
+ mLock.unlock();
+ closeSession(openSessions[i]);
+ mLock.lock();
}
mOpenSessions.clear();
}
DrmHal::~DrmHal() {
- closeOpenSessions();
DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
}
+void DrmHal::cleanup() {
+ closeOpenSessions();
+
+ Mutex::Autolock autoLock(mLock);
+ reportPluginMetrics();
+ reportFrameworkMetrics();
+
+ setListener(NULL);
+ mInitCheck = NO_INIT;
+
+ if (mPlugin != NULL) {
+ if (!mPlugin->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ }
+ mPlugin.clear();
+ mPluginV1_1.clear();
+}
+
Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
Vector<sp<IDrmFactory>> factories;
auto manager = hardware::defaultServiceManager();
if (manager != NULL) {
- manager->listByInterface(IDrmFactory::descriptor,
+ manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
+ [&factories](const hidl_vec<hidl_string> &registered) {
+ for (const auto &instance : registered) {
+ auto factory = drm::V1_0::IDrmFactory::getService(instance);
+ if (factory != NULL) {
+ ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str());
+ factories.push_back(factory);
+ }
+ }
+ }
+ );
+ manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
[&factories](const hidl_vec<hidl_string> &registered) {
for (const auto &instance : registered) {
- auto factory = IDrmFactory::getService(instance);
+ auto factory = drm::V1_1::IDrmFactory::getService(instance);
if (factory != NULL) {
+ ALOGD("found drm@1.1 IDrmFactory %s", instance.c_str());
factories.push_back(factory);
- ALOGI("makeDrmFactories: factory instance %s is %s",
- instance.c_str(),
- factory->isRemote() ? "Remote" : "Not Remote");
}
}
}
@@ -235,7 +341,7 @@ Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
// must be in passthrough mode, load the default passthrough service
auto passthrough = IDrmFactory::getService();
if (passthrough != NULL) {
- ALOGI("makeDrmFactories: using default drm instance");
+ ALOGI("makeDrmFactories: using default passthrough drm instance");
factories.push_back(passthrough);
} else {
ALOGE("Failed to find any drm factories");
@@ -246,6 +352,8 @@ Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
const uint8_t uuid[16], const String8& appPackageName) {
+ mAppPackageName = appPackageName;
+ mMetrics.SetAppPackageName(appPackageName);
sp<IDrmPlugin> plugin;
Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
@@ -284,6 +392,7 @@ status_t DrmHal::setListener(const sp<IDrmClient>& listener)
Return<void> DrmHal::sendEvent(EventType hEventType,
const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
+ mMetrics.mEventCounter.Increment(hEventType);
mEventLock.lock();
sp<IDrmClient> listener = mListener;
@@ -374,12 +483,21 @@ Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
break;
}
obj.writeInt32(type);
+ mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
}
obj.writeInt32(hasNewUsableKey);
Mutex::Autolock lock(mNotifyLock);
listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
+ } else {
+ // There's no listener. But we still want to count the key change
+ // events.
+ size_t nKeys = keyStatusList.size();
+ for (size_t i = 0; i < nKeys; i++) {
+ mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
+ }
}
+
return Void();
}
@@ -407,6 +525,9 @@ status_t DrmHal::createPlugin(const uint8_t uuid[16],
for (size_t i = 0; i < mFactories.size(); i++) {
if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
+ if (mPlugin != NULL) {
+ mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
+ }
}
}
@@ -424,46 +545,66 @@ status_t DrmHal::createPlugin(const uint8_t uuid[16],
}
status_t DrmHal::destroyPlugin() {
- Mutex::Autolock autoLock(mLock);
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- closeOpenSessions();
- reportMetrics();
- setListener(NULL);
- mInitCheck = NO_INIT;
-
- if (mPlugin != NULL) {
- if (!mPlugin->setListener(NULL).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- }
- mPlugin.clear();
+ cleanup();
return OK;
}
-status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
+status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
+ Vector<uint8_t> &sessionId) {
Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
- if (mInitCheck != OK) {
- return mInitCheck;
+ SecurityLevel hSecurityLevel;
+ bool setSecurityLevel = true;
+
+ switch(level) {
+ case DrmPlugin::kSecurityLevelSwSecureCrypto:
+ hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
+ break;
+ case DrmPlugin::kSecurityLevelSwSecureDecode:
+ hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
+ break;
+ case DrmPlugin::kSecurityLevelHwSecureCrypto:
+ hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
+ break;
+ case DrmPlugin::kSecurityLevelHwSecureDecode:
+ hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
+ break;
+ case DrmPlugin::kSecurityLevelHwSecureAll:
+ hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
+ break;
+ case DrmPlugin::kSecurityLevelMax:
+ setSecurityLevel = false;
+ break;
+ default:
+ return ERROR_DRM_CANNOT_HANDLE;
}
status_t err = UNKNOWN_ERROR;
-
bool retry = true;
do {
hidl_vec<uint8_t> hSessionId;
- Return<void> hResult = mPlugin->openSession(
- [&](Status status, const hidl_vec<uint8_t>& id) {
- if (status == Status::OK) {
- sessionId = toVector(id);
+ Return<void> hResult;
+ if (mPluginV1_1 == NULL || !setSecurityLevel) {
+ hResult = mPlugin->openSession(
+ [&](Status status,const hidl_vec<uint8_t>& id) {
+ if (status == Status::OK) {
+ sessionId = toVector(id);
+ }
+ err = toStatusT(status);
}
- err = toStatusT(status);
- }
- );
+ );
+ } else {
+ hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
+ [&](Status status, const hidl_vec<uint8_t>& id) {
+ if (status == Status::OK) {
+ sessionId = toVector(id);
+ }
+ err = toStatusT(status);
+ }
+ );
+ }
if (!hResult.isOk()) {
err = DEAD_OBJECT;
@@ -485,16 +626,16 @@ status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
DrmSessionManager::Instance()->addSession(getCallingPid(),
mDrmSessionClient, sessionId);
mOpenSessions.push(sessionId);
+ mMetrics.SetSessionStart(sessionId);
}
+
+ mMetrics.mOpenSessionCounter.Increment(err);
return err;
}
status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
if (status.isOk()) {
@@ -507,9 +648,12 @@ status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
}
}
}
- reportMetrics();
- return toStatusT(status);
+ status_t response = toStatusT(status);
+ mMetrics.SetSessionEnd(sessionId);
+ mMetrics.mCloseSessionCounter.Increment(response);
+ return response;
}
+ mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
return DEAD_OBJECT;
}
@@ -519,10 +663,8 @@ status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
String8> const &optionalParameters, Vector<uint8_t> &request,
String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
+ EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
@@ -534,6 +676,7 @@ status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
} else if (keyType == DrmPlugin::kKeyType_Release) {
hKeyType = KeyType::RELEASE;
} else {
+ keyRequestTimer.SetAttribute(BAD_VALUE);
return BAD_VALUE;
}
@@ -541,23 +684,63 @@ status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
status_t err = UNKNOWN_ERROR;
+ if (mPluginV1_1 != NULL) {
+ Return<void> hResult =
+ mPluginV1_1->getKeyRequest_1_1(
+ toHidlVec(sessionId), toHidlVec(initData),
+ toHidlString(mimeType), hKeyType, hOptionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ drm::V1_1::KeyRequestType hKeyRequestType,
+ const hidl_string& hDefaultUrl) {
+
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+
+ switch (hKeyRequestType) {
+ case drm::V1_1::KeyRequestType::INITIAL:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
+ break;
+ case drm::V1_1::KeyRequestType::RENEWAL:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
+ break;
+ case drm::V1_1::KeyRequestType::RELEASE:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Release;
+ break;
+ case drm::V1_1::KeyRequestType::NONE:
+ *keyRequestType = DrmPlugin::kKeyRequestType_None;
+ break;
+ case drm::V1_1::KeyRequestType::UPDATE:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Update;
+ break;
+ default:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
+ break;
+ }
+ err = toStatusT(status);
+ }
+ });
+ return hResult.isOk() ? err : DEAD_OBJECT;
+ }
+
Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
[&](Status status, const hidl_vec<uint8_t>& hRequest,
- KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
+ drm::V1_0::KeyRequestType hKeyRequestType,
+ const hidl_string& hDefaultUrl) {
if (status == Status::OK) {
request = toVector(hRequest);
defaultUrl = toString8(hDefaultUrl);
switch (hKeyRequestType) {
- case KeyRequestType::INITIAL:
+ case drm::V1_0::KeyRequestType::INITIAL:
*keyRequestType = DrmPlugin::kKeyRequestType_Initial;
break;
- case KeyRequestType::RENEWAL:
+ case drm::V1_0::KeyRequestType::RENEWAL:
*keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
break;
- case KeyRequestType::RELEASE:
+ case drm::V1_0::KeyRequestType::RELEASE:
*keyRequestType = DrmPlugin::kKeyRequestType_Release;
break;
default:
@@ -568,16 +751,17 @@ status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
}
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ keyRequestTimer.SetAttribute(err);
+ return err;
}
status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
Mutex::Autolock autoLock(mLock);
+ EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
@@ -592,41 +776,35 @@ status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
err = toStatusT(status);
}
);
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ keyResponseTimer.SetAttribute(err);
+ return err;
}
status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
+ Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
}
status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keySetId) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
- toHidlVec(keySetId)));
+ Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId),
+ toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
}
status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
KeyedVector<String8, String8> &infoMap) const {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
@@ -650,10 +828,7 @@ status_t DrmHal::getProvisionRequest(String8 const &certType,
String8 const &certAuthority, Vector<uint8_t> &request,
String8 &defaultUrl) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
status_t err = UNKNOWN_ERROR;
@@ -669,16 +844,15 @@ status_t DrmHal::getProvisionRequest(String8 const &certType,
}
);
- return hResult.isOk() ? err : DEAD_OBJECT;
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ mMetrics.mGetProvisionRequestCounter.Increment(err);
+ return err;
}
status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
status_t err = UNKNOWN_ERROR;
@@ -693,15 +867,14 @@ status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
}
);
- return hResult.isOk() ? err : DEAD_OBJECT;
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ return err;
}
status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
status_t err = UNKNOWN_ERROR;
@@ -718,13 +891,36 @@ status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
}
-status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
+status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
return mInitCheck;
}
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPluginV1_1->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
+ if (status == Status::OK) {
+ secureStopIds = toSecureStopIds(hSecureStopIds);
+ }
+ err = toStatusT(status);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+
+status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
status_t err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
@@ -741,22 +937,132 @@ status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &sec
status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status(Status::ERROR_DRM_UNKNOWN);
+ if (mPluginV1_1 != NULL) {
+ SecureStopRelease secureStopRelease;
+ secureStopRelease.opaqueData = toHidlVec(ssRelease);
+ status = mPluginV1_1->releaseSecureStops(secureStopRelease);
+ } else {
+ status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
+ }
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
+ Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
return mInitCheck;
}
- return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
}
-status_t DrmHal::releaseAllSecureStops() {
+status_t DrmHal::removeAllSecureStops() {
Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
- if (mInitCheck != OK) {
- return mInitCheck;
+ Return<Status> status(Status::ERROR_DRM_UNKNOWN);
+ if (mPluginV1_1 != NULL) {
+ status = mPluginV1_1->removeAllSecureStops();
+ } else {
+ status = mPlugin->releaseAllSecureStops();
+ }
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
+ DrmPlugin::HdcpLevel *max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (connected == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
}
- return toStatusT(mPlugin->releaseAllSecureStops());
+ *connected = DrmPlugin::kHdcpLevelUnknown;
+ *max = DrmPlugin::kHdcpLevelUnknown;
+
+ Return<void> hResult = mPluginV1_1->getHdcpLevels(
+ [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
+ if (status == Status::OK) {
+ *connected = toHdcpLevel(hConnected);
+ *max = toHdcpLevel(hMax);
+ }
+ err = toStatusT(status);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (open == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ *open = 0;
+ *max = 0;
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ Return<void> hResult = mPluginV1_1->getNumberOfSessions(
+ [&](Status status, uint32_t hOpen, uint32_t hMax) {
+ if (status == Status::OK) {
+ *open = hOpen;
+ *max = hMax;
+ }
+ err = toStatusT(status);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
+ DrmPlugin::SecurityLevel *level) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (level == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ *level = DrmPlugin::kSecurityLevelUnknown;
+
+ Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
+ [&](Status status, SecurityLevel hLevel) {
+ if (status == Status::OK) {
+ *level = toSecurityLevel(hLevel);
+ }
+ err = toStatusT(status);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
}
status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
@@ -767,10 +1073,7 @@ status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
status_t err = UNKNOWN_ERROR;
@@ -794,10 +1097,7 @@ status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &valu
status_t DrmHal::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.
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
status_t err = UNKNOWN_ERROR;
@@ -810,73 +1110,106 @@ status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_
}
);
- return hResult.isOk() ? err : DEAD_OBJECT;
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ if (name == kPropertyDeviceUniqueId) {
+ mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ }
+ return err;
}
status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- Status status = mPlugin->setPropertyString(toHidlString(name),
+ Return<Status> status = mPlugin->setPropertyString(toHidlString(name),
toHidlString(value));
- return toStatusT(status);
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
}
status_t DrmHal::setPropertyByteArray(String8 const &name,
Vector<uint8_t> const &value ) const {
Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- Status status = mPlugin->setPropertyByteArray(toHidlString(name),
+ Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name),
toHidlVec(value));
- return toStatusT(status);
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
}
+status_t DrmHal::getMetrics(PersistableBundle* metrics) {
+ if (metrics == nullptr) {
+ return UNEXPECTED_NULL;
+ }
+ mMetrics.Export(metrics);
+
+ // Append vendor metrics if they are supported.
+ if (mPluginV1_1 != NULL) {
+ String8 vendor;
+ String8 description;
+ if (getPropertyStringInternal(String8("vendor"), vendor) != OK
+ || vendor.isEmpty()) {
+ ALOGE("Get vendor failed or is empty");
+ vendor = "NONE";
+ }
+ if (getPropertyStringInternal(String8("description"), description) != OK
+ || description.isEmpty()) {
+ ALOGE("Get description failed or is empty.");
+ description = "NONE";
+ }
+ vendor += ".";
+ vendor += description;
+
+ hidl_vec<DrmMetricGroup> pluginMetrics;
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> status = mPluginV1_1->getMetrics(
+ [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
+ if (status != Status::OK) {
+ ALOGV("Error getting plugin metrics: %d", status);
+ } else {
+ PersistableBundle pluginBundle;
+ if (MediaDrmMetrics::HidlMetricsToBundle(
+ pluginMetrics, &pluginBundle) == OK) {
+ metrics->putPersistableBundle(String16(vendor), pluginBundle);
+ }
+ }
+ err = toStatusT(status);
+ });
+ return status.isOk() ? err : DEAD_OBJECT;
+ }
+
+ return OK;
+}
status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
String8 const &algorithm) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
+ Return<Status> status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
toHidlString(algorithm));
- return toStatusT(status);
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
}
status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
String8 const &algorithm) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
+ Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
toHidlString(algorithm));
- return toStatusT(status);
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
}
status_t DrmHal::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);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
@@ -899,10 +1232,7 @@ status_t DrmHal::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);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
@@ -925,10 +1255,7 @@ status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
Vector<uint8_t> &signature) {
Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
@@ -951,10 +1278,7 @@ status_t DrmHal::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);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
@@ -979,10 +1303,7 @@ status_t DrmHal::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);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
+ INIT_CHECK();
if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
return -EPERM;
@@ -1007,17 +1328,7 @@ status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
{
- Mutex::Autolock autoLock(mLock);
- closeOpenSessions();
- setListener(NULL);
- mInitCheck = NO_INIT;
-
- if (mPlugin != NULL) {
- if (!mPlugin->setListener(NULL).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- }
- mPlugin.clear();
+ cleanup();
}
void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
@@ -1030,18 +1341,55 @@ void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
}
}
-void DrmHal::reportMetrics() const
+void DrmHal::reportFrameworkMetrics() const
+{
+ MediaAnalyticsItem item("mediadrm");
+ item.generateSessionID();
+ item.setPkgName(mMetrics.GetAppPackageName().c_str());
+ 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 {
+ item.setCString("vendor", vendor.c_str());
+ }
+ result = getPropertyStringInternal(String8("description"), description);
+ if (result != OK) {
+ ALOGE("Failed to get description from drm plugin: %d", result);
+ } else {
+ item.setCString("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()) {
+ item.setCString("serialized_metrics", b64EncodedMetrics.c_str());
+ }
+ if (!item.selfrecord()) {
+ ALOGE("Failed to self record framework metrics");
+ }
+}
+
+void DrmHal::reportPluginMetrics() const
{
- Vector<uint8_t> metrics;
+ Vector<uint8_t> metricsVector;
String8 vendor;
String8 description;
if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
getPropertyStringInternal(String8("description"), description) == OK &&
- getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
- status_t res = android::reportDrmPluginMetrics(
- metrics, vendor, description);
+ getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
+ std::string metricsString = toBase64StringNoPad(metricsVector.array(),
+ metricsVector.size());
+ status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
+ description, mAppPackageName);
if (res != OK) {
- ALOGE("Metrics were retrieved but could not be reported: %i", res);
+ ALOGE("Metrics were retrieved but could not be reported: %d", res);
}
}
}