Check for open session when initializing usage table.
[ Merge of http://go/wvgerrit/122984 ] There was an issue encountered by some vendors with how the usage table was initialized on some devices. Previously, the CDM would open an OEMCrypto session first, then initialize the usage table (loading existing or creating a new one). On these devices, OEMCrypto_CreateUsageTableHeader() and OEMCrypto_LoadUsageTableHeader() would fail if there were any open sessions. This CL changes the initialization process to create/load the usage table before opening an OEMCrypto session. This change also lays the ground work for another usage table fix to address GTS tests failure. In the process, several of the functions for the usage table have been split up into smaller chunks of code. This required additional changes to the usage table unittest to keep them up to date. Bug: 169195093 Bug: 180639135 Test: Linux unittests and MediaDrmTest Change-Id: Ifbf35f5d8cff5b89fea9b16edb998c84803f4fbe
This commit is contained in:
@@ -293,7 +293,7 @@ class CryptoSession {
|
||||
// exist as long as the new CryptoSession exists.
|
||||
explicit CryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
||||
|
||||
int session_count() { return session_count_; }
|
||||
int session_count() const { return session_count_; }
|
||||
|
||||
private:
|
||||
friend class CryptoSessionForTest;
|
||||
@@ -313,6 +313,13 @@ class CryptoSession {
|
||||
}
|
||||
|
||||
void Init();
|
||||
|
||||
// Will set up the UsageTableHeader for this session. This may require
|
||||
// creating a new UsageTableHeader if the global instance has not
|
||||
// been initialized.
|
||||
// Note: This function will lock the global static field lock in write mode.
|
||||
bool SetUpUsageTableHeader(SecurityLevel requested_security_level);
|
||||
|
||||
CdmResponseType GetTokenFromKeybox(std::string* token);
|
||||
CdmResponseType GetTokenFromOemCert(std::string* token);
|
||||
static bool ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
@@ -355,9 +362,15 @@ class CryptoSession {
|
||||
// These methods should be used to take the various CryptoSession mutexes in
|
||||
// preference to taking the mutexes directly.
|
||||
//
|
||||
// A lock should be taken on the Static Field Mutex before accessing any of
|
||||
// CryptoSession's non-atomic static fields. It can be taken as a reader or as
|
||||
// a writer, depending on how you will be accessing the static fields.
|
||||
// A lock should be taken on the Static Field Mutex before accessing
|
||||
// any of CryptoSession's non-atomic static fields with the exception
|
||||
// of the Usage Table Mutex. The Static Field Mutex can be taken as
|
||||
// a reader or as a writer, depending on how you will be accessing
|
||||
// the static fields. The Usage Table Mutex should be taken when
|
||||
// reading and writing to the static usage table fields (creating,
|
||||
// destroying or taking a pointer of the handles). The purpose of
|
||||
// having a separate mutex for usage table is due to the recursive
|
||||
// nature of initializing the global usage table.
|
||||
//
|
||||
// Before calling into OEMCrypto, code must take locks on the OEMCrypto Mutex
|
||||
// and/or the OEMCrypto Session Mutex. Which of them should be taken and how
|
||||
@@ -414,6 +427,9 @@ class CryptoSession {
|
||||
static shared_mutex static_field_mutex_;
|
||||
static shared_mutex oem_crypto_mutex_;
|
||||
std::mutex oem_crypto_session_mutex_;
|
||||
// Usage table mutex used only when performing write operations on
|
||||
// the static usage table pointers.
|
||||
static std::recursive_mutex usage_table_mutex_;
|
||||
|
||||
static bool initialized_;
|
||||
static int session_count_;
|
||||
@@ -446,8 +462,10 @@ class CryptoSession {
|
||||
// Open session-cached result of OEMCrypto_SupportsUsageTable().
|
||||
CachedBooleanProperty has_usage_info_support_ = kBooleanUnset;
|
||||
UsageTableHeader* usage_table_header_ = nullptr;
|
||||
static UsageTableHeader* usage_table_header_l1_;
|
||||
static UsageTableHeader* usage_table_header_l3_;
|
||||
// These fields are protected by |usage_table_mutex_| and not
|
||||
// |static_field_mutex_|.
|
||||
static std::unique_ptr<UsageTableHeader> usage_table_header_l1_;
|
||||
static std::unique_ptr<UsageTableHeader> usage_table_header_l3_;
|
||||
|
||||
std::string request_id_;
|
||||
static std::atomic<uint64_t> request_id_index_source_;
|
||||
|
||||
@@ -53,8 +53,12 @@ class UsageTableHeader {
|
||||
UsageTableHeader();
|
||||
virtual ~UsageTableHeader() {}
|
||||
|
||||
// |crypto_session| is used to create or load a usage master table and
|
||||
// not cached beyound this call.
|
||||
// |crypto_session| is used to create or load a usage master table
|
||||
// and not cached beyound this call.
|
||||
// First attempts to restore the usage table from the device files.
|
||||
// If restoring fails, then a new usage table is created.
|
||||
// Note: No OEMCrypto session for the same security level should be
|
||||
// opened before calling.
|
||||
bool Init(CdmSecurityLevel security_level, CryptoSession* crypto_session);
|
||||
|
||||
// |persistent_license| false indicates usage info record
|
||||
@@ -125,6 +129,32 @@ class UsageTableHeader {
|
||||
}
|
||||
|
||||
private:
|
||||
// == Initialization methods ==
|
||||
// These should only be called during table initialization.
|
||||
// All parameters are assumed valid.
|
||||
|
||||
// Creates a new, empty usage table. Any existing usage table files
|
||||
// will be deleted.
|
||||
bool CreateNewTable(CryptoSession* const crypto_session);
|
||||
// Attempts to restore the usage table from persistent storage, and
|
||||
// loads the usage table header into OEMCrypto.
|
||||
// Note: No other OEMCrypto session should be opened before calling.
|
||||
bool RestoreTable(CryptoSession* const crypto_session);
|
||||
|
||||
// Performs a check that there are no open OEMCrypto sessions for
|
||||
// the current security level of the usage table.
|
||||
bool OpenSessionCheck(CryptoSession* const crypto_session);
|
||||
// Performs a check that the OEMCrypto table can support at least
|
||||
// one more entry if the table is at or near the reported capacity.
|
||||
// If this check fails, a new usage table SHOULD be created.
|
||||
bool CapacityCheck(CryptoSession* const crypto_session);
|
||||
|
||||
// Attempts to determine the capacity of the OEMCrypto usage table.
|
||||
// Sets the result to |potential_table_capacity_|.
|
||||
bool DetermineTableCapacity(CryptoSession* crypto_session);
|
||||
|
||||
// == Table operation methods ==
|
||||
|
||||
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
|
||||
const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to /* usage entry number */,
|
||||
@@ -153,8 +183,6 @@ class UsageTableHeader {
|
||||
// evicted.
|
||||
CdmResponseType ReleaseOldestEntry(metrics::CryptoMetrics* metrics);
|
||||
|
||||
virtual bool is_inited() { return is_inited_; }
|
||||
|
||||
// Performs and LRU upgrade on all loaded CdmUsageEntryInfo from a
|
||||
// device file that had not yet been upgraded to use the LRU data.
|
||||
virtual bool LruUpgradeAllUsageEntries();
|
||||
@@ -213,16 +241,15 @@ class UsageTableHeader {
|
||||
// by CdmSession.
|
||||
std::unique_ptr<DeviceFiles> device_files_;
|
||||
std::unique_ptr<FileSystem> file_system_;
|
||||
CdmSecurityLevel security_level_;
|
||||
SecurityLevel requested_security_level_;
|
||||
CdmSecurityLevel security_level_ = kSecurityLevelUninitialized;
|
||||
SecurityLevel requested_security_level_ = kLevelDefault;
|
||||
|
||||
CdmUsageTableHeader usage_table_header_;
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_;
|
||||
|
||||
// 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_;
|
||||
// Table is sync with persistent storage and can be used by the CDM
|
||||
// to interact with OEMCrypto.
|
||||
bool is_initialized_ = false;
|
||||
|
||||
// Synchonizes access to the Usage Table Header and bookkeeping
|
||||
// data-structures
|
||||
|
||||
Reference in New Issue
Block a user