Support ATSC license installation
[ Merge of http://go/wvgerrit/163900/ ] ATSC licenses can be saved by calling MediaDrm#setPropertyString("storeAtscLicense",<value>) where <value> is "<atsc-key-set-ID>:<license-file-data in Base64 format>" Before storing an ATSC license a session must be opened and the ATSC mode must be enabled. Use MediaDrm#setPropertyString("atscMode","enable"); Bug: 176871821 Test: WV Unit/integration/Luci tests Test: libwvdrmdrmplugin_hal_test Test: GtsMediaTestCases Change-Id: Iec2a8b7f87b1122395d06856202278b92316fdfe
This commit is contained in:
@@ -235,6 +235,10 @@ class CdmEngine {
|
||||
virtual CdmResponseType RemoveOfflineLicense(const std::string& key_set_id,
|
||||
CdmSecurityLevel security_level);
|
||||
|
||||
virtual CdmResponseType StoreAtscLicense(
|
||||
RequestedSecurityLevel security_level, const CdmKeySetId& key_set_id,
|
||||
const std::string& serialized_license_data);
|
||||
|
||||
// Usage related methods for streaming licenses
|
||||
// Retrieve a random usage info from the list of all usage infos for this app
|
||||
// id. If |error_detail| is not null, an additional error code may be provided
|
||||
|
||||
@@ -155,6 +155,9 @@ class DeviceFiles {
|
||||
virtual bool RetrieveLicense(const std::string& key_set_id,
|
||||
CdmLicenseData* license_data,
|
||||
ResponseType* result);
|
||||
virtual ResponseType StoreAtscLicense(
|
||||
const CdmKeySetId& key_set_id,
|
||||
const std::string& serialized_license_data);
|
||||
|
||||
virtual bool DeleteLicense(const std::string& key_set_id);
|
||||
virtual bool ListLicenses(std::vector<std::string>* key_set_ids);
|
||||
|
||||
@@ -1413,6 +1413,35 @@ CdmResponseType CdmEngine::RemoveOfflineLicense(
|
||||
return sts;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::StoreAtscLicense(
|
||||
RequestedSecurityLevel requested_security_level,
|
||||
const CdmKeySetId& key_set_id, const std::string& serialized_license_data) {
|
||||
std::string security_level_string;
|
||||
|
||||
CdmResponseType status =
|
||||
QueryStatus(requested_security_level, QUERY_KEY_SECURITY_LEVEL,
|
||||
&security_level_string);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
DeviceFiles handle(file_system_);
|
||||
CdmSecurityLevel security_level =
|
||||
security_level_string == QUERY_VALUE_SECURITY_LEVEL_L1 ? kSecurityLevelL1
|
||||
: kSecurityLevelL3;
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("Unable to initialize device files");
|
||||
return CdmResponseType(STORE_ATSC_LICENSE_DEVICE_FILES_INIT_ERROR);
|
||||
}
|
||||
|
||||
DeviceFiles::ResponseType response_type =
|
||||
handle.StoreAtscLicense(key_set_id, serialized_license_data);
|
||||
if (response_type != DeviceFiles::kNoError) {
|
||||
LOGE("Unable to store ATSC license: response = %s",
|
||||
DeviceFiles::ResponseTypeToString(response_type));
|
||||
return CdmResponseType(STORE_ATSC_LICENSE_ERROR);
|
||||
}
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
int* error_detail,
|
||||
|
||||
@@ -943,6 +943,11 @@ bool DeviceFiles::RetrieveLicense(const std::string& key_set_id,
|
||||
&license_data->wrapped_private_key);
|
||||
}
|
||||
|
||||
DeviceFiles::ResponseType DeviceFiles::StoreAtscLicense(
|
||||
const CdmKeySetId& key_set_id, const std::string& serialized_data) {
|
||||
return StoreFileWithHash(key_set_id + kLicenseFileNameExt, serialized_data);
|
||||
}
|
||||
|
||||
bool DeviceFiles::DeleteLicense(const std::string& key_set_id) {
|
||||
RETURN_FALSE_IF_UNINITIALIZED();
|
||||
return RemoveFile(key_set_id + kLicenseFileNameExt);
|
||||
|
||||
@@ -194,6 +194,10 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
virtual CdmResponseType GetSessionUserId(const CdmSessionId& session_id,
|
||||
uint32_t* user_id);
|
||||
|
||||
virtual CdmResponseType StoreAtscLicense(
|
||||
const CdmIdentifier& identifier, RequestedSecurityLevel security_level,
|
||||
const CdmKeySetId& key_set_id,
|
||||
const std::string& serialized_license_data);
|
||||
virtual bool SetDefaultOtaKeyboxFallbackDurationRules();
|
||||
virtual bool SetFastOtaKeyboxFallbackDurationRules();
|
||||
|
||||
|
||||
@@ -656,6 +656,15 @@ CdmResponseType WvContentDecryptionModule::GetSessionUserId(
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::StoreAtscLicense(
|
||||
const CdmIdentifier& identifier,
|
||||
RequestedSecurityLevel requested_security_level,
|
||||
const CdmKeySetId& key_set_id, const std::string& serialized_license_data) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
return cdm_engine->StoreAtscLicense(requested_security_level, key_set_id,
|
||||
serialized_license_data);
|
||||
}
|
||||
|
||||
bool WvContentDecryptionModule::SetDefaultOtaKeyboxFallbackDurationRules() {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
|
||||
if (!cdm_engine) return false;
|
||||
|
||||
@@ -456,6 +456,10 @@ class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin,
|
||||
in_keyStatusList,
|
||||
bool in_hasNewUsableKey);
|
||||
void sendSessionLostState(const std::vector<uint8_t>& in_sessionId);
|
||||
|
||||
WvStatus parseAtscLicenseData(const std::string& value,
|
||||
std::string* key_set_id,
|
||||
std::string* serialized_license_data);
|
||||
};
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "mapErrors-inl.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "openssl/sha.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_metrics.pb.h"
|
||||
#include "wv_metrics_adapter.h"
|
||||
@@ -1344,6 +1345,32 @@ Status WVDrmPlugin::unprovisionDevice() {
|
||||
if (!success) {
|
||||
return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN);
|
||||
}
|
||||
} else if (name == "storeAtscLicense") {
|
||||
if (!mCdmIdentifierBuilder.is_sealed()) {
|
||||
ALOGE("Cdm identifier builder is not sealed. Storing ATSC license "
|
||||
"prohibited");
|
||||
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
|
||||
}
|
||||
if (!mPropertySet.use_atsc_mode()) {
|
||||
ALOGE("ATSC mode not enabled. Storing ATSC license prohibited");
|
||||
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
|
||||
}
|
||||
|
||||
CdmIdentifier identifier;
|
||||
auto status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
|
||||
if (status != Status::OK) {
|
||||
ALOGE("Unable to get CDM Identifier = %d", status.get());
|
||||
return toNdkScopedAStatus(status);
|
||||
}
|
||||
std::string key_set_id, license_data;
|
||||
status = parseAtscLicenseData(_value, &key_set_id, &license_data);
|
||||
if (status != Status::OK)
|
||||
return toNdkScopedAStatus(status);
|
||||
|
||||
const CdmResponseType res = mCDM->StoreAtscLicense(
|
||||
identifier, getRequestedSecurityLevel(), key_set_id, license_data);
|
||||
|
||||
return toNdkScopedAStatus(mapCdmResponseType(res));
|
||||
} else {
|
||||
ALOGE("App set unknown string property %s", name.c_str());
|
||||
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
|
||||
@@ -1871,6 +1898,57 @@ bool WVDrmPlugin::isProvisioned(wvcdm::CdmSecurityLevel securityLevel,
|
||||
return mCDM->IsProvisioned(securityLevel, origin, spoid, atsc_mode_enabled);
|
||||
}
|
||||
|
||||
WvStatus WVDrmPlugin::parseAtscLicenseData(
|
||||
const std::string& in_value,
|
||||
std::string* key_set_id,
|
||||
std::string* serialized_license_data) {
|
||||
if (key_set_id == nullptr) {
|
||||
ALOGE("key_set_id null");
|
||||
return WvStatus(Status::ERROR_DRM_CANNOT_HANDLE);
|
||||
}
|
||||
|
||||
if (serialized_license_data == nullptr) {
|
||||
ALOGE("serialized_license_data null");
|
||||
return WvStatus(Status::ERROR_DRM_CANNOT_HANDLE);
|
||||
}
|
||||
|
||||
if (in_value.compare(0,
|
||||
strlen(wvcdm::ATSC_KEY_SET_ID_PREFIX),
|
||||
&wvcdm::ATSC_KEY_SET_ID_PREFIX[0]) != 0) {
|
||||
ALOGE("ATSC license input does not conform to expectations. Key set does "
|
||||
"not have a valid ATSC Key set prefix %s", in_value.c_str());
|
||||
return WvStatus(Status::BAD_VALUE);
|
||||
}
|
||||
const char kColon = ':';
|
||||
const size_t pos = in_value.find(kColon);
|
||||
if (pos == std::string::npos) {
|
||||
ALOGE("ATSC license input does not conform to expectations. Missing colon "
|
||||
"= %s", in_value.c_str());
|
||||
return WvStatus(Status::BAD_VALUE);
|
||||
}
|
||||
|
||||
if (pos == in_value.length()) {
|
||||
ALOGE("ATSC license input does not conform to expectations. No data after "
|
||||
"colon");
|
||||
return WvStatus(Status::BAD_VALUE);
|
||||
}
|
||||
|
||||
*key_set_id = in_value.substr(0, pos);
|
||||
const std::vector<uint8_t> license_data_binary =
|
||||
wvutil::Base64Decode(in_value.substr(pos+1));
|
||||
|
||||
if (license_data_binary.empty()) {
|
||||
ALOGE("ATSC license input does not conform to expectations. License data "
|
||||
"failed to decode from Base64");
|
||||
return WvStatus(Status::BAD_VALUE);
|
||||
}
|
||||
serialized_license_data->assign(license_data_binary.begin(),
|
||||
license_data_binary.end());
|
||||
|
||||
return WvStatus(Status::OK);
|
||||
}
|
||||
|
||||
|
||||
WvStatus WVDrmPlugin::mapAndNotifyOfCdmResponseType(
|
||||
const vector<uint8_t>& sessionId, CdmResponseType res) {
|
||||
notifyOfCdmResponseType(sessionId, res);
|
||||
|
||||
@@ -239,6 +239,11 @@ public:
|
||||
MOCK_METHOD(CdmResponseType, RemoveOfflineLicense,
|
||||
(const std::string &, CdmSecurityLevel, const CdmIdentifier &),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(CdmResponseType, StoreAtscLicense,
|
||||
(const CdmIdentifier &, wvcdm::RequestedSecurityLevel,
|
||||
const std::string &, const std::string &),
|
||||
(override));
|
||||
};
|
||||
|
||||
class MockCrypto : public WVGenericCryptoInterface {
|
||||
@@ -2909,6 +2914,253 @@ TEST_F(WVDrmPluginHalTest, RemoveOfflineLicense) {
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginHalTest, CanStoreAtscLicense) {
|
||||
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
|
||||
StrictMock<MockCrypto> crypto;
|
||||
std::string appPackageName = "com.test.package";
|
||||
|
||||
const CdmClientPropertySet *propertySet = nullptr;
|
||||
CdmIdentifier mCdmIdAtscModeSet;
|
||||
|
||||
// Generate ATSC keyset and license data
|
||||
uint8_t atscKeySetIdRaw[kKeySetIdSize];
|
||||
std::vector<uint8_t> licenseDataRaw;
|
||||
const size_t kLicenseDataSize = 512;
|
||||
licenseDataRaw.resize(kLicenseDataSize);
|
||||
|
||||
FILE *fp = fopen("/dev/urandom", "r");
|
||||
ASSERT_NE(fp, nullptr) << "Failed to open /dev/urandom";
|
||||
|
||||
fread(atscKeySetIdRaw, sizeof(uint8_t), sizeof(atscKeySetIdRaw), fp);
|
||||
fread(&licenseDataRaw[0], sizeof(uint8_t), licenseDataRaw.size(), fp);
|
||||
fclose(fp);
|
||||
|
||||
// Generate an ATSC key set ID of the form <ATSC prefix>+<random hex>
|
||||
// with a total length of kKeySetIdSize
|
||||
std::string atscKeySetId(wvcdm::ATSC_KEY_SET_ID_PREFIX);
|
||||
atscKeySetId.append(wvutil::HexEncode(atscKeySetIdRaw, kKeySetIdSize));
|
||||
atscKeySetId.resize(kKeySetIdSize);
|
||||
memcpy(atscKeySetIdRaw, atscKeySetId.c_str(), sizeof(atscKeySetIdRaw));
|
||||
|
||||
std::string licenseDataBase64 = Base64Encode(licenseDataRaw);
|
||||
std::string atscLicenseData = atscKeySetId + ":" + licenseDataBase64;
|
||||
|
||||
// Provide expected mock behavior
|
||||
{
|
||||
// Provide expected behavior in response to OpenSession and store the
|
||||
// property set
|
||||
EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<4>(mCdmSessionId),
|
||||
SaveArg<1>(&propertySet),
|
||||
SaveArg<2>(&mCdmIdAtscModeSet),
|
||||
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||
|
||||
// Provide expected behavior when plugin requests session control info
|
||||
EXPECT_CALL(*cdm, QueryOemCryptoSessionId(mCdmSessionId, _))
|
||||
.WillRepeatedly(Invoke(setSessionIdOnMap<4>));
|
||||
|
||||
EXPECT_CALL(
|
||||
*cdm, StoreAtscLicense(HasOrigin(EMPTY_ORIGIN), wvcdm::kLevelDefault,
|
||||
ElementsAreArray(atscKeySetIdRaw, kKeySetIdSize),
|
||||
ElementsAreArray(licenseDataRaw)))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*cdm, CloseSession(_)).Times(1);
|
||||
}
|
||||
|
||||
std::shared_ptr<WVDrmPlugin> plugin = ::ndk::SharedRefBase::make<WVDrmPlugin>(
|
||||
cdm.get(), appPackageName, &crypto, false);
|
||||
|
||||
// Test turning on ATSC mode
|
||||
auto ret =
|
||||
plugin->setPropertyString(std::string("atscMode"), std::string("enable"));
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
|
||||
ret = plugin->openSession(SecurityLevel::DEFAULT, &sessionId);
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
ASSERT_THAT(propertySet, NotNull());
|
||||
EXPECT_TRUE(propertySet->use_atsc_mode());
|
||||
EXPECT_EQ(mCdmIdAtscModeSet.app_package_name, wvcdm::ATSC_APP_PACKAGE_NAME);
|
||||
|
||||
ret = plugin->setPropertyString(std::string("storeAtscLicense"),
|
||||
atscLicenseData);
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
|
||||
ret = plugin->closeSession(sessionId);
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginHalTest, FailsToStoreAtscLicense) {
|
||||
android::sp<StrictMock<MockCDM>> cdm1 = new StrictMock<MockCDM>();
|
||||
android::sp<StrictMock<MockCDM>> cdm2 = new StrictMock<MockCDM>();
|
||||
android::sp<StrictMock<MockCDM>> cdm3 = new StrictMock<MockCDM>();
|
||||
StrictMock<MockCrypto> crypto;
|
||||
std::string appPackageName = "com.test.package";
|
||||
|
||||
const CdmClientPropertySet *propertySet = nullptr;
|
||||
CdmIdentifier mCdmIdAtscModeSet;
|
||||
|
||||
// Generate ATSC keyset and license data
|
||||
uint8_t atscKeySetIdRaw[kKeySetIdSize];
|
||||
std::vector<uint8_t> licenseDataRaw;
|
||||
const size_t kLicenseDataSize = 512;
|
||||
licenseDataRaw.resize(kLicenseDataSize);
|
||||
|
||||
FILE *fp = fopen("/dev/urandom", "r");
|
||||
ASSERT_NE(fp, nullptr) << "Failed to open /dev/urandom";
|
||||
|
||||
fread(atscKeySetIdRaw, sizeof(uint8_t), sizeof(atscKeySetIdRaw), fp);
|
||||
fread(&licenseDataRaw[0], sizeof(uint8_t), licenseDataRaw.size(), fp);
|
||||
fclose(fp);
|
||||
|
||||
std::string atscKeySetId(wvcdm::ATSC_KEY_SET_ID_PREFIX);
|
||||
atscKeySetId.append(wvutil::HexEncode(&atscKeySetIdRaw[0], kKeySetIdSize));
|
||||
atscKeySetId.resize(kKeySetIdSize);
|
||||
memcpy(atscKeySetIdRaw, atscKeySetId.c_str(), sizeof(atscKeySetIdRaw));
|
||||
|
||||
std::string licenseDataBase64 = Base64Encode(licenseDataRaw);
|
||||
std::string atscLicenseData = atscKeySetId + ":" + licenseDataBase64;
|
||||
|
||||
// Provide expected mock behavior
|
||||
{
|
||||
// No mock behavior expected for plugin1/cdm1
|
||||
|
||||
// For plugin2/cdm2
|
||||
// Provide expected behavior in response to OpenSession and store the
|
||||
// property set
|
||||
EXPECT_CALL(*cdm2, OpenSession(_, _, _, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<4>(mCdmSessionId),
|
||||
SaveArg<1>(&propertySet),
|
||||
SaveArg<2>(&mCdmIdAtscModeSet),
|
||||
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||
|
||||
// Provide expected behavior when plugin2 requests session control info
|
||||
EXPECT_CALL(*cdm2, QueryOemCryptoSessionId(mCdmSessionId, _))
|
||||
.WillRepeatedly(Invoke(setSessionIdOnMap<4>));
|
||||
|
||||
EXPECT_CALL(*cdm2, CloseSession(_)).Times(1);
|
||||
|
||||
// For plugin3/cdm3
|
||||
// Provide expected behavior in response to OpenSession and store the
|
||||
// property set
|
||||
EXPECT_CALL(*cdm3, OpenSession(_, _, _, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<4>(mCdmSessionId),
|
||||
SaveArg<1>(&propertySet),
|
||||
SaveArg<2>(&mCdmIdAtscModeSet),
|
||||
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||
|
||||
// Provide expected behavior when plugin3 requests session control info
|
||||
EXPECT_CALL(*cdm3, QueryOemCryptoSessionId(mCdmSessionId, _))
|
||||
.WillRepeatedly(Invoke(setSessionIdOnMap<4>));
|
||||
|
||||
EXPECT_CALL(*cdm3, CloseSession(_)).Times(1);
|
||||
}
|
||||
|
||||
// Try storing an ATSC license without opening a session. Should fail.
|
||||
std::shared_ptr<WVDrmPlugin> plugin1 =
|
||||
::ndk::SharedRefBase::make<WVDrmPlugin>(
|
||||
cdm1.get(), appPackageName.c_str(), &crypto, false);
|
||||
|
||||
auto ret = plugin1->setPropertyString(std::string("storeAtscLicense"),
|
||||
atscLicenseData);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
EXPECT_EQ(static_cast<int>(Status::ERROR_DRM_CANNOT_HANDLE),
|
||||
ret.getServiceSpecificError());
|
||||
|
||||
// Try storing an ATSC license without setting ATSC mode. Should fail.
|
||||
std::shared_ptr<WVDrmPlugin> plugin2 =
|
||||
::ndk::SharedRefBase::make<WVDrmPlugin>(
|
||||
cdm2.get(), appPackageName.c_str(), &crypto, false);
|
||||
|
||||
ret = plugin2->openSession(SecurityLevel::DEFAULT, &sessionId);
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
ASSERT_THAT(propertySet, NotNull());
|
||||
EXPECT_FALSE(propertySet->use_atsc_mode());
|
||||
EXPECT_NE(mCdmIdAtscModeSet.app_package_name, wvcdm::ATSC_APP_PACKAGE_NAME);
|
||||
|
||||
ret = plugin2->setPropertyString(std::string("storeAtscLicense"),
|
||||
atscLicenseData);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
EXPECT_EQ(static_cast<int>(Status::ERROR_DRM_CANNOT_HANDLE),
|
||||
ret.getServiceSpecificError());
|
||||
|
||||
ret = plugin2->closeSession(sessionId);
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
|
||||
// Try storing an ATSC license
|
||||
// (a) Without ATSC key set prefix
|
||||
// (b) Only ATSC key set
|
||||
// (c) Only license data
|
||||
// (d) Invalid Base64 license data
|
||||
// (e) No ATSC key set
|
||||
// (f) No license data
|
||||
// All these should fail.
|
||||
std::shared_ptr<WVDrmPlugin> plugin3 =
|
||||
::ndk::SharedRefBase::make<WVDrmPlugin>(
|
||||
cdm3.get(), appPackageName.c_str(), &crypto, false);
|
||||
|
||||
// Test turning on ATSC mode
|
||||
ret = plugin3->setPropertyString(std::string("atscMode"),
|
||||
std::string("enable"));
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
|
||||
ret = plugin3->openSession(SecurityLevel::DEFAULT, &sessionId);
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
ASSERT_THAT(propertySet, NotNull());
|
||||
EXPECT_TRUE(propertySet->use_atsc_mode());
|
||||
EXPECT_EQ(mCdmIdAtscModeSet.app_package_name, wvcdm::ATSC_APP_PACKAGE_NAME);
|
||||
|
||||
// (a) No ATSC key set prefix
|
||||
atscKeySetId.assign(wvutil::HexEncode(&atscKeySetIdRaw[0], kKeySetIdSize));
|
||||
atscKeySetId.resize(kKeySetIdSize);
|
||||
atscLicenseData = atscKeySetId + ":" + licenseDataBase64;
|
||||
|
||||
ret = plugin3->setPropertyString(std::string("storeAtscLicense"),
|
||||
atscLicenseData);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
EXPECT_EQ(static_cast<int>(Status::BAD_VALUE), ret.getServiceSpecificError());
|
||||
|
||||
// (b) Only ATSC key set
|
||||
atscKeySetId.assign(wvcdm::ATSC_KEY_SET_ID_PREFIX);
|
||||
atscKeySetId.append(wvutil::HexEncode(&atscKeySetIdRaw[0], kKeySetIdSize));
|
||||
atscKeySetId.resize(kKeySetIdSize);
|
||||
|
||||
ret =
|
||||
plugin3->setPropertyString(std::string("storeAtscLicense"), atscKeySetId);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
|
||||
// (c) Only license data
|
||||
ret = plugin3->setPropertyString(std::string("storeAtscLicense"),
|
||||
licenseDataBase64);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
|
||||
// (d) Invalid Base64 license data
|
||||
licenseDataBase64.append("$");
|
||||
atscLicenseData = atscKeySetId + ":" + licenseDataBase64;
|
||||
|
||||
ret = plugin3->setPropertyString(std::string("storeAtscLicense"),
|
||||
atscLicenseData);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
|
||||
// (e) No ATSC key set
|
||||
licenseDataBase64 = Base64Encode(licenseDataRaw);
|
||||
atscLicenseData = ":" + licenseDataBase64;
|
||||
|
||||
ret = plugin3->setPropertyString(std::string("storeAtscLicense"),
|
||||
atscLicenseData);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
|
||||
// (f) No license data
|
||||
atscLicenseData = atscKeySetId + ":";
|
||||
|
||||
ret = plugin3->setPropertyString(std::string("storeAtscLicense"),
|
||||
atscLicenseData);
|
||||
EXPECT_TRUE(!ret.isOk());
|
||||
|
||||
ret = plugin3->closeSession(sessionId);
|
||||
EXPECT_TRUE(ret.isOk());
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
} // namespace drm
|
||||
} // namespace hardware
|
||||
|
||||
Reference in New Issue
Block a user