From ab91cf934e18abde284996079df4acadac2ca5a8 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Wed, 21 Dec 2022 17:28:59 -0800 Subject: [PATCH] Support renew on load [ Merge of http://go/wvgerrit/164477 ] Renew on load is supported when OEMCrypto is >= v18. A new class, policy_timer_v18 has been added to support this functionality. In addtition,offsets of renewal from first decrypt and license start are also included. Bug: 256038127 Test: GtsMediaTestCases Change-Id: Ib18af3096d1d8807af6a03fd2f84783123ab6b6d --- libwvdrmengine/cdm/Android.bp | 1 + .../cdm/core/include/policy_timers_v18.h | 56 ++++++++++++ .../cdm/core/src/policy_timers_v18.cpp | 87 +++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 libwvdrmengine/cdm/core/include/policy_timers_v18.h create mode 100644 libwvdrmengine/cdm/core/src/policy_timers_v18.cpp diff --git a/libwvdrmengine/cdm/Android.bp b/libwvdrmengine/cdm/Android.bp index ea10f2d7..c7f59985 100644 --- a/libwvdrmengine/cdm/Android.bp +++ b/libwvdrmengine/cdm/Android.bp @@ -60,6 +60,7 @@ cc_library_static { CORE_SRC_DIR + "/policy_engine.cpp", CORE_SRC_DIR + "/policy_timers.cpp", CORE_SRC_DIR + "/policy_timers_v16.cpp", + CORE_SRC_DIR + "/policy_timers_v18.cpp", CORE_SRC_DIR + "/privacy_crypto_boringssl.cpp", CORE_SRC_DIR + "/service_certificate.cpp", CORE_SRC_DIR + "/system_id_extractor.cpp", diff --git a/libwvdrmengine/cdm/core/include/policy_timers_v18.h b/libwvdrmengine/cdm/core/include/policy_timers_v18.h new file mode 100644 index 00000000..5eead2ac --- /dev/null +++ b/libwvdrmengine/cdm/core/include/policy_timers_v18.h @@ -0,0 +1,56 @@ +// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine License +// Agreement. + +#ifndef WVCDM_CORE_POLICY_TIMERS_V18_H_ +#define WVCDM_CORE_POLICY_TIMERS_V18_H_ + +#include "disallow_copy_and_assign.h" +#include "license_protocol.pb.h" +#include "policy_timers.h" +#include "wv_cdm_types.h" + +namespace wvcdm { + +// OEMCrypto v18 includes support for renewing licenses on load by using +// |initial_renewal_delay_base| and TimerDelayBase. +// +// Backward compatibility may be needed if +// * OEMCrypto has not been upgraded to v18 +// * Licenses were persisted before the device was upgraded to v18 + +class PolicyTimersV18 : public PolicyTimers { + public: + PolicyTimersV18() {} + + ~PolicyTimersV18() override {} + + // UpdateLicense is used in handling a license response, a renewal response, + // or when restoring or releasing a persistent license. + // In a renewal the response may only contain policy fields that have + // changed. In this case an exact copy is not what we want to happen. + // |renewal_start_time_| is set to the time mentioned in the renewal + // response. + // UpdateLicense will return false if |license_start_time| is not + // present or playback is not allowed due to policy or timer duration + // expiration. + 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; + + // Renewal related methods + bool HasRenewalDelayExpired(int64_t current_time) override; + + private: + // Indicates whether this is an initial license or a renewal + bool license_renewal_ = false; + bool renew_on_first_decrypt_ = false; + + CORE_DISALLOW_COPY_AND_ASSIGN(PolicyTimersV18); +}; + +} // namespace wvcdm + +#endif // WVCDM_CORE_POLICY_TIMERS_V18_H_ diff --git a/libwvdrmengine/cdm/core/src/policy_timers_v18.cpp b/libwvdrmengine/cdm/core/src/policy_timers_v18.cpp new file mode 100644 index 00000000..79b73c27 --- /dev/null +++ b/libwvdrmengine/cdm/core/src/policy_timers_v18.cpp @@ -0,0 +1,87 @@ +// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine License +// Agreement. + +#include "policy_timers_v18.h" + +#include + +#include "log.h" +#include "wv_cdm_constants.h" + +using video_widevine::License; + +namespace wvcdm { + +bool PolicyTimersV18::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 renewal information + if (license_renewal_) { + renewal_start_time_ = license.license_start_time(); + next_renewal_time_ = + license.license_start_time() + policy_.renewal_delay_seconds(); + } else { + // Initial license received, use |renewal_delay_base| in calcualtion + switch (license.policy().initial_renewal_delay_base()) { + case video_widevine:: + License_Policy_TimerDelayBase_TIMER_DELAY_BASE_UNSPECIFIED: + case video_widevine::License_Policy_TimerDelayBase_LICENSE_START: + renewal_start_time_ = license.license_start_time(); + break; + case video_widevine::License_Policy_TimerDelayBase_LICENSE_LOAD: + renewal_start_time_ = current_time; + break; + case video_widevine::License_Policy_TimerDelayBase_FIRST_DECRYPT: + break; + default: + LOGE("Unrecognized initial_renewal_delay_base value = %d", + license.policy().initial_renewal_delay_base()); + renewal_start_time_ = license.license_start_time(); + break; + } + + if (!renew_on_first_decrypt_) { + next_renewal_time_ = + renewal_start_time_ + policy_.renewal_delay_seconds(); + } + // Any subsequent calls to |UpdateLicense| will be license renewals + license_renewal_ = true; + } + + if (!policy_.can_play() || + HasLicenseOrRentalOrPlaybackDurationExpired(current_time)) + return false; + + return true; +} + +void PolicyTimersV18::BeginDecryption(int64_t current_time) { + if (playback_start_time_ != 0) return; + + playback_start_time_ = current_time; + last_playback_time_ = current_time; + + if (renew_on_first_decrypt_) { + renewal_start_time_ = current_time; + next_renewal_time_ = renewal_start_time_ + policy_.renewal_delay_seconds(); + renew_on_first_decrypt_ = false; + } +} + +bool PolicyTimersV18::HasRenewalDelayExpired(int64_t current_time) { + if (renew_on_first_decrypt_ && playback_start_time_ == 0) return false; + + return policy_.can_renew() && + (renewal_start_time_ + policy_.renewal_delay_seconds() <= + current_time); +} + +} // namespace wvcdm