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:
Rahul Frias
2014-07-02 13:03:09 -07:00
parent 9b4da994ec
commit 7a933ee48e
18 changed files with 1308 additions and 692 deletions

View File

@@ -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(&current_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;
}