Enable usage reporting
[ Merge from Widevine CDM repo of https://widevine-internal-review.googlesource.com/#/c/10171/ and https://widevine-internal-review.googlesource.com/#/c/10172/ ] Updated license_protocol.proto from constituent protos in google3 These changes make use of OEMCrypto v9 changes to support usage reporting. Usage reporting may be enabled for streaming (by means of secure stops) and offline playback by a provider session token specified in the license. Changes include periodically updating usage information for relevant sessions and reporting and releasing usage information as needed. The CDM has removed all references to Secure Stops. This change updates the Android API implementation to comply. b/11987015 Change-Id: Ibb6f2ced4ef20ee349ca1ae6412ce686b2b5d085
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "crypto_key.h"
|
||||
#include "crypto_session.h"
|
||||
#include "device_files.h"
|
||||
#include "log.h"
|
||||
#include "policy_engine.h"
|
||||
#include "properties.h"
|
||||
@@ -81,15 +82,16 @@ using video_widevine_server::sdk::ClientIdentification;
|
||||
using video_widevine_server::sdk::ClientIdentification_NameValue;
|
||||
using video_widevine_server::sdk::DeviceCertificate;
|
||||
using video_widevine_server::sdk::EncryptedClientIdentification;
|
||||
using video_widevine_server::sdk::License;
|
||||
using video_widevine_server::sdk::License_KeyContainer;
|
||||
using video_widevine_server::sdk::LicenseError;
|
||||
using video_widevine_server::sdk::LicenseIdentification;
|
||||
using video_widevine_server::sdk::LicenseRequest;
|
||||
using video_widevine_server::sdk::LicenseRequest_ContentIdentification;
|
||||
using video_widevine_server::sdk::LicenseRequest_ContentIdentification_CENC;
|
||||
using video_widevine_server::sdk::LicenseRequest_ContentIdentification_WebM;
|
||||
using video_widevine_server::sdk::
|
||||
LicenseRequest_ContentIdentification_ExistingLicense;
|
||||
using video_widevine_server::sdk::License;
|
||||
using video_widevine_server::sdk::License_KeyContainer;
|
||||
using video_widevine_server::sdk::LicenseError;
|
||||
using video_widevine_server::sdk::SignedDeviceCertificate;
|
||||
using video_widevine_server::sdk::SignedMessage;
|
||||
|
||||
@@ -424,7 +426,19 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
|
||||
LicenseRequest_ContentIdentification_ExistingLicense* current_license =
|
||||
license_request.mutable_content_id()->mutable_license();
|
||||
current_license->mutable_license_id()->CopyFrom(policy_engine_->license_id());
|
||||
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 (!session_->GenerateUsageReport(license_id.provider_session_token(),
|
||||
&usage_report)) {
|
||||
return false;
|
||||
}
|
||||
current_license->set_session_usage_table_entry(usage_report);
|
||||
}
|
||||
}
|
||||
|
||||
// Get/set the nonce. This value will be reflected in the Key Control Block
|
||||
// of the license response.
|
||||
@@ -488,7 +502,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
break;
|
||||
case SignedMessage::SERVICE_CERTIFICATE:
|
||||
return CdmLicense::HandleServiceCertificateResponse(signed_response);
|
||||
case SignedMessage::ERROR:
|
||||
case SignedMessage::ERROR_RESPONSE:
|
||||
return HandleKeyErrorResponse(signed_response);
|
||||
default:
|
||||
LOGE("CdmLicense::HandleKeyResponse: unrecognized signed message type: %d"
|
||||
@@ -546,6 +560,10 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
std::string provider_session_token;
|
||||
if (license.id().has_provider_session_token())
|
||||
provider_session_token_ = license.id().provider_session_token();
|
||||
|
||||
if (license.policy().has_renewal_server_url()) {
|
||||
server_url_ = license.policy().renewal_server_url();
|
||||
}
|
||||
@@ -559,8 +577,8 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
signed_response.signature(),
|
||||
mac_key_iv,
|
||||
mac_key,
|
||||
key_array.size(),
|
||||
&key_array[0]);
|
||||
key_array,
|
||||
provider_session_token);
|
||||
|
||||
if (KEY_ADDED == resp) {
|
||||
loaded_keys_.clear();
|
||||
@@ -590,7 +608,7 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
if (signed_response.type() == SignedMessage::ERROR) {
|
||||
if (signed_response.type() == SignedMessage::ERROR_RESPONSE) {
|
||||
return HandleKeyErrorResponse(signed_response);
|
||||
}
|
||||
|
||||
@@ -618,6 +636,14 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
server_url_ = license.policy().renewal_server_url();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (license.id().has_provider_session_token()) {
|
||||
provider_session_token_ = license.id().provider_session_token();
|
||||
session_->ReleaseUsageInformation(signed_response.msg(),
|
||||
signed_response.signature(),
|
||||
provider_session_token_);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(kqyang, jfore, gmorgan): change UpdateLicense function signature to
|
||||
// be able to return true/false to accept/reject the license. (Pending code
|
||||
@@ -637,8 +663,9 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
}
|
||||
|
||||
bool CdmLicense::RestoreOfflineLicense(
|
||||
CdmKeyMessage& license_request, CdmKeyResponse& license_response,
|
||||
CdmKeyResponse& license_renewal_response) {
|
||||
const CdmKeyMessage& license_request,
|
||||
const CdmKeyResponse& license_response,
|
||||
const CdmKeyResponse& license_renewal_response) {
|
||||
|
||||
if (license_request.empty() || license_response.empty()) {
|
||||
LOGE(
|
||||
@@ -681,6 +708,77 @@ bool CdmLicense::RestoreOfflineLicense(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CdmLicense::RestoreUsageLicense(const CdmKeyMessage& license_request,
|
||||
const CdmKeyResponse& license_response) {
|
||||
|
||||
if (license_request.empty() || license_response.empty()) {
|
||||
LOGE(
|
||||
"CdmLicense::RestoreUsageLicense: key_request or response empty: %u %u",
|
||||
license_request.size(), license_response.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
SignedMessage signed_request;
|
||||
if (!signed_request.ParseFromString(license_request)) {
|
||||
LOGE("CdmLicense::RestoreUsageLicense: license_request parse failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (signed_request.type() != SignedMessage::LICENSE_REQUEST) {
|
||||
LOGE(
|
||||
"CdmLicense::RestoreUsageLicense: license request type: expected = %d,"
|
||||
" actual = %d",
|
||||
SignedMessage::LICENSE_REQUEST, signed_request.type());
|
||||
return false;
|
||||
}
|
||||
|
||||
key_request_ = signed_request.msg();
|
||||
|
||||
SignedMessage signed_response;
|
||||
if (!signed_response.ParseFromString(license_response)) {
|
||||
LOGE("CdmLicense::RestoreUsageLicense: unable to parse signed license"
|
||||
" response");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SignedMessage::LICENSE != signed_response.type()) {
|
||||
LOGE("CdmLicense::RestoreUsageLicense: unrecognized signed message type: %d"
|
||||
, signed_response.type());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Properties::use_certificates_as_identification()) {
|
||||
if (!signed_response.has_session_key()) {
|
||||
LOGE("CdmLicense::RestoreUsageLicense: no session keys present");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!session_->GenerateDerivedKeys(key_request_,
|
||||
signed_response.session_key()))
|
||||
return false;
|
||||
} else {
|
||||
if (!session_->GenerateDerivedKeys(key_request_)) return false;
|
||||
}
|
||||
|
||||
if (!signed_response.has_signature()) {
|
||||
LOGE("CdmLicense::RestoreUsageLicense: license response is not signed");
|
||||
return false;
|
||||
}
|
||||
|
||||
License license;
|
||||
if (!license.ParseFromString(signed_response.msg())) {
|
||||
LOGE("CdmLicense::RestoreUsageLicense: unable to parse license response");
|
||||
return false;
|
||||
}
|
||||
|
||||
policy_engine_->SetLicense(license);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CdmLicense::IsKeyLoaded(const KeyId& key_id) {
|
||||
return loaded_keys_.find(key_id) != loaded_keys_.end();
|
||||
}
|
||||
|
||||
bool CdmLicense::PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
|
||||
std::string* server_url) {
|
||||
if (!initialized_) {
|
||||
@@ -804,8 +902,4 @@ bool CdmLicense::PrepareContentId(const CdmLicenseType license_type,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CdmLicense::IsKeyLoaded(const KeyId& key_id) {
|
||||
return loaded_keys_.find(key_id) != loaded_keys_.end();
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user