Support Offline Licenses

Bug: 8621588

Merge of the following CLs from the Widevine CDM repository:

https://widevine-internal-review.googlesource.com/#/c/5602/
https://widevine-internal-review.googlesource.com/#/c/5431/
https://widevine-internal-review.googlesource.com/#/c/5660/

Change-Id: If37940e2535e1a1eca95e4394d8cf9bf689e9c3a
This commit is contained in:
Jeff Tinker
2013-05-15 19:23:36 -07:00
parent 898d870126
commit 1b295f4c81
30 changed files with 1647 additions and 471 deletions

View File

@@ -3,6 +3,7 @@
//
#include <stdio.h>
#include <string.h>
#include <string>
#include "gmock/gmock.h"
@@ -27,17 +28,22 @@ class MockCDM : public WvContentDecryptionModule {
MOCK_METHOD1(CloseSession, CdmResponseType(const CdmSessionId&));
MOCK_METHOD6(GenerateKeyRequest, CdmResponseType(const CdmSessionId&,
MOCK_METHOD7(GenerateKeyRequest, CdmResponseType(const CdmSessionId&,
const CdmKeySetId&,
const CdmInitData&,
const CdmLicenseType,
CdmAppParameterMap&,
CdmKeyMessage*, string*));
MOCK_METHOD2(AddKey, CdmResponseType(const CdmSessionId&,
const CdmKeyResponse&));
MOCK_METHOD3(AddKey, CdmResponseType(const CdmSessionId&,
const CdmKeyResponse&,
CdmKeySetId&));
MOCK_METHOD1(CancelKeyRequest, CdmResponseType(const CdmSessionId&));
MOCK_METHOD2(RestoreKey, CdmResponseType(const CdmSessionId&,
const CdmKeySetId&));
MOCK_METHOD1(QueryStatus, CdmResponseType(CdmQueryMap*));
MOCK_METHOD2(QueryKeyStatus, CdmResponseType(const CdmSessionId&,
@@ -111,6 +117,7 @@ class WVDrmPluginTest : public Test {
fread(sessionIdRaw, sizeof(uint8_t), kSessionIdSize, fp);
fclose(fp);
memcpy(sessionIdRaw, SESSION_ID_PREFIX.data(), SESSION_ID_PREFIX.size());
sessionId.appendArray(sessionIdRaw, kSessionIdSize);
cdmSessionId.assign(sessionId.begin(), sessionId.end());
@@ -122,8 +129,8 @@ class WVDrmPluginTest : public Test {
};
TEST_F(WVDrmPluginTest, OpensSessions) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
@@ -149,8 +156,8 @@ TEST_F(WVDrmPluginTest, OpensSessions) {
}
TEST_F(WVDrmPluginTest, ClosesSessions) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
EXPECT_CALL(cdm, CloseSession(cdmSessionId))
@@ -162,19 +169,27 @@ TEST_F(WVDrmPluginTest, ClosesSessions) {
}
TEST_F(WVDrmPluginTest, GeneratesKeyRequests) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const size_t kInitDataSize = 128;
uint8_t initDataRaw[kInitDataSize];
static const size_t kRequestSize = 256;
uint8_t requestRaw[kRequestSize];
static const uint32_t kKeySetIdSize = 32;
uint8_t keySetIdRaw[kKeySetIdSize];
FILE* fp = fopen("/dev/urandom", "r");
fread(initDataRaw, sizeof(uint8_t), kInitDataSize, fp);
fread(requestRaw, sizeof(uint8_t), kRequestSize, fp);
fread(keySetIdRaw, sizeof(uint8_t), kKeySetIdSize, fp);
fclose(fp);
memcpy(keySetIdRaw, KEY_SET_ID_PREFIX.data(), KEY_SET_ID_PREFIX.size());
CdmKeySetId cdmKeySetId(reinterpret_cast<char *>(keySetIdRaw), kKeySetIdSize);
Vector<uint8_t> keySetId;
keySetId.appendArray(keySetIdRaw, kKeySetIdSize);
Vector<uint8_t> initData;
initData.appendArray(initDataRaw, kInitDataSize);
@@ -209,20 +224,28 @@ TEST_F(WVDrmPluginTest, GeneratesKeyRequests) {
{
InSequence calls;
EXPECT_CALL(cdm, GenerateKeyRequest(cdmSessionId,
EXPECT_CALL(cdm, GenerateKeyRequest(cdmSessionId, "",
ElementsAreArray(psshBox, kPsshBoxSize),
kLicenseTypeOffline, cdmParameters, _,
_))
.WillOnce(DoAll(SetArgPointee<4>(cdmRequest),
SetArgPointee<5>(kDefaultUrl),
.WillOnce(DoAll(SetArgPointee<5>(cdmRequest),
SetArgPointee<6>(kDefaultUrl),
Return(wvcdm::KEY_MESSAGE)));
EXPECT_CALL(cdm, GenerateKeyRequest(cdmSessionId,
EXPECT_CALL(cdm, GenerateKeyRequest(cdmSessionId, "",
ElementsAreArray(psshBox, kPsshBoxSize),
kLicenseTypeStreaming, cdmParameters, _,
_))
.WillOnce(DoAll(SetArgPointee<4>(cdmRequest),
SetArgPointee<5>(kDefaultUrl),
.WillOnce(DoAll(SetArgPointee<5>(cdmRequest),
SetArgPointee<6>(kDefaultUrl),
Return(wvcdm::KEY_MESSAGE)));
EXPECT_CALL(cdm, GenerateKeyRequest("", cdmKeySetId,
ElementsAreArray(psshBox, kPsshBoxSize),
kLicenseTypeRelease, cdmParameters, _,
_))
.WillOnce(DoAll(SetArgPointee<5>(cdmRequest),
SetArgPointee<6>(kDefaultUrl),
Return(wvcdm::KEY_MESSAGE)));
}
@@ -233,7 +256,6 @@ TEST_F(WVDrmPluginTest, GeneratesKeyRequests) {
String8("video/h264"),
DrmPlugin::kKeyType_Offline,
parameters, request, defaultUrl);
ASSERT_EQ(OK, res);
EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize));
EXPECT_STREQ(kDefaultUrl, defaultUrl.string());
@@ -241,44 +263,96 @@ TEST_F(WVDrmPluginTest, GeneratesKeyRequests) {
res = plugin.getKeyRequest(sessionId, initData, String8("video/h264"),
DrmPlugin::kKeyType_Streaming, parameters,
request, defaultUrl);
ASSERT_EQ(OK, res);
EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize));
EXPECT_STREQ(kDefaultUrl, defaultUrl.string());
res = plugin.getKeyRequest(keySetId, initData, String8("video/h264"),
DrmPlugin::kKeyType_Release, parameters,
request, defaultUrl);
ASSERT_EQ(OK, res);
EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize));
EXPECT_STREQ(kDefaultUrl, defaultUrl.string());
}
TEST_F(WVDrmPluginTest, AddsKeys) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const uint32_t kResponseSize = 256;
uint8_t responseRaw[kResponseSize];
static const uint32_t kKeySetIdSize = 32;
uint8_t keySetIdRaw[kKeySetIdSize];
FILE* fp = fopen("/dev/urandom", "r");
fread(responseRaw, sizeof(uint8_t), kResponseSize, fp);
fread(keySetIdRaw, sizeof(uint8_t), kKeySetIdSize, fp);
fclose(fp);
Vector<uint8_t> response;
response.appendArray(responseRaw, kResponseSize);
// TODO: Do something with the key set ID.
Vector<uint8_t> ignoredKeySetId;
memcpy(keySetIdRaw, KEY_SET_ID_PREFIX.data(), KEY_SET_ID_PREFIX.size());
CdmKeySetId cdmKeySetId(reinterpret_cast<char *>(keySetIdRaw), kKeySetIdSize);
Vector<uint8_t> keySetId;
EXPECT_CALL(cdm, AddKey(cdmSessionId, ElementsAreArray(responseRaw,
kResponseSize)))
.WillOnce(Return(wvcdm::KEY_ADDED));
Vector<uint8_t> emptyKeySetId;
status_t res = plugin.provideKeyResponse(sessionId, response,
ignoredKeySetId);
EXPECT_CALL(cdm, AddKey(cdmSessionId,
ElementsAreArray(responseRaw, kResponseSize), _))
.WillOnce(DoAll(SetArgReferee<2>(cdmKeySetId),
Return(wvcdm::KEY_ADDED)));
EXPECT_CALL(cdm, AddKey("", ElementsAreArray(responseRaw, kResponseSize),
cdmKeySetId))
.Times(1);
status_t res = plugin.provideKeyResponse(sessionId, response, keySetId);
ASSERT_EQ(OK, res);
ASSERT_THAT(keySetId, ElementsAreArray(keySetIdRaw, kKeySetIdSize));
res = plugin.provideKeyResponse(keySetId, response, emptyKeySetId);
ASSERT_EQ(OK, res);
EXPECT_EQ(0u, emptyKeySetId.size());
}
TEST_F(WVDrmPluginTest, CancelsKeyRequests) {
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
EXPECT_CALL(cdm, CancelKeyRequest(cdmSessionId))
.Times(1);
status_t res = plugin.removeKeys(sessionId);
ASSERT_EQ(OK, res);
}
// TODO: Reinstate removeKeys() test once its behavior is finalized.
TEST_F(WVDrmPluginTest, RestoresKeys) {
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const size_t kKeySetIdSize = 32;
uint8_t keySetIdRaw[kKeySetIdSize];
FILE* fp = fopen("/dev/urandom", "r");
fread(keySetIdRaw, sizeof(uint8_t), kKeySetIdSize, fp);
fclose(fp);
Vector<uint8_t> keySetId;
keySetId.appendArray(keySetIdRaw, kKeySetIdSize);
EXPECT_CALL(cdm, RestoreKey(cdmSessionId,
ElementsAreArray(keySetIdRaw, kKeySetIdSize)))
.Times(1);
status_t res = plugin.restoreKeys(sessionId, keySetId);
ASSERT_EQ(OK, res);
}
TEST_F(WVDrmPluginTest, QueriesKeyStatus) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
KeyedVector<String8, String8> expectedLicenseStatus;
@@ -293,7 +367,7 @@ TEST_F(WVDrmPluginTest, QueriesKeyStatus) {
EXPECT_CALL(cdm, QueryKeyStatus(cdmSessionId, _))
.WillOnce(DoAll(SetArgPointee<1>(cdmLicenseStatus),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
KeyedVector<String8, String8> licenseStatus;
@@ -310,8 +384,8 @@ TEST_F(WVDrmPluginTest, QueriesKeyStatus) {
}
TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const uint32_t kRequestSize = 256;
@@ -340,8 +414,8 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
}
TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const uint32_t kResponseSize = 512;
@@ -363,8 +437,8 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
}
TEST_F(WVDrmPluginTest, GetsSecureStops) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const uint32_t kStopSize = 53;
@@ -405,8 +479,8 @@ TEST_F(WVDrmPluginTest, GetsSecureStops) {
}
TEST_F(WVDrmPluginTest, ReleasesSecureStops) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const uint32_t kMessageSize = 128;
@@ -428,8 +502,8 @@ TEST_F(WVDrmPluginTest, ReleasesSecureStops) {
}
TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
CdmQueryMap l1Map;
@@ -493,8 +567,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
}
TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
String8 stringResult;
@@ -512,8 +586,8 @@ TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {
}
TEST_F(WVDrmPluginTest, DoesNotSetProperties) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const uint32_t kValueSize = 32;
@@ -534,8 +608,8 @@ TEST_F(WVDrmPluginTest, DoesNotSetProperties) {
}
TEST_F(WVDrmPluginTest, FailsGenericMethodsWithoutAnAlgorithmSet) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
Vector<uint8_t> keyId;
@@ -548,7 +622,7 @@ TEST_F(WVDrmPluginTest, FailsGenericMethodsWithoutAnAlgorithmSet) {
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.Times(AtLeast(1))
@@ -591,8 +665,8 @@ MATCHER_P(IsIV, iv, "") {
}
TEST_F(WVDrmPluginTest, CallsGenericEncrypt) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const size_t kDataSize = 256;
@@ -631,7 +705,7 @@ TEST_F(WVDrmPluginTest, CallsGenericEncrypt) {
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.Times(AtLeast(1))
@@ -655,8 +729,8 @@ TEST_F(WVDrmPluginTest, CallsGenericEncrypt) {
}
TEST_F(WVDrmPluginTest, CallsGenericDecrypt) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const size_t kDataSize = 256;
@@ -695,7 +769,7 @@ TEST_F(WVDrmPluginTest, CallsGenericDecrypt) {
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.Times(AtLeast(1))
@@ -719,8 +793,8 @@ TEST_F(WVDrmPluginTest, CallsGenericDecrypt) {
}
TEST_F(WVDrmPluginTest, CallsGenericSign) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const size_t kDataSize = 256;
@@ -761,7 +835,7 @@ TEST_F(WVDrmPluginTest, CallsGenericSign) {
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.Times(AtLeast(1))
@@ -785,8 +859,8 @@ TEST_F(WVDrmPluginTest, CallsGenericSign) {
}
TEST_F(WVDrmPluginTest, CallsGenericVerify) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
static const size_t kDataSize = 256;
@@ -837,7 +911,7 @@ TEST_F(WVDrmPluginTest, CallsGenericVerify) {
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.Times(AtLeast(1))
@@ -866,8 +940,8 @@ TEST_F(WVDrmPluginTest, CallsGenericVerify) {
}
TEST_F(WVDrmPluginTest, RegistersForEvents) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
EXPECT_CALL(cdm, AttachEventListener(cdmSessionId, &plugin))
@@ -877,7 +951,7 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) {
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.Times(AtLeast(1))
@@ -892,8 +966,8 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) {
}
TEST_F(WVDrmPluginTest, UnregistersForAllEventsOnDestruction) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
{
WVDrmPlugin plugin(&cdm, &crypto);
@@ -939,8 +1013,8 @@ TEST_F(WVDrmPluginTest, UnregistersForAllEventsOnDestruction) {
}
TEST_F(WVDrmPluginTest, MarshalsEvents) {
MockCDM cdm;
MockCrypto crypto;
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
sp<MockDrmPluginListener> listener = new MockDrmPluginListener();
@@ -965,7 +1039,7 @@ TEST_F(WVDrmPluginTest, MarshalsEvents) {
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.Times(AtLeast(1))