Reworked DeleteEntry() into InvalidateEntry().
[ Merge of http://go/wvgerrit/95406 ] There was an issue with DeleteEntry() where it would result in an invalid table state if shrinking the usage table when the number of sessions is at its max. This required changing how the usage table invalidates entries. Now, after invalidating an entry (marking an entry as kStorageTypeUnknown) the table is defragmented if specified to. Defragmentation involves: 1) Move valid entries near the end of the table to the position of invalid entries near the front of the table. 2) Shrinking the table to cut off trailing invalid entries. This change updates the existing tests to pass, but still needs new tests for some of the edge cases. Bug: 150887808 Bug: 149100568 Test: Linux unit tests and Android unit tests Change-Id: I70c7b296e5e4b367746fcdaabbf0f12dcfb39230
This commit is contained in:
@@ -73,18 +73,21 @@ 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.
|
||||
virtual CdmResponseType DeleteEntry(uint32_t usage_entry_number,
|
||||
DeviceFiles* handle,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
// to InvalidateEntry and MoveEntry are made.
|
||||
// If |defrag_table| is true, the table will be defragmented after
|
||||
// the entry has been invalidated.
|
||||
virtual CdmResponseType InvalidateEntry(uint32_t usage_entry_number,
|
||||
bool defrag_table,
|
||||
DeviceFiles* device_files,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
|
||||
// Test only method. This method emulates the behavior of DeleteEntry
|
||||
// Test only method. This method emulates the behavior of InvalidateEntry
|
||||
// without actually invoking OEMCrypto (through CryptoSession)
|
||||
// or storage (through DeviceFiles). It modifies internal data structures
|
||||
// when DeleteEntry is mocked. This allows one to test methods that are
|
||||
// dependent on DeleteEntry without having to set expectations
|
||||
// for the objects that DeleteEntry depends on.
|
||||
void DeleteEntryForTest(uint32_t usage_entry_number);
|
||||
// when InvalidateEntry is mocked. This allows one to test methods that are
|
||||
// dependent on InvalidateEntry without having to set expectations
|
||||
// for the objects that InvalidateEntry depends on.
|
||||
void InvalidateEntryForTest(uint32_t usage_entry_number);
|
||||
|
||||
size_t size() { return usage_entry_info_.size(); }
|
||||
|
||||
@@ -115,17 +118,27 @@ class UsageTableHeader {
|
||||
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
|
||||
const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to /* usage entry number */,
|
||||
DeviceFiles* handle,
|
||||
DeviceFiles* device_files,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
|
||||
CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
CdmResponseType GetEntry(uint32_t usage_entry_number,
|
||||
DeviceFiles* device_files,
|
||||
CdmUsageEntry* usage_entry);
|
||||
CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
CdmResponseType StoreEntry(uint32_t usage_entry_number,
|
||||
DeviceFiles* device_files,
|
||||
const CdmUsageEntry& usage_entry);
|
||||
|
||||
// Stores the usage table and it's info. This will increment
|
||||
// |store_table_counter_| if successful.
|
||||
bool StoreTable(DeviceFiles* device_files);
|
||||
|
||||
CdmResponseType Shrink(metrics::CryptoMetrics* metrics,
|
||||
uint32_t number_of_usage_entries_to_delete);
|
||||
|
||||
// Must lock table before calling.
|
||||
CdmResponseType DefragTable(DeviceFiles* device_files,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
|
||||
virtual bool is_inited() { return is_inited_; }
|
||||
|
||||
// Performs and LRU upgrade on all loaded CdmUsageEntryInfo from a
|
||||
@@ -184,7 +197,7 @@ class UsageTableHeader {
|
||||
// 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.
|
||||
std::unique_ptr<DeviceFiles> file_handle_;
|
||||
std::unique_ptr<DeviceFiles> device_files_;
|
||||
std::unique_ptr<FileSystem> file_system_;
|
||||
CdmSecurityLevel security_level_;
|
||||
SecurityLevel requested_security_level_;
|
||||
@@ -217,6 +230,11 @@ class UsageTableHeader {
|
||||
// assumed to be |kMinimumUsageTableEntriesSupported|.
|
||||
size_t potential_table_capacity_ = 0u;
|
||||
|
||||
// Counts the number of successful calls to |StoreTable()|. Used
|
||||
// to reduce the number of calls to device files for certain
|
||||
// table operations.
|
||||
uint32_t store_table_counter_ = 0u;
|
||||
|
||||
#if defined(UNIT_TEST)
|
||||
// Test related declarations
|
||||
friend class UsageTableHeaderTest;
|
||||
@@ -228,7 +246,7 @@ class UsageTableHeader {
|
||||
|
||||
// These setters are for testing only. Takes ownership of the pointers.
|
||||
void SetDeviceFiles(DeviceFiles* device_files) {
|
||||
file_handle_.reset(device_files);
|
||||
device_files_.reset(device_files);
|
||||
}
|
||||
void SetCryptoSession(CryptoSession* crypto_session) {
|
||||
test_crypto_session_.reset(crypto_session);
|
||||
|
||||
@@ -533,6 +533,14 @@ struct CdmUsageEntryInfo {
|
||||
// else storage_type == kStorageTypeUnknown
|
||||
return true;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
storage_type = kStorageTypeUnknown;
|
||||
key_set_id.clear();
|
||||
usage_info_file_name.clear();
|
||||
last_use_time = 0;
|
||||
offline_license_expiry_time = 0;
|
||||
}
|
||||
};
|
||||
|
||||
enum CdmKeySecurityLevel {
|
||||
|
||||
Reference in New Issue
Block a user