Improve android MediaDrm property latency
[ Merge of http://go/wvgerrit/89848 ] Apps query a number of properties at initialization. The mediaDrm API getProperty allows the query of a single property at a time. This causes a series of requests. If no crypto sessions are concurrently open, a series of expensive OEMCrypto Initialization and Termination calls will occur. In this change OEMCrypto termination is delayed. If an OEMCrypto Terminate is followed in close succession by an Initialize, neither will occur avoiding the overhead. A timer enables a countdown process. If no session activity occurs, the timer will eventually terminate OEMCrypto and exit. Bug: 136282358 Test: Android unit/integration tests Change-Id: I442b7919b4e7835c52583516c8bc64d0c150241d
This commit is contained in:
@@ -60,6 +60,7 @@ const size_t kOemCryptoApiVersionSupportsSwitchingCipherMode = 14;
|
||||
|
||||
// Constants and utility objects relating to OEM Certificates
|
||||
const char* const kWidevineSystemIdExtensionOid = "1.3.6.1.4.1.11129.4.1.1";
|
||||
constexpr int kMaxTerminateCountDown = 5;
|
||||
|
||||
const std::string kStringNotAvailable = "NA";
|
||||
|
||||
@@ -96,6 +97,7 @@ shared_mutex CryptoSession::static_field_mutex_;
|
||||
shared_mutex CryptoSession::oem_crypto_mutex_;
|
||||
bool CryptoSession::initialized_ = false;
|
||||
int CryptoSession::session_count_ = 0;
|
||||
int CryptoSession::termination_counter_ = 0;
|
||||
UsageTableHeader* CryptoSession::usage_table_header_l1_ = nullptr;
|
||||
UsageTableHeader* CryptoSession::usage_table_header_l3_ = nullptr;
|
||||
std::atomic<uint64_t> CryptoSession::request_id_index_source_(0);
|
||||
@@ -189,7 +191,15 @@ CryptoSession::~CryptoSession() {
|
||||
if (open_) {
|
||||
Close();
|
||||
}
|
||||
Terminate();
|
||||
WithStaticFieldWriteLock("~CryptoSession", [&] {
|
||||
if (session_count_ > 0) {
|
||||
--session_count_;
|
||||
} else {
|
||||
LOGE("Invalid crypto session count: session_count_ = %d", session_count_);
|
||||
}
|
||||
});
|
||||
|
||||
TryTerminate();
|
||||
M_RECORD(metrics_, crypto_session_life_span_, life_span_.AsMs());
|
||||
}
|
||||
|
||||
@@ -244,6 +254,9 @@ void CryptoSession::Init() {
|
||||
LOGE("OEMCrypto_Initialize failed: status = %d", static_cast<int>(sts));
|
||||
return;
|
||||
}
|
||||
termination_counter_ = Properties::delay_oem_crypto_termination()
|
||||
? kMaxTerminateCountDown
|
||||
: 0;
|
||||
initialized_ = true;
|
||||
initialized = true;
|
||||
}
|
||||
@@ -273,17 +286,20 @@ void CryptoSession::Init() {
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoSession::Terminate() {
|
||||
bool CryptoSession::TryTerminate() {
|
||||
LOGV("Terminating crypto session");
|
||||
WithStaticFieldWriteLock("Terminate", [&] {
|
||||
LOGV("Terminating crypto session: initialized_ = %s, session_count_ = %d",
|
||||
initialized_ ? "true" : "false", session_count_);
|
||||
if (session_count_ > 0) {
|
||||
session_count_ -= 1;
|
||||
} else {
|
||||
LOGE("Invalid crypto session count: session_count_ = %d", session_count_);
|
||||
WithStaticFieldWriteLock("TryTerminate", [&] {
|
||||
LOGV(
|
||||
"Terminating crypto session: initialized_ = %s, session_count_ = %d, "
|
||||
"termination_counter_ = %d",
|
||||
initialized_ ? "true" : "false", session_count_, termination_counter_);
|
||||
|
||||
if (termination_counter_ > 0) {
|
||||
--termination_counter_;
|
||||
}
|
||||
if (session_count_ > 0 || !initialized_) return;
|
||||
if (session_count_ > 0 || termination_counter_ > 0 || !initialized_)
|
||||
return false;
|
||||
|
||||
OEMCryptoResult sts;
|
||||
WithOecWriteLock("Terminate", [&] { sts = OEMCrypto_Terminate(); });
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
@@ -300,7 +316,15 @@ void CryptoSession::Terminate() {
|
||||
}
|
||||
|
||||
initialized_ = false;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
void CryptoSession::DisableDelayedTermination() {
|
||||
LOGV("Disable delayed termination");
|
||||
WithStaticFieldWriteLock("DisableDelayedTermination",
|
||||
[&] { termination_counter_ = 0; });
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GetTokenFromKeybox(std::string* token) {
|
||||
@@ -687,6 +711,11 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
||||
return MapOEMCryptoResult(sts, OPEN_CRYPTO_SESSION_ERROR, "Open");
|
||||
}
|
||||
|
||||
WithStaticFieldWriteLock("Open() termination_counter", [&] {
|
||||
termination_counter_ =
|
||||
Properties::delay_oem_crypto_termination() ? kMaxTerminateCountDown : 0;
|
||||
});
|
||||
|
||||
oec_session_id_ = static_cast<CryptoSessionId>(sid);
|
||||
LOGV("Opened session: id = %u", oec_session_id_);
|
||||
open_ = true;
|
||||
|
||||
Reference in New Issue
Block a user