Initial import of Widevine Common Encryption DRM engine

Builds libwvmdrmengine.so, which is loaded by the new
MediaDrm APIs to support playback of Widevine/CENC
protected content.

Change-Id: I6f57dd37083dfd96c402cb9dd137c7d74edc8f1c
This commit is contained in:
Jeff Tinker
2013-03-21 17:39:02 -07:00
parent 38334efbe7
commit 1a8aa0dd05
211 changed files with 51913 additions and 144 deletions

View File

@@ -0,0 +1,211 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#include "policy_engine.h"
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include "log.h"
#include "string_conversions.h"
namespace wvcdm {
PolicyEngine::PolicyEngine() :
license_state_(kLicenseStateInitial),
license_start_time_(0),
next_renewal_time_(0),
policy_max_duration_seconds_(0) {
}
PolicyEngine::~PolicyEngine() {
}
void PolicyEngine::OnTimerEvent(int64_t current_time, bool event_occured, CdmEventType& event) {
event_occured = false;
// License expiration trumps all.
if (IsLicenseDurationExpired(current_time) &&
license_state_ != kLicenseStateExpired) {
license_state_ = kLicenseStateExpired;
event = LICENSE_EXPIRED_EVENT;
event_occured = true;
return;
}
// Test to determine if renewal should be attempted.
switch (license_state_) {
case kLicenseStateCanPlay: {
if (IsRenewalDelayExpired(current_time)) {
license_state_ = kLicenseStateNeedRenewal;
UpdateRenewalRequest(current_time);
event = LICENSE_RENEWAL_NEEDED_EVENT;
event_occured = true;
}
return;
}
case kLicenseStateNeedRenewal: {
UpdateRenewalRequest(current_time);
event = LICENSE_RENEWAL_NEEDED_EVENT;
event_occured = true;
return;
}
case kLicenseStateWaitingLicenseUpdate: {
if (IsRenewalRetryIntervalExpired(current_time)) {
UpdateRenewalRequest(current_time);
event = LICENSE_RENEWAL_NEEDED_EVENT;
event_occured = true;
}
return;
}
case kLicenseStateInitial:
case kLicenseStateExpired: {
return;
}
default: {
license_state_ = kLicenseStateCannotPlay;
return;
}
}
}
// TODO: Fix up differences between Eureka and other platforms' use cases.
// Eureka does not get calls to decrypt. license usage begins
// when we receive the initial license. renew_with_usage will cause renewal to
// occur on the first call to OnTimeEvent after PolicyEngine::SetLicense is
// called.
void PolicyEngine::SetLicense(
const video_widevine_server::sdk::License& license) {
license_id_.Clear();
license_id_.CopyFrom(license.id());
policy_.Clear();
UpdateLicense(license);
}
void PolicyEngine::UpdateLicense(
const video_widevine_server::sdk::License& license) {
if (!license.has_policy() || kLicenseStateExpired == license_state_)
return;
policy_.MergeFrom(license.policy());
policy_max_duration_seconds_ = 0;
// Calculate policy_max_duration_seconds_. policy_max_duration_seconds_
// will be set to the minimum of the following policies :
// rental_duration_seconds, playback_duration_seconds, and
// license_duration_seconds. The value is used to determine
// when the license expires.
if (policy_.has_rental_duration_seconds())
policy_max_duration_seconds_ = policy_.rental_duration_seconds();
if ((policy_.has_playback_duration_seconds() &&
(policy_.playback_duration_seconds() < policy_max_duration_seconds_)) ||
!policy_max_duration_seconds_) {
policy_max_duration_seconds_ = policy_.playback_duration_seconds();
}
if ((policy_.has_license_duration_seconds() &&
(policy_.license_duration_seconds() < policy_max_duration_seconds_)) ||
!policy_max_duration_seconds_) {
policy_max_duration_seconds_ = policy_.license_duration_seconds();
}
switch (license_state_) {
case kLicenseStateInitial: {
// Process initial license.
license_start_time_ = license.license_start_time();
if (policy_.can_play()) {
license_state_ =
policy_.renew_with_usage() ?
kLicenseStateNeedRenewal : kLicenseStateCanPlay;
} else {
license_state_ = kLicenseStateExpired;
}
next_renewal_time_ = license_start_time_
+ policy_.renewal_delay_seconds();
}
break;
case kLicenseStateExpired:
// Ignore policy updates.
return;
default: {
// Process license renewal.
if (license.id().version() > license_id_.version()) {
// This is the normal case.
policy_.MergeFrom(license.policy());
license_id_.CopyFrom(license.id());
} else {
// This isn't supposed to happen.
// TODO(jfore): Handle wrap? We can miss responses and that should be
// considered normal until retries are exhausted.
policy_.set_can_play(false);
}
if (license.has_license_start_time()) {
// license start has been updated. Transition back to the
// normal kLicenseStateCanPlay state if playback is allowed by
// the updated license.
license_start_time_ = license.license_start_time();
next_renewal_time_ = license_start_time_
+ policy_.renewal_delay_seconds();
license_state_ =
policy_.can_play() ? kLicenseStateCanPlay : kLicenseStateExpired;
} else {
// license start was not updated. Continue sending renewel requests
// at the specified retry rate. To perform this we transition directly
// to kLicenseStateWaitingLicenseUpdate. While in this state
// IsRenewalRetryIntervalExpired will always return false if retries are
// not allowed. Note that next_renewal_time_ was updated when this
// renewal was requested.
license_state_ =
policy_.can_play() ?
kLicenseStateWaitingLicenseUpdate : kLicenseStateExpired;
}
}
}
}
void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
license_state_ = kLicenseStateWaitingLicenseUpdate;
next_renewal_time_ = current_time + policy_.renewal_retry_interval_seconds();
}
// For the policy time fields checked in the following methods, a value of 0
// indicates that there is no limit to the duration. These methods
// will always return false if the value is 0.
bool PolicyEngine::IsLicenseDurationExpired(int64_t current_time) {
return policy_max_duration_seconds_ &&
license_start_time_ + policy_max_duration_seconds_ <=
current_time;
}
bool PolicyEngine::IsRenewalDelayExpired(int64_t current_time) {
return (policy_.renewal_delay_seconds() > 0) &&
license_start_time_ + policy_.renewal_delay_seconds() <=
current_time;
}
// TODO(jfore): there is some gray around how this should be
// implemented. It currently is not.
bool PolicyEngine::IsRenewalRecoveryDurationExpired(
int64_t current_time) {
return (policy_.renewal_recovery_duration_seconds() > 0) &&
license_start_time_ + policy_.renewal_recovery_duration_seconds() <=
current_time;
}
bool PolicyEngine::IsRenewalRetryIntervalExpired(
int64_t current_time) {
return (policy_.renewal_retry_interval_seconds() > 0) &&
next_renewal_time_ <= current_time;
}
} // wvcdm