Merge "Corrections for big usage table support in L3" into oc-dev am: 9edaf2ab39

am: 97a77d4c2c

Change-Id: Ie8949a574ae8ea3c9219fe483eeae985a54b05cd
This commit is contained in:
Rahul Frias
2017-05-31 21:36:00 +00:00
committed by android-build-merger
18 changed files with 1937 additions and 214 deletions

View File

@@ -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/license_keys_unittest
try_adb_push $OUT/vendor/bin/initialization_data_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/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/service_certificate_unittest
try_adb_push $OUT/vendor/bin/timer_unittest try_adb_push $OUT/vendor/bin/timer_unittest
try_adb_push $OUT/vendor/bin/libwvdrmengine_test try_adb_push $OUT/vendor/bin/libwvdrmengine_test

View File

@@ -82,8 +82,7 @@ class CdmSession {
// ReleaseKey() - Accept response and release key. // ReleaseKey() - Accept response and release key.
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response); virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
virtual CdmResponseType DeleteUsageEntry( virtual CdmResponseType DeleteUsageEntry(uint32_t usage_entry_number);
const DeviceFiles::CdmUsageData& usage_data);
virtual bool IsKeyLoaded(const KeyId& key_id); virtual bool IsKeyLoaded(const KeyId& key_id);
virtual int64_t GetDurationRemaining(); virtual int64_t GetDurationRemaining();

View File

@@ -17,6 +17,8 @@
namespace wvcdm { namespace wvcdm {
class CryptoKey; class CryptoKey;
class UsageTableHeader;
typedef std::map<CryptoKeyId, CryptoKey*> CryptoKeyMap; typedef std::map<CryptoKeyId, CryptoKey*> CryptoKeyMap;
class CryptoSession { class CryptoSession {
@@ -142,6 +144,9 @@ class CryptoSession {
const std::string& signature); const std::string& signature);
// Usage table header and usage entry related methods // Usage table header and usage entry related methods
virtual UsageTableHeader* GetUsageTableHeader() {
return usage_table_header_;
}
virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type); virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type);
virtual CdmResponseType CreateUsageTableHeader( virtual CdmResponseType CreateUsageTableHeader(
CdmUsageTableHeader* usage_table_header); CdmUsageTableHeader* usage_table_header);
@@ -217,6 +222,9 @@ class CryptoSession {
bool is_usage_support_type_valid_; bool is_usage_support_type_valid_;
CdmUsageSupportType usage_support_type_; 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_; uint64_t request_id_base_;
static uint64_t request_id_index_; static uint64_t request_id_index_;

View File

@@ -21,6 +21,7 @@ namespace wvcdm {
class Clock; class Clock;
class CryptoSession; class CryptoSession;
class PolicyEngine; class PolicyEngine;
class CdmSession;
class CdmLicense { class CdmLicense {
public: public:
@@ -37,7 +38,8 @@ class CdmLicense {
std::string* server_url); std::string* server_url);
virtual CdmResponseType PrepareKeyUpdateRequest( virtual CdmResponseType PrepareKeyUpdateRequest(
bool is_renewal, const CdmAppParameterMap& app_parameters, 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( virtual CdmResponseType HandleKeyResponse(
const CdmKeyResponse& license_response); const CdmKeyResponse& license_response);
virtual CdmResponseType HandleKeyUpdateResponse( virtual CdmResponseType HandleKeyUpdateResponse(

View File

@@ -7,36 +7,48 @@
#include <vector> #include <vector>
#include "device_files.h" #include "device_files.h"
#include "file_store.h"
#include "lock.h" #include "lock.h"
#include "metrics_group.h" #include "metrics_group.h"
#include "scoped_ptr.h" #include "scoped_ptr.h"
#include "timer_metric.h"
#include "wv_cdm_types.h" #include "wv_cdm_types.h"
namespace wvcdm { namespace wvcdm {
class FileSystem;
class CryptoSession; class CryptoSession;
// The UsageTableHeader class is a singleton that CDM sessions will share. // Offline licenses/secure stops may be securely tracked using usage
// A separate object will be created for each security level. // tables (OEMCrypto v9-12) or usage table headers+usage entries
// The class synchronizes access to usage table header and associated // (OEMCrypto v13+). This class assists with the latter, synchronizing
// data-structures and controls when they are read in or written out to // access to usage table header and associated data-structures and controlling
// non-secure persistent storage. // 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 // Upgrades from a fixed size usage table (supported by previous
// versions of the OEMCrypto API v9-12) are handled by this class. // 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 // |usage_entry| and |usage_entry_number|s need to be saved in the license
// and usage info records by the caller. // and usage info records by the caller.
class UsageTableHeader { class UsageTableHeader {
public: public:
// This methods instantiates or retrieves a usage table header singleton of UsageTableHeader();
// appropriate security level as specified by the |crypto_session| virtual ~UsageTableHeader() {}
// object.
// |crypto_session| is used to create or load a usage master table and // |crypto_session| is used to create or load a usage master table and
// not cached beyound this call. // not cached beyound this call.
static UsageTableHeader* GetInstance(FileSystem* file_system, bool Init(CdmSecurityLevel security_level, CryptoSession* crypto_session);
CryptoSession* crypto_session_);
virtual ~UsageTableHeader() {}
// |persistent_license| false indicates usage info record // |persistent_license| false indicates usage info record
CdmResponseType AddEntry(CryptoSession* crypto_session, CdmResponseType AddEntry(CryptoSession* crypto_session,
@@ -53,54 +65,67 @@ class UsageTableHeader {
// The licenses or usage info records specified by |usage_entry_number| // The licenses or usage info records specified by |usage_entry_number|
// should not be in use by any open CryptoSession objects when calls // should not be in use by any open CryptoSession objects when calls
// to DeleteEntry and MoveEntry are made. // to DeleteEntry and MoveEntry are made.
CdmResponseType DeleteEntry(uint32_t usage_entry_number); CdmResponseType DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle,
CdmResponseType MoveEntry(uint32_t from_usage_entry_number, metrics::MetricsGroup* metrics);
const CdmUsageEntry& from_usage_entry,
uint32_t to_usage_entry_number);
private: private:
UsageTableHeader(FileSystem* file_system, CryptoSession* crypto_session, CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
CdmSecurityLevel security_level); 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); CdmUsageEntry* usage_entry);
CdmResponseType StoreEntry(uint32_t usage_entry_number, CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle,
const CdmUsageEntry& usage_entry); const CdmUsageEntry& usage_entry);
bool DeleteLastEntry(); CdmResponseType Shrink(metrics::MetricsGroup* metrics,
uint32_t number_of_usage_entries_to_delete);
CdmResponseType UpgradeFromUsageTable(); CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle,
bool UpgradeLicensesFromUsageTable(); metrics::MetricsGroup* metrics);
bool UpgradeUsageInfoFromUsageTable(); bool UpgradeLicensesFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
virtual bool is_inited() { return is_inited_; } virtual bool is_inited() { return is_inited_; }
SecurityLevel GetSecurityLevel() { // This handle and file system is only to be used when accessing
return security_level_ == kSecurityLevelL3 ? kLevel3 : kLevelDefault; // usage_table_header. Usage entries should use the file system provided
} // by CdmSession.
static UsageTableHeader* usage_table_header_l1_;
static UsageTableHeader* usage_table_header_l3_;
scoped_ptr<DeviceFiles> file_handle_; scoped_ptr<DeviceFiles> file_handle_;
scoped_ptr<FileSystem> file_system_;
CdmSecurityLevel security_level_; CdmSecurityLevel security_level_;
SecurityLevel requested_security_level_;
CdmUsageTableHeader usage_table_header_; CdmUsageTableHeader usage_table_header_;
std::vector<CdmUsageEntryInfo> usage_entry_info_; 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 // Lock to ensure that a single object is created for each security level
// and data member to represent whether an object has been correctly // and data member to represent whether an object has been correctly
// initialized. // initialized.
bool is_inited_; bool is_inited_;
static Lock initialization_lock_;
// Synchonizes access to the Usage Table Header and bookkeeping // Synchonizes access to the Usage Table Header and bookkeeping
// data-structures // data-structures
Lock usage_table_header_lock_; 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); CORE_DISALLOW_COPY_AND_ASSIGN(UsageTableHeader);
}; };

View File

@@ -297,6 +297,7 @@ enum CdmResponseType {
INCORRECT_USAGE_SUPPORT_TYPE_2, INCORRECT_USAGE_SUPPORT_TYPE_2,
KEY_PROHIBITED_FOR_SECURITY_LEVEL, /* 255 */ KEY_PROHIBITED_FOR_SECURITY_LEVEL, /* 255 */
KEY_NOT_FOUND_IN_SESSION, KEY_NOT_FOUND_IN_SESSION,
NO_USAGE_ENTRIES,
}; };
enum CdmKeyStatus { enum CdmKeyStatus {
@@ -392,6 +393,12 @@ struct CdmUsageEntryInfo {
CdmUsageEntryStorageType storage_type; CdmUsageEntryStorageType storage_type;
CdmKeySetId key_set_id; CdmKeySetId key_set_id;
std::string usage_info_file_name; 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 { class CdmKeyAllowedUsage {

View File

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

View File

@@ -44,15 +44,6 @@ CdmSession::CdmSession(FileSystem* file_system) :
usage_entry_number_(0), usage_entry_number_(0),
mock_license_parser_in_use_(false), mock_license_parser_in_use_(false),
mock_policy_engine_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(); life_span_.Start();
} }
@@ -104,6 +95,13 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
return SESSION_FILE_HANDLE_INIT_ERROR; 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. // Device Provisioning state is not yet known.
// If not using certificates, then Keybox is client token for license // If not using certificates, then Keybox is client token for license
// requests. // requests.
@@ -447,7 +445,8 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
!provider_session_token.empty()) { !provider_session_token.empty()) {
if (sts != KEY_ADDED) { if (sts != KEY_ADDED) {
CdmResponseType sts = CdmResponseType sts =
usage_table_header_->DeleteEntry(usage_entry_number_); usage_table_header_->DeleteEntry(usage_entry_number_,
file_handle_.get(), &metrics_);
if (sts != NO_ERROR) { if (sts != NO_ERROR) {
LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts); LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts);
} }
@@ -588,7 +587,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
CdmResponseType CdmSession::GenerateRenewalRequest( CdmResponseType CdmSession::GenerateRenewalRequest(
CdmKeyRequest* key_request) { CdmKeyRequest* key_request) {
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest( 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; key_request->type = kKeyRequestTypeRenewal;
@@ -618,8 +617,8 @@ CdmResponseType CdmSession::GenerateReleaseRequest(
CdmKeyRequest* key_request) { CdmKeyRequest* key_request) {
is_release_ = true; is_release_ = true;
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest( CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
false, app_parameters_, &key_request->message, false, app_parameters_, usage_table_header_ == NULL ? NULL : this,
&key_request->url); &key_request->message, &key_request->url);
key_request->type = kKeyRequestTypeRelease; key_request->type = kKeyRequestTypeRelease;
@@ -656,34 +655,50 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
if (is_offline_ || has_provider_session_token()) { if (is_offline_ || has_provider_session_token()) {
DeleteLicense(); 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) { if (usage_support_type_ == kUsageEntrySupport) {
crypto_session_->Close(); sts = DeleteUsageEntry(usage_entry_number_);
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_);
if (NO_ERROR != sts) return sts; if (NO_ERROR != sts) return sts;
} }
} }
return NO_ERROR; return NO_ERROR;
} }
CdmResponseType CdmSession::DeleteUsageEntry( CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
const DeviceFiles::CdmUsageData& usage_data) {
if (usage_support_type_ != kUsageEntrySupport) { if (usage_support_type_ != kUsageEntrySupport) {
LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d", LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d",
usage_support_type_); usage_support_type_);
return INCORRECT_USAGE_SUPPORT_TYPE_1; 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) { bool CdmSession::IsKeyLoaded(const KeyId& key_id) {

View File

@@ -17,6 +17,7 @@
#include "properties.h" #include "properties.h"
#include "pst_report.h" #include "pst_report.h"
#include "string_conversions.h" #include "string_conversions.h"
#include "usage_table_header.h"
#include "wv_cdm_constants.h" #include "wv_cdm_constants.h"
namespace { namespace {
@@ -41,6 +42,8 @@ Lock CryptoSession::crypto_lock_;
bool CryptoSession::initialized_ = false; bool CryptoSession::initialized_ = false;
int CryptoSession::session_count_ = 0; int CryptoSession::session_count_ = 0;
uint64_t CryptoSession::request_id_index_ = 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) CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
: metrics_(metrics), : metrics_(metrics),
@@ -50,6 +53,7 @@ CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
requested_security_level_(kLevelDefault), requested_security_level_(kLevelDefault),
is_usage_support_type_valid_(false), is_usage_support_type_valid_(false),
usage_support_type_(kNonSecureUsageSupport), usage_support_type_(kNonSecureUsageSupport),
usage_table_header_(NULL),
request_id_base_(0), request_id_base_(0),
cipher_mode_(kCipherModeCtr) { cipher_mode_(kCipherModeCtr) {
Init(); Init();
@@ -120,6 +124,16 @@ void CryptoSession::Terminate() {
if (OEMCrypto_SUCCESS != sts) { if (OEMCrypto_SUCCESS != sts) {
LOGE("OEMCrypto_Terminate failed: %d", 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; initialized_ = false;
} }
@@ -210,8 +224,7 @@ bool CryptoSession::GetProvisioningToken(std::string* token) {
} }
CdmSecurityLevel CryptoSession::GetSecurityLevel() { CdmSecurityLevel CryptoSession::GetSecurityLevel() {
LOGV("CryptoSession::GetSecurityLevel: Lock"); LOGV("CryptoSession::GetSecurityLevel");
AutoLock auto_lock(crypto_lock_);
if (!initialized_) { if (!initialized_) {
return kSecurityLevelUninitialized; return kSecurityLevelUninitialized;
} }
@@ -421,7 +434,8 @@ uint8_t CryptoSession::GetSecurityPatchLevel() {
} }
CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) { 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_); AutoLock auto_lock(crypto_lock_);
if (!initialized_) return UNKNOWN_ERROR; if (!initialized_) return UNKNOWN_ERROR;
if (open_) return NO_ERROR; if (open_) return NO_ERROR;
@@ -461,6 +475,35 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
random_sts, random_sts,
metrics::Pow2Bucket(sizeof(request_id_base_))); metrics::Pow2Bucket(sizeof(request_id_base_)));
++request_id_index_; ++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; return NO_ERROR;
} }
@@ -1085,9 +1128,7 @@ CdmResponseType CryptoSession::UpdateUsageInformation() {
AutoLock auto_lock(crypto_lock_); AutoLock auto_lock(crypto_lock_);
if (!initialized_) return UNKNOWN_ERROR; if (!initialized_) return UNKNOWN_ERROR;
CdmUsageSupportType usage_support_type; if (usage_table_header_ != NULL) {
if (GetUsageSupportType(&usage_support_type) == NO_ERROR &&
usage_support_type == kUsageEntrySupport) {
LOGV("UpdateUsageInformation: deprecated for OEMCrypto v13+"); LOGV("UpdateUsageInformation: deprecated for OEMCrypto v13+");
return NO_ERROR; return NO_ERROR;
} }
@@ -1248,6 +1289,11 @@ CdmResponseType CryptoSession::ReleaseUsageInformation(
LOGV("ReleaseUsageInformation: id=%ld", (uint32_t)oec_session_id_); LOGV("ReleaseUsageInformation: id=%ld", (uint32_t)oec_session_id_);
{ {
AutoLock auto_lock(crypto_lock_); 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* msg = reinterpret_cast<const uint8_t*>(message.data());
const uint8_t* sig = reinterpret_cast<const uint8_t*>(signature.data()); const uint8_t* sig = reinterpret_cast<const uint8_t*>(signature.data());
const uint8_t* pst = msg + GetOffset(message, provider_session_token); const uint8_t* pst = msg + GetOffset(message, provider_session_token);

View File

@@ -7,6 +7,7 @@
#include <vector> #include <vector>
#include "clock.h" #include "clock.h"
#include "cdm_session.h"
#include "crypto_key.h" #include "crypto_key.h"
#include "crypto_session.h" #include "crypto_session.h"
#include "device_files.h" #include "device_files.h"
@@ -287,7 +288,8 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
CdmResponseType CdmLicense::PrepareKeyUpdateRequest( CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
bool is_renewal, const CdmAppParameterMap& app_parameters, 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_) { if (!initialized_) {
LOGE("CdmLicense::PrepareKeyUpdateRequest: not initialized"); LOGE("CdmLicense::PrepareKeyUpdateRequest: not initialized");
return LICENSE_PARSER_NOT_INITIALIZED_1; return LICENSE_PARSER_NOT_INITIALIZED_1;
@@ -346,6 +348,12 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
if (NO_ERROR != status) return status; 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; std::string usage_report;
CdmResponseType status = crypto_session_->GenerateUsageReport( CdmResponseType status = crypto_session_->GenerateUsageReport(
provider_session_token_, &usage_report, &usage_duration_status, provider_session_token_, &usage_report, &usage_duration_status,

View File

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

View File

@@ -574,6 +574,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
case KEY_NOT_FOUND_IN_SESSION: case KEY_NOT_FOUND_IN_SESSION:
*os << "KEY_NOT_FOUND_IN_SESSION"; *os << "KEY_NOT_FOUND_IN_SESSION";
break; break;
case NO_USAGE_ENTRIES:
*os << "NO_USAGE_ENTRIES";
break;
default: default:
*os << "Unknown CdmResponseType"; *os << "Unknown CdmResponseType";

File diff suppressed because it is too large Load Diff

View File

@@ -71,6 +71,10 @@ test_name := timer_unittest
test_src_dir := . test_src_dir := .
include $(LOCAL_PATH)/unit-test.mk 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_name := distribution_test
test_src_dir := ../metrics/test test_src_dir := ../metrics/test
include $(LOCAL_PATH)/unit-test.mk include $(LOCAL_PATH)/unit-test.mk

View File

@@ -2617,7 +2617,12 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
key_id.append(1, ch); key_id.append(1, ch);
GenerateKeyRequest(key_id, kLicenseTypeStreaming, property_set); 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()); std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters( CdmDecryptionParameters decryption_parameters(
@@ -2693,7 +2698,11 @@ TEST_F(WvCdmRequestLicenseTest, UsageReleaseAllTest) {
key_id.append(1, ch); key_id.append(1, ch);
GenerateKeyRequest(key_id, kLicenseTypeStreaming, &property_set); 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()); std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters( CdmDecryptionParameters decryption_parameters(

View File

@@ -259,10 +259,11 @@ enum {
kReleaseUsageInfoFailed = ERROR_DRM_VENDOR_MIN + 246, kReleaseUsageInfoFailed = ERROR_DRM_VENDOR_MIN + 246,
kIncorrectUsageSupportType1 = ERROR_DRM_VENDOR_MIN + 247, kIncorrectUsageSupportType1 = ERROR_DRM_VENDOR_MIN + 247,
kIncorrectUsageSupportType2 = ERROR_DRM_VENDOR_MIN + 248, kIncorrectUsageSupportType2 = ERROR_DRM_VENDOR_MIN + 248,
kNoUsageEntries = ERROR_DRM_VENDOR_MIN + 249,
// This should always follow the last error code. // This should always follow the last error code.
// The offset value should be updated each time a new error code is added. // 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 // Used by crypto test mode
kErrorTestMode = ERROR_DRM_VENDOR_MAX, kErrorTestMode = ERROR_DRM_VENDOR_MAX,

View File

@@ -503,6 +503,8 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) {
return kIncorrectUsageSupportType1; return kIncorrectUsageSupportType1;
case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_2: case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_2:
return kIncorrectUsageSupportType2; return kIncorrectUsageSupportType2;
case wvcdm::NO_USAGE_ENTRIES:
return kNoUsageEntries;
case wvcdm::UNUSED_1: case wvcdm::UNUSED_1:
case wvcdm::UNUSED_2: case wvcdm::UNUSED_2:

View File

@@ -82,6 +82,7 @@ adb_shell_run license_unittest
adb_shell_run license_keys_unittest adb_shell_run license_keys_unittest
adb_shell_run initialization_data_unittest adb_shell_run initialization_data_unittest
adb_shell_run device_files_unittest adb_shell_run device_files_unittest
adb_shell_run usage_table_header_unittest
adb_shell_run service_certificate_unittest adb_shell_run service_certificate_unittest
adb_shell_run timer_unittest adb_shell_run timer_unittest
adb_shell_run buffer_reader_test adb_shell_run buffer_reader_test