Respect Client Properties when reporting CDM Status
[ Merge from go/wvgerrit/14286 ] CDM now reports status information associated with the specified security level. Earlier information would be reported from the default security level. b/18709693 Change-Id: I7a01e8ea9773b56951c207437ce85e567fd32b09
This commit is contained in:
@@ -98,7 +98,8 @@ class CdmEngine {
|
||||
const CdmKeyResponse& key_data);
|
||||
|
||||
// Query system information
|
||||
virtual CdmResponseType QueryStatus(CdmQueryMap* info);
|
||||
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
|
||||
CdmQueryMap* info);
|
||||
|
||||
// Query session information
|
||||
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
#define WVCDM_CORE_OEMCRYPTO_ADAPTER_H_
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
enum SecurityLevel { kLevelDefault, kLevel3 };
|
||||
|
||||
// This attempts to open a session at the desired security level.
|
||||
// If one level is not available, the other will be used instead.
|
||||
OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session,
|
||||
|
||||
@@ -185,6 +185,7 @@ enum CdmResponseType {
|
||||
CLIENT_ID_AES_ENCRYPT_ERROR,
|
||||
CLIENT_ID_RSA_INIT_ERROR,
|
||||
CLIENT_ID_RSA_ENCRYPT_ERROR,
|
||||
INVALID_QUERY_STATUS,
|
||||
};
|
||||
|
||||
enum CdmKeyStatus {
|
||||
@@ -206,6 +207,11 @@ enum CdmLicenseType {
|
||||
kLicenseTypeRelease
|
||||
};
|
||||
|
||||
enum SecurityLevel {
|
||||
kLevelDefault,
|
||||
kLevel3
|
||||
};
|
||||
|
||||
enum CdmSecurityLevel {
|
||||
kSecurityLevelUninitialized,
|
||||
kSecurityLevelL1,
|
||||
|
||||
@@ -393,9 +393,14 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
|
||||
return KEY_ADDED;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
|
||||
CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
CdmQueryMap* key_info) {
|
||||
LOGI("CdmEngine::QueryStatus");
|
||||
CryptoSession crypto_session;
|
||||
if (security_level == kLevel3) {
|
||||
CdmResponseType status = crypto_session.Open(kLevel3);
|
||||
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;
|
||||
|
||||
@@ -60,7 +60,8 @@ class WvContentDecryptionModule : public TimerHandler {
|
||||
virtual CdmResponseType RemoveKeys(const CdmSessionId& session_id);
|
||||
|
||||
// Query system information
|
||||
virtual CdmResponseType QueryStatus(CdmQueryMap* key_info);
|
||||
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
|
||||
CdmQueryMap* key_info);
|
||||
|
||||
// Query session information
|
||||
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
|
||||
|
||||
@@ -117,8 +117,10 @@ CdmResponseType WvContentDecryptionModule::RemoveKeys(
|
||||
return cdm_engine_->RemoveKeys(session_id);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::QueryStatus(CdmQueryMap* key_info) {
|
||||
return cdm_engine_->QueryStatus(key_info);
|
||||
CdmResponseType WvContentDecryptionModule::QueryStatus(
|
||||
SecurityLevel security_level,
|
||||
CdmQueryMap* key_info) {
|
||||
return cdm_engine_->QueryStatus(security_level, key_info);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::QuerySessionStatus(
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
using ::testing::_;
|
||||
using ::testing::AllOf;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::Contains;
|
||||
using ::testing::Each;
|
||||
using ::testing::IsEmpty;
|
||||
using ::testing::Not;
|
||||
@@ -1723,7 +1724,8 @@ TEST_F(WvCdmRequestLicenseTest, QueryUnmodifiedSessionStatus) {
|
||||
// Test that the global value is returned when no properties are modifying it.
|
||||
CdmQueryMap system_query_info;
|
||||
CdmQueryMap::iterator system_itr;
|
||||
ASSERT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(&system_query_info));
|
||||
ASSERT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.QueryStatus(kLevelDefault, &system_query_info));
|
||||
system_itr = system_query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
||||
ASSERT_TRUE(system_itr != system_query_info.end());
|
||||
|
||||
@@ -1790,7 +1792,8 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyStatus) {
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
||||
CdmQueryMap query_info;
|
||||
CdmQueryMap::iterator itr;
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(&query_info));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.QueryStatus(kLevelDefault, &query_info));
|
||||
|
||||
itr = query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
||||
ASSERT_TRUE(itr != query_info.end());
|
||||
@@ -1813,6 +1816,49 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
||||
EXPECT_EQ(16u, itr->second.size());
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) {
|
||||
CdmQueryMap query_info, query_info_default;
|
||||
CdmQueryMap::iterator itr;
|
||||
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.QueryStatus(kLevel3, &query_info));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.QueryStatus(kLevelDefault, &query_info_default));
|
||||
|
||||
EXPECT_THAT(query_info, Contains(Pair(wvcdm::QUERY_KEY_SECURITY_LEVEL,
|
||||
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3)));
|
||||
|
||||
itr = query_info.find(wvcdm::QUERY_KEY_DEVICE_ID);
|
||||
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;
|
||||
EXPECT_TRUE(ss >> system_id);
|
||||
EXPECT_TRUE(ss.eof());
|
||||
|
||||
itr = query_info.find(wvcdm::QUERY_KEY_PROVISIONING_ID);
|
||||
ASSERT_TRUE(itr != query_info.end());
|
||||
EXPECT_EQ(16u, itr->second.size());
|
||||
|
||||
itr = query_info_default.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
||||
ASSERT_TRUE(itr != query_info_default.end());
|
||||
EXPECT_EQ(2u, itr->second.size());
|
||||
EXPECT_EQ(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3.at(0), itr->second.at(0));
|
||||
|
||||
if (wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3.compare(itr->second) != 0) {
|
||||
itr = query_info_default.find(wvcdm::QUERY_KEY_SYSTEM_ID);
|
||||
ASSERT_TRUE(itr != query_info_default.end());
|
||||
std::istringstream ss(itr->second);
|
||||
uint32_t default_system_id;
|
||||
EXPECT_TRUE(ss >> system_id);
|
||||
EXPECT_TRUE(ss.eof());
|
||||
EXPECT_NE(system_id, default_system_id);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
||||
Unprovision();
|
||||
Provision(kLevelDefault);
|
||||
@@ -1848,7 +1894,8 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
|
||||
|
||||
CdmQueryMap query_info;
|
||||
CdmQueryMap::iterator itr;
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QueryStatus(&query_info));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.QueryStatus(kLevelDefault, &query_info));
|
||||
itr = query_info.find(wvcdm::QUERY_KEY_SECURITY_LEVEL);
|
||||
ASSERT_TRUE(itr != query_info.end());
|
||||
EXPECT_EQ(2u, itr->second.size());
|
||||
|
||||
@@ -160,7 +160,8 @@ enum {
|
||||
kClientIdAesEncryptError = ERROR_DRM_VENDOR_MIN + 144,
|
||||
kClientIdRsaInitError = ERROR_DRM_VENDOR_MIN + 145,
|
||||
kClientIdRsaEncryptError = ERROR_DRM_VENDOR_MIN + 146,
|
||||
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 146,
|
||||
kInvalidQueryStatus = ERROR_DRM_VENDOR_MIN + 147,
|
||||
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 147,
|
||||
|
||||
// Used by crypto test mode
|
||||
kErrorTestMode = ERROR_DRM_VENDOR_MAX,
|
||||
|
||||
@@ -309,6 +309,8 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) {
|
||||
// KEY_ERROR is used by the CDM to mean just about any kind of error, not
|
||||
// just license errors, so it is mapped to the generic response.
|
||||
return kErrorCDMGeneric;
|
||||
case wvcdm::INVALID_QUERY_STATUS:
|
||||
return kInvalidQueryStatus;
|
||||
case wvcdm::UNKNOWN_ERROR:
|
||||
return android::ERROR_DRM_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -254,7 +254,11 @@ class WVDrmPlugin : public android::DrmPlugin,
|
||||
map<CdmSessionId, CryptoSession> mCryptoSessions;
|
||||
|
||||
status_t queryProperty(const std::string& property,
|
||||
std::string& string_value) const;
|
||||
std::string& stringValue) const;
|
||||
|
||||
status_t queryProperty(wvcdm::SecurityLevel securityLevel,
|
||||
const std::string& property,
|
||||
std::string& stringValue) const;
|
||||
|
||||
status_t queryProperty(const std::string& property,
|
||||
String8& string8_value) const;
|
||||
|
||||
@@ -537,7 +537,8 @@ status_t WVDrmPlugin::setPropertyString(const String8& name,
|
||||
// We must be sure we CAN set the security level to L1.
|
||||
std::string current_security_level;
|
||||
status_t status =
|
||||
queryProperty(QUERY_KEY_SECURITY_LEVEL, current_security_level);
|
||||
queryProperty(kLevelDefault, QUERY_KEY_SECURITY_LEVEL,
|
||||
current_security_level);
|
||||
if (status != android::OK) return status;
|
||||
|
||||
if (current_security_level != QUERY_VALUE_SECURITY_LEVEL_L1) {
|
||||
@@ -880,9 +881,20 @@ void WVDrmPlugin::OnExpirationUpdate(const CdmSessionId& cdmSessionId,
|
||||
}
|
||||
|
||||
status_t WVDrmPlugin::queryProperty(const std::string& property,
|
||||
std::string& string_value) const {
|
||||
std::string& stringValue) const {
|
||||
SecurityLevel securityLevel =
|
||||
mPropertySet.security_level().compare(QUERY_VALUE_SECURITY_LEVEL_L3) == 0
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
return queryProperty(securityLevel, property, stringValue);
|
||||
}
|
||||
|
||||
status_t WVDrmPlugin::queryProperty(SecurityLevel securityLevel,
|
||||
const std::string& property,
|
||||
std::string& stringValue) const {
|
||||
CdmQueryMap status;
|
||||
CdmResponseType res = mCDM->QueryStatus(&status);
|
||||
CdmResponseType res = mCDM->QueryStatus(securityLevel, &status);
|
||||
|
||||
if (res != wvcdm::NO_ERROR) {
|
||||
ALOGE("Error querying CDM status: %u", res);
|
||||
return mapCdmResponseType(res);
|
||||
@@ -890,7 +902,7 @@ status_t WVDrmPlugin::queryProperty(const std::string& property,
|
||||
ALOGE("CDM did not report %s", property.c_str());
|
||||
return kErrorCDMGeneric;
|
||||
}
|
||||
string_value = status[property];
|
||||
stringValue = status[property];
|
||||
return android::OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class MockCDM : public WvContentDecryptionModule {
|
||||
MOCK_METHOD2(RestoreKey, CdmResponseType(const CdmSessionId&,
|
||||
const CdmKeySetId&));
|
||||
|
||||
MOCK_METHOD1(QueryStatus, CdmResponseType(CdmQueryMap*));
|
||||
MOCK_METHOD2(QueryStatus, CdmResponseType(SecurityLevel, CdmQueryMap*));
|
||||
|
||||
MOCK_METHOD2(QueryKeyStatus, CdmResponseType(const CdmSessionId&,
|
||||
CdmQueryMap*));
|
||||
@@ -812,20 +812,20 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
|
||||
CdmQueryMap maxSessionsMap;
|
||||
maxSessionsMap[QUERY_KEY_MAX_NUMBER_OF_SESSIONS] = maxSessions;
|
||||
|
||||
EXPECT_CALL(cdm, QueryStatus(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(l1Map),
|
||||
EXPECT_CALL(cdm, QueryStatus(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l1Map),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(l3Map),
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l3Map),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(deviceIDMap),
|
||||
.WillOnce(DoAll(SetArgPointee<1>(deviceIDMap),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(systemIDMap),
|
||||
.WillOnce(DoAll(SetArgPointee<1>(systemIDMap),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(provisioningIDMap),
|
||||
.WillOnce(DoAll(SetArgPointee<1>(provisioningIDMap),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(openSessionsMap),
|
||||
.WillOnce(DoAll(SetArgPointee<1>(openSessionsMap),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(maxSessionsMap),
|
||||
.WillOnce(DoAll(SetArgPointee<1>(maxSessionsMap),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
String8 stringResult;
|
||||
@@ -1457,8 +1457,8 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// Provide expected behavior when plugin queries for the security level
|
||||
EXPECT_CALL(cdm, QueryStatus(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(l3Map),
|
||||
EXPECT_CALL(cdm, QueryStatus(_, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<1>(l3Map),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// Provide expected behavior when plugin requests session control info
|
||||
@@ -1539,10 +1539,10 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
|
||||
CdmQueryMap l3Map;
|
||||
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||
|
||||
EXPECT_CALL(cdm, QueryStatus(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(l3Map),
|
||||
EXPECT_CALL(cdm, QueryStatus(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l3Map),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(l1Map),
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l1Map),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// Provide expected mock behavior
|
||||
|
||||
Reference in New Issue
Block a user