Merge "Add License::Policy::soft_enforce_playback_duration"
This commit is contained in:
@@ -119,7 +119,7 @@ class PolicyEngine {
|
|||||||
int64_t GetRentalExpiryTime();
|
int64_t GetRentalExpiryTime();
|
||||||
// Gets the clock time that the license expires based on whether we have
|
// Gets the clock time that the license expires based on whether we have
|
||||||
// started playing. This takes into account GetHardLicenseExpiryTime.
|
// started playing. This takes into account GetHardLicenseExpiryTime.
|
||||||
int64_t GetExpiryTime();
|
int64_t GetExpiryTime(bool ignore_soft_enforce_playback_duration);
|
||||||
|
|
||||||
int64_t GetLicenseOrRentalDurationRemaining(int64_t current_time);
|
int64_t GetLicenseOrRentalDurationRemaining(int64_t current_time);
|
||||||
int64_t GetPlaybackDurationRemaining(int64_t current_time);
|
int64_t GetPlaybackDurationRemaining(int64_t current_time);
|
||||||
@@ -161,6 +161,7 @@ class PolicyEngine {
|
|||||||
int64_t last_playback_time_;
|
int64_t last_playback_time_;
|
||||||
int64_t last_expiry_time_;
|
int64_t last_expiry_time_;
|
||||||
bool last_expiry_time_set_;
|
bool last_expiry_time_set_;
|
||||||
|
bool was_expired_on_load_;
|
||||||
|
|
||||||
// This is used as a reference point for policy management. This value
|
// This is used as a reference point for policy management. This value
|
||||||
// represents an offset from license_start_time_. This is used to
|
// represents an offset from license_start_time_. This is used to
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ message License {
|
|||||||
// Indicates to client that license renewal and release requests ought to
|
// Indicates to client that license renewal and release requests ought to
|
||||||
// include ClientIdentification (client_id).
|
// include ClientIdentification (client_id).
|
||||||
optional bool renew_with_client_id = 12 [default = false];
|
optional bool renew_with_client_id = 12 [default = false];
|
||||||
|
|
||||||
|
// Enables "soft enforcement" of playback_duration_seconds, letting the user
|
||||||
|
// finish playback even if short window expires. Optional.
|
||||||
|
optional bool soft_enforce_playback_duration = 14 [default = false];
|
||||||
}
|
}
|
||||||
|
|
||||||
message KeyContainer {
|
message KeyContainer {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ PolicyEngine::PolicyEngine(CdmSessionId session_id,
|
|||||||
last_playback_time_(0),
|
last_playback_time_(0),
|
||||||
last_expiry_time_(0),
|
last_expiry_time_(0),
|
||||||
last_expiry_time_set_(false),
|
last_expiry_time_set_(false),
|
||||||
|
was_expired_on_load_(false),
|
||||||
next_renewal_time_(0),
|
next_renewal_time_(0),
|
||||||
session_id_(session_id),
|
session_id_(session_id),
|
||||||
event_listener_(event_listener),
|
event_listener_(event_listener),
|
||||||
@@ -290,7 +291,8 @@ bool PolicyEngine::GetSecondsSinceLastPlayed(
|
|||||||
|
|
||||||
int64_t PolicyEngine::GetLicenseOrPlaybackDurationRemaining() {
|
int64_t PolicyEngine::GetLicenseOrPlaybackDurationRemaining() {
|
||||||
int64_t current_time = clock_->GetCurrentTime();
|
int64_t current_time = clock_->GetCurrentTime();
|
||||||
const int64_t expiry_time = GetExpiryTime();
|
const int64_t expiry_time =
|
||||||
|
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ false);
|
||||||
if (expiry_time == NEVER_EXPIRES) return LLONG_MAX;
|
if (expiry_time == NEVER_EXPIRES) return LLONG_MAX;
|
||||||
if (expiry_time < current_time) return 0;
|
if (expiry_time < current_time) return 0;
|
||||||
return expiry_time - current_time;
|
return expiry_time - current_time;
|
||||||
@@ -300,6 +302,13 @@ void PolicyEngine::RestorePlaybackTimes(int64_t playback_start_time,
|
|||||||
int64_t last_playback_time) {
|
int64_t last_playback_time) {
|
||||||
playback_start_time_ = (playback_start_time > 0) ? playback_start_time : 0;
|
playback_start_time_ = (playback_start_time > 0) ? playback_start_time : 0;
|
||||||
last_playback_time_ = (last_playback_time > 0) ? last_playback_time : 0;
|
last_playback_time_ = (last_playback_time > 0) ? last_playback_time : 0;
|
||||||
|
|
||||||
|
const int64_t current_time = clock_->GetCurrentTime();
|
||||||
|
const int64_t expiry_time =
|
||||||
|
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ true);
|
||||||
|
was_expired_on_load_ =
|
||||||
|
expiry_time != NEVER_EXPIRES && expiry_time < current_time;
|
||||||
|
|
||||||
NotifyExpirationUpdate();
|
NotifyExpirationUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,8 +318,9 @@ void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PolicyEngine::HasLicenseOrPlaybackDurationExpired(int64_t current_time) {
|
bool PolicyEngine::HasLicenseOrPlaybackDurationExpired(int64_t current_time) {
|
||||||
const int64_t expiry_time = GetExpiryTime();
|
const int64_t expiry_time =
|
||||||
return (expiry_time == NEVER_EXPIRES) ? false : (expiry_time <= current_time);
|
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ false);
|
||||||
|
return (expiry_time != NEVER_EXPIRES) && expiry_time <= current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the policy time fields checked in the following methods, a value of 0
|
// For the policy time fields checked in the following methods, a value of 0
|
||||||
@@ -332,12 +342,17 @@ int64_t PolicyEngine::GetRentalExpiryTime() {
|
|||||||
return std::min(hard_limit, expiry_time);
|
return std::min(hard_limit, expiry_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t PolicyEngine::GetExpiryTime() {
|
int64_t PolicyEngine::GetExpiryTime(
|
||||||
|
bool ignore_soft_enforce_playback_duration) {
|
||||||
if (!HasPlaybackStarted())
|
if (!HasPlaybackStarted())
|
||||||
return GetRentalExpiryTime();
|
return GetRentalExpiryTime();
|
||||||
|
|
||||||
const int64_t hard_limit = GetHardLicenseExpiryTime();
|
const int64_t hard_limit = GetHardLicenseExpiryTime();
|
||||||
if (policy_.playback_duration_seconds() == 0) return hard_limit;
|
if (policy_.playback_duration_seconds() == 0) return hard_limit;
|
||||||
|
if (!ignore_soft_enforce_playback_duration && !was_expired_on_load_ &&
|
||||||
|
policy_.soft_enforce_playback_duration()) {
|
||||||
|
return hard_limit;
|
||||||
|
}
|
||||||
const int64_t expiry_time =
|
const int64_t expiry_time =
|
||||||
playback_start_time_ + policy_.playback_duration_seconds();
|
playback_start_time_ + policy_.playback_duration_seconds();
|
||||||
|
|
||||||
@@ -404,7 +419,8 @@ void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PolicyEngine::NotifyExpirationUpdate() {
|
void PolicyEngine::NotifyExpirationUpdate() {
|
||||||
const int64_t expiry_time = GetExpiryTime();
|
const int64_t expiry_time =
|
||||||
|
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ false);
|
||||||
if (!last_expiry_time_set_ || expiry_time != last_expiry_time_) {
|
if (!last_expiry_time_set_ || expiry_time != last_expiry_time_) {
|
||||||
last_expiry_time_ = expiry_time;
|
last_expiry_time_ = expiry_time;
|
||||||
if (event_listener_)
|
if (event_listener_)
|
||||||
|
|||||||
@@ -1040,6 +1040,89 @@ TEST_F(PolicyEngineTest, MultipleKeysInLicense) {
|
|||||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kSomeRandomKeyId));
|
EXPECT_FALSE(policy_engine_->CanDecryptContent(kSomeRandomKeyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PolicyEngineTest, PlaybackOk_SoftEnforcePlaybackDuration) {
|
||||||
|
License_Policy* policy = license_.mutable_policy();
|
||||||
|
policy->set_soft_enforce_playback_duration(true);
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||||
|
.WillOnce(Return(kLicenseStartTime + 1))
|
||||||
|
.WillOnce(Return(kPlaybackStartTime))
|
||||||
|
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration - 5))
|
||||||
|
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration + 5))
|
||||||
|
.WillOnce(Return(kLicenseStartTime + kLicenseDuration - 5))
|
||||||
|
.WillOnce(Return(kLicenseStartTime + kLicenseDuration + 5));
|
||||||
|
|
||||||
|
InSequence seq;
|
||||||
|
ExpectSessionKeysChange(kKeyStatusUsable, true);
|
||||||
|
EXPECT_CALL(mock_event_listener_,
|
||||||
|
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
|
||||||
|
EXPECT_CALL(mock_event_listener_,
|
||||||
|
OnExpirationUpdate(_, kLicenseStartTime + kLicenseDuration));
|
||||||
|
EXPECT_CALL(check_, Call(1));
|
||||||
|
EXPECT_CALL(check_, Call(2));
|
||||||
|
EXPECT_CALL(check_, Call(3));
|
||||||
|
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
||||||
|
EXPECT_CALL(check_, Call(4));
|
||||||
|
|
||||||
|
policy_engine_->SetLicense(license_);
|
||||||
|
policy_engine_->BeginDecryption();
|
||||||
|
|
||||||
|
for (int i = 1; i <= 4; ++i) {
|
||||||
|
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId));
|
||||||
|
policy_engine_->OnTimerEvent();
|
||||||
|
check_.Call(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PolicyEngineTest, LicenseExpired_SoftEnforceLoadBeforeExpire) {
|
||||||
|
License_Policy* policy = license_.mutable_policy();
|
||||||
|
policy->set_soft_enforce_playback_duration(true);
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||||
|
.WillOnce(Return(kLicenseStartTime + 1))
|
||||||
|
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration - 5))
|
||||||
|
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration + 10));
|
||||||
|
|
||||||
|
InSequence seq;
|
||||||
|
ExpectSessionKeysChange(kKeyStatusUsable, true);
|
||||||
|
EXPECT_CALL(mock_event_listener_,
|
||||||
|
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
|
||||||
|
EXPECT_CALL(mock_event_listener_,
|
||||||
|
OnExpirationUpdate(_, kLicenseStartTime + kLicenseDuration));
|
||||||
|
|
||||||
|
policy_engine_->SetLicense(license_);
|
||||||
|
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime);
|
||||||
|
policy_engine_->OnTimerEvent();
|
||||||
|
|
||||||
|
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PolicyEngineTest, LicenseExpired_SoftEnforceLoadAfterExpire) {
|
||||||
|
License_Policy* policy = license_.mutable_policy();
|
||||||
|
policy->set_soft_enforce_playback_duration(true);
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||||
|
.WillOnce(Return(kLicenseStartTime + 1))
|
||||||
|
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration + 5))
|
||||||
|
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration + 10));
|
||||||
|
|
||||||
|
InSequence seq;
|
||||||
|
ExpectSessionKeysChange(kKeyStatusUsable, true);
|
||||||
|
EXPECT_CALL(mock_event_listener_,
|
||||||
|
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
|
||||||
|
EXPECT_CALL(mock_event_listener_,
|
||||||
|
OnExpirationUpdate(_, kPlaybackStartTime + kPlaybackDuration));
|
||||||
|
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
||||||
|
|
||||||
|
policy_engine_->SetLicense(license_);
|
||||||
|
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime);
|
||||||
|
policy_engine_->OnTimerEvent();
|
||||||
|
|
||||||
|
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||||
|
}
|
||||||
|
|
||||||
class PolicyEngineKeyAllowedUsageTest : public PolicyEngineTest {
|
class PolicyEngineKeyAllowedUsageTest : public PolicyEngineTest {
|
||||||
protected:
|
protected:
|
||||||
enum KeyFlag {
|
enum KeyFlag {
|
||||||
|
|||||||
Reference in New Issue
Block a user