diff --git a/libwvdrmengine/cdm/include/wv_content_decryption_module.h b/libwvdrmengine/cdm/include/wv_content_decryption_module.h index 909156ce..d6f6a5ab 100644 --- a/libwvdrmengine/cdm/include/wv_content_decryption_module.h +++ b/libwvdrmengine/cdm/include/wv_content_decryption_module.h @@ -52,9 +52,39 @@ class WvMetricsSnapshot { ::time_t timestamp_ = 0; }; +class WvMetricsSnapshotQueue + : public android::LightRefBase { + public: + WvMetricsSnapshotQueue(); + explicit WvMetricsSnapshotQueue(size_t capacity) : capacity_(capacity) {} + + size_t capacity() const { return capacity_; } + size_t size() const { return snapshots_.size(); } + + WvMetricsSnapshotQueue(const WvMetricsSnapshotQueue&) = delete; + WvMetricsSnapshotQueue(WvMetricsSnapshotQueue&&) = delete; + WvMetricsSnapshotQueue& operator=(const WvMetricsSnapshotQueue&) = delete; + WvMetricsSnapshotQueue& operator=(WvMetricsSnapshotQueue&&) = delete; + + void PushMetrics(WvMetricsSnapshot&& snapshot); + void PushMetrics(const WvMetricsSnapshot& snapshot); + + bool GetAll(std::vector* snapshots) const; + + void Clear(); + + private: + void ReFit(); + + const size_t capacity_; + mutable std::mutex mutex_; + std::deque snapshots_; +}; + class WvContentDecryptionModule : public android::RefBase, public TimerHandler { public: WvContentDecryptionModule(); + explicit WvContentDecryptionModule(WvMetricsSnapshotQueue* metrics_queue); virtual ~WvContentDecryptionModule(); // Static methods @@ -308,7 +338,8 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { // Contains a finite list of histories of different CDM engine instances. // When a CDM engine is closed, its metrics will be saved. - std::deque saved_metrics_snapshots_; + // Only used if not null. + WvMetricsSnapshotQueue* saved_metrics_snapshots_ = nullptr; CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule); }; diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index 9b0d507d..9ce0108f 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -86,10 +86,48 @@ std::string WvMetricsSnapshot::GetFormattedTimestamp() const { return result; } +WvMetricsSnapshotQueue::WvMetricsSnapshotQueue() + : capacity_(kMaxSavedMetricsSnapshotCount) {} + +void WvMetricsSnapshotQueue::PushMetrics(WvMetricsSnapshot&& snapshot) { + std::unique_lock lock(mutex_); + snapshots_.push_front(std::move(snapshot)); + ReFit(); +} + +void WvMetricsSnapshotQueue::PushMetrics(const WvMetricsSnapshot& snapshot) { + std::unique_lock lock(mutex_); + snapshots_.push_front(snapshot); + ReFit(); +} + +bool WvMetricsSnapshotQueue::GetAll( + std::vector* snapshots) const { + if (snapshots == nullptr) return false; + std::unique_lock lock(mutex_); + snapshots->assign(snapshots_.begin(), snapshots_.end()); + return true; +} + +void WvMetricsSnapshotQueue::Clear() { + std::unique_lock lock(mutex_); + snapshots_.clear(); +} + +void WvMetricsSnapshotQueue::ReFit() { + if (capacity_ > 0 && snapshots_.size() > capacity_) { + snapshots_.resize(capacity_); + } +} + std::mutex WvContentDecryptionModule::session_sharing_id_generation_lock_; WvContentDecryptionModule::WvContentDecryptionModule() {} +WvContentDecryptionModule::WvContentDecryptionModule( + WvMetricsSnapshotQueue* metrics_queue) + : saved_metrics_snapshots_(metrics_queue) {} + WvContentDecryptionModule::~WvContentDecryptionModule() { CryptoSession::DisableDelayedTermination(); CloseAllCdms(); @@ -497,11 +535,16 @@ CdmResponseType WvContentDecryptionModule::GetAllSavedMetricsSnapshots( if (snapshots == nullptr) { return CdmResponseType(PARAMETER_NULL); } - std::unique_lock auto_lock(cdms_lock_); + if (saved_metrics_snapshots_ == nullptr) { + snapshots->clear(); + // Storing the metrics might not be available in some cases. + return CdmResponseType(NO_ERROR); + } // This has the potential to be an expensive operation. However, // this function is only used during debug reporting. - snapshots->assign(saved_metrics_snapshots_.cbegin(), - saved_metrics_snapshots_.cend()); + if (!saved_metrics_snapshots_->GetAll(snapshots)) { + return CdmResponseType(UNKNOWN_ERROR); + } return CdmResponseType(NO_ERROR); } @@ -521,12 +564,9 @@ CdmResponseType WvContentDecryptionModule::GetCurrentMetricsInternal( void WvContentDecryptionModule::SaveMetrics( const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics&& metrics) { - // Caller should have acquired |cdms_lock_|. - saved_metrics_snapshots_.push_front( + if (saved_metrics_snapshots_ == nullptr) return; + saved_metrics_snapshots_->PushMetrics( WvMetricsSnapshot::MakeSnapshot(identifier, std::move(metrics))); - if (saved_metrics_snapshots_.size() > kMaxSavedMetricsSnapshotCount) { - saved_metrics_snapshots_.resize(kMaxSavedMetricsSnapshotCount); - } } WvContentDecryptionModule::CdmInfo::CdmInfo() diff --git a/libwvdrmengine/src/WVCDMSingleton.cpp b/libwvdrmengine/src/WVCDMSingleton.cpp index 6589613d..1d1fe23a 100644 --- a/libwvdrmengine/src/WVCDMSingleton.cpp +++ b/libwvdrmengine/src/WVCDMSingleton.cpp @@ -15,12 +15,16 @@ namespace wvdrm { -using wvcdm::WvContentDecryptionModule; using android::Mutex; using android::sp; using android::wp; +using wvcdm::WvContentDecryptionModule; +using wvcdm::WvMetricsSnapshotQueue; Mutex cdmLock; +// TODO(b/270166158): Make this a loadable/storable when provided +// a special debug property. +sp sMetricsQueue; // The strong pointers that keep this object alive live in the plugin objects. // If all the plugins are deleted, the CDM will be deleted, and subsequent // invocations of this code will construct a new CDM. @@ -29,11 +33,16 @@ wp sCdm; sp getCDM() { Mutex::Autolock lock(cdmLock); // This function is a critical section. + if (sMetricsQueue == nullptr) { + ALOGD("Instantiating CDM metrics queue"); + sMetricsQueue = new WvMetricsSnapshotQueue(); + } + sp cdm = sCdm.promote(); if (cdm == NULL) { ALOGD("Instantiating CDM."); - cdm = new WvContentDecryptionModule(); + cdm = new WvContentDecryptionModule(sMetricsQueue.get()); sCdm = cdm; }