Merge CE Device Changes

This is a merge of the following changes made for CE devices in the
widevine share repo:

http://go/wvgerrit/16211 Only load offline session if needed in GKR
http://go/wvgerrit/16245 Unreserve IDs in reservation test
http://go/wvgerrit/16242 Re-enable WebM tests
http://go/wvgerrit/16240 Un-reserve reserved license IDs
http://go/wvgerrit/16190 Add temporary session type
http://go/wvgerrit/16189 Enforce license type and can_persist for storage

Change-Id: I592416f66c0d1286844266c01cc9b4906c7b6b05
This commit is contained in:
Fred Gylys-Colwell
2015-12-07 14:12:46 -08:00
parent 6886b1fa12
commit e4513f4a59
12 changed files with 68 additions and 7 deletions

View File

@@ -104,6 +104,8 @@ class CdmSession {
virtual bool is_release() { return is_release_; }
virtual bool is_offline() { return is_offline_; }
virtual bool is_temporary() { return is_temporary_; }
virtual bool license_received() { return license_received_; }
// ReleaseCrypto() - Closes the underlying crypto session but leaves this
// object alive. It is invalid to call any method that requires a crypto
@@ -141,6 +143,7 @@ class CdmSession {
bool license_received_;
bool is_offline_;
bool is_release_;
bool is_temporary_;
CdmSecurityLevel security_level_;
SecurityLevel requested_security_level_;
CdmAppParameterMap app_parameters_;

View File

@@ -67,6 +67,7 @@ class DeviceFiles {
virtual bool DeleteAllLicenses();
virtual bool LicenseExists(const std::string& key_set_id);
virtual bool ReserveLicenseId(const std::string& key_set_id);
virtual bool UnreserveLicenseId(const std::string& key_set_id);
virtual bool StoreUsageInfo(const std::string& provider_session_token,
const CdmKeyMessage& key_request,

View File

@@ -56,6 +56,10 @@ class CdmLicense {
return provider_session_token_;
}
virtual bool is_offline() {
return is_offline_;
}
static CdmResponseType VerifySignedServiceCertificate(
const std::string& signed_service_certificate);
@@ -89,6 +93,7 @@ class CdmLicense {
std::set<KeyId> loaded_keys_;
std::string provider_session_token_;
bool renew_with_client_id_;
bool is_offline_;
// Used for certificate based licensing
CdmKeyMessage key_request_;

View File

@@ -207,6 +207,8 @@ enum CdmResponseType {
DUPLICATE_SESSION_ID_SPECIFIED,
LICENSE_RENEWAL_PROHIBITED,
EMPTY_PROVISIONING_CERTIFICATE_2,
OFFLINE_LICENSE_PROHIBITED,
STORAGE_PROHIBITED,
};
enum CdmKeyStatus {
@@ -229,6 +231,9 @@ enum CdmLicenseType {
// If the original request was saved to make a service certificate request,
// use Deferred for the license type in the subsequent request.
kLicenseTypeDeferred,
// Like Streaming, but stricter. Does not permit storage of any kind.
// Named after the 'temporary' session type in EME, which has this behavior.
kLicenseTypeTemporary,
};
enum SecurityLevel {

View File

@@ -228,7 +228,8 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
key_request->clear();
if (license_type == kLicenseTypeRelease) {
if (license_type == kLicenseTypeRelease &&
!iter->second->license_received()) {
sts = iter->second->RestoreOfflineSession(key_set_id, kLicenseTypeRelease);
if (sts != KEY_ADDED) {
LOGE("CdmEngine::GenerateKeyRequest: key release restoration failed,"

View File

@@ -37,6 +37,7 @@ CdmSession::CdmSession(CdmClientPropertySet* cdm_client_property_set,
license_received_(false),
is_offline_(false),
is_release_(false),
is_temporary_(false),
security_level_(kSecurityLevelUninitialized),
requested_security_level_(kLevelDefault),
is_initial_decryption_(true),
@@ -66,7 +67,13 @@ CdmSession::CdmSession(CdmClientPropertySet* cdm_client_property_set,
}
}
CdmSession::~CdmSession() { Properties::RemoveSessionPropertySet(session_id_); }
CdmSession::~CdmSession() {
if (!key_set_id_.empty()) {
// Unreserve the license ID.
file_handle_->UnreserveLicenseId(key_set_id_);
}
Properties::RemoveSessionPropertySet(session_id_);
}
CdmResponseType CdmSession::Init() {
if (session_id_.empty()) {
@@ -184,6 +191,9 @@ CdmResponseType CdmSession::GenerateKeyRequest(
}
switch (license_type) {
case kLicenseTypeTemporary:
is_temporary_ = true;
break;
case kLicenseTypeStreaming:
is_offline_ = false;
break;
@@ -207,6 +217,8 @@ CdmResponseType CdmSession::GenerateKeyRequest(
license_type = kLicenseTypeRelease;
} else if (is_offline_) {
license_type = kLicenseTypeOffline;
} else if (is_temporary_) {
license_type = kLicenseTypeTemporary;
} else {
license_type = kLicenseTypeStreaming;
}
@@ -484,12 +496,22 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
}
CdmResponseType CdmSession::StoreLicense() {
if (is_temporary_) {
LOGE("CdmSession::StoreLicense: Session type prohibits storage.");
return STORAGE_PROHIBITED;
}
if (is_offline_) {
if (key_set_id_.empty()) {
LOGE("CdmSession::StoreLicense: No key set ID");
return EMPTY_KEYSET_ID;
}
if (!license_parser_->is_offline()) {
LOGE("CdmSession::StoreLicense: License policy prohibits storage.");
return OFFLINE_LICENSE_PROHIBITED;
}
if (!StoreLicense(DeviceFiles::kLicenseStateActive)) {
LOGE("CdmSession::StoreLicense: Unable to store license");
CdmResponseType sts = Init();
@@ -502,7 +524,7 @@ CdmResponseType CdmSession::StoreLicense() {
return STORE_LICENSE_ERROR_1;
}
return NO_ERROR;
}
} // if (is_offline_)
std::string provider_session_token =
license_parser_->provider_session_token();

View File

@@ -343,6 +343,15 @@ bool DeviceFiles::ReserveLicenseId(const std::string& key_set_id) {
return true;
}
bool DeviceFiles::UnreserveLicenseId(const std::string& key_set_id) {
if (!initialized_) {
LOGW("DeviceFiles::UnreserveLicenseId: not initialized");
return false;
}
reserved_license_ids_.erase(key_set_id);
return true;
}
bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
const CdmKeyMessage& key_request,
const CdmKeyResponse& key_response,

View File

@@ -132,6 +132,7 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id)
session_id_(session_id),
initialized_(false),
renew_with_client_id_(false),
is_offline_(false),
clock_(new Clock()) {}
CdmLicense::CdmLicense(const CdmSessionId& session_id, Clock* clock)
@@ -139,7 +140,8 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id, Clock* clock)
policy_engine_(NULL),
session_id_(session_id),
initialized_(false),
renew_with_client_id_(false) {
renew_with_client_id_(false),
is_offline_(false) {
clock_.reset(clock);
}
@@ -522,6 +524,10 @@ CdmResponseType CdmLicense::HandleKeyResponse(
return NO_CONTENT_KEY;
}
if (license.id().type() == video_widevine_server::sdk::OFFLINE &&
license.policy().can_persist())
is_offline_ = true;
if (license.id().has_provider_session_token())
provider_session_token_ = license.id().provider_session_token();
@@ -1102,6 +1108,7 @@ bool CdmLicense::PrepareContentId(const CdmLicenseType license_type,
content_id->set_license_type(video_widevine_server::sdk::OFFLINE);
break;
case kLicenseTypeStreaming:
case kLicenseTypeTemporary:
content_id->set_license_type(video_widevine_server::sdk::STREAMING);
break;
default:

View File

@@ -200,7 +200,7 @@ TEST_F(WvCdmEngineTest, BaseIsoBmffMessageTest) {
}
// TODO(juce): Set up with correct test data.
TEST_F(WvCdmEngineTest, DISABLED_BaseWebmMessageTest) {
TEST_F(WvCdmEngineTest, BaseWebmMessageTest) {
GenerateKeyRequest(g_key_id_unwrapped, kWebmMimeType);
GetKeyRequestResponse(g_license_server, g_client_auth);
}
@@ -220,7 +220,7 @@ TEST_F(WvCdmEngineTest, NormalDecryptionIsoBmff) {
}
// TODO(juce): Set up with correct test data.
TEST_F(WvCdmEngineTest, DISABLED_NormalDecryptionWebm) {
TEST_F(WvCdmEngineTest, NormalDecryptionWebm) {
GenerateKeyRequest(g_key_id_unwrapped, kWebmMimeType);
VerifyNewKeyResponse(g_license_server, g_client_auth);
}

View File

@@ -2140,6 +2140,8 @@ TEST_F(DeviceFilesTest, ReserveLicenseIdsDoesNotUseFileSystem) {
EXPECT_TRUE(device_files.ReserveLicenseId(license_test_data[i].key_set_id));
// Validate that the license IDs are actually reserved.
EXPECT_TRUE(device_files.LicenseExists(license_test_data[i].key_set_id));
// Unreserve these IDs to avoid polluting other tests.
EXPECT_TRUE(device_files.UnreserveLicenseId(license_test_data[i].key_set_id));
}
}

View File

@@ -177,7 +177,9 @@ enum {
kEmptyLicenseRequest = ERROR_DRM_VENDOR_MIN + 163,
kDuplicateSessionIdSpecified = ERROR_DRM_VENDOR_MIN + 164,
kLicenseRenewalProhibited = ERROR_DRM_VENDOR_MIN + 165,
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 165,
kOfflineLicenseProhibited = ERROR_DRM_VENDOR_MIN + 166,
kStorageProhibited = ERROR_DRM_VENDOR_MIN + 167,
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 167,
// Used by crypto test mode
kErrorTestMode = ERROR_DRM_VENDOR_MAX,

View File

@@ -343,6 +343,10 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) {
return kDuplicateSessionIdSpecified;
case wvcdm::LICENSE_RENEWAL_PROHIBITED:
return kLicenseRenewalProhibited;
case wvcdm::OFFLINE_LICENSE_PROHIBITED:
return kOfflineLicenseProhibited;
case wvcdm::STORAGE_PROHIBITED:
return kStorageProhibited;
case wvcdm::UNKNOWN_ERROR:
return android::ERROR_DRM_UNKNOWN;
case wvcdm::SECURE_BUFFER_REQUIRED: