Report key status change

Also modified PolicyEngine::CanDecrypt to use the new Keys_status_.

Bug: 19771431

Merged from Widevine CDM repo:
https://widevine-internal-review.googlesource.com/#/c/13904/

Change-Id: If7fb7fa45ecf9ff4e65278cda00ad7230b57f50b
This commit is contained in:
Kongqun Yang
2015-03-30 19:10:56 -07:00
parent bdb82e04f8
commit 4621028434
10 changed files with 315 additions and 26 deletions

View File

@@ -15,13 +15,14 @@
#include "wv_cdm_constants.h"
#include "wv_cdm_event_listener.h"
using video_widevine_server::sdk::License;
namespace wvcdm {
PolicyEngine::PolicyEngine(CdmSessionId session_id,
WvCdmEventListener* event_listener,
CryptoSession* crypto_session)
: license_state_(kLicenseStateInitial),
can_decrypt_(false),
license_start_time_(0),
playback_start_time_(0),
last_playback_time_(0),
@@ -30,13 +31,18 @@ PolicyEngine::PolicyEngine(CdmSessionId session_id,
policy_max_duration_seconds_(0),
session_id_(session_id),
event_listener_(event_listener),
max_res_engine_(crypto_session),
max_res_engine_(new MaxResEngine(crypto_session)),
clock_(new Clock) {}
PolicyEngine::~PolicyEngine() {}
bool PolicyEngine::CanDecrypt(const KeyId& key_id) {
return can_decrypt_ && max_res_engine_.CanDecrypt(key_id);
if (keys_status_.find(key_id) == keys_status_.end()) {
LOGE("PolicyEngine::CanDecrypt Key '%s' not in license.",
b2a_hex(key_id).c_str());
return false;
}
return keys_status_[key_id] == kKeyStatusUsable;
}
void PolicyEngine::OnTimerEvent() {
@@ -47,17 +53,21 @@ void PolicyEngine::OnTimerEvent() {
IsPlaybackDurationExpired(current_time)) &&
license_state_ != kLicenseStateExpired) {
license_state_ = kLicenseStateExpired;
can_decrypt_ = false;
NotifyKeysChange(kKeyStatusExpired);
if (event_listener_) event_listener_->OnSessionExpiration(session_id_);
return;
}
max_res_engine_->OnTimerEvent();
bool renewal_needed = false;
// Test to determine if renewal should be attempted.
switch (license_state_) {
case kLicenseStateCanPlay: {
if (IsRenewalDelayExpired(current_time)) renewal_needed = true;
// HDCP may change, so force a check.
NotifyKeysChange(kKeyStatusUsable);
break;
}
@@ -74,7 +84,7 @@ void PolicyEngine::OnTimerEvent() {
case kLicenseStatePending: {
if (current_time >= license_start_time_) {
license_state_ = kLicenseStateCanPlay;
can_decrypt_ = true;
NotifyKeysChange(kKeyStatusUsable);
}
break;
}
@@ -86,7 +96,7 @@ void PolicyEngine::OnTimerEvent() {
default: {
license_state_ = kLicenseStateExpired;
can_decrypt_ = false;
NotifyKeysChange(kKeyStatusInternalError);
break;
}
}
@@ -95,21 +105,26 @@ void PolicyEngine::OnTimerEvent() {
UpdateRenewalRequest(current_time);
if (event_listener_) event_listener_->OnSessionRenewalNeeded(session_id_);
}
max_res_engine_.OnTimerEvent();
}
void PolicyEngine::SetLicense(
const video_widevine_server::sdk::License& license) {
void PolicyEngine::SetLicense(const License& license) {
license_id_.Clear();
license_id_.CopyFrom(license.id());
policy_.Clear();
// Extract content key ids.
keys_status_.clear();
for (int key_index = 0; key_index < license.key_size(); ++key_index) {
const License::KeyContainer& key = license.key(key_index);
if (key.type() == License::KeyContainer::CONTENT && key.has_id())
keys_status_[key.id()] = kKeyStatusInternalError;
}
UpdateLicense(license);
max_res_engine_.SetLicense(license);
max_res_engine_->SetLicense(license);
}
void PolicyEngine::UpdateLicense(
const video_widevine_server::sdk::License& license) {
void PolicyEngine::UpdateLicense(const License& license) {
if (!license.has_policy()) return;
if (kLicenseStateExpired == license_state_) {
@@ -153,16 +168,17 @@ void PolicyEngine::UpdateLicense(
if (!policy_.can_play() || IsLicenseDurationExpired(current_time) ||
IsPlaybackDurationExpired(current_time)) {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusExpired);
return;
}
// Update state
if (current_time >= license_start_time_) {
license_state_ = kLicenseStateCanPlay;
can_decrypt_ = true;
NotifyKeysChange(kKeyStatusUsable);
} else {
license_state_ = kLicenseStatePending;
can_decrypt_ = false;
NotifyKeysChange(kKeyStatusPending);
}
NotifyExpirationUpdate();
}
@@ -195,7 +211,13 @@ void PolicyEngine::DecryptionEvent() {
}
void PolicyEngine::NotifyResolution(uint32_t width, uint32_t height) {
max_res_engine_.SetResolution(width, height);
max_res_engine_->SetResolution(width, height);
}
void PolicyEngine::NotifySessionExpiration() {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusExpired);
if (event_listener_) event_listener_->OnSessionExpiration(session_id_);
}
CdmResponseType PolicyEngine::Query(CdmQueryMap* key_info) {
@@ -303,6 +325,35 @@ bool PolicyEngine::IsRenewalRetryIntervalExpired(int64_t current_time) {
next_renewal_time_ <= current_time;
}
void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) {
bool keys_changed = false;
bool has_new_usable_key = false;
for (std::map<KeyId, CdmKeyStatus>::iterator it = keys_status_.begin();
it != keys_status_.end(); ++it) {
const KeyId key_id = it->first;
CdmKeyStatus& key_status = it->second;
CdmKeyStatus updated_status = new_status;
if (updated_status == kKeyStatusUsable) {
if (!max_res_engine_->CanDecrypt(key_id))
updated_status = kKeyStatusOutputNotAllowed;
}
if (key_status != updated_status) {
key_status = updated_status;
if (updated_status == kKeyStatusUsable) has_new_usable_key = true;
keys_changed = true;
}
}
if (keys_changed && event_listener_) {
std::vector<CdmKeyInformation> keys_info;
for (std::map<KeyId, CdmKeyStatus>::iterator it = keys_status_.begin();
it != keys_status_.end(); ++it) {
keys_info.push_back(CdmKeyInformation(it->first, it->second));
}
event_listener_->OnSessionKeysChange(session_id_, keys_info,
has_new_usable_key);
}
}
void PolicyEngine::NotifyExpirationUpdate() {
int64_t expiry_time =
std::min(GetLicenseExpiryTime(), GetPlaybackExpiryTime());
@@ -315,4 +366,8 @@ void PolicyEngine::NotifyExpirationUpdate() {
void PolicyEngine::set_clock(Clock* clock) { clock_.reset(clock); }
void PolicyEngine::set_max_res_engine(MaxResEngine* max_res_engine) {
max_res_engine_.reset(max_res_engine);
}
} // wvcdm