am 20191d99: Allow Secure Stops to be queried and deleted by application ID
* commit '20191d996c1aace4544e0b59466e3a0321e6b980': Allow Secure Stops to be queried and deleted by application ID
This commit is contained in:
@@ -19,6 +19,7 @@ class CdmClientPropertySet {
|
||||
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;
|
||||
virtual const std::string& app_id() const = 0;
|
||||
};
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -93,7 +93,16 @@ class CdmEngine {
|
||||
virtual CdmResponseType Unprovision(CdmSecurityLevel security_level);
|
||||
|
||||
// Usage related methods for streaming licenses
|
||||
virtual CdmResponseType GetUsageInfo(CdmUsageInfo* usage_info);
|
||||
// Retrieve a random usage info from the list of all usage infos for this app
|
||||
// id.
|
||||
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
|
||||
CdmUsageInfo* usage_info);
|
||||
// Retrieve the usage info for the specified pst.
|
||||
// Returns UNKNOWN_ERROR if no usage info was found.
|
||||
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
CdmUsageInfo* usage_info);
|
||||
virtual CdmResponseType ReleaseAllUsageInfo(const std::string& app_id);
|
||||
virtual CdmResponseType ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message);
|
||||
|
||||
@@ -120,7 +129,8 @@ class CdmEngine {
|
||||
private:
|
||||
// private methods
|
||||
bool ValidateKeySystem(const CdmKeySystem& key_system);
|
||||
CdmResponseType GetUsageInfo(SecurityLevel requested_security_level,
|
||||
CdmResponseType GetUsageInfo(const std::string& app_id,
|
||||
SecurityLevel requested_security_level,
|
||||
CdmUsageInfo* usage_info);
|
||||
|
||||
void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
|
||||
|
||||
@@ -83,9 +83,11 @@ class CdmSession {
|
||||
virtual void OnTimerEvent(bool update_usage);
|
||||
virtual void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
|
||||
|
||||
virtual void GetApplicationId(std::string* app_id);
|
||||
virtual SecurityLevel GetRequestedSecurityLevel();
|
||||
virtual CdmSecurityLevel GetSecurityLevel();
|
||||
|
||||
virtual CdmResponseType DeleteUsageInformation(const std::string& app_id);
|
||||
virtual CdmResponseType UpdateUsageInformation();
|
||||
|
||||
virtual bool is_initial_usage_update() { return is_initial_usage_update_; }
|
||||
@@ -120,6 +122,7 @@ class CdmSession {
|
||||
bool is_offline_;
|
||||
bool is_release_;
|
||||
CdmSecurityLevel security_level_;
|
||||
std::string app_id_;
|
||||
|
||||
// decryption and usage flags
|
||||
bool is_initial_decryption_;
|
||||
|
||||
@@ -62,11 +62,22 @@ class DeviceFiles {
|
||||
|
||||
virtual bool StoreUsageInfo(const std::string& provider_session_token,
|
||||
const CdmKeyMessage& key_request,
|
||||
const CdmKeyResponse& key_response);
|
||||
virtual bool DeleteUsageInfo(const std::string& provider_session_token);
|
||||
virtual bool DeleteUsageInfo();
|
||||
const CdmKeyResponse& key_response,
|
||||
const std::string& app_id);
|
||||
virtual bool DeleteUsageInfo(const std::string& app_id,
|
||||
const std::string& provider_session_token);
|
||||
virtual bool DeleteAllUsageInfoForApp(const std::string& app_id);
|
||||
// Retrieve one usage info from the file. Subsequent calls will retrieve
|
||||
// subsequent entries in the table for this app_id.
|
||||
virtual bool RetrieveUsageInfo(
|
||||
const std::string& app_id,
|
||||
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> >* usage_info);
|
||||
// Retrieve the usage info entry specified by |provider_session_token|.
|
||||
// Returns false if the entry could not be found.
|
||||
virtual bool RetrieveUsageInfo(const std::string& app_id,
|
||||
const std::string& provider_session_token,
|
||||
CdmKeyMessage* license_request,
|
||||
CdmKeyResponse* license_response);
|
||||
|
||||
private:
|
||||
bool StoreFile(const char* name, const std::string& serialized_file);
|
||||
@@ -80,7 +91,7 @@ class DeviceFiles {
|
||||
// For testing only:
|
||||
static std::string GetCertificateFileName();
|
||||
static std::string GetLicenseFileNameExtension();
|
||||
static std::string GetUsageInfoFileName();
|
||||
static std::string GetUsageInfoFileName(const std::string& app_id);
|
||||
void SetTestFile(File* file);
|
||||
#if defined(UNIT_TEST)
|
||||
FRIEND_TEST(DeviceFilesSecurityLevelTest, SecurityLevel);
|
||||
|
||||
@@ -53,6 +53,8 @@ class Properties {
|
||||
static bool GetFactoryKeyboxPath(std::string* keybox);
|
||||
static bool GetOEMCryptoPath(std::string* library_name);
|
||||
static bool GetSecurityLevelDirectories(std::vector<std::string>* dirs);
|
||||
static bool GetApplicationId(const CdmSessionId& session_id,
|
||||
std::string* app_id);
|
||||
static bool GetSecurityLevel(const CdmSessionId& session_id,
|
||||
std::string* security_level);
|
||||
static bool GetServiceCertificate(const CdmSessionId& session_id,
|
||||
|
||||
@@ -15,6 +15,7 @@ typedef std::string CdmInitData;
|
||||
typedef std::string CdmKeyMessage;
|
||||
typedef std::string CdmKeyResponse;
|
||||
typedef std::string KeyId;
|
||||
typedef std::string CdmSecureStopId;
|
||||
typedef std::string CdmSessionId;
|
||||
typedef std::string CdmKeySetId;
|
||||
typedef std::string RequestId;
|
||||
|
||||
@@ -43,7 +43,11 @@ class UsagePropertySet : public CdmClientPropertySet {
|
||||
virtual void set_session_sharing_id(uint32_t id) {
|
||||
id; // noop to suppress warning
|
||||
}
|
||||
virtual const std::string& app_id() const { return app_id_; }
|
||||
void set_app_id(const std::string& appId) { app_id_ = appId; }
|
||||
|
||||
private:
|
||||
std::string app_id_;
|
||||
std::string security_level_;
|
||||
const std::string empty_;
|
||||
};
|
||||
@@ -582,29 +586,95 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
CdmUsageInfo* usage_info) {
|
||||
if (NULL == usage_property_set_.get()) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
}
|
||||
usage_property_set_->set_security_level(kLevelDefault);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
usage_session_.reset(new CdmSession(usage_property_set_.get()));
|
||||
CdmResponseType status = usage_session_->Init();
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error");
|
||||
return status;
|
||||
}
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(usage_session_->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::GetUsageInfo: device file init error");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
CdmKeyMessage license_request;
|
||||
CdmKeyResponse license_response;
|
||||
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
|
||||
&license_response)) {
|
||||
usage_property_set_->set_security_level(kLevel3);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
usage_session_.reset(new CdmSession(usage_property_set_.get()));
|
||||
status = usage_session_->Init();
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error");
|
||||
return status;
|
||||
}
|
||||
if (!handle.Reset(usage_session_->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::GetUsageInfo: device file init error");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
|
||||
&license_response)) {
|
||||
// No entry found for that ssid.
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
std::string server_url;
|
||||
usage_info->resize(1);
|
||||
status =
|
||||
usage_session_->RestoreUsageSession(license_request, license_response);
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: restore usage session error %d", status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
|
||||
status =
|
||||
usage_session_->GenerateReleaseRequest(&(*usage_info)[0], &server_url);
|
||||
|
||||
if (KEY_MESSAGE != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %d", status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
CdmUsageInfo* usage_info) {
|
||||
// Return a random usage report from a random security level
|
||||
SecurityLevel security_level = ((rand() % 2) == 0) ? kLevelDefault : kLevel3;
|
||||
CdmResponseType status = GetUsageInfo(security_level, usage_info);
|
||||
CdmResponseType status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
|
||||
if (KEY_MESSAGE == status && !usage_info->empty())
|
||||
return status;
|
||||
|
||||
security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3;
|
||||
status = GetUsageInfo(security_level, usage_info);
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
if (NEED_PROVISIONING == status)
|
||||
return NO_ERROR; // Valid scenario that one of the security
|
||||
// levels has not been provisioned
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(
|
||||
SecurityLevel requested_security_level,
|
||||
CdmUsageInfo* usage_info) {
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
SecurityLevel requested_security_level,
|
||||
CdmUsageInfo* usage_info) {
|
||||
if (NULL == usage_property_set_.get()) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
}
|
||||
usage_property_set_->set_security_level(requested_security_level);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
|
||||
usage_session_.reset(new CdmSession(usage_property_set_.get()));
|
||||
|
||||
@@ -617,11 +687,11 @@ CdmResponseType CdmEngine::GetUsageInfo(
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(usage_session_->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::GetUsageInfo: unable to initialize device files");
|
||||
return status;
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
|
||||
if (!handle.RetrieveUsageInfo(&license_info)) {
|
||||
if (!handle.RetrieveUsageInfo(app_id, &license_info)) {
|
||||
LOGE("CdmEngine::GetUsageInfo: unable to read usage information");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
@@ -655,6 +725,23 @@ CdmResponseType CdmEngine::GetUsageInfo(
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
CdmResponseType status = NO_ERROR;
|
||||
DeviceFiles handle[kSecurityLevelUnknown - kSecurityLevelL1];
|
||||
for (int i = 0, j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++i, ++j) {
|
||||
if (handle[i].Init(static_cast<CdmSecurityLevel>(j))) {
|
||||
if (!handle[i].DeleteAllUsageInfoForApp(app_id)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure stops", j);
|
||||
status = UNKNOWN_ERROR;
|
||||
}
|
||||
} else {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to initialize L%d device files", j);
|
||||
status = UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message) {
|
||||
if (NULL == usage_session_.get()) {
|
||||
|
||||
@@ -81,6 +81,7 @@ void CdmSession::Create(
|
||||
}
|
||||
security_level_ = GetRequestedSecurityLevel() == kLevel3
|
||||
? kSecurityLevelL3 : GetSecurityLevel();
|
||||
app_id_.clear();
|
||||
}
|
||||
|
||||
CdmSession::~CdmSession() { Properties::RemoveSessionPropertySet(session_id_); }
|
||||
@@ -503,8 +504,10 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_,
|
||||
key_response_)) {
|
||||
key_response_, app_id)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to store usage info");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
@@ -532,11 +535,14 @@ bool CdmSession::DeleteLicense() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_offline_)
|
||||
if (is_offline_) {
|
||||
return file_handle_->DeleteLicense(key_set_id_);
|
||||
else
|
||||
} else {
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
return file_handle_->DeleteUsageInfo(
|
||||
license_parser_->provider_session_token());
|
||||
app_id, license_parser_->provider_session_token());
|
||||
}
|
||||
}
|
||||
|
||||
bool CdmSession::AttachEventListener(WvCdmEventListener* listener) {
|
||||
@@ -579,6 +585,12 @@ void CdmSession::OnKeyReleaseEvent(const CdmKeySetId& key_set_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void CdmSession::GetApplicationId(std::string* app_id) {
|
||||
if (app_id && !Properties::GetApplicationId(session_id_, app_id)) {
|
||||
*app_id = "";
|
||||
}
|
||||
}
|
||||
|
||||
SecurityLevel CdmSession::GetRequestedSecurityLevel() {
|
||||
std::string security_level;
|
||||
if (Properties::GetSecurityLevel(session_id_, &security_level) &&
|
||||
@@ -596,6 +608,20 @@ CdmSecurityLevel CdmSession::GetSecurityLevel() {
|
||||
return crypto_session_.get()->GetSecurityLevel();
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::DeleteUsageInformation(const std::string& app_id) {
|
||||
if (!file_handle_->Reset(security_level_)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to initialize device files");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (file_handle_->DeleteAllUsageInfoForApp(app_id)) {
|
||||
return NO_ERROR;
|
||||
} else {
|
||||
LOGE("CdmSession::DeleteUsageInformation: failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::UpdateUsageInformation() {
|
||||
return crypto_session_->UpdateUsageInformation();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
|
||||
#else
|
||||
# include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
@@ -31,7 +32,8 @@ using video_widevine_client::sdk::UsageInfo_ProviderSession;
|
||||
namespace {
|
||||
|
||||
const char kCertificateFileName[] = "cert.bin";
|
||||
const char kUsageInfoFileName[] = "usage.bin";
|
||||
const char kUsageInfoFileNamePrefix[] = "usage";
|
||||
const char kUsageInfoFileNameExt[] = ".bin";
|
||||
const char kLicenseFileNameExt[] = ".lic";
|
||||
const char kWildcard[] = "*";
|
||||
const char kDirectoryDelimiter = '/';
|
||||
@@ -329,7 +331,8 @@ bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
|
||||
|
||||
bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
|
||||
const CdmKeyMessage& key_request,
|
||||
const CdmKeyResponse& key_response) {
|
||||
const CdmKeyResponse& key_response,
|
||||
const std::string& app_id) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::StoreUsageInfo: not initialized");
|
||||
return false;
|
||||
@@ -337,7 +340,8 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
|
||||
|
||||
std::string serialized_file;
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!RetrieveFile(kUsageInfoFileName, &serialized_file)) {
|
||||
std::string file_name = GetUsageInfoFileName(app_id);
|
||||
if (!RetrieveFile(file_name.c_str(), &serialized_file)) {
|
||||
file.set_type(video_widevine_client::sdk::File::USAGE_INFO);
|
||||
file.set_version(video_widevine_client::sdk::File::VERSION_1);
|
||||
} else {
|
||||
@@ -358,17 +362,19 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
|
||||
key_response.size());
|
||||
|
||||
file.SerializeToString(&serialized_file);
|
||||
return StoreFile(kUsageInfoFileName, serialized_file);
|
||||
return StoreFile(file_name.c_str(), serialized_file);
|
||||
}
|
||||
|
||||
bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
|
||||
bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
|
||||
const std::string& provider_session_token) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string serialized_file;
|
||||
if (!RetrieveFile(kUsageInfoFileName, &serialized_file)) return false;
|
||||
std::string file_name = GetUsageInfoFileName(app_id);
|
||||
if (!RetrieveFile(file_name.c_str(), &serialized_file)) return false;
|
||||
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!file.ParseFromString(serialized_file)) {
|
||||
@@ -400,27 +406,29 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
|
||||
sessions->RemoveLast();
|
||||
|
||||
file.SerializeToString(&serialized_file);
|
||||
return StoreFile(kUsageInfoFileName, serialized_file);
|
||||
return StoreFile(file_name.c_str(), serialized_file);
|
||||
}
|
||||
|
||||
bool DeviceFiles::DeleteUsageInfo() {
|
||||
bool DeviceFiles::DeleteAllUsageInfoForApp(const std::string& app_id) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
|
||||
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string path;
|
||||
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
|
||||
LOGW("DeviceFiles::DeleteUsageInfo: Unable to get base path");
|
||||
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to get base path");
|
||||
return false;
|
||||
}
|
||||
path.append(kUsageInfoFileName);
|
||||
std::string file_name = GetUsageInfoFileName(app_id);
|
||||
path.append(file_name);
|
||||
|
||||
return file_->Remove(path);
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveUsageInfo(std::vector<
|
||||
std::pair<CdmKeyMessage, CdmKeyResponse> >* usage_info) {
|
||||
bool DeviceFiles::RetrieveUsageInfo(
|
||||
const std::string &app_id,
|
||||
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> >* usage_info) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
|
||||
return false;
|
||||
@@ -433,13 +441,14 @@ bool DeviceFiles::RetrieveUsageInfo(std::vector<
|
||||
}
|
||||
|
||||
std::string serialized_file;
|
||||
if (!RetrieveFile(kUsageInfoFileName, &serialized_file)) {
|
||||
std::string file_name = GetUsageInfoFileName(app_id);
|
||||
if (!RetrieveFile(file_name.c_str(), &serialized_file)) {
|
||||
std::string path;
|
||||
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
path += kUsageInfoFileName;
|
||||
path += file_name;
|
||||
|
||||
if (!file_->Exists(path) || 0 == file_->FileSize(path)) {
|
||||
usage_info->resize(0);
|
||||
@@ -465,6 +474,42 @@ bool DeviceFiles::RetrieveUsageInfo(std::vector<
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
|
||||
const std::string& provider_session_token,
|
||||
CdmKeyMessage* license_request,
|
||||
CdmKeyResponse* license_response) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
|
||||
return false;
|
||||
}
|
||||
std::string serialized_file;
|
||||
std::string file_name = GetUsageInfoFileName(app_id);
|
||||
if (!RetrieveFile(file_name.c_str(), &serialized_file)) return false;
|
||||
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!file.ParseFromString(serialized_file)) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: Unable to parse file");
|
||||
return false;
|
||||
}
|
||||
int index = 0;
|
||||
bool found = false;
|
||||
for (; index < file.usage_info().sessions_size(); ++index) {
|
||||
if (file.usage_info().sessions(index).token().compare(
|
||||
provider_session_token) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*license_request = file.usage_info().sessions(index).license_request();
|
||||
*license_response = file.usage_info().sessions(index).license();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceFiles::StoreFile(const char* name,
|
||||
const std::string& serialized_file) {
|
||||
if (!file_.get()) {
|
||||
@@ -671,8 +716,15 @@ std::string DeviceFiles::GetLicenseFileNameExtension() {
|
||||
return kLicenseFileNameExt;
|
||||
}
|
||||
|
||||
std::string DeviceFiles::GetUsageInfoFileName() {
|
||||
return kUsageInfoFileName;
|
||||
std::string DeviceFiles::GetUsageInfoFileName(const std::string& app_id) {
|
||||
if (app_id == "") return std::string(kUsageInfoFileNamePrefix)
|
||||
+ std::string(kUsageInfoFileNameExt);
|
||||
std::vector<uint8_t> hash(MD5_DIGEST_LENGTH);
|
||||
const unsigned char* input =
|
||||
reinterpret_cast<const unsigned char*>(app_id.data());
|
||||
MD5(input, app_id.size(), &hash[0]);
|
||||
return std::string(kUsageInfoFileNamePrefix) + wvcdm::Base64SafeEncode(hash) +
|
||||
std::string(kUsageInfoFileNameExt);
|
||||
}
|
||||
|
||||
void DeviceFiles::SetTestFile(File* file) {
|
||||
|
||||
@@ -60,6 +60,17 @@ const CdmClientPropertySet* Properties::GetCdmClientPropertySet(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Properties::GetApplicationId(const CdmSessionId& session_id,
|
||||
std::string* app_id) {
|
||||
const CdmClientPropertySet* property_set =
|
||||
GetCdmClientPropertySet(session_id);
|
||||
if (NULL == property_set) {
|
||||
return false;
|
||||
}
|
||||
*app_id = property_set->app_id();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Properties::GetSecurityLevel(const CdmSessionId& session_id,
|
||||
std::string* security_level) {
|
||||
const CdmClientPropertySet* property_set =
|
||||
|
||||
@@ -1747,7 +1747,8 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, Read) {
|
||||
MockFile file;
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageInfoFileName();
|
||||
std::string app_id; // TODO(fredgc): expand tests.
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageInfoFileName(app_id);
|
||||
|
||||
int index = GetParam();
|
||||
std::string data;
|
||||
@@ -1777,7 +1778,7 @@ TEST_P(DeviceFilesUsageInfoTest, Read) {
|
||||
device_files.SetTestFile(&file);
|
||||
|
||||
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
|
||||
ASSERT_TRUE(device_files.RetrieveUsageInfo(&license_info));
|
||||
ASSERT_TRUE(device_files.RetrieveUsageInfo(app_id, &license_info));
|
||||
if (index >= 0) {
|
||||
EXPECT_EQ(index, license_info.size());
|
||||
for (size_t i = 0; i < license_info.size(); ++i) {
|
||||
@@ -1799,10 +1800,11 @@ TEST_P(DeviceFilesUsageInfoTest, Read) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, Store) {
|
||||
MockFile file;
|
||||
std::string app_id; // TODO(fredgc): expand tests.
|
||||
std::string pst(GenerateRandomData(kProviderSessionTokenLen));
|
||||
std::string license_request(GenerateRandomData(kLicenseRequestLen));
|
||||
std::string license(GenerateRandomData(kLicenseLen));
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageInfoFileName();
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageInfoFileName(app_id);
|
||||
|
||||
int index = GetParam();
|
||||
std::string data;
|
||||
@@ -1836,12 +1838,13 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
device_files.SetTestFile(&file);
|
||||
|
||||
ASSERT_TRUE(device_files.StoreUsageInfo(pst, license_request, license));
|
||||
ASSERT_TRUE(device_files.StoreUsageInfo(pst, license_request, license, app_id));
|
||||
}
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, Delete) {
|
||||
MockFile file;
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageInfoFileName();
|
||||
std::string app_id; // TODO(fredgc): expand tests.
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageInfoFileName(app_id);
|
||||
|
||||
int index = GetParam();
|
||||
if (index < 0) return;
|
||||
@@ -1886,9 +1889,9 @@ TEST_P(DeviceFilesUsageInfoTest, Delete) {
|
||||
device_files.SetTestFile(&file);
|
||||
|
||||
if (index >= 1) {
|
||||
ASSERT_TRUE(device_files.DeleteUsageInfo(pst));
|
||||
ASSERT_TRUE(device_files.DeleteUsageInfo(app_id, pst));
|
||||
} else {
|
||||
ASSERT_FALSE(device_files.DeleteUsageInfo(pst));
|
||||
ASSERT_FALSE(device_files.DeleteUsageInfo(app_id, pst));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,12 @@ class WvContentDecryptionModule : public TimerHandler {
|
||||
virtual CdmResponseType Unprovision(CdmSecurityLevel level);
|
||||
|
||||
// Secure stop related methods
|
||||
virtual CdmResponseType GetUsageInfo(CdmUsageInfo* usage_info);
|
||||
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
|
||||
CdmUsageInfo* usage_info);
|
||||
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
CdmUsageInfo* usage_info);
|
||||
virtual CdmResponseType ReleaseAllUsageInfo(const std::string& app_id);
|
||||
virtual CdmResponseType ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message);
|
||||
|
||||
|
||||
@@ -159,8 +159,20 @@ CdmResponseType WvContentDecryptionModule::Unprovision(
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
const std::string& app_id, CdmUsageInfo* usage_info) {
|
||||
return cdm_engine_->GetUsageInfo(app_id, usage_info);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
CdmUsageInfo* usage_info) {
|
||||
return cdm_engine_->GetUsageInfo(usage_info);
|
||||
return cdm_engine_->GetUsageInfo(app_id, ssid, usage_info);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::ReleaseAllUsageInfo(
|
||||
const std::string& app_id) {
|
||||
return cdm_engine_->ReleaseAllUsageInfo(app_id);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::ReleaseUsageInfo(
|
||||
|
||||
@@ -1022,7 +1022,8 @@ TEST_P(WvCdmStreamingUsageReportTest, UsageTest) {
|
||||
uint32_t num_usage_info = 0;
|
||||
CdmUsageInfo usage_info;
|
||||
CdmUsageInfoReleaseMessage release_msg;
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(&usage_info);
|
||||
std::string app_id;
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(app_id, &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
while (usage_info.size() > 0) {
|
||||
for (size_t i = 0; i < usage_info.size(); ++i) {
|
||||
@@ -1034,7 +1035,7 @@ TEST_P(WvCdmStreamingUsageReportTest, UsageTest) {
|
||||
GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[i]);
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg));
|
||||
}
|
||||
status = decryptor_.GetUsageInfo(&usage_info);
|
||||
status = decryptor_.GetUsageInfo(app_id, &usage_info);
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
EXPECT_FALSE(usage_info.empty());
|
||||
|
||||
@@ -393,6 +393,7 @@ class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
session_sharing_id_(0) {}
|
||||
virtual ~TestWvCdmClientPropertySet() {}
|
||||
|
||||
virtual const std::string& app_id() const { return app_id_; }
|
||||
virtual const std::string& security_level() const { return security_level_; }
|
||||
virtual const std::string& service_certificate() const {
|
||||
return service_certificate_;
|
||||
@@ -403,6 +404,7 @@ class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
}
|
||||
virtual uint32_t session_sharing_id() const { return session_sharing_id_; }
|
||||
|
||||
void set_app_id(const std::string& app_id) { app_id_ = app_id; }
|
||||
void set_security_level(const std::string& security_level) {
|
||||
if (!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L1) ||
|
||||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3)) {
|
||||
@@ -421,6 +423,7 @@ class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
void set_session_sharing_id(uint32_t id) { session_sharing_id_ = id; }
|
||||
|
||||
private:
|
||||
std::string app_id_;
|
||||
std::string security_level_;
|
||||
std::string service_certificate_;
|
||||
bool use_privacy_mode_;
|
||||
@@ -830,6 +833,14 @@ TEST_F(WvCdmRequestLicenseTest, PropertySetTest) {
|
||||
EXPECT_TRUE(security_level.empty() ||
|
||||
!security_level.compare(QUERY_VALUE_SECURITY_LEVEL_L3));
|
||||
|
||||
std::string app_id = "not empty";
|
||||
EXPECT_TRUE(Properties::GetApplicationId(session_id_Ln, &app_id));
|
||||
EXPECT_STREQ("", app_id.c_str());
|
||||
|
||||
property_set_Ln.set_app_id("com.unittest.mock.app.id");
|
||||
EXPECT_TRUE(Properties::GetApplicationId(session_id_Ln, &app_id));
|
||||
EXPECT_STREQ("com.unittest.mock.app.id", app_id.c_str());
|
||||
|
||||
decryptor_.CloseSession(session_id_L1);
|
||||
decryptor_.CloseSession(session_id_L3);
|
||||
decryptor_.CloseSession(session_id_Ln);
|
||||
@@ -1202,7 +1213,7 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
||||
EXPECT_TRUE(handle.Init(security_level));
|
||||
File file;
|
||||
handle.SetTestFile(&file);
|
||||
EXPECT_TRUE(handle.DeleteUsageInfo());
|
||||
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp("")); // default app_id.
|
||||
|
||||
for (size_t i = 0; i < usage_info_data->usage_info; ++i) {
|
||||
SubSampleInfo* data = usage_info_data->sub_sample + i;
|
||||
@@ -1236,7 +1247,8 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
||||
uint32_t num_usage_info = 0;
|
||||
CdmUsageInfo usage_info;
|
||||
CdmUsageInfoReleaseMessage release_msg;
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(&usage_info);
|
||||
CdmResponseType status =
|
||||
decryptor_.GetUsageInfo(property_set->app_id(), &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
while (usage_info.size() > 0) {
|
||||
for (size_t i = 0; i < usage_info.size(); ++i) {
|
||||
@@ -1244,7 +1256,7 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
||||
GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[i]);
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg));
|
||||
}
|
||||
status = decryptor_.GetUsageInfo(&usage_info);
|
||||
status = decryptor_.GetUsageInfo(property_set->app_id(), &usage_info);
|
||||
switch (status) {
|
||||
case KEY_MESSAGE: EXPECT_FALSE(usage_info.empty()); break;
|
||||
case NO_ERROR: EXPECT_TRUE(usage_info.empty()); break;
|
||||
|
||||
@@ -85,8 +85,13 @@ class WVDrmPlugin : public android::DrmPlugin,
|
||||
|
||||
virtual status_t unprovisionDevice();
|
||||
|
||||
virtual status_t getSecureStop(const Vector<uint8_t>& ssid,
|
||||
Vector<uint8_t>& secureStop);
|
||||
|
||||
virtual status_t getSecureStops(List<Vector<uint8_t> >& secureStops);
|
||||
|
||||
virtual status_t releaseAllSecureStops();
|
||||
|
||||
virtual status_t releaseSecureStops(const Vector<uint8_t>& ssRelease);
|
||||
|
||||
virtual status_t getPropertyString(const String8& name, String8& value) const;
|
||||
@@ -219,6 +224,14 @@ class WVDrmPlugin : public android::DrmPlugin,
|
||||
mSessionSharingId = id;
|
||||
}
|
||||
|
||||
virtual const std::string& app_id() const {
|
||||
return mAppId;
|
||||
}
|
||||
|
||||
void set_app_id(const std::string& appId) {
|
||||
mAppId = appId;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_EVIL_CONSTRUCTORS(WVClientPropertySet);
|
||||
|
||||
@@ -227,6 +240,7 @@ class WVDrmPlugin : public android::DrmPlugin,
|
||||
std::string mServiceCertificate;
|
||||
bool mShareKeys;
|
||||
uint32_t mSessionSharingId;
|
||||
std::string mAppId;
|
||||
} mPropertySet;
|
||||
|
||||
WvContentDecryptionModule* mCDM;
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace {
|
||||
static const char* const kResetSecurityLevel = "";
|
||||
static const char* const kEnable = "enable";
|
||||
static const char* const kDisable = "disable";
|
||||
|
||||
static const std::string kPsshTag = "pssh";
|
||||
}
|
||||
|
||||
@@ -394,9 +393,30 @@ status_t WVDrmPlugin::unprovisionDevice() {
|
||||
}
|
||||
}
|
||||
|
||||
status_t WVDrmPlugin::getSecureStop(const Vector<uint8_t>& ssid,
|
||||
Vector<uint8_t>& secureStop) {
|
||||
CdmUsageInfo cdmUsageInfo;
|
||||
CdmSecureStopId cdmSsid(ssid.begin(), ssid.end());
|
||||
CdmResponseType res = mCDM->GetUsageInfo(
|
||||
mPropertySet.app_id(), cdmSsid, &cdmUsageInfo);
|
||||
if (isCdmResponseTypeSuccess(res)) {
|
||||
secureStop.clear();
|
||||
for (CdmUsageInfo::const_iterator iter = cdmUsageInfo.begin();
|
||||
iter != cdmUsageInfo.end();
|
||||
++iter) {
|
||||
const string& cdmStop = *iter;
|
||||
|
||||
secureStop.appendArray(reinterpret_cast<const uint8_t*>(cdmStop.data()),
|
||||
cdmStop.size());
|
||||
}
|
||||
}
|
||||
return mapCdmResponseType(res);
|
||||
}
|
||||
|
||||
status_t WVDrmPlugin::getSecureStops(List<Vector<uint8_t> >& secureStops) {
|
||||
CdmUsageInfo cdmUsageInfo;
|
||||
CdmResponseType res = mCDM->GetUsageInfo(&cdmUsageInfo);
|
||||
CdmResponseType res =
|
||||
mCDM->GetUsageInfo(mPropertySet.app_id(), &cdmUsageInfo);
|
||||
if (isCdmResponseTypeSuccess(res)) {
|
||||
secureStops.clear();
|
||||
for (CdmUsageInfo::const_iterator iter = cdmUsageInfo.begin();
|
||||
@@ -414,6 +434,11 @@ status_t WVDrmPlugin::getSecureStops(List<Vector<uint8_t> >& secureStops) {
|
||||
return mapCdmResponseType(res);
|
||||
}
|
||||
|
||||
status_t WVDrmPlugin::releaseAllSecureStops() {
|
||||
CdmResponseType res = mCDM->ReleaseAllUsageInfo(mPropertySet.app_id());
|
||||
return mapCdmResponseType(res);
|
||||
}
|
||||
|
||||
status_t WVDrmPlugin::releaseSecureStops(const Vector<uint8_t>& ssRelease) {
|
||||
CdmUsageInfoReleaseMessage cdmMessage(ssRelease.begin(), ssRelease.end());
|
||||
CdmResponseType res = mCDM->ReleaseUsageInfo(cdmMessage);
|
||||
@@ -628,6 +653,18 @@ status_t WVDrmPlugin::setPropertyString(const String8& name,
|
||||
ALOGE("App tried to change key sharing while sessions are open.");
|
||||
return kErrorSessionIsOpen;
|
||||
}
|
||||
} else if (name == "appId") {
|
||||
size_t sessionCount = 0;
|
||||
{
|
||||
Mutex::Autolock lock(mCryptoSessionsMutex);
|
||||
sessionCount = mCryptoSessions.size();
|
||||
}
|
||||
if (sessionCount == 0) {
|
||||
mPropertySet.set_app_id(value.string());
|
||||
} else {
|
||||
ALOGE("App tried to set the application id while sessions are opened.");
|
||||
return kErrorSessionIsOpen;
|
||||
}
|
||||
} else {
|
||||
ALOGE("App set unknown string property %s", name.string());
|
||||
return android::ERROR_DRM_CANNOT_HANDLE;
|
||||
|
||||
@@ -12,6 +12,7 @@ LOCAL_C_INCLUDES := \
|
||||
frameworks/native/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/core/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/include \
|
||||
vendor/widevine/libwvdrmengine/include \
|
||||
vendor/widevine/libwvdrmengine/mediadrm/include \
|
||||
vendor/widevine/libwvdrmengine/oemcrypto/include \
|
||||
vendor/widevine/libwvdrmengine/test/gmock/include \
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_content_decryption_module.h"
|
||||
#include "WVDrmPlugin.h"
|
||||
#include "WVErrors.h"
|
||||
|
||||
using namespace android;
|
||||
using namespace std;
|
||||
@@ -65,10 +66,17 @@ class MockCDM : public WvContentDecryptionModule {
|
||||
MOCK_METHOD3(HandleProvisioningResponse,
|
||||
CdmResponseType(CdmProvisioningResponse&, std::string*, std::string*));
|
||||
|
||||
MOCK_METHOD1(GetUsageInfo, CdmResponseType(CdmUsageInfo*));
|
||||
MOCK_METHOD2(GetUsageInfo, CdmResponseType(const std::string&,
|
||||
CdmUsageInfo*));
|
||||
|
||||
MOCK_METHOD3(GetUsageInfo, CdmResponseType(const std::string&,
|
||||
const CdmSecureStopId&,
|
||||
CdmUsageInfo*));
|
||||
|
||||
MOCK_METHOD1(Unprovision, CdmResponseType(CdmSecurityLevel));
|
||||
|
||||
MOCK_METHOD1(ReleaseAllUsageInfo, CdmResponseType(const std::string&));
|
||||
|
||||
MOCK_METHOD1(ReleaseUsageInfo,
|
||||
CdmResponseType(const CdmUsageInfoReleaseMessage&));
|
||||
|
||||
@@ -599,6 +607,8 @@ TEST_F(WVDrmPluginTest, GetsSecureStops) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
StrictMock<MockCrypto> crypto;
|
||||
WVDrmPlugin plugin(&cdm, &crypto);
|
||||
const char* app_id = "my_app_id";
|
||||
plugin.setPropertyString(String8("appId"), String8(app_id));
|
||||
|
||||
static const uint32_t kStopSize = 53;
|
||||
static const uint32_t kStopCount = 7;
|
||||
@@ -614,8 +624,8 @@ TEST_F(WVDrmPluginTest, GetsSecureStops) {
|
||||
cdmStops.push_back(string(stopsRaw[i], stopsRaw[i] + kStopSize));
|
||||
}
|
||||
|
||||
EXPECT_CALL(cdm, GetUsageInfo(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(cdmStops),
|
||||
EXPECT_CALL(cdm, GetUsageInfo(StrEq(app_id), _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(cdmStops),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
List<Vector<uint8_t> > stops;
|
||||
@@ -637,6 +647,21 @@ TEST_F(WVDrmPluginTest, GetsSecureStops) {
|
||||
EXPECT_EQ(stops.end(), iter);
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, ReleasesAllSecureStops) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
StrictMock<MockCrypto> crypto;
|
||||
WVDrmPlugin plugin(&cdm, &crypto);
|
||||
|
||||
status_t res = plugin.setPropertyString(String8("appId"), String8(""));
|
||||
ASSERT_EQ(OK, res);
|
||||
|
||||
EXPECT_CALL(cdm, ReleaseAllUsageInfo(StrEq("")))
|
||||
.Times(1);
|
||||
|
||||
res = plugin.releaseAllSecureStops();
|
||||
ASSERT_EQ(OK, res);
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, ReleasesSecureStops) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
StrictMock<MockCrypto> crypto;
|
||||
@@ -1309,6 +1334,59 @@ TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) {
|
||||
EXPECT_EQ(0u, propertySet->service_certificate().size());
|
||||
EXPECT_FALSE(propertySet->is_session_sharing_enabled());
|
||||
EXPECT_EQ(0u, propertySet->session_sharing_id());
|
||||
EXPECT_STREQ("", propertySet->app_id().c_str());
|
||||
}
|
||||
TEST_F(WVDrmPluginTest, CanSetAppId) {
|
||||
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 setting an empty string
|
||||
res = plugin.setPropertyString(String8("appId"), String8(""));
|
||||
ASSERT_EQ(OK, res);
|
||||
|
||||
// Test setting an application id before a session is opened.
|
||||
const String8 kAppId("com.unittest.mock.app.id");
|
||||
res = plugin.setPropertyString(String8("appId"), kAppId);
|
||||
ASSERT_EQ(OK, res);
|
||||
|
||||
plugin.openSession(sessionId);
|
||||
ASSERT_THAT(propertySet, NotNull());
|
||||
|
||||
// Verify application id is set correctly.
|
||||
EXPECT_STREQ(kAppId, propertySet->app_id().c_str());
|
||||
|
||||
// Test setting application id while session is opened, this should fail.
|
||||
res = plugin.setPropertyString(String8("appId"), kAppId);
|
||||
ASSERT_EQ(kErrorSessionIsOpen, res);
|
||||
}
|
||||
|
||||
TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
|
||||
|
||||
Reference in New Issue
Block a user