Allow Resetting Device to L1 from L3

This change allows the security level, after it is forced from L1 to
L3, to be reset back to L1 using the string "L1" instead of only
allowing the reset string. (the empty string)

Merge of https://widevine-internal-review.googlesource.com/#/c/8928/
from the widevine cdm repo.

Bug: 10651521
Change-Id: I39797bb0a51b82db3543aec800a08ad36e11d661
This commit is contained in:
John "Juce" Bruce
2014-03-21 17:13:28 -07:00
committed by John Bruce
parent 0a2c9889b0
commit 55e8f29b40
2 changed files with 73 additions and 16 deletions

View File

@@ -462,8 +462,26 @@ status_t WVDrmPlugin::setPropertyString(const String8& name,
if (mCryptoSessions.size() == 0) {
if (value == QUERY_VALUE_SECURITY_LEVEL_L3.c_str()) {
mPropertySet.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
} else if (value == QUERY_VALUE_SECURITY_LEVEL_L1.c_str()) {
// We must be sure we CAN set the security level to L1.
CdmQueryMap status;
CdmResponseType res = mCDM->QueryStatus(&status);
if (!isCdmResponseTypeSuccess(res)) {
ALOGE("Error querying CDM status: %u", res);
return mapCdmResponseType(res);
} else if (!status.count(QUERY_KEY_SECURITY_LEVEL)) {
ALOGE("CDM did not report a security level");
return kErrorCDMGeneric;
}
if (status[QUERY_KEY_SECURITY_LEVEL] != QUERY_VALUE_SECURITY_LEVEL_L1) {
ALOGE("App requested L1 security on a non-L1 device.");
return android::BAD_VALUE;
} else {
mPropertySet.set_security_level(kResetSecurityLevel);
}
} else if (value == kResetSecurityLevel) {
mPropertySet.set_security_level("");
mPropertySet.set_security_level(kResetSecurityLevel);
} else {
ALOGE("App requested invalid security level %s", value.string());
return android::BAD_VALUE;

View File

@@ -595,16 +595,16 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
provisioningIDMap[QUERY_KEY_PROVISIONING_ID] = provisioningId;
EXPECT_CALL(cdm, QueryStatus(_))
.WillOnce(DoAll(SetArgPointee<0>(l1Map),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(l3Map),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(deviceIDMap),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(systemIDMap),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(provisioningIDMap),
Return(wvcdm::NO_ERROR)));
.WillOnce(DoAll(SetArgPointee<0>(l1Map),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(l3Map),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(deviceIDMap),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(systemIDMap),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(provisioningIDMap),
Return(wvcdm::NO_ERROR)));
String8 stringResult;
Vector<uint8_t> vectorResult;
@@ -666,7 +666,7 @@ TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {
EXPECT_TRUE(vectorResult.isEmpty());
}
TEST_F(WVDrmPluginTest, DoesNotSetProperties) {
TEST_F(WVDrmPluginTest, DoesNotSetUnknownProperties) {
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
@@ -680,11 +680,11 @@ TEST_F(WVDrmPluginTest, DoesNotSetProperties) {
Vector<uint8_t> value;
value.appendArray(valueRaw, kValueSize);
status_t res = plugin.setPropertyString(String8("property"),
status_t res = plugin.setPropertyString(String8("unknownProperty"),
String8("ignored"));
ASSERT_NE(OK, res);
res = plugin.setPropertyByteArray(String8("property"), value);
res = plugin.setPropertyByteArray(String8("unknownProperty"), value);
ASSERT_NE(OK, res);
}
@@ -1229,6 +1229,18 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
const CdmClientPropertySet* propertySet = NULL;
CdmQueryMap l1Map;
l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
CdmQueryMap l3Map;
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
EXPECT_CALL(cdm, QueryStatus(_))
.WillOnce(DoAll(SetArgPointee<0>(l3Map),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<0>(l1Map),
Return(wvcdm::NO_ERROR)));
// Provide expected mock behavior
{
// Provide expected behavior in response to OpenSession and store the
@@ -1264,11 +1276,33 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
EXPECT_STREQ("L3", propertySet->security_level().c_str());
plugin.closeSession(sessionId);
// Test forcing L1 (Should Fail)
// Test returning to L1 on an L3 device (Should Fail)
res = plugin.setPropertyString(String8("securityLevel"), String8("L1"));
ASSERT_NE(OK, res);
// Test un-forcing a level
plugin.openSession(sessionId);
ASSERT_THAT(propertySet, NotNull());
EXPECT_STREQ("L3", propertySet->security_level().c_str());
plugin.closeSession(sessionId);
// Test returning to L1 on an L1 device
res = plugin.setPropertyString(String8("securityLevel"), String8("L1"));
ASSERT_EQ(OK, res);
plugin.openSession(sessionId);
ASSERT_THAT(propertySet, NotNull());
EXPECT_STREQ("", propertySet->security_level().c_str());
plugin.closeSession(sessionId);
// Test un-forcing a level (first forcing to L3 so we have something to reset)
res = plugin.setPropertyString(String8("securityLevel"), String8("L3"));
ASSERT_EQ(OK, res);
plugin.openSession(sessionId);
ASSERT_THAT(propertySet, NotNull());
EXPECT_STREQ("L3", propertySet->security_level().c_str());
plugin.closeSession(sessionId);
res = plugin.setPropertyString(String8("securityLevel"), String8(""));
ASSERT_EQ(OK, res);
@@ -1281,6 +1315,11 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
res = plugin.setPropertyString(String8("securityLevel"), String8("nonsense"));
ASSERT_NE(OK, res);
plugin.openSession(sessionId);
ASSERT_THAT(propertySet, NotNull());
EXPECT_STREQ("", propertySet->security_level().c_str());
plugin.closeSession(sessionId);
// Test attempting to force a level with a session open (Should Fail)
plugin.openSession(sessionId);
res = plugin.setPropertyString(String8("securityLevel"), String8("L3"));