Secure stop API related changes

[ Merge of http://go/wvgerrit/44921 ]

* Added the ability to remove a single usage information record.
* Added a method to retrieve all secure stop Ids.

Bug: 69674645
Test: WV unit, integration tests
Change-Id: I04ac8224b4bdda69541e61ff1103af3836138228
This commit is contained in:
Rahul Frias
2018-03-09 00:04:30 -08:00
parent 1d9a16c3b9
commit 4ba82e4585
9 changed files with 700 additions and 28 deletions

View File

@@ -188,11 +188,13 @@ class CdmEngine {
virtual CdmResponseType ListStoredLicenses(
CdmSecurityLevel security_level, std::vector<std::string>* key_set_ids);
// Return the list of key_set_ids stored as usage records on the
// current (origin-specific) file system.
virtual CdmResponseType ListUsageRecords(
// Return the list of IDs associated with usage records for the
// current (origin-specific) file system. At least one parameter
// |ksids| or |provider_session_tokens| needs to be supplied.
virtual CdmResponseType ListUsageIds(
const std::string& app_id, CdmSecurityLevel security_level,
std::vector<std::string>* ksids);
std::vector<std::string>* ksids,
std::vector<std::string>* provider_session_tokens);
// Delete the usage record for the given key_set_id. This removes the
// usage record in the file system and the OEMCrypto usage record.
@@ -220,6 +222,10 @@ class CdmEngine {
// security levels.
virtual CdmResponseType RemoveAllUsageInfo(const std::string& app_id);
virtual CdmResponseType RemoveUsageInfo(
const std::string& app_id,
const CdmSecureStopId& secure_stop_id);
virtual CdmResponseType ReleaseUsageInfo(
const CdmUsageInfoReleaseMessage& message);
virtual CdmResponseType LoadUsageSession(const CdmKeySetId& key_set_id,

View File

@@ -105,9 +105,13 @@ class DeviceFiles {
const CdmUsageEntry& usage_entry,
uint32_t usage_entry_number);
// Extract KSIDs from usage information on the file system.
virtual bool ListUsageRecords(const std::string& app_id,
std::vector<std::string>* ksids);
// Retrieve usage identifying information stored on the file system.
// The caller needs to specify at least one of |ksids| or
// |provider_session_tokens|
virtual bool ListUsageIds(
const std::string& app_id,
std::vector<std::string>* ksids,
std::vector<std::string>* provider_session_tokens);
// Get the provider session token for the given key_set_id.
virtual bool GetProviderSessionToken(const std::string& app_id,

View File

@@ -929,20 +929,22 @@ CdmResponseType CdmEngine::ListStoredLicenses(
return NO_ERROR;
}
CdmResponseType CdmEngine::ListUsageRecords(const std::string& app_id,
CdmResponseType CdmEngine::ListUsageIds(
const std::string& app_id,
CdmSecurityLevel security_level,
std::vector<std::string>* ksids) {
std::vector<std::string>* ksids,
std::vector<std::string>* provider_session_tokens) {
DeviceFiles handle(file_system_);
if (!ksids) {
LOGE("CdmEngine::ListUsageRecords: no response destination");
if (!ksids && !provider_session_tokens) {
LOGE("CdmEngine::ListUsageIds: no response destination");
return INVALID_PARAMETERS_ENG_23;
}
if (!handle.Init(security_level)) {
LOGE("CdmEngine::ListUsageRecords: unable to initialize device files");
LOGE("CdmEngine::ListUsageIds: unable to initialize device files");
return LIST_USAGE_ERROR_1;
}
if (!handle.ListUsageRecords(app_id, ksids)) {
LOGE("CdmEngine::ListUsageRecords: ListUsageRecords call failed");
if (!handle.ListUsageIds(app_id, ksids, provider_session_tokens)) {
LOGE("CdmEngine::ListUsageIds: ListUsageIds call failed");
return LIST_USAGE_ERROR_2;
}
return NO_ERROR;
@@ -1272,6 +1274,85 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(const std::string& app_id) {
return status;
}
CdmResponseType CdmEngine::RemoveUsageInfo(
const std::string& app_id,
const CdmSecureStopId& provider_session_token) {
if (NULL == usage_property_set_.get()) {
usage_property_set_.reset(new UsagePropertySet());
}
usage_property_set_->set_app_id(app_id);
CdmResponseType status = NO_ERROR;
for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) {
DeviceFiles handle(file_system_);
if (handle.Init(static_cast<CdmSecurityLevel>(j))) {
SecurityLevel security_level =
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
? kLevel3
: kLevelDefault;
usage_property_set_->set_security_level(security_level);
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
usage_session_->Init(usage_property_set_.get());
std::vector<DeviceFiles::CdmUsageData> usage_data;
CdmKeyMessage license_request;
CdmKeyResponse license_response;
CdmUsageEntry usage_entry;
uint32_t usage_entry_number;
if (!handle.RetrieveUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id), provider_session_token,
&license_request, &license_response, &usage_entry,
&usage_entry_number)) {
// Try other security level
continue;
}
switch (usage_session_->get_usage_support_type()) {
case kUsageEntrySupport: {
status = usage_session_->DeleteUsageEntry(
usage_data[0].usage_entry_number);
if (!handle.DeleteUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
provider_session_token)) {
status = REMOVE_USAGE_INFO_ERROR_1;
}
usage_session_.reset(NULL);
return status;
}
case kUsageTableSupport: {
std::vector<std::string> provider_session_tokens;
handle.DeleteUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
provider_session_token);
scoped_ptr<CryptoSession> crypto_session(
new CryptoSession(metrics_.GetCryptoMetrics()));
status = crypto_session->Open(
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
? kLevel3 : kLevelDefault);
if (status == NO_ERROR) {
crypto_session->UpdateUsageInformation();
status =
crypto_session->DeleteUsageInformation(provider_session_token);
crypto_session->UpdateUsageInformation();
}
return status;
}
default:
// Ignore
break;
}
} else {
LOGE("CdmEngine::RemoveUsageInfo: failed to initialize L%d devicefiles",
j);
status = REMOVE_USAGE_INFO_ERROR_2;
}
}
usage_session_.reset(NULL);
return REMOVE_USAGE_INFO_ERROR_3;
}
CdmResponseType CdmEngine::ReleaseUsageInfo(
const CdmUsageInfoReleaseMessage& message) {
if (NULL == usage_session_.get()) {

View File

@@ -868,10 +868,22 @@ void CdmSession::GetApplicationId(std::string* app_id) {
CdmResponseType CdmSession::DeleteMultipleUsageInformation(
const std::vector<std::string>& provider_session_tokens) {
CdmResponseType sts = crypto_session_->DeleteMultipleUsageInformation(
CdmUsageSupportType usage_support_type;
CdmResponseType sts =
crypto_session_->GetUsageSupportType(&usage_support_type);
if (sts == NO_ERROR && usage_support_type == kUsageTableSupport) {
for (size_t i = 0; i < provider_session_tokens.size(); ++i) {
crypto_session_->DeactivateUsageInformation(provider_session_tokens[i]);
UpdateUsageTableInformation();
}
}
if (sts == NO_ERROR) {
sts = crypto_session_->DeleteMultipleUsageInformation(
provider_session_tokens);
crypto_metrics_->crypto_session_delete_multiple_usage_information_
.Increment(sts);
}
return sts;
}

View File

@@ -464,22 +464,25 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
return StoreFileWithHash(usage_info_file_name, serialized_file);
}
bool DeviceFiles::ListUsageRecords(const std::string& app_id,
std::vector<std::string>* ksids) {
bool DeviceFiles::ListUsageIds(
const std::string& app_id,
std::vector<std::string>* ksids,
std::vector<std::string>* provider_session_tokens) {
if (!initialized_) {
LOGW("DeviceFiles::ListUsageRecords: not initialized");
LOGW("DeviceFiles::ListUsageIds: not initialized");
return false;
}
if (ksids == NULL) {
LOGW("DeviceFiles::ListUsageRecords: return parameter not provided");
if (ksids == NULL && provider_session_tokens == NULL) {
LOGW("DeviceFiles::ListUsageIds: ksids or pst parameter not provided");
return false;
}
// Empty or non-existent file == no usage records.
std::string file_name = GetUsageInfoFileName(app_id);
if (!FileExists(file_name) || GetFileSize(file_name) == 0) {
ksids->clear();
if (ksids != NULL) ksids->clear();
if (provider_session_tokens != NULL) provider_session_tokens->clear();
return true;
}
@@ -489,13 +492,19 @@ bool DeviceFiles::ListUsageRecords(const std::string& app_id,
return false;
}
ksids->clear();
if (ksids != NULL) ksids->clear();
if (provider_session_tokens != NULL) provider_session_tokens->clear();
size_t num_records = file.usage_info().sessions_size();
for (size_t i = 0; i < num_records; ++i) {
if (!file.usage_info().sessions(i).key_set_id().empty()) {
if ((ksids != NULL) &&
!file.usage_info().sessions(i).key_set_id().empty()) {
ksids->push_back(file.usage_info().sessions(i).key_set_id());
}
if ((provider_session_tokens != NULL) &&
!file.usage_info().sessions(i).token().empty()) {
provider_session_tokens->push_back(file.usage_info().sessions(i).token());
}
}
return true;
}

View File

@@ -2629,6 +2629,73 @@ TEST_F(DeviceFilesUsageInfoTest, ListNullParam) {
EXPECT_FALSE(device_files.ListUsageInfoFiles(NULL));
}
TEST_F(DeviceFilesUsageInfoTest, ListIdsNull) {
MockFileSystem file_system;
MockFile file;
std::string app_id = kUsageInfoTestData[0].app_id;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
EXPECT_FALSE(device_files.ListUsageIds(app_id, NULL, NULL));
}
TEST_F(DeviceFilesUsageInfoTest, ListUsageIds) {
MockFileSystem file_system;
MockFile file;
int index = 8;
std::string app_id = kUsageInfoTestData[index].app_id;
std::string file_name = DeviceFiles::GetUsageInfoFileName(app_id);
std::string path = device_base_path_ + file_name;
std::string file_data = (index < 0) ? kEmptyUsageInfoFileData
: kUsageInfoTestData[index].file_data;
if (index >= 0) {
EXPECT_CALL(file_system, Exists(StrEq(path)))
.Times(2)
.WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path)))
.Times(2)
.WillRepeatedly(Return(kUsageInfoTestData[index].file_data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file,
Read(NotNull(), Eq(kUsageInfoTestData[index].file_data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
Return(file_data.size())));
EXPECT_CALL(file, Close());
}
else {
EXPECT_CALL(file_system, Exists(StrEq(path)))
.WillOnce(Return(false));
}
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
std::vector<std::string> key_set_ids;
std::vector<std::string> provider_session_tokens;
EXPECT_TRUE(device_files.ListUsageIds(
app_id, &key_set_ids, &provider_session_tokens));
EXPECT_EQ(key_set_ids.size(), provider_session_tokens.size());
if (index >= 0) {
for (size_t i = 0; i < provider_session_tokens.size(); ++i) {
bool found = false;
for (int j = 0; !found && j <= index; ++j) {
if (app_id == kUsageInfoTestData[j].app_id &&
kUsageInfoTestData[j].usage_data.provider_session_token ==
provider_session_tokens[i] &&
kUsageInfoTestData[j].usage_data.key_set_id ==
key_set_ids[i]) {
found = true;
}
}
EXPECT_TRUE(found);
}
}
}
TEST_P(DeviceFilesUsageInfoListTest, UsageInfoList) {
MockFileSystem file_system;
MockFile file;
@@ -2767,6 +2834,113 @@ TEST_P(DeviceFilesUsageInfoTest, Retrieve) {
}
}
TEST_P(DeviceFilesUsageInfoTest, ListKeySetIds) {
MockFileSystem file_system;
MockFile file;
int index = GetParam();
std::string app_id;
if (index >= 0) app_id = kUsageInfoTestData[index].app_id;
std::string file_name = DeviceFiles::GetUsageInfoFileName(app_id);
std::string path = device_base_path_ + file_name;
std::string file_data = (index < 0) ? kEmptyUsageInfoFileData
: kUsageInfoTestData[index].file_data;
if (index >= 0) {
EXPECT_CALL(file_system, Exists(StrEq(path)))
.Times(2)
.WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path)))
.Times(2)
.WillRepeatedly(Return(kUsageInfoTestData[index].file_data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file,
Read(NotNull(), Eq(kUsageInfoTestData[index].file_data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
Return(file_data.size())));
EXPECT_CALL(file, Close());
}
else {
EXPECT_CALL(file_system, Exists(StrEq(path)))
.WillOnce(Return(false));
}
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
std::vector<std::string> key_set_ids;
EXPECT_TRUE(device_files.ListUsageIds(app_id, &key_set_ids, NULL));
if (index >= 0) {
for (size_t i = 0; i < key_set_ids.size(); ++i) {
bool found = false;
for (int j = 0; !found && j <= index; ++j) {
if (app_id == kUsageInfoTestData[j].app_id &&
kUsageInfoTestData[j].usage_data.key_set_id ==
key_set_ids[i]) {
found = true;
}
}
EXPECT_TRUE(found);
}
}
}
TEST_P(DeviceFilesUsageInfoTest, ListProviderSessionTokenIds) {
MockFileSystem file_system;
MockFile file;
int index = GetParam();
std::string app_id;
if (index >= 0) app_id = kUsageInfoTestData[index].app_id;
std::string file_name = DeviceFiles::GetUsageInfoFileName(app_id);
std::string path = device_base_path_ + file_name;
std::string file_data = (index < 0) ? kEmptyUsageInfoFileData
: kUsageInfoTestData[index].file_data;
if (index >= 0) {
EXPECT_CALL(file_system, Exists(StrEq(path)))
.Times(2)
.WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path)))
.Times(2)
.WillRepeatedly(Return(kUsageInfoTestData[index].file_data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file,
Read(NotNull(), Eq(kUsageInfoTestData[index].file_data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
Return(file_data.size())));
EXPECT_CALL(file, Close());
}
else {
EXPECT_CALL(file_system, Exists(StrEq(path)))
.WillOnce(Return(false));
}
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
std::vector<std::string> provider_session_tokens;
EXPECT_TRUE(
device_files.ListUsageIds(app_id, NULL, &provider_session_tokens));
if (index >= 0) {
for (size_t i = 0; i < provider_session_tokens.size(); ++i) {
bool found = false;
for (int j = 0; !found && j <= index; ++j) {
if (app_id == kUsageInfoTestData[j].app_id &&
kUsageInfoTestData[j].usage_data.provider_session_token ==
provider_session_tokens[i]) {
found = true;
}
}
EXPECT_TRUE(found);
}
}
}
TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) {
MockFileSystem file_system;
MockFile file;

View File

@@ -107,10 +107,18 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
CdmUsageInfo* usage_info);
virtual CdmResponseType RemoveAllUsageInfo(const std::string& app_id,
const CdmIdentifier& identifier);
virtual CdmResponseType RemoveUsageInfo(
const std::string& app_id,
const CdmIdentifier& identifier,
const CdmSecureStopId& secure_stop_id);
virtual CdmResponseType ReleaseUsageInfo(
const CdmUsageInfoReleaseMessage& message,
const CdmIdentifier& identifier);
virtual CdmResponseType GetSecureStopIds(const std::string& app_id,
const CdmIdentifier& identifier,
std::vector<CdmSecureStopId>* ssids);
// Accept encrypted buffer and decrypt data.
// Decryption parameters that need to be specified are
// is_encrypted, is_secure, key_id, encrypt_buffer, encrypt_length,

View File

@@ -305,6 +305,16 @@ CdmResponseType WvContentDecryptionModule::RemoveAllUsageInfo(
return sts;
}
CdmResponseType WvContentDecryptionModule::RemoveUsageInfo(
const std::string& app_id,
const CdmIdentifier& identifier,
const CdmSecureStopId& secure_stop_id) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts = cdm_engine->RemoveUsageInfo(app_id, secure_stop_id);
cdm_engine->GetMetrics()->cdm_engine_remove_usage_info_.Increment(sts);
return sts;
}
CdmResponseType WvContentDecryptionModule::ReleaseUsageInfo(
const CdmUsageInfoReleaseMessage& message,
const CdmIdentifier& identifier) {
@@ -314,6 +324,27 @@ CdmResponseType WvContentDecryptionModule::ReleaseUsageInfo(
return sts;
}
CdmResponseType WvContentDecryptionModule::GetSecureStopIds(
const std::string& app_id,
const CdmIdentifier& identifier,
std::vector<CdmSecureStopId>* ssids) {
if (ssids == NULL) {
LOGE("WvContentDecryptionModule::Decrypt: ssid destination not provided");
return PARAMETER_NULL;
}
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts = cdm_engine->ListUsageIds(app_id, kSecurityLevelL1,
NULL, ssids);
std::vector<CdmSecureStopId> secure_stop_ids;
CdmResponseType sts_l3 = cdm_engine->ListUsageIds(app_id, kSecurityLevelL3,
NULL, &secure_stop_ids);
ssids->insert(ssids->end(), secure_stop_ids.begin(), secure_stop_ids.end());
if (sts_l3 != NO_ERROR) sts = sts_l3;
cdm_engine->GetMetrics()->cdm_engine_get_secure_stop_ids_.Increment(sts);
return sts;
}
CdmResponseType WvContentDecryptionModule::Decrypt(
const CdmSessionId& session_id,
bool validate_key_id,

View File

@@ -37,6 +37,7 @@ using ::testing::IsEmpty;
using ::testing::Not;
using ::testing::Pair;
using ::testing::StrictMock;
using ::testing::UnorderedElementsAreArray;
namespace {
@@ -418,6 +419,55 @@ UsageInfoSubSampleInfo usage_info_sub_sample_info[] = {
{&usage_info_sub_samples_icp[0], 5, wvcdm::kLevel3, ""},
{&usage_info_sub_samples_icp[0], 3, wvcdm::kLevel3, "other app id"}};
struct UsageLicenseAndSubSampleInfo {
std::string pssh;
SubSampleInfo* sub_sample;
std::string provider_session_token;
};
std::string kPsshStreamingClip3 = wvcdm::a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
"08011a0d7769646576696e655f74657374220f73" // pssh data
"747265616d696e675f636c697033");
std::string kPsshStreamingClip4 = wvcdm::a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
"08011a0d7769646576696e655f74657374220f73" // pssh data
"747265616d696e675f636c697034");
std::string kPsshStreamingClip5 = wvcdm::a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
"08011a0d7769646576696e655f74657374220f73" // pssh data
"747265616d696e675f636c697035");
std::string kPsshStreamingClip7 = wvcdm::a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
"08011a0d7769646576696e655f74657374220f73" // pssh data
"747265616d696e675f636c697037");
std::string kProviderSessionTokenStreamingClip3 = wvcdm::a2bs_hex(
"4851305A4A4156485A554936444E4931");
std::string kProviderSessionTokenStreamingClip4 = wvcdm::a2bs_hex(
"4942524F4355544E5557553145463243");
std::string kProviderSessionTokenStreamingClip7 = wvcdm::a2bs_hex(
"44434C53524F4E30394C4E5535544B4C");
UsageLicenseAndSubSampleInfo kUsageLicenseTestVector1[] = {
{ kPsshStreamingClip3, &usage_info_sub_samples_icp[0],
kProviderSessionTokenStreamingClip3 },
{ kPsshStreamingClip4, &usage_info_sub_samples_icp[1],
kProviderSessionTokenStreamingClip4 },
};
UsageLicenseAndSubSampleInfo kUsageLicenseTestVector2[] = {
{ kPsshStreamingClip7, &usage_info_sub_samples_icp[4],
kProviderSessionTokenStreamingClip7 },
// TODO(rfrias): Add another streaming usage license. Streaming
// clip 5 has includes a randomly generated PST, while
// streaming clip 6 does not include a PST.
};
struct RenewWithClientIdTestConfiguration {
bool always_include_client_id;
bool specify_app_parameters;
@@ -1273,6 +1323,18 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
CdmAppParameterMap& app_parameters,
CdmLicenseType license_type,
CdmClientPropertySet* property_set) {
GenerateKeyRequest(expected_response, init_data_type, init_data,
app_parameters, license_type, kDefaultCdmIdentifier,
property_set);
}
void GenerateKeyRequest(CdmResponseType expected_response,
const std::string& init_data_type,
const std::string& init_data,
CdmAppParameterMap& app_parameters,
CdmLicenseType license_type,
const CdmIdentifier& cdm_identifier,
CdmClientPropertySet* property_set) {
CdmKeyRequest key_request;
std::string key_set_id;
license_type_ = license_type;
@@ -1280,7 +1342,7 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
decryptor_.GenerateKeyRequest(
session_id_, key_set_id, init_data_type, init_data,
license_type, app_parameters, property_set,
kDefaultCdmIdentifier, &key_request));
cdm_identifier, &key_request));
key_msg_ = key_request.message;
EXPECT_EQ(0u, key_request.url.size());
}
@@ -3054,6 +3116,291 @@ TEST_F(WvCdmRequestLicenseTest, UsageRemoveAllTest) {
EXPECT_TRUE(usage_info.empty());
}
TEST_F(WvCdmRequestLicenseTest, GetSecureStopIdsTest) {
Unprovision();
std::string app_id_empty = "";
TestWvCdmClientPropertySet property_set;
Provision(kLevelDefault);
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
FileSystem file_system;
DeviceFiles handle(&file_system);
EXPECT_TRUE(handle.Init(security_level));
std::vector<std::string> psts;
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(""), &psts));
std::vector<CdmSecureStopId> retrieved_secure_stop_ids;
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(app_id_empty, kDefaultCdmIdentifier,
&retrieved_secure_stop_ids));
EXPECT_TRUE(retrieved_secure_stop_ids.empty());
// First fetch licenses for the default app
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector1); ++i) {
SubSampleInfo* data = kUsageLicenseTestVector1[i].sub_sample;
property_set.set_app_id(app_id_empty);
decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
NULL, &session_id_);
GenerateKeyRequest(kUsageLicenseTestVector1[i].pssh, kLicenseTypeStreaming,
&property_set);
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
&data->iv, data->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = data->is_encrypted;
decryption_parameters.is_secure = data->is_secure;
decryption_parameters.subsample_flags = data->subsample_flags;
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
decryption_parameters));
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
decrypt_buffer.begin()));
decryptor_.CloseSession(session_id_);
}
// Provision the other identifier
Provision(kExampleIdentifier, kLevelDefault);
// Verify that there are usage records for the default identifier but
// none yet for the non-default one
std::vector<CdmSecureStopId> expected_provider_session_tokens;
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector1); ++i) {
expected_provider_session_tokens.push_back(
kUsageLicenseTestVector1[i].provider_session_token);
}
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(app_id_empty, kDefaultCdmIdentifier,
&retrieved_secure_stop_ids));
EXPECT_EQ(N_ELEM(kUsageLicenseTestVector1), retrieved_secure_stop_ids.size());
EXPECT_THAT(retrieved_secure_stop_ids,
UnorderedElementsAreArray(expected_provider_session_tokens));
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kExampleIdentifier.app_package_name,
kDefaultCdmIdentifier,
&retrieved_secure_stop_ids));
EXPECT_TRUE(retrieved_secure_stop_ids.empty());
// Now fetch licenses for the other identifier
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector2); ++i) {
SubSampleInfo* data = kUsageLicenseTestVector2[i].sub_sample;
property_set.set_app_id(kExampleIdentifier.app_package_name);
EXPECT_EQ(NO_ERROR,
decryptor_.OpenSession(g_key_system, &property_set,
kExampleIdentifier, NULL,
&session_id_));
std::string init_data_type = "video/mp4";
CdmAppParameterMap app_parameters;
GenerateKeyRequest(wvcdm::KEY_MESSAGE, init_data_type,
kUsageLicenseTestVector2[i].pssh, app_parameters,
kLicenseTypeStreaming, kExampleIdentifier,
&property_set);
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
&data->iv, data->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = data->is_encrypted;
decryption_parameters.is_secure = data->is_secure;
decryption_parameters.subsample_flags = data->subsample_flags;
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
decryption_parameters));
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
decrypt_buffer.begin()));
decryptor_.CloseSession(session_id_);
}
// Verify that there are usage records for both the default and
// non-default identifier.
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kDefaultCdmIdentifier.app_package_name,
kDefaultCdmIdentifier,
&retrieved_secure_stop_ids));
EXPECT_EQ(N_ELEM(kUsageLicenseTestVector1), retrieved_secure_stop_ids.size());
EXPECT_THAT(retrieved_secure_stop_ids,
UnorderedElementsAreArray(expected_provider_session_tokens));
retrieved_secure_stop_ids.clear();
expected_provider_session_tokens.clear();
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector2); ++i) {
expected_provider_session_tokens.push_back(
kUsageLicenseTestVector2[i].provider_session_token);
}
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kExampleIdentifier.app_package_name,
kExampleIdentifier,
&retrieved_secure_stop_ids));
EXPECT_EQ(N_ELEM(kUsageLicenseTestVector2), retrieved_secure_stop_ids.size());
EXPECT_THAT(retrieved_secure_stop_ids,
UnorderedElementsAreArray(expected_provider_session_tokens));
EXPECT_EQ(
NO_ERROR,
decryptor_.RemoveAllUsageInfo(kDefaultCdmIdentifier.app_package_name,
kDefaultCdmIdentifier));
EXPECT_EQ(
NO_ERROR,
decryptor_.RemoveAllUsageInfo(kExampleIdentifier.app_package_name,
kExampleIdentifier));
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kDefaultCdmIdentifier.app_package_name,
kDefaultCdmIdentifier,
&retrieved_secure_stop_ids));
EXPECT_TRUE(retrieved_secure_stop_ids.empty());
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kExampleIdentifier.app_package_name,
kExampleIdentifier,
&retrieved_secure_stop_ids));
EXPECT_TRUE(retrieved_secure_stop_ids.empty());
}
TEST_F(WvCdmRequestLicenseTest, UsageRemoveSecureStopTest) {
Unprovision();
std::string app_id_empty = "";
TestWvCdmClientPropertySet property_set;
Provision(kLevelDefault);
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
FileSystem file_system;
DeviceFiles handle(&file_system);
EXPECT_TRUE(handle.Init(security_level));
std::vector<std::string> psts;
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(""), &psts));
// First fetch licenses for the default app
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector1); ++i) {
SubSampleInfo* data = kUsageLicenseTestVector1[i].sub_sample;
property_set.set_app_id(app_id_empty);
decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
NULL, &session_id_);
GenerateKeyRequest(kUsageLicenseTestVector1[i].pssh, kLicenseTypeStreaming,
&property_set);
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
&data->iv, data->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = data->is_encrypted;
decryption_parameters.is_secure = data->is_secure;
decryption_parameters.subsample_flags = data->subsample_flags;
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
decryption_parameters));
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
decrypt_buffer.begin()));
decryptor_.CloseSession(session_id_);
}
// Provision and fetch licenses for the other identifier
Provision(kExampleIdentifier, kLevelDefault);
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector2); ++i) {
SubSampleInfo* data = kUsageLicenseTestVector2[i].sub_sample;
property_set.set_app_id(kExampleIdentifier.app_package_name);
EXPECT_EQ(NO_ERROR,
decryptor_.OpenSession(g_key_system, &property_set,
kExampleIdentifier, NULL,
&session_id_));
std::string init_data_type = "video/mp4";
CdmAppParameterMap app_parameters;
GenerateKeyRequest(wvcdm::KEY_MESSAGE, init_data_type,
kUsageLicenseTestVector2[i].pssh, app_parameters,
kLicenseTypeStreaming, kExampleIdentifier,
&property_set);
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
&data->iv, data->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = data->is_encrypted;
decryption_parameters.is_secure = data->is_secure;
decryption_parameters.subsample_flags = data->subsample_flags;
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
decryption_parameters));
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
decrypt_buffer.begin()));
decryptor_.CloseSession(session_id_);
}
// Release usage records for both the default and non-default identifier.
std::vector<CdmSecureStopId> secure_stop_ids;
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kDefaultCdmIdentifier.app_package_name,
kDefaultCdmIdentifier,
&secure_stop_ids));
EXPECT_EQ(N_ELEM(kUsageLicenseTestVector1), secure_stop_ids.size());
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector1); ++i) {
EXPECT_EQ(
NO_ERROR,
decryptor_.RemoveUsageInfo(kDefaultCdmIdentifier.app_package_name,
kDefaultCdmIdentifier,
secure_stop_ids[i]));
}
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kDefaultCdmIdentifier.app_package_name,
kDefaultCdmIdentifier,
&secure_stop_ids));
EXPECT_TRUE(secure_stop_ids.empty());
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kExampleIdentifier.app_package_name,
kExampleIdentifier,
&secure_stop_ids));
EXPECT_EQ(N_ELEM(kUsageLicenseTestVector2), secure_stop_ids.size());
for (size_t i = 0; i < N_ELEM(kUsageLicenseTestVector2); ++i) {
EXPECT_EQ(
NO_ERROR,
decryptor_.RemoveUsageInfo(kExampleIdentifier.app_package_name,
kExampleIdentifier,
secure_stop_ids[i]));
}
EXPECT_EQ(
NO_ERROR,
decryptor_.GetSecureStopIds(kExampleIdentifier.app_package_name,
kExampleIdentifier,
&secure_stop_ids));
EXPECT_TRUE(secure_stop_ids.empty());
}
TEST_F(WvCdmRequestLicenseTest, QueryUnmodifiedSessionStatus) {
// Test that the global value is returned when no properties are modifying it.
std::string security_level;