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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user