Create unique cdm engines per WVDrmPlugin instance

This change creates a unique id in the cdm identifier in order to force
a one-to-one mapping between WVDrmPlugin instances and CDM Engines. This
change simplifies some assumptions. This includes ensuring that the
metrics for a given MediaDrm instance map to a given CdmEngine instance.

This change contains the original change go/ag/3819203 and a fix to the
deadlock that was seen on Marlin and Taimen.

Bug: 73724453
Test: Updated unit tests. GTS test pass. Shaka Player, Netflix and Google Play test.
Change-Id: Ib208204a1b794df9f306fa11d13a8bb6cd6889f7
This commit is contained in:
Adam Stone
2018-03-29 12:28:57 -07:00
parent 1a25cbdad6
commit 5c71603e8c
11 changed files with 354 additions and 207 deletions

View File

@@ -32,12 +32,28 @@ struct CdmIdentifier {
// provide a friendly name of the application package for the purposes of
// logging and metrics.
std::string app_package_name;
// The unique identifier guarantees that no two identifiers share the same
// CdmEngine instance. We're moving to a model where a plugin maps 1 to 1
// with a CdmEngine instance. This is a simple way to implement that.
uint32_t unique_id;
// This method is needed to check to see if the identifier is equivalent
// to the default cdm. E.g. no spoid, origin or app package name. Use this
// comparison in lieu of the == operator when checking to see if the
// identifier would cause the default provisioned certificate to be used.
bool IsEquivalentToDefault() {
return spoid == EMPTY_SPOID
&& origin == EMPTY_ORIGIN
&& app_package_name == EMPTY_APP_PACKAGE_NAME;
}
};
// Provide comparison operators
inline bool operator==(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
return lhs.spoid == rhs.spoid && lhs.origin == rhs.origin
&& lhs.app_package_name == rhs.app_package_name;
&& lhs.app_package_name == rhs.app_package_name
&& lhs.unique_id == rhs.unique_id;
}
inline bool operator!=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
@@ -49,7 +65,9 @@ inline bool operator<(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
|| ((lhs.spoid == rhs.spoid)
&& (lhs.origin < rhs.origin
|| (lhs.origin == rhs.origin
&& lhs.app_package_name < rhs.app_package_name)));
&& (lhs.app_package_name < rhs.app_package_name
|| (lhs.app_package_name == rhs.app_package_name
&& lhs.unique_id < rhs.unique_id)))));
}
inline bool operator>(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
@@ -68,7 +86,8 @@ inline bool operator>=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
static const CdmIdentifier kDefaultCdmIdentifier = {
EMPTY_SPOID,
EMPTY_ORIGIN,
EMPTY_APP_PACKAGE_NAME
EMPTY_APP_PACKAGE_NAME,
0
};
} // namespace wvcdm

View File

@@ -129,9 +129,14 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// Validate a passed-in service certificate
virtual bool IsValidServiceCertificate(const std::string& certificate);
// Retrieve the serialized metrics from CdmEngine and CdmSession instances
// that have been closed.
virtual void GetSerializedMetrics(std::string* serialized_metrics);
// Fill the metrics parameter with the metrics data for the CdmEngine
// associated with the given CdmIdentifier. If the CdmEngine instance does
// not exist, this will return an error.
virtual CdmResponseType GetMetrics(const CdmIdentifier& identifier,
drm_metrics::WvCdmMetrics* metrics);
// Closes the CdmEngine and sessions associated with the given CdmIdentifier.
virtual CdmResponseType CloseCdm(const CdmIdentifier& identifier);
private:
struct CdmInfo {
@@ -147,17 +152,16 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// Finds the CdmEngine instance for the given session id, returning NULL if
// not found.
CdmEngine* GetCdmForSessionId(const std::string& session_id);
// Closes CdmEngine instances that don't have any open sessions. Also stores
// metrics data for closed CdmEngine instances.
// Callers must acquire the cdms_lock_ before calling this method.
void CloseCdmsWithoutSessions();
// Close all of the open CdmEngine instances. This is used when ready to close
// the WvContentDecryptionModule instance.
void CloseAllCdms();
uint32_t GenerateSessionSharingId();
// timer related methods to drive policy decisions
void EnablePolicyTimer();
void DisablePolicyTimer(); // Disable if all cdm engines are closed.
void ForceDisablePolicyTimer(); // Force disable the policy timer.
void DisablePolicyTimer();
void OnTimerEvent();
static Lock session_sharing_id_generation_lock_;
@@ -172,9 +176,6 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// This contains weak pointers to the CDM instances contained in |cdms_|.
std::map<std::string, CdmEngine*> cdm_by_session_id_;
// The metrics for cdm engines and sessions that have been closed.
drm_metrics::WvCdmMetricsGroup metrics_group_;
CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule);
};