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:
@@ -88,6 +88,7 @@ try_adb_push $OUT/vendor/bin/license_unittest
|
||||
try_adb_push $OUT/vendor/bin/license_keys_unittest
|
||||
try_adb_push $OUT/vendor/bin/initialization_data_unittest
|
||||
try_adb_push $OUT/vendor/bin/device_files_unittest
|
||||
try_adb_push $OUT/vendor/bin/usage_table_header_unittest
|
||||
try_adb_push $OUT/vendor/bin/service_certificate_unittest
|
||||
try_adb_push $OUT/vendor/bin/timer_unittest
|
||||
try_adb_push $OUT/vendor/bin/libwvdrmengine_test
|
||||
|
||||
@@ -82,8 +82,7 @@ class CdmSession {
|
||||
// ReleaseKey() - Accept response and release key.
|
||||
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
|
||||
|
||||
virtual CdmResponseType DeleteUsageEntry(
|
||||
const DeviceFiles::CdmUsageData& usage_data);
|
||||
virtual CdmResponseType DeleteUsageEntry(uint32_t usage_entry_number);
|
||||
|
||||
virtual bool IsKeyLoaded(const KeyId& key_id);
|
||||
virtual int64_t GetDurationRemaining();
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
namespace wvcdm {
|
||||
|
||||
class CryptoKey;
|
||||
class UsageTableHeader;
|
||||
|
||||
typedef std::map<CryptoKeyId, CryptoKey*> CryptoKeyMap;
|
||||
|
||||
class CryptoSession {
|
||||
@@ -142,6 +144,9 @@ class CryptoSession {
|
||||
const std::string& signature);
|
||||
|
||||
// Usage table header and usage entry related methods
|
||||
virtual UsageTableHeader* GetUsageTableHeader() {
|
||||
return usage_table_header_;
|
||||
}
|
||||
virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type);
|
||||
virtual CdmResponseType CreateUsageTableHeader(
|
||||
CdmUsageTableHeader* usage_table_header);
|
||||
@@ -217,6 +222,9 @@ class CryptoSession {
|
||||
|
||||
bool is_usage_support_type_valid_;
|
||||
CdmUsageSupportType usage_support_type_;
|
||||
UsageTableHeader* usage_table_header_;
|
||||
static UsageTableHeader* usage_table_header_l1_;
|
||||
static UsageTableHeader* usage_table_header_l3_;
|
||||
|
||||
uint64_t request_id_base_;
|
||||
static uint64_t request_id_index_;
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace wvcdm {
|
||||
class Clock;
|
||||
class CryptoSession;
|
||||
class PolicyEngine;
|
||||
class CdmSession;
|
||||
|
||||
class CdmLicense {
|
||||
public:
|
||||
@@ -37,7 +38,8 @@ class CdmLicense {
|
||||
std::string* server_url);
|
||||
virtual CdmResponseType 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);
|
||||
virtual CdmResponseType HandleKeyResponse(
|
||||
const CdmKeyResponse& license_response);
|
||||
virtual CdmResponseType HandleKeyUpdateResponse(
|
||||
|
||||
@@ -7,36 +7,48 @@
|
||||
#include <vector>
|
||||
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "lock.h"
|
||||
#include "metrics_group.h"
|
||||
#include "scoped_ptr.h"
|
||||
#include "timer_metric.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
class FileSystem;
|
||||
class CryptoSession;
|
||||
|
||||
// The UsageTableHeader class is a singleton that CDM sessions will share.
|
||||
// A separate object will be created for each security level.
|
||||
// The class synchronizes access to usage table header and associated
|
||||
// data-structures and controls when they are read in or written out to
|
||||
// non-secure persistent storage.
|
||||
// Offline licenses/secure stops may be securely tracked using usage
|
||||
// tables (OEMCrypto v9-12) or usage table headers+usage entries
|
||||
// (OEMCrypto v13+). This class assists with the latter, synchronizing
|
||||
// access to usage table header and associated data-structures and controlling
|
||||
// when they are read in or written out to non-secure persistent storage.
|
||||
//
|
||||
// Each OEMCrypto (for each security level) will maintain its own usage table
|
||||
// header. Each license will have an associated usage entry that is also
|
||||
// stored in persistent memory and is noted in the usage table header.
|
||||
// Usage entry information will be verified when licenses are loaded.
|
||||
//
|
||||
// OEMCrypto for each security level have their own usage table
|
||||
// headers. They are loaded on initialization and written out periodically.
|
||||
// The lifecycle of this class is tied to when OEMCrypto is
|
||||
// initialized/terminated.
|
||||
//
|
||||
// Sessions and licenses are however handled by CdmSession and so most
|
||||
// calls to maniplate the usage table header related to usage entries
|
||||
// are by CdmSession.
|
||||
//
|
||||
// Upgrades from a fixed size usage table (supported by previous
|
||||
// versions of the OEMCrypto API v9-12) are handled by this class.
|
||||
// |usage_entry| and |usage_entry_number|s need to be saved in the license
|
||||
// and usage info records by the caller.
|
||||
class UsageTableHeader {
|
||||
public:
|
||||
// This methods instantiates or retrieves a usage table header singleton of
|
||||
// appropriate security level as specified by the |crypto_session|
|
||||
// object.
|
||||
UsageTableHeader();
|
||||
virtual ~UsageTableHeader() {}
|
||||
|
||||
// |crypto_session| is used to create or load a usage master table and
|
||||
// not cached beyound this call.
|
||||
static UsageTableHeader* GetInstance(FileSystem* file_system,
|
||||
CryptoSession* crypto_session_);
|
||||
virtual ~UsageTableHeader() {}
|
||||
bool Init(CdmSecurityLevel security_level, CryptoSession* crypto_session);
|
||||
|
||||
// |persistent_license| false indicates usage info record
|
||||
CdmResponseType AddEntry(CryptoSession* crypto_session,
|
||||
@@ -53,54 +65,67 @@ class UsageTableHeader {
|
||||
// The licenses or usage info records specified by |usage_entry_number|
|
||||
// should not be in use by any open CryptoSession objects when calls
|
||||
// to DeleteEntry and MoveEntry are made.
|
||||
CdmResponseType DeleteEntry(uint32_t usage_entry_number);
|
||||
CdmResponseType MoveEntry(uint32_t from_usage_entry_number,
|
||||
const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to_usage_entry_number);
|
||||
CdmResponseType DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
|
||||
private:
|
||||
UsageTableHeader(FileSystem* file_system, CryptoSession* crypto_session,
|
||||
CdmSecurityLevel security_level);
|
||||
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
|
||||
const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to /* usage entry number */,
|
||||
DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
|
||||
CdmResponseType GetEntry(uint32_t usage_entry_number,
|
||||
CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
CdmUsageEntry* usage_entry);
|
||||
CdmResponseType StoreEntry(uint32_t usage_entry_number,
|
||||
CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
const CdmUsageEntry& usage_entry);
|
||||
|
||||
bool DeleteLastEntry();
|
||||
CdmResponseType Shrink(metrics::MetricsGroup* metrics,
|
||||
uint32_t number_of_usage_entries_to_delete);
|
||||
|
||||
CdmResponseType UpgradeFromUsageTable();
|
||||
bool UpgradeLicensesFromUsageTable();
|
||||
bool UpgradeUsageInfoFromUsageTable();
|
||||
CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
bool UpgradeLicensesFromUsageTable(DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
|
||||
virtual bool is_inited() { return is_inited_; }
|
||||
|
||||
SecurityLevel GetSecurityLevel() {
|
||||
return security_level_ == kSecurityLevelL3 ? kLevel3 : kLevelDefault;
|
||||
}
|
||||
|
||||
static UsageTableHeader* usage_table_header_l1_;
|
||||
static UsageTableHeader* usage_table_header_l3_;
|
||||
|
||||
// This handle and file system is only to be used when accessing
|
||||
// usage_table_header. Usage entries should use the file system provided
|
||||
// by CdmSession.
|
||||
scoped_ptr<DeviceFiles> file_handle_;
|
||||
scoped_ptr<FileSystem> file_system_;
|
||||
CdmSecurityLevel security_level_;
|
||||
SecurityLevel requested_security_level_;
|
||||
|
||||
CdmUsageTableHeader usage_table_header_;
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_;
|
||||
|
||||
metrics::MetricsGroup metrics_;
|
||||
metrics::TimerMetric life_span_;
|
||||
|
||||
// Lock to ensure that a single object is created for each security level
|
||||
// and data member to represent whether an object has been correctly
|
||||
// initialized.
|
||||
bool is_inited_;
|
||||
static Lock initialization_lock_;
|
||||
|
||||
// Synchonizes access to the Usage Table Header and bookkeeping
|
||||
// data-structures
|
||||
Lock usage_table_header_lock_;
|
||||
|
||||
// Test related declarations
|
||||
friend class UsageTableHeaderTest;
|
||||
|
||||
// These setters are for testing only. Takes ownership of the pointers.
|
||||
void SetDeviceFiles(DeviceFiles* device_files) {
|
||||
file_handle_.reset(device_files);
|
||||
}
|
||||
void SetCryptoSession(CryptoSession* crypto_session) {
|
||||
test_crypto_session_.reset(crypto_session);
|
||||
}
|
||||
|
||||
// Test related data members
|
||||
scoped_ptr<CryptoSession> test_crypto_session_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(UsageTableHeader);
|
||||
};
|
||||
|
||||
|
||||
@@ -297,6 +297,7 @@ enum CdmResponseType {
|
||||
INCORRECT_USAGE_SUPPORT_TYPE_2,
|
||||
KEY_PROHIBITED_FOR_SECURITY_LEVEL, /* 255 */
|
||||
KEY_NOT_FOUND_IN_SESSION,
|
||||
NO_USAGE_ENTRIES,
|
||||
};
|
||||
|
||||
enum CdmKeyStatus {
|
||||
@@ -392,6 +393,12 @@ struct CdmUsageEntryInfo {
|
||||
CdmUsageEntryStorageType storage_type;
|
||||
CdmKeySetId key_set_id;
|
||||
std::string usage_info_file_name;
|
||||
bool operator==(const CdmUsageEntryInfo& other) const {
|
||||
return storage_type == other.storage_type &&
|
||||
key_set_id == other.key_set_id &&
|
||||
(storage_type != kStorageUsageInfo ||
|
||||
usage_info_file_name == other.usage_info_file_name);
|
||||
}
|
||||
};
|
||||
|
||||
class CdmKeyAllowedUsage {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -574,6 +574,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case KEY_NOT_FOUND_IN_SESSION:
|
||||
*os << "KEY_NOT_FOUND_IN_SESSION";
|
||||
break;
|
||||
case NO_USAGE_ENTRIES:
|
||||
*os << "NO_USAGE_ENTRIES";
|
||||
break;
|
||||
|
||||
default:
|
||||
*os << "Unknown CdmResponseType";
|
||||
|
||||
1563
libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp
Normal file
1563
libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -71,6 +71,10 @@ test_name := timer_unittest
|
||||
test_src_dir := .
|
||||
include $(LOCAL_PATH)/unit-test.mk
|
||||
|
||||
test_name := usage_table_header_unittest
|
||||
test_src_dir := ../core/test
|
||||
include $(LOCAL_PATH)/unit-test.mk
|
||||
|
||||
test_name := distribution_test
|
||||
test_src_dir := ../metrics/test
|
||||
include $(LOCAL_PATH)/unit-test.mk
|
||||
|
||||
@@ -2617,7 +2617,12 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
||||
key_id.append(1, ch);
|
||||
|
||||
GenerateKeyRequest(key_id, kLicenseTypeStreaming, property_set);
|
||||
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
|
||||
|
||||
// TODO(rfrias): streaming_clip6 is a streaming license without a pst
|
||||
if (ch == '6')
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
|
||||
else
|
||||
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
|
||||
|
||||
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
|
||||
CdmDecryptionParameters decryption_parameters(
|
||||
@@ -2693,7 +2698,11 @@ TEST_F(WvCdmRequestLicenseTest, UsageReleaseAllTest) {
|
||||
key_id.append(1, ch);
|
||||
|
||||
GenerateKeyRequest(key_id, kLicenseTypeStreaming, &property_set);
|
||||
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
|
||||
// TODO(rfrias): streaming_clip6 is a streaming license without a pst
|
||||
if (ch == '6')
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
|
||||
else
|
||||
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
|
||||
|
||||
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
|
||||
CdmDecryptionParameters decryption_parameters(
|
||||
|
||||
@@ -259,10 +259,11 @@ enum {
|
||||
kReleaseUsageInfoFailed = ERROR_DRM_VENDOR_MIN + 246,
|
||||
kIncorrectUsageSupportType1 = ERROR_DRM_VENDOR_MIN + 247,
|
||||
kIncorrectUsageSupportType2 = ERROR_DRM_VENDOR_MIN + 248,
|
||||
kNoUsageEntries = ERROR_DRM_VENDOR_MIN + 249,
|
||||
|
||||
// This should always follow the last error code.
|
||||
// The offset value should be updated each time a new error code is added.
|
||||
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 248,
|
||||
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 249,
|
||||
|
||||
// Used by crypto test mode
|
||||
kErrorTestMode = ERROR_DRM_VENDOR_MAX,
|
||||
|
||||
@@ -503,6 +503,8 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) {
|
||||
return kIncorrectUsageSupportType1;
|
||||
case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_2:
|
||||
return kIncorrectUsageSupportType2;
|
||||
case wvcdm::NO_USAGE_ENTRIES:
|
||||
return kNoUsageEntries;
|
||||
|
||||
case wvcdm::UNUSED_1:
|
||||
case wvcdm::UNUSED_2:
|
||||
|
||||
@@ -82,6 +82,7 @@ adb_shell_run license_unittest
|
||||
adb_shell_run license_keys_unittest
|
||||
adb_shell_run initialization_data_unittest
|
||||
adb_shell_run device_files_unittest
|
||||
adb_shell_run usage_table_header_unittest
|
||||
adb_shell_run service_certificate_unittest
|
||||
adb_shell_run timer_unittest
|
||||
adb_shell_run buffer_reader_test
|
||||
|
||||
Reference in New Issue
Block a user