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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
};
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -147,6 +147,26 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
virtual CdmResponseType GetDecryptHashError(const CdmSessionId& session_id,
|
||||
std::string* hash_error_string);
|
||||
|
||||
// Return the list of key_set_ids stored on the current (origin-specific)
|
||||
// file system.
|
||||
virtual CdmResponseType ListStoredLicenses(
|
||||
CdmSecurityLevel security_level,
|
||||
const CdmIdentifier& identifier,
|
||||
std::vector<CdmKeySetId>* key_set_ids);
|
||||
|
||||
// Retrieve offline license state using key_set_id.
|
||||
virtual CdmResponseType GetOfflineLicenseState(
|
||||
const CdmKeySetId& key_set_id,
|
||||
CdmSecurityLevel security_level,
|
||||
const CdmIdentifier& identifier,
|
||||
CdmOfflineLicenseState* licenseState);
|
||||
|
||||
// Remove offline license using key_set_id.
|
||||
virtual CdmResponseType RemoveOfflineLicense(
|
||||
const CdmKeySetId& key_set_id,
|
||||
CdmSecurityLevel security_level,
|
||||
const CdmIdentifier& identifier);
|
||||
|
||||
private:
|
||||
struct CdmInfo {
|
||||
CdmInfo();
|
||||
|
||||
@@ -525,4 +525,32 @@ uint32_t WvContentDecryptionModule::GenerateSessionSharingId() {
|
||||
return ++next_session_sharing_id;
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::ListStoredLicenses(
|
||||
CdmSecurityLevel security_level,
|
||||
const CdmIdentifier& identifier,
|
||||
std::vector<CdmKeySetId>* key_set_ids) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
return cdm_engine->ListStoredLicenses(
|
||||
security_level, key_set_ids);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetOfflineLicenseState(
|
||||
const CdmKeySetId& key_set_id,
|
||||
CdmSecurityLevel security_level,
|
||||
const CdmIdentifier& identifier,
|
||||
CdmOfflineLicenseState* license_state) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
return cdm_engine->GetOfflineLicenseState(
|
||||
key_set_id, security_level, license_state);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::RemoveOfflineLicense(
|
||||
const CdmKeySetId& key_set_id,
|
||||
CdmSecurityLevel security_level,
|
||||
const CdmIdentifier& identifier) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
return cdm_engine->RemoveOfflineLicense(
|
||||
key_set_id, security_level);
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user