Offline playback for fastball

[ Merge of http://go/wvgerrit/18560 ]

This adds support for offline playback. If the content contains
mutiple playlists which contain differing EXT-X-KEY attribute lists,
each of those keys will need to be saved and restored into separate
sessions.

b/30041089

Test: Added unit tests to cover new functionality. Some oem_crypto,
request_license_test failures but the same as without this CL.

Change-Id: Ia1b877e12a67e8a720d29897ac7e2da236090123
This commit is contained in:
Rahul Frias
2017-01-09 17:54:06 -08:00
parent 3bb90b9450
commit 079ee03869
4 changed files with 231 additions and 2 deletions

View File

@@ -1408,7 +1408,28 @@ UsageInfo kUsageInfoTestData[] = {
"0E12202FF1FBA9926A24A1F79970EC427DDF87B4421488F7952499BC33CEB282D9E48"
"A")}};
const std::string kTestOrigin = "com.google";
struct HlsAttributesInfo {
std::string key_set_id;
CdmHlsMethod method;
std::string media_segment_iv;
std::string file_data;
};
HlsAttributesInfo kHlsAttributesTestData[] = {
{
"ksidC8EAA2579A282EB0", kHlsMethodAes128, // hls attributes 0
a2bs_hex("F7C4D15BD466BF285E241A4E58638543"),
a2bs_hex("0A1A08041001321408011210F7C4D15BD466BF285E241A4E5863854312201"
"39114B0372FF80FADF92614106E27BE8BD1588B4CAE6E1AEFB7F9C34EA52E"
"CC"),
},
{
"ksidE8C37662C88DC673", kHlsMethodSampleAes, // hls attributes 1
a2bs_hex("16413F038088438B5D4CD99F03EBB3D8"),
a2bs_hex("0A1A0804100132140802121016413F038088438B5D4CD99F03EBB3D812205"
"9EA13188B75C55D1EB78B3A65DB3EA3F43BD1B16642266D988E3543943C5F"
"41"),
}};
class MockFile : public File {
public:
@@ -1506,12 +1527,22 @@ class DeviceFilesSecurityLevelTest
class DeviceFilesUsageInfoTest : public DeviceFilesTest,
public ::testing::WithParamInterface<int> {};
class DeviceFilesHlsAttributesTest
: public DeviceFilesTest,
public ::testing::WithParamInterface<HlsAttributesInfo*> {};
MATCHER(IsCreateFileFlagSet, "") { return FileSystem::kCreate & arg; }
MATCHER_P(IsStrEq, str, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
return memcmp(arg, str.c_str(), str.size()) == 0;
}
MATCHER_P2(Contains, str1, size, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
std::string data(arg, size + str1.size() + kProtobufEstimatedOverhead);
return (data.find(str1) != std::string::npos);
}
MATCHER_P3(Contains, str1, str2, size, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
@@ -2209,4 +2240,75 @@ TEST_P(DeviceFilesUsageInfoTest, DeleteAll) {
INSTANTIATE_TEST_CASE_P(UsageInfo, DeviceFilesUsageInfoTest,
::testing::Range(-1, 4));
TEST_P(DeviceFilesHlsAttributesTest, Read) {
MockFileSystem file_system;
MockFile file;
HlsAttributesInfo* param = GetParam();
std::string path = device_base_path_ + param->key_set_id +
DeviceFiles::GetHlsAttributesFileNameExtension();
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillRepeatedly(Return(param->file_data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(param->file_data.size())))
.WillOnce(DoAll(
SetArrayArgument<0>(param->file_data.begin(), param->file_data.end()),
Return(param->file_data.size())));
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Write(_, _)).Times(0);
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
CdmHlsMethod method;
std::vector<uint8_t> media_segment_iv;
ASSERT_TRUE(device_files.RetrieveHlsAttributes(param->key_set_id, &method,
&media_segment_iv));
EXPECT_EQ(param->method, method);
EXPECT_EQ(b2a_hex(param->media_segment_iv), b2a_hex(media_segment_iv));
}
TEST_P(DeviceFilesHlsAttributesTest, Store) {
MockFileSystem file_system;
MockFile file;
HlsAttributesInfo* param = GetParam();
std::string path = device_base_path_ + param->key_set_id +
DeviceFiles::GetHlsAttributesFileNameExtension();
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file, Write(Contains(param->media_segment_iv, 0),
Gt(param->media_segment_iv.size())))
.WillOnce(ReturnArg<1>());
EXPECT_CALL(file, Read(_, _)).Times(0);
EXPECT_CALL(file, Close()).Times(1);
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
std::vector<uint8_t> iv(param->media_segment_iv.begin(),
param->media_segment_iv.end());
ASSERT_TRUE(
device_files.StoreHlsAttributes(param->key_set_id, param->method, iv));
}
TEST_P(DeviceFilesHlsAttributesTest, Delete) {
MockFileSystem file_system;
MockFile file;
HlsAttributesInfo* param = GetParam();
std::string path = device_base_path_ + param->key_set_id +
DeviceFiles::GetHlsAttributesFileNameExtension();
EXPECT_CALL(file_system, Remove(StrEq(path))).WillOnce(Return(true));
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
ASSERT_TRUE(device_files.DeleteHlsAttributes(param->key_set_id));
}
INSTANTIATE_TEST_CASE_P(HlsAttributes, DeviceFilesHlsAttributesTest,
::testing::Range(&kHlsAttributesTestData[0],
&kHlsAttributesTestData[2]));
} // namespace wvcdm