Corrections for big usage table support in L3

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

* Corrects usage_table_header lifetime management. Earlier the
  UsageTableHeader class was a singleton tied to the CdmEngine lifetime.
  With SPOIDs there might be multiple concurrent CdmEngine objects.
  The UsageTableHeader class is now associated with OEMCrypto
  lifetime. There are two UsageTableHeader objects one for each L1 and L3.
  These get allocated/deallocated on OEMCrypto Initialization/Termination
  respectively.
* UsageTableHeader requires OEMCrypto, file read/writes and
  metric gathering to perform its required functionality. Because of the
  lifetime changes, CryptoSession, DeviceFiles and MetricsGroup objects
  need to passed to the methods rather than at Creation time.
* Miscellaneous fixes, when moving or deleteing entries.
* Adds usage_table_header_unittests.
* Addresses failures with request_license_test with secure stop in L3.

b/36858906
b/36855557
b/36048120
b/38341136
b/37100505
b/35946047

Test: Verified by unit and integration tests. Added new
      usage_table_header_unittests

Change-Id: I20e396ab2c0afbd14372dd93b969e5b0f1ccd291
This commit is contained in:
Rahul Frias
2017-05-22 13:33:20 -07:00
parent 45c98e47f2
commit 5da8da58f6
18 changed files with 1937 additions and 214 deletions

View File

@@ -1132,7 +1132,8 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
} else {
for (size_t k = 0; k < usage_data.size(); ++k) {
CdmResponseType status2 =
usage_session_->DeleteUsageEntry(usage_data[k]);
usage_session_->DeleteUsageEntry(
usage_data[k].usage_entry_number);
if (status == NO_ERROR && status2 != NO_ERROR)
status = status2;
}

View File

@@ -44,15 +44,6 @@ CdmSession::CdmSession(FileSystem* file_system) :
usage_entry_number_(0),
mock_license_parser_in_use_(false),
mock_policy_engine_in_use_(false) {
CdmResponseType sts =
crypto_session_->GetUsageSupportType(&usage_support_type_);
if (sts != NO_ERROR) {
LOGW("CdmSession::CdmSession: Failed to get usage support type");
}
if (usage_support_type_ == kUsageEntrySupport)
usage_table_header_ = UsageTableHeader::GetInstance(file_system,
crypto_session_.get());
life_span_.Start();
}
@@ -104,6 +95,13 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
return SESSION_FILE_HANDLE_INIT_ERROR;
}
if (crypto_session_->GetUsageSupportType(&usage_support_type_) == NO_ERROR) {
if (usage_support_type_ == kUsageEntrySupport)
usage_table_header_ = crypto_session_->GetUsageTableHeader();
} else {
usage_support_type_ = kNonSecureUsageSupport;
}
// Device Provisioning state is not yet known.
// If not using certificates, then Keybox is client token for license
// requests.
@@ -447,7 +445,8 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
!provider_session_token.empty()) {
if (sts != KEY_ADDED) {
CdmResponseType sts =
usage_table_header_->DeleteEntry(usage_entry_number_);
usage_table_header_->DeleteEntry(usage_entry_number_,
file_handle_.get(), &metrics_);
if (sts != NO_ERROR) {
LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts);
}
@@ -589,7 +588,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
CdmResponseType CdmSession::GenerateRenewalRequest(
CdmKeyRequest* key_request) {
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
true, app_parameters_, &key_request->message, &key_request->url);
true, app_parameters_, NULL, &key_request->message, &key_request->url);
key_request->type = kKeyRequestTypeRenewal;
@@ -619,8 +618,8 @@ CdmResponseType CdmSession::GenerateReleaseRequest(
CdmKeyRequest* key_request) {
is_release_ = true;
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
false, app_parameters_, &key_request->message,
&key_request->url);
false, app_parameters_, usage_table_header_ == NULL ? NULL : this,
&key_request->message, &key_request->url);
key_request->type = kKeyRequestTypeRelease;
@@ -657,34 +656,50 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
if (is_offline_ || has_provider_session_token()) {
DeleteLicense();
// Deletion of usage entry cannot occur while in use by a crypto session.
// So close and reopen after deletion.
if (usage_support_type_ == kUsageEntrySupport) {
crypto_session_->Close();
CdmResponseType sts = usage_table_header_->DeleteEntry(usage_entry_number_);
if (sts != NO_ERROR) return sts;
M_TIME(
sts = crypto_session_->Open(requested_security_level_),
&metrics_,
crypto_session_open_,
sts,
requested_security_level_);
sts = DeleteUsageEntry(usage_entry_number_);
if (NO_ERROR != sts) return sts;
}
}
return NO_ERROR;
}
CdmResponseType CdmSession::DeleteUsageEntry(
const DeviceFiles::CdmUsageData& usage_data) {
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
if (usage_support_type_ != kUsageEntrySupport) {
LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d",
usage_support_type_);
return INCORRECT_USAGE_SUPPORT_TYPE_1;
}
return usage_table_header_->DeleteEntry(usage_data.usage_entry_number);
// The usage entry cannot be deleted if it has a crypto session handling
// it, so close and reopen session.
CdmResponseType sts;
crypto_session_->Close();
crypto_session_.reset(new CryptoSession(&metrics_));
M_TIME(
sts = crypto_session_->Open(requested_security_level_),
&metrics_,
crypto_session_open_,
sts,
requested_security_level_);
if (sts != NO_ERROR) return sts;
usage_table_header_ = NULL;
if (crypto_session_->GetUsageSupportType(&usage_support_type_) == NO_ERROR) {
if (usage_support_type_ == kUsageEntrySupport)
usage_table_header_ = crypto_session_->GetUsageTableHeader();
} else {
usage_support_type_ = kNonSecureUsageSupport;
}
if (usage_table_header_ == NULL) {
LOGE("CdmSession::DeleteUsageEntry: Usage table header unavailable");
return INCORRECT_USAGE_SUPPORT_TYPE_1;
}
return usage_table_header_->DeleteEntry(usage_entry_number,
file_handle_.get(),
&metrics_);
}
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {

View File

@@ -17,6 +17,7 @@
#include "properties.h"
#include "pst_report.h"
#include "string_conversions.h"
#include "usage_table_header.h"
#include "wv_cdm_constants.h"
namespace {
@@ -41,6 +42,8 @@ Lock CryptoSession::crypto_lock_;
bool CryptoSession::initialized_ = false;
int CryptoSession::session_count_ = 0;
uint64_t CryptoSession::request_id_index_ = 0;
UsageTableHeader* CryptoSession::usage_table_header_l1_ = NULL;
UsageTableHeader* CryptoSession::usage_table_header_l3_ = NULL;
CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
: metrics_(metrics),
@@ -50,6 +53,7 @@ CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
requested_security_level_(kLevelDefault),
is_usage_support_type_valid_(false),
usage_support_type_(kNonSecureUsageSupport),
usage_table_header_(NULL),
request_id_base_(0),
cipher_mode_(kCipherModeCtr) {
Init();
@@ -120,6 +124,16 @@ void CryptoSession::Terminate() {
if (OEMCrypto_SUCCESS != sts) {
LOGE("OEMCrypto_Terminate failed: %d", sts);
}
if (usage_table_header_l1_ != NULL) {
delete usage_table_header_l1_;
usage_table_header_l1_ = NULL;
}
if (usage_table_header_l3_ != NULL) {
delete usage_table_header_l3_;
usage_table_header_l3_ = NULL;
}
initialized_ = false;
}
@@ -210,8 +224,7 @@ bool CryptoSession::GetProvisioningToken(std::string* token) {
}
CdmSecurityLevel CryptoSession::GetSecurityLevel() {
LOGV("CryptoSession::GetSecurityLevel: Lock");
AutoLock auto_lock(crypto_lock_);
LOGV("CryptoSession::GetSecurityLevel");
if (!initialized_) {
return kSecurityLevelUninitialized;
}
@@ -421,7 +434,8 @@ uint8_t CryptoSession::GetSecurityPatchLevel() {
}
CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
LOGV("CryptoSession::Open: Lock");
LOGV("CryptoSession::Open: Lock: requested_security_level: %d",
requested_security_level);
AutoLock auto_lock(crypto_lock_);
if (!initialized_) return UNKNOWN_ERROR;
if (open_) return NO_ERROR;
@@ -461,6 +475,35 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
random_sts,
metrics::Pow2Bucket(sizeof(request_id_base_)));
++request_id_index_;
CdmUsageSupportType usage_support_type;
if (GetUsageSupportType(&usage_support_type) == NO_ERROR) {
if (usage_support_type == kUsageEntrySupport) {
CdmSecurityLevel security_level = GetSecurityLevel();
if (security_level == kSecurityLevelL1 ||
security_level == kSecurityLevelL3) {
UsageTableHeader* header = security_level == kSecurityLevelL1 ?
usage_table_header_l1_ : usage_table_header_l3_;
if (header == NULL) {
header = new UsageTableHeader();
// Ignore errors since we do not know when a session is opened,
// if it is intended to be used for offline/usage session related
// or otherwise.
if (!header->Init(security_level, this)) {
delete header;
usage_table_header_ = NULL;
return NO_ERROR;
}
if (security_level == kSecurityLevelL1)
usage_table_header_l1_ = header;
else
usage_table_header_l3_ = header;
}
usage_table_header_ = header;
}
}
}
return NO_ERROR;
}
@@ -1085,9 +1128,7 @@ CdmResponseType CryptoSession::UpdateUsageInformation() {
AutoLock auto_lock(crypto_lock_);
if (!initialized_) return UNKNOWN_ERROR;
CdmUsageSupportType usage_support_type;
if (GetUsageSupportType(&usage_support_type) == NO_ERROR &&
usage_support_type == kUsageEntrySupport) {
if (usage_table_header_ != NULL) {
LOGV("UpdateUsageInformation: deprecated for OEMCrypto v13+");
return NO_ERROR;
}
@@ -1248,6 +1289,11 @@ CdmResponseType CryptoSession::ReleaseUsageInformation(
LOGV("ReleaseUsageInformation: id=%ld", (uint32_t)oec_session_id_);
{
AutoLock auto_lock(crypto_lock_);
if (usage_table_header_ != NULL) {
LOGW("ReleaseUsageInformation: deprecated for OEMCrypto v13+");
return NO_ERROR;
}
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
const uint8_t* sig = reinterpret_cast<const uint8_t*>(signature.data());
const uint8_t* pst = msg + GetOffset(message, provider_session_token);

View File

@@ -7,6 +7,7 @@
#include <vector>
#include "clock.h"
#include "cdm_session.h"
#include "crypto_key.h"
#include "crypto_session.h"
#include "device_files.h"
@@ -287,7 +288,8 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
bool is_renewal, const CdmAppParameterMap& app_parameters,
CdmKeyMessage* signed_request, std::string* server_url) {
CdmSession* cdm_session, CdmKeyMessage* signed_request,
std::string* server_url) {
if (!initialized_) {
LOGE("CdmLicense::PrepareKeyUpdateRequest: not initialized");
return LICENSE_PARSER_NOT_INITIALIZED_1;
@@ -346,6 +348,12 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
if (NO_ERROR != status) return status;
}
// TODO(rfrias): Refactor to avoid needing to call CdmSession
if (cdm_session) {
CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
if (NO_ERROR != status) return status;
}
std::string usage_report;
CdmResponseType status = crypto_session_->GenerateUsageReport(
provider_session_token_, &usage_report, &usage_duration_status,

View File

@@ -5,6 +5,7 @@
#include "crypto_session.h"
#include "license.h"
#include "log.h"
#include "metrics_group.h"
namespace {
std::string kEmptyString;
@@ -12,78 +13,66 @@ std::string kEmptyString;
namespace wvcdm {
UsageTableHeader* UsageTableHeader::usage_table_header_l1_ = NULL;
UsageTableHeader* UsageTableHeader::usage_table_header_l3_ = NULL;
Lock UsageTableHeader::initialization_lock_;
UsageTableHeader* UsageTableHeader::GetInstance(FileSystem* file_system,
CryptoSession* crypto_session) {
LOGV("UsageTableHeader::GetInstance");
AutoLock auto_lock(initialization_lock_);
CdmSecurityLevel security_level = crypto_session->GetSecurityLevel();
switch (security_level) {
case kSecurityLevelL1:
if (usage_table_header_l1_ != NULL)
return usage_table_header_l1_;
break;
case kSecurityLevelL3:
if (usage_table_header_l3_ != NULL)
return usage_table_header_l3_;
break;
default:
LOGE("UsageTableHeader::GetInstance: unsupported security level: %d",
security_level);
return NULL;
}
UsageTableHeader* header =
new UsageTableHeader(file_system, crypto_session, security_level);
if (!header->is_inited()) {
delete header;
return NULL;
}
if (security_level == kSecurityLevelL1)
usage_table_header_l1_ = header;
else
usage_table_header_l3_ = header;
return header;
UsageTableHeader::UsageTableHeader()
: security_level_(kSecurityLevelUninitialized),
requested_security_level_(kLevelDefault),
is_inited_(false) {
file_system_.reset(new FileSystem());
file_handle_.reset(new DeviceFiles(file_system_.get()));
}
UsageTableHeader::UsageTableHeader(FileSystem* file_system,
CryptoSession* crypto_session,
CdmSecurityLevel security_level)
: file_handle_(new DeviceFiles(file_system)),
security_level_(security_level),
is_inited_(false) {
LOGV("UsageTableHeader::UsageTablerHeader: security level: %d",
security_level);
bool UsageTableHeader::Init(CdmSecurityLevel security_level,
CryptoSession* crypto_session) {
LOGV("UsageTableHeader::Init: security level: %d", security_level);
if (crypto_session == NULL) {
LOGE("UsageTableHeader::Init: no crypto session provided");
return false;
}
switch (security_level) {
case kSecurityLevelL1:
case kSecurityLevelL3:
break;
default:
LOGE("UsageTableHeader::Init: invalid security level provided: %d",
security_level);
return false;
}
security_level_ = security_level;
if (!file_handle_->Init(security_level)) {
LOGE("UsageTableHeader::Init: device files initialization failed");
return false;
}
if (!file_handle_->RetrieveUsageTableInfo(&usage_table_header_,
&usage_entry_info_)) {
CdmResponseType status =
crypto_session->CreateUsageTableHeader(&usage_table_header_);
if (status != NO_ERROR) return;
if (status != NO_ERROR) return false;
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
} else {
CdmResponseType status =
crypto_session->LoadUsageTableHeader(usage_table_header_);
if (status != NO_ERROR) {
LOGE(
"UsageTableHeader::UsageTablerHeader: load usage table failed, "
"security level: %d",
"UsageTableHeader::Init: load usage table failed, security level: %d",
security_level);
return;
return false;
}
}
requested_security_level_ =
security_level_ == kSecurityLevelL3 ? kLevel3 : kLevelDefault;
is_inited_ = true;
return true;
}
CdmResponseType UsageTableHeader::AddEntry(
CryptoSession* crypto_session, bool persistent_license,
const CdmKeySetId& key_set_id, const std::string& usage_info_file_name,
uint32_t* usage_entry_number) {
LOGV("UsageTableHeader::AddEntry");
LOGV("UsageTableHeader::AddEntry: Lock");
AutoLock auto_lock(usage_table_header_lock_);
CdmResponseType status = crypto_session->CreateUsageEntry(usage_entry_number);
@@ -120,15 +109,17 @@ CdmResponseType UsageTableHeader::AddEntry(
return NO_ERROR;
}
CdmResponseType UsageTableHeader::LoadEntry(
CryptoSession* crypto_session, const CdmUsageEntry& usage_entry,
uint32_t usage_entry_number) {
LOGV("UsageTableHeader::LoadEntry");
CdmResponseType UsageTableHeader::LoadEntry(CryptoSession* crypto_session,
const CdmUsageEntry& usage_entry,
uint32_t usage_entry_number) {
LOGV("UsageTableHeader::LoadEntry: Lock");
AutoLock auto_lock(usage_table_header_lock_);
if (usage_entry_number >= usage_entry_info_.size()) {
LOGE("UsageTableHeader::LoadEntry: usage entry number %d larger than table size: %d",
usage_entry_number, usage_entry_info_.size());
LOGE(
"UsageTableHeader::LoadEntry: usage entry number %d larger than table "
"size: %d",
usage_entry_number, usage_entry_info_.size());
return USAGE_INVALID_LOAD_ENTRY;
}
return crypto_session->LoadUsageEntry(usage_entry_number, usage_entry);
@@ -136,20 +127,21 @@ CdmResponseType UsageTableHeader::LoadEntry(
CdmResponseType UsageTableHeader::UpdateEntry(CryptoSession* crypto_session,
CdmUsageEntry* usage_entry) {
LOGV("UsageTableHeader::UpdateEntry");
LOGV("UsageTableHeader::UpdateEntryL: Lock");
AutoLock auto_lock(usage_table_header_lock_);
CdmUsageTableHeader usage_table_header;
CdmResponseType status =
crypto_session->UpdateUsageEntry(&usage_table_header_, usage_entry);
if (status != NO_ERROR) return status;
file_handle_->StoreUsageTableInfo(usage_table_header, usage_entry_info_);
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
return NO_ERROR;
}
CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number) {
LOGV("UsageTableHeader::DeleteEntry");
CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number,
DeviceFiles* handle,
metrics::MetricsGroup* metrics) {
LOGV("UsageTableHeader::DeleteEntry: Lock");
AutoLock auto_lock(usage_table_header_lock_);
if (usage_entry_number >= usage_entry_info_.size())
return USAGE_INVALID_PARAMETERS_1;
@@ -159,12 +151,12 @@ CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number) {
CdmUsageEntry swap_usage_entry;
bool swap_usage_entry_valid = false;
for (; !swap_usage_entry_valid && swap_entry_number > usage_entry_number;
--swap_entry_number) {
while (!swap_usage_entry_valid && swap_entry_number > usage_entry_number) {
switch (usage_entry_info_[swap_entry_number].storage_type) {
case kStorageLicense:
case kStorageUsageInfo: {
CdmResponseType status = GetEntry(swap_entry_number, &swap_usage_entry);
CdmResponseType status =
GetEntry(swap_entry_number, handle, &swap_usage_entry);
if (status == NO_ERROR) swap_usage_entry_valid = true;
break;
}
@@ -172,37 +164,54 @@ CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number) {
default:
break;
}
if (!swap_usage_entry_valid) --swap_entry_number;
}
uint32_t new_usage_table_size = 0;
uint32_t number_of_entries_to_be_deleted =
usage_entry_info_.size() - usage_entry_number;
if (swap_usage_entry_valid) {
MoveEntry(swap_entry_number, swap_usage_entry, usage_entry_number);
new_usage_table_size = swap_entry_number;
} else {
// No valid usage entries before entry to be deleted
new_usage_table_size = usage_entry_number;
CdmResponseType status = MoveEntry(swap_entry_number, swap_usage_entry,
usage_entry_number, handle, metrics);
// If unable to move entry, unset storage type of entry to be deleted and
// resize |usage_entry_info_| so that swap usage entry is the last entry.
if (status != NO_ERROR) {
usage_entry_info_[usage_entry_number].storage_type = kStorageUnknown;
usage_entry_info_[usage_entry_number].key_set_id.clear();
if (usage_entry_info_.size() - 1 == swap_entry_number) {
file_handle_->StoreUsageTableInfo(usage_table_header_,
usage_entry_info_);
} else {
Shrink(metrics, usage_entry_info_.size() - swap_entry_number - 1);
}
return NO_ERROR;
}
number_of_entries_to_be_deleted =
usage_entry_info_.size() - swap_entry_number;
}
usage_entry_info_.resize(new_usage_table_size);
CryptoSession crypto_session(&metrics_);
crypto_session.Open(GetSecurityLevel());
crypto_session.ShrinkUsageTableHeader(new_usage_table_size,
&usage_table_header_);
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
return NO_ERROR;
return Shrink(metrics, number_of_entries_to_be_deleted);
}
CdmResponseType UsageTableHeader::MoveEntry(
uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry,
uint32_t to_usage_entry_number) {
uint32_t to_usage_entry_number, DeviceFiles* handle,
metrics::MetricsGroup* metrics) {
LOGV("UsageTableHeader::MoveEntry");
AutoLock auto_lock(usage_table_header_lock_);
CryptoSession crypto_session(&metrics_);
crypto_session.Open(GetSecurityLevel());
// crypto_session points to an object whose scope is this method or a test
// object whose scope is the lifetime of this class
scoped_ptr<CryptoSession> scoped_crypto_session;
CryptoSession* crypto_session = test_crypto_session_.get();
if (crypto_session == NULL) {
scoped_crypto_session.reset((new CryptoSession(metrics)));
crypto_session = scoped_crypto_session.get();
}
crypto_session->Open(requested_security_level_);
CdmResponseType status =
crypto_session.LoadUsageEntry(from_usage_entry_number, from_usage_entry);
crypto_session->LoadUsageEntry(from_usage_entry_number, from_usage_entry);
if (status != NO_ERROR) {
LOGE("UsageTableHeader::MoveEntry: Failed to load usage entry: %d",
@@ -210,7 +219,7 @@ CdmResponseType UsageTableHeader::MoveEntry(
return status;
}
status = crypto_session.MoveUsageEntry(to_usage_entry_number);
status = crypto_session->MoveUsageEntry(to_usage_entry_number);
if (status != NO_ERROR) {
LOGE("UsageTableHeader::MoveEntry: Failed to move usage entry: %d->%d",
@@ -222,7 +231,7 @@ CdmResponseType UsageTableHeader::MoveEntry(
usage_entry_info_[from_usage_entry_number];
CdmUsageEntry usage_entry;
status = crypto_session.UpdateUsageEntry(&usage_table_header_, &usage_entry);
status = crypto_session->UpdateUsageEntry(&usage_table_header_, &usage_entry);
if (status != NO_ERROR) {
LOGE("UsageTableHeader::MoveEntry: Failed to update usage entry: %d",
@@ -232,12 +241,13 @@ CdmResponseType UsageTableHeader::MoveEntry(
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
StoreEntry(to_usage_entry_number, usage_entry);
StoreEntry(to_usage_entry_number, handle, usage_entry);
return NO_ERROR;
}
CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
DeviceFiles* handle,
CdmUsageEntry* usage_entry) {
uint32_t entry_number;
switch (usage_entry_info_[usage_entry_number].storage_type) {
@@ -247,7 +257,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
std::string key_renewal_response, release_server_url;
int64_t playback_start_time, last_playback_time, grace_period_end_time;
CdmAppParameterMap app_parameters;
if (!file_handle_->RetrieveLicense(
if (!handle->RetrieveLicense(
usage_entry_info_[usage_entry_number].key_set_id, &license_state,
&init_data, &key_request, &key_response, &key_renewal_request,
&key_renewal_response, &release_server_url, &playback_start_time,
@@ -263,7 +273,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
CdmKeyMessage license_request;
CdmKeyResponse license_response;
if (!file_handle_->RetrieveUsageInfoByKeySetId(
if (!handle->RetrieveUsageInfoByKeySetId(
usage_entry_info_[usage_entry_number].usage_info_file_name,
usage_entry_info_[usage_entry_number].key_set_id,
&provider_session_token, &license_request, &license_response,
@@ -293,6 +303,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
}
CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
DeviceFiles* handle,
const CdmUsageEntry& usage_entry) {
uint32_t entry_number;
switch (usage_entry_info_[usage_entry_number].storage_type) {
@@ -303,7 +314,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
int64_t playback_start_time, last_playback_time, grace_period_end_time;
CdmAppParameterMap app_parameters;
CdmUsageEntry entry;
if (!file_handle_->RetrieveLicense(
if (!handle->RetrieveLicense(
usage_entry_info_[usage_entry_number].key_set_id, &license_state,
&init_data, &key_request, &key_response, &key_renewal_request,
&key_renewal_response, &release_server_url, &playback_start_time,
@@ -312,7 +323,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
LOGE("UsageTableHeader::StoreEntry: Failed to retrieve license");
return USAGE_RETRIEVE_LICENSE_FAILED;
}
if (!file_handle_->StoreLicense(
if (!handle->StoreLicense(
usage_entry_info_[usage_entry_number].key_set_id, license_state,
init_data, key_request, key_response, key_renewal_request,
key_renewal_response, release_server_url, playback_start_time,
@@ -327,7 +338,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
CdmUsageEntry entry;
std::string provider_session_token, init_data, key_request, key_response,
key_renewal_request;
if (!file_handle_->RetrieveUsageInfoByKeySetId(
if (!handle->RetrieveUsageInfoByKeySetId(
usage_entry_info_[usage_entry_number].usage_info_file_name,
usage_entry_info_[usage_entry_number].key_set_id,
&provider_session_token, &key_request, &key_response, &entry,
@@ -337,10 +348,10 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
"information");
return USAGE_RETRIEVE_USAGE_INFO_FAILED;
}
file_handle_->DeleteUsageInfo(
handle->DeleteUsageInfo(
usage_entry_info_[usage_entry_number].usage_info_file_name,
provider_session_token);
if (!file_handle_->StoreUsageInfo(
if (!handle->StoreUsageInfo(
provider_session_token, key_request, key_response,
usage_entry_info_[usage_entry_number].usage_info_file_name,
usage_entry_info_[usage_entry_number].key_set_id, usage_entry,
@@ -361,41 +372,56 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
return NO_ERROR;
}
bool UsageTableHeader::DeleteLastEntry() {
CdmResponseType UsageTableHeader::Shrink(
metrics::MetricsGroup* metrics,
uint32_t number_of_usage_entries_to_delete) {
if (usage_entry_info_.empty()) {
LOGW(
"UsageTableHeader::DeleteLastEntry: usage entry info table "
"unexpectedly empty");
return false;
LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty");
return NO_USAGE_ENTRIES;
}
usage_entry_info_.resize(usage_entry_info_.size() - 1);
if (usage_entry_info_.size() < number_of_usage_entries_to_delete) {
LOGW(
"UsageTableHeader::Shrink: cannot delete %d entries when usage entry "
"table size is %d", number_of_usage_entries_to_delete,
usage_entry_info_.size());
return NO_ERROR;
}
if (number_of_usage_entries_to_delete == 0) return NO_ERROR;
usage_entry_info_.resize(usage_entry_info_.size() -
number_of_usage_entries_to_delete);
// crypto_session points to an object whose scope is this method or a test
// object whose scope is the lifetime of this class
scoped_ptr<CryptoSession> scoped_crypto_session;
CryptoSession* crypto_session = test_crypto_session_.get();
if (crypto_session == NULL) {
scoped_crypto_session.reset((new CryptoSession(metrics)));
crypto_session = scoped_crypto_session.get();
}
CdmResponseType status = crypto_session->Open(requested_security_level_);
if (status != NO_ERROR) return status;
status = crypto_session->ShrinkUsageTableHeader(usage_entry_info_.size(),
&usage_table_header_);
if (status != NO_ERROR) return status;
CryptoSession crypto_session(&metrics_);
crypto_session.Open(GetSecurityLevel());
crypto_session.ShrinkUsageTableHeader(usage_entry_info_.size(),
&usage_table_header_);
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
return true;
}
CdmResponseType UsageTableHeader::UpgradeFromUsageTable() {
CryptoSession crypto_session(&metrics_);
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
if (status != NO_ERROR) return status;
status = crypto_session.CreateUsageTableHeader(&usage_table_header_);
if (status != NO_ERROR) return status;
crypto_session.Close();
UpgradeLicensesFromUsageTable();
UpgradeUsageInfoFromUsageTable();
return NO_ERROR;
}
bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
CdmResponseType UsageTableHeader::UpgradeFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
UpgradeLicensesFromUsageTable(handle, metrics);
UpgradeUsageInfoFromUsageTable(handle, metrics);
return NO_ERROR;
}
bool UsageTableHeader::UpgradeLicensesFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
// Fetch the key set IDs for each offline license. For each license
// * retrieve the provider session token,
// * create a new usage entry
@@ -404,7 +430,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
// * save the usage table header and store the usage entry number and
// usage entry along with the license to persistent memory
std::vector<std::string> key_set_ids;
if (file_handle_->ListLicenses(&key_set_ids)) {
if (handle->ListLicenses(&key_set_ids)) {
LOGW(
"UpgradeUsageTableHeader::UpgradeLicensesFromUsageTable: unable to "
"retrieve list of licenses");
@@ -419,7 +445,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
CdmAppParameterMap app_parameters;
CdmUsageEntry usage_entry;
uint32_t usage_entry_number;
if (!file_handle_->RetrieveLicense(
if (!handle->RetrieveLicense(
key_set_ids[i], &license_state, &init_data, &key_request,
&key_response, &key_renewal_request, &key_renewal_response,
&release_server_url, &playback_start_time, &last_playback_time,
@@ -442,8 +468,8 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
if (provider_session_token.empty()) continue;
CryptoSession crypto_session(&metrics_);
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
CryptoSession crypto_session(metrics);
CdmResponseType status = crypto_session.Open(requested_security_level_);
if (status != NO_ERROR) continue;
@@ -456,7 +482,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
Shrink(metrics, 1);
continue;
}
@@ -464,16 +490,18 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
Shrink(metrics, 1);
continue;
}
if (!file_handle_->StoreLicense(
if (!handle->StoreLicense(
key_set_ids[i], license_state, init_data, key_request, key_response,
key_renewal_request, key_renewal_response, release_server_url,
playback_start_time, last_playback_time, grace_period_end_time,
app_parameters, usage_entry, usage_entry_number)) {
LOGE("UsageTableHeader::StoreEntry: Failed to store license");
LOGE(
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to store "
"license");
continue;
}
}
@@ -481,7 +509,8 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
return NO_ERROR;
}
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
// Fetch all usage files. For each file retrieve all the usage info records
// within the file. For each piece of usage information
// * create a new usage entry
@@ -492,7 +521,7 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
// information to persistent memory along with usage entry number and usage
// entry.
std::vector<std::string> usage_info_file_names;
if (file_handle_->ListUsageInfoFiles(&usage_info_file_names)) {
if (handle->ListUsageInfoFiles(&usage_info_file_names)) {
LOGW(
"UpgradeUsageTableHeader::UpgradeUsageInfoFromUsageTable: Unable to "
"retrieve list of usage info file names");
@@ -501,8 +530,7 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
for (size_t i = 0; i < usage_info_file_names.size(); ++i) {
std::vector<DeviceFiles::CdmUsageData> usage_data;
if (!file_handle_->RetrieveUsageInfo(usage_info_file_names[i],
&usage_data)) {
if (!handle->RetrieveUsageInfo(usage_info_file_names[i], &usage_data)) {
LOGW(
"UsageTableHeader::UpgradeUsageInfoFromUsageTable: Failed to "
"retrieve usage records from %s",
@@ -518,8 +546,8 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
continue;
}
CryptoSession crypto_session(&metrics_);
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
CryptoSession crypto_session(metrics);
CdmResponseType status = crypto_session.Open(requested_security_level_);
if (status != NO_ERROR) continue;
@@ -536,7 +564,7 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
Shrink(metrics, 1);
continue;
}
@@ -544,12 +572,12 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
Shrink(metrics, 1);
continue;
}
}
if (!file_handle_->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
if (!handle->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
LOGE(
"UsageTableHeader::StoreUsageInfo: Failed to store usage records to "
"%s",