Merge "Filter out key set IDs based on ATSC mode." into udc-widevine-dev
This commit is contained in:
@@ -162,6 +162,18 @@ bool isCsrAccessAllowed() {
|
|||||||
return (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL);
|
return (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsAtscKeySetId(const CdmKeySetId& keySetId) {
|
||||||
|
if (keySetId.empty()) return false;
|
||||||
|
// Pre-installed licenses might not perfectly match ATSC_KEY_SET_ID_PREFIX.
|
||||||
|
// If "atsc" is in the license name, then it is safe to assume
|
||||||
|
// it is an ATSC license.
|
||||||
|
return keySetId.find("atsc") != std::string::npos ||
|
||||||
|
keySetId.find("ATSC") != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNotAtscKeySetId(const CdmKeySetId& keySetId) {
|
||||||
|
return !IsAtscKeySetId(keySetId);
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WVDrmPlugin::WVDrmPlugin(const android::sp<WvContentDecryptionModule>& cdm,
|
WVDrmPlugin::WVDrmPlugin(const android::sp<WvContentDecryptionModule>& cdm,
|
||||||
@@ -949,39 +961,53 @@ Status WVDrmPlugin::unprovisionDevice() {
|
|||||||
|
|
||||||
::ndk::ScopedAStatus WVDrmPlugin::getOfflineLicenseKeySetIds(
|
::ndk::ScopedAStatus WVDrmPlugin::getOfflineLicenseKeySetIds(
|
||||||
vector<::aidl::android::hardware::drm::KeySetId>* _aidl_return) {
|
vector<::aidl::android::hardware::drm::KeySetId>* _aidl_return) {
|
||||||
vector<vector<uint8_t>> keySetIds;
|
_aidl_return->clear();
|
||||||
vector<KeySetId> keySetIdsVec;
|
|
||||||
|
|
||||||
CdmIdentifier identifier;
|
CdmIdentifier identifier;
|
||||||
auto status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
|
const auto status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
|
||||||
if (status != Status::OK) {
|
if (status != Status::OK) {
|
||||||
*_aidl_return = keySetIdsVec;
|
|
||||||
return toNdkScopedAStatus(status);
|
return toNdkScopedAStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<CdmSecurityLevel> levels = {wvcdm::kSecurityLevelL1,
|
const std::vector<CdmSecurityLevel> levels = {wvcdm::kSecurityLevelL1,
|
||||||
wvcdm::kSecurityLevelL3};
|
wvcdm::kSecurityLevelL3};
|
||||||
|
|
||||||
|
std::vector<CdmKeySetId> allKeySetIds;
|
||||||
CdmResponseType res(wvcdm::UNKNOWN_ERROR);
|
CdmResponseType res(wvcdm::UNKNOWN_ERROR);
|
||||||
|
bool success = false;
|
||||||
for (auto level : levels) {
|
for (auto level : levels) {
|
||||||
vector<CdmKeySetId> cdmKeySetIds;
|
std::vector<CdmKeySetId> levelKeySetIds;
|
||||||
res = mCDM->ListStoredLicenses(level, identifier, &cdmKeySetIds);
|
res = mCDM->ListStoredLicenses(level, identifier, &levelKeySetIds);
|
||||||
|
|
||||||
if (isCdmResponseTypeSuccess(res)) {
|
if (!isCdmResponseTypeSuccess(res)) continue;
|
||||||
keySetIds.clear();
|
success = true;
|
||||||
for (auto id : cdmKeySetIds) {
|
if (levelKeySetIds.empty()) continue;
|
||||||
keySetIds.push_back(StrToVector(id));
|
if (allKeySetIds.empty()) {
|
||||||
}
|
allKeySetIds = std::move(levelKeySetIds);
|
||||||
KeySetId kid;
|
} else {
|
||||||
for (auto id : keySetIds) {
|
allKeySetIds.reserve(allKeySetIds.size() + levelKeySetIds.size());
|
||||||
kid.keySetId = id;
|
for (CdmKeySetId& keySetId : levelKeySetIds) {
|
||||||
keySetIdsVec.push_back(kid);
|
allKeySetIds.push_back(std::move(keySetId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*_aidl_return = keySetIdsVec;
|
|
||||||
return toNdkScopedAStatus(mapCdmResponseType(res));
|
if (!success) {
|
||||||
|
// Return whatever the last error was.
|
||||||
|
return toNdkScopedAStatus(mapCdmResponseType(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out key sets based on ATSC mode.
|
||||||
|
const auto isAllowedKeySetId =
|
||||||
|
mPropertySet.use_atsc_mode() ? IsAtscKeySetId : IsNotAtscKeySetId;
|
||||||
|
std::vector<KeySetId> keySetIds;
|
||||||
|
for (const CdmKeySetId& keySetId : allKeySetIds) {
|
||||||
|
if (isAllowedKeySetId(keySetId)) {
|
||||||
|
keySetIds.push_back(KeySetId{StrToVector(keySetId)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*_aidl_return = std::move(keySetIds);
|
||||||
|
return toNdkScopedAStatus(mapCdmResponseType(wvcdm::NO_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
::ndk::ScopedAStatus WVDrmPlugin::getOfflineLicenseState(
|
::ndk::ScopedAStatus WVDrmPlugin::getOfflineLicenseState(
|
||||||
|
|||||||
@@ -2853,49 +2853,90 @@ TEST_F(WVDrmPluginHalTest, DoesNotSetDecryptHashProperties) {
|
|||||||
EXPECT_TRUE(ret.isOk());
|
EXPECT_TRUE(ret.isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WVDrmPluginHalTest, GetOfflineLicenseIds) {
|
TEST_F(WVDrmPluginHalTest, GetOfflineLicenseKeySetIds_NonAtscMode) {
|
||||||
const uint32_t kLicenseCount = 5;
|
const std::vector<CdmKeySetId> cdmKeySetIdsL1 = {
|
||||||
|
// Non-ATSC key set IDs
|
||||||
|
"ksid1111", "ksid2222", "ksid3333", "ksid4444",
|
||||||
|
// ATSC key set IDs.
|
||||||
|
"atscksid1111", "atscksid2222", "atscksid3333", "atsc_group1_profile1",
|
||||||
|
"atsc_group1_profile7"};
|
||||||
|
const std::vector<CdmKeySetId> cdmKeySetIdsL3 = {
|
||||||
|
// Non-ATSC key set IDs
|
||||||
|
"ksid5555", "ksid6666", "ksid7777", "ksid8888",
|
||||||
|
// ATSC key set IDs.
|
||||||
|
"atscksid5555", "atscksid6666", "atscksid7777", "atsc_group3_profile1",
|
||||||
|
"atsc_group3_profile7"};
|
||||||
|
// Expect non-ATSC key set IDs (order is important).
|
||||||
|
const std::vector<CdmKeySetId> expectedCdmKeySetIds = {
|
||||||
|
// From L1
|
||||||
|
"ksid1111", "ksid2222", "ksid3333", "ksid4444",
|
||||||
|
// From L3
|
||||||
|
"ksid5555", "ksid6666", "ksid7777", "ksid8888"};
|
||||||
|
|
||||||
uint8_t mockIdsRaw[kLicenseCount * 2][kKeySetIdSize];
|
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL1, _, NotNull()))
|
||||||
FILE *fp = fopen("/dev/urandom", "r");
|
.WillOnce(DoAll(SetArgPointee<2>(cdmKeySetIdsL1),
|
||||||
ASSERT_NE(fp, nullptr) << "Failed to open /dev/urandom";
|
|
||||||
for (uint32_t i = 0; i < kLicenseCount * 2; ++i) {
|
|
||||||
fread(mockIdsRaw[i], sizeof(uint8_t), kKeySetIdSize, fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
std::vector<std::string> mockIdsL1;
|
|
||||||
for (uint32_t i = 0; i < kLicenseCount; ++i) {
|
|
||||||
mockIdsL1.push_back(
|
|
||||||
std::string(mockIdsRaw[i], mockIdsRaw[i] + kKeySetIdSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> mockIdsL3;
|
|
||||||
for (uint32_t i = 0; i < kLicenseCount; ++i) {
|
|
||||||
mockIdsL3.push_back(
|
|
||||||
std::string(mockIdsRaw[i + 5], mockIdsRaw[i + 5] + kKeySetIdSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_CALL(*mCdm,
|
|
||||||
ListStoredLicenses(kSecurityLevelL1, HasOrigin(EMPTY_ORIGIN), _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<2>(mockIdsL1),
|
|
||||||
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||||
|
|
||||||
EXPECT_CALL(*mCdm,
|
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL3, _, NotNull()))
|
||||||
ListStoredLicenses(kSecurityLevelL3, HasOrigin(EMPTY_ORIGIN), _))
|
.WillOnce(DoAll(SetArgPointee<2>(cdmKeySetIdsL3),
|
||||||
.WillOnce(DoAll(SetArgPointee<2>(mockIdsL3),
|
|
||||||
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||||
|
|
||||||
std::vector<KeySetId> offlineIds;
|
std::vector<KeySetId> offlineKeySetIds;
|
||||||
auto ret = mPlugin->getOfflineLicenseKeySetIds(&offlineIds);
|
const auto ret = mPlugin->getOfflineLicenseKeySetIds(&offlineKeySetIds);
|
||||||
EXPECT_TRUE(ret.isOk());
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
std::vector<CdmKeySetId> offlineCdmKeySetIds;
|
||||||
size_t index = 0;
|
for (const auto &keySetId : offlineKeySetIds) {
|
||||||
for (auto id : offlineIds) {
|
offlineCdmKeySetIds.emplace_back(keySetId.keySetId.begin(),
|
||||||
EXPECT_THAT(id.keySetId,
|
keySetId.keySetId.end());
|
||||||
ElementsAreArray(mockIdsRaw[index++], kKeySetIdSize));
|
|
||||||
}
|
}
|
||||||
EXPECT_EQ(kLicenseCount * 2, index);
|
|
||||||
|
EXPECT_EQ(expectedCdmKeySetIds.size(), offlineCdmKeySetIds.size());
|
||||||
|
EXPECT_EQ(expectedCdmKeySetIds, offlineCdmKeySetIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WVDrmPluginHalTest, GetOfflineLicenseKeySetIds_AtscMode) {
|
||||||
|
const std::vector<CdmKeySetId> cdmKeySetIdsL1 = {
|
||||||
|
// Non-ATSC key set IDs
|
||||||
|
"ksid1111", "ksid2222", "ksid3333", "ksid4444",
|
||||||
|
// ATSC key set IDs.
|
||||||
|
"atscksid1111", "atscksid2222", "atscksid3333", "atsc_group1_profile1",
|
||||||
|
"atsc_group1_profile7"};
|
||||||
|
const std::vector<CdmKeySetId> cdmKeySetIdsL3 = {
|
||||||
|
// Non-ATSC key set IDs
|
||||||
|
"ksid5555", "ksid6666", "ksid7777", "ksid8888",
|
||||||
|
// ATSC key set IDs.
|
||||||
|
"atscksid5555", "atscksid6666", "atscksid7777", "atsc_group3_profile1",
|
||||||
|
"atsc_group3_profile7"};
|
||||||
|
// Expect ATSC key set IDs (order is important).
|
||||||
|
const std::vector<CdmKeySetId> expectedCdmKeySetIds = {
|
||||||
|
// From L1
|
||||||
|
"atscksid1111", "atscksid2222", "atscksid3333", "atsc_group1_profile1",
|
||||||
|
"atsc_group1_profile7",
|
||||||
|
// From L3
|
||||||
|
"atscksid5555", "atscksid6666", "atscksid7777", "atsc_group3_profile1",
|
||||||
|
"atsc_group3_profile7"};
|
||||||
|
|
||||||
|
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL1, _, NotNull()))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<2>(cdmKeySetIdsL1),
|
||||||
|
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||||
|
|
||||||
|
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL3, _, NotNull()))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<2>(cdmKeySetIdsL3),
|
||||||
|
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||||
|
|
||||||
|
mPlugin->setPropertyString("atscMode", "enable");
|
||||||
|
|
||||||
|
std::vector<KeySetId> offlineKeySetIds;
|
||||||
|
const auto ret = mPlugin->getOfflineLicenseKeySetIds(&offlineKeySetIds);
|
||||||
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
std::vector<CdmKeySetId> offlineCdmKeySetIds;
|
||||||
|
for (const auto &keySetId : offlineKeySetIds) {
|
||||||
|
offlineCdmKeySetIds.emplace_back(keySetId.keySetId.begin(),
|
||||||
|
keySetId.keySetId.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(expectedCdmKeySetIds.size(), offlineCdmKeySetIds.size());
|
||||||
|
EXPECT_EQ(expectedCdmKeySetIds, offlineCdmKeySetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WVDrmPluginHalTest, GetOfflineLicenseState) {
|
TEST_F(WVDrmPluginHalTest, GetOfflineLicenseState) {
|
||||||
|
|||||||
Reference in New Issue
Block a user