Source release 16.4.0
This commit is contained in:
@@ -47,7 +47,7 @@
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'includes': ['../third_party/protoc.gypi'],
|
||||
'sources': ['../metrics/src/metrics.proto',],
|
||||
'sources': ['../metrics/src/wv_metrics.proto',],
|
||||
'variables': {
|
||||
'proto_in_dir': '../metrics/src',
|
||||
},
|
||||
|
||||
@@ -24,11 +24,13 @@
|
||||
'../core/test/parallel_operations_test.cpp',
|
||||
'../core/test/policy_engine_constraints_unittest.cpp',
|
||||
'../core/test/policy_engine_unittest.cpp',
|
||||
'../core/test/policy_integration_test.cpp',
|
||||
'../core/test/rw_lock_test.cpp',
|
||||
'../core/test/service_certificate_unittest.cpp',
|
||||
'../core/test/test_base.cpp',
|
||||
'../core/test/test_printers.cpp',
|
||||
'../core/test/url_request.cpp',
|
||||
'../core/test/url_request_unittest.cpp',
|
||||
'../core/test/usage_table_header_unittest.cpp',
|
||||
'../metrics/test/counter_metric_unittest.cpp',
|
||||
'../metrics/test/distribution_unittest.cpp',
|
||||
|
||||
@@ -42,25 +42,25 @@ class CDM_EXPORT ITimerClient {
|
||||
class CDM_EXPORT Cdm : public ITimerClient {
|
||||
public:
|
||||
// Session types defined by EME.
|
||||
typedef enum {
|
||||
enum SessionType : int32_t {
|
||||
kTemporary = 0,
|
||||
kPersistentLicense = 1,
|
||||
kPersistent = kPersistentLicense, // deprecated name from June 1 draft
|
||||
kPersistentUsageRecord = 2,
|
||||
} SessionType;
|
||||
};
|
||||
|
||||
// Message types defined by EME.
|
||||
typedef enum {
|
||||
enum MessageType : int32_t {
|
||||
kLicenseRequest = 0,
|
||||
kLicenseRenewal = 1,
|
||||
kLicenseRelease = 2,
|
||||
kIndividualizationRequest = 3, // Not used. Direct Individualization
|
||||
// is used instead of App-Assisted
|
||||
} MessageType;
|
||||
};
|
||||
|
||||
// Status codes returned by CDM functions.
|
||||
//
|
||||
typedef enum {
|
||||
enum Status : int32_t {
|
||||
kSuccess = 0,
|
||||
|
||||
// These are analogous to the exceptions defined in the EME specification.
|
||||
@@ -94,27 +94,27 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
|
||||
// This covers errors that we do not expect (see logs for details):
|
||||
kUnexpectedError = 99999,
|
||||
} Status;
|
||||
};
|
||||
|
||||
// These are the init data types defined by EME.
|
||||
typedef enum {
|
||||
enum InitDataType : int32_t {
|
||||
kCenc = 0,
|
||||
kKeyIds = 1, // NOTE: not supported by Widevine at this time
|
||||
kWebM = 2,
|
||||
|
||||
// This type is not defined by EME but is supported by Widevine
|
||||
kHls = 10000,
|
||||
} InitDataType;
|
||||
};
|
||||
|
||||
// These are the crypto schemes supported by CENC 3.0.
|
||||
typedef enum {
|
||||
enum EncryptionScheme : int32_t {
|
||||
kClear = 0,
|
||||
kAesCtr = 1, // AES-CTR, for use with the "cenc" schema
|
||||
kAesCbc = 2, // AES-CBC, for use with the "cbcs" schema
|
||||
} EncryptionScheme;
|
||||
};
|
||||
|
||||
// These are key statuses defined by EME.
|
||||
typedef enum {
|
||||
enum KeyStatus : int32_t {
|
||||
kUsable = 0,
|
||||
kExpired = 1,
|
||||
kOutputRestricted = 2,
|
||||
@@ -122,18 +122,18 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
kStatusPending = 3,
|
||||
kInternalError = 4,
|
||||
kReleased = 5,
|
||||
} KeyStatus;
|
||||
};
|
||||
|
||||
// These are the possible HDCP levels supported by Widevine.
|
||||
// For ease of comparison, these values are kept in ascending order by version
|
||||
// number.
|
||||
typedef enum {
|
||||
enum HdcpVersion : int32_t {
|
||||
kHdcp1_x = 0,
|
||||
kHdcp2_0 = 1,
|
||||
kHdcp2_1 = 2,
|
||||
kHdcp2_2 = 3,
|
||||
kHdcp2_3 = 4,
|
||||
} HdcpVersion;
|
||||
};
|
||||
|
||||
// Permissible usages for a key. Returned as a set of flags; multiple
|
||||
// flags may be set. The specific settings are defined in the license
|
||||
@@ -150,7 +150,7 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
|
||||
// These are defined by Widevine. The CDM can be configured to decrypt in
|
||||
// three modes (dependent on OEMCrypto support).
|
||||
typedef enum {
|
||||
enum SecureOutputType : int32_t {
|
||||
// Data is decrypted to an opaque handle.
|
||||
// Translates to OEMCrypto's OEMCrypto_BufferType_Secure.
|
||||
kOpaqueHandle = 0,
|
||||
@@ -164,35 +164,35 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// clear buffer in main memory.
|
||||
// Translates to OEMCrypto's OEMCrypto_BufferType_Clear.
|
||||
kNoSecureOutput = 2,
|
||||
} SecureOutputType;
|
||||
};
|
||||
|
||||
// Logging levels defined by Widevine.
|
||||
// See Cdm::initialize().
|
||||
typedef enum {
|
||||
enum LogLevel : int32_t {
|
||||
kSilent = -1,
|
||||
kErrors = 0,
|
||||
kWarnings = 1,
|
||||
kInfo = 2,
|
||||
kDebug = 3,
|
||||
kVerbose = 4,
|
||||
} LogLevel;
|
||||
};
|
||||
|
||||
// Types of service defined by Widevine.
|
||||
// The service certificate installation methods - Cdm::setServiceCertificate()
|
||||
// and Cdm::parseAndLoadServiceCertificateResponse() - use these to identify
|
||||
// which service the certificate is intended for.
|
||||
typedef enum {
|
||||
enum ServiceRole : int32_t {
|
||||
kAllServices = 0,
|
||||
kProvisioningService = 1,
|
||||
kLicensingService = 2,
|
||||
} ServiceRole;
|
||||
};
|
||||
|
||||
// These are the available Widevine robustness levels.
|
||||
typedef enum {
|
||||
enum RobustnessLevel : int32_t {
|
||||
kL1 = 1,
|
||||
kL2 = 2,
|
||||
kL3 = 3,
|
||||
} RobustnessLevel;
|
||||
};
|
||||
|
||||
// A map of key statuses.
|
||||
// See Cdm::getKeyStatuses().
|
||||
@@ -788,15 +788,15 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// Generic crypto - functions for applying crypto operations to
|
||||
// app-level data (outside the content stream).
|
||||
|
||||
typedef enum {
|
||||
enum GenericEncryptionAlgorithmType : int32_t {
|
||||
kEncryptionAlgorithmUnknown,
|
||||
kEncryptionAlgorithmAesCbc128,
|
||||
} GenericEncryptionAlgorithmType;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
enum GenericSigningAlgorithmType : int32_t {
|
||||
kSigningAlgorithmUnknown,
|
||||
kSigningAlgorithmHmacSha256
|
||||
} GenericSigningAlgorithmType;
|
||||
};
|
||||
|
||||
// Encrypts a buffer of app-level data.
|
||||
virtual Status genericEncrypt(const std::string& session_id,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Widevine CE CDM Version
|
||||
#ifndef CDM_VERSION
|
||||
# define CDM_VERSION "16.3.0"
|
||||
# define CDM_VERSION "16.4.0"
|
||||
#endif
|
||||
#define EME_VERSION "https://www.w3.org/TR/2017/REC-encrypted-media-20170918"
|
||||
|
||||
145
cdm/src/cdm.cpp
145
cdm/src/cdm.cpp
@@ -22,13 +22,13 @@
|
||||
#include "file_store.h"
|
||||
#include "license.h"
|
||||
#include "log.h"
|
||||
#include "metrics.pb.h"
|
||||
#include "properties.h"
|
||||
#include "service_certificate.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_event_listener.h"
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_metrics.pb.h"
|
||||
|
||||
// CE:
|
||||
#include "cdm_version.h"
|
||||
@@ -367,7 +367,8 @@ Cdm::Status CdmImpl::setServiceCertificate(ServiceRole role,
|
||||
// Verify that the certificate is properly signed and well-formed.
|
||||
CdmResponseType status = cdm_engine_->ValidateServiceCertificate(certificate);
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Invalid service certificate! Error code = %d", status);
|
||||
LOGE("Invalid service certificate! Error code = %d",
|
||||
static_cast<int>(status));
|
||||
return kTypeError;
|
||||
}
|
||||
|
||||
@@ -421,13 +422,13 @@ Cdm::Status CdmImpl::getRobustnessLevel(RobustnessLevel* level) {
|
||||
}
|
||||
|
||||
std::string level_string;
|
||||
CdmResponseType result = cdm_engine_->QueryStatus(
|
||||
const CdmResponseType result = cdm_engine_->QueryStatus(
|
||||
kLevelDefault, QUERY_KEY_SECURITY_LEVEL, &level_string);
|
||||
if (result == SYSTEM_INVALIDATED_ERROR) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -452,19 +453,19 @@ Cdm::Status CdmImpl::getResourceRatingTier(uint32_t* tier) {
|
||||
}
|
||||
|
||||
std::string tier_string;
|
||||
CdmResponseType result = cdm_engine_->QueryStatus(
|
||||
const CdmResponseType result = cdm_engine_->QueryStatus(
|
||||
kLevelDefault, QUERY_KEY_RESOURCE_RATING_TIER, &tier_string);
|
||||
if (result == SYSTEM_INVALIDATED_ERROR) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
uint32_t parsed_tier = static_cast<uint32_t>(std::stoul(tier_string));
|
||||
const uint32_t parsed_tier = static_cast<uint32_t>(std::stoul(tier_string));
|
||||
if (parsed_tier <= 0) {
|
||||
LOGE("Invalid resource rating tier %lu", parsed_tier);
|
||||
LOGE("Invalid resource rating tier %u", parsed_tier);
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -484,7 +485,7 @@ Cdm::Status CdmImpl::getOemCryptoBuildInfo(std::string* build_info) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -508,7 +509,7 @@ Cdm::Status CdmImpl::getProvisioningRequest(std::string* request) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
return kSuccess;
|
||||
@@ -524,7 +525,7 @@ Cdm::Status CdmImpl::handleProvisioningResponse(const std::string& response) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -537,7 +538,7 @@ Cdm::Status CdmImpl::removeProvisioning() {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
return kSuccess;
|
||||
@@ -554,7 +555,7 @@ Cdm::Status CdmImpl::listStoredLicenses(std::vector<std::string>* key_set_ids) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
return kSuccess;
|
||||
@@ -571,7 +572,7 @@ Cdm::Status CdmImpl::listUsageRecords(std::vector<std::string>* ksids) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
return kSuccess;
|
||||
@@ -584,7 +585,7 @@ Cdm::Status CdmImpl::deleteUsageRecord(const std::string& key_set_id) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
return kSuccess;
|
||||
@@ -597,7 +598,7 @@ Cdm::Status CdmImpl::deleteAllUsageRecords() {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
return kSuccess;
|
||||
@@ -643,7 +644,7 @@ Cdm::Status CdmImpl::createSession(SessionType session_type,
|
||||
case kPersistentUsageRecord:
|
||||
break;
|
||||
default:
|
||||
LOGE("Unsupported session type: %d", session_type);
|
||||
LOGE("Unsupported session type: %d", static_cast<int>(session_type));
|
||||
return kNotSupported;
|
||||
}
|
||||
|
||||
@@ -663,7 +664,7 @@ Cdm::Status CdmImpl::createSession(SessionType session_type,
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
default:
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
}
|
||||
@@ -681,7 +682,7 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
|
||||
return kInvalidState;
|
||||
}
|
||||
|
||||
SessionType session_type = sessions_[session_id].type;
|
||||
const SessionType session_type = sessions_[session_id].type;
|
||||
CdmLicenseType license_type;
|
||||
switch (session_type) {
|
||||
case kTemporary:
|
||||
@@ -694,7 +695,7 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
|
||||
license_type = kLicenseTypeStreaming;
|
||||
break;
|
||||
default:
|
||||
LOGE("Unexpected session type: %d", session_type);
|
||||
LOGE("Unexpected session type: %d", static_cast<int>(session_type));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -713,7 +714,7 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
|
||||
init_data_type_name = HLS_INIT_DATA_FORMAT;
|
||||
break;
|
||||
default:
|
||||
LOGE("Invalid init data type: %d", init_data_type);
|
||||
LOGE("Invalid init data type: %d", static_cast<int>(init_data_type));
|
||||
return kTypeError;
|
||||
}
|
||||
|
||||
@@ -739,7 +740,7 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
|
||||
|
||||
CdmKeyRequest key_request;
|
||||
|
||||
CdmResponseType result = cdm_engine_->GenerateKeyRequest(
|
||||
const CdmResponseType result = cdm_engine_->GenerateKeyRequest(
|
||||
session_id, session_id, init_data_obj, license_type, app_parameters_,
|
||||
&key_request);
|
||||
|
||||
@@ -760,14 +761,14 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
|
||||
LOGE("No licensing service certificate installed");
|
||||
return kNeedsServiceCertificate;
|
||||
} else if (result != KEY_MESSAGE) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
sessions_[session_id].callable = true;
|
||||
assert(key_request.type == kKeyRequestTypeInitial);
|
||||
|
||||
LOGI("A license request has been generated.");
|
||||
LOGI("A license request has been generated");
|
||||
listener_->onMessage(session_id, kLicenseRequest, key_request.message);
|
||||
return kSuccess;
|
||||
}
|
||||
@@ -794,7 +795,7 @@ Cdm::Status CdmImpl::load(const std::string& session_id) {
|
||||
case NEED_PROVISIONING:
|
||||
return kNeedsDeviceCertificate;
|
||||
default:
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -818,7 +819,7 @@ Cdm::Status CdmImpl::load(const std::string& session_id) {
|
||||
LOGE("Unable to load license: %s", session_id.c_str());
|
||||
return kSessionNotFound;
|
||||
} else {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
}
|
||||
@@ -836,7 +837,7 @@ Cdm::Status CdmImpl::load(const std::string& session_id) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != KEY_ADDED) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -871,8 +872,8 @@ Cdm::Status CdmImpl::update(const std::string& session_id,
|
||||
// NOTE: If the CdmSession object recognizes that this is not the first
|
||||
// AddKey(), it will internally delegate to RenewKey().
|
||||
CdmKeySetId key_set_id = session_id;
|
||||
CdmLicenseType license_type; // Required for AddKey. Unused otherwise.
|
||||
CdmResponseType result =
|
||||
CdmLicenseType license_type = {}; // Required for AddKey. Unused otherwise.
|
||||
const CdmResponseType result =
|
||||
cdm_engine_->AddKey(session_id, response, &license_type, &key_set_id);
|
||||
|
||||
// result should only be NEED_KEY after server certificate provisioning, which
|
||||
@@ -894,7 +895,7 @@ Cdm::Status CdmImpl::update(const std::string& session_id,
|
||||
LOGE("The device needs to reprovision.");
|
||||
return kNeedsDeviceCertificate;
|
||||
} else if (result != KEY_ADDED) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -921,7 +922,7 @@ Cdm::Status CdmImpl::loadEmbeddedKeys(const std::string& session_id,
|
||||
}
|
||||
|
||||
if (init_data_type != kCenc) {
|
||||
LOGE("Invalid init data type: %d", init_data_type);
|
||||
LOGE("Invalid init data type: %d", static_cast<int>(init_data_type));
|
||||
return kTypeError;
|
||||
}
|
||||
|
||||
@@ -942,7 +943,7 @@ Cdm::Status CdmImpl::loadEmbeddedKeys(const std::string& session_id,
|
||||
}
|
||||
|
||||
CdmKeyRequest key_request;
|
||||
CdmResponseType result = cdm_engine_->GenerateKeyRequest(
|
||||
const CdmResponseType result = cdm_engine_->GenerateKeyRequest(
|
||||
session_id, session_id, init_data_obj, kLicenseTypeEmbeddedKeyData,
|
||||
app_parameters_, &key_request);
|
||||
|
||||
@@ -956,7 +957,8 @@ Cdm::Status CdmImpl::loadEmbeddedKeys(const std::string& session_id,
|
||||
LOGE("Nonce quota exceeded");
|
||||
return kResourceContention;
|
||||
} else if (result != KEY_ADDED) {
|
||||
LOGE("Unexpected Failure: GenerateKeyRequest() returned %lu", result);
|
||||
LOGE("Unexpected Failure: GenerateKeyRequest() returned %d",
|
||||
static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
return kSuccess;
|
||||
@@ -1019,7 +1021,7 @@ Cdm::Status CdmImpl::getKeyAllowedUsages(const std::string& session_id,
|
||||
LOGE("Session invalidated");
|
||||
return kSessionStateLost;
|
||||
} else {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
}
|
||||
@@ -1036,7 +1038,7 @@ Cdm::Status CdmImpl::getKeyAllowedUsages(const std::string& key_id,
|
||||
}
|
||||
|
||||
CdmKeyAllowedUsage usage_for_key;
|
||||
CdmResponseType result =
|
||||
const CdmResponseType result =
|
||||
cdm_engine_->QueryKeyAllowedUsage(key_id, &usage_for_key);
|
||||
if (result != NO_ERROR) {
|
||||
if (result == KEY_NOT_FOUND_1 || result == KEY_NOT_FOUND_2) {
|
||||
@@ -1050,7 +1052,7 @@ Cdm::Status CdmImpl::getKeyAllowedUsages(const std::string& key_id,
|
||||
} else if (result == KEY_CONFLICT_1) {
|
||||
return kTypeError;
|
||||
} else {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
}
|
||||
@@ -1101,12 +1103,12 @@ Cdm::Status CdmImpl::close(const std::string& session_id) {
|
||||
return kSessionNotFound;
|
||||
}
|
||||
|
||||
CdmResponseType result = cdm_engine_->CloseSession(session_id);
|
||||
const CdmResponseType result = cdm_engine_->CloseSession(session_id);
|
||||
if (result == SYSTEM_INVALIDATED_ERROR) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
sessions_.erase(session_id);
|
||||
@@ -1140,7 +1142,7 @@ Cdm::Status CdmImpl::remove(const std::string& session_id) {
|
||||
it->second = kReleased;
|
||||
}
|
||||
|
||||
CdmResponseType result = cdm_engine_->GenerateKeyRequest(
|
||||
const CdmResponseType result = cdm_engine_->GenerateKeyRequest(
|
||||
session_id, session_id, empty_initialization_data, kLicenseTypeRelease,
|
||||
app_parameters_, &key_request);
|
||||
|
||||
@@ -1154,7 +1156,7 @@ Cdm::Status CdmImpl::remove(const std::string& session_id) {
|
||||
LOGE("Nonce quota exceeded");
|
||||
return kResourceContention;
|
||||
} else if (result != KEY_MESSAGE) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
cdm_engine_->CloseSession(session_id);
|
||||
return kUnexpectedError;
|
||||
}
|
||||
@@ -1181,7 +1183,7 @@ Cdm::Status CdmImpl::forceRemove(const std::string& session_id) {
|
||||
return kRangeError;
|
||||
}
|
||||
|
||||
CdmResponseType result = cdm_engine_->RemoveLicense(session_id);
|
||||
const CdmResponseType result = cdm_engine_->RemoveLicense(session_id);
|
||||
|
||||
if (result == SYSTEM_INVALIDATED_ERROR) {
|
||||
LOGE("System invalidated");
|
||||
@@ -1190,7 +1192,7 @@ Cdm::Status CdmImpl::forceRemove(const std::string& session_id) {
|
||||
LOGE("Session invalidated");
|
||||
return kSessionStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -1285,7 +1287,8 @@ Cdm::Status CdmImpl::decrypt(const std::string& session_id,
|
||||
return cdm_sample;
|
||||
});
|
||||
|
||||
CdmResponseType result = cdm_engine_->DecryptV16(session_id, parameters);
|
||||
const CdmResponseType result =
|
||||
cdm_engine_->DecryptV16(session_id, parameters);
|
||||
|
||||
if (result == NO_ERROR) {
|
||||
return kSuccess;
|
||||
@@ -1317,7 +1320,7 @@ Cdm::Status CdmImpl::decrypt(const std::string& session_id,
|
||||
return kKeyUsageBlockedByPolicy;
|
||||
}
|
||||
|
||||
LOGE("Decrypt error: %d", result);
|
||||
LOGE("Decrypt error: %d", static_cast<int>(result));
|
||||
return kDecryptError;
|
||||
}
|
||||
|
||||
@@ -1327,9 +1330,11 @@ Cdm::Status CdmImpl::genericEncrypt(const std::string& session_id,
|
||||
const std::string& iv,
|
||||
GenericEncryptionAlgorithmType algorithm,
|
||||
std::string* out_buffer) {
|
||||
CdmEncryptionAlgorithm cdm_algorithm = ConvertEncryptionAlgorithm(algorithm);
|
||||
const CdmEncryptionAlgorithm cdm_algorithm =
|
||||
ConvertEncryptionAlgorithm(algorithm);
|
||||
if (cdm_algorithm == wvcdm::kEncryptionAlgorithmUnknown) {
|
||||
LOGE("Unrecognized encryption algorithm: %d.", cdm_algorithm);
|
||||
LOGE("Unrecognized encryption algorithm: %d.",
|
||||
static_cast<int>(cdm_algorithm));
|
||||
return kNotSupported;
|
||||
}
|
||||
|
||||
@@ -1358,7 +1363,7 @@ Cdm::Status CdmImpl::genericEncrypt(const std::string& session_id,
|
||||
LOGE("Key Error: %s", session_id.c_str());
|
||||
return kNoKey;
|
||||
}
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -1368,13 +1373,15 @@ Cdm::Status CdmImpl::genericDecrypt(const std::string& session_id,
|
||||
const std::string& iv,
|
||||
GenericEncryptionAlgorithmType algorithm,
|
||||
std::string* out_buffer) {
|
||||
CdmEncryptionAlgorithm cdm_algorithm = ConvertEncryptionAlgorithm(algorithm);
|
||||
const CdmEncryptionAlgorithm cdm_algorithm =
|
||||
ConvertEncryptionAlgorithm(algorithm);
|
||||
if (cdm_algorithm == wvcdm::kEncryptionAlgorithmUnknown) {
|
||||
LOGE("Unrecognized encryption algorithm: %d.", cdm_algorithm);
|
||||
LOGE("Unrecognized encryption algorithm: %d.",
|
||||
static_cast<int>(cdm_algorithm));
|
||||
return kNotSupported;
|
||||
}
|
||||
|
||||
CdmResponseType result = cdm_engine_->GenericDecrypt(
|
||||
const CdmResponseType result = cdm_engine_->GenericDecrypt(
|
||||
session_id, in_buffer, key_id, iv, cdm_algorithm, out_buffer);
|
||||
if (result == NO_ERROR) {
|
||||
return kSuccess;
|
||||
@@ -1399,7 +1406,7 @@ Cdm::Status CdmImpl::genericDecrypt(const std::string& session_id,
|
||||
LOGE("Key Error: %s", session_id.c_str());
|
||||
return kNoKey;
|
||||
}
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -1408,14 +1415,14 @@ Cdm::Status CdmImpl::genericSign(const std::string& session_id,
|
||||
const std::string& key_id,
|
||||
GenericSigningAlgorithmType algorithm,
|
||||
std::string* signature) {
|
||||
CdmSigningAlgorithm cdm_algorithm = ConvertSigningAlgorithm(algorithm);
|
||||
const CdmSigningAlgorithm cdm_algorithm = ConvertSigningAlgorithm(algorithm);
|
||||
if (cdm_algorithm == wvcdm::kSigningAlgorithmUnknown) {
|
||||
LOGE("Unrecognized signing algorithm: %d.", cdm_algorithm);
|
||||
LOGE("Unrecognized signing algorithm: %d", static_cast<int>(cdm_algorithm));
|
||||
return kNotSupported;
|
||||
}
|
||||
|
||||
CdmResponseType result = cdm_engine_->GenericSign(session_id, message, key_id,
|
||||
cdm_algorithm, signature);
|
||||
const CdmResponseType result = cdm_engine_->GenericSign(
|
||||
session_id, message, key_id, cdm_algorithm, signature);
|
||||
if (result == NO_ERROR) {
|
||||
return kSuccess;
|
||||
}
|
||||
@@ -1435,7 +1442,7 @@ Cdm::Status CdmImpl::genericSign(const std::string& session_id,
|
||||
LOGE("Key Error: %s", session_id.c_str());
|
||||
return kNoKey;
|
||||
}
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
@@ -1444,13 +1451,13 @@ Cdm::Status CdmImpl::genericVerify(const std::string& session_id,
|
||||
const std::string& key_id,
|
||||
GenericSigningAlgorithmType algorithm,
|
||||
const std::string& signature) {
|
||||
CdmSigningAlgorithm cdm_algorithm = ConvertSigningAlgorithm(algorithm);
|
||||
const CdmSigningAlgorithm cdm_algorithm = ConvertSigningAlgorithm(algorithm);
|
||||
if (cdm_algorithm == wvcdm::kSigningAlgorithmUnknown) {
|
||||
LOGE("Unrecognized signing algorithm: %d.", cdm_algorithm);
|
||||
LOGE("Unrecognized signing algorithm: %d", static_cast<int>(cdm_algorithm));
|
||||
return kNotSupported;
|
||||
}
|
||||
|
||||
CdmResponseType result = cdm_engine_->GenericVerify(
|
||||
const CdmResponseType result = cdm_engine_->GenericVerify(
|
||||
session_id, message, key_id, cdm_algorithm, signature);
|
||||
if (result == NO_ERROR) {
|
||||
return kSuccess;
|
||||
@@ -1471,18 +1478,19 @@ Cdm::Status CdmImpl::genericVerify(const std::string& session_id,
|
||||
LOGE("Key Error: %s", session_id.c_str());
|
||||
return kNoKey;
|
||||
}
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
Cdm::Status CdmImpl::setVideoResolution(const std::string& session_id,
|
||||
uint32_t width, uint32_t height) {
|
||||
constexpr uint64_t kMaxUint32 = std::numeric_limits<uint32_t>::max();
|
||||
// Verify that width * height will fit into a 32-bit quantity.
|
||||
// This is done to be compatible with the video resolution in the
|
||||
// license policy settings.
|
||||
uint64_t pixels = width;
|
||||
pixels *= height;
|
||||
if (pixels >= (1ULL << 32)) return kRangeError;
|
||||
const uint64_t pixels =
|
||||
static_cast<uint64_t>(width) * static_cast<uint64_t>(height);
|
||||
if (pixels > kMaxUint32) return kRangeError;
|
||||
if (cdm_engine_->NotifyResolution(session_id, width, height)) {
|
||||
return kSuccess;
|
||||
} else {
|
||||
@@ -1516,7 +1524,7 @@ void CdmImpl::onTimerExpired(void* context) {
|
||||
|
||||
void CdmImpl::OnSessionRenewalNeeded(const CdmSessionId& session_id) {
|
||||
CdmKeyRequest key_request;
|
||||
CdmResponseType result =
|
||||
const CdmResponseType result =
|
||||
cdm_engine_->GenerateRenewalRequest(session_id, &key_request);
|
||||
if (result == LICENSE_RENEWAL_NONCE_GENERATION_ERROR) {
|
||||
// TODO(b/73606893): this error should be recoverable. Rather
|
||||
@@ -1526,7 +1534,7 @@ void CdmImpl::OnSessionRenewalNeeded(const CdmSessionId& session_id) {
|
||||
return;
|
||||
}
|
||||
if (result != KEY_MESSAGE) {
|
||||
LOGE("Unexpected error %d", result);
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1574,7 +1582,8 @@ void CdmImpl::OnSessionKeysChange(const CdmSessionId& session_id,
|
||||
// compiler will flag if someone fails to add a case for new enum members,
|
||||
// while still handling the possibility of an invalid value sneaking into
|
||||
// the map at runtime.
|
||||
LOGE("Invalid key status %d. Reporting internal error.", it->second);
|
||||
LOGE("Internal error: Invalid key status: %d",
|
||||
static_cast<int>(it->second));
|
||||
map[it->first] = kInternalError;
|
||||
}
|
||||
|
||||
@@ -1608,7 +1617,7 @@ CdmEncryptionAlgorithm CdmImpl::ConvertEncryptionAlgorithm(
|
||||
if (algorithm == Cdm::kEncryptionAlgorithmAesCbc128) {
|
||||
return wvcdm::kEncryptionAlgorithmAesCbc128;
|
||||
} else {
|
||||
LOGW("Unknown encryption algorithm: %d", algorithm);
|
||||
LOGW("Unknown encryption algorithm: %d", static_cast<int>(algorithm));
|
||||
return wvcdm::kEncryptionAlgorithmUnknown;
|
||||
}
|
||||
}
|
||||
@@ -1618,7 +1627,7 @@ CdmSigningAlgorithm CdmImpl::ConvertSigningAlgorithm(
|
||||
if (algorithm == Cdm::kSigningAlgorithmHmacSha256) {
|
||||
return wvcdm::kSigningAlgorithmHmacSha256;
|
||||
} else {
|
||||
LOGW("Unknown signing algorithm: %d", algorithm);
|
||||
LOGW("Unknown signing algorithm: %d", static_cast<int>(algorithm));
|
||||
return wvcdm::kSigningAlgorithmUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ const int kRenewalTestDelayMs = 3 * 60 * 1000;
|
||||
const int kExpirationTestDelayMs = 5 * 60 * 1000;
|
||||
const int kOfflineLicenseDurationMs = 604800 * 1000;
|
||||
|
||||
constexpr size_t kMaxFetchAttempts = 5;
|
||||
|
||||
const std::string kDeviceCertFileName = "cert.bin";
|
||||
|
||||
const Cdm::SessionType kBogusSessionType = static_cast<Cdm::SessionType>(-1);
|
||||
@@ -243,19 +245,26 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
|
||||
|
||||
bool Fetch(const std::string& url, const std::string& message,
|
||||
std::string* response, int* status_code) {
|
||||
UrlRequest url_request(url);
|
||||
EXPECT_TRUE(url_request.is_connected());
|
||||
if (!url_request.is_connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
url_request.PostRequest(message);
|
||||
std::string http_response;
|
||||
url_request.GetResponse(&http_response);
|
||||
for (size_t attempt = 1; attempt <= kMaxFetchAttempts; ++attempt) {
|
||||
UrlRequest url_request(url);
|
||||
if (!url_request.is_connected()) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
url_request.PostRequest(message);
|
||||
|
||||
if (!url_request.GetResponse(&http_response)) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Some license servers return 400 for invalid message, some
|
||||
// return 500; treat anything other than 200 as an invalid message.
|
||||
int http_status_code = url_request.GetStatusCode(http_response);
|
||||
int http_status_code = UrlRequest::GetStatusCode(http_response);
|
||||
if (status_code) {
|
||||
*status_code = http_status_code;
|
||||
}
|
||||
@@ -310,11 +319,20 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
|
||||
void FetchLicense(const std::string& license_server,
|
||||
const std::string& message, std::string* response) {
|
||||
int status_code;
|
||||
bool ok = Fetch(license_server, message, response, &status_code);
|
||||
const bool ok = Fetch(license_server, message, response, &status_code);
|
||||
ASSERT_TRUE(ok);
|
||||
if (ok)
|
||||
if (!ok) return;
|
||||
if (kHttpOk != status_code) {
|
||||
std::map<std::string, std::string> fields;
|
||||
if (UrlRequest::GetDebugHeaderFields(*response, &fields)) {
|
||||
LOGD("Unexpected status code: code = %d", status_code);
|
||||
for (auto field : fields) {
|
||||
LOGD("- %s: %s", field.first.c_str(), field.second.c_str());
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(kHttpOk, status_code) << "Error response: " << *response << "\n"
|
||||
<< "license_server: " << license_server;
|
||||
}
|
||||
}
|
||||
|
||||
void FetchLicenseFailure(const std::string& message,
|
||||
@@ -682,7 +700,7 @@ TEST_F(CdmTest, ServiceCertificateRequestResponseUat) {
|
||||
|
||||
std::string response;
|
||||
ASSERT_TRUE(FetchServiceCertificate(uat_config.license_server(), &response));
|
||||
LOGV("response size=%d", response.size());
|
||||
LOGV("Response size = %zu", response.size());
|
||||
#if 0 // enable to extract the service certificate in byte form
|
||||
size_t done = 0;
|
||||
while (done < response.size()) {
|
||||
@@ -705,7 +723,7 @@ TEST_F(CdmTest, ServiceCertificateRequestResponseStaging) {
|
||||
std::string response;
|
||||
ASSERT_TRUE(
|
||||
FetchServiceCertificate(staging_config.license_server(), &response));
|
||||
LOGV("response size=%d", response.size());
|
||||
LOGV("Response: size = %zu", response.size());
|
||||
#if 0 // enable to extract the service certificate in byte form
|
||||
size_t done = 0;
|
||||
while (done < response.size()) {
|
||||
@@ -789,21 +807,21 @@ TEST_F(CdmTest, OpenSessionWithoutServiceCertificate) {
|
||||
|
||||
TEST_F(CdmTest, GetRobustnessLevel) {
|
||||
Cdm::RobustnessLevel level;
|
||||
Cdm::Status status = cdm_->getRobustnessLevel(&level);
|
||||
const Cdm::Status status = cdm_->getRobustnessLevel(&level);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
LOGI("Got robustness level %d", level);
|
||||
LOGI("Got robustness level %d", static_cast<int>(level));
|
||||
}
|
||||
|
||||
TEST_F(CdmTest, GetResourceRatingTier) {
|
||||
uint32_t tier;
|
||||
Cdm::Status status = cdm_->getResourceRatingTier(&tier);
|
||||
const Cdm::Status status = cdm_->getResourceRatingTier(&tier);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
LOGI("Got resource rating tier %lu", tier);
|
||||
LOGI("Got resource rating tier %u", tier);
|
||||
}
|
||||
|
||||
TEST_F(CdmTest, GetOemCryptoBuildInfo) {
|
||||
std::string build_info;
|
||||
Cdm::Status status = cdm_->getOemCryptoBuildInfo(&build_info);
|
||||
const Cdm::Status status = cdm_->getOemCryptoBuildInfo(&build_info);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
LOGI("Got OEMCrypto build info: %s", build_info.c_str());
|
||||
}
|
||||
|
||||
@@ -40,22 +40,28 @@ void TestHost::Reset() {
|
||||
}
|
||||
|
||||
void TestHost::ElapseTime(int64_t milliseconds) {
|
||||
// Note that, during the time rollback tests, milliseconds will be negative,
|
||||
// so we cannot assume goal_time > now_.
|
||||
int64_t goal_time = now_ + milliseconds;
|
||||
while (now_ < goal_time) {
|
||||
if (timers_.empty()) {
|
||||
now_ = goal_time;
|
||||
|
||||
// Walk forward from now_ to goal_time, stepping at each timer along the way
|
||||
// to fire its callback.
|
||||
while (!timers_.empty() && now_ < goal_time) {
|
||||
Timer t = timers_.top();
|
||||
ASSERT_GE(t.expiry_time(), now_);
|
||||
if (t.expiry_time() <= goal_time) {
|
||||
timers_.pop();
|
||||
now_ = t.expiry_time();
|
||||
t.client()->onTimerExpired(t.context());
|
||||
} else {
|
||||
Timer t = timers_.top();
|
||||
ASSERT_GE(t.expiry_time(), now_);
|
||||
if (t.expiry_time() <= goal_time) {
|
||||
timers_.pop();
|
||||
now_ = t.expiry_time();
|
||||
t.client()->onTimerExpired(t.context());
|
||||
} else {
|
||||
now_ = goal_time;
|
||||
}
|
||||
// The next timer is further in the future than goal_time, so we are done
|
||||
// processing the timers.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No matter what happened with the timers, update now_ to the goal_time.
|
||||
now_ = goal_time;
|
||||
}
|
||||
|
||||
int TestHost::NumTimers() const { return timers_.size(); }
|
||||
|
||||
Reference in New Issue
Block a user