Merge "Use session with longest remaining duration when session sharing is used." into nyc-dev
This commit is contained in:
@@ -91,6 +91,7 @@ class CdmSession {
|
||||
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
|
||||
|
||||
virtual bool IsKeyLoaded(const KeyId& key_id);
|
||||
virtual int64_t GetDurationRemaining();
|
||||
|
||||
// Used for notifying the Policy Engine of resolution changes
|
||||
virtual void NotifyResolution(uint32_t width, uint32_t height);
|
||||
|
||||
@@ -84,6 +84,7 @@ class PolicyEngine {
|
||||
bool IsPlaybackStarted() { return playback_start_time_ > 0; }
|
||||
|
||||
bool IsLicenseOrPlaybackDurationExpired(int64_t current_time);
|
||||
int64_t GetLicenseOrPlaybackDurationRemaining();
|
||||
|
||||
bool CanRenew() { return policy_.can_renew(); }
|
||||
|
||||
|
||||
@@ -1034,24 +1034,31 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
|
||||
// else we must be level 1 direct and we don't need to return a buffer.
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter;
|
||||
CdmSessionMap::iterator session_iter = sessions_.end();
|
||||
if (session_id.empty()) {
|
||||
// Loop through the sessions to find the session containing the key_id.
|
||||
for (iter = sessions_.begin(); iter != sessions_.end(); ++iter) {
|
||||
// Loop through the sessions to find the session containing the key_id
|
||||
// with the longest remaining license validity.
|
||||
int64_t seconds_remaining = 0;
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
if (iter->second->IsKeyLoaded(*parameters.key_id)) {
|
||||
break;
|
||||
int64_t duration = iter->second->GetDurationRemaining();
|
||||
if (duration > seconds_remaining) {
|
||||
session_iter = iter;
|
||||
seconds_remaining = duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iter = sessions_.find(session_id);
|
||||
session_iter = sessions_.find(session_id);
|
||||
}
|
||||
if (iter == sessions_.end()) {
|
||||
if (session_iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::Decrypt: session not found: id=%s, id size=%d",
|
||||
session_id.c_str(), session_id.size());
|
||||
return SESSION_NOT_FOUND_FOR_DECRYPT;
|
||||
}
|
||||
|
||||
return iter->second->Decrypt(parameters);
|
||||
return session_iter->second->Decrypt(parameters);
|
||||
}
|
||||
|
||||
bool CdmEngine::IsKeyLoaded(const KeyId& key_id) {
|
||||
@@ -1071,25 +1078,29 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
|
||||
return false;
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(*session_id);
|
||||
if (iter != sessions_.end()) {
|
||||
if (iter->second->IsKeyLoaded(key_id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t session_sharing_id = Properties::GetSessionSharingId(*session_id);
|
||||
|
||||
for (iter = sessions_.begin(); iter != sessions_.end(); ++iter) {
|
||||
CdmSessionMap::iterator session_iter = sessions_.end();
|
||||
int64_t seconds_remaining = 0;
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin(); iter != sessions_.end(); ++iter) {
|
||||
CdmSessionId local_session_id = iter->second->session_id();
|
||||
if (Properties::GetSessionSharingId(local_session_id) ==
|
||||
session_sharing_id) {
|
||||
if (iter->second->IsKeyLoaded(key_id)) {
|
||||
*session_id = local_session_id;
|
||||
return true;
|
||||
int64_t duration = iter->second->GetDurationRemaining();
|
||||
if (duration > seconds_remaining) {
|
||||
session_iter = iter;
|
||||
seconds_remaining = duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (session_iter != sessions_.end()) {
|
||||
*session_id = session_iter->second->session_id();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -461,6 +461,11 @@ bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
|
||||
return license_parser_->IsKeyLoaded(key_id);
|
||||
}
|
||||
|
||||
int64_t CdmSession::GetDurationRemaining() {
|
||||
if (policy_engine_->IsLicenseForFuture()) return 0;
|
||||
return policy_engine_->GetLicenseOrPlaybackDurationRemaining();
|
||||
}
|
||||
|
||||
CdmSessionId CdmSession::GenerateSessionId() {
|
||||
static int session_num = 1;
|
||||
return SESSION_ID_PREFIX + IntToString(++session_num);
|
||||
|
||||
@@ -272,6 +272,12 @@ bool PolicyEngine::GetSecondsSinceLastPlayed(
|
||||
return (*seconds_since_last_played >= 0) ? true : false;
|
||||
}
|
||||
|
||||
int64_t PolicyEngine::GetLicenseOrPlaybackDurationRemaining() {
|
||||
int64_t current_time = clock_->GetCurrentTime();
|
||||
return std::min(GetLicenseDurationRemaining(current_time),
|
||||
GetPlaybackDurationRemaining(current_time));
|
||||
}
|
||||
|
||||
void PolicyEngine::RestorePlaybackTimes(int64_t playback_start_time,
|
||||
int64_t last_playback_time) {
|
||||
playback_start_time_ = (playback_start_time > 0) ? playback_start_time : 0;
|
||||
|
||||
@@ -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