Improve query performance
[ Merge of http://go/wvgerrit/15780 ] Android mediaDrm allows callers to serially query status information through a property API. CDM however retrieves all status information in a map and filters out all but the relevent one. This leads to delays in Netflix app startup. Rewriting the CDM interface to return only the queried value. b/24181894 Change-Id: Ie9ed6288524e3a7e03b83aa55ef3531dd52a0dfb
This commit is contained in:
@@ -100,7 +100,8 @@ class CdmEngine {
|
|||||||
|
|
||||||
// Query system information
|
// Query system information
|
||||||
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
|
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
|
||||||
CdmQueryMap* info);
|
const std::string& key,
|
||||||
|
std::string* value);
|
||||||
|
|
||||||
// Query session information
|
// Query session information
|
||||||
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
|
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
|
||||||
|
|||||||
@@ -405,91 +405,115 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||||
CdmQueryMap* key_info) {
|
const std::string& key,
|
||||||
|
std::string* value) {
|
||||||
LOGI("CdmEngine::QueryStatus");
|
LOGI("CdmEngine::QueryStatus");
|
||||||
CryptoSession crypto_session;
|
CryptoSession crypto_session;
|
||||||
if (security_level == kLevel3) {
|
if (security_level == kLevel3) {
|
||||||
CdmResponseType status = crypto_session.Open(kLevel3);
|
CdmResponseType status = crypto_session.Open(kLevel3);
|
||||||
if (NO_ERROR != status) return INVALID_QUERY_STATUS;
|
if (NO_ERROR != status) return INVALID_QUERY_STATUS;
|
||||||
}
|
}
|
||||||
switch (crypto_session.GetSecurityLevel()) {
|
|
||||||
case kSecurityLevelL1:
|
|
||||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
|
|
||||||
break;
|
|
||||||
case kSecurityLevelL2:
|
|
||||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L2;
|
|
||||||
break;
|
|
||||||
case kSecurityLevelL3:
|
|
||||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
|
||||||
break;
|
|
||||||
case kSecurityLevelUninitialized:
|
|
||||||
case kSecurityLevelUnknown:
|
|
||||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] =
|
|
||||||
QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return INVALID_QUERY_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string deviceId;
|
if (key == QUERY_KEY_SECURITY_LEVEL) {
|
||||||
bool success = crypto_session.GetDeviceUniqueId(&deviceId);
|
CdmSecurityLevel security_level = crypto_session.GetSecurityLevel();
|
||||||
if (success) {
|
switch (security_level) {
|
||||||
(*key_info)[QUERY_KEY_DEVICE_ID] = deviceId;
|
case kSecurityLevelL1:
|
||||||
}
|
*value = QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||||
|
break;
|
||||||
|
case kSecurityLevelL2:
|
||||||
|
*value = QUERY_VALUE_SECURITY_LEVEL_L2;
|
||||||
|
break;
|
||||||
|
case kSecurityLevelL3:
|
||||||
|
*value = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||||
|
break;
|
||||||
|
case kSecurityLevelUninitialized:
|
||||||
|
case kSecurityLevelUnknown:
|
||||||
|
*value = QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGW("CdmEngine::QueryStatus: Unknown security level: %d",
|
||||||
|
security_level);
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
} else if (key == QUERY_KEY_DEVICE_ID) {
|
||||||
|
std::string deviceId;
|
||||||
|
if (!crypto_session.GetDeviceUniqueId(&deviceId)) {
|
||||||
|
LOGW("CdmEngine::QueryStatus: GetDeviceUniqueId failed");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = deviceId;
|
||||||
|
} else if (key == QUERY_KEY_SYSTEM_ID) {
|
||||||
|
uint32_t system_id;
|
||||||
|
if (!crypto_session.GetSystemId(&system_id)) {
|
||||||
|
LOGW("CdmEngine::QueryStatus: GetSystemId failed");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t system_id;
|
|
||||||
success = crypto_session.GetSystemId(&system_id);
|
|
||||||
if (success) {
|
|
||||||
std::ostringstream system_id_stream;
|
std::ostringstream system_id_stream;
|
||||||
system_id_stream << system_id;
|
system_id_stream << system_id;
|
||||||
(*key_info)[QUERY_KEY_SYSTEM_ID] = system_id_stream.str();
|
*value = system_id_stream.str();
|
||||||
}
|
} else if (key == QUERY_KEY_PROVISIONING_ID) {
|
||||||
|
std::string provisioning_id;
|
||||||
|
if (!crypto_session.GetProvisioningId(&provisioning_id)) {
|
||||||
|
LOGW("CdmEngine::QueryStatus: GetProvisioningId failed");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
std::string provisioning_id;
|
*value = provisioning_id;
|
||||||
success = crypto_session.GetProvisioningId(&provisioning_id);
|
} else if (key == QUERY_KEY_CURRENT_HDCP_LEVEL ||
|
||||||
if (success) {
|
key == QUERY_KEY_MAX_HDCP_LEVEL) {
|
||||||
(*key_info)[QUERY_KEY_PROVISIONING_ID] = provisioning_id;
|
CryptoSession::HdcpCapability current_hdcp;
|
||||||
}
|
CryptoSession::HdcpCapability max_hdcp;
|
||||||
|
if (!crypto_session.GetHdcpCapabilities(¤t_hdcp, &max_hdcp)) {
|
||||||
|
LOGW("CdmEngine::QueryStatus: GetHdcpCapabilities failed");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
CryptoSession::HdcpCapability current_hdcp;
|
*value = MapHdcpVersion(key == QUERY_KEY_CURRENT_HDCP_LEVEL ? current_hdcp
|
||||||
CryptoSession::HdcpCapability max_hdcp;
|
: max_hdcp);
|
||||||
success = crypto_session.GetHdcpCapabilities(¤t_hdcp, &max_hdcp);
|
} else if (key == QUERY_KEY_USAGE_SUPPORT) {
|
||||||
if (success) {
|
bool supports_usage_reporting;
|
||||||
(*key_info)[QUERY_KEY_CURRENT_HDCP_LEVEL] = MapHdcpVersion(current_hdcp);
|
if (!crypto_session.UsageInformationSupport(&supports_usage_reporting)) {
|
||||||
(*key_info)[QUERY_KEY_MAX_HDCP_LEVEL] = MapHdcpVersion(max_hdcp);
|
LOGW("CdmEngine::QueryStatus: UsageInformationSupport failed");
|
||||||
}
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
bool supports_usage_reporting;
|
*value = supports_usage_reporting ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
||||||
success = crypto_session.UsageInformationSupport(&supports_usage_reporting);
|
} else if (key == QUERY_KEY_NUMBER_OF_OPEN_SESSIONS) {
|
||||||
if (success) {
|
size_t number_of_open_sessions;
|
||||||
(*key_info)[QUERY_KEY_USAGE_SUPPORT] =
|
if (!crypto_session.GetNumberOfOpenSessions(&number_of_open_sessions)) {
|
||||||
supports_usage_reporting ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
LOGW("CdmEngine::QueryStatus: GetNumberOfOpenSessions failed");
|
||||||
}
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
size_t number_of_open_sessions;
|
|
||||||
success = crypto_session.GetNumberOfOpenSessions(&number_of_open_sessions);
|
|
||||||
if (success) {
|
|
||||||
std::ostringstream open_sessions_stream;
|
std::ostringstream open_sessions_stream;
|
||||||
open_sessions_stream << number_of_open_sessions;
|
open_sessions_stream << number_of_open_sessions;
|
||||||
(*key_info)[QUERY_KEY_NUMBER_OF_OPEN_SESSIONS] =
|
*value = open_sessions_stream.str();
|
||||||
open_sessions_stream.str();
|
} else if (key == QUERY_KEY_MAX_NUMBER_OF_SESSIONS) {
|
||||||
}
|
size_t maximum_number_of_sessions;
|
||||||
|
if (!crypto_session.GetMaxNumberOfSessions(&maximum_number_of_sessions)) {
|
||||||
|
LOGW("CdmEngine::QueryStatus: GetMaxNumberOfOpenSessions failed");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
size_t maximum_number_of_sessions;
|
|
||||||
success = crypto_session.GetMaxNumberOfSessions(&maximum_number_of_sessions);
|
|
||||||
if (success) {
|
|
||||||
std::ostringstream max_sessions_stream;
|
std::ostringstream max_sessions_stream;
|
||||||
max_sessions_stream << maximum_number_of_sessions;
|
max_sessions_stream << maximum_number_of_sessions;
|
||||||
(*key_info)[QUERY_KEY_MAX_NUMBER_OF_SESSIONS] =
|
*value = max_sessions_stream.str();
|
||||||
max_sessions_stream.str();
|
} else if (key == QUERY_KEY_OEMCRYPTO_API_VERSION) {
|
||||||
}
|
uint32_t api_version;
|
||||||
|
if (!crypto_session.GetApiVersion(&api_version)) {
|
||||||
|
LOGW("CdmEngine::QueryStatus: GetApiVersion failed");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t api_version;
|
|
||||||
success = crypto_session.GetApiVersion(&api_version);
|
|
||||||
if (success) {
|
|
||||||
std::ostringstream api_version_stream;
|
std::ostringstream api_version_stream;
|
||||||
api_version_stream << api_version;
|
api_version_stream << api_version;
|
||||||
(*key_info)[QUERY_KEY_OEMCRYPTO_API_VERSION] = api_version_stream.str();
|
*value = api_version_stream.str();
|
||||||
|
} else {
|
||||||
|
LOGW("CdmEngine::QueryStatus: Unknown status requested, key = %s",
|
||||||
|
key.c_str());
|
||||||
|
return INVALID_QUERY_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
|||||||
|
|
||||||
// Query system information
|
// Query system information
|
||||||
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
|
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
|
||||||
CdmQueryMap* key_info);
|
const std::string& key,
|
||||||
|
std::string* value);
|
||||||
// Query session information
|
// Query session information
|
||||||
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
|
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
|
||||||
CdmQueryMap* key_info);
|
CdmQueryMap* key_info);
|
||||||
|
|||||||
@@ -121,8 +121,9 @@ CdmResponseType WvContentDecryptionModule::RemoveKeys(
|
|||||||
|
|
||||||
CdmResponseType WvContentDecryptionModule::QueryStatus(
|
CdmResponseType WvContentDecryptionModule::QueryStatus(
|
||||||
SecurityLevel security_level,
|
SecurityLevel security_level,
|
||||||
CdmQueryMap* key_info) {
|
const std::string& key,
|
||||||
return cdm_engine_->QueryStatus(security_level, key_info);
|
std::string* value) {
|
||||||
|
return cdm_engine_->QueryStatus(security_level, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType WvContentDecryptionModule::QuerySessionStatus(
|
CdmResponseType WvContentDecryptionModule::QuerySessionStatus(
|
||||||
|
|||||||
@@ -2051,14 +2051,12 @@ TEST_F(WvCdmRequestLicenseTest, UsageReleaseAllTest) {
|
|||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, QueryUnmodifiedSessionStatus) {
|
TEST_F(WvCdmRequestLicenseTest, QueryUnmodifiedSessionStatus) {
|
||||||
// Test that the global value is returned when no properties are modifying it.
|
// Test that the global value is returned when no properties are modifying it.
|
||||||
CdmQueryMap system_query_info;
|
std::string security_level;
|
||||||
CdmQueryMap::iterator system_itr;
|
|
||||||
ASSERT_EQ(wvcdm::NO_ERROR,
|
ASSERT_EQ(wvcdm::NO_ERROR,
|
||||||
decryptor_.QueryStatus(kLevelDefault, &system_query_info));
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
system_itr = system_query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
wvcdm::QUERY_KEY_SECURITY_LEVEL,
|
||||||
ASSERT_TRUE(system_itr != system_query_info.end());
|
&security_level));
|
||||||
|
EXPECT_EQ(GetSecurityLevel(NULL), security_level);
|
||||||
EXPECT_EQ(system_itr->second, GetSecurityLevel(NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, QueryModifiedSessionStatus) {
|
TEST_F(WvCdmRequestLicenseTest, QueryModifiedSessionStatus) {
|
||||||
@@ -2121,68 +2119,72 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyStatus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
||||||
CdmQueryMap query_info;
|
std::string value;
|
||||||
CdmQueryMap::iterator itr;
|
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
decryptor_.QueryStatus(kLevelDefault, &query_info));
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
|
wvcdm::QUERY_KEY_SECURITY_LEVEL, &value));
|
||||||
|
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
EXPECT_EQ(2u, value.size());
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
EXPECT_TRUE(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3 == value ||
|
||||||
EXPECT_EQ(2u, itr->second.size());
|
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1 == value);
|
||||||
EXPECT_EQ(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3.at(0), itr->second.at(0));
|
|
||||||
|
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_DEVICE_ID);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(kLevelDefault, wvcdm::QUERY_KEY_DEVICE_ID,
|
||||||
EXPECT_GT(itr->second.size(), 0u);
|
&value));
|
||||||
|
EXPECT_LT(0u, value.size());
|
||||||
|
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_SYSTEM_ID);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(kLevelDefault, wvcdm::QUERY_KEY_SYSTEM_ID,
|
||||||
std::istringstream ss(itr->second);
|
&value));
|
||||||
|
std::istringstream ss(value);
|
||||||
uint32_t system_id;
|
uint32_t system_id;
|
||||||
ss >> system_id;
|
ss >> system_id;
|
||||||
ASSERT_FALSE(ss.fail());
|
ASSERT_FALSE(ss.fail());
|
||||||
EXPECT_TRUE(ss.eof());
|
EXPECT_TRUE(ss.eof());
|
||||||
|
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_PROVISIONING_ID);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
EXPECT_EQ(16u, itr->second.size());
|
wvcdm::QUERY_KEY_PROVISIONING_ID, &value));
|
||||||
|
EXPECT_EQ(16u, value.size());
|
||||||
|
|
||||||
itr = query_info.find(QUERY_KEY_CURRENT_HDCP_LEVEL);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(
|
||||||
EXPECT_TRUE(itr->second == QUERY_VALUE_UNPROTECTED ||
|
kLevelDefault, wvcdm::QUERY_KEY_CURRENT_HDCP_LEVEL, &value));
|
||||||
itr->second == QUERY_VALUE_HDCP_V1 ||
|
EXPECT_TRUE(
|
||||||
itr->second == QUERY_VALUE_HDCP_V2_0 ||
|
value == QUERY_VALUE_UNPROTECTED || value == QUERY_VALUE_HDCP_V1 ||
|
||||||
itr->second == QUERY_VALUE_HDCP_V2_1 ||
|
value == QUERY_VALUE_HDCP_V2_0 || value == QUERY_VALUE_HDCP_V2_1 ||
|
||||||
itr->second == QUERY_VALUE_HDCP_V2_2 ||
|
value == QUERY_VALUE_HDCP_V2_2 || value == QUERY_VALUE_DISCONNECTED);
|
||||||
itr->second == QUERY_VALUE_DISCONNECTED);
|
|
||||||
|
|
||||||
itr = query_info.find(QUERY_KEY_MAX_HDCP_LEVEL);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
EXPECT_TRUE(itr->second == QUERY_VALUE_UNPROTECTED ||
|
wvcdm::QUERY_KEY_MAX_HDCP_LEVEL, &value));
|
||||||
itr->second == QUERY_VALUE_HDCP_V1 ||
|
EXPECT_TRUE(
|
||||||
itr->second == QUERY_VALUE_HDCP_V2_0 ||
|
value == QUERY_VALUE_UNPROTECTED || value == QUERY_VALUE_HDCP_V1 ||
|
||||||
itr->second == QUERY_VALUE_HDCP_V2_1 ||
|
value == QUERY_VALUE_HDCP_V2_0 || value == QUERY_VALUE_HDCP_V2_1 ||
|
||||||
itr->second == QUERY_VALUE_HDCP_V2_2 ||
|
value == QUERY_VALUE_HDCP_V2_2 || value == QUERY_VALUE_DISCONNECTED);
|
||||||
itr->second == QUERY_VALUE_DISCONNECTED);
|
|
||||||
|
|
||||||
itr = query_info.find(QUERY_KEY_USAGE_SUPPORT);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
EXPECT_TRUE(itr->second == QUERY_VALUE_TRUE ||
|
wvcdm::QUERY_KEY_USAGE_SUPPORT, &value));
|
||||||
itr->second == QUERY_VALUE_FALSE);
|
EXPECT_TRUE(value == QUERY_VALUE_TRUE || value == QUERY_VALUE_FALSE);
|
||||||
|
|
||||||
itr = query_info.find(QUERY_KEY_NUMBER_OF_OPEN_SESSIONS);
|
EXPECT_EQ(
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
|
wvcdm::QUERY_KEY_NUMBER_OF_OPEN_SESSIONS, &value));
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str(itr->second);
|
ss.str(value);
|
||||||
uint32_t open_sessions;
|
uint32_t open_sessions;
|
||||||
ss >> open_sessions;
|
ss >> open_sessions;
|
||||||
ASSERT_FALSE(ss.fail());
|
ASSERT_FALSE(ss.fail());
|
||||||
EXPECT_TRUE(ss.eof());
|
EXPECT_TRUE(ss.eof());
|
||||||
|
|
||||||
itr = query_info.find(QUERY_KEY_MAX_NUMBER_OF_SESSIONS);
|
EXPECT_EQ(
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
|
wvcdm::QUERY_KEY_MAX_NUMBER_OF_SESSIONS, &value));
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str(itr->second);
|
ss.str(value);
|
||||||
uint32_t max_sessions;
|
uint32_t max_sessions;
|
||||||
ss >> max_sessions;
|
ss >> max_sessions;
|
||||||
ASSERT_FALSE(ss.fail());
|
ASSERT_FALSE(ss.fail());
|
||||||
@@ -2190,10 +2192,11 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
|||||||
EXPECT_LE(open_sessions, max_sessions);
|
EXPECT_LE(open_sessions, max_sessions);
|
||||||
EXPECT_LE(8u, max_sessions);
|
EXPECT_LE(8u, max_sessions);
|
||||||
|
|
||||||
itr = query_info.find(QUERY_KEY_OEMCRYPTO_API_VERSION);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(
|
||||||
|
kLevelDefault, wvcdm::QUERY_KEY_OEMCRYPTO_API_VERSION, &value));
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str(itr->second);
|
ss.str(value);
|
||||||
uint32_t api_version;
|
uint32_t api_version;
|
||||||
ss >> api_version;
|
ss >> api_version;
|
||||||
ASSERT_FALSE(ss.fail());
|
ASSERT_FALSE(ss.fail());
|
||||||
@@ -2202,50 +2205,94 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) {
|
TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) {
|
||||||
CdmQueryMap query_info, query_info_default;
|
std::string value;
|
||||||
CdmQueryMap::iterator itr;
|
EXPECT_EQ(
|
||||||
|
wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(kLevel3, wvcdm::QUERY_KEY_SECURITY_LEVEL, &value));
|
||||||
|
EXPECT_EQ(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3, value);
|
||||||
|
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(
|
||||||
|
kLevel3, wvcdm::QUERY_KEY_DEVICE_ID, &value));
|
||||||
|
EXPECT_LT(0u, value.size());
|
||||||
|
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
decryptor_.QueryStatus(kLevel3, &query_info));
|
decryptor_.QueryStatus(kLevelDefault, wvcdm::QUERY_KEY_SYSTEM_ID,
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
&value));
|
||||||
decryptor_.QueryStatus(kLevelDefault, &query_info_default));
|
std::istringstream ss(value);
|
||||||
|
uint32_t default_system_id;
|
||||||
|
ss >> default_system_id;
|
||||||
|
ASSERT_FALSE(ss.fail());
|
||||||
|
EXPECT_TRUE(ss.eof());
|
||||||
|
|
||||||
EXPECT_THAT(query_info, Contains(Pair(wvcdm::QUERY_KEY_SECURITY_LEVEL,
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(
|
||||||
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3)));
|
kLevel3, wvcdm::QUERY_KEY_SYSTEM_ID, &value));
|
||||||
|
ss.clear();
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_DEVICE_ID);
|
ss.str(value);
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
|
||||||
EXPECT_GT(itr->second.size(), 0u);
|
|
||||||
|
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_SYSTEM_ID);
|
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
|
||||||
std::istringstream ss(itr->second);
|
|
||||||
uint32_t system_id;
|
uint32_t system_id;
|
||||||
ss >> system_id;
|
ss >> system_id;
|
||||||
ASSERT_FALSE(ss.fail());
|
ASSERT_FALSE(ss.fail());
|
||||||
EXPECT_TRUE(ss.eof());
|
EXPECT_TRUE(ss.eof());
|
||||||
|
EXPECT_NE(default_system_id, system_id);
|
||||||
|
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_PROVISIONING_ID);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
decryptor_.QueryStatus(kLevel3, wvcdm::QUERY_KEY_PROVISIONING_ID,
|
||||||
EXPECT_EQ(16u, itr->second.size());
|
&value));
|
||||||
|
EXPECT_EQ(16u, value.size());
|
||||||
|
|
||||||
itr = query_info_default.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info_default.end());
|
decryptor_.QueryStatus(kLevel3, wvcdm::QUERY_KEY_CURRENT_HDCP_LEVEL,
|
||||||
EXPECT_EQ(2u, itr->second.size());
|
&value));
|
||||||
EXPECT_EQ(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3.at(0), itr->second.at(0));
|
EXPECT_TRUE(
|
||||||
|
value == QUERY_VALUE_UNPROTECTED || value == QUERY_VALUE_HDCP_V1 ||
|
||||||
|
value == QUERY_VALUE_HDCP_V2_0 || value == QUERY_VALUE_HDCP_V2_1 ||
|
||||||
|
value == QUERY_VALUE_HDCP_V2_2 || value == QUERY_VALUE_DISCONNECTED);
|
||||||
|
|
||||||
if (wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3.compare(itr->second) != 0) {
|
EXPECT_EQ(
|
||||||
itr = query_info_default.find(wvcdm::QUERY_KEY_SYSTEM_ID);
|
wvcdm::NO_ERROR,
|
||||||
ASSERT_TRUE(itr != query_info_default.end());
|
decryptor_.QueryStatus(kLevel3, wvcdm::QUERY_KEY_MAX_HDCP_LEVEL, &value));
|
||||||
std::istringstream ss(itr->second);
|
EXPECT_TRUE(
|
||||||
uint32_t default_system_id;
|
value == QUERY_VALUE_UNPROTECTED || value == QUERY_VALUE_HDCP_V1 ||
|
||||||
ss >> system_id;
|
value == QUERY_VALUE_HDCP_V2_0 || value == QUERY_VALUE_HDCP_V2_1 ||
|
||||||
ASSERT_FALSE(ss.fail());
|
value == QUERY_VALUE_HDCP_V2_2 || value == QUERY_VALUE_DISCONNECTED);
|
||||||
EXPECT_TRUE(ss.eof());
|
|
||||||
EXPECT_NE(system_id, default_system_id);
|
EXPECT_EQ(
|
||||||
}
|
wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(kLevel3, wvcdm::QUERY_KEY_USAGE_SUPPORT, &value));
|
||||||
|
EXPECT_TRUE(value == QUERY_VALUE_TRUE || value == QUERY_VALUE_FALSE);
|
||||||
|
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(
|
||||||
|
kLevel3, wvcdm::QUERY_KEY_NUMBER_OF_OPEN_SESSIONS, &value));
|
||||||
|
ss.clear();
|
||||||
|
ss.str(value);
|
||||||
|
uint32_t open_sessions;
|
||||||
|
ss >> open_sessions;
|
||||||
|
ASSERT_FALSE(ss.fail());
|
||||||
|
EXPECT_TRUE(ss.eof());
|
||||||
|
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(
|
||||||
|
kLevel3, wvcdm::QUERY_KEY_MAX_NUMBER_OF_SESSIONS, &value));
|
||||||
|
ss.clear();
|
||||||
|
ss.str(value);
|
||||||
|
uint32_t max_sessions;
|
||||||
|
ss >> max_sessions;
|
||||||
|
ASSERT_FALSE(ss.fail());
|
||||||
|
EXPECT_TRUE(ss.eof());
|
||||||
|
EXPECT_LE(open_sessions, max_sessions);
|
||||||
|
EXPECT_LE(8u, max_sessions);
|
||||||
|
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(
|
||||||
|
kLevel3, wvcdm::QUERY_KEY_OEMCRYPTO_API_VERSION, &value));
|
||||||
|
ss.clear();
|
||||||
|
ss.str(value);
|
||||||
|
uint32_t api_version;
|
||||||
|
ss >> api_version;
|
||||||
|
ASSERT_FALSE(ss.fail());
|
||||||
|
EXPECT_TRUE(ss.eof());
|
||||||
|
EXPECT_LE(10u, api_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
||||||
Unprovision();
|
Unprovision();
|
||||||
Provision(kLevelDefault);
|
Provision(kLevelDefault);
|
||||||
@@ -2280,18 +2327,16 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
|
|||||||
|
|
||||||
GetOfflineConfiguration(&key_id, &client_auth);
|
GetOfflineConfiguration(&key_id, &client_auth);
|
||||||
|
|
||||||
CdmQueryMap query_info;
|
std::string level;
|
||||||
CdmQueryMap::iterator itr;
|
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
decryptor_.QueryStatus(kLevelDefault, &query_info));
|
decryptor_.QueryStatus(kLevelDefault,
|
||||||
itr = query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
wvcdm::QUERY_KEY_SECURITY_LEVEL,
|
||||||
ASSERT_TRUE(itr != query_info.end());
|
&level));
|
||||||
EXPECT_EQ(2u, itr->second.size());
|
EXPECT_TRUE(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3 == level ||
|
||||||
EXPECT_TRUE(itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3) == 0 ||
|
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1 == level);
|
||||||
itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1) == 0);
|
|
||||||
|
|
||||||
CdmSecurityLevel security_level =
|
CdmSecurityLevel security_level =
|
||||||
(itr->second.compare(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1) == 0)
|
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1 == level
|
||||||
? kSecurityLevelL1
|
? kSecurityLevelL1
|
||||||
: kSecurityLevelL3;
|
: kSecurityLevelL3;
|
||||||
|
|
||||||
|
|||||||
@@ -880,18 +880,13 @@ status_t WVDrmPlugin::queryProperty(const std::string& property,
|
|||||||
status_t WVDrmPlugin::queryProperty(SecurityLevel securityLevel,
|
status_t WVDrmPlugin::queryProperty(SecurityLevel securityLevel,
|
||||||
const std::string& property,
|
const std::string& property,
|
||||||
std::string& stringValue) const {
|
std::string& stringValue) const {
|
||||||
CdmQueryMap status;
|
CdmResponseType res =
|
||||||
CdmResponseType res = mCDM->QueryStatus(securityLevel, &status);
|
mCDM->QueryStatus(securityLevel, property, &stringValue);
|
||||||
|
|
||||||
if (res != wvcdm::NO_ERROR) {
|
if (res != wvcdm::NO_ERROR) {
|
||||||
ALOGE("Error querying CDM status: %u", res);
|
ALOGE("Error querying CDM status: %u", res);
|
||||||
return mapCdmResponseType(res);
|
|
||||||
} else if (!status.count(property)) {
|
|
||||||
ALOGE("CDM did not report %s", property.c_str());
|
|
||||||
return kErrorCDMGeneric;
|
|
||||||
}
|
}
|
||||||
stringValue = status[property];
|
return mapCdmResponseType(res);
|
||||||
return android::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t WVDrmPlugin::queryProperty(const std::string& property,
|
status_t WVDrmPlugin::queryProperty(const std::string& property,
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ class MockCDM : public WvContentDecryptionModule {
|
|||||||
MOCK_METHOD2(RestoreKey, CdmResponseType(const CdmSessionId&,
|
MOCK_METHOD2(RestoreKey, CdmResponseType(const CdmSessionId&,
|
||||||
const CdmKeySetId&));
|
const CdmKeySetId&));
|
||||||
|
|
||||||
MOCK_METHOD2(QueryStatus, CdmResponseType(SecurityLevel, CdmQueryMap*));
|
MOCK_METHOD3(QueryStatus, CdmResponseType(SecurityLevel, const std::string&,
|
||||||
|
std::string*));
|
||||||
|
|
||||||
MOCK_METHOD2(QueryKeyStatus, CdmResponseType(const CdmSessionId&,
|
MOCK_METHOD2(QueryKeyStatus, CdmResponseType(const CdmSessionId&,
|
||||||
CdmQueryMap*));
|
CdmQueryMap*));
|
||||||
@@ -808,45 +809,40 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
|
|||||||
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||||
|
|
||||||
static const string uniqueId = "The Universe";
|
static const string uniqueId = "The Universe";
|
||||||
CdmQueryMap deviceIDMap;
|
|
||||||
deviceIDMap[QUERY_KEY_DEVICE_ID] = uniqueId;
|
|
||||||
|
|
||||||
static const string systemId = "42";
|
static const string systemId = "42";
|
||||||
CdmQueryMap systemIDMap;
|
|
||||||
systemIDMap[QUERY_KEY_SYSTEM_ID] = systemId;
|
|
||||||
|
|
||||||
static const string provisioningId("Life\0&Everything", 16);
|
static const string provisioningId("Life\0&Everything", 16);
|
||||||
CdmQueryMap provisioningIDMap;
|
|
||||||
provisioningIDMap[QUERY_KEY_PROVISIONING_ID] = provisioningId;
|
|
||||||
|
|
||||||
static const string openSessions = "15";
|
static const string openSessions = "15";
|
||||||
CdmQueryMap openSessionsMap;
|
|
||||||
openSessionsMap[QUERY_KEY_NUMBER_OF_OPEN_SESSIONS] = openSessions;
|
|
||||||
|
|
||||||
static const string maxSessions = "18";
|
static const string maxSessions = "18";
|
||||||
CdmQueryMap maxSessionsMap;
|
|
||||||
maxSessionsMap[QUERY_KEY_MAX_NUMBER_OF_SESSIONS] = maxSessions;
|
|
||||||
|
|
||||||
static const string oemCryptoApiVersion = "10";
|
static const string oemCryptoApiVersion = "10";
|
||||||
CdmQueryMap oemCryptoApiVersionMap;
|
|
||||||
oemCryptoApiVersionMap[QUERY_KEY_OEMCRYPTO_API_VERSION] = oemCryptoApiVersion;
|
|
||||||
|
|
||||||
EXPECT_CALL(*cdm, QueryStatus(_, _))
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(l1Map),
|
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
|
||||||
Return(wvcdm::NO_ERROR)))
|
Return(wvcdm::NO_ERROR)))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(l3Map),
|
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L3),
|
||||||
Return(wvcdm::NO_ERROR)))
|
Return(wvcdm::NO_ERROR)));
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(deviceIDMap),
|
|
||||||
Return(wvcdm::NO_ERROR)))
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(systemIDMap),
|
.WillOnce(DoAll(SetArgPointee<2>(uniqueId),
|
||||||
Return(wvcdm::NO_ERROR)))
|
Return(wvcdm::NO_ERROR)));
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(provisioningIDMap),
|
|
||||||
Return(wvcdm::NO_ERROR)))
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SYSTEM_ID, _))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(openSessionsMap),
|
.WillOnce(DoAll(SetArgPointee<2>(systemId),
|
||||||
Return(wvcdm::NO_ERROR)))
|
Return(wvcdm::NO_ERROR)));
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(maxSessionsMap),
|
|
||||||
Return(wvcdm::NO_ERROR)))
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_PROVISIONING_ID, _))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(oemCryptoApiVersionMap),
|
.WillOnce(DoAll(SetArgPointee<2>(provisioningId),
|
||||||
|
Return(wvcdm::NO_ERROR)));
|
||||||
|
|
||||||
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_NUMBER_OF_OPEN_SESSIONS, _))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<2>(openSessions),
|
||||||
|
Return(wvcdm::NO_ERROR)));
|
||||||
|
|
||||||
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_MAX_NUMBER_OF_SESSIONS, _))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<2>(maxSessions),
|
||||||
|
Return(wvcdm::NO_ERROR)));
|
||||||
|
|
||||||
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_OEMCRYPTO_API_VERSION, _))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<2>(oemCryptoApiVersion),
|
||||||
Return(wvcdm::NO_ERROR)));
|
Return(wvcdm::NO_ERROR)));
|
||||||
|
|
||||||
String8 stringResult;
|
String8 stringResult;
|
||||||
@@ -1475,9 +1471,6 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
|
|||||||
|
|
||||||
const CdmClientPropertySet* propertySet = NULL;
|
const CdmClientPropertySet* propertySet = NULL;
|
||||||
|
|
||||||
CdmQueryMap l3Map;
|
|
||||||
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
|
||||||
|
|
||||||
// Provide expected mock behavior
|
// Provide expected mock behavior
|
||||||
{
|
{
|
||||||
// Provide expected behavior in response to OpenSession and store the
|
// Provide expected behavior in response to OpenSession and store the
|
||||||
@@ -1488,8 +1481,8 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
|
|||||||
Return(wvcdm::NO_ERROR)));
|
Return(wvcdm::NO_ERROR)));
|
||||||
|
|
||||||
// Provide expected behavior when plugin queries for the security level
|
// Provide expected behavior when plugin queries for the security level
|
||||||
EXPECT_CALL(*cdm, QueryStatus(_, _))
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
|
||||||
.WillRepeatedly(DoAll(SetArgPointee<1>(l3Map),
|
.WillRepeatedly(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L3),
|
||||||
Return(wvcdm::NO_ERROR)));
|
Return(wvcdm::NO_ERROR)));
|
||||||
|
|
||||||
// Provide expected behavior when plugin requests session control info
|
// Provide expected behavior when plugin requests session control info
|
||||||
@@ -1564,16 +1557,10 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
|
|||||||
|
|
||||||
const CdmClientPropertySet* propertySet = NULL;
|
const CdmClientPropertySet* propertySet = NULL;
|
||||||
|
|
||||||
CdmQueryMap l1Map;
|
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
|
||||||
l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
|
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L3),
|
||||||
|
|
||||||
CdmQueryMap l3Map;
|
|
||||||
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
|
||||||
|
|
||||||
EXPECT_CALL(*cdm, QueryStatus(_, _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(l3Map),
|
|
||||||
Return(wvcdm::NO_ERROR)))
|
Return(wvcdm::NO_ERROR)))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(l1Map),
|
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
|
||||||
Return(wvcdm::NO_ERROR)));
|
Return(wvcdm::NO_ERROR)));
|
||||||
|
|
||||||
// Provide expected mock behavior
|
// Provide expected mock behavior
|
||||||
|
|||||||
Reference in New Issue
Block a user