Merge "Unified State-Changing API for LicenseKeyStatus" into oc-mr1-dev

This commit is contained in:
TreeHugger Robot
2017-08-31 23:45:41 +00:00
committed by Android (Google) Code Review
6 changed files with 264 additions and 115 deletions

View File

@@ -86,14 +86,17 @@ bool LicenseKeys::GetAllowedUsage(const KeyId& key_id,
}
}
bool LicenseKeys::ApplyStatusChange(CdmKeyStatus new_status,
bool* new_usable_keys) {
bool LicenseKeys::ApplyStatusChange(
const CdmKeyStatus* new_status, const uint32_t* new_resolution,
const CryptoSession::HdcpCapability* new_hdcp_level,
bool* new_usable_keys) {
bool keys_changed = false;
bool newly_usable = false;
*new_usable_keys = false;
for (LicenseKeyStatusIterator it = keys_.begin(); it != keys_.end(); ++it) {
bool usable;
if (it->second->ApplyStatusChange(new_status, &usable)) {
if (it->second->ApplyStatusChange(new_status, new_resolution,
new_hdcp_level, &usable)) {
newly_usable |= usable;
keys_changed = true;
}
@@ -122,13 +125,6 @@ bool LicenseKeys::MeetsConstraints(const KeyId& key_id) {
}
}
void LicenseKeys::ApplyConstraints(
uint32_t new_resolution, CryptoSession::HdcpCapability new_hdcp_level) {
for (LicenseKeyStatusIterator i = keys_.begin(); i != keys_.end(); ++i) {
i->second->ApplyConstraints(new_resolution, new_hdcp_level);
}
}
void LicenseKeys::SetFromLicense(
const video_widevine::License& license) {
this->Clear();
@@ -145,6 +141,9 @@ void LicenseKeys::SetFromLicense(
LicenseKeyStatus::LicenseKeyStatus(const KeyContainer& key) :
is_content_key_(false),
key_status_(kKeyStatusInternalError),
resolution_(kNoResolution),
hdcp_level_(HDCP_NONE),
can_check_constraints_(false),
meets_constraints_(true),
default_hdcp_level_(HDCP_NONE) {
@@ -221,26 +220,55 @@ bool LicenseKeyStatus::GetAllowedUsage(CdmKeyAllowedUsage* allowed_usage) {
return true;
}
bool LicenseKeyStatus::ApplyStatusChange(CdmKeyStatus new_status,
bool* new_usable_key) {
*new_usable_key = false;
bool LicenseKeyStatus::ApplyStatusChange(
const CdmKeyStatus* maybe_new_status, const uint32_t* maybe_new_resolution,
const CryptoSession::HdcpCapability* maybe_new_hdcp_level,
bool* newly_usable) {
*newly_usable = false;
if (!is_content_key_) {
return false;
}
CdmKeyStatus updated_status = new_status;
if (updated_status == kKeyStatusUsable) {
// Most of this function is various work to calculate an updated value for
// the status. We start at the same value as the current status.
CdmKeyStatus updated_status = key_status_;
// Account for the new status, if provided.
if (maybe_new_status != NULL) {
const CdmKeyStatus& new_status = *maybe_new_status;
can_check_constraints_ = (new_status == kKeyStatusUsable);
updated_status = new_status;
}
// Account for the new resolution, if provided.
if (maybe_new_resolution != NULL) {
resolution_ = *maybe_new_resolution;
}
// Account for the new HDCP level, if provided.
if (maybe_new_hdcp_level != NULL) {
hdcp_level_ = *maybe_new_hdcp_level;
}
// If we can, check the current state against the constraints and update the
// status if needed.
if (can_check_constraints_) {
ApplyConstraints();
if (!MeetsConstraints()) {
updated_status = kKeyStatusOutputNotAllowed;
}
}
// Check if any of that work changed the key status.
if (key_status_ != updated_status) {
key_status_ = updated_status;
if (updated_status == kKeyStatusUsable) {
*new_usable_key = true;
*newly_usable = true;
}
return true;
} else {
return false;
}
return false;
}
// If the key has constraints, find the constraint that applies.
@@ -250,12 +278,16 @@ bool LicenseKeyStatus::ApplyStatusChange(CdmKeyStatus new_status,
// If the key has no constraints, or if the constraint has no HDCP
// requirement, use the key's default HDCP setting to check against the
// device's current HDCP level.
void LicenseKeyStatus::ApplyConstraints(
uint32_t new_resolution, CryptoSession::HdcpCapability new_hdcp_level) {
void LicenseKeyStatus::ApplyConstraints() {
if (resolution_ == kNoResolution) {
// Until a resolution has been detected, the constraints cannot be checked.
meets_constraints_ = true;
return;
}
VideoResolutionConstraint* current_constraint = NULL;
if (HasConstraints()) {
current_constraint = GetConstraintForRes(new_resolution, constraints_);
current_constraint = GetConstraintForRes(resolution_, constraints_);
if (NULL == current_constraint) {
meets_constraints_ = false;
return;
@@ -270,7 +302,7 @@ void LicenseKeyStatus::ApplyConstraints(
desired_hdcp_level = default_hdcp_level_;
}
meets_constraints_ = (new_hdcp_level >= desired_hdcp_level);
meets_constraints_ = (hdcp_level_ >= desired_hdcp_level);
}
void LicenseKeyStatus::SetConstraints(const ConstraintList& constraints) {

View File

@@ -17,7 +17,6 @@ using video_widevine::License;
namespace {
const int64_t kHdcpCheckInterval = 10;
const uint32_t kNoResolution = 0;
} // namespace
@@ -71,7 +70,15 @@ void PolicyEngine::CheckDevice(int64_t current_time) {
if (!crypto_session_->GetHdcpCapabilities(&current_hdcp_level, &ignored)) {
current_hdcp_level = HDCP_NONE;
}
license_keys_->ApplyConstraints(current_resolution_, current_hdcp_level);
bool new_usable_keys = false;
bool keys_changed =
license_keys_->ApplyStatusChange(NULL, // new_status
&current_resolution_,
&current_hdcp_level,
&new_usable_keys);
NotifyIfKeysChanged(keys_changed, new_usable_keys);
next_device_check_ = current_time + kHdcpCheckInterval;
}
}
@@ -89,21 +96,19 @@ void PolicyEngine::OnTimerEvent() {
if (HasLicenseOrPlaybackDurationExpired(current_time) &&
license_state_ != kLicenseStateExpired) {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusExpired);
UpdateKeyStatus(kKeyStatusExpired);
return;
}
// Check device conditions that affect playability (HDCP, resolution)
CheckDevice(current_time);
// Test to determine if renewal should be attempted.
bool renewal_needed = false;
// Test to determine if renewal should be attempted.
switch (license_state_) {
case kLicenseStateCanPlay: {
if (HasRenewalDelayExpired(current_time)) renewal_needed = true;
// HDCP may change, so force a check.
NotifyKeysChange(kKeyStatusUsable);
break;
}
@@ -120,7 +125,7 @@ void PolicyEngine::OnTimerEvent() {
case kLicenseStatePending: {
if (current_time >= license_start_time_) {
license_state_ = kLicenseStateCanPlay;
NotifyKeysChange(kKeyStatusUsable);
UpdateKeyStatus(kKeyStatusUsable);
}
break;
}
@@ -132,7 +137,7 @@ void PolicyEngine::OnTimerEvent() {
default: {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusInternalError);
UpdateKeyStatus(kKeyStatusInternalError);
break;
}
}
@@ -157,7 +162,7 @@ void PolicyEngine::SetLicenseForRelease(const License& license) {
policy_.Clear();
// Expire any old keys.
NotifyKeysChange(kKeyStatusExpired);
UpdateKeyStatus(kKeyStatusExpired);
UpdateLicense(license);
}
@@ -190,17 +195,17 @@ void PolicyEngine::UpdateLicense(const License& license) {
if (!policy_.can_play() ||
HasLicenseOrPlaybackDurationExpired(current_time)) {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusExpired);
UpdateKeyStatus(kKeyStatusExpired);
return;
}
// Update state
if (current_time >= license_start_time_) {
license_state_ = kLicenseStateCanPlay;
NotifyKeysChange(kKeyStatusUsable);
UpdateKeyStatus(kKeyStatusUsable);
} else {
license_state_ = kLicenseStatePending;
NotifyKeysChange(kKeyStatusPending);
UpdateKeyStatus(kKeyStatusPending);
}
NotifyExpirationUpdate(current_time);
}
@@ -240,7 +245,7 @@ void PolicyEngine::NotifyResolution(uint32_t width, uint32_t height) {
void PolicyEngine::NotifySessionExpiration() {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusExpired);
UpdateKeyStatus(kKeyStatusExpired);
}
CdmResponseType PolicyEngine::Query(CdmQueryMap* query_response) {
@@ -429,16 +434,23 @@ bool PolicyEngine::HasRenewalRetryIntervalExpired(int64_t current_time) {
next_renewal_time_ <= current_time;
}
void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) {
bool keys_changed;
bool has_new_usable_key = false;
keys_changed = license_keys_->ApplyStatusChange(new_status,
&has_new_usable_key);
void PolicyEngine::UpdateKeyStatus(CdmKeyStatus new_status) {
bool new_usable_keys = false;
bool keys_changed =
license_keys_->ApplyStatusChange(&new_status,
NULL, // new_resolution
NULL, // new_hdcp_level
&new_usable_keys);
NotifyIfKeysChanged(keys_changed, new_usable_keys);
}
void PolicyEngine::NotifyIfKeysChanged(bool keys_changed,
bool new_usable_keys) {
if (event_listener_ && keys_changed) {
CdmKeyStatusMap content_keys;
license_keys_->ExtractKeyStatuses(&content_keys);
event_listener_->OnSessionKeysChange(session_id_, content_keys,
has_new_usable_key);
new_usable_keys);
}
}