Merge changes Iacbbd51a,Id925ddcc

* changes:
  Add policy handling for v16
  More policy engine/timers refactoring
This commit is contained in:
Rahul Frias
2020-02-19 15:37:35 +00:00
committed by Android (Google) Code Review
14 changed files with 2058 additions and 257 deletions

View File

@@ -663,7 +663,8 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
} else {
Clock clock;
int64_t current_time = clock.GetCurrentTime();
if (policy_engine_->HasLicenseOrPlaybackDurationExpired(current_time)) {
if (policy_engine_->HasLicenseOrRentalOrPlaybackDurationExpired(
current_time)) {
return NEED_KEY;
}
}
@@ -823,7 +824,7 @@ bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
int64_t CdmSession::GetDurationRemaining() {
if (policy_engine_->IsLicenseForFuture()) return 0;
return policy_engine_->GetLicenseOrPlaybackDurationRemaining();
return policy_engine_->GetLicenseOrRentalOrPlaybackDurationRemaining();
}
CdmSessionId CdmSession::GenerateSessionId() {

View File

@@ -944,7 +944,7 @@ CdmResponseType CdmLicense::RestoreLicenseForRelease(
// If the policy engine already has keys, they will now expire.
// If the policy engine does not already have keys, this will not add any.
policy_engine_->SetLicenseForRelease(license);
policy_engine_->SetLicenseForRelease(license, supports_core_messages());
return NO_ERROR;
}
@@ -1106,7 +1106,7 @@ CdmResponseType CdmLicense::HandleContentKeyResponse(
it != key_array.end(); ++it) {
loaded_keys_.insert(it->key_id());
}
policy_engine_->SetLicense(license);
policy_engine_->SetLicense(license, supports_core_messages());
}
return resp;
}
@@ -1135,7 +1135,7 @@ CdmResponseType CdmLicense::HandleEntitlementKeyResponse(
// Save the entitlement keys for future use to handle key changes.
entitlement_keys_.CopyFrom(license.key());
policy_engine_->SetLicense(license);
policy_engine_->SetLicense(license, supports_core_messages());
return HandleNewEntitledKeys(wrapped_keys_);
}

View File

@@ -9,6 +9,7 @@
#include "clock.h"
#include "log.h"
#include "policy_timers_v15.h"
#include "policy_timers_v16.h"
#include "properties.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
@@ -33,7 +34,7 @@ PolicyEngine::PolicyEngine(CdmSessionId session_id,
session_id_(session_id),
event_listener_(event_listener),
license_keys_(new LicenseKeys(crypto_session->GetSecurityLevel())),
policy_timers(new PolicyTimersV15),
policy_timers_(new PolicyTimersV15),
clock_(new Clock) {
InitDevice(crypto_session);
}
@@ -90,12 +91,13 @@ void PolicyEngine::OnTimerEvent() {
const int64_t current_time = GetCurrentTime();
// If we have passed the grace period, the expiration will update.
if (policy_timers->HasPassedGracePeriod(current_time)) {
if (policy_timers_->HasPassedGracePeriod(current_time)) {
NotifyExpirationUpdate(current_time);
}
// License expiration trumps all.
if (policy_timers->HasLicenseOrPlaybackDurationExpired(current_time) &&
if (policy_timers_->HasLicenseOrRentalOrPlaybackDurationExpired(
current_time) &&
license_state_ != kLicenseStateExpired) {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusExpired);
@@ -110,7 +112,7 @@ void PolicyEngine::OnTimerEvent() {
// Test to determine if renewal should be attempted.
switch (license_state_) {
case kLicenseStateCanPlay: {
if (policy_timers->HasRenewalDelayExpired(current_time)) {
if (policy_timers_->HasRenewalDelayExpired(current_time)) {
renewal_needed = true;
}
// HDCP may change, so force a check.
@@ -124,14 +126,14 @@ void PolicyEngine::OnTimerEvent() {
}
case kLicenseStateWaitingLicenseUpdate: {
if (policy_timers->HasRenewalRetryIntervalExpired(current_time)) {
if (policy_timers_->HasRenewalRetryIntervalExpired(current_time)) {
renewal_needed = true;
}
break;
}
case kLicenseStatePending: {
if (!policy_timers->IsLicenseForFuture(current_time)) {
if (!policy_timers_->IsLicenseForFuture(current_time)) {
license_state_ = kLicenseStateCanPlay;
NotifyKeysChange(kKeyStatusUsable);
}
@@ -156,11 +158,12 @@ void PolicyEngine::OnTimerEvent() {
}
}
void PolicyEngine::SetLicense(const License& license) {
license_id_.Clear();
void PolicyEngine::SetLicense(const License& license,
bool supports_core_messages) {
if (supports_core_messages) policy_timers_.reset(new PolicyTimersV16());
license_id_.CopyFrom(license.id());
license_keys_->SetFromLicense(license);
policy_timers->SetLicense(license);
policy_timers_->SetLicense(license);
UpdateLicense(license);
}
@@ -169,13 +172,14 @@ void PolicyEngine::SetEntitledLicenseKeys(
license_keys_->SetEntitledKeys(entitled_keys);
}
void PolicyEngine::SetLicenseForRelease(const License& license) {
license_id_.Clear();
void PolicyEngine::SetLicenseForRelease(const License& license,
bool supports_core_messages) {
if (supports_core_messages) policy_timers_.reset(new PolicyTimersV16());
license_id_.CopyFrom(license.id());
// Expire any old keys.
NotifyKeysChange(kKeyStatusExpired);
policy_timers->SetLicense(license);
policy_timers_->SetLicense(license);
UpdateLicense(license);
}
@@ -199,18 +203,19 @@ void PolicyEngine::UpdateLicense(const License& license) {
}
const int64_t current_time = GetCurrentTime();
policy_timers->UpdateLicense(current_time, license);
policy_timers_->UpdateLicense(current_time, license);
// Update time information
if (!policy_timers->get_policy().can_play() ||
policy_timers->HasLicenseOrPlaybackDurationExpired(current_time)) {
if (!policy_timers_->get_policy().can_play() ||
policy_timers_->HasLicenseOrRentalOrPlaybackDurationExpired(
current_time)) {
license_state_ = kLicenseStateExpired;
NotifyKeysChange(kKeyStatusExpired);
return;
}
// Update state
if (!policy_timers->IsLicenseForFuture(current_time)) {
if (!policy_timers_->IsLicenseForFuture(current_time)) {
license_state_ = kLicenseStateCanPlay;
NotifyKeysChange(kKeyStatusUsable);
} else {
@@ -222,14 +227,14 @@ void PolicyEngine::UpdateLicense(const License& license) {
bool PolicyEngine::BeginDecryption() {
const int64_t current_time = GetCurrentTime();
if (!policy_timers->HasPlaybackStarted(current_time)) {
if (!policy_timers_->HasPlaybackStarted(current_time)) {
switch (license_state_) {
case kLicenseStateCanPlay:
case kLicenseStateNeedRenewal:
case kLicenseStateWaitingLicenseUpdate:
policy_timers->BeginDecryption(current_time);
policy_timers_->BeginDecryption(current_time);
if (policy_timers->get_policy().renew_with_usage()) {
if (policy_timers_->get_policy().renew_with_usage()) {
license_state_ = kLicenseStateNeedRenewal;
}
NotifyExpirationUpdate(current_time);
@@ -246,7 +251,7 @@ bool PolicyEngine::BeginDecryption() {
}
void PolicyEngine::DecryptionEvent() {
policy_timers->DecryptionEvent(GetCurrentTime());
policy_timers_->DecryptionEvent(GetCurrentTime());
}
void PolicyEngine::NotifyResolution(uint32_t width, uint32_t height) {
@@ -270,20 +275,20 @@ CdmResponseType PolicyEngine::Query(CdmQueryMap* query_response) {
license_id_.type() == video_widevine::STREAMING ? QUERY_VALUE_STREAMING
: QUERY_VALUE_OFFLINE;
(*query_response)[QUERY_KEY_PLAY_ALLOWED] =
policy_timers->get_policy().can_play() ? QUERY_VALUE_TRUE
: QUERY_VALUE_FALSE;
(*query_response)[QUERY_KEY_PERSIST_ALLOWED] =
policy_timers->get_policy().can_persist() ? QUERY_VALUE_TRUE
: QUERY_VALUE_FALSE;
(*query_response)[QUERY_KEY_RENEW_ALLOWED] =
policy_timers->get_policy().can_renew() ? QUERY_VALUE_TRUE
policy_timers_->get_policy().can_play() ? QUERY_VALUE_TRUE
: QUERY_VALUE_FALSE;
(*query_response)[QUERY_KEY_PERSIST_ALLOWED] =
policy_timers_->get_policy().can_persist() ? QUERY_VALUE_TRUE
: QUERY_VALUE_FALSE;
(*query_response)[QUERY_KEY_RENEW_ALLOWED] =
policy_timers_->get_policy().can_renew() ? QUERY_VALUE_TRUE
: QUERY_VALUE_FALSE;
(*query_response)[QUERY_KEY_LICENSE_DURATION_REMAINING] = std::to_string(
policy_timers->GetLicenseOrRentalDurationRemaining(current_time));
(*query_response)[QUERY_KEY_PLAYBACK_DURATION_REMAINING] =
std::to_string(policy_timers->GetPlaybackDurationRemaining(current_time));
policy_timers_->GetLicenseOrRentalDurationRemaining(current_time));
(*query_response)[QUERY_KEY_PLAYBACK_DURATION_REMAINING] = std::to_string(
policy_timers_->GetPlaybackDurationRemaining(current_time));
(*query_response)[QUERY_KEY_RENEWAL_SERVER_URL] =
policy_timers->get_policy().renewal_server_url();
policy_timers_->get_policy().renewal_server_url();
return NO_ERROR;
}
@@ -305,54 +310,57 @@ bool PolicyEngine::CanUseKeyForSecurityLevel(const KeyId& key_id) {
}
bool PolicyEngine::GetSecondsSinceStarted(int64_t* seconds_since_started) {
return policy_timers->GetSecondsSinceStarted(GetCurrentTime(),
seconds_since_started);
return policy_timers_->GetSecondsSinceStarted(GetCurrentTime(),
seconds_since_started);
}
bool PolicyEngine::GetSecondsSinceLastPlayed(
int64_t* seconds_since_last_played) {
return policy_timers->GetSecondsSinceLastPlayed(GetCurrentTime(),
seconds_since_last_played);
return policy_timers_->GetSecondsSinceLastPlayed(GetCurrentTime(),
seconds_since_last_played);
}
int64_t PolicyEngine::GetLicenseOrPlaybackDurationRemaining() {
return policy_timers->GetLicenseOrPlaybackDurationRemaining(GetCurrentTime());
int64_t PolicyEngine::GetLicenseOrRentalOrPlaybackDurationRemaining() {
return policy_timers_->GetLicenseOrRentalOrPlaybackDurationRemaining(
GetCurrentTime());
}
bool PolicyEngine::CanRenew() const {
return policy_timers->get_policy().can_renew();
return policy_timers_->get_policy().can_renew();
}
int64_t PolicyEngine::GetPlaybackStartTime() {
return policy_timers->GetPlaybackStartTime();
return policy_timers_->GetPlaybackStartTime();
}
int64_t PolicyEngine::GetLastPlaybackTime() {
return policy_timers->GetLastPlaybackTime();
return policy_timers_->GetLastPlaybackTime();
}
int64_t PolicyEngine::GetGracePeriodEndTime() {
return policy_timers->GetGracePeriodEndTime();
return policy_timers_->GetGracePeriodEndTime();
}
void PolicyEngine::RestorePlaybackTimes(int64_t playback_start_time,
int64_t last_playback_time,
int64_t grace_period_end_time) {
const int64_t current_time = GetCurrentTime();
policy_timers->RestorePlaybackTimes(current_time, playback_start_time,
last_playback_time,
grace_period_end_time);
policy_timers_->RestorePlaybackTimes(current_time, playback_start_time,
last_playback_time,
grace_period_end_time);
NotifyExpirationUpdate(current_time);
}
void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
license_state_ = kLicenseStateWaitingLicenseUpdate;
policy_timers->UpdateRenewalRequest(current_time);
policy_timers_->UpdateRenewalRequest(current_time);
}
bool PolicyEngine::HasLicenseOrPlaybackDurationExpired(int64_t current_time) {
return policy_timers->HasLicenseOrPlaybackDurationExpired(current_time);
bool PolicyEngine::HasLicenseOrRentalOrPlaybackDurationExpired(
int64_t current_time) {
return policy_timers_->HasLicenseOrRentalOrPlaybackDurationExpired(
current_time);
}
// Apply a key status to the current keys.
@@ -377,7 +385,7 @@ void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) {
void PolicyEngine::NotifyExpirationUpdate(int64_t current_time) {
int64_t expiry_time;
if (policy_timers->UpdateExpirationTime(current_time, &expiry_time)) {
if (policy_timers_->UpdateExpirationTime(current_time, &expiry_time)) {
if (event_listener_)
event_listener_->OnExpirationUpdate(session_id_, expiry_time);
}

View File

@@ -16,13 +16,26 @@ namespace wvcdm {
void PolicyTimers::SetLicense(const video_widevine::License& license) {
policy_.Clear();
license_start_time_ = license.license_start_time();
if (license.has_license_start_time())
license_start_time_ = license.license_start_time();
}
void PolicyTimers::DecryptionEvent(int64_t current_time) {
last_playback_time_ = current_time;
}
int64_t PolicyTimers::GetPlaybackDurationRemaining(int64_t current_time) {
const int64_t playback_duration = policy_.playback_duration_seconds();
if (playback_duration == 0) return LLONG_MAX;
if (playback_start_time_ == 0) return playback_duration;
const int64_t playback_expiry_time = playback_duration + playback_start_time_;
if (playback_expiry_time < current_time) return 0;
const int64_t policy_playback_duration = policy_.playback_duration_seconds();
return std::min(playback_expiry_time - current_time,
policy_playback_duration);
}
bool PolicyTimers::GetSecondsSinceStarted(int64_t current_time,
int64_t* seconds_since_started) {
if (seconds_since_started == nullptr) {

View File

@@ -34,7 +34,8 @@ bool PolicyTimersV15::UpdateLicense(int64_t current_time,
license_start_time_ = license.license_start_time();
next_renewal_time_ = license_start_time_ + policy_.renewal_delay_seconds();
if (!policy_.can_play() || HasLicenseOrPlaybackDurationExpired(current_time))
if (!policy_.can_play() ||
HasLicenseOrRentalOrPlaybackDurationExpired(current_time))
return false;
return true;
@@ -78,7 +79,7 @@ bool PolicyTimersV15::HasPlaybackStarted(int64_t current_time) {
return playback_time >= policy_.play_start_grace_period_seconds();
}
bool PolicyTimersV15::HasLicenseOrPlaybackDurationExpired(
bool PolicyTimersV15::HasLicenseOrRentalOrPlaybackDurationExpired(
int64_t current_time) {
const int64_t expiry_time = GetExpiryTime(
current_time, /* ignore_soft_enforce_playback_duration */ false);
@@ -93,7 +94,7 @@ bool PolicyTimersV15::HasPassedGracePeriod(int64_t current_time) {
return false;
}
int64_t PolicyTimersV15::GetLicenseOrPlaybackDurationRemaining(
int64_t PolicyTimersV15::GetLicenseOrRentalOrPlaybackDurationRemaining(
int64_t current_time) {
const int64_t expiry_time = GetExpiryTime(
current_time, /* ignore_soft_enforce_playback_duration */ false);
@@ -104,31 +105,20 @@ int64_t PolicyTimersV15::GetLicenseOrPlaybackDurationRemaining(
int64_t PolicyTimersV15::GetLicenseOrRentalDurationRemaining(
int64_t current_time) {
if (HasLicenseOrPlaybackDurationExpired(current_time)) return 0;
if (HasLicenseOrRentalOrPlaybackDurationExpired(current_time)) return 0;
const int64_t license_expiry_time = GetRentalExpiryTime();
if (license_expiry_time == NEVER_EXPIRES) return LLONG_MAX;
if (license_expiry_time < current_time) return 0;
const int64_t policy_license_duration = policy_.license_duration_seconds();
if (policy_license_duration == NEVER_EXPIRES)
if (policy_license_duration == UNLIMITED_DURATION)
return license_expiry_time - current_time;
return std::min(license_expiry_time - current_time, policy_license_duration);
}
int64_t PolicyTimersV15::GetPlaybackDurationRemaining(int64_t current_time) {
const int64_t playback_duration = policy_.playback_duration_seconds();
if (playback_duration == 0) return LLONG_MAX;
if (playback_start_time_ == 0) return playback_duration;
const int64_t playback_expiry_time = playback_duration + playback_start_time_;
if (playback_expiry_time < current_time) return 0;
const int64_t policy_playback_duration = policy_.playback_duration_seconds();
return std::min(playback_expiry_time - current_time,
policy_playback_duration);
}
// For the policy time fields checked in the following methods, a value of 0
// indicates that there is no limit to the duration. If the fields are zero
// (including the hard limit) then these methods will return NEVER_EXPIRES.
// (UNLIMITED_DURATION) indicates that there is no limit to the duration.
// If the fields are UNLIMITED_DURATION (including the hard limit) then these
// methods will return NEVER_EXPIRES.
int64_t PolicyTimersV15::GetHardLicenseExpiryTime() {
return policy_.license_duration_seconds() > 0
? license_start_time_ + policy_.license_duration_seconds()

View File

@@ -0,0 +1,123 @@
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "policy_timers_v16.h"
#include <algorithm>
#include "log.h"
#include "wv_cdm_constants.h"
using video_widevine::License;
namespace wvcdm {
bool PolicyTimersV16::UpdateLicense(int64_t current_time,
const License& license) {
if (!license.has_policy()) return false;
policy_.MergeFrom(license.policy());
// some basic license validation
// license start time needs to be specified in the initial response
if (!license.has_license_start_time()) return false;
// Update time information
renewal_start_time_ = license.license_start_time();
next_renewal_time_ =
license.license_start_time() + policy_.renewal_delay_seconds();
if (!policy_.can_play() ||
HasLicenseOrRentalOrPlaybackDurationExpired(current_time))
return false;
return true;
}
void PolicyTimersV16::BeginDecryption(int64_t current_time) {
if (playback_start_time_ == 0) {
playback_start_time_ = current_time;
last_playback_time_ = current_time;
}
}
void PolicyTimersV16::RestorePlaybackTimes(
int64_t current_time, int64_t playback_start_time,
int64_t last_playback_time, int64_t /* grace_period_end_time */) {
playback_start_time_ = (playback_start_time > 0) ? playback_start_time : 0;
last_playback_time_ = (last_playback_time > 0) ? last_playback_time : 0;
const int64_t expiry_time = GetExpiryTime(
current_time, /* ignore_soft_enforce_playback_duration */ true);
was_expired_on_load_ =
expiry_time != NEVER_EXPIRES && expiry_time < current_time;
}
bool PolicyTimersV16::HasRentalOrPlaybackDurationExpired(int64_t current_time) {
const int64_t expiry_time = GetExpiryTime(
current_time, /* ignore_soft_enforce_playback_duration */ false);
return expiry_time != NEVER_EXPIRES && expiry_time <= current_time;
}
int64_t PolicyTimersV16::GetLicenseOrRentalOrPlaybackDurationRemaining(
int64_t current_time) {
const int64_t expiry_time = GetExpiryTime(
current_time, /* ignore_soft_enforce_playback_duration */ false);
if (expiry_time == NEVER_EXPIRES) return LLONG_MAX;
if (expiry_time < current_time) return 0;
return expiry_time - current_time;
}
int64_t PolicyTimersV16::GetRentalDurationRemaining(int64_t current_time) {
if (HasLicenseOrRentalOrPlaybackDurationExpired(current_time)) return 0;
const int64_t rental_expiry_time = GetRentalExpiryTime(current_time);
if (rental_expiry_time == NEVER_EXPIRES) return LLONG_MAX;
if (rental_expiry_time < current_time) return 0;
return rental_expiry_time - current_time;
}
// For the policy time fields checked in the following methods, a value of 0
// (UNLIMITED_DURATION) indicates that there is no limit to the duration.
// If the fields are UNLIMITED_DURATION then these methods will return
// NEVER_EXPIRES.
int64_t PolicyTimersV16::GetRentalExpiryTime(int64_t current_time) {
if (policy_.rental_duration_seconds() == UNLIMITED_DURATION)
return NEVER_EXPIRES;
if (HasPlaybackStarted(current_time) &&
policy_.soft_enforce_rental_duration())
return NEVER_EXPIRES;
return license_start_time_ + policy_.rental_duration_seconds();
}
int64_t PolicyTimersV16::GetPlaybackExpiryTime(
int64_t current_time, bool ignore_soft_enforce_playback_duration) {
if (policy_.playback_duration_seconds() == UNLIMITED_DURATION)
return NEVER_EXPIRES;
if (!HasPlaybackStarted(current_time)) return NEVER_EXPIRES;
if (was_expired_on_load_) return current_time;
if (!ignore_soft_enforce_playback_duration &&
policy_.soft_enforce_playback_duration())
return NEVER_EXPIRES;
return playback_start_time_ + policy_.playback_duration_seconds();
}
int64_t PolicyTimersV16::GetExpiryTime(
int64_t current_time, bool ignore_soft_enforce_playback_duration) {
const int64_t rental_expiry_time = GetRentalExpiryTime(current_time);
const int64_t playback_expiry_time = GetPlaybackExpiryTime(
current_time, ignore_soft_enforce_playback_duration);
if (rental_expiry_time == NEVER_EXPIRES) return playback_expiry_time;
if (playback_expiry_time == NEVER_EXPIRES) return rental_expiry_time;
return std::min(rental_expiry_time, playback_expiry_time);
}
} // namespace wvcdm