release-request-cacfaf25-4304-4e6b-ab4e-089367c7ed39-for-git_pi-release-4326570 snap-temp-L59400000101056305

Change-Id: Id92d5813c233d1b100b74eb5ff8a82766a0dc5c3
This commit is contained in:
android-build-team Robot
2017-09-10 08:17:58 +00:00
18 changed files with 106 additions and 83 deletions

View File

@@ -50,7 +50,7 @@ class CdmLicense {
const CdmKeyResponse& license_response,
const CdmKeyResponse& license_renewal_response,
int64_t playback_start_time, int64_t last_playback_time,
int64_t grace_period_end_time);
int64_t grace_period_end_time, CdmSession* cdm_session);
virtual bool RestoreLicenseForRelease(const CdmKeyMessage& license_request,
const CdmKeyResponse& license_response);
virtual bool HasInitData() { return stored_init_data_.get(); }

View File

@@ -105,6 +105,7 @@ static const std::string HLS_URI_ATTRIBUTE = "URI";
static const char EMPTY_ORIGIN[] = "";
static const char EMPTY_SPOID[] = "";
static const char EMPTY_APP_PACKAGE_NAME[] = "";
} // namespace wvcdm
#endif // WVCDM_CORE_WV_CDM_CONSTANTS_H_

View File

@@ -312,6 +312,7 @@ enum CdmResponseType {
PARSE_RESPONSE_ERROR_2,
PARSE_RESPONSE_ERROR_3, /* 270 */
PARSE_RESPONSE_ERROR_4,
RELEASE_ALL_USAGE_INFO_ERROR_6,
};
enum CdmKeyStatus {

View File

@@ -1135,19 +1135,32 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
std::vector<DeviceFiles::CdmUsageData> usage_data;
if (!handle.RetrieveUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
&usage_data)) {
status = RELEASE_ALL_USAGE_INFO_ERROR_4;
} else {
for (size_t k = 0; k < usage_data.size(); ++k) {
CdmResponseType status2 =
usage_session_->DeleteUsageEntry(
usage_data[k].usage_entry_number);
if (status == NO_ERROR && status2 != NO_ERROR)
status = status2;
// Retrieve all usage information but delete only one before
// refetching. This is because deleting the usage entry
// might cause other entries to be shifted and information updated.
do {
if (!handle.RetrieveUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
&usage_data)) {
status = RELEASE_ALL_USAGE_INFO_ERROR_4;
break;
}
}
if (usage_data.empty()) break;
status = usage_session_->DeleteUsageEntry(
usage_data[0].usage_entry_number);
if (status != NO_ERROR) break;
if (!handle.DeleteUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
usage_data[0].provider_session_token)) {
status = RELEASE_ALL_USAGE_INFO_ERROR_6;
break;
}
} while (status == NO_ERROR && !usage_data.empty());
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),

View File

@@ -240,7 +240,8 @@ CdmResponseType CdmSession::RestoreOfflineSession(
} else {
if (!license_parser_->RestoreOfflineLicense(
key_request_, key_response_, offline_key_renewal_response_,
playback_start_time, last_playback_time, grace_period_end_time)) {
playback_start_time, last_playback_time, grace_period_end_time,
this)) {
return RESTORE_OFFLINE_LICENSE_ERROR_2;
}
}
@@ -685,8 +686,7 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
}
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
if (usage_support_type_ != kUsageEntrySupport ||
!has_provider_session_token()) {
if (usage_support_type_ != kUsageEntrySupport) {
LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d",
usage_support_type_);
return INCORRECT_USAGE_SUPPORT_TYPE_1;
@@ -885,10 +885,13 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() {
CdmResponseType CdmSession::UpdateUsageEntryInformation() {
if (usage_support_type_ != kUsageEntrySupport ||
!has_provider_session_token() &&
usage_table_header_ != nullptr) {
LOGE("CdmSession::UpdateUsageEntryInformation: Unexpected usage type "
"supported: %d", usage_support_type_);
!has_provider_session_token() ||
usage_table_header_ == nullptr) {
LOGE("CdmSession::UpdateUsageEntryInformation: Unexpected state, "
"usage support type: %d, PST present: %s, usage table header available"
": %s", usage_support_type_,
has_provider_session_token() ? "yes" : "no",
usage_table_header_ == nullptr ? "no" : "yes");
return INCORRECT_USAGE_SUPPORT_TYPE_2;
}

View File

@@ -349,7 +349,8 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
}
// TODO(rfrias): Refactor to avoid needing to call CdmSession
if (cdm_session) {
if (cdm_session &&
cdm_session->get_usage_support_type() == kUsageEntrySupport) {
CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
if (NO_ERROR != status) return status;
}
@@ -628,7 +629,8 @@ bool CdmLicense::RestoreOfflineLicense(
const CdmKeyMessage& license_request,
const CdmKeyResponse& license_response,
const CdmKeyResponse& license_renewal_response, int64_t playback_start_time,
int64_t last_playback_time, int64_t grace_period_end_time) {
int64_t last_playback_time, int64_t grace_period_end_time,
CdmSession* cdm_session) {
if (license_request.empty() || license_response.empty()) {
LOGE(
"CdmLicense::RestoreOfflineLicense: key_request or response empty: "
@@ -670,9 +672,16 @@ bool CdmLicense::RestoreOfflineLicense(
}
if (!provider_session_token_.empty()) {
if (cdm_session &&
cdm_session->get_usage_support_type() == kUsageEntrySupport) {
CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
if (NO_ERROR != status) return false;
}
std::string usage_report;
CryptoSession::UsageDurationStatus usage_duration_status =
CryptoSession::kUsageDurationsInvalid;
int64_t seconds_since_started, seconds_since_last_played;
sts = crypto_session_->GenerateUsageReport(
provider_session_token_, &usage_report, &usage_duration_status,

View File

@@ -560,6 +560,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
case RELEASE_ALL_USAGE_INFO_ERROR_5:
*os << "RELEASE_ALL_USAGE_INFO_ERROR_5";
break;
case RELEASE_ALL_USAGE_INFO_ERROR_6:
*os << "RELEASE_ALL_USAGE_INFO_ERROR_6";
break;
case RELEASE_USAGE_INFO_FAILED: *os << "RELEASE_USAGE_INFO_FAILED";
break;
case INCORRECT_USAGE_SUPPORT_TYPE_1:

View File

@@ -25,11 +25,17 @@ struct CdmIdentifier {
// The origin. May be blank if the app does not set an origin, which is
// the likely behavior of most non-web-browser apps.
std::string origin;
// The application package name provided by the application. This is used to
// provide a friendly name of the application package for the purposes of
// logging and metrics.
std::string app_package_name;
};
// Provide comparison operators
inline bool operator==(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
return lhs.spoid == rhs.spoid && lhs.origin == rhs.origin;
return lhs.spoid == rhs.spoid && lhs.origin == rhs.origin
&& lhs.app_package_name == rhs.app_package_name;
}
inline bool operator!=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
@@ -37,8 +43,11 @@ inline bool operator!=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
}
inline bool operator<(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
return (lhs.spoid < rhs.spoid) ||
((lhs.spoid == rhs.spoid) && lhs.origin < rhs.origin);
return (lhs.spoid < rhs.spoid)
|| ((lhs.spoid == rhs.spoid)
&& (lhs.origin < rhs.origin
|| (lhs.origin == rhs.origin
&& lhs.app_package_name < rhs.app_package_name)));
}
inline bool operator>(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
@@ -56,7 +65,8 @@ inline bool operator>=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
// Provide default
static const CdmIdentifier kDefaultCdmIdentifier = {
EMPTY_SPOID,
EMPTY_ORIGIN
EMPTY_ORIGIN,
EMPTY_APP_PACKAGE_NAME
};
} // namespace wvcdm

View File

@@ -263,6 +263,8 @@ class EngineMetrics {
void Serialize(drm_metrics::MetricsGroup* metric_group, bool completed_only,
bool clear_serialized_sessions);
void SetAppPackageName(const std::string& app_package_name);
// Metrics recorded at the engine level.
EventMetric<CdmResponseType> cdm_engine_add_key_;
ValueMetric<std::string> cdm_engine_cdm_version_;
@@ -288,6 +290,7 @@ class EngineMetrics {
Lock session_metrics_lock_;
std::vector<metrics::SessionMetrics*> session_metrics_list_;
CryptoMetrics crypto_metrics_;
std::string app_package_name_;
void SerializeEngineMetrics(drm_metrics::MetricsGroup* out);
};

View File

@@ -33,4 +33,7 @@ message MetricsGroup {
// Allow multiple sub groups of metrics.
repeated MetricsGroup metric_sub_group = 2;
// Name of the application package associated with the metrics.
optional string app_package_name = 3;
}

View File

@@ -440,7 +440,8 @@ EngineMetrics::EngineMetrics() :
cdm_engine_unprovision_(
"/drm/widevine/cdm_engine/unprovision",
"error",
"security_level") {
"security_level"),
app_package_name_("") {
}
EngineMetrics::~EngineMetrics() {
@@ -482,14 +483,20 @@ void EngineMetrics::Serialize(drm_metrics::MetricsGroup* metric_group,
OemCryptoDynamicAdapterMetrics& adapter_metrics =
GetDynamicAdapterMetricsInstance();
adapter_metrics.Serialize(metric_group);
if (!app_package_name_.empty()) {
metric_group->set_app_package_name(app_package_name_);
}
SerializeEngineMetrics(metric_group);
std::vector<SessionMetrics*>::iterator i;
for (i = session_metrics_list_.begin(); i != session_metrics_list_.end();
/* no increment */) {
bool serialized = false;
if (!completed_only || (*i)->IsCompleted()) {
(*i)->Serialize(metric_group->add_metric_sub_group());
MetricsGroup* metric_sub_group = metric_group->add_metric_sub_group();
if (!app_package_name_.empty()) {
metric_sub_group->set_app_package_name(app_package_name_);
}
(*i)->Serialize(metric_sub_group);
serialized = true;
}
@@ -502,6 +509,10 @@ void EngineMetrics::Serialize(drm_metrics::MetricsGroup* metric_group,
}
}
void EngineMetrics::SetAppPackageName(const std::string& app_package_name) {
app_package_name_ = app_package_name;
}
void EngineMetrics::SerializeEngineMetrics(MetricsGroup* metric_group) {
ProtoMetricSerializer serializer(metric_group);
cdm_engine_add_key_.Serialize(&serializer);

View File

@@ -380,9 +380,14 @@ CdmEngine* WvContentDecryptionModule::EnsureCdmForIdentifier(
cdms_[identifier].file_system.SetOrigin(identifier.origin);
cdms_[identifier].file_system.SetIdentifier(
identifier.spoid + identifier.origin);
}
return cdms_[identifier].cdm_engine.get();
// Set the app package name for use by metrics.
cdms_[identifier].cdm_engine->GetMetrics()
->SetAppPackageName(identifier.app_package_name);
}
CdmEngine* cdm_engine = cdms_[identifier].cdm_engine.get();
return cdm_engine;
}
CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(

View File

@@ -51,6 +51,7 @@ const int kHttpInternalServerError = 500;
const wvcdm::CdmIdentifier kExampleIdentifier = {
wvcdm::EMPTY_SPOID,
"com.example",
"com.example"
};
@@ -2023,55 +2024,6 @@ TEST_F(WvCdmRequestLicenseTest,
VerifyKeyRequestResponse(g_license_server, client_auth);
}
TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
Unprovision();
Provision(kLevelDefault);
// override default settings unless configured through the command line
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
&session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
session_id_.clear();
key_set_id_.clear();
StrictMock<TestWvCdmEventListener> listener;
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, &listener,
&session_id_);
CdmSessionId restore_session_id = session_id_;
EXPECT_CALL(
listener,
OnSessionKeysChange(
restore_session_id,
AllOf(Each(Pair(_, kKeyStatusUsable)), Not(IsEmpty())), true));
EXPECT_CALL(listener, OnExpirationUpdate(restore_session_id, _));
EXPECT_EQ(wvcdm::KEY_ADDED,
decryptor_.RestoreKey(restore_session_id, key_set_id));
session_id_.clear();
key_set_id_.clear();
// Maybe called since VerifyKeyRequestResponse could take some time.
EXPECT_CALL(listener, OnSessionRenewalNeeded(restore_session_id))
.Times(AtLeast(0));
EXPECT_CALL(
listener,
OnSessionKeysChange(
restore_session_id,
AllOf(Each(Pair(_, kKeyStatusExpired)), Not(IsEmpty())), false));
GenerateKeyRelease(key_set_id);
key_set_id_ = key_set_id;
VerifyKeyRequestResponse(g_license_server, client_auth);
decryptor_.CloseSession(restore_session_id);
}
// This test verifies that repeated generation of the key release message
// for the same key_set_id results in the previous session being
// deallocated (rather than leaked) and a new one allocated.

View File

@@ -106,7 +106,7 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) {
TEST_F(WvContentDecryptionModuleMetricsTest, MultipleEngineMetric) {
CdmSessionId session_id;
wvcdm::CdmKeySystem key_system("com.widevine");
CdmIdentifier identifier = { "foo", "bar" };
CdmIdentifier identifier = { "foo", "bar", "baz" };
// Openning the session will fail with NEEDS_PROVISIONING error. But it will
// still create some session-level stats.
@@ -146,6 +146,9 @@ TEST_F(WvContentDecryptionModuleMetricsTest, MultipleEngineMetric) {
metrics.metric_sub_group(i).metric_sub_group(0).metric(0).name(),
StrEq("/drm/widevine/cdm_session/session_id"));
}
// Verify that the second metrics app package name is set.
EXPECT_THAT(metrics.metric_sub_group(1).app_package_name(), StrEq("baz"));
}
}

View File

@@ -274,10 +274,11 @@ enum {
kParseResponseError2 = ERROR_DRM_VENDOR_MIN + 261,
kParseResponseError3 = ERROR_DRM_VENDOR_MIN + 262,
kParseResponseError4 = ERROR_DRM_VENDOR_MIN + 263,
kReleaseAllUsageInfoError6 = ERROR_DRM_VENDOR_MIN + 264,
// This should always follow the last error code.
// The offset value should be updated each time a new error code is added.
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 263,
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 264,
// Used by crypto test mode
kErrorTestMode = ERROR_DRM_VENDOR_MAX,

View File

@@ -499,6 +499,8 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) {
return kReleaseAllUsageInfoError4;
case wvcdm::RELEASE_ALL_USAGE_INFO_ERROR_5:
return kReleaseAllUsageInfoError5;
case wvcdm::RELEASE_ALL_USAGE_INFO_ERROR_6:
return kReleaseAllUsageInfoError6;
case wvcdm::RELEASE_USAGE_INFO_FAILED:
return android::ERROR_DRM_TAMPER_DETECTED;
case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_1:

View File

@@ -286,6 +286,7 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) {
case wvcdm::USAGE_INVALID_LOAD_ENTRY:
case wvcdm::RELEASE_ALL_USAGE_INFO_ERROR_4:
case wvcdm::RELEASE_ALL_USAGE_INFO_ERROR_5:
case wvcdm::RELEASE_ALL_USAGE_INFO_ERROR_6:
case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_1:
case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_2:
case wvcdm::NO_USAGE_ENTRIES:

View File

@@ -1375,7 +1375,9 @@ WVDrmPlugin::CdmIdentifierBuilder::CdmIdentifierBuilder(
mIsIdentifierSealed(false),
mUseSpoid(useSpoid),
mAppPackageName(appPackageName),
mParent(parent) {}
mParent(parent) {
mCdmIdentifier.app_package_name = mAppPackageName;
}
Status WVDrmPlugin::CdmIdentifierBuilder::getCdmIdentifier(
CdmIdentifier* identifier) {