Merges to android Pi release (part 5)
These are a set of CLs merged from the wv cdm repo to the android repo. * Change build options for make protobuf host tools Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/30381 ] Also revert local change to protobuf/extension_set.cc This builds after adding -Wno-return-type and -Wno-unused flags. * OEMCrypto v13 stub Author: Rintaro Kuroiwa <rkuroiwa@google.com> [ Merge of http://go/wvgerrit/30004 ] * Remove merge conflict tags Author: Edwin Wong <edwinwong@google.com> [ Merge of http://go/wvgerrit/30120 ] Remove merge conflict tags for http://go/wvgerrit/29880 * Added Android Things ARM provisioning key to L3 Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/29701 ] BUG: 63443584 BUG: 71650075 Test: Not currently passing. Will be addressed in a subsequent commit in the chain. Change-Id: Ifd867b491dfda5d67d2e225695535b5af9e18260
This commit is contained in:
@@ -104,7 +104,26 @@ class CdmEngine {
|
||||
const CdmSessionId& session_id, const CdmKeySetId& key_set_id,
|
||||
const InitializationData& init_data, const CdmLicenseType license_type,
|
||||
CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
|
||||
// Accept license response and extract key info.
|
||||
// This API may
|
||||
// (a) accept license response, extract key info and load keys.
|
||||
// (b) accept a renewal response and update license policy information.
|
||||
// (c) accept a release response and release an offline license or secure
|
||||
// stop.
|
||||
// (d) accept a service certificate and cache that information for the
|
||||
// the lifetime of the session.
|
||||
//
|
||||
// |session_id| identifies the session that generated the request and can
|
||||
// process the response. Should be empty if a release response.
|
||||
// |key_data| is the license, renewal, release response or service
|
||||
// certificate response.
|
||||
// |key_set_id| should be non-null and specified if license release.
|
||||
// If offline license or streaming license associated with
|
||||
// a secure stop, |key_set_id| should be non-null and will
|
||||
// be filled in on return. Use the |key_set_id| with
|
||||
// RestoreKeys (to reload offline session) or
|
||||
// GenerateKeyRequest (to release offline session/secure stop).
|
||||
// |key_set_id| will be cleared if release or streaming
|
||||
// (not associated with a secure stop).
|
||||
virtual CdmResponseType AddKey(const CdmSessionId& session_id,
|
||||
const CdmKeyResponse& key_data,
|
||||
CdmKeySetId* key_set_id);
|
||||
|
||||
@@ -87,8 +87,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();
|
||||
@@ -122,6 +121,10 @@ class CdmSession {
|
||||
virtual bool is_offline() { return is_offline_; }
|
||||
virtual bool is_temporary() { return is_temporary_; }
|
||||
virtual bool license_received() { return license_received_; }
|
||||
virtual bool has_provider_session_token() {
|
||||
return (license_parser_.get() != NULL &&
|
||||
license_parser_->provider_session_token().size() > 0);
|
||||
}
|
||||
|
||||
virtual CdmUsageSupportType get_usage_support_type()
|
||||
{ return usage_support_type_; }
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
namespace wvcdm {
|
||||
|
||||
class CryptoKey;
|
||||
class UsageTableHeader;
|
||||
|
||||
typedef std::map<CryptoKeyId, CryptoKey*> CryptoKeyMap;
|
||||
|
||||
class CryptoSession {
|
||||
@@ -145,6 +147,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);
|
||||
@@ -230,7 +235,11 @@ class CryptoSession {
|
||||
|
||||
KeyId cached_key_id_;
|
||||
|
||||
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 @@ class Clock;
|
||||
class CryptoSession;
|
||||
class PolicyEngine;
|
||||
class ServiceCertificate;
|
||||
class CdmSession;
|
||||
|
||||
class CdmLicense {
|
||||
public:
|
||||
@@ -38,7 +39,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,6 +7,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "lock.h"
|
||||
#include "metrics_group.h"
|
||||
#include "scoped_ptr.h"
|
||||
@@ -15,28 +16,40 @@
|
||||
|
||||
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| 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.
|
||||
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,56 +66,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();
|
||||
|
||||
// Indicates whether one of more license/usage records failed to be upgraded.
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -64,6 +64,10 @@ static const std::string QUERY_KEY_MAX_NUMBER_OF_SESSIONS =
|
||||
"MaxNumberOfSessions";
|
||||
static const std::string QUERY_KEY_OEMCRYPTO_API_VERSION =
|
||||
"OemCryptoApiVersion";
|
||||
static const std::string QUERY_KEY_CURRENT_SRM_VERSION = "CurrentSRMVersion";
|
||||
static const std::string QUERY_KEY_SRM_UPDATE_SUPPORT = "SRMUpdateSupport";
|
||||
// whether OEM supports SRM update
|
||||
static const std::string QUERY_KEY_WVCDM_VERSION = "WidevineCdmVersion";
|
||||
|
||||
static const std::string QUERY_VALUE_TRUE = "True";
|
||||
static const std::string QUERY_VALUE_FALSE = "False";
|
||||
|
||||
@@ -407,13 +407,19 @@ enum CdmUsageSupportType {
|
||||
enum CdmUsageEntryStorageType {
|
||||
kStorageLicense,
|
||||
kStorageUsageInfo,
|
||||
kStorageUnknown,
|
||||
kStorageTypeUnknown,
|
||||
};
|
||||
|
||||
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 {
|
||||
|
||||
@@ -409,7 +409,12 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
|
||||
|
||||
CdmResponseType sts = session->AddKey(key_data);
|
||||
if (key_set_id) {
|
||||
*key_set_id = session->key_set_id();
|
||||
if ((session->is_offline() ||
|
||||
session->has_provider_session_token()) && !license_type_release) {
|
||||
*key_set_id = session->key_set_id();
|
||||
} else {
|
||||
key_set_id->clear();
|
||||
}
|
||||
}
|
||||
|
||||
switch (sts) {
|
||||
@@ -681,6 +686,28 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
std::ostringstream api_version_stream;
|
||||
api_version_stream << api_version;
|
||||
*query_response = api_version_stream.str();
|
||||
} else if (query_token == QUERY_KEY_CURRENT_SRM_VERSION) {
|
||||
uint16_t current_srm_version;
|
||||
if (!crypto_session.GetSrmVersion(¤t_srm_version)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetCurrentSRMVersion failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
std::ostringstream current_srm_version_stream;
|
||||
current_srm_version_stream << current_srm_version;
|
||||
*query_response = current_srm_version_stream.str();
|
||||
} else if (query_token == QUERY_KEY_SRM_UPDATE_SUPPORT) {
|
||||
bool is_srm_update_supported = crypto_session.IsSrmUpdateSupported();
|
||||
*query_response =
|
||||
is_srm_update_supported ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
||||
} else if (query_token == QUERY_KEY_WVCDM_VERSION) {
|
||||
std::string cdm_version;
|
||||
if (!Properties::GetWVCdmVersion(&cdm_version)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetWVCdmVersion failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
*query_response = cdm_version;
|
||||
} else {
|
||||
LOGW("CdmEngine::QueryStatus: Unknown status requested, token = %s",
|
||||
query_token.c_str());
|
||||
@@ -1261,42 +1288,47 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
usage_session_->Init(usage_property_set_.get());
|
||||
|
||||
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
if (!handle.RetrieveUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&usage_data)) {
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_4;
|
||||
} else {
|
||||
for (size_t k = 0; k < usage_data.size(); ++k) {
|
||||
CdmResponseType status2 =
|
||||
usage_session_->DeleteUsageEntry(usage_data[k]);
|
||||
if (status == NO_ERROR && status2 != NO_ERROR)
|
||||
status = status2;
|
||||
switch (usage_session_->get_usage_support_type()) {
|
||||
case kUsageEntrySupport: {
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
if (!handle.RetrieveUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), &usage_data)) {
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_4;
|
||||
} else {
|
||||
for (size_t k = 0; k < usage_data.size(); ++k) {
|
||||
CdmResponseType status2 = usage_session_->DeleteUsageEntry(
|
||||
usage_data[k].usage_entry_number);
|
||||
if (status == NO_ERROR && status2 != NO_ERROR)
|
||||
status = status2;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_5;
|
||||
}
|
||||
} else if (usage_session_->get_usage_support_type()
|
||||
== kUsageTableSupport) {
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure"
|
||||
"stops", j);
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
|
||||
} else {
|
||||
CdmResponseType status2 = usage_session_->
|
||||
DeleteMultipleUsageInformation(provider_session_tokens);
|
||||
if (status2 != NO_ERROR) {
|
||||
status = status2;
|
||||
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kUsageTableSupport: {
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete %d secure"
|
||||
"stops", j);
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
|
||||
} else {
|
||||
CdmResponseType status2 = usage_session_->
|
||||
DeleteMultipleUsageInformation(provider_session_tokens);
|
||||
if (status2 != NO_ERROR) status = status2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to initialize L%d device"
|
||||
@@ -1611,25 +1643,25 @@ void CdmEngine::OnTimerEvent() {
|
||||
for (CdmSessionList::iterator iter = sessions.begin();
|
||||
iter != sessions.end(); ++iter) {
|
||||
(*iter)->reset_usage_flags();
|
||||
if ((*iter)->get_usage_support_type() == kUsageEntrySupport)
|
||||
(*iter)->UpdateUsageEntryInformation();
|
||||
|
||||
if (!has_usage_been_updated) {
|
||||
// usage is updated for all sessions so this needs to be
|
||||
// called only once per update usage information period
|
||||
if ((*iter)->get_usage_support_type() == kUsageTableSupport) {
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = (*iter)->UpdateUsageTableInformation(),
|
||||
(*iter)->GetMetrics(),
|
||||
crypto_session_update_usage_information_,
|
||||
status);
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
switch ((*iter)->get_usage_support_type()) {
|
||||
case kUsageEntrySupport:
|
||||
(*iter)->UpdateUsageEntryInformation();
|
||||
break;
|
||||
case kUsageTableSupport:
|
||||
if (!has_usage_been_updated) {
|
||||
// usage is updated for all sessions so this needs to be
|
||||
// called only once per update usage information period
|
||||
CdmResponseType status = (*iter)->UpdateUsageTableInformation();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,15 +45,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();
|
||||
}
|
||||
|
||||
@@ -106,6 +97,13 @@ CdmResponseType CdmSession::Init(
|
||||
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.
|
||||
@@ -195,6 +193,9 @@ CdmResponseType CdmSession::Init(
|
||||
|
||||
CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
const CdmKeySetId& key_set_id, const CdmLicenseType license_type) {
|
||||
if (!key_set_id_.empty()) {
|
||||
file_handle_->UnreserveLicenseId(key_set_id_);
|
||||
}
|
||||
key_set_id_ = key_set_id;
|
||||
|
||||
DeviceFiles::LicenseState license_state;
|
||||
@@ -430,7 +431,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);
|
||||
}
|
||||
@@ -446,7 +448,7 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
license_parser_->provider_session_token().size(),
|
||||
license_parser_->provider_session_token().c_str());
|
||||
|
||||
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
|
||||
if (is_offline_ || has_provider_session_token()) {
|
||||
if (usage_support_type_ == kUsageEntrySupport)
|
||||
usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_);
|
||||
|
||||
@@ -556,8 +558,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
}
|
||||
has_decrypted_since_last_report_ = true;
|
||||
if (!is_usage_update_needed_) {
|
||||
is_usage_update_needed_ =
|
||||
!license_parser_->provider_session_token().empty();
|
||||
is_usage_update_needed_ = has_provider_session_token();
|
||||
}
|
||||
} else {
|
||||
Clock clock;
|
||||
@@ -576,7 +577,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;
|
||||
|
||||
@@ -606,8 +607,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;
|
||||
|
||||
@@ -641,38 +642,53 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
license_parser_->HandleKeyUpdateResponse(false, key_response);
|
||||
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RELEASE_KEY_ERROR : sts;
|
||||
|
||||
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
|
||||
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) {
|
||||
@@ -775,7 +791,7 @@ CdmResponseType CdmSession::ReleaseCrypto() {
|
||||
}
|
||||
|
||||
bool CdmSession::DeleteLicense() {
|
||||
if (!is_offline_ && license_parser_->provider_session_token().empty())
|
||||
if (!is_offline_ && !has_provider_session_token())
|
||||
return false;
|
||||
|
||||
if (is_offline_) {
|
||||
|
||||
@@ -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),
|
||||
@@ -48,7 +51,9 @@ CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
|
||||
update_usage_table_after_close_session_(false),
|
||||
is_destination_buffer_type_valid_(false),
|
||||
requested_security_level_(kLevelDefault),
|
||||
usage_support_type_(kUnknownUsageSupport),
|
||||
is_usage_support_type_valid_(false),
|
||||
usage_support_type_(kNonSecureUsageSupport),
|
||||
usage_table_header_(NULL),
|
||||
request_id_base_(0),
|
||||
cipher_mode_(kCipherModeCtr) {
|
||||
Init();
|
||||
@@ -121,6 +126,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;
|
||||
}
|
||||
|
||||
@@ -217,8 +232,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;
|
||||
}
|
||||
@@ -430,7 +444,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;
|
||||
@@ -470,8 +485,35 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
||||
random_sts,
|
||||
metrics::Pow2Bucket(sizeof(request_id_base_)));
|
||||
++request_id_index_;
|
||||
|
||||
CdmUsageSupportType usage_support_type;
|
||||
GetUsageSupportType(&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;
|
||||
}
|
||||
|
||||
@@ -1108,6 +1150,11 @@ CdmResponseType CryptoSession::UpdateUsageInformation() {
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!initialized_) return UNKNOWN_ERROR;
|
||||
|
||||
if (usage_table_header_ != NULL) {
|
||||
LOGV("UpdateUsageInformation: deprecated for OEMCrypto v13+");
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_UpdateUsageTable(),
|
||||
@@ -1264,6 +1311,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);
|
||||
|
||||
@@ -858,6 +858,11 @@ bool DeviceFiles::ListUsageInfoFiles(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usage_info_file_names == NULL) {
|
||||
LOGW("DeviceFiles::ListUsageInfoFiles: usage_info_file_names not provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get list of filenames
|
||||
std::vector<std::string> filenames;
|
||||
if (!ListFiles(&filenames)) {
|
||||
@@ -982,7 +987,7 @@ bool DeviceFiles::StoreUsageTableInfo(
|
||||
const CdmUsageTableHeader& usage_table_header,
|
||||
const std::vector<CdmUsageEntryInfo>& usage_entry_info) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::StoreUsageTableHeader: not initialized");
|
||||
LOGW("DeviceFiles::StoreUsageTableInfo: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1009,7 +1014,7 @@ bool DeviceFiles::StoreUsageTableInfo(
|
||||
info->set_usage_info_file_name(
|
||||
usage_entry_info[i].usage_info_file_name);
|
||||
break;
|
||||
case kStorageUnknown:
|
||||
case kStorageTypeUnknown:
|
||||
default:
|
||||
info->set_storage(
|
||||
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN);
|
||||
@@ -1081,7 +1086,7 @@ bool DeviceFiles::RetrieveUsageTableInfo(
|
||||
break;
|
||||
case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN:
|
||||
default:
|
||||
(*usage_entry_info)[i].storage_type = kStorageUnknown;
|
||||
(*usage_entry_info)[i].storage_type = kStorageTypeUnknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -274,7 +275,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;
|
||||
@@ -330,6 +332,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,
|
||||
|
||||
@@ -29,14 +29,15 @@ RSA* GetKey(const std::string& serialized_key) {
|
||||
return NULL;
|
||||
}
|
||||
RSA* key = d2i_RSAPublicKey_bio(bio, NULL);
|
||||
BIO_free(bio);
|
||||
|
||||
if (key == NULL) {
|
||||
LOGE("GetKey: RSA key deserialization failure: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
BIO_free(bio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,65 @@ 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_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);
|
||||
|
||||
@@ -101,7 +89,7 @@ CdmResponseType UsageTableHeader::AddEntry(
|
||||
size_t number_of_entries = usage_entry_info_.size();
|
||||
usage_entry_info_.resize(*usage_entry_number + 1);
|
||||
for (size_t i = number_of_entries; i < usage_entry_info_.size() - 1; ++i) {
|
||||
usage_entry_info_[i].storage_type = kStorageUnknown;
|
||||
usage_entry_info_[i].storage_type = kStorageTypeUnknown;
|
||||
usage_entry_info_[i].key_set_id.clear();
|
||||
usage_entry_info_[i].usage_info_file_name.clear();
|
||||
}
|
||||
@@ -120,15 +108,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 +126,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,50 +150,67 @@ 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;
|
||||
}
|
||||
case kStorageUnknown:
|
||||
case kStorageTypeUnknown:
|
||||
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 = kStorageTypeUnknown;
|
||||
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 +218,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 +230,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 +240,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 +256,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 +272,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,
|
||||
@@ -274,7 +283,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kStorageUnknown:
|
||||
case kStorageTypeUnknown:
|
||||
default:
|
||||
LOGE(
|
||||
"UsageTableHeader::GetEntry: Attempting to retrieve usage "
|
||||
@@ -293,6 +302,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 +313,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 +322,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
LOGE("UsageTableHeader::StoreEntry: Failed to retrieve license");
|
||||
return USAGE_STORE_ENTRY_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 +337,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 +347,10 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
"information");
|
||||
return USAGE_STORE_ENTRY_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,
|
||||
@@ -350,7 +360,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kStorageUnknown:
|
||||
case kStorageTypeUnknown:
|
||||
default:
|
||||
LOGE(
|
||||
"UsageTableHeader::GetUsageEntry: Attempting to retrieve usage "
|
||||
@@ -361,41 +371,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
|
||||
@@ -403,18 +428,14 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
|
||||
// * update the usage header table and entry numbers
|
||||
// * save the usage table header and store the usage entry number and
|
||||
// usage entry along with the license to persistent memory
|
||||
// On errors, continue to the next license, but indicate on return that not
|
||||
// all licenses may have been upgraded.
|
||||
std::vector<std::string> key_set_ids;
|
||||
if (file_handle_->ListLicenses(&key_set_ids)) {
|
||||
LOGE(
|
||||
if (handle->ListLicenses(&key_set_ids)) {
|
||||
LOGW(
|
||||
"UpgradeUsageTableHeader::UpgradeLicensesFromUsageTable: unable to "
|
||||
"retrieve list of licenses");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
for (size_t i = 0; i < key_set_ids.size(); ++i) {
|
||||
DeviceFiles::LicenseState license_state;
|
||||
std::string init_data, key_request, key_response, key_renewal_request;
|
||||
@@ -423,7 +444,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,
|
||||
@@ -432,7 +453,6 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
|
||||
LOGW(
|
||||
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to "
|
||||
"retrieve license");
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -442,37 +462,26 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
|
||||
LOGW(
|
||||
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to "
|
||||
"retrieve provider session token");
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (provider_session_token.empty()) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
if (status != NO_ERROR) continue;
|
||||
|
||||
status = AddEntry(&crypto_session, true /* persistent license */,
|
||||
key_set_ids[i], kEmptyString, &usage_entry_number);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
if (status != NO_ERROR) continue;
|
||||
|
||||
status = crypto_session.CopyOldUsageEntry(provider_session_token);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
Shrink(metrics, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -480,26 +489,27 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
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)) {
|
||||
LOGW("UsageTableHeader::StoreEntry: Failed to store license");
|
||||
result = false;
|
||||
LOGE(
|
||||
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to store "
|
||||
"license");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
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
|
||||
@@ -509,27 +519,21 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
|
||||
// * once done processing all the usage records from a file, save the usage
|
||||
// information to persistent memory along with usage entry number and usage
|
||||
// entry.
|
||||
// On errors, continue to the next usage record, but indicate on return
|
||||
// that not all usage records may have been upgraded.
|
||||
std::vector<std::string> usage_info_file_names;
|
||||
if (file_handle_->ListUsageInfoFiles(&usage_info_file_names)) {
|
||||
LOGE(
|
||||
if (handle->ListUsageInfoFiles(&usage_info_file_names)) {
|
||||
LOGW(
|
||||
"UpgradeUsageTableHeader::UpgradeUsageInfoFromUsageTable: Unable to "
|
||||
"retrieve list of usage info file names");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
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",
|
||||
usage_info_file_names[i].c_str());
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -538,17 +542,13 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
|
||||
LOGW(
|
||||
"UsageTableHeader::UpgradeUsageInfoFromUsageTable: Provider "
|
||||
"session id empty");
|
||||
result = false;
|
||||
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) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
if (status != NO_ERROR) continue;
|
||||
|
||||
// TODO(rfrias): We need to fill in the app id, but it is hashed
|
||||
// and we have no way to extract. Use the hased filename instead?
|
||||
@@ -556,18 +556,14 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
|
||||
usage_data[j].key_set_id, kEmptyString,
|
||||
&(usage_data[i].usage_entry_number));
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
if (status != NO_ERROR) continue;
|
||||
|
||||
status = crypto_session.CopyOldUsageEntry(
|
||||
usage_data[i].provider_session_token);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
Shrink(metrics, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -575,23 +571,21 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
Shrink(metrics, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file_handle_->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
|
||||
LOGW(
|
||||
if (!handle->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
|
||||
LOGE(
|
||||
"UsageTableHeader::StoreUsageInfo: Failed to store usage records to "
|
||||
"%s",
|
||||
usage_info_file_names[i].c_str());
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,9 @@
|
||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
#include "usage_table_header.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
|
||||
#include "crypto_session.h"
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
@@ -52,58 +50,10 @@ const CdmUsageEntryInfo kUsageEntryInfoStorageTypeUnknown = {
|
||||
.storage_type = kStorageTypeUnknown,
|
||||
.key_set_id = "",
|
||||
.usage_info_file_name = ""};
|
||||
|
||||
const std::vector<std::string> kEmptyLicenseList;
|
||||
|
||||
const std::string kLicenseArray[] = {
|
||||
kUsageEntryInfoOfflineLicense1.key_set_id,
|
||||
kUsageEntryInfoOfflineLicense2.key_set_id,
|
||||
kUsageEntryInfoOfflineLicense3.key_set_id,
|
||||
};
|
||||
const size_t kLicenseArraySize = sizeof(kLicenseArray)/
|
||||
sizeof(kLicenseArray[0]);
|
||||
std::vector<std::string> kLicenseList;
|
||||
|
||||
const std::vector<std::string> kEmptyUsageInfoFilesList;
|
||||
|
||||
const std::string kUsageInfoFileArray[] = {
|
||||
kUsageEntryInfoSecureStop1.usage_info_file_name,
|
||||
kUsageEntryInfoSecureStop2.usage_info_file_name,
|
||||
kUsageEntryInfoSecureStop3.usage_info_file_name,
|
||||
};
|
||||
const size_t kUsageInfoFileArraySize = sizeof(kUsageInfoFileArray)/
|
||||
sizeof(kUsageInfoFileArray[0]);
|
||||
std::vector<std::string> kUsageInfoFileList;
|
||||
|
||||
const DeviceFiles::CdmUsageData kCdmUsageData1 = {
|
||||
.provider_session_token = "provider_session_token_1",
|
||||
.license_request = "license_request_1",
|
||||
.license = "license_1",
|
||||
.key_set_id = "key_set_id_1",
|
||||
.usage_entry = "usage_entry_1",
|
||||
.usage_entry_number = 0,
|
||||
};
|
||||
const DeviceFiles::CdmUsageData kCdmUsageData2 = {
|
||||
.provider_session_token = "provider_session_token_2",
|
||||
.license_request = "license_request_2",
|
||||
.license = "license_2",
|
||||
.key_set_id = "key_set_id_2",
|
||||
.usage_entry = "usage_entry_2",
|
||||
.usage_entry_number = 0,
|
||||
};
|
||||
const DeviceFiles::CdmUsageData kCdmUsageData3 = {
|
||||
.provider_session_token = "provider_session_token_3",
|
||||
.license_request = "license_request_3",
|
||||
.license = "license_3",
|
||||
.key_set_id = "key_set_id_3",
|
||||
.usage_entry = "usage_entry_3",
|
||||
.usage_entry_number = 0,
|
||||
};
|
||||
const std::vector<DeviceFiles::CdmUsageData> kEmptyUsageInfoUsageDataList;
|
||||
|
||||
const std::vector<CdmUsageEntryInfo> kEmptyUsageEntryInfoVector;
|
||||
std::vector<CdmUsageEntryInfo> kUsageEntryInfoVector;
|
||||
|
||||
const std::vector<CdmUsageEntryInfo> kUsageEntryInfoVector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
|
||||
kUsageEntryInfoStorageTypeUnknown};
|
||||
const DeviceFiles::LicenseState kActiveLicenseState =
|
||||
DeviceFiles::kLicenseStateActive;
|
||||
const CdmInitData kPsshData = "pssh data";
|
||||
@@ -118,36 +68,6 @@ int64_t kPlaybackStartTime = 1030005;
|
||||
int64_t kPlaybackDuration = 300;
|
||||
int64_t kGracePeriodEndTime = 60;
|
||||
|
||||
namespace {
|
||||
|
||||
void InitVectorConstants() {
|
||||
kUsageEntryInfoVector.clear();
|
||||
kUsageEntryInfoVector.push_back(kUsageEntryInfoOfflineLicense1);
|
||||
kUsageEntryInfoVector.push_back(kUsageEntryInfoSecureStop1);
|
||||
kUsageEntryInfoVector.push_back(kUsageEntryInfoStorageTypeUnknown);
|
||||
|
||||
kUsageInfoFileList.clear();
|
||||
for (size_t i = 0; i < kUsageInfoFileArraySize; i++) {
|
||||
kUsageInfoFileList.push_back(kUsageInfoFileArray[i]);
|
||||
}
|
||||
|
||||
kLicenseList.clear();
|
||||
for (size_t i = 0; i < kLicenseArraySize; i++) {
|
||||
kLicenseList.push_back(kLicenseArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ToVector(std::vector<CdmUsageEntryInfo>& vec,
|
||||
const CdmUsageEntryInfo* arr, size_t total_size) {
|
||||
size_t max = total_size / sizeof(CdmUsageEntryInfo);
|
||||
vec.clear();
|
||||
for (size_t i = 0; i < max; i++) {
|
||||
vec.push_back(arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
||||
class MockDeviceFiles : public DeviceFiles {
|
||||
public:
|
||||
MockDeviceFiles() : DeviceFiles(&file_system_) { Init(kSecurityLevelL1); }
|
||||
@@ -162,17 +82,12 @@ class MockDeviceFiles : public DeviceFiles {
|
||||
bool(const std::string&, const std::string&, std::string*,
|
||||
CdmKeyMessage*, CdmKeyResponse*, CdmUsageEntry*,
|
||||
uint32_t*));
|
||||
MOCK_METHOD0(DeleteAllLicenses, bool());
|
||||
MOCK_METHOD7(StoreUsageInfo,
|
||||
bool(const std::string&, const CdmKeyMessage&,
|
||||
const CdmKeyResponse&, const std::string&,
|
||||
const std::string&, const CdmUsageEntry&, uint32_t));
|
||||
MOCK_METHOD2(RetrieveUsageInfo,
|
||||
bool(const std::string&, std::vector<CdmUsageData>*));
|
||||
MOCK_METHOD1(ListLicenses,
|
||||
bool(std::vector<std::string>* key_set_ids));
|
||||
MOCK_METHOD1(ListUsageInfoFiles,
|
||||
bool(std::vector<std::string>* usage_info_files));
|
||||
|
||||
private:
|
||||
FileSystem file_system_;
|
||||
@@ -180,8 +95,7 @@ class MockDeviceFiles : public DeviceFiles {
|
||||
|
||||
class MockCryptoSession : public CryptoSession {
|
||||
public:
|
||||
MockCryptoSession(metrics::CryptoMetrics* metrics)
|
||||
: CryptoSession(metrics) {}
|
||||
MockCryptoSession() : CryptoSession(NULL) {}
|
||||
MOCK_METHOD1(Open, CdmResponseType(SecurityLevel));
|
||||
MOCK_METHOD1(LoadUsageTableHeader,
|
||||
CdmResponseType(const CdmUsageTableHeader&));
|
||||
@@ -207,16 +121,11 @@ using ::testing::UnorderedElementsAre;
|
||||
using ::testing::UnorderedElementsAreArray;
|
||||
|
||||
class UsageTableHeaderTest : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase() {
|
||||
InitVectorConstants();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
// UsageTableHeader will take ownership of the pointer
|
||||
device_files_ = new MockDeviceFiles();
|
||||
crypto_session_ = new MockCryptoSession(&crypto_metrics_);
|
||||
crypto_session_ = new MockCryptoSession();
|
||||
usage_table_header_ = new UsageTableHeader();
|
||||
|
||||
// usage_table_header_ object takes ownership of these objects
|
||||
@@ -242,7 +151,6 @@ class UsageTableHeaderTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
MockDeviceFiles* device_files_;
|
||||
metrics::CryptoMetrics crypto_metrics_;
|
||||
MockCryptoSession* crypto_session_;
|
||||
UsageTableHeader* usage_table_header_;
|
||||
};
|
||||
@@ -259,86 +167,21 @@ TEST_F(UsageTableHeaderTest, InitError) {
|
||||
|
||||
class UsageTableHeaderInitializationTest
|
||||
: public UsageTableHeaderTest,
|
||||
public ::testing::WithParamInterface<CdmSecurityLevel> {
|
||||
public:
|
||||
static void SetUpTestCase() {
|
||||
InitVectorConstants();
|
||||
}
|
||||
|
||||
};
|
||||
public ::testing::WithParamInterface<CdmSecurityLevel> {};
|
||||
|
||||
TEST_P(UsageTableHeaderInitializationTest, CreateUsageTableHeader) {
|
||||
std::vector<CdmUsageEntryInfo> empty_usage_entry_info;
|
||||
|
||||
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
|
||||
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
|
||||
Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyLicenseList),
|
||||
Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageInfoFilesList),
|
||||
Return(false)));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
|
||||
kEmptyUsageEntryInfoVector))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
|
||||
TEST_P(UsageTableHeaderInitializationTest, Upgrade_UnableToRetrieveLicenses) {
|
||||
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
|
||||
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
|
||||
Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kLicenseList),
|
||||
Return(true)));
|
||||
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageInfoFilesList),
|
||||
Return(false)));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
|
||||
// TODO: Why not being called?
|
||||
//EXPECT_CALL(*device_files_, DeleteAllLicenses()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
|
||||
kEmptyUsageEntryInfoVector))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
for (size_t i = 0; i < kLicenseList.size(); ++i)
|
||||
device_files_->DeleteLicense(kLicenseList[i]);
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
|
||||
TEST_P(UsageTableHeaderInitializationTest, Upgrade_UnableToRetrieveUsageInfo) {
|
||||
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
|
||||
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
|
||||
Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyLicenseList),
|
||||
Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUsageInfoFileList),
|
||||
Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
|
||||
kEmptyUsageEntryInfoVector))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
for (size_t i = 0; i < kUsageInfoFileList.size(); ++i) {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageInfo(kUsageInfoFileList[i], NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kEmptyUsageInfoUsageDataList),
|
||||
Return(false)));
|
||||
}
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
@@ -552,7 +395,7 @@ TEST_F(UsageTableHeaderTest, UpdateEntry) {
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) {
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector);
|
||||
uint32_t usage_entry_number = kUsageEntryInfoVector.size();
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_NE(NO_ERROR, usage_table_header_->DeleteEntry(
|
||||
usage_entry_number, device_files_, &metrics));
|
||||
@@ -576,17 +419,14 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) {
|
||||
//
|
||||
// # of usage entries 4 4
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
|
||||
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -615,17 +455,14 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) {
|
||||
//
|
||||
// # of usage entries 4 3
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
|
||||
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -663,17 +500,14 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) {
|
||||
//
|
||||
// # of usage entries 4 3
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
|
||||
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoSecureStop2};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop2
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -716,19 +550,17 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) {
|
||||
// # of usage entries 5 2
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DeleteEntry_LastOfflineEntriesHaveMissingLicenses) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
|
||||
kUsageEntryInfoOfflineLicense3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
device_files_->DeleteAllLicenses();
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
*crypto_session_,
|
||||
@@ -768,18 +600,15 @@ TEST_F(UsageTableHeaderTest,
|
||||
//
|
||||
// # of usage entries 5 2
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
|
||||
kUsageEntryInfoSecureStop3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -834,18 +663,15 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) {
|
||||
// # of usage entries 5 2
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DeleteEntry_LastOfflineEntriesHaveIncorrectUsageEntryNumber) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
|
||||
kUsageEntryInfoOfflineLicense3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[usage_entry_info_vector.size() - 1].key_set_id,
|
||||
@@ -903,20 +729,17 @@ TEST_F(UsageTableHeaderTest,
|
||||
// # of usage entries 5 2
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DeleteEntry_LastSecureStopEntriesHaveIncorrectUsageEntryNumber) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
|
||||
kUsageEntryInfoSecureStop3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
uint32_t usage_entry_number_after_deleted_entry =
|
||||
usage_entry_number_to_be_deleted + 1;
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -981,18 +804,15 @@ TEST_F(UsageTableHeaderTest,
|
||||
//
|
||||
// # of usage entries 7 4
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoOfflineLicense1,
|
||||
kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3,
|
||||
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -1037,20 +857,17 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) {
|
||||
// # of usage entries 5 5
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DeleteEntry_LastEntryIsOffline_MoveOfflineEntryFailed) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
|
||||
kUsageEntryInfoOfflineLicense3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_usage_entry_number].key_set_id,
|
||||
@@ -1106,20 +923,17 @@ TEST_F(UsageTableHeaderTest,
|
||||
// # of usage entries 5 5
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DeleteEntry_LastEntryIsSecureStop_MoveSecureStopEntryFailed) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
|
||||
kUsageEntryInfoSecureStop3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
@@ -1182,21 +996,18 @@ TEST_F(UsageTableHeaderTest,
|
||||
// # of usage entries 7 5
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DeleteEntry_LastEntriesAreOfflineAndUnknown_MoveOfflineEntryFailed) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
|
||||
kUsageEntryInfoOfflineLicense3, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoStorageTypeUnknown};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
|
||||
@@ -1263,21 +1074,18 @@ TEST_F(UsageTableHeaderTest,
|
||||
// # of usage entries 7 5
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DeleteEntry_LastEntriesAreSecureStopAndUnknown_MoveOfflineEntryFailed) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
|
||||
kUsageEntryInfoSecureStop3, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoStorageTypeUnknown};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
|
||||
.Times(2)
|
||||
@@ -1339,20 +1147,17 @@ TEST_F(UsageTableHeaderTest,
|
||||
//
|
||||
// # of usage entries 5 4
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
|
||||
kUsageEntryInfoOfflineLicense3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_usage_entry_number].key_set_id,
|
||||
@@ -1456,20 +1261,17 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) {
|
||||
//
|
||||
// # of usage entries 5 4
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
|
||||
kUsageEntryInfoSecureStop3};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
|
||||
.Times(2)
|
||||
@@ -1558,21 +1360,18 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) {
|
||||
//
|
||||
// # of usage entries 7 4
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
|
||||
kUsageEntryInfoOfflineLicense3, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoStorageTypeUnknown};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
|
||||
@@ -1680,21 +1479,18 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) {
|
||||
//
|
||||
// # of usage entries 7 4
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
|
||||
kUsageEntryInfoSecureStop3, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoStorageTypeUnknown};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoSecureStop1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop3
|
||||
metrics::CryptoMetrics metrics;
|
||||
metrics::MetricsGroup metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
|
||||
.Times(2)
|
||||
@@ -1762,30 +1558,4 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) {
|
||||
device_files_, &metrics));
|
||||
}
|
||||
|
||||
// If the crypto session says the usage table header is stale, init should fail.
|
||||
TEST_F(UsageTableHeaderTest, StaleHeader) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
|
||||
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
sizeof(usage_entry_info_array));
|
||||
|
||||
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader),
|
||||
SetArgPointee<1>(usage_entry_info_vector),
|
||||
Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, LoadUsageTableHeader(kUsageTableHeader))
|
||||
.WillOnce(Return(LOAD_USAGE_HEADER_GENERATION_SKEW));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, DeleteAllLicenses()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
|
||||
kEmptyUsageEntryInfoVector))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user