Upgrade widevine HIDL service to v1.1.

Merged from http://go/wvgerrit/44803.

Upgrade HIDL service to v1.1 and implements new 1.1 media API.

Test: Netflix and Play Movies & TV
  streaming and offline playback

Test: GTS WidevineH264PlaybackTests test
  e.g. ANDROID_BUILD_TOP= ./android-gts/tools/gts-tradefed run gts -m GtsMediaTestCases
  --test com.google.android.media.gts.WidevineH264PlaybackTests#testL1With480P30

Test: GTS MediaDrmTest tests
  e.g. ANDROID_BUILD_TOP= ./android-gts/tools/gts-tradefed run gts -m GtsMediaTestCases
  --test com.google.android.media.gts.MediaDrmTest#testWidevineApi28

Test: unit tests

bug: 69674645
Change-Id: I91e7e43f9178b61a531e846beffb5f5c17050a3c
This commit is contained in:
Edwin Wong
2018-02-06 10:53:10 -08:00
parent efc008c5a1
commit bc66aebfe2
24 changed files with 447 additions and 89 deletions

View File

@@ -7,6 +7,7 @@
#include <utils/Log.h>
#include <list>
#include <stdlib.h>
#include "WVDrmPlugin.h"
#include "TypeConvert.h"
@@ -29,7 +30,7 @@ static const char* const kSpecialUnprovisionResponse = "unprovision";
namespace wvdrm {
namespace hardware {
namespace drm {
namespace V1_0 {
namespace V1_1 {
namespace widevine {
using ::android::hardware::drm::V1_0::EventType;
@@ -37,9 +38,9 @@ using ::android::hardware::drm::V1_0::KeyRequestType;
using ::android::hardware::drm::V1_0::KeyStatusType;
using ::android::hardware::drm::V1_0::KeyType;
using ::android::hardware::drm::V1_0::Status;
using ::android::hardware::drm::V1_0::widevine::toHidlVec;
using ::android::hardware::drm::V1_0::widevine::toVector;
using ::android::hardware::drm::V1_1::SecurityLevel;
using ::android::hardware::drm::V1_1::widevine::toHidlVec;
using ::android::hardware::drm::V1_1::widevine::toVector;
using ::android::hardware::Void;
using wvcdm::kDefaultCdmIdentifier;
@@ -59,7 +60,6 @@ using wvcdm::CdmSecureStopId;
using wvcdm::CdmUsageInfo;
using wvcdm::CdmUsageInfoReleaseMessage;
using wvcdm::KeyId;
using wvcdm::SecurityLevel;
namespace {
@@ -98,6 +98,25 @@ KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) {
}
}
HdcpLevel mapHdcpLevel(const std::string level) {
if (level == wvcdm::QUERY_VALUE_HDCP_V1)
return HdcpLevel::HDCP_V1;
else if (level == wvcdm::QUERY_VALUE_HDCP_V2_0)
return HdcpLevel::HDCP_V2;
else if (level == wvcdm::QUERY_VALUE_HDCP_V2_1)
return HdcpLevel::HDCP_V2_1;
else if (level == wvcdm::QUERY_VALUE_HDCP_V2_2)
return HdcpLevel::HDCP_V2_2;
else if (level == wvcdm::QUERY_VALUE_HDCP_NONE)
return HdcpLevel::HDCP_NONE;
else if (level == wvcdm::QUERY_VALUE_HDCP_NO_DIGITAL_OUTPUT)
return HdcpLevel::HDCP_NO_OUTPUT;
else {
ALOGE("Invalid HDCP level=%s", level.c_str());
return HdcpLevel::HDCP_NONE;
}
}
} // namespace
WVDrmPlugin::WVDrmPlugin(const sp<WvContentDecryptionModule>& cdm,
@@ -122,15 +141,13 @@ WVDrmPlugin::~WVDrmPlugin() {
mCryptoSessions.clear();
}
Return<void> WVDrmPlugin::openSession(openSession_cb _hidl_cb) {
Status WVDrmPlugin::openSessionCommon(std::vector<uint8_t>& sessionId) {
Status status = Status::OK;
std::vector<uint8_t> sessionId;
CdmIdentifier identifier;
status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
_hidl_cb(status, toHidlVec(sessionId));
return Void();
return status;
}
CdmSessionId cdmSessionId;
@@ -140,8 +157,7 @@ Return<void> WVDrmPlugin::openSession(openSession_cb _hidl_cb) {
if (!isCdmResponseTypeSuccess(res)) {
status = mapAndNotifyOfCdmResponseType(sessionId, res);
_hidl_cb(status, toHidlVec(sessionId));
return Void();
return status;
}
bool success = false;
@@ -164,8 +180,7 @@ Return<void> WVDrmPlugin::openSession(openSession_cb _hidl_cb) {
if (success) {
// Marshal Session ID
sessionId = StrToVector(cdmSessionId);
_hidl_cb(Status::OK, toHidlVec(sessionId));
return Void();
return Status::OK;
} else {
mCDM->CloseSession(cdmSessionId);
@@ -179,6 +194,79 @@ Return<void> WVDrmPlugin::openSession(openSession_cb _hidl_cb) {
status = Status::ERROR_DRM_UNKNOWN;
}
}
return status;
}
Return<void> WVDrmPlugin::openSession(openSession_cb _hidl_cb) {
std::vector<uint8_t> sessionId;
Status status = openSessionCommon(sessionId);
_hidl_cb(status, toHidlVec(sessionId));
return Void();
}
SecurityLevel WVDrmPlugin::mapSecurityLevel(const std::string& level) {
SecurityLevel hSecurityLevel = SecurityLevel::UNKNOWN;
if (wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1 == level) {
hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
} else if (wvcdm::QUERY_VALUE_SECURITY_LEVEL_L2 == level) {
hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
} else if (wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3 == level) {
hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
} // else QUERY_VALUE_SECURITY_LEVEL_UNKNOWN returns Security::UNKNOWN
return hSecurityLevel;
}
Return<void> WVDrmPlugin::openSession_1_1(
SecurityLevel requestedLevel,
openSession_1_1_cb _hidl_cb) {
std::vector<uint8_t> sessionId;
sessionId.clear();
if (SecurityLevel::UNKNOWN == requestedLevel) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, toHidlVec(sessionId));
return Void();
}
std::string native_security_level;
Status status = queryProperty(wvcdm::kLevelDefault,
wvcdm::QUERY_KEY_SECURITY_LEVEL, native_security_level);
if (Status::OK != status) {
_hidl_cb(status, toHidlVec(sessionId));
return Void();
}
if (wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3 == native_security_level &&
requestedLevel >= SecurityLevel::SW_SECURE_DECODE) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, toHidlVec(sessionId));
return Void();
}
std::string wvcdm_security_level =
(SecurityLevel::SW_SECURE_CRYPTO == requestedLevel) ?
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3 : wvcdm::QUERY_VALUE_SECURITY_LEVEL_DEFAULT;
setPropertyString(hidl_string(wvcdm::QUERY_KEY_SECURITY_LEVEL),
hidl_string(wvcdm_security_level));
status = openSessionCommon(sessionId);
hidl_vec<uint8_t> hSessionId = toHidlVec(sessionId);
if (Status::OK == status) {
Return<void> hResult = getSecurityLevel(hSessionId, [&](Status status, SecurityLevel hSecurityLevel) {
if (Status::OK != status || requestedLevel != hSecurityLevel) {
ALOGE("Failed to open session with the requested security level=%d", requestedLevel);
if (Status::OK != closeSession(hSessionId)) sessionId.clear();
}
});
if (!hResult.isOk()) {
status = Status::ERROR_DRM_INVALID_STATE;
ALOGE("openSession_1_1 fails communication with the remote HAL");
}
}
_hidl_cb(status, toHidlVec(sessionId));
return Void();
}
@@ -319,6 +407,38 @@ Return<void> WVDrmPlugin::getKeyRequest(
return Void();
}
Return<void> WVDrmPlugin::getKeyRequest_1_1(
const hidl_vec<uint8_t>& scope,
const hidl_vec<uint8_t>& initData,
const hidl_string& mimeType,
KeyType keyType,
const hidl_vec<KeyValue>& optionalParameters,
getKeyRequest_1_1_cb _hidl_cb) {
hidl_string defaultUrl;
hidl_vec<uint8_t> request;
::android::hardware::drm::V1_1::KeyRequestType requestType =
static_cast<::android::hardware::drm::V1_1::KeyRequestType>(KeyRequestType::UNKNOWN);
Status status = Status::ERROR_DRM_UNKNOWN;
defaultUrl.clear();
Return<void> hResult = getKeyRequest(scope, initData, mimeType, keyType, optionalParameters,
[&](Status statusCode, const hidl_vec<uint8_t>& hRequest,
KeyRequestType hKeyRequestType,
const hidl_string& hDefaultUrl) {
defaultUrl = hDefaultUrl;
request = hRequest;
requestType = static_cast<::android::hardware::drm::V1_1::KeyRequestType>(hKeyRequestType);
status = statusCode;
});
if (!hResult.isOk()) {
status = Status::ERROR_DRM_INVALID_STATE;
ALOGE("getKeyRequest_1_1 fails communication with the remote HAL");
}
_hidl_cb(status, request, requestType, defaultUrl);
return Void();
}
Return<void> WVDrmPlugin::provideKeyResponse(
const hidl_vec<uint8_t>& scope,
const hidl_vec<uint8_t>& response,
@@ -602,16 +722,7 @@ Return<void> WVDrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
}
Return<Status> WVDrmPlugin::releaseAllSecureStops() {
CdmIdentifier identifier;
Status status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
return status;
}
CdmResponseType res = mCDM->RemoveAllUsageInfo(mPropertySet.app_id(),
identifier);
return mapCdmResponseType(res);
return removeAllSecureStops();
}
Return<Status> WVDrmPlugin::releaseSecureStop(
@@ -633,6 +744,158 @@ Return<Status> WVDrmPlugin::releaseSecureStop(
return mapCdmResponseType(res);
}
Return<void> WVDrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
std::vector<SecureStopId> secureStopIds;
CdmIdentifier identifier;
Status status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
_hidl_cb(status, toHidlVec(secureStopIds));
return Void();
}
std::vector<CdmSecureStopId> ssids;
CdmResponseType res =
mCDM->GetSecureStopIds(mPropertySet.app_id(), identifier, &ssids);
if (isCdmResponseTypeSuccess(res)) {
for (auto itr = ssids.begin(); itr != ssids.end(); ++itr) {
const CdmSecureStopId& ssid = *itr;
secureStopIds.push_back(StrToVector(ssid));
}
}
_hidl_cb(mapCdmResponseType(res), toHidlVec(secureStopIds));
return Void();
}
Return<Status> WVDrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
if (ssRelease.opaqueData.size() == 0) {
return Status::BAD_VALUE;
}
CdmIdentifier identifier;
Status status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
return status;
}
const std::vector<uint8_t> data = toVector(ssRelease.opaqueData);
CdmUsageInfoReleaseMessage cdmMessage(data.begin(), data.end());
CdmResponseType res = mCDM->ReleaseUsageInfo(cdmMessage, identifier);
return mapCdmResponseType(res);
}
Return<Status> WVDrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
if (!secureStopId.size()) {
return Status::BAD_VALUE;
}
CdmIdentifier identifier;
Status status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
return status;
}
const std::vector<uint8_t> idVec = toVector(secureStopId);
CdmSecureStopId id(idVec.begin(), idVec.end());
CdmResponseType res = mCDM->RemoveUsageInfo(mPropertySet.app_id(), identifier, id);
return mapCdmResponseType(res);
}
Return<Status> WVDrmPlugin::removeAllSecureStops() {
CdmIdentifier identifier;
Status status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
return status;
}
CdmResponseType res = mCDM->RemoveAllUsageInfo(mPropertySet.app_id(),
identifier);
return mapCdmResponseType(res);
}
Return<void> WVDrmPlugin::getHdcpLevels(getHdcpLevels_cb _hidl_cb) {
HdcpLevel connectedLevel = HdcpLevel::HDCP_NONE;
HdcpLevel maxLevel = HdcpLevel::HDCP_NO_OUTPUT;
std::string level;
Status status = queryProperty(wvcdm::QUERY_KEY_CURRENT_HDCP_LEVEL, level);
if (status == Status::OK) {
connectedLevel = mapHdcpLevel(level);
} else {
ALOGE("Failed to query current hdcp level.");
_hidl_cb(Status::ERROR_DRM_INVALID_STATE, connectedLevel, maxLevel);
return Void();
}
status = queryProperty(wvcdm::QUERY_KEY_MAX_HDCP_LEVEL, level);
if (status == Status::OK) {
maxLevel = mapHdcpLevel(level);
} else {
ALOGE("Failed to query maximum hdcp level.");
_hidl_cb(Status::ERROR_DRM_INVALID_STATE, connectedLevel, maxLevel);
return Void();
}
_hidl_cb(Status::OK, connectedLevel, maxLevel);
return Void();
}
Return<void> WVDrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
uint32_t currentSessions = 0;
uint32_t maxSessions = 1;
std::string value;
Status status = queryProperty(wvcdm::QUERY_KEY_NUMBER_OF_OPEN_SESSIONS, value);
if (status == Status::OK) {
currentSessions = std::strtoul(value.c_str(), nullptr, 10);
} else {
ALOGE("Failed to query currently opened sessions.");
_hidl_cb(Status::ERROR_DRM_INVALID_STATE, currentSessions, maxSessions);
return Void();
}
status = queryProperty(wvcdm::QUERY_KEY_MAX_NUMBER_OF_SESSIONS, value);
if (status == Status::OK) {
maxSessions = std::strtoul(value.c_str(), nullptr, 10);
} else {
ALOGE("Failed to query maximum number of sessions that the device can support.");
_hidl_cb(Status::ERROR_DRM_INVALID_STATE, currentSessions, maxSessions);
return Void();
}
_hidl_cb(Status::OK, currentSessions, maxSessions);
return Void();
}
Return<void> WVDrmPlugin::getSecurityLevel(
const hidl_vec<uint8_t>& sessionId,
getSecurityLevel_cb _hidl_cb) {
if (sessionId.size() == 0) {
_hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
return Void();
}
std::vector<uint8_t> sid = toVector(sessionId);
CdmQueryMap info;
SecurityLevel hSecurityLevel = SecurityLevel::UNKNOWN;
CdmResponseType status = mCDM->QuerySessionStatus(
std::string(sid.begin(), sid.end()), &info);
if (wvcdm::NO_ERROR == status) {
std::string level = info[wvcdm::QUERY_KEY_SECURITY_LEVEL];
hSecurityLevel = mapSecurityLevel(level);
} else {
ALOGE("Failed to query security level, status=%d", status);
}
_hidl_cb(mapCdmResponseType(status), hSecurityLevel);
return Void();
}
Return<void> WVDrmPlugin::getPropertyString(const hidl_string& propertyName,
getPropertyString_cb _hidl_cb) {
Status status = Status::OK;
@@ -757,7 +1020,8 @@ Return<Status> WVDrmPlugin::setPropertyString(const hidl_string& propertyName,
} else {
mPropertySet.set_security_level(kResetSecurityLevel);
}
} else if (_value == kResetSecurityLevel) {
} else if (_value == kResetSecurityLevel ||
_value == wvcdm::QUERY_VALUE_SECURITY_LEVEL_DEFAULT) {
mPropertySet.set_security_level(kResetSecurityLevel);
} else {
ALOGE("App requested invalid security level %s", _value.c_str());
@@ -1245,7 +1509,7 @@ void WVDrmPlugin::OnExpirationUpdate(const CdmSessionId& cdmSessionId,
Status WVDrmPlugin::queryProperty(const std::string& property,
std::string& stringValue) const {
SecurityLevel securityLevel =
wvcdm::SecurityLevel securityLevel =
mPropertySet.security_level().compare(
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3) == 0
? wvcdm::kLevel3
@@ -1253,7 +1517,7 @@ Status WVDrmPlugin::queryProperty(const std::string& property,
return queryProperty(securityLevel, property, stringValue);
}
Status WVDrmPlugin::queryProperty(SecurityLevel securityLevel,
Status WVDrmPlugin::queryProperty(wvcdm::SecurityLevel securityLevel,
const std::string& property,
std::string& stringValue) const {
CdmResponseType res =
@@ -1454,7 +1718,7 @@ Status WVDrmPlugin::CdmIdentifierBuilder::getOemcryptoDeviceId(
}
} // namespace widevine
} // namespace V1_0
} // namespace V1_1
} // namespace drm
} // namespace hardware
} // namespace wvdrm