Fix deadlock when pending key release sessions are deallocated
[ Merge from http://go/wvgerrit/27261/ ] Sessions created to release keys are periodically cleaned up if the key release operation does not complete within a specific amount of time. If other sessions are open, they will be released through the timer thread. This would result in deadlock as a mutex was taken twice. Test: Verified by cdm_extended_duration_test (AutomatedOfflineSessionReleaseOnOpenSession and AutomatedOfflineSessionReleaseOnTimerEvent tests) b/37546078 Change-Id: I7d45f939bdce77e5db461a401364da4f42c1c034
This commit is contained in:
@@ -1443,35 +1443,37 @@ void CdmEngine::OnTimerEvent() {
|
||||
bool is_initial_usage_update = false;
|
||||
bool is_usage_update_needed = false;
|
||||
|
||||
AutoLock lock(session_list_lock_);
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
is_initial_usage_update =
|
||||
is_initial_usage_update || iter->second->is_initial_usage_update();
|
||||
is_usage_update_needed =
|
||||
is_usage_update_needed || iter->second->is_usage_update_needed();
|
||||
|
||||
iter->second->OnTimerEvent(usage_update_period_expired);
|
||||
}
|
||||
|
||||
if (is_usage_update_needed &&
|
||||
(usage_update_period_expired || is_initial_usage_update)) {
|
||||
bool has_usage_been_updated = false;
|
||||
{
|
||||
AutoLock lock(session_list_lock_);
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
iter->second->reset_usage_flags();
|
||||
if (iter->second->get_usage_support_type() == kUsageEntrySupport)
|
||||
iter->second->UpdateUsageEntryInformation();
|
||||
is_initial_usage_update =
|
||||
is_initial_usage_update || iter->second->is_initial_usage_update();
|
||||
is_usage_update_needed =
|
||||
is_usage_update_needed || iter->second->is_usage_update_needed();
|
||||
|
||||
if (!has_usage_been_updated) {
|
||||
// usage is updated for all sessions so this needs to be
|
||||
// called only once per update usage information period
|
||||
if (iter->second->get_usage_support_type() == kUsageTableSupport) {
|
||||
CdmResponseType status = iter->second->UpdateUsageTableInformation();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
iter->second->OnTimerEvent(usage_update_period_expired);
|
||||
}
|
||||
|
||||
if (is_usage_update_needed &&
|
||||
(usage_update_period_expired || is_initial_usage_update)) {
|
||||
bool has_usage_been_updated = false;
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
iter->second->reset_usage_flags();
|
||||
if (iter->second->get_usage_support_type() == kUsageEntrySupport)
|
||||
iter->second->UpdateUsageEntryInformation();
|
||||
|
||||
if (!has_usage_been_updated) {
|
||||
// usage is updated for all sessions so this needs to be
|
||||
// called only once per update usage information period
|
||||
if (iter->second->get_usage_support_type() == kUsageTableSupport) {
|
||||
CdmResponseType status = iter->second->UpdateUsageTableInformation();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user