Merge "Corrections for big usage table support in L3" into oc-dev
am: 9edaf2ab39
Change-Id: I4651713271f53d0aca77d8ecaaae57f3ab855471
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