Implement MediaDrm offline license support in Widevine hidl service.

Merged from http://go/wvgerrit/69723.

The new APIs are getOfflineLicenseIds, getOfflineLicenseState and
removeOfflineLicense. These methods are currently stubbed out in
Widevine hidl service. This CL completes the implementation.

Test: unit tests - libwvdrmdrmplugin_hidl_test

Test: GTS
  --test com.google.android.media.gts.MediaDrmTest#testWidevineApi29

bug: 117570686
Change-Id: I96ffb75f453e36e931effefd3664b5faa8d69d30
This commit is contained in:
Edwin Wong
2019-01-21 17:07:43 -08:00
parent 19c4996b3c
commit 54104c7a22
12 changed files with 462 additions and 30 deletions

View File

@@ -212,6 +212,17 @@ class CdmEngine {
CdmSecurityLevel security_level,
const std::string& key_set_id);
// Get offline license status: active, release or unknown
virtual CdmResponseType GetOfflineLicenseState(
const std::string& key_set_id,
CdmSecurityLevel security_level,
CdmOfflineLicenseState* license_state);
// Remove offline license with the given key_set_id
virtual CdmResponseType RemoveOfflineLicense(
const std::string& key_set_id,
CdmSecurityLevel security_level);
// Usage related methods for streaming licenses
// Retrieve a random usage info from the list of all usage infos for this app
// id.

View File

@@ -194,7 +194,7 @@ class CdmSession {
const std::string& signature);
virtual CdmResponseType SetDecryptHash(uint32_t frame_number,
const std::string& hash);
const std::string& hash);
virtual CdmResponseType GetDecryptHashError(std::string* hash_error_string);

View File

@@ -91,6 +91,7 @@ class DeviceFiles {
const CdmUsageEntry& usage_entry,
uint32_t usage_entry_number,
ResponseType* result);
virtual bool RetrieveLicense(
const std::string& key_set_id, LicenseState* state,
CdmInitData* pssh_data, CdmKeyMessage* key_request,

View File

@@ -40,6 +40,12 @@ enum CdmKeyRequestType {
kKeyRequestTypeRelease,
};
enum CdmOfflineLicenseState {
kLicenseStateActive,
kLicenseStateReleasing,
kLicenseStateUnknown,
};
enum CdmResponseType {
NO_ERROR = 0,
UNKNOWN_ERROR = 1,
@@ -355,6 +361,11 @@ enum CdmResponseType {
INVALID_LICENSE_TYPE_2 = 310,
SIGNATURE_NOT_FOUND_2 = 311,
SESSION_KEYS_NOT_FOUND_2 = 312,
GET_OFFLINE_LICENSE_STATE_ERROR_1 = 313,
GET_OFFLINE_LICENSE_STATE_ERROR_2 = 314,
REMOVE_OFFLINE_LICENSE_ERROR_1 = 315,
REMOVE_OFFLINE_LICENSE_ERROR_2 = 316,
SESSION_NOT_FOUND_21 = 317,
// Don't forget to add new values to ../test/test_printers.cpp.
};

View File

@@ -27,6 +27,18 @@ namespace {
const uint64_t kReleaseSessionTimeToLive = 60; // seconds
const uint32_t kUpdateUsageInformationPeriod = 60; // seconds
const size_t kUsageReportsPerRequest = 1;
wvcdm::CdmOfflineLicenseState MapDeviceFilesLicenseState(
wvcdm::DeviceFiles::LicenseState state) {
switch (state) {
case wvcdm::DeviceFiles::LicenseState::kLicenseStateActive:
return wvcdm::kLicenseStateActive;
case wvcdm::DeviceFiles::LicenseState::kLicenseStateReleasing:
return wvcdm::kLicenseStateReleasing;
default:
return wvcdm::kLicenseStateUnknown;
}
}
} // namespace
namespace wvcdm {
@@ -1100,6 +1112,98 @@ CdmResponseType CdmEngine::DeleteUsageRecord(const std::string& app_id,
return status;
}
CdmResponseType CdmEngine::GetOfflineLicenseState(
const CdmKeySetId &key_set_id,
CdmSecurityLevel security_level,
CdmOfflineLicenseState* license_state) {
DeviceFiles handle(file_system_);
if (!handle.Init(security_level)) {
LOGE("CdmEngine::GetOfflineLicenseState: cannot initialize device files");
return GET_OFFLINE_LICENSE_STATE_ERROR_1;
}
DeviceFiles::LicenseState state;
// Dummy arguments to make the RetrieveLicense call,
// do not care about the return value except for license state.
CdmAppParameterMap app_parameters;
CdmKeyMessage key_request;
CdmKeyResponse key_response;
CdmInitData offline_init_data;
CdmKeyMessage offline_key_renewal_request;
CdmKeyResponse offline_key_renewal_response;
CdmUsageEntry usage_entry;
int64_t grace_period_end_time;
int64_t last_playback_time;
std::string offline_release_server_url;
int64_t playback_start_time;
uint32_t usage_entry_number;
DeviceFiles::ResponseType sub_error_code = DeviceFiles::kNoError;
if (handle.RetrieveLicense(key_set_id, &state, &offline_init_data,
&key_request, &key_response,
&offline_key_renewal_request, &offline_key_renewal_response,
&offline_release_server_url,
&playback_start_time, &last_playback_time, &grace_period_end_time,
&app_parameters, &usage_entry, &usage_entry_number,
&sub_error_code)) {
*license_state = MapDeviceFilesLicenseState(state);
} else {
LOGE("CdmEngine::GetOfflineLicenseState:: failed to retrieve license state "
"key set id = %s",
key_set_id.c_str());
return GET_OFFLINE_LICENSE_STATE_ERROR_2;
}
return NO_ERROR;
}
CdmResponseType CdmEngine::RemoveOfflineLicense(
const CdmKeySetId &key_set_id,
CdmSecurityLevel security_level) {
UsagePropertySet property_set;
property_set.set_security_level(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
DeviceFiles handle(file_system_);
CdmResponseType sts = OpenKeySetSession(key_set_id,
&property_set, nullptr /* event listener */);
if (sts != NO_ERROR) {
if (!handle.Init(security_level)) {
LOGE("CdmEngine::RemoveOfflineLicense: cannot initialize device files");
}
handle.DeleteLicense(key_set_id);
return REMOVE_OFFLINE_LICENSE_ERROR_1;
}
CdmSessionId session_id;
CdmAppParameterMap dummy_app_params;
InitializationData dummy_init_data("", "", "");
CdmKeyRequest key_request;
// Calling with no session_id is okay
sts = GenerateKeyRequest(session_id, key_set_id, dummy_init_data,
kLicenseTypeRelease, dummy_app_params, &key_request);
if (sts == KEY_MESSAGE) {
std::unique_lock<std::mutex> lock(release_key_sets_lock_);
CdmReleaseKeySetMap::iterator iter = release_key_sets_.find(key_set_id);
if (iter == release_key_sets_.end()) {
LOGE("CdmEngine::RemoveOfflineLicense: key set id not found = %s",
key_set_id.c_str());
sts = REMOVE_OFFLINE_LICENSE_ERROR_2;
} else {
session_id = iter->second.first;
sts = RemoveLicense(session_id);
}
}
if (sts != NO_ERROR) {
LOGE("CdmEngine: GenerateKeyRequest error=%d", sts);
handle.DeleteLicense(key_set_id);
}
CloseKeySetSession(key_set_id);
return sts;
}
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
const CdmSecureStopId& ssid,
CdmUsageInfo* usage_info) {

View File

@@ -154,6 +154,12 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
case GET_LICENSE_ERROR:
*os << "GET_LICENSE_ERROR";
break;
case GET_OFFLINE_LICENSE_STATE_ERROR_1:
*os << "GET_OFFLINE_LICENSE_STATE_ERROR_1";
break;
case GET_OFFLINE_LICENSE_STATE_ERROR_2:
*os << "GET_OFFLINE_LICENSE_STATE_ERROR_2";
break;
case GET_RELEASED_LICENSE_ERROR:
*os << "GET_RELEASED_LICENSE_ERROR";
break;
@@ -784,6 +790,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
case SESSION_NOT_FOUND_20:
*os << "SESSION_NOT_FOUND_20";
break;
case SESSION_NOT_FOUND_21:
*os << "SESSION_NOT_FOUND_21";
break;
case INVALID_DECRYPT_HASH_FORMAT:
*os << "INVALID_DECRYPT_HASH_FORMAT";
break;
@@ -825,6 +834,11 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case SESSION_KEYS_NOT_FOUND_2:
*os << "SESSION_KEYS_NOT_FOUND_2";
case REMOVE_OFFLINE_LICENSE_ERROR_1:
*os << "REMOVE_OFFLINE_LICENSE_ERROR_1";
break;
case REMOVE_OFFLINE_LICENSE_ERROR_2:
*os << "REMOVE_OFFLINE_LICENSE_ERROR_2";
break;
default:
*os << "Unknown CdmResponseType";