Merge changes I420fb181,Id0c38b45
* changes: Policy Engine refactoring Update license proto
This commit is contained in:
@@ -44,6 +44,8 @@ cc_library_static {
|
|||||||
CORE_SRC_DIR + "/license_key_status.cpp",
|
CORE_SRC_DIR + "/license_key_status.cpp",
|
||||||
CORE_SRC_DIR + "/oemcrypto_adapter_dynamic.cpp",
|
CORE_SRC_DIR + "/oemcrypto_adapter_dynamic.cpp",
|
||||||
CORE_SRC_DIR + "/policy_engine.cpp",
|
CORE_SRC_DIR + "/policy_engine.cpp",
|
||||||
|
CORE_SRC_DIR + "/policy_timers.cpp",
|
||||||
|
CORE_SRC_DIR + "/policy_timers_v15.cpp",
|
||||||
CORE_SRC_DIR + "/privacy_crypto_boringssl.cpp",
|
CORE_SRC_DIR + "/privacy_crypto_boringssl.cpp",
|
||||||
CORE_SRC_DIR + "/service_certificate.cpp",
|
CORE_SRC_DIR + "/service_certificate.cpp",
|
||||||
CORE_SRC_DIR + "/usage_table_header.cpp",
|
CORE_SRC_DIR + "/usage_table_header.cpp",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "clock.h"
|
||||||
#include "disallow_copy_and_assign.h"
|
#include "disallow_copy_and_assign.h"
|
||||||
#include "license_key_status.h"
|
#include "license_key_status.h"
|
||||||
#include "license_protocol.pb.h"
|
#include "license_protocol.pb.h"
|
||||||
@@ -21,6 +22,7 @@ using video_widevine::WidevinePsshData_EntitledKey;
|
|||||||
|
|
||||||
class Clock;
|
class Clock;
|
||||||
class CryptoSession;
|
class CryptoSession;
|
||||||
|
class PolicyTimers;
|
||||||
class WvCdmEventListener;
|
class WvCdmEventListener;
|
||||||
|
|
||||||
// This acts as an oracle that basically says "Yes(true) you may still decrypt
|
// This acts as an oracle that basically says "Yes(true) you may still decrypt
|
||||||
@@ -68,6 +70,7 @@ class PolicyEngine {
|
|||||||
|
|
||||||
// Call this on first decrypt to set the start of playback.
|
// Call this on first decrypt to set the start of playback.
|
||||||
virtual bool BeginDecryption(void);
|
virtual bool BeginDecryption(void);
|
||||||
|
// Call this periodically to update the most recent playback time.
|
||||||
virtual void DecryptionEvent(void);
|
virtual void DecryptionEvent(void);
|
||||||
|
|
||||||
// UpdateLicense is used in handling a license response for a renewal request.
|
// UpdateLicense is used in handling a license response for a renewal request.
|
||||||
@@ -92,26 +95,20 @@ class PolicyEngine {
|
|||||||
bool GetSecondsSinceStarted(int64_t* seconds_since_started);
|
bool GetSecondsSinceStarted(int64_t* seconds_since_started);
|
||||||
bool GetSecondsSinceLastPlayed(int64_t* seconds_since_started);
|
bool GetSecondsSinceLastPlayed(int64_t* seconds_since_started);
|
||||||
|
|
||||||
// for offline save and restore
|
// For offline save and restore
|
||||||
int64_t GetPlaybackStartTime() { return playback_start_time_; }
|
int64_t GetPlaybackStartTime();
|
||||||
int64_t GetLastPlaybackTime() { return last_playback_time_; }
|
int64_t GetLastPlaybackTime();
|
||||||
int64_t GetGracePeriodEndTime() { return grace_period_end_time_; }
|
int64_t GetGracePeriodEndTime();
|
||||||
void RestorePlaybackTimes(int64_t playback_start_time,
|
void RestorePlaybackTimes(int64_t playback_start_time,
|
||||||
int64_t last_playback_time,
|
int64_t last_playback_time,
|
||||||
int64_t grace_period_end_time);
|
int64_t grace_period_end_time);
|
||||||
|
|
||||||
bool IsLicenseForFuture() { return license_state_ == kLicenseStatePending; }
|
bool IsLicenseForFuture() { return license_state_ == kLicenseStatePending; }
|
||||||
bool HasPlaybackStarted(int64_t current_time) {
|
|
||||||
if (playback_start_time_ == 0) return false;
|
|
||||||
|
|
||||||
const int64_t playback_time = current_time - playback_start_time_;
|
|
||||||
return playback_time >= policy_.play_start_grace_period_seconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasLicenseOrPlaybackDurationExpired(int64_t current_time);
|
bool HasLicenseOrPlaybackDurationExpired(int64_t current_time);
|
||||||
int64_t GetLicenseOrPlaybackDurationRemaining();
|
int64_t GetLicenseOrPlaybackDurationRemaining();
|
||||||
|
|
||||||
bool CanRenew() { return policy_.can_renew(); }
|
bool CanRenew() const;
|
||||||
|
|
||||||
bool IsSufficientOutputProtection(const KeyId& key_id) {
|
bool IsSufficientOutputProtection(const KeyId& key_id) {
|
||||||
return license_keys_->MeetsConstraints(key_id);
|
return license_keys_->MeetsConstraints(key_id);
|
||||||
@@ -135,26 +132,6 @@ class PolicyEngine {
|
|||||||
kLicenseStateExpired
|
kLicenseStateExpired
|
||||||
} LicenseState;
|
} LicenseState;
|
||||||
|
|
||||||
// Gets the clock time that the license expires. This is the hard limit that
|
|
||||||
// all license types must obey at all times.
|
|
||||||
int64_t GetHardLicenseExpiryTime();
|
|
||||||
// Gets the clock time that the rental duration will expire, using the license
|
|
||||||
// duration if one is not present.
|
|
||||||
int64_t GetRentalExpiryTime();
|
|
||||||
// Gets the clock time that the license expires based on whether we have
|
|
||||||
// started playing. This takes into account GetHardLicenseExpiryTime.
|
|
||||||
int64_t GetExpiryTime(int64_t current_time,
|
|
||||||
bool ignore_soft_enforce_playback_duration);
|
|
||||||
|
|
||||||
int64_t GetLicenseOrRentalDurationRemaining(int64_t current_time);
|
|
||||||
int64_t GetPlaybackDurationRemaining(int64_t current_time);
|
|
||||||
|
|
||||||
bool HasRenewalDelayExpired(int64_t current_time);
|
|
||||||
bool HasRenewalRecoveryDurationExpired(int64_t current_time);
|
|
||||||
bool HasRenewalRetryIntervalExpired(int64_t current_time);
|
|
||||||
|
|
||||||
void UpdateRenewalRequest(int64_t current_time);
|
|
||||||
|
|
||||||
// Notifies updates in keys information and fire OnKeysChange event if
|
// Notifies updates in keys information and fire OnKeysChange event if
|
||||||
// key changes.
|
// key changes.
|
||||||
void NotifyKeysChange(CdmKeyStatus new_status);
|
void NotifyKeysChange(CdmKeyStatus new_status);
|
||||||
@@ -163,7 +140,8 @@ class PolicyEngine {
|
|||||||
// expiry time changes.
|
// expiry time changes.
|
||||||
void NotifyExpirationUpdate(int64_t current_time);
|
void NotifyExpirationUpdate(int64_t current_time);
|
||||||
|
|
||||||
// Guard against clock rollbacks
|
void UpdateRenewalRequest(int64_t current_time);
|
||||||
|
|
||||||
int64_t GetCurrentTime();
|
int64_t GetCurrentTime();
|
||||||
|
|
||||||
// Test only methods
|
// Test only methods
|
||||||
@@ -174,31 +152,11 @@ class PolicyEngine {
|
|||||||
|
|
||||||
LicenseState license_state_;
|
LicenseState license_state_;
|
||||||
|
|
||||||
// This is the current policy information for this license. This gets updated
|
|
||||||
// as license renewals occur.
|
|
||||||
video_widevine::License::Policy policy_;
|
|
||||||
|
|
||||||
// This is the license id field from server response. This data gets passed
|
// This is the license id field from server response. This data gets passed
|
||||||
// back to the server in each renewal request. When we get a renewal response
|
// back to the server in each renewal request. When we get a renewal response
|
||||||
// from the license server we will get an updated id field.
|
// from the license server we will get an updated id field.
|
||||||
video_widevine::LicenseIdentification license_id_;
|
video_widevine::LicenseIdentification license_id_;
|
||||||
|
|
||||||
// The server returns the license start time in the license/license renewal
|
|
||||||
// response based off the request time sent by the client in the
|
|
||||||
// license request/renewal
|
|
||||||
int64_t license_start_time_;
|
|
||||||
int64_t playback_start_time_;
|
|
||||||
int64_t last_playback_time_;
|
|
||||||
int64_t last_expiry_time_;
|
|
||||||
int64_t grace_period_end_time_;
|
|
||||||
bool last_expiry_time_set_;
|
|
||||||
bool was_expired_on_load_;
|
|
||||||
|
|
||||||
// This is used as a reference point for policy management. This value
|
|
||||||
// represents an offset from license_start_time_. This is used to
|
|
||||||
// calculate the time where renewal retries should occur.
|
|
||||||
int64_t next_renewal_time_;
|
|
||||||
|
|
||||||
// to assist in clock rollback checks
|
// to assist in clock rollback checks
|
||||||
int64_t last_recorded_current_time_;
|
int64_t last_recorded_current_time_;
|
||||||
|
|
||||||
@@ -210,11 +168,16 @@ class PolicyEngine {
|
|||||||
// and current status (CdmKeyStatus)
|
// and current status (CdmKeyStatus)
|
||||||
std::unique_ptr<LicenseKeys> license_keys_;
|
std::unique_ptr<LicenseKeys> license_keys_;
|
||||||
|
|
||||||
|
// This is the current policy information for this license. This gets updated
|
||||||
|
// as license renewals occur.
|
||||||
|
video_widevine::License::Policy policy_;
|
||||||
|
|
||||||
// Device checks
|
// Device checks
|
||||||
int64_t next_device_check_;
|
int64_t next_device_check_;
|
||||||
uint32_t current_resolution_;
|
uint32_t current_resolution_;
|
||||||
CryptoSession* crypto_session_;
|
CryptoSession* crypto_session_;
|
||||||
|
|
||||||
|
std::unique_ptr<PolicyTimers> policy_timers;
|
||||||
std::unique_ptr<Clock> clock_;
|
std::unique_ptr<Clock> clock_;
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(PolicyEngine);
|
CORE_DISALLOW_COPY_AND_ASSIGN(PolicyEngine);
|
||||||
|
|||||||
112
libwvdrmengine/cdm/core/include/policy_timers.h
Normal file
112
libwvdrmengine/cdm/core/include/policy_timers.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef WVCDM_CORE_POLICY_TIMERS_H_
|
||||||
|
#define WVCDM_CORE_POLICY_TIMERS_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "disallow_copy_and_assign.h"
|
||||||
|
#include "license_protocol.pb.h"
|
||||||
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
|
namespace wvcdm {
|
||||||
|
|
||||||
|
// This is driven by the Policy Engine and maintains timer related
|
||||||
|
// information from the policy such as duration windows and renewals.
|
||||||
|
// Timer expiration behavior has changed with the introduction of core
|
||||||
|
// messages in OEMCrypto v16. Handling of behavior that differs between
|
||||||
|
// a OEMCrypto v16 license with core messages and one without is left to
|
||||||
|
// a class that derives from this interface.
|
||||||
|
|
||||||
|
class PolicyTimers {
|
||||||
|
public:
|
||||||
|
virtual ~PolicyTimers() {}
|
||||||
|
|
||||||
|
// SetLicense is used in handling the initial license response.
|
||||||
|
virtual void SetLicense(const video_widevine::License& license);
|
||||||
|
|
||||||
|
// UpdateLicense is used in handling a license response for a renewal request.
|
||||||
|
// The response may only contain policy fields that have changed. In this
|
||||||
|
// case an exact copy is not what we want to happen.
|
||||||
|
virtual bool UpdateLicense(int64_t current_time,
|
||||||
|
const video_widevine::License& license) = 0;
|
||||||
|
|
||||||
|
// Call this on first decrypt to set the start of playback.
|
||||||
|
virtual void BeginDecryption(int64_t current_time) = 0;
|
||||||
|
// Call this periodically to update the most recent playback time.
|
||||||
|
virtual void DecryptionEvent(int64_t current_time);
|
||||||
|
|
||||||
|
// For offline save and restore
|
||||||
|
virtual int64_t GetPlaybackStartTime() { return playback_start_time_; }
|
||||||
|
virtual int64_t GetLastPlaybackTime() { return last_playback_time_; }
|
||||||
|
virtual int64_t GetGracePeriodEndTime() = 0;
|
||||||
|
virtual void RestorePlaybackTimes(int64_t current_time,
|
||||||
|
int64_t playback_start_time,
|
||||||
|
int64_t last_playback_time,
|
||||||
|
int64_t grace_period_end_time) = 0;
|
||||||
|
|
||||||
|
virtual bool HasPlaybackStarted(int64_t current_time) = 0;
|
||||||
|
virtual bool HasLicenseOrPlaybackDurationExpired(int64_t current_time) = 0;
|
||||||
|
virtual bool HasPassedGracePeriod(int64_t current_time) = 0;
|
||||||
|
|
||||||
|
virtual int64_t GetLicenseOrPlaybackDurationRemaining(
|
||||||
|
int64_t current_time) = 0;
|
||||||
|
virtual int64_t GetLicenseOrRentalDurationRemaining(int64_t current_time) = 0;
|
||||||
|
virtual int64_t GetPlaybackDurationRemaining(int64_t current_time) = 0;
|
||||||
|
|
||||||
|
virtual bool GetSecondsSinceStarted(int64_t current_time,
|
||||||
|
int64_t* seconds_since_started);
|
||||||
|
virtual bool GetSecondsSinceLastPlayed(int64_t current_time,
|
||||||
|
int64_t* seconds_since_started);
|
||||||
|
|
||||||
|
virtual bool IsLicenseForFuture(int64_t current_time);
|
||||||
|
|
||||||
|
virtual bool UpdateExpirationTime(int64_t current_time, int64_t* expiry_time);
|
||||||
|
|
||||||
|
// Renewal related methods
|
||||||
|
virtual bool HasRenewalDelayExpired(int64_t current_time);
|
||||||
|
virtual bool HasRenewalRetryIntervalExpired(int64_t current_time);
|
||||||
|
virtual void UpdateRenewalRequest(int64_t current_time);
|
||||||
|
virtual bool HasRenewalRecoveryDurationExpired(int64_t current_time);
|
||||||
|
|
||||||
|
const video_widevine::License::Policy& get_policy() { return policy_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PolicyTimers()
|
||||||
|
: license_start_time_(0),
|
||||||
|
playback_start_time_(0),
|
||||||
|
last_playback_time_(0),
|
||||||
|
last_expiry_time_(0),
|
||||||
|
last_expiry_time_set_(false),
|
||||||
|
next_renewal_time_(0),
|
||||||
|
was_expired_on_load_(false) {}
|
||||||
|
|
||||||
|
// Gets the clock time that the license expires based on whether we have
|
||||||
|
// started playing.
|
||||||
|
virtual int64_t GetExpiryTime(int64_t current_time,
|
||||||
|
bool ignore_soft_enforce_playback_duration) = 0;
|
||||||
|
|
||||||
|
// This is the current policy information for this license. This gets updated
|
||||||
|
// as license renewals occur.
|
||||||
|
video_widevine::License::Policy policy_;
|
||||||
|
|
||||||
|
int64_t license_start_time_;
|
||||||
|
int64_t playback_start_time_;
|
||||||
|
int64_t last_playback_time_;
|
||||||
|
int64_t last_expiry_time_;
|
||||||
|
int64_t last_expiry_time_set_;
|
||||||
|
int64_t next_renewal_time_;
|
||||||
|
|
||||||
|
// Indicates whether a persistent license was expired when loaded
|
||||||
|
bool was_expired_on_load_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CORE_DISALLOW_COPY_AND_ASSIGN(PolicyTimers);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace wvcdm
|
||||||
|
|
||||||
|
#endif // WVCDM_CORE_POLICY_TIMERS_H_
|
||||||
85
libwvdrmengine/cdm/core/include/policy_timers_v15.h
Normal file
85
libwvdrmengine/cdm/core/include/policy_timers_v15.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef WVCDM_CORE_POLICY_TIMERS_V15_H_
|
||||||
|
#define WVCDM_CORE_POLICY_TIMERS_V15_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "disallow_copy_and_assign.h"
|
||||||
|
#include "license_protocol.pb.h"
|
||||||
|
#include "policy_timers.h"
|
||||||
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
|
namespace wvcdm {
|
||||||
|
|
||||||
|
// OEMCrypto v16 and core messages introduced changes to how duration values
|
||||||
|
// and clocks should be evaluated. This class provides backward compatibility
|
||||||
|
// for licenses that do not include a core message. Durations are handled
|
||||||
|
// in the same way as in earlier releases.
|
||||||
|
//
|
||||||
|
// Backward compatibility may be needed if
|
||||||
|
// * OEMCrypto has not been upgraded to v16
|
||||||
|
// * Licenses were persisted before the device was upgraded to v16
|
||||||
|
// * License service does not yet support core messages
|
||||||
|
|
||||||
|
class PolicyTimersV15 : public PolicyTimers {
|
||||||
|
public:
|
||||||
|
PolicyTimersV15() : grace_period_end_time_(0) {}
|
||||||
|
|
||||||
|
virtual ~PolicyTimersV15(){};
|
||||||
|
|
||||||
|
// UpdateLicense is used in handling a license response for a renewal request.
|
||||||
|
// The response may only contain any policy fields that have changed. In this
|
||||||
|
// case an exact copy is not what we want to happen.
|
||||||
|
bool UpdateLicense(int64_t current_time,
|
||||||
|
const video_widevine::License& license) override;
|
||||||
|
|
||||||
|
// Call this on first decrypt to set the start of playback.
|
||||||
|
void BeginDecryption(int64_t current_time) override;
|
||||||
|
|
||||||
|
// for offline save and restore
|
||||||
|
int64_t GetGracePeriodEndTime() override { return grace_period_end_time_; }
|
||||||
|
|
||||||
|
// for offline save and restore
|
||||||
|
void RestorePlaybackTimes(int64_t current_time, int64_t playback_start_time,
|
||||||
|
int64_t last_playback_time,
|
||||||
|
int64_t grace_period_end_time) override;
|
||||||
|
|
||||||
|
bool HasPlaybackStarted(int64_t current_time) override;
|
||||||
|
bool HasLicenseOrPlaybackDurationExpired(int64_t current_time) override;
|
||||||
|
bool HasPassedGracePeriod(int64_t current_time) override;
|
||||||
|
|
||||||
|
int64_t GetLicenseOrPlaybackDurationRemaining(int64_t current_time) override;
|
||||||
|
// This is only used in Query. This should return the time remaining on
|
||||||
|
// license_duration_seconds for streaming licenses and rental_duration_seconds
|
||||||
|
// for offline licenses.
|
||||||
|
int64_t GetLicenseOrRentalDurationRemaining(int64_t current_time) override;
|
||||||
|
// This is only used in Query. This should return playback_duration_seconds,
|
||||||
|
// or the time remaining on it if playing.
|
||||||
|
int64_t GetPlaybackDurationRemaining(int64_t current_time) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Gets the clock time that the license expires based on whether we have
|
||||||
|
// started playing. This takes into account GetHardLicenseExpiryTime.
|
||||||
|
int64_t GetExpiryTime(int64_t current_time,
|
||||||
|
bool ignore_soft_enforce_playback_duration) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Gets the clock time that the license expires. This is the hard limit that
|
||||||
|
// all license types must obey at all times.
|
||||||
|
int64_t GetHardLicenseExpiryTime();
|
||||||
|
// Gets the clock time that the rental duration will expire, using the license
|
||||||
|
// duration if one is not present.
|
||||||
|
int64_t GetRentalExpiryTime();
|
||||||
|
|
||||||
|
int64_t grace_period_end_time_;
|
||||||
|
|
||||||
|
CORE_DISALLOW_COPY_AND_ASSIGN(PolicyTimersV15);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace wvcdm
|
||||||
|
|
||||||
|
#endif // WVCDM_CORE_POLICY_TIMERS_V15_H_
|
||||||
@@ -37,9 +37,6 @@ const std::string kEmptyString;
|
|||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
// Protobuf generated classes.
|
// Protobuf generated classes.
|
||||||
using video_widevine::ClientIdentification_ClientCapabilities;
|
|
||||||
using video_widevine::ClientIdentification_NameValue;
|
|
||||||
using video_widevine::DrmDeviceCertificate;
|
|
||||||
using video_widevine::EncryptedClientIdentification;
|
using video_widevine::EncryptedClientIdentification;
|
||||||
using video_widevine::License;
|
using video_widevine::License;
|
||||||
using video_widevine::License_KeyContainer;
|
using video_widevine::License_KeyContainer;
|
||||||
@@ -47,10 +44,9 @@ using video_widevine::LicenseError;
|
|||||||
using video_widevine::LicenseIdentification;
|
using video_widevine::LicenseIdentification;
|
||||||
using video_widevine::LicenseRequest;
|
using video_widevine::LicenseRequest;
|
||||||
using video_widevine::LicenseRequest_ContentIdentification;
|
using video_widevine::LicenseRequest_ContentIdentification;
|
||||||
using video_widevine::LicenseRequest_ContentIdentification_CencDeprecated;
|
|
||||||
using video_widevine::LicenseRequest_ContentIdentification_ExistingLicense;
|
using video_widevine::LicenseRequest_ContentIdentification_ExistingLicense;
|
||||||
using video_widevine::LicenseRequest_ContentIdentification_WebmDeprecated;
|
using video_widevine::LicenseRequest_ContentIdentification_WebmKeyId;
|
||||||
using video_widevine::SignedDrmDeviceCertificate;
|
using video_widevine::LicenseRequest_ContentIdentification_WidevinePsshData;
|
||||||
using video_widevine::SignedMessage;
|
using video_widevine::SignedMessage;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -1052,31 +1048,31 @@ CdmResponseType CdmLicense::PrepareContentId(
|
|||||||
license_request->mutable_content_id();
|
license_request->mutable_content_id();
|
||||||
|
|
||||||
if (init_data.is_cenc() || init_data.is_hls()) {
|
if (init_data.is_cenc() || init_data.is_hls()) {
|
||||||
LicenseRequest_ContentIdentification_CencDeprecated* cenc_content_id =
|
LicenseRequest_ContentIdentification_WidevinePsshData* widevine_pssh_data =
|
||||||
content_id->mutable_cenc_id_deprecated();
|
content_id->mutable_widevine_pssh_data();
|
||||||
|
|
||||||
if (!init_data.IsEmpty()) {
|
if (!init_data.IsEmpty()) {
|
||||||
cenc_content_id->add_pssh(init_data.data());
|
widevine_pssh_data->add_pssh_data(init_data.data());
|
||||||
} else {
|
} else {
|
||||||
LOGE("ISO-CENC init data not available");
|
LOGE("ISO-CENC init data not available");
|
||||||
return CENC_INIT_DATA_UNAVAILABLE;
|
return CENC_INIT_DATA_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetTypeAndId(license_type, request_id, cenc_content_id)) {
|
if (!SetTypeAndId(license_type, request_id, widevine_pssh_data)) {
|
||||||
return PREPARE_CENC_CONTENT_ID_FAILED;
|
return PREPARE_CENC_CONTENT_ID_FAILED;
|
||||||
}
|
}
|
||||||
} else if (init_data.is_webm()) {
|
} else if (init_data.is_webm()) {
|
||||||
LicenseRequest_ContentIdentification_WebmDeprecated* webm_content_id =
|
LicenseRequest_ContentIdentification_WebmKeyId* webm_key_id =
|
||||||
content_id->mutable_webm_id_deprecated();
|
content_id->mutable_webm_key_id();
|
||||||
|
|
||||||
if (!init_data.IsEmpty()) {
|
if (!init_data.IsEmpty()) {
|
||||||
webm_content_id->set_header(init_data.data());
|
webm_key_id->set_header(init_data.data());
|
||||||
} else {
|
} else {
|
||||||
LOGE("WebM init data not available");
|
LOGE("WebM init data not available");
|
||||||
return WEBM_INIT_DATA_UNAVAILABLE;
|
return WEBM_INIT_DATA_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetTypeAndId(license_type, request_id, webm_content_id)) {
|
if (!SetTypeAndId(license_type, request_id, webm_key_id)) {
|
||||||
return PREPARE_WEBM_CONTENT_ID_FAILED;
|
return PREPARE_WEBM_CONTENT_ID_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ message RemoteAttestation {
|
|||||||
enum LicenseType {
|
enum LicenseType {
|
||||||
STREAMING = 1;
|
STREAMING = 1;
|
||||||
OFFLINE = 2;
|
OFFLINE = 2;
|
||||||
|
// License type decision is left to provider.
|
||||||
|
AUTOMATIC = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PlatformVerificationStatus {
|
enum PlatformVerificationStatus {
|
||||||
@@ -131,15 +133,23 @@ message License {
|
|||||||
// Enables "soft enforcement" of playback_duration_seconds, letting the user
|
// Enables "soft enforcement" of playback_duration_seconds, letting the user
|
||||||
// finish playback even if short window expires. Optional.
|
// finish playback even if short window expires. Optional.
|
||||||
optional bool soft_enforce_playback_duration = 14 [default = false];
|
optional bool soft_enforce_playback_duration = 14 [default = false];
|
||||||
|
|
||||||
|
// Enables "soft enforcement" of rental_duration_seconds. Initial playback
|
||||||
|
// must always start before rental duration expires. In order to allow
|
||||||
|
// subsequent playbacks to start after the rental duration expires,
|
||||||
|
// soft_enforce_playback_duration must be true. Otherwise, subsequent
|
||||||
|
// playbacks will not be allowed once rental duration expires. Optional.
|
||||||
|
optional bool soft_enforce_rental_duration = 15 [default = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
message KeyContainer {
|
message KeyContainer {
|
||||||
enum KeyType {
|
enum KeyType {
|
||||||
SIGNING = 1; // Exactly one key of this type must appear.
|
SIGNING = 1; // Exactly one key of this type must appear.
|
||||||
CONTENT = 2; // Content key.
|
CONTENT = 2; // Content key.
|
||||||
KEY_CONTROL = 3; // Key control block for license renewals. No key.
|
KEY_CONTROL = 3; // Key control block for license renewals. No key.
|
||||||
OPERATOR_SESSION = 4; // wrapped keys for auxiliary crypto operations.
|
OPERATOR_SESSION = 4; // wrapped keys for auxiliary crypto operations.
|
||||||
ENTITLEMENT = 5; // Entitlement keys.
|
ENTITLEMENT = 5; // Entitlement keys.
|
||||||
|
OEM_CONTENT = 6; // Partner-specific content key.
|
||||||
}
|
}
|
||||||
|
|
||||||
// The SecurityLevel enumeration allows the server to communicate the level
|
// The SecurityLevel enumeration allows the server to communicate the level
|
||||||
@@ -291,7 +301,6 @@ message License {
|
|||||||
[default = PLATFORM_NO_VERIFICATION];
|
[default = PLATFORM_NO_VERIFICATION];
|
||||||
// IDs of the groups for which keys are delivered in this license, if any.
|
// IDs of the groups for which keys are delivered in this license, if any.
|
||||||
repeated bytes group_ids = 11;
|
repeated bytes group_ids = 11;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ProtocolVersion {
|
enum ProtocolVersion {
|
||||||
@@ -302,13 +311,13 @@ enum ProtocolVersion {
|
|||||||
|
|
||||||
message LicenseRequest {
|
message LicenseRequest {
|
||||||
message ContentIdentification {
|
message ContentIdentification {
|
||||||
message CencDeprecated {
|
message WidevinePsshData {
|
||||||
repeated bytes pssh = 1;
|
repeated bytes pssh_data = 1;
|
||||||
optional LicenseType license_type = 2;
|
optional LicenseType license_type = 2;
|
||||||
optional bytes request_id = 3; // Opaque, client-specified.
|
optional bytes request_id = 3; // Opaque, client-specified.
|
||||||
}
|
}
|
||||||
|
|
||||||
message WebmDeprecated {
|
message WebmKeyId {
|
||||||
optional bytes header = 1;
|
optional bytes header = 1;
|
||||||
optional LicenseType license_type = 2;
|
optional LicenseType license_type = 2;
|
||||||
optional bytes request_id = 3; // Opaque, client-specified.
|
optional bytes request_id = 3; // Opaque, client-specified.
|
||||||
@@ -335,8 +344,8 @@ message LicenseRequest {
|
|||||||
|
|
||||||
oneof content_id_variant {
|
oneof content_id_variant {
|
||||||
// Exactly one of these must be present.
|
// Exactly one of these must be present.
|
||||||
CencDeprecated cenc_id_deprecated = 1;
|
WidevinePsshData widevine_pssh_data = 1;
|
||||||
WebmDeprecated webm_id_deprecated = 2;
|
WebmKeyId webm_key_id = 2;
|
||||||
ExistingLicense existing_license = 3;
|
ExistingLicense existing_license = 3;
|
||||||
InitData init_data = 4;
|
InitData init_data = 4;
|
||||||
}
|
}
|
||||||
@@ -431,7 +440,6 @@ message SignedMessage {
|
|||||||
WRAPPED_AES_KEY = 1;
|
WRAPPED_AES_KEY = 1;
|
||||||
EPHERMERAL_ECC_PUBLIC_KEY = 2;
|
EPHERMERAL_ECC_PUBLIC_KEY = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional MessageType type = 1;
|
optional MessageType type = 1;
|
||||||
optional bytes msg = 2;
|
optional bytes msg = 2;
|
||||||
// Required field that contains the signature of the bytes of msg.
|
// Required field that contains the signature of the bytes of msg.
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
|
|
||||||
#include "policy_engine.h"
|
#include "policy_engine.h"
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "policy_timers_v15.h"
|
||||||
#include "properties.h"
|
#include "properties.h"
|
||||||
#include "string_conversions.h"
|
#include "string_conversions.h"
|
||||||
#include "wv_cdm_constants.h"
|
#include "wv_cdm_constants.h"
|
||||||
@@ -30,18 +29,11 @@ PolicyEngine::PolicyEngine(CdmSessionId session_id,
|
|||||||
WvCdmEventListener* event_listener,
|
WvCdmEventListener* event_listener,
|
||||||
CryptoSession* crypto_session)
|
CryptoSession* crypto_session)
|
||||||
: license_state_(kLicenseStateInitial),
|
: license_state_(kLicenseStateInitial),
|
||||||
license_start_time_(0),
|
|
||||||
playback_start_time_(0),
|
|
||||||
last_playback_time_(0),
|
|
||||||
last_expiry_time_(0),
|
|
||||||
grace_period_end_time_(0),
|
|
||||||
last_expiry_time_set_(false),
|
|
||||||
was_expired_on_load_(false),
|
|
||||||
next_renewal_time_(0),
|
|
||||||
last_recorded_current_time_(0),
|
last_recorded_current_time_(0),
|
||||||
session_id_(session_id),
|
session_id_(session_id),
|
||||||
event_listener_(event_listener),
|
event_listener_(event_listener),
|
||||||
license_keys_(new LicenseKeys(crypto_session->GetSecurityLevel())),
|
license_keys_(new LicenseKeys(crypto_session->GetSecurityLevel())),
|
||||||
|
policy_timers(new PolicyTimersV15),
|
||||||
clock_(new Clock) {
|
clock_(new Clock) {
|
||||||
InitDevice(crypto_session);
|
InitDevice(crypto_session);
|
||||||
}
|
}
|
||||||
@@ -95,16 +87,15 @@ void PolicyEngine::CheckDeviceHdcpStatus() {
|
|||||||
|
|
||||||
void PolicyEngine::OnTimerEvent() {
|
void PolicyEngine::OnTimerEvent() {
|
||||||
last_recorded_current_time_ += kCdmPolicyTimerDurationSeconds;
|
last_recorded_current_time_ += kCdmPolicyTimerDurationSeconds;
|
||||||
int64_t current_time = GetCurrentTime();
|
const int64_t current_time = GetCurrentTime();
|
||||||
|
|
||||||
// If we have passed the grace period, the expiration will update.
|
// If we have passed the grace period, the expiration will update.
|
||||||
if (grace_period_end_time_ == 0 && HasPlaybackStarted(current_time)) {
|
if (policy_timers->HasPassedGracePeriod(current_time)) {
|
||||||
grace_period_end_time_ = playback_start_time_;
|
|
||||||
NotifyExpirationUpdate(current_time);
|
NotifyExpirationUpdate(current_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// License expiration trumps all.
|
// License expiration trumps all.
|
||||||
if (HasLicenseOrPlaybackDurationExpired(current_time) &&
|
if (policy_timers->HasLicenseOrPlaybackDurationExpired(current_time) &&
|
||||||
license_state_ != kLicenseStateExpired) {
|
license_state_ != kLicenseStateExpired) {
|
||||||
license_state_ = kLicenseStateExpired;
|
license_state_ = kLicenseStateExpired;
|
||||||
NotifyKeysChange(kKeyStatusExpired);
|
NotifyKeysChange(kKeyStatusExpired);
|
||||||
@@ -119,7 +110,7 @@ void PolicyEngine::OnTimerEvent() {
|
|||||||
// Test to determine if renewal should be attempted.
|
// Test to determine if renewal should be attempted.
|
||||||
switch (license_state_) {
|
switch (license_state_) {
|
||||||
case kLicenseStateCanPlay: {
|
case kLicenseStateCanPlay: {
|
||||||
if (HasRenewalDelayExpired(current_time)) {
|
if (policy_timers->HasRenewalDelayExpired(current_time)) {
|
||||||
renewal_needed = true;
|
renewal_needed = true;
|
||||||
}
|
}
|
||||||
// HDCP may change, so force a check.
|
// HDCP may change, so force a check.
|
||||||
@@ -133,14 +124,14 @@ void PolicyEngine::OnTimerEvent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case kLicenseStateWaitingLicenseUpdate: {
|
case kLicenseStateWaitingLicenseUpdate: {
|
||||||
if (HasRenewalRetryIntervalExpired(current_time)) {
|
if (policy_timers->HasRenewalRetryIntervalExpired(current_time)) {
|
||||||
renewal_needed = true;
|
renewal_needed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case kLicenseStatePending: {
|
case kLicenseStatePending: {
|
||||||
if (current_time >= license_start_time_) {
|
if (!policy_timers->IsLicenseForFuture(current_time)) {
|
||||||
license_state_ = kLicenseStateCanPlay;
|
license_state_ = kLicenseStateCanPlay;
|
||||||
NotifyKeysChange(kKeyStatusUsable);
|
NotifyKeysChange(kKeyStatusUsable);
|
||||||
}
|
}
|
||||||
@@ -168,8 +159,8 @@ void PolicyEngine::OnTimerEvent() {
|
|||||||
void PolicyEngine::SetLicense(const License& license) {
|
void PolicyEngine::SetLicense(const License& license) {
|
||||||
license_id_.Clear();
|
license_id_.Clear();
|
||||||
license_id_.CopyFrom(license.id());
|
license_id_.CopyFrom(license.id());
|
||||||
policy_.Clear();
|
|
||||||
license_keys_->SetFromLicense(license);
|
license_keys_->SetFromLicense(license);
|
||||||
|
policy_timers->SetLicense(license);
|
||||||
UpdateLicense(license);
|
UpdateLicense(license);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +172,10 @@ void PolicyEngine::SetEntitledLicenseKeys(
|
|||||||
void PolicyEngine::SetLicenseForRelease(const License& license) {
|
void PolicyEngine::SetLicenseForRelease(const License& license) {
|
||||||
license_id_.Clear();
|
license_id_.Clear();
|
||||||
license_id_.CopyFrom(license.id());
|
license_id_.CopyFrom(license.id());
|
||||||
policy_.Clear();
|
|
||||||
|
|
||||||
// Expire any old keys.
|
// Expire any old keys.
|
||||||
NotifyKeysChange(kKeyStatusExpired);
|
NotifyKeysChange(kKeyStatusExpired);
|
||||||
|
policy_timers->SetLicense(license);
|
||||||
UpdateLicense(license);
|
UpdateLicense(license);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,8 +186,6 @@ void PolicyEngine::UpdateLicense(const License& license) {
|
|||||||
LOGD("Updating an expired license");
|
LOGD("Updating an expired license");
|
||||||
}
|
}
|
||||||
|
|
||||||
policy_.MergeFrom(license.policy());
|
|
||||||
|
|
||||||
// some basic license validation
|
// some basic license validation
|
||||||
// license start time needs to be specified in the initial response
|
// license start time needs to be specified in the initial response
|
||||||
if (!license.has_license_start_time()) return;
|
if (!license.has_license_start_time()) return;
|
||||||
@@ -209,20 +198,19 @@ void PolicyEngine::UpdateLicense(const License& license) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update time information
|
const int64_t current_time = GetCurrentTime();
|
||||||
license_start_time_ = license.license_start_time();
|
policy_timers->UpdateLicense(current_time, license);
|
||||||
next_renewal_time_ = license_start_time_ + policy_.renewal_delay_seconds();
|
|
||||||
|
|
||||||
int64_t current_time = GetCurrentTime();
|
// Update time information
|
||||||
if (!policy_.can_play() ||
|
if (!policy_timers->get_policy().can_play() ||
|
||||||
HasLicenseOrPlaybackDurationExpired(current_time)) {
|
policy_timers->HasLicenseOrPlaybackDurationExpired(current_time)) {
|
||||||
license_state_ = kLicenseStateExpired;
|
license_state_ = kLicenseStateExpired;
|
||||||
NotifyKeysChange(kKeyStatusExpired);
|
NotifyKeysChange(kKeyStatusExpired);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
if (current_time >= license_start_time_) {
|
if (!policy_timers->IsLicenseForFuture(current_time)) {
|
||||||
license_state_ = kLicenseStateCanPlay;
|
license_state_ = kLicenseStateCanPlay;
|
||||||
NotifyKeysChange(kKeyStatusUsable);
|
NotifyKeysChange(kKeyStatusUsable);
|
||||||
} else {
|
} else {
|
||||||
@@ -233,20 +221,18 @@ void PolicyEngine::UpdateLicense(const License& license) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PolicyEngine::BeginDecryption() {
|
bool PolicyEngine::BeginDecryption() {
|
||||||
if (playback_start_time_ == 0) {
|
const int64_t current_time = GetCurrentTime();
|
||||||
|
if (!policy_timers->HasPlaybackStarted(current_time)) {
|
||||||
switch (license_state_) {
|
switch (license_state_) {
|
||||||
case kLicenseStateCanPlay:
|
case kLicenseStateCanPlay:
|
||||||
case kLicenseStateNeedRenewal:
|
case kLicenseStateNeedRenewal:
|
||||||
case kLicenseStateWaitingLicenseUpdate:
|
case kLicenseStateWaitingLicenseUpdate:
|
||||||
playback_start_time_ = GetCurrentTime();
|
policy_timers->BeginDecryption(current_time);
|
||||||
last_playback_time_ = playback_start_time_;
|
|
||||||
if (policy_.play_start_grace_period_seconds() == 0)
|
|
||||||
grace_period_end_time_ = playback_start_time_;
|
|
||||||
|
|
||||||
if (policy_.renew_with_usage()) {
|
if (policy_timers->get_policy().renew_with_usage()) {
|
||||||
license_state_ = kLicenseStateNeedRenewal;
|
license_state_ = kLicenseStateNeedRenewal;
|
||||||
}
|
}
|
||||||
NotifyExpirationUpdate(playback_start_time_);
|
NotifyExpirationUpdate(current_time);
|
||||||
return true;
|
return true;
|
||||||
case kLicenseStateInitial:
|
case kLicenseStateInitial:
|
||||||
case kLicenseStatePending:
|
case kLicenseStatePending:
|
||||||
@@ -259,7 +245,9 @@ bool PolicyEngine::BeginDecryption() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolicyEngine::DecryptionEvent() { last_playback_time_ = GetCurrentTime(); }
|
void PolicyEngine::DecryptionEvent() {
|
||||||
|
policy_timers->DecryptionEvent(GetCurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
void PolicyEngine::NotifyResolution(uint32_t width, uint32_t height) {
|
void PolicyEngine::NotifyResolution(uint32_t width, uint32_t height) {
|
||||||
SetDeviceResolution(width, height);
|
SetDeviceResolution(width, height);
|
||||||
@@ -271,7 +259,7 @@ void PolicyEngine::NotifySessionExpiration() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType PolicyEngine::Query(CdmQueryMap* query_response) {
|
CdmResponseType PolicyEngine::Query(CdmQueryMap* query_response) {
|
||||||
int64_t current_time = GetCurrentTime();
|
const int64_t current_time = GetCurrentTime();
|
||||||
|
|
||||||
if (license_state_ == kLicenseStateInitial) {
|
if (license_state_ == kLicenseStateInitial) {
|
||||||
query_response->clear();
|
query_response->clear();
|
||||||
@@ -282,17 +270,20 @@ CdmResponseType PolicyEngine::Query(CdmQueryMap* query_response) {
|
|||||||
license_id_.type() == video_widevine::STREAMING ? QUERY_VALUE_STREAMING
|
license_id_.type() == video_widevine::STREAMING ? QUERY_VALUE_STREAMING
|
||||||
: QUERY_VALUE_OFFLINE;
|
: QUERY_VALUE_OFFLINE;
|
||||||
(*query_response)[QUERY_KEY_PLAY_ALLOWED] =
|
(*query_response)[QUERY_KEY_PLAY_ALLOWED] =
|
||||||
policy_.can_play() ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
policy_timers->get_policy().can_play() ? QUERY_VALUE_TRUE
|
||||||
|
: QUERY_VALUE_FALSE;
|
||||||
(*query_response)[QUERY_KEY_PERSIST_ALLOWED] =
|
(*query_response)[QUERY_KEY_PERSIST_ALLOWED] =
|
||||||
policy_.can_persist() ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
policy_timers->get_policy().can_persist() ? QUERY_VALUE_TRUE
|
||||||
|
: QUERY_VALUE_FALSE;
|
||||||
(*query_response)[QUERY_KEY_RENEW_ALLOWED] =
|
(*query_response)[QUERY_KEY_RENEW_ALLOWED] =
|
||||||
policy_.can_renew() ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
policy_timers->get_policy().can_renew() ? QUERY_VALUE_TRUE
|
||||||
(*query_response)[QUERY_KEY_LICENSE_DURATION_REMAINING] =
|
: QUERY_VALUE_FALSE;
|
||||||
std::to_string(GetLicenseOrRentalDurationRemaining(current_time));
|
(*query_response)[QUERY_KEY_LICENSE_DURATION_REMAINING] = std::to_string(
|
||||||
|
policy_timers->GetLicenseOrRentalDurationRemaining(current_time));
|
||||||
(*query_response)[QUERY_KEY_PLAYBACK_DURATION_REMAINING] =
|
(*query_response)[QUERY_KEY_PLAYBACK_DURATION_REMAINING] =
|
||||||
std::to_string(GetPlaybackDurationRemaining(current_time));
|
std::to_string(policy_timers->GetPlaybackDurationRemaining(current_time));
|
||||||
(*query_response)[QUERY_KEY_RENEWAL_SERVER_URL] =
|
(*query_response)[QUERY_KEY_RENEWAL_SERVER_URL] =
|
||||||
policy_.renewal_server_url();
|
policy_timers->get_policy().renewal_server_url();
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -314,148 +305,54 @@ bool PolicyEngine::CanUseKeyForSecurityLevel(const KeyId& key_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PolicyEngine::GetSecondsSinceStarted(int64_t* seconds_since_started) {
|
bool PolicyEngine::GetSecondsSinceStarted(int64_t* seconds_since_started) {
|
||||||
if (playback_start_time_ == 0) return false;
|
return policy_timers->GetSecondsSinceStarted(GetCurrentTime(),
|
||||||
|
seconds_since_started);
|
||||||
*seconds_since_started = GetCurrentTime() - playback_start_time_;
|
|
||||||
return (*seconds_since_started >= 0) ? true : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PolicyEngine::GetSecondsSinceLastPlayed(
|
bool PolicyEngine::GetSecondsSinceLastPlayed(
|
||||||
int64_t* seconds_since_last_played) {
|
int64_t* seconds_since_last_played) {
|
||||||
if (last_playback_time_ == 0) return false;
|
return policy_timers->GetSecondsSinceLastPlayed(GetCurrentTime(),
|
||||||
|
seconds_since_last_played);
|
||||||
*seconds_since_last_played = GetCurrentTime() - last_playback_time_;
|
|
||||||
return (*seconds_since_last_played >= 0) ? true : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t PolicyEngine::GetLicenseOrPlaybackDurationRemaining() {
|
int64_t PolicyEngine::GetLicenseOrPlaybackDurationRemaining() {
|
||||||
const int64_t current_time = GetCurrentTime();
|
return policy_timers->GetLicenseOrPlaybackDurationRemaining(GetCurrentTime());
|
||||||
const int64_t expiry_time =
|
}
|
||||||
GetExpiryTime(current_time,
|
|
||||||
/* ignore_soft_enforce_playback_duration */ false);
|
bool PolicyEngine::CanRenew() const {
|
||||||
if (expiry_time == NEVER_EXPIRES) return LLONG_MAX;
|
return policy_timers->get_policy().can_renew();
|
||||||
if (expiry_time < current_time) return 0;
|
}
|
||||||
return expiry_time - current_time;
|
|
||||||
|
int64_t PolicyEngine::GetPlaybackStartTime() {
|
||||||
|
return policy_timers->GetPlaybackStartTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t PolicyEngine::GetLastPlaybackTime() {
|
||||||
|
return policy_timers->GetLastPlaybackTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t PolicyEngine::GetGracePeriodEndTime() {
|
||||||
|
return policy_timers->GetGracePeriodEndTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolicyEngine::RestorePlaybackTimes(int64_t playback_start_time,
|
void PolicyEngine::RestorePlaybackTimes(int64_t playback_start_time,
|
||||||
int64_t last_playback_time,
|
int64_t last_playback_time,
|
||||||
int64_t grace_period_end_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;
|
|
||||||
grace_period_end_time_ = grace_period_end_time;
|
|
||||||
|
|
||||||
if (policy_.play_start_grace_period_seconds() != 0) {
|
|
||||||
// If we are using grace period, we may need to override some of the values
|
|
||||||
// given to us by OEMCrypto. |grace_period_end_time| will be 0 if the grace
|
|
||||||
// period has not expired (effectively playback has not begun). Otherwise,
|
|
||||||
// |grace_period_end_time| contains the playback start time we should use.
|
|
||||||
playback_start_time_ = grace_period_end_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int64_t current_time = GetCurrentTime();
|
const int64_t current_time = GetCurrentTime();
|
||||||
const int64_t expiry_time =
|
policy_timers->RestorePlaybackTimes(current_time, playback_start_time,
|
||||||
GetExpiryTime(current_time,
|
last_playback_time,
|
||||||
/* ignore_soft_enforce_playback_duration */ true);
|
grace_period_end_time);
|
||||||
was_expired_on_load_ =
|
|
||||||
expiry_time != NEVER_EXPIRES && expiry_time < current_time;
|
|
||||||
|
|
||||||
NotifyExpirationUpdate(current_time);
|
NotifyExpirationUpdate(current_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
|
void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
|
||||||
license_state_ = kLicenseStateWaitingLicenseUpdate;
|
license_state_ = kLicenseStateWaitingLicenseUpdate;
|
||||||
next_renewal_time_ = current_time + policy_.renewal_retry_interval_seconds();
|
policy_timers->UpdateRenewalRequest(current_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PolicyEngine::HasLicenseOrPlaybackDurationExpired(int64_t current_time) {
|
bool PolicyEngine::HasLicenseOrPlaybackDurationExpired(int64_t current_time) {
|
||||||
const int64_t expiry_time =
|
return policy_timers->HasLicenseOrPlaybackDurationExpired(current_time);
|
||||||
GetExpiryTime(current_time,
|
|
||||||
/* 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
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
int64_t PolicyEngine::GetHardLicenseExpiryTime() {
|
|
||||||
return policy_.license_duration_seconds() > 0
|
|
||||||
? license_start_time_ + policy_.license_duration_seconds()
|
|
||||||
: NEVER_EXPIRES;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t PolicyEngine::GetRentalExpiryTime() {
|
|
||||||
const int64_t hard_limit = GetHardLicenseExpiryTime();
|
|
||||||
if (policy_.rental_duration_seconds() == 0) return hard_limit;
|
|
||||||
const int64_t expiry_time =
|
|
||||||
license_start_time_ + policy_.rental_duration_seconds();
|
|
||||||
if (hard_limit == NEVER_EXPIRES) return expiry_time;
|
|
||||||
return std::min(hard_limit, expiry_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t PolicyEngine::GetExpiryTime(
|
|
||||||
int64_t current_time, bool ignore_soft_enforce_playback_duration) {
|
|
||||||
if (!HasPlaybackStarted(current_time)) return GetRentalExpiryTime();
|
|
||||||
|
|
||||||
const int64_t hard_limit = GetHardLicenseExpiryTime();
|
|
||||||
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 =
|
|
||||||
playback_start_time_ + policy_.playback_duration_seconds();
|
|
||||||
|
|
||||||
if (hard_limit == NEVER_EXPIRES) return expiry_time;
|
|
||||||
return std::min(hard_limit, expiry_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t PolicyEngine::GetLicenseOrRentalDurationRemaining(
|
|
||||||
int64_t current_time) {
|
|
||||||
// This is only used in Query. This should return the time remaining on
|
|
||||||
// license_duration_seconds for streaming licenses and rental_duration_seconds
|
|
||||||
// for offline licenses.
|
|
||||||
if (HasLicenseOrPlaybackDurationExpired(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)
|
|
||||||
return license_expiry_time - current_time;
|
|
||||||
return std::min(license_expiry_time - current_time, policy_license_duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t PolicyEngine::GetPlaybackDurationRemaining(int64_t current_time) {
|
|
||||||
// This is only used in Query. This should return playback_duration_seconds,
|
|
||||||
// or the time remaining on it if playing.
|
|
||||||
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 PolicyEngine::HasRenewalDelayExpired(int64_t current_time) {
|
|
||||||
return policy_.can_renew() && (policy_.renewal_delay_seconds() > 0) &&
|
|
||||||
license_start_time_ + policy_.renewal_delay_seconds() <= current_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PolicyEngine::HasRenewalRecoveryDurationExpired(int64_t current_time) {
|
|
||||||
// NOTE: Renewal Recovery Duration is currently not used.
|
|
||||||
return (policy_.renewal_recovery_duration_seconds() > 0) &&
|
|
||||||
license_start_time_ + policy_.renewal_recovery_duration_seconds() <=
|
|
||||||
current_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PolicyEngine::HasRenewalRetryIntervalExpired(int64_t current_time) {
|
|
||||||
return policy_.can_renew() &&
|
|
||||||
(policy_.renewal_retry_interval_seconds() > 0) &&
|
|
||||||
next_renewal_time_ <= current_time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply a key status to the current keys.
|
// Apply a key status to the current keys.
|
||||||
@@ -479,15 +376,11 @@ void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PolicyEngine::NotifyExpirationUpdate(int64_t current_time) {
|
void PolicyEngine::NotifyExpirationUpdate(int64_t current_time) {
|
||||||
const int64_t expiry_time =
|
int64_t expiry_time;
|
||||||
GetExpiryTime(current_time,
|
if (policy_timers->UpdateExpirationTime(current_time, &expiry_time)) {
|
||||||
/* ignore_soft_enforce_playback_duration */ false);
|
|
||||||
if (!last_expiry_time_set_ || expiry_time != last_expiry_time_) {
|
|
||||||
last_expiry_time_ = expiry_time;
|
|
||||||
if (event_listener_)
|
if (event_listener_)
|
||||||
event_listener_->OnExpirationUpdate(session_id_, expiry_time);
|
event_listener_->OnExpirationUpdate(session_id_, expiry_time);
|
||||||
}
|
}
|
||||||
last_expiry_time_set_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t PolicyEngine::GetCurrentTime() {
|
int64_t PolicyEngine::GetCurrentTime() {
|
||||||
|
|||||||
97
libwvdrmengine/cdm/core/src/policy_timers.cpp
Normal file
97
libwvdrmengine/cdm/core/src/policy_timers.cpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// 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.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
using video_widevine::License;
|
||||||
|
|
||||||
|
namespace wvcdm {
|
||||||
|
|
||||||
|
void PolicyTimers::SetLicense(const video_widevine::License& license) {
|
||||||
|
policy_.Clear();
|
||||||
|
license_start_time_ = license.license_start_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyTimers::DecryptionEvent(int64_t current_time) {
|
||||||
|
last_playback_time_ = current_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimers::GetSecondsSinceStarted(int64_t current_time,
|
||||||
|
int64_t* seconds_since_started) {
|
||||||
|
if (seconds_since_started == nullptr) {
|
||||||
|
LOGE("|seconds_since_started| not provided");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playback_start_time_ == 0) return false;
|
||||||
|
|
||||||
|
*seconds_since_started = current_time - playback_start_time_;
|
||||||
|
return (*seconds_since_started >= 0) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimers::GetSecondsSinceLastPlayed(
|
||||||
|
int64_t current_time, int64_t* seconds_since_last_played) {
|
||||||
|
if (seconds_since_last_played == nullptr) {
|
||||||
|
LOGE("|seconds_since_last_played| not provided");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_playback_time_ == 0) return false;
|
||||||
|
|
||||||
|
*seconds_since_last_played = current_time - last_playback_time_;
|
||||||
|
return (*seconds_since_last_played >= 0) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimers::IsLicenseForFuture(int64_t current_time) {
|
||||||
|
return current_time < license_start_time_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimers::UpdateExpirationTime(int64_t current_time,
|
||||||
|
int64_t* expiry_time) {
|
||||||
|
if (expiry_time == nullptr) {
|
||||||
|
LOGE("|expiry_time| mot provided");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*expiry_time =
|
||||||
|
GetExpiryTime(current_time,
|
||||||
|
/* ignore_soft_enforce_playback_duration */ false);
|
||||||
|
const bool has_expiry_time_been_updated =
|
||||||
|
!last_expiry_time_set_ || *expiry_time != last_expiry_time_;
|
||||||
|
|
||||||
|
if (has_expiry_time_been_updated) last_expiry_time_ = *expiry_time;
|
||||||
|
|
||||||
|
last_expiry_time_set_ = true;
|
||||||
|
return has_expiry_time_been_updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimers::HasRenewalDelayExpired(int64_t current_time) {
|
||||||
|
return policy_.can_renew() && (policy_.renewal_delay_seconds() > 0) &&
|
||||||
|
(license_start_time_ + policy_.renewal_delay_seconds() <=
|
||||||
|
current_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimers::HasRenewalRetryIntervalExpired(int64_t current_time) {
|
||||||
|
return policy_.can_renew() &&
|
||||||
|
(policy_.renewal_retry_interval_seconds() > 0) &&
|
||||||
|
(next_renewal_time_ <= current_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyTimers::UpdateRenewalRequest(int64_t current_time) {
|
||||||
|
next_renewal_time_ = current_time + policy_.renewal_retry_interval_seconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimers::HasRenewalRecoveryDurationExpired(int64_t current_time) {
|
||||||
|
return (policy_.renewal_recovery_duration_seconds() > 0) &&
|
||||||
|
(license_start_time_ + policy_.renewal_recovery_duration_seconds() <=
|
||||||
|
current_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace wvcdm
|
||||||
164
libwvdrmengine/cdm/core/src/policy_timers_v15.cpp
Normal file
164
libwvdrmengine/cdm/core/src/policy_timers_v15.cpp
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
// 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_v15.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "wv_cdm_constants.h"
|
||||||
|
|
||||||
|
using video_widevine::License;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const int64_t kTimeZero = 0;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace wvcdm {
|
||||||
|
|
||||||
|
bool PolicyTimersV15::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
|
||||||
|
license_start_time_ = license.license_start_time();
|
||||||
|
next_renewal_time_ = license_start_time_ + policy_.renewal_delay_seconds();
|
||||||
|
|
||||||
|
if (!policy_.can_play() || HasLicenseOrPlaybackDurationExpired(current_time))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyTimersV15::BeginDecryption(int64_t current_time) {
|
||||||
|
if (playback_start_time_ == 0) {
|
||||||
|
playback_start_time_ = current_time;
|
||||||
|
last_playback_time_ = current_time;
|
||||||
|
if (policy_.play_start_grace_period_seconds() == 0)
|
||||||
|
grace_period_end_time_ = current_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyTimersV15::RestorePlaybackTimes(int64_t current_time,
|
||||||
|
int64_t playback_start_time,
|
||||||
|
int64_t last_playback_time,
|
||||||
|
int64_t grace_period_end_time) {
|
||||||
|
playback_start_time_ = std::max(playback_start_time, kTimeZero);
|
||||||
|
last_playback_time_ = std::max(last_playback_time, kTimeZero);
|
||||||
|
grace_period_end_time_ = grace_period_end_time;
|
||||||
|
|
||||||
|
if (policy_.play_start_grace_period_seconds() != 0) {
|
||||||
|
// If we are using grace period, we may need to override some of the values
|
||||||
|
// given to us by OEMCrypto. |grace_period_end_time| will be 0 if the grace
|
||||||
|
// period has not expired (effectively playback has not begun). Otherwise,
|
||||||
|
// |grace_period_end_time| contains the playback start time we should use.
|
||||||
|
playback_start_time_ = grace_period_end_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 PolicyTimersV15::HasPlaybackStarted(int64_t current_time) {
|
||||||
|
if (playback_start_time_ == 0) return false;
|
||||||
|
|
||||||
|
const int64_t playback_time = current_time - playback_start_time_;
|
||||||
|
return playback_time >= policy_.play_start_grace_period_seconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimersV15::HasLicenseOrPlaybackDurationExpired(
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyTimersV15::HasPassedGracePeriod(int64_t current_time) {
|
||||||
|
if (grace_period_end_time_ == 0 && HasPlaybackStarted(current_time)) {
|
||||||
|
grace_period_end_time_ = playback_start_time_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t PolicyTimersV15::GetLicenseOrPlaybackDurationRemaining(
|
||||||
|
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 PolicyTimersV15::GetLicenseOrRentalDurationRemaining(
|
||||||
|
int64_t current_time) {
|
||||||
|
if (HasLicenseOrPlaybackDurationExpired(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)
|
||||||
|
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.
|
||||||
|
int64_t PolicyTimersV15::GetHardLicenseExpiryTime() {
|
||||||
|
return policy_.license_duration_seconds() > 0
|
||||||
|
? license_start_time_ + policy_.license_duration_seconds()
|
||||||
|
: NEVER_EXPIRES;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t PolicyTimersV15::GetRentalExpiryTime() {
|
||||||
|
const int64_t hard_limit = GetHardLicenseExpiryTime();
|
||||||
|
if (policy_.rental_duration_seconds() == 0) return hard_limit;
|
||||||
|
const int64_t expiry_time =
|
||||||
|
license_start_time_ + policy_.rental_duration_seconds();
|
||||||
|
if (hard_limit == NEVER_EXPIRES) return expiry_time;
|
||||||
|
return std::min(hard_limit, expiry_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t PolicyTimersV15::GetExpiryTime(
|
||||||
|
int64_t current_time, bool ignore_soft_enforce_playback_duration) {
|
||||||
|
if (!HasPlaybackStarted(current_time)) return GetRentalExpiryTime();
|
||||||
|
|
||||||
|
const int64_t hard_limit = GetHardLicenseExpiryTime();
|
||||||
|
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 =
|
||||||
|
playback_start_time_ + policy_.playback_duration_seconds();
|
||||||
|
|
||||||
|
if (hard_limit == NEVER_EXPIRES) return expiry_time;
|
||||||
|
return std::min(hard_limit, expiry_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace wvcdm
|
||||||
@@ -402,17 +402,19 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
|||||||
// Verify Content Identification
|
// Verify Content Identification
|
||||||
const LicenseRequest_ContentIdentification& content_id =
|
const LicenseRequest_ContentIdentification& content_id =
|
||||||
license_request.content_id();
|
license_request.content_id();
|
||||||
ASSERT_TRUE(content_id.has_cenc_id_deprecated());
|
ASSERT_TRUE(content_id.has_widevine_pssh_data());
|
||||||
EXPECT_FALSE(content_id.has_webm_id_deprecated());
|
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||||
EXPECT_FALSE(content_id.has_existing_license());
|
EXPECT_FALSE(content_id.has_existing_license());
|
||||||
|
|
||||||
const ::video_widevine::LicenseRequest_ContentIdentification_CencDeprecated&
|
const ::video_widevine::LicenseRequest_ContentIdentification_WidevinePsshData&
|
||||||
cenc_id = content_id.cenc_id_deprecated();
|
widevine_pssh_data = content_id.widevine_pssh_data();
|
||||||
EXPECT_TRUE(std::equal(cenc_id.pssh(0).begin(), cenc_id.pssh(0).end(),
|
EXPECT_TRUE(std::equal(widevine_pssh_data.pssh_data(0).begin(),
|
||||||
|
widevine_pssh_data.pssh_data(0).end(),
|
||||||
kCencPssh.begin()));
|
kCencPssh.begin()));
|
||||||
EXPECT_EQ(video_widevine::STREAMING, cenc_id.license_type());
|
EXPECT_EQ(video_widevine::STREAMING, widevine_pssh_data.license_type());
|
||||||
EXPECT_TRUE(std::equal(cenc_id.request_id().begin(),
|
EXPECT_TRUE(std::equal(widevine_pssh_data.request_id().begin(),
|
||||||
cenc_id.request_id().end(), kCryptoRequestId.begin()));
|
widevine_pssh_data.request_id().end(),
|
||||||
|
kCryptoRequestId.begin()));
|
||||||
|
|
||||||
// Verify other license request fields
|
// Verify other license request fields
|
||||||
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
||||||
@@ -527,17 +529,19 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
|||||||
// Verify Content Identification
|
// Verify Content Identification
|
||||||
const LicenseRequest_ContentIdentification& content_id =
|
const LicenseRequest_ContentIdentification& content_id =
|
||||||
license_request.content_id();
|
license_request.content_id();
|
||||||
ASSERT_TRUE(content_id.has_cenc_id_deprecated());
|
ASSERT_TRUE(content_id.has_widevine_pssh_data());
|
||||||
EXPECT_FALSE(content_id.has_webm_id_deprecated());
|
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||||
EXPECT_FALSE(content_id.has_existing_license());
|
EXPECT_FALSE(content_id.has_existing_license());
|
||||||
|
|
||||||
const ::video_widevine::LicenseRequest_ContentIdentification_CencDeprecated&
|
const ::video_widevine::LicenseRequest_ContentIdentification_WidevinePsshData&
|
||||||
cenc_id = content_id.cenc_id_deprecated();
|
widevine_pssh_data = content_id.widevine_pssh_data();
|
||||||
EXPECT_TRUE(std::equal(cenc_id.pssh(0).begin(), cenc_id.pssh(0).end(),
|
EXPECT_TRUE(std::equal(widevine_pssh_data.pssh_data(0).begin(),
|
||||||
|
widevine_pssh_data.pssh_data(0).end(),
|
||||||
kCencPssh.begin()));
|
kCencPssh.begin()));
|
||||||
EXPECT_EQ(video_widevine::STREAMING, cenc_id.license_type());
|
EXPECT_EQ(video_widevine::STREAMING, widevine_pssh_data.license_type());
|
||||||
EXPECT_TRUE(std::equal(cenc_id.request_id().begin(),
|
EXPECT_TRUE(std::equal(widevine_pssh_data.request_id().begin(),
|
||||||
cenc_id.request_id().end(), kCryptoRequestId.begin()));
|
widevine_pssh_data.request_id().end(),
|
||||||
|
kCryptoRequestId.begin()));
|
||||||
|
|
||||||
// Verify other license request fields
|
// Verify other license request fields
|
||||||
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
||||||
|
|||||||
@@ -312,7 +312,8 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanPlayFalse) {
|
|||||||
|
|
||||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||||
.WillOnce(Return(kLicenseStartTime + 1))
|
.WillOnce(Return(kLicenseStartTime + 1))
|
||||||
.WillOnce(Return(kLicenseStartTime + 5));
|
.WillOnce(Return(kLicenseStartTime + 5))
|
||||||
|
.WillOnce(Return(kLicenseStartTime + 7));
|
||||||
|
|
||||||
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
||||||
|
|
||||||
@@ -2170,6 +2171,7 @@ TEST_F(PolicyEngineQueryTest, QuerySuccess_CanPlayFalse) {
|
|||||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||||
.WillOnce(Return(kLicenseStartTime + 1))
|
.WillOnce(Return(kLicenseStartTime + 1))
|
||||||
.WillOnce(Return(kLicenseStartTime + 5))
|
.WillOnce(Return(kLicenseStartTime + 5))
|
||||||
|
.WillOnce(Return(kLicenseStartTime + 7))
|
||||||
.WillOnce(Return(kLicenseStartTime + 100));
|
.WillOnce(Return(kLicenseStartTime + 100));
|
||||||
|
|
||||||
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
|
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ namespace wvcdm {
|
|||||||
using video_widevine::ClientIdentification;
|
using video_widevine::ClientIdentification;
|
||||||
using video_widevine::LicenseIdentification;
|
using video_widevine::LicenseIdentification;
|
||||||
using video_widevine::LicenseRequest_ContentIdentification;
|
using video_widevine::LicenseRequest_ContentIdentification;
|
||||||
using video_widevine::LicenseRequest_ContentIdentification_CencDeprecated;
|
using video_widevine::LicenseRequest_ContentIdentification_WidevinePsshData;
|
||||||
using video_widevine::SignedMessage;
|
using video_widevine::SignedMessage;
|
||||||
|
|
||||||
class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||||
@@ -505,8 +505,8 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
|
|||||||
// Verify Content Identification
|
// Verify Content Identification
|
||||||
const LicenseRequest_ContentIdentification& content_id =
|
const LicenseRequest_ContentIdentification& content_id =
|
||||||
license_renewal.content_id();
|
license_renewal.content_id();
|
||||||
EXPECT_FALSE(content_id.has_cenc_id_deprecated());
|
EXPECT_FALSE(content_id.has_widevine_pssh_data());
|
||||||
EXPECT_FALSE(content_id.has_webm_id_deprecated());
|
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||||
EXPECT_TRUE(content_id.has_existing_license());
|
EXPECT_TRUE(content_id.has_existing_license());
|
||||||
|
|
||||||
const LicenseRequest_ContentIdentification::ExistingLicense&
|
const LicenseRequest_ContentIdentification::ExistingLicense&
|
||||||
@@ -551,8 +551,8 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
|
|||||||
// Verify Content Identification
|
// Verify Content Identification
|
||||||
const LicenseRequest_ContentIdentification& content_id =
|
const LicenseRequest_ContentIdentification& content_id =
|
||||||
license_renewal.content_id();
|
license_renewal.content_id();
|
||||||
EXPECT_FALSE(content_id.has_cenc_id_deprecated());
|
EXPECT_FALSE(content_id.has_widevine_pssh_data());
|
||||||
EXPECT_FALSE(content_id.has_webm_id_deprecated());
|
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||||
EXPECT_TRUE(content_id.has_existing_license());
|
EXPECT_TRUE(content_id.has_existing_license());
|
||||||
|
|
||||||
const LicenseRequest_ContentIdentification::ExistingLicense&
|
const LicenseRequest_ContentIdentification::ExistingLicense&
|
||||||
@@ -790,16 +790,17 @@ TEST_F(WvCdmExtendedDurationTest, VerifyLicenseRequestTest) {
|
|||||||
// Verify Content Identification
|
// Verify Content Identification
|
||||||
const LicenseRequest_ContentIdentification& content_id =
|
const LicenseRequest_ContentIdentification& content_id =
|
||||||
license_request.content_id();
|
license_request.content_id();
|
||||||
EXPECT_TRUE(content_id.has_cenc_id_deprecated());
|
EXPECT_TRUE(content_id.has_widevine_pssh_data());
|
||||||
EXPECT_FALSE(content_id.has_webm_id_deprecated());
|
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||||
EXPECT_FALSE(content_id.has_existing_license());
|
EXPECT_FALSE(content_id.has_existing_license());
|
||||||
|
|
||||||
const LicenseRequest_ContentIdentification_CencDeprecated& cenc_id =
|
const LicenseRequest_ContentIdentification_WidevinePsshData& pssh_data =
|
||||||
content_id.cenc_id_deprecated();
|
content_id.widevine_pssh_data();
|
||||||
EXPECT_TRUE(std::equal(cenc_id.pssh(0).begin(), cenc_id.pssh(0).end(),
|
EXPECT_TRUE(std::equal(pssh_data.pssh_data(0).begin(),
|
||||||
|
pssh_data.pssh_data(0).end(),
|
||||||
binary_key_id().begin() + 32));
|
binary_key_id().begin() + 32));
|
||||||
EXPECT_EQ(video_widevine::STREAMING, cenc_id.license_type());
|
EXPECT_EQ(video_widevine::STREAMING, pssh_data.license_type());
|
||||||
EXPECT_TRUE(cenc_id.has_request_id());
|
EXPECT_TRUE(pssh_data.has_request_id());
|
||||||
|
|
||||||
// Verify other license request fields
|
// Verify other license request fields
|
||||||
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
||||||
@@ -859,8 +860,8 @@ TEST_F(WvCdmExtendedDurationTest, VerifyLicenseRenewalTest) {
|
|||||||
// Verify Content Identification
|
// Verify Content Identification
|
||||||
const LicenseRequest_ContentIdentification& content_id =
|
const LicenseRequest_ContentIdentification& content_id =
|
||||||
license_renewal.content_id();
|
license_renewal.content_id();
|
||||||
EXPECT_FALSE(content_id.has_cenc_id_deprecated());
|
EXPECT_FALSE(content_id.has_widevine_pssh_data());
|
||||||
EXPECT_FALSE(content_id.has_webm_id_deprecated());
|
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||||
EXPECT_TRUE(content_id.has_existing_license());
|
EXPECT_TRUE(content_id.has_existing_license());
|
||||||
|
|
||||||
const LicenseRequest_ContentIdentification::ExistingLicense&
|
const LicenseRequest_ContentIdentification::ExistingLicense&
|
||||||
|
|||||||
@@ -2766,8 +2766,8 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeySessionUsageDisabledTest) {
|
|||||||
// Verify Content Identification
|
// Verify Content Identification
|
||||||
const LicenseRequest_ContentIdentification& content_id =
|
const LicenseRequest_ContentIdentification& content_id =
|
||||||
license_renewal.content_id();
|
license_renewal.content_id();
|
||||||
EXPECT_FALSE(content_id.has_cenc_id_deprecated());
|
EXPECT_FALSE(content_id.has_widevine_pssh_data());
|
||||||
EXPECT_FALSE(content_id.has_webm_id_deprecated());
|
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||||
EXPECT_TRUE(content_id.has_existing_license());
|
EXPECT_TRUE(content_id.has_existing_license());
|
||||||
|
|
||||||
const LicenseRequest_ContentIdentification::ExistingLicense&
|
const LicenseRequest_ContentIdentification::ExistingLicense&
|
||||||
|
|||||||
Reference in New Issue
Block a user