Use session with longest remaining duration when session sharing is used.
[ Merge of https://go/wvgerrit/16940 ] An alternate scenario to renewing keys is to load the same keys in a separate session and make use of them by using the session sharing feature. Session sharing involves iterating through a map of sessions and returning the first session that contains the Key ID. In certain cases (license about to expire) we might prefer an alternate session be chosen. Licenses may expire in two ways. Policy engine, driven by a 1 second timer may detect expiry and send an asynchronous event. OEMCrypto may also detect expiry based on information in the key control block and return an error during decryption. It is possible that these may differ by upto a second. This can lead to issues where decryption fails but EVENT_KEY_EXPIRED is not generated till later. It is possible to address this by using information from both timers to notify the app about expiry. To implement this correctly will add complexity and require synchronization between threads. To avoid this an alternate solution is, if session sharing is used, to pick the session that has a license with the longest remaining validity. b/27041140 Change-Id: I398cc4c10ee3a2f192d4a0befe7c8a469dd5bf86
This commit is contained in:
@@ -363,8 +363,9 @@ SubSampleInfo usage_info_sub_samples_icp[] = {
|
||||
"614f080d83f3b15cbc6600ddda43adff5d2941da13ebe49d80fd0cea5025412b"),
|
||||
wvcdm::a2b_hex("964c2dfda920357c668308d52d33c652"), 0, 3}};
|
||||
|
||||
// License duration + fudge factor
|
||||
const uint32_t kSingleEncryptedSubSampleIcpLicenseDurationExpiration = 5 + 2;
|
||||
// License duration and uncertainty window
|
||||
const uint32_t kSingleEncryptedSubSampleIcpLicenseDurationExpiration = 5;
|
||||
const uint32_t kSingleEncryptedSubSampleIcpLicenseExpirationWindow = 2;
|
||||
|
||||
struct SessionSharingSubSampleInfo {
|
||||
SubSampleInfo* sub_sample;
|
||||
@@ -2663,6 +2664,74 @@ TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
|
||||
decryptor_.CloseSession(gp_session_id_2);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmSessionSharingTest,
|
||||
::testing::Range(&session_sharing_sub_samples[0],
|
||||
&session_sharing_sub_samples[6]));
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, SessionSharingTest) {
|
||||
TestWvCdmClientPropertySet property_set;
|
||||
property_set.set_session_sharing_mode(true);
|
||||
|
||||
// TODO(rfrias): Move content information to ConfigTestEnv
|
||||
const std::string init_data1 = a2bs_hex(
|
||||
"000000347073736800000000" // blob size and pssh
|
||||
"EDEF8BA979D64ACEA3C827DCD51D21ED00000014" // Widevine system id
|
||||
"0801121030313233343536373839616263646566"); // pssh data
|
||||
|
||||
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
|
||||
&session_id_);
|
||||
CdmSessionId session_id1 = session_id_;
|
||||
GenerateKeyRequest(init_data1, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
|
||||
|
||||
// TODO(rfrias): Move content information to ConfigTestEnv
|
||||
std::string gp_client_auth2 =
|
||||
"?source=YOUTUBE&video_id=z3S_NhwueaM&oauth=ya.gtsqawidevine";
|
||||
std::string init_data2 = a2bs_hex(
|
||||
"000000347073736800000000" // blob size and pssh
|
||||
"edef8ba979d64acea3c827dcd51d21ed00000014" // Widevine system id
|
||||
"08011210bdf1cb4fffc6506b8b7945b0bd2917fb"); // pssh data
|
||||
|
||||
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
|
||||
&session_id_);
|
||||
CdmSessionId session_id2 = session_id_;
|
||||
GenerateKeyRequest(init_data2, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, gp_client_auth2, false);
|
||||
|
||||
SubSampleInfo* data = &single_encrypted_sub_sample_short_expiry;
|
||||
|
||||
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
|
||||
CdmDecryptionParameters decryption_parameters(
|
||||
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
|
||||
&data->iv, data->block_offset, &decrypt_buffer[0]);
|
||||
decryption_parameters.is_encrypted = data->is_encrypted;
|
||||
decryption_parameters.is_secure = data->is_secure;
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id1, data->validate_key_id,
|
||||
decryption_parameters));
|
||||
|
||||
sleep(kSingleEncryptedSubSampleIcpLicenseDurationExpiration -
|
||||
kSingleEncryptedSubSampleIcpLicenseExpirationWindow);
|
||||
|
||||
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
|
||||
&session_id_);
|
||||
CdmSessionId session_id3 = session_id_;
|
||||
GenerateKeyRequest(init_data1, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id1, data->validate_key_id,
|
||||
decryption_parameters));
|
||||
|
||||
sleep(2*kSingleEncryptedSubSampleIcpLicenseExpirationWindow);
|
||||
// session 1 will be expired, shared session 3 will be used to decrypt
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id1, data->validate_key_id,
|
||||
decryption_parameters));
|
||||
|
||||
decryptor_.CloseSession(session_id1);
|
||||
decryptor_.CloseSession(session_id2);
|
||||
decryptor_.CloseSession(session_id3);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, DecryptionKeyExpiredTest) {
|
||||
const std::string kCpKeyId = a2bs_hex(
|
||||
"000000347073736800000000" // blob size and pssh
|
||||
@@ -2683,16 +2752,13 @@ TEST_F(WvCdmRequestLicenseTest, DecryptionKeyExpiredTest) {
|
||||
decryption_parameters.is_secure = data->is_secure;
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
|
||||
decryption_parameters));
|
||||
sleep(kSingleEncryptedSubSampleIcpLicenseDurationExpiration);
|
||||
sleep(kSingleEncryptedSubSampleIcpLicenseDurationExpiration +
|
||||
kSingleEncryptedSubSampleIcpLicenseExpirationWindow);
|
||||
EXPECT_EQ(NEED_KEY, decryptor_.Decrypt(session_id_, data->validate_key_id,
|
||||
decryption_parameters));
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmSessionSharingTest,
|
||||
::testing::Range(&session_sharing_sub_samples[0],
|
||||
&session_sharing_sub_samples[6]));
|
||||
|
||||
class WvCdmDecryptionTest
|
||||
: public WvCdmRequestLicenseTest,
|
||||
public ::testing::WithParamInterface<SubSampleInfo*> {};
|
||||
|
||||
Reference in New Issue
Block a user