Merge "Allows sharing of keys between sessions" into klp-dev
This commit is contained in:
@@ -16,6 +16,9 @@ class CdmClientPropertySet {
|
||||
virtual std::string security_level() const = 0;
|
||||
virtual bool use_privacy_mode() const = 0;
|
||||
virtual std::vector<uint8_t> service_certificate() const = 0;
|
||||
virtual bool is_session_sharing_enabled() const = 0;
|
||||
virtual uint32_t session_sharing_id() const = 0;
|
||||
virtual void set_session_sharing_id(uint32_t id) = 0;
|
||||
};
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -93,6 +93,7 @@ class CdmEngine : public TimerHandler {
|
||||
|
||||
// Is the key known to any session?
|
||||
virtual bool IsKeyValid(const KeyId& key_id);
|
||||
virtual bool FindSessionForKey(const KeyId& key_id, CdmSessionId* sessionId);
|
||||
|
||||
// Event listener related methods
|
||||
virtual bool AttachEventListener(const CdmSessionId& session_id,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#ifndef CDM_BASE_LICENSE_H_
|
||||
#define CDM_BASE_LICENSE_H_
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace video_widevine_server {
|
||||
@@ -41,6 +43,7 @@ class CdmLicense {
|
||||
CdmKeyResponse& license_response,
|
||||
CdmKeyResponse& license_renewal_response);
|
||||
bool HasInitData() { return !init_data_.empty(); }
|
||||
bool IsKeyLoaded(const KeyId& key_id);
|
||||
|
||||
private:
|
||||
bool PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
|
||||
@@ -58,6 +61,7 @@ class CdmLicense {
|
||||
std::string service_certificate_;
|
||||
std::string init_data_;
|
||||
bool initialized_;
|
||||
std::set<KeyId> loaded_keys_;
|
||||
|
||||
// Used for certificate based licensing
|
||||
CdmKeyMessage key_request_;
|
||||
|
||||
@@ -66,6 +66,7 @@ class Properties {
|
||||
static const std::vector<uint8_t> GetServiceCertificate(
|
||||
const CdmSessionId& session_id);
|
||||
static bool UsePrivacyMode(const CdmSessionId& session_id);
|
||||
static uint32_t GetSessionSharingId(const CdmSessionId& session_id);
|
||||
|
||||
static bool AddSessionPropertySet(
|
||||
const CdmSessionId& session_id,
|
||||
|
||||
@@ -525,6 +525,29 @@ bool CdmEngine::IsKeyValid(const KeyId& key_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CdmEngine::FindSessionForKey(
|
||||
const KeyId& key_id,
|
||||
CdmSessionId* session_id) {
|
||||
if (NULL == session_id) {
|
||||
LOGE("CdmEngine::FindSessionForKey: session id not provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t session_sharing_id = Properties::GetSessionSharingId(*session_id);
|
||||
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
CdmSessionId id = iter->second->session_id();
|
||||
if (Properties::GetSessionSharingId(id) == session_sharing_id) {
|
||||
if (iter->second->IsKeyValid(key_id)) {
|
||||
*session_id = id;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CdmEngine::AttachEventListener(
|
||||
const CdmSessionId& session_id,
|
||||
WvCdmEventListener* listener) {
|
||||
|
||||
@@ -324,22 +324,7 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
}
|
||||
|
||||
bool CdmSession::IsKeyValid(const KeyId& key_id) {
|
||||
if (crypto_session_.get() == NULL || !crypto_session_->IsOpen())
|
||||
return false;
|
||||
|
||||
if (key_id_ != key_id) {
|
||||
// OEMCrypto does not provide a way to query the existence/validity of a
|
||||
// key. SelectKey can be used to check whether a key is valid, but there
|
||||
// is also a side effect - the key is selected for decryption, which might
|
||||
// be undesirable and it posts restriction on the use of IsKeyValid API.
|
||||
// TODO(kqyang, gmorgan): consider adding a function in OEMCrypto to check
|
||||
// if a key is valid.
|
||||
if (!crypto_session_->SelectKey(key_id)) {
|
||||
return false;
|
||||
}
|
||||
key_id_ = key_id;
|
||||
}
|
||||
return true;
|
||||
return license_parser_.IsKeyLoaded(key_id);
|
||||
}
|
||||
|
||||
CdmSessionId CdmSession::GenerateSessionId() {
|
||||
|
||||
@@ -539,9 +539,22 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
// merge from Eureka)
|
||||
policy_engine_->SetLicense(license);
|
||||
|
||||
return session_->LoadKeys(signed_response.msg(), signed_response.signature(),
|
||||
mac_key_iv, mac_key, key_array.size(),
|
||||
&key_array[0]);
|
||||
CdmResponseType resp = session_->LoadKeys(signed_response.msg(),
|
||||
signed_response.signature(),
|
||||
mac_key_iv,
|
||||
mac_key,
|
||||
key_array.size(),
|
||||
&key_array[0]);
|
||||
|
||||
if (KEY_ADDED == resp) {
|
||||
loaded_keys_.clear();
|
||||
for (std::vector<CryptoKey>::iterator it = key_array.begin();
|
||||
it != key_array.end();
|
||||
++it) {
|
||||
loaded_keys_.insert(it->key_id());
|
||||
}
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
@@ -753,4 +766,8 @@ CdmResponseType CdmLicense::HandleKeyErrorResponse(
|
||||
}
|
||||
}
|
||||
|
||||
bool CdmLicense::IsKeyLoaded(const KeyId& key_id) {
|
||||
return loaded_keys_.find(key_id) != loaded_keys_.end();
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -100,6 +100,17 @@ bool Properties::UsePrivacyMode(const CdmSessionId& session_id) {
|
||||
return property_set->use_privacy_mode();
|
||||
}
|
||||
|
||||
uint32_t Properties::GetSessionSharingId(const CdmSessionId& session_id) {
|
||||
const CdmClientPropertySet* property_set =
|
||||
GetCdmClientPropertySet(session_id);
|
||||
if (NULL == property_set) {
|
||||
LOGE("Properties::GetSessionSharingId: cannot find property set for %s",
|
||||
session_id.c_str());
|
||||
return 0;
|
||||
}
|
||||
return property_set->session_sharing_id();
|
||||
}
|
||||
|
||||
bool Properties::GetSecurityLevelDirectories(std::vector<std::string>* dirs) {
|
||||
dirs->resize(sizeof(kSecurityLevelDirs)/sizeof(const char*));
|
||||
for (size_t i = 0; i < dirs->size(); ++i) {
|
||||
|
||||
@@ -21,7 +21,7 @@ class WvContentDecryptionModule {
|
||||
// Session related methods
|
||||
virtual CdmResponseType OpenSession(
|
||||
const CdmKeySystem& key_system,
|
||||
const CdmClientPropertySet* property_set,
|
||||
CdmClientPropertySet* property_set,
|
||||
CdmSessionId* session_id);
|
||||
virtual CdmResponseType CloseSession(const CdmSessionId& session_id);
|
||||
|
||||
@@ -84,6 +84,7 @@ class WvContentDecryptionModule {
|
||||
WvCdmEventListener* listener);
|
||||
|
||||
private:
|
||||
uint32_t GenerateSessionSharingId();
|
||||
|
||||
// instance variables
|
||||
UniquePtr<CdmEngine> cdm_engine_;
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "cdm_client_property_set.h"
|
||||
#include "cdm_engine.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_event_listener.h"
|
||||
|
||||
@@ -18,8 +20,13 @@ WvContentDecryptionModule::~WvContentDecryptionModule() {}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::OpenSession(
|
||||
const CdmKeySystem& key_system,
|
||||
const CdmClientPropertySet* property_set,
|
||||
CdmClientPropertySet* property_set,
|
||||
CdmSessionId* session_id) {
|
||||
if (property_set && property_set->is_session_sharing_enabled()) {
|
||||
if (property_set->session_sharing_id() == 0)
|
||||
property_set->set_session_sharing_id(GenerateSessionSharingId());
|
||||
}
|
||||
|
||||
return cdm_engine_->OpenSession(key_system, property_set, session_id);
|
||||
}
|
||||
|
||||
@@ -111,7 +118,15 @@ CdmResponseType WvContentDecryptionModule::ReleaseSecureStops(
|
||||
CdmResponseType WvContentDecryptionModule::Decrypt(
|
||||
const CdmSessionId& session_id,
|
||||
const CdmDecryptionParameters& parameters) {
|
||||
return cdm_engine_->Decrypt(session_id, parameters);
|
||||
CdmSessionId id = session_id;
|
||||
if (Properties::GetSessionSharingId(session_id) != 0) {
|
||||
bool status = cdm_engine_->FindSessionForKey(*parameters.key_id, &id);
|
||||
if (!status) {
|
||||
LOGE("WvContentDecryptionModule::Decrypt: unable to find session");
|
||||
return KEY_ERROR;
|
||||
}
|
||||
}
|
||||
return cdm_engine_->Decrypt(id, parameters);
|
||||
}
|
||||
|
||||
bool WvContentDecryptionModule::AttachEventListener(
|
||||
@@ -124,4 +139,9 @@ bool WvContentDecryptionModule::DetachEventListener(
|
||||
return cdm_engine_->DetachEventListener(session_id, listener);
|
||||
}
|
||||
|
||||
uint32_t WvContentDecryptionModule::GenerateSessionSharingId() {
|
||||
static int next_session_sharing_id = 0;
|
||||
return ++next_session_sharing_id;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -205,7 +205,10 @@ SubSampleInfo partial_offset_single_encrypted_sub_sample = {
|
||||
namespace wvcdm {
|
||||
class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
TestWvCdmClientPropertySet() : use_privacy_mode_(false) {}
|
||||
TestWvCdmClientPropertySet()
|
||||
: use_privacy_mode_(false),
|
||||
is_session_sharing_enabled_(false),
|
||||
session_sharing_id_(0) {}
|
||||
virtual ~TestWvCdmClientPropertySet() {}
|
||||
|
||||
virtual std::string security_level() const { return security_level_; }
|
||||
@@ -213,6 +216,10 @@ class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
return service_certificate_;
|
||||
}
|
||||
virtual bool use_privacy_mode() const { return use_privacy_mode_; }
|
||||
bool is_session_sharing_enabled() const {
|
||||
return is_session_sharing_enabled_;
|
||||
}
|
||||
uint32_t session_sharing_id() const { return session_sharing_id_; }
|
||||
|
||||
void set_security_level(const std::string& security_level) {
|
||||
if (!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L1) ||
|
||||
@@ -227,11 +234,17 @@ class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
void set_use_privacy_mode(bool use_privacy_mode) {
|
||||
use_privacy_mode_ = use_privacy_mode;
|
||||
}
|
||||
void set_session_sharing_mode(bool enable) {
|
||||
is_session_sharing_enabled_ = enable;
|
||||
}
|
||||
void set_session_sharing_id(uint32_t id) { session_sharing_id_ = id; }
|
||||
|
||||
private:
|
||||
std::string security_level_;
|
||||
std::vector<uint8_t> service_certificate_;
|
||||
bool use_privacy_mode_;
|
||||
bool is_session_sharing_enabled_;
|
||||
uint32_t session_sharing_id_;
|
||||
};
|
||||
|
||||
class TestWvCdmEventListener : public WvCdmEventListener {
|
||||
@@ -377,6 +390,10 @@ class WvCdmDecryptionTest
|
||||
: public WvCdmRequestLicenseTest,
|
||||
public ::testing::WithParamInterface<SubSampleInfo*> {};
|
||||
|
||||
class WvCdmSessionSharingTest
|
||||
: public WvCdmRequestLicenseTest,
|
||||
public ::testing::WithParamInterface<bool> {};
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
std::string provisioning_server_url;
|
||||
@@ -523,6 +540,54 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_PrivacyModeWithServiceCertificateTest)
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
|
||||
bool enable_session_sharing = GetParam();
|
||||
|
||||
TestWvCdmClientPropertySet property_set;
|
||||
property_set.set_session_sharing_mode(enable_session_sharing);
|
||||
|
||||
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
|
||||
CdmSessionId gp_session_id_1 = session_id_;
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||
|
||||
// TODO(rfrias): Move content information to ConfigTestEnv
|
||||
std::string gp_client_auth2 =
|
||||
"?source=YOUTUBE&video_id=z3S_NhwueaM&oauth=ya.gtsqawidevine";
|
||||
std::string gp_key_id2 =
|
||||
wvcdm::a2bs_hex(
|
||||
"000000347073736800000000" // blob size and pssh
|
||||
"edef8ba979d64acea3c827dcd51d21ed00000014" // Widevine system id
|
||||
"08011210bdf1cb4fffc6506b8b7945b0bd2917fb"); // pssh data
|
||||
|
||||
decryptor_.OpenSession(g_key_system, &property_set, &session_id_);
|
||||
CdmSessionId gp_session_id_2 = session_id_;
|
||||
GenerateKeyRequest(g_key_system, gp_key_id2, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, gp_client_auth2, gp_key_id2, false);
|
||||
|
||||
SubSampleInfo* data = &single_encrypted_sub_sample;
|
||||
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(gp_session_id_2, decryption_parameters),
|
||||
enable_session_sharing);
|
||||
EXPECT_EQ(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
|
||||
decrypt_buffer.begin()),
|
||||
enable_session_sharing);
|
||||
|
||||
decryptor_.CloseSession(gp_session_id_1);
|
||||
decryptor_.CloseSession(gp_session_id_2);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmSessionSharingTest, ::testing::Bool());
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, BaseMessageTest) {
|
||||
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||
GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming);
|
||||
|
||||
@@ -161,40 +161,58 @@ class WVDrmPlugin : public android::DrmPlugin,
|
||||
class WVClientPropertySet : public wvcdm::CdmClientPropertySet {
|
||||
public:
|
||||
WVClientPropertySet()
|
||||
: mUsePrivacyMode(false) {}
|
||||
: mUsePrivacyMode(false), mShareKeys(false), mSessionSharingId(0) {}
|
||||
|
||||
virtual ~WVClientPropertySet() {}
|
||||
|
||||
void set_security_level(const std::string& securityLevel) {
|
||||
mSecurityLevel = securityLevel;
|
||||
}
|
||||
|
||||
virtual std::string security_level() const {
|
||||
return mSecurityLevel;
|
||||
}
|
||||
|
||||
void set_use_privacy_mode(bool usePrivacyMode) {
|
||||
mUsePrivacyMode = usePrivacyMode;
|
||||
void set_security_level(const std::string& securityLevel) {
|
||||
mSecurityLevel = securityLevel;
|
||||
}
|
||||
|
||||
virtual bool use_privacy_mode() const {
|
||||
return mUsePrivacyMode;
|
||||
}
|
||||
|
||||
void set_service_certificate(const std::vector<uint8_t>& serviceCertificate) {
|
||||
mServiceCertificate = serviceCertificate;
|
||||
void set_use_privacy_mode(bool usePrivacyMode) {
|
||||
mUsePrivacyMode = usePrivacyMode;
|
||||
}
|
||||
|
||||
virtual std::vector<uint8_t> service_certificate() const {
|
||||
return mServiceCertificate;
|
||||
}
|
||||
|
||||
void set_service_certificate(const std::vector<uint8_t>& serviceCertificate) {
|
||||
mServiceCertificate = serviceCertificate;
|
||||
}
|
||||
|
||||
virtual bool is_session_sharing_enabled() const {
|
||||
return mShareKeys;
|
||||
}
|
||||
|
||||
void set_is_session_sharing_enabled(bool shareKeys) {
|
||||
mShareKeys = shareKeys;
|
||||
}
|
||||
|
||||
virtual uint32_t session_sharing_id() const {
|
||||
return mSessionSharingId;
|
||||
}
|
||||
|
||||
virtual void set_session_sharing_id(uint32_t id) {
|
||||
mSessionSharingId = id;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_EVIL_CONSTRUCTORS(WVClientPropertySet);
|
||||
|
||||
std::string mSecurityLevel;
|
||||
bool mUsePrivacyMode;
|
||||
std::vector<uint8_t> mServiceCertificate;
|
||||
bool mShareKeys;
|
||||
uint32_t mSessionSharingId;
|
||||
} mPropertySet;
|
||||
|
||||
WvContentDecryptionModule* mCDM;
|
||||
|
||||
@@ -392,6 +392,12 @@ status_t WVDrmPlugin::getPropertyString(const String8& name,
|
||||
} else {
|
||||
value = kDisable;
|
||||
}
|
||||
} else if (name == "sessionSharing") {
|
||||
if (mPropertySet.is_session_sharing_enabled()) {
|
||||
value = kEnable;
|
||||
} else {
|
||||
value = kDisable;
|
||||
}
|
||||
} else {
|
||||
ALOGE("App requested unknown string property %s", name.string());
|
||||
return android::ERROR_DRM_CANNOT_HANDLE;
|
||||
@@ -475,6 +481,20 @@ status_t WVDrmPlugin::setPropertyString(const String8& name,
|
||||
ALOGE("App requested unknown privacy mode %s", value.string());
|
||||
return android::BAD_VALUE;
|
||||
}
|
||||
} else if (name == "sessionSharing") {
|
||||
if (mCryptoSessions.size() == 0) {
|
||||
if (value == kEnable) {
|
||||
mPropertySet.set_is_session_sharing_enabled(true);
|
||||
} else if (value == kDisable) {
|
||||
mPropertySet.set_is_session_sharing_enabled(false);
|
||||
} else {
|
||||
ALOGE("App requested unknown sharing type %s", value.string());
|
||||
return android::BAD_VALUE;
|
||||
}
|
||||
} else {
|
||||
ALOGE("App tried to change key sharing while sessions are open.");
|
||||
return kErrorSessionIsOpen;
|
||||
}
|
||||
} else {
|
||||
ALOGE("App set unknown string property %s", name.string());
|
||||
return android::ERROR_DRM_CANNOT_HANDLE;
|
||||
|
||||
@@ -26,7 +26,7 @@ using namespace wvdrm;
|
||||
class MockCDM : public WvContentDecryptionModule {
|
||||
public:
|
||||
MOCK_METHOD3(OpenSession, CdmResponseType(const CdmKeySystem&,
|
||||
const CdmClientPropertySet*,
|
||||
CdmClientPropertySet*,
|
||||
CdmSessionId*));
|
||||
|
||||
MOCK_METHOD1(CloseSession, CdmResponseType(const CdmSessionId&));
|
||||
@@ -1181,7 +1181,6 @@ TEST_F(WVDrmPluginTest, GeneratesProvisioningNeededEvent) {
|
||||
ASSERT_EQ(ERROR_DRM_NOT_PROVISIONED, res);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
StrictMock<MockCrypto> crypto;
|
||||
@@ -1219,6 +1218,8 @@ TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) {
|
||||
EXPECT_STREQ("", propertySet->security_level().c_str());
|
||||
EXPECT_FALSE(propertySet->use_privacy_mode());
|
||||
EXPECT_EQ(0u, propertySet->service_certificate().size());
|
||||
EXPECT_FALSE(propertySet->is_session_sharing_enabled());
|
||||
EXPECT_EQ(0u, propertySet->session_sharing_id());
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
|
||||
@@ -1395,3 +1396,107 @@ TEST_F(WVDrmPluginTest, CanSetServiceCertificate) {
|
||||
ASSERT_EQ(OK, res);
|
||||
EXPECT_EQ(0u, propertySet->service_certificate().size());
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, CanSetSessionSharing) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
StrictMock<MockCrypto> crypto;
|
||||
WVDrmPlugin plugin(&cdm, &crypto);
|
||||
|
||||
const CdmClientPropertySet* propertySet = NULL;
|
||||
|
||||
// Provide expected mock behavior
|
||||
{
|
||||
// Provide expected behavior in response to OpenSession and store the
|
||||
// property set
|
||||
EXPECT_CALL(cdm, OpenSession(_, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<2>(cdmSessionId),
|
||||
SaveArg<1>(&propertySet),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// Provide expected behavior when plugin requests session control info
|
||||
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
|
||||
.WillRepeatedly(Invoke(setSessionIdOnMap<4>));
|
||||
|
||||
// Let gMock know these calls will happen but we aren't interested in them.
|
||||
EXPECT_CALL(cdm, AttachEventListener(_, _))
|
||||
.Times(AtLeast(0));
|
||||
|
||||
EXPECT_CALL(cdm, DetachEventListener(_, _))
|
||||
.Times(AtLeast(0));
|
||||
|
||||
EXPECT_CALL(cdm, CloseSession(_))
|
||||
.Times(AtLeast(0));
|
||||
}
|
||||
|
||||
status_t res;
|
||||
|
||||
// Test turning on session sharing
|
||||
res = plugin.setPropertyString(String8("sessionSharing"), String8("enable"));
|
||||
ASSERT_EQ(OK, res);
|
||||
|
||||
plugin.openSession(sessionId);
|
||||
ASSERT_THAT(propertySet, NotNull());
|
||||
EXPECT_TRUE(propertySet->is_session_sharing_enabled());
|
||||
plugin.closeSession(sessionId);
|
||||
|
||||
// Test turning off session sharing
|
||||
res = plugin.setPropertyString(String8("sessionSharing"), String8("disable"));
|
||||
ASSERT_EQ(OK, res);
|
||||
|
||||
plugin.openSession(sessionId);
|
||||
ASSERT_THAT(propertySet, NotNull());
|
||||
EXPECT_FALSE(propertySet->is_session_sharing_enabled());
|
||||
plugin.closeSession(sessionId);
|
||||
|
||||
// Test nonsense (Should Fail)
|
||||
res = plugin.setPropertyString(String8("sessionSharing"), String8("nonsense"));
|
||||
ASSERT_NE(OK, res);
|
||||
|
||||
// Test changing sharing with a session open (Should Fail)
|
||||
plugin.openSession(sessionId);
|
||||
res = plugin.setPropertyString(String8("sessionSharing"), String8("enable"));
|
||||
ASSERT_NE(OK, res);
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, AllowsStoringOfSessionSharingId) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
StrictMock<MockCrypto> crypto;
|
||||
WVDrmPlugin plugin(&cdm, &crypto);
|
||||
|
||||
CdmClientPropertySet* propertySet = NULL;
|
||||
|
||||
uint32_t sharingId;
|
||||
FILE* fp = fopen("/dev/urandom", "r");
|
||||
fread(&sharingId, sizeof(uint32_t), 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
// Provide expected mock behavior
|
||||
{
|
||||
// Provide expected behavior in response to OpenSession and store the
|
||||
// property set
|
||||
EXPECT_CALL(cdm, OpenSession(_, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<2>(cdmSessionId),
|
||||
SaveArg<1>(&propertySet),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
// Provide expected behavior when plugin requests session control info
|
||||
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
|
||||
.WillRepeatedly(Invoke(setSessionIdOnMap<4>));
|
||||
|
||||
// Let gMock know these calls will happen but we aren't interested in them.
|
||||
EXPECT_CALL(cdm, AttachEventListener(_, _))
|
||||
.Times(AtLeast(0));
|
||||
|
||||
EXPECT_CALL(cdm, DetachEventListener(_, _))
|
||||
.Times(AtLeast(0));
|
||||
|
||||
EXPECT_CALL(cdm, CloseSession(_))
|
||||
.Times(AtLeast(0));
|
||||
}
|
||||
|
||||
plugin.openSession(sessionId);
|
||||
|
||||
ASSERT_THAT(propertySet, NotNull());
|
||||
propertySet->set_session_sharing_id(sharingId);
|
||||
EXPECT_EQ(sharingId, propertySet->session_sharing_id());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user