Merge of usage reporting and license changes from WV CDM repo
* CdmSession unittest and license request time changes b/15914199 Merge of https://widevine-internal-review.googlesource.com/#/c/10597/ * Specify OEMCrypto API version in client capabilities b/15388863 Merge of https://widevine-internal-review.googlesource.com/#/c/10616/ * Report start and last play time in license request b/15995227 Merge of https://widevine-internal-review.googlesource.com/#/c/10617/ * Respect can_play flag b/15330338 Merge of https://widevine-internal-review.googlesource.com/#/c/10619/ * Restore offline session information b/16009274 Merge of https://widevine-internal-review.googlesource.com/#/c/10641/ Change-Id: I17fdc309efbc1d44385a86a368df11b1349b29c2
This commit is contained in:
@@ -2,8 +2,11 @@
|
||||
|
||||
#include "license.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "clock.h"
|
||||
#include "crypto_key.h"
|
||||
#include "crypto_session.h"
|
||||
#include "device_files.h"
|
||||
@@ -22,7 +25,6 @@ std::string kDeviceNameKey = "device_name";
|
||||
std::string kProductNameKey = "product_name";
|
||||
std::string kBuildInfoKey = "build_info";
|
||||
std::string kDeviceIdKey = "device_id";
|
||||
std::string kOemCryptoApiVersion = "oemcrypto_api_version";
|
||||
const unsigned char kServiceCertificateCAPublicKey[] = {
|
||||
0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81,
|
||||
0x00, 0xb4, 0xfe, 0x39, 0xc3, 0x65, 0x90, 0x03,
|
||||
@@ -80,6 +82,7 @@ namespace wvcdm {
|
||||
|
||||
// Protobuf generated classes.
|
||||
using video_widevine_server::sdk::ClientIdentification;
|
||||
using video_widevine_server::sdk::ClientIdentification_ClientCapabilities;
|
||||
using video_widevine_server::sdk::ClientIdentification_NameValue;
|
||||
using video_widevine_server::sdk::DeviceCertificate;
|
||||
using video_widevine_server::sdk::EncryptedClientIdentification;
|
||||
@@ -140,6 +143,24 @@ static std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
return key_array;
|
||||
}
|
||||
|
||||
CdmLicense::CdmLicense()
|
||||
: session_(NULL),
|
||||
initialized_(false),
|
||||
clock_(new Clock()) {
|
||||
}
|
||||
|
||||
CdmLicense::CdmLicense(Clock* clock)
|
||||
: session_(NULL),
|
||||
initialized_(false) {
|
||||
if (NULL == clock) {
|
||||
LOGE("CdmLicense::CdmLicense: clock parameter not provided");
|
||||
return;
|
||||
}
|
||||
clock_.reset(clock);
|
||||
}
|
||||
|
||||
CdmLicense::~CdmLicense() {}
|
||||
|
||||
bool CdmLicense::Init(const std::string& token, CryptoSession* session,
|
||||
PolicyEngine* policy_engine) {
|
||||
if (token.size() == 0) {
|
||||
@@ -206,7 +227,7 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
|
||||
}
|
||||
|
||||
std::string request_id;
|
||||
session_->GenerateRequestId(request_id);
|
||||
session_->GenerateRequestId(&request_id);
|
||||
|
||||
LicenseRequest license_request;
|
||||
ClientIdentification* client_id = license_request.mutable_client_id();
|
||||
@@ -260,11 +281,54 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
|
||||
client_info->set_name(kDeviceIdKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
|
||||
ClientIdentification_ClientCapabilities* client_capabilities =
|
||||
client_id->mutable_client_capabilities();
|
||||
bool supports_usage_information;
|
||||
if (session_->UsageInformationSupport(&supports_usage_information)) {
|
||||
client_capabilities->set_session_token(supports_usage_information);
|
||||
}
|
||||
|
||||
CryptoSession::OemCryptoHdcpVersion current_version, max_version;
|
||||
if (session_->GetHdcpCapabilities(¤t_version, &max_version)) {
|
||||
switch (max_version) {
|
||||
case CryptoSession::kOemCryptoHdcpNotSupported:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine_server::sdk::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE);
|
||||
break;
|
||||
case CryptoSession::kOemCryptoHdcpVersion1:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine_server::sdk::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1);
|
||||
break;
|
||||
case CryptoSession::kOemCryptoHdcpVersion2:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine_server::sdk::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2);
|
||||
break;
|
||||
case CryptoSession::kOemCryptoHdcpVersion2_1:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine_server::sdk::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1);
|
||||
break;
|
||||
case CryptoSession::kOemCryptoHdcpVersion2_2:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine_server::sdk::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2);
|
||||
break;
|
||||
case CryptoSession::kOemCryptoNoHdcpDeviceAttached:
|
||||
default:
|
||||
LOGW(
|
||||
"CdmLicense::PrepareKeyRequest: unexpected HDCP max capability "
|
||||
"version %d",
|
||||
max_version);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t version = 0;
|
||||
if (session_->GetApiVersion(&version)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kOemCryptoApiVersion);
|
||||
client_info->set_value(UintToString(version));
|
||||
client_capabilities->set_oem_crypto_api_version(version);
|
||||
}
|
||||
|
||||
if (privacy_mode_enabled) {
|
||||
@@ -359,12 +423,10 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
|
||||
return false;
|
||||
}
|
||||
|
||||
// The time field will be updated once the cdm wrapper
|
||||
// has been updated to pass us in the time.
|
||||
license_request.set_request_time(0);
|
||||
|
||||
license_request.set_type(LicenseRequest::NEW);
|
||||
|
||||
license_request.set_request_time(clock_->GetCurrentTime());
|
||||
|
||||
// Get/set the nonce. This value will be reflected in the Key Control Block
|
||||
// of the license response.
|
||||
uint32_t nonce;
|
||||
@@ -430,21 +492,47 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
else
|
||||
license_request.set_type(LicenseRequest::RELEASE);
|
||||
|
||||
license_request.set_request_time(clock_->GetCurrentTime());
|
||||
|
||||
LicenseRequest_ContentIdentification_ExistingLicense* current_license =
|
||||
license_request.mutable_content_id()->mutable_license();
|
||||
LicenseIdentification license_id = policy_engine_->license_id();
|
||||
current_license->mutable_license_id()->CopyFrom(license_id);
|
||||
|
||||
if (!is_renewal) {
|
||||
if (license_id.has_provider_session_token()) {
|
||||
std::string usage_report;
|
||||
if (NO_ERROR !=
|
||||
session_->GenerateUsageReport(license_id.provider_session_token(),
|
||||
&usage_report)) {
|
||||
int64_t seconds_since_started, seconds_since_last_played;
|
||||
CryptoSession::UsageDurationStatus usage_duration_status =
|
||||
CryptoSession::kUsageDurationsInvalid;
|
||||
if (!provider_session_token_.empty()) {
|
||||
if (!is_renewal) {
|
||||
CdmResponseType status =
|
||||
session_->DeactivateUsageInformation(provider_session_token_);
|
||||
if (NO_ERROR != status)
|
||||
return false;
|
||||
}
|
||||
current_license->set_session_usage_table_entry(usage_report);
|
||||
}
|
||||
|
||||
std::string usage_report;
|
||||
CdmResponseType status =
|
||||
session_->GenerateUsageReport(provider_session_token_,
|
||||
&usage_report, &usage_duration_status,
|
||||
&seconds_since_started,
|
||||
&seconds_since_last_played);
|
||||
if (!is_renewal) {
|
||||
if (NO_ERROR == status)
|
||||
current_license->set_session_usage_table_entry(usage_report);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (CryptoSession::kUsageDurationsValid != usage_duration_status) {
|
||||
if (policy_engine_->GetSecondsSinceStarted(&seconds_since_started) &&
|
||||
policy_engine_->GetSecondsSinceLastPlayed(&seconds_since_last_played))
|
||||
usage_duration_status = CryptoSession::kUsageDurationsValid;
|
||||
}
|
||||
|
||||
if (CryptoSession::kUsageDurationsValid == usage_duration_status) {
|
||||
current_license->set_seconds_since_started(seconds_since_started);
|
||||
current_license->set_seconds_since_last_played(seconds_since_last_played);
|
||||
}
|
||||
|
||||
// Get/set the nonce. This value will be reflected in the Key Control Block
|
||||
@@ -664,7 +752,9 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
bool CdmLicense::RestoreOfflineLicense(
|
||||
const CdmKeyMessage& license_request,
|
||||
const CdmKeyResponse& license_response,
|
||||
const CdmKeyResponse& license_renewal_response) {
|
||||
const CdmKeyResponse& license_renewal_response,
|
||||
int64_t playback_start_time,
|
||||
int64_t last_playback_time) {
|
||||
|
||||
if (license_request.empty() || license_response.empty()) {
|
||||
LOGE(
|
||||
@@ -704,6 +794,36 @@ bool CdmLicense::RestoreOfflineLicense(
|
||||
if (sts != KEY_ADDED) return false;
|
||||
}
|
||||
|
||||
if (!provider_session_token_.empty()) {
|
||||
std::string usage_report;
|
||||
CryptoSession::UsageDurationStatus usage_duration_status =
|
||||
CryptoSession::kUsageDurationsInvalid;
|
||||
int64_t seconds_since_started, seconds_since_last_played;
|
||||
sts = session_->GenerateUsageReport(
|
||||
provider_session_token_, &usage_report, &usage_duration_status,
|
||||
&seconds_since_started, &seconds_since_last_played);
|
||||
|
||||
if (NO_ERROR == sts) {
|
||||
switch (usage_duration_status) {
|
||||
case CryptoSession::kUsageDurationPlaybackNotBegun:
|
||||
playback_start_time = 0;
|
||||
last_playback_time = 0;
|
||||
break;
|
||||
case CryptoSession::kUsageDurationsValid: {
|
||||
int64_t current_time = clock_->GetCurrentTime();
|
||||
if (current_time - seconds_since_started > 0)
|
||||
playback_start_time = current_time - seconds_since_started;
|
||||
if (current_time - last_playback_time > 0)
|
||||
last_playback_time = current_time - seconds_since_last_played;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
policy_engine_->RestorePlaybackTimes(playback_start_time, last_playback_time);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user