Enable SPOIDs in Treble Widevine Glue Layer

Adds code to the Widevine Glue Layer that drives the generation and use
of SPOIDs on platforms that support SPOIDs. (All devices whose first
release is Android O or later.) Note that this only applies to the new,
Treble-ized API. If the Widevine DRM Plugin is accessed through the old
API, it will not use SPOIDs. This is by design because the old API does
not provide an application package name, so SPOID generation is no
better than the existing, origin-based solution.

Bug: 27101531
Test: Unit tests
Test: GTS tests
Test: Google Play
Change-Id: I80f79fca84065105e218e9070a1d5299c8e33500
This commit is contained in:
John W. Bruce
2017-01-25 18:40:40 -08:00
parent 2dc53442e7
commit d9b90be205
4 changed files with 369 additions and 138 deletions

View File

@@ -46,6 +46,8 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/mediadrm/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \
LOCAL_STATIC_LIBRARIES := libcrypto_static
LOCAL_SHARED_LIBRARIES := \
android.hardware.drm@1.0 \
android.hidl.memory@1.0 \

View File

@@ -309,17 +309,39 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener,
const std::string mEmptyString;
} mPropertySet;
std::string mAppPackageName;
sp<wvcdm::WvContentDecryptionModule> const mCDM;
class CdmIdentifierBuilder {
public:
CdmIdentifierBuilder();
const CdmIdentifier& get_identifier();
const std::string& get_device_unique_id();
bool set_device_id(const std::string& id);
const std::string& app_package_name() { return mAppPackageName; }
bool set_app_package_name(const std::string& id);
const std::string& origin() const { return mCdmIdentifier.origin; }
bool set_origin(const std::string& id);
private:
WVDRM_DISALLOW_COPY_AND_ASSIGN(CdmIdentifierBuilder);
CdmIdentifier mCdmIdentifier;
bool mIsIdentifierSealed;
bool mUseSpoid;
std::string mDeviceId;
std::string mAppPackageName;
void calculateSpoid();
} mCdmIdentifierBuilder;
sp<wvcdm::WvContentDecryptionModule> const mCDM;
WVGenericCryptoInterface* mCrypto;
map<CdmSessionId, CryptoSession> mCryptoSessions;
sp<IDrmPluginListener> mListener;
const std::string& appPackageName() const {
return mAppPackageName;
}
status_t queryProperty(const std::string& property,
std::string& stringValue) const;

View File

@@ -9,18 +9,22 @@
#include "WVDrmPlugin.h"
#include "TypeConvert.h"
#include "cutils/properties.h"
#include "mapErrors-inl.h"
#include "media/stagefright/MediaErrors.h"
#include "openssl/sha.h"
#include "utils/List.h"
#include "wv_cdm_constants.h"
namespace {
static const char* const kResetSecurityLevel = "";
static const char* const kEnable = "enable";
static const char* const kDisable = "disable";
static const std::string kPsshTag = "pssh";
static const char* const kSpecialUnprovisionResponse = "unprovision";
}
static const char* const kResetSecurityLevel = "";
static const char* const kEnable = "enable";
static const char* const kDisable = "disable";
static const std::string kPsshTag = "pssh";
static const char* const kSpecialUnprovisionResponse = "unprovision";
} // namespace
namespace wvdrm {
namespace hardware {
@@ -102,11 +106,15 @@ KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) {
WVDrmPlugin::WVDrmPlugin(const sp<WvContentDecryptionModule>& cdm,
const std::string& appPackageName,
WVGenericCryptoInterface* crypto)
: mAppPackageName(appPackageName),
mCDM(cdm),
mCdmIdentifier(kDefaultCdmIdentifier),
: mCDM(cdm),
mCrypto(crypto),
mCryptoSessions() {}
mCryptoSessions() {
mCdmIdentifierBuilder.set_app_package_name(appPackageName);
std::string deviceId;
queryProperty(wvcdm::QUERY_KEY_DEVICE_ID, deviceId);
mCdmIdentifierBuilder.set_device_id(deviceId);
}
WVDrmPlugin::~WVDrmPlugin() {
typedef map<CdmSessionId, CryptoSession>::iterator mapIterator;
@@ -127,7 +135,8 @@ Return<void> WVDrmPlugin::openSession(openSession_cb _hidl_cb) {
CdmSessionId cdmSessionId;
CdmResponseType res =
mCDM->OpenSession("com.widevine", &mPropertySet, mCdmIdentifier, this,
mCDM->OpenSession("com.widevine", &mPropertySet,
mCdmIdentifierBuilder.get_identifier(), this,
&cdmSessionId);
if (!isCdmResponseTypeSuccess(res)) {
@@ -269,8 +278,8 @@ Return<void> WVDrmPlugin::getKeyRequest(
CdmKeyRequest keyRequest;
CdmResponseType res = mCDM->GenerateKeyRequest(
cdmSessionId, cdmKeySetId, cdmInitDataType, processedInitData,
cdmLicenseType, cdmParameters, &mPropertySet, mCdmIdentifier,
&keyRequest);
cdmLicenseType, cdmParameters, &mPropertySet,
mCdmIdentifierBuilder.get_identifier(), &keyRequest);
requestType = ConvertFromCdmKeyRequestType(keyRequest.type);
@@ -412,11 +421,9 @@ Return<Status> WVDrmPlugin::restoreKeys(const hidl_vec<uint8_t>& sessionId,
std::string cdmCertAuthority = certificateAuthority;
CdmResponseType res = mCDM->GetProvisioningRequest(cdmCertType,
cdmCertAuthority,
mCdmIdentifier,
&cdmProvisionRequest,
&cdmDefaultUrl);
CdmResponseType res = mCDM->GetProvisioningRequest(
cdmCertType, cdmCertAuthority, mCdmIdentifierBuilder.get_identifier(),
&cdmProvisionRequest, &cdmDefaultUrl);
String8 defaultUrl;
Vector<uint8_t> request;
if (isCdmResponseTypeSuccess(res)) {
@@ -440,20 +447,20 @@ Return<void> WVDrmPlugin::provideProvisionResponse(
CdmProvisioningResponse cdmResponse(resp.begin(), resp.end());
if (cdmResponse == kSpecialUnprovisionResponse) {
if (mCdmIdentifier == kDefaultCdmIdentifier) {
if (mCdmIdentifierBuilder.get_identifier() == kDefaultCdmIdentifier) {
_hidl_cb(toStatus(kErrorNoOriginSpecified), toHidlVec(certificate),
toHidlVec(wrappedKey));
return Void();
}
_hidl_cb(toStatus(unprovision(mCdmIdentifier)), toHidlVec(certificate),
_hidl_cb(toStatus(unprovision(mCdmIdentifierBuilder.get_identifier())),
toHidlVec(certificate),
toHidlVec(wrappedKey));
return Void();
} else {
std::string cdmCertificate;
std::string cdmWrappedKey;
CdmResponseType res = mCDM->HandleProvisioningResponse(mCdmIdentifier,
cdmResponse,
&cdmCertificate,
CdmResponseType res = mCDM->HandleProvisioningResponse(
mCdmIdentifierBuilder.get_identifier(), cdmResponse, &cdmCertificate,
&cdmWrappedKey);
if (isCdmResponseTypeSuccess(res)) {
certificate = StrToVector(cdmCertificate);
@@ -594,7 +601,7 @@ Return<void> WVDrmPlugin::getPropertyString(const hidl_string& propertyName,
} else if (name == "appId") {
value = mPropertySet.app_id().c_str();
} else if (name == "origin") {
value = mCdmIdentifier.origin.c_str();
value = mCdmIdentifierBuilder.origin().c_str();
} else {
ALOGE("App requested unknown string property %s", name.string());
status = android::ERROR_DRM_CANNOT_HANDLE;
@@ -613,7 +620,7 @@ Return<void> WVDrmPlugin::getPropertyByteArray(
Vector<uint8_t> value;
if (name == "deviceUniqueId") {
status = queryProperty(wvcdm::QUERY_KEY_DEVICE_ID, value);
value = StrToVector(mCdmIdentifierBuilder.get_device_unique_id());
} else if (name == "provisioningUniqueId") {
status = queryProperty(wvcdm::QUERY_KEY_PROVISIONING_ID, value);
} else if (name == "serviceCertificate") {
@@ -696,7 +703,9 @@ Return<Status> WVDrmPlugin::setPropertyString(const hidl_string& propertyName,
ALOGE("App tried to set the origin while sessions are opened.");
return toStatus(kErrorSessionIsOpen);
} else {
mCdmIdentifier.origin = _value.string();
if (!mCdmIdentifierBuilder.set_origin(_value.string())) {
return Status::BAD_VALUE;
}
}
} else {
ALOGE("App set unknown string property %s", name.string());
@@ -1242,6 +1251,70 @@ status_t WVDrmPlugin::unprovision(const CdmIdentifier& identifier) {
}
}
// Implementation for the CdmIdentifierBuilder inner class
WVDrmPlugin::CdmIdentifierBuilder::CdmIdentifierBuilder()
: mCdmIdentifier(),
mIsIdentifierSealed(false),
mDeviceId(),
mAppPackageName() {
// Determine if this device supports SPOIDs.
int32_t firstApiLevel = property_get_int32("ro.product.first_api_level", 0);
if (firstApiLevel == 0) {
// First API Level is 0 on factory ROMs, but we can assume the current SDK
// version is the first if it's a factory ROM.
firstApiLevel = property_get_int32("ro.build.version.sdk", 0);
}
// TODO(juce): b/34548395 Make sure this API version is correct.
mUseSpoid = firstApiLevel >= 26; // Android O
}
const CdmIdentifier& WVDrmPlugin::CdmIdentifierBuilder::get_identifier() {
if (!mIsIdentifierSealed) calculateSpoid();
mIsIdentifierSealed = true;
return mCdmIdentifier;
}
const std::string& WVDrmPlugin::CdmIdentifierBuilder::get_device_unique_id() {
if (mUseSpoid) {
return get_identifier().spoid;
} else {
return mDeviceId;
}
}
bool WVDrmPlugin::CdmIdentifierBuilder::set_device_id(const std::string& id) {
if (mIsIdentifierSealed) return false;
mDeviceId = id;
return true;
}
bool WVDrmPlugin::CdmIdentifierBuilder::set_app_package_name(const std::string& id) {
if (mIsIdentifierSealed) return false;
mAppPackageName = id;
return true;
}
bool WVDrmPlugin::CdmIdentifierBuilder::set_origin(const std::string& id) {
if (mIsIdentifierSealed) return false;
mCdmIdentifier.origin = id;
return true;
}
void WVDrmPlugin::CdmIdentifierBuilder::calculateSpoid() {
if (mUseSpoid) {
uint8_t hash[SHA256_DIGEST_LENGTH];
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, mDeviceId.data(), mDeviceId.length());
SHA256_Update(&ctx, mAppPackageName.data(), mAppPackageName.length());
SHA256_Update(&ctx, origin().data(), origin().length());
SHA256_Final(hash, &ctx);
mCdmIdentifier.spoid =
std::string(reinterpret_cast<char*>(hash), SHA256_DIGEST_LENGTH);
}
}
} // namespace widevine
} // namespace V1_0
} // namespace drm

View File

@@ -18,6 +18,7 @@
#include <string>
#include "cdm_client_property_set.h"
#include "cutils/properties.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "media/stagefright/foundation/ABase.h"
@@ -121,6 +122,7 @@ const String8 kAppId("com.unittest.mock.app.id");
const uint8_t* const kUnprovisionResponse =
reinterpret_cast<const uint8_t*>("unprovision");
const size_t kUnprovisionResponseSize = 11;
const std::string kDeviceId = "0123456789ABCDEF";
}
class MockCDM : public WvContentDecryptionModule {
@@ -287,7 +289,9 @@ TEST_F(WVDrmPluginTest, OpensSessions) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm,
OpenSession(StrEq("com.widevine"), _, HasOrigin(EMPTY_ORIGIN), _, _))
@@ -302,6 +306,8 @@ TEST_F(WVDrmPluginTest, OpensSessions) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -315,11 +321,14 @@ TEST_F(WVDrmPluginTest, ClosesSessions) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, CloseSession(cdmSessionId))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.closeSession(toHidlVec(sessionId));
ASSERT_EQ(Status::OK, status);
}
@@ -328,11 +337,14 @@ TEST_F(WVDrmPluginTest, ClosesSessionWithoutReturningError) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, CloseSession(cdmSessionId))
.WillOnce(testing::Return(wvcdm::SESSION_NOT_FOUND_1));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.closeSession(toHidlVec(sessionId));
ASSERT_EQ(Status::OK, status);
}
@@ -342,7 +354,9 @@ TEST_F(WVDrmPluginTest, DISABLED_GeneratesKeyRequests) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const size_t kInitDataSize = 128;
uint8_t initDataRaw[kInitDataSize];
@@ -473,6 +487,7 @@ TEST_F(WVDrmPluginTest, DISABLED_GeneratesKeyRequests) {
}
// Performs the actual tests
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
for (size_t i = 0; i < testSetCount; ++i)
{
const String8 mimeType(testSets[i].mimeType);
@@ -523,7 +538,9 @@ TEST_F(WVDrmPluginTest, AddsKeys) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const uint32_t kResponseSize = 256;
uint8_t responseRaw[kResponseSize];
@@ -552,6 +569,8 @@ TEST_F(WVDrmPluginTest, AddsKeys) {
Pointee(cdmKeySetId)))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.provideKeyResponse(
toHidlVec(sessionId), toHidlVec(response),
[&](Status status, hidl_vec<uint8_t> hKeySetId) {
@@ -575,7 +594,9 @@ TEST_F(WVDrmPluginTest, HandlesPrivacyCertCaseOfAddKey) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
sp<StrictMock<MockDrmPluginListener> > listener =
new StrictMock<MockDrmPluginListener>();
@@ -613,6 +634,8 @@ TEST_F(WVDrmPluginTest, HandlesPrivacyCertCaseOfAddKey) {
EXPECT_CALL(*cdm, AddKey(_, _, _))
.WillRepeatedly(testing::Return(wvcdm::NEED_KEY));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -642,11 +665,14 @@ TEST_F(WVDrmPluginTest, RemovesKeys) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, RemoveKeys(cdmSessionId))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.removeKeys(toHidlVec(sessionId));
ASSERT_EQ(Status::OK, status);
}
@@ -655,7 +681,9 @@ TEST_F(WVDrmPluginTest, RestoresKeys) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const size_t kKeySetIdSize = 32;
uint8_t keySetIdRaw[kKeySetIdSize];
@@ -670,6 +698,7 @@ TEST_F(WVDrmPluginTest, RestoresKeys) {
ElementsAreArray(keySetIdRaw, kKeySetIdSize)))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.restoreKeys(toHidlVec(sessionId), toHidlVec(keySetId));
ASSERT_EQ(Status::OK, status);
}
@@ -678,7 +707,9 @@ TEST_F(WVDrmPluginTest, QueriesKeyStatus) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
KeyedVector<String8, String8> expectedLicenseStatus;
CdmQueryMap cdmLicenseStatus;
@@ -694,6 +725,7 @@ TEST_F(WVDrmPluginTest, QueriesKeyStatus) {
.WillOnce(DoAll(SetArgPointee<1>(cdmLicenseStatus),
testing::Return(wvcdm::NO_ERROR)));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.queryKeyStatus(toHidlVec(sessionId),
[&](Status status, hidl_vec<KeyValue>(hLicenseStatus)) {
ASSERT_EQ(Status::OK, status);
@@ -713,7 +745,9 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const uint32_t kRequestSize = 256;
uint8_t requestRaw[kRequestSize];
@@ -731,6 +765,7 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
SetArgPointee<4>(kDefaultUrl),
testing::Return(wvcdm::NO_ERROR)));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.getProvisionRequest(
hidl_string(""), hidl_string(""),
[&](Status status, hidl_vec<uint8_t> hRequest, hidl_string defaultUrl) {
@@ -746,7 +781,9 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const uint32_t kResponseSize = 512;
uint8_t responseRaw[kResponseSize];
@@ -766,6 +803,7 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
Vector<uint8_t> cert;
Vector<uint8_t> key;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.provideProvisionResponse(
toHidlVec(response),
[&](Status status, hidl_vec<uint8_t> /* cert */,
@@ -778,13 +816,16 @@ TEST_F(WVDrmPluginTest, UnprovisionsDevice) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL1, HasOrigin(EMPTY_ORIGIN)))
.Times(1);
EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL3, HasOrigin(EMPTY_ORIGIN)))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
status_t res = plugin.unprovisionDevice();
ASSERT_EQ(android::OK, res);
}
@@ -793,7 +834,9 @@ TEST_F(WVDrmPluginTest, MuxesUnprovisioningErrors) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
// Tests that both Unprovisions are called even if one fails. Also tests that
// no matter which fails, the function always propagates the error.
@@ -806,6 +849,7 @@ TEST_F(WVDrmPluginTest, MuxesUnprovisioningErrors) {
.WillOnce(testing::Return(wvcdm::UNKNOWN_ERROR))
.WillOnce(testing::Return(wvcdm::UNKNOWN_ERROR));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
status_t res = plugin.unprovisionDevice();
ASSERT_NE(android::OK, res);
res = plugin.unprovisionDevice();
@@ -818,7 +862,9 @@ TEST_F(WVDrmPluginTest, UnprovisionsOrigin) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
Vector<uint8_t> cert;
Vector<uint8_t> key;
@@ -830,6 +876,8 @@ TEST_F(WVDrmPluginTest, UnprovisionsOrigin) {
EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL3, HasOrigin(kOrigin.string())))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.setPropertyString(hidl_string("origin"),
hidl_string(kOrigin));
ASSERT_EQ(Status::OK, status);
@@ -843,10 +891,22 @@ TEST_F(WVDrmPluginTest, UnprovisionsOrigin) {
}
TEST_F(WVDrmPluginTest, WillNotUnprovisionWithoutOrigin) {
// This test is only valid on SPOID-free devices. SPOID devices can
// unprovision without an origin because the empty-origin provisioning is
// not global.
int32_t firstApiLevel = property_get_int32("ro.product.first_api_level", 0);
if (firstApiLevel == 0) {
firstApiLevel = property_get_int32("ro.build.version.sdk", 0);
}
// TODO(juce): b/34548395 Make sure this API version is correct.
if (firstApiLevel >= 26) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
Vector<uint8_t> cert;
Vector<uint8_t> key;
@@ -856,19 +916,23 @@ TEST_F(WVDrmPluginTest, WillNotUnprovisionWithoutOrigin) {
EXPECT_CALL(*cdm, Unprovision(_, _))
.Times(0);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.provideProvisionResponse(
toHidlVec(specialResponse),
[&](Status status, hidl_vec<uint8_t> /* cert */,
hidl_vec<uint8_t> /* key */) {
EXPECT_NE(Status::OK, status);
});
}
}
TEST_F(WVDrmPluginTest, MuxesOriginUnprovisioningErrors) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
Vector<uint8_t> cert;
Vector<uint8_t> key;
@@ -886,6 +950,8 @@ TEST_F(WVDrmPluginTest, MuxesOriginUnprovisioningErrors) {
.WillOnce(testing::Return(wvcdm::UNKNOWN_ERROR))
.WillOnce(testing::Return(wvcdm::UNKNOWN_ERROR));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.setPropertyString(hidl_string("origin"),
hidl_string(kOrigin));
ASSERT_EQ(Status::OK, status);
@@ -916,12 +982,9 @@ TEST_F(WVDrmPluginTest, GetsSecureStops) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
const char* app_id = "my_app_id";
Status status = plugin.setPropertyString(hidl_string("appId"),
hidl_string(app_id));
ASSERT_EQ(Status::OK, status);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const uint32_t kStopSize = 53;
static const uint32_t kStopCount = 7;
@@ -937,12 +1000,18 @@ TEST_F(WVDrmPluginTest, GetsSecureStops) {
cdmStops.push_back(std::string(stopsRaw[i], stopsRaw[i] + kStopSize));
}
const char* app_id = "my_app_id";
EXPECT_CALL(*cdm, GetUsageInfo(StrEq(app_id), _))
.WillOnce(DoAll(SetArgPointee<1>(cdmStops),
testing::Return(wvcdm::NO_ERROR)));
List<std::vector<uint8_t> > stops;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.setPropertyString(hidl_string("appId"),
hidl_string(app_id));
ASSERT_EQ(Status::OK, status);
plugin.getSecureStops([&](Status status, hidl_vec<SecureStop> hSecureStops) {
ASSERT_EQ(Status::OK, status);
@@ -972,15 +1041,19 @@ TEST_F(WVDrmPluginTest, ReleasesAllSecureStops) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, ReleaseAllUsageInfo(StrEq("")))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.setPropertyString(hidl_string("appId"),
hidl_string(""));
ASSERT_EQ(Status::OK, status);
EXPECT_CALL(*cdm, ReleaseAllUsageInfo(StrEq("")))
.Times(1);
status = plugin.releaseAllSecureStops();
ASSERT_EQ(Status::OK, status);
}
@@ -989,7 +1062,9 @@ TEST_F(WVDrmPluginTest, ReleasesSecureStop) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const uint32_t kMessageSize = 128;
uint8_t messageRaw[kMessageSize];
@@ -1004,6 +1079,7 @@ TEST_F(WVDrmPluginTest, ReleasesSecureStop) {
kMessageSize)))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Status status = plugin.releaseSecureStop(toHidlVec(message));
ASSERT_EQ(Status::OK, status);
}
@@ -1012,7 +1088,9 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
CdmQueryMap l1Map;
l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
@@ -1020,12 +1098,11 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
CdmQueryMap l3Map;
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
static const std::string uniqueId = "The Universe";
static const std::string systemId = "42";
static const std::string systemId = "The Universe";
static const std::string provisioningId("Life\0&Everything", 16);
static const std::string openSessions = "15";
static const std::string maxSessions = "18";
static const std::string oemCryptoApiVersion = "10";
static const std::string openSessions = "42";
static const std::string maxSessions = "54";
static const std::string oemCryptoApiVersion = "13";
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
@@ -1033,10 +1110,6 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L3),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(uniqueId),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SYSTEM_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(systemId),
testing::Return(wvcdm::NO_ERROR)));
@@ -1057,6 +1130,7 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
.WillOnce(DoAll(SetArgPointee<2>(oemCryptoApiVersion),
testing::Return(wvcdm::NO_ERROR)));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
String8 stringResult;
Vector<uint8_t> vectorResult;
@@ -1098,14 +1172,6 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
EXPECT_STREQ(QUERY_VALUE_SECURITY_LEVEL_L3.c_str(), stringResult.c_str());
});
plugin.getPropertyByteArray(
hidl_string("deviceUniqueId"),
[&](Status status, hidl_vec<uint8_t> vectorResult) {
ASSERT_EQ(Status::OK, status);
std::vector<uint8_t> id(vectorResult);
EXPECT_THAT(id, ElementsAreArray(uniqueId.data(), uniqueId.size()));
});
plugin.getPropertyString(
hidl_string("systemId"),
[&](Status status, hidl_string stringResult) {
@@ -1148,8 +1214,11 @@ TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
String8 stringResult;
Vector<uint8_t> vectorResult;
@@ -1172,7 +1241,9 @@ TEST_F(WVDrmPluginTest, DoesNotSetUnknownProperties) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const uint32_t kValueSize = 32;
uint8_t valueRaw[kValueSize];
@@ -1180,6 +1251,7 @@ TEST_F(WVDrmPluginTest, DoesNotSetUnknownProperties) {
fread(valueRaw, sizeof(uint8_t), kValueSize, fp);
fclose(fp);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
Vector<uint8_t> value;
value.appendArray(valueRaw, kValueSize);
@@ -1196,7 +1268,9 @@ TEST_F(WVDrmPluginTest, FailsGenericMethodsWithoutAnAlgorithmSet) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
Vector<uint8_t> keyId;
Vector<uint8_t> input;
@@ -1217,6 +1291,8 @@ TEST_F(WVDrmPluginTest, FailsGenericMethodsWithoutAnAlgorithmSet) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -1262,7 +1338,9 @@ TEST_F(WVDrmPluginTest, CallsGenericEncrypt) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const size_t kDataSize = 256;
uint8_t keyIdRaw[KEY_ID_SIZE];
@@ -1309,6 +1387,8 @@ TEST_F(WVDrmPluginTest, CallsGenericEncrypt) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -1329,7 +1409,9 @@ TEST_F(WVDrmPluginTest, CallsGenericDecrypt) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const size_t kDataSize = 256;
uint8_t keyIdRaw[KEY_ID_SIZE];
@@ -1376,6 +1458,8 @@ TEST_F(WVDrmPluginTest, CallsGenericDecrypt) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -1396,7 +1480,9 @@ TEST_F(WVDrmPluginTest, CallsGenericSign) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const size_t kDataSize = 256;
uint8_t keyIdRaw[KEY_ID_SIZE];
@@ -1445,6 +1531,8 @@ TEST_F(WVDrmPluginTest, CallsGenericSign) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -1466,7 +1554,9 @@ TEST_F(WVDrmPluginTest, CallsGenericVerify) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
static const size_t kDataSize = 256;
static const size_t kSignatureSize = 16;
@@ -1525,6 +1615,8 @@ TEST_F(WVDrmPluginTest, CallsGenericVerify) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -1552,10 +1644,12 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
// Provide expected behavior to support session creation
EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, &plugin, _))
EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
testing::Return(wvcdm::NO_ERROR)));
@@ -1567,6 +1661,7 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> /* hSessionId */) {
ASSERT_EQ(Status::OK, status);
});
@@ -1575,10 +1670,10 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) {
TEST_F(WVDrmPluginTest, UnregistersForAllEventsOnDestruction) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
{
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
uint8_t sessionIdRaw1[kSessionIdSize];
uint8_t sessionIdRaw2[kSessionIdSize];
@@ -1605,6 +1700,9 @@ TEST_F(WVDrmPluginTest, UnregistersForAllEventsOnDestruction) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
{
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> /* hSessionId */) {
ASSERT_EQ(Status::OK, status);
});
@@ -1620,7 +1718,9 @@ TEST_F(WVDrmPluginTest, DISABLED_MarshalsEvents) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
sp<StrictMock<MockDrmPluginListener> > listener =
new StrictMock<MockDrmPluginListener>();
@@ -1682,6 +1782,7 @@ TEST_F(WVDrmPluginTest, DISABLED_MarshalsEvents) {
EXPECT_CALL(*listener, sendKeysChange(hSessionId, hKeyStatusList2, false));
}
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.setListener(listener);
CdmKeyStatusMap cdmKeysStatus;
@@ -1704,7 +1805,9 @@ TEST_F(WVDrmPluginTest, DISABLED_GeneratesProvisioningNeededEvent) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
sp<StrictMock<MockDrmPluginListener> > listener =
new StrictMock<MockDrmPluginListener>();
@@ -1725,6 +1828,7 @@ TEST_F(WVDrmPluginTest, DISABLED_GeneratesProvisioningNeededEvent) {
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.setListener(listener);
plugin.openSession([&](Status status, hidl_vec<uint8_t> /* hSessionId */) {
@@ -1736,7 +1840,9 @@ TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
const CdmClientPropertySet* propertySet = NULL;
@@ -1757,6 +1863,8 @@ TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) {
.Times(AtLeast(0));
}
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> /* hSessionId */) {
ASSERT_EQ(Status::OK, status);
});
@@ -1774,7 +1882,9 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
const CdmClientPropertySet* propertySet = NULL;
@@ -1800,6 +1910,8 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
.Times(AtLeast(0));
}
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
// Test setting an empty string
Status status = plugin.setPropertyString(hidl_string("appId"),
hidl_string(""));
@@ -1828,7 +1940,9 @@ TEST_P(WVDrmPluginOriginTest, CanSetOrigin) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
OriginTestVariant params = GetParam();
@@ -1849,6 +1963,8 @@ TEST_P(WVDrmPluginOriginTest, CanSetOrigin) {
testing::Return(wvcdm::NO_ERROR)));
// Set the properties & run the test
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
if (!params.origin.isEmpty()) {
ASSERT_EQ(Status::OK,
plugin.setPropertyString(hidl_string("origin"),
@@ -1873,7 +1989,9 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
const CdmClientPropertySet* propertySet = NULL;
@@ -1900,6 +2018,8 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
.Times(AtLeast(0));
}
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
// Test forcing L3
Status status = plugin.setPropertyString(hidl_string("securityLevel"),
hidl_string("L3"));
@@ -2002,7 +2122,9 @@ TEST_F(WVDrmPluginTest, CanSetPrivacyMode) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
const CdmClientPropertySet* propertySet = NULL;
@@ -2023,6 +2145,8 @@ TEST_F(WVDrmPluginTest, CanSetPrivacyMode) {
.Times(AtLeast(0));
}
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -2052,7 +2176,9 @@ TEST_F(WVDrmPluginTest, CanSetServiceCertificate) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
const CdmClientPropertySet* propertySet = NULL;
@@ -2093,6 +2219,8 @@ TEST_F(WVDrmPluginTest, CanSetServiceCertificate) {
.WillOnce(testing::Return(true))
.WillOnce(testing::Return(false));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
@@ -2124,7 +2252,9 @@ TEST_F(WVDrmPluginTest, CanSetSessionSharing) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
const CdmClientPropertySet* propertySet = NULL;
@@ -2145,6 +2275,7 @@ TEST_F(WVDrmPluginTest, CanSetSessionSharing) {
.Times(AtLeast(0));
}
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
status_t res;
// Test turning on session sharing
@@ -2200,7 +2331,9 @@ TEST_F(WVDrmPluginTest, AllowsStoringOfSessionSharingId) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _))
.WillOnce(DoAll(SetArgPointee<2>(kDeviceId),
testing::Return(wvcdm::NO_ERROR)));
CdmClientPropertySet* propertySet = NULL;
@@ -2226,6 +2359,7 @@ TEST_F(WVDrmPluginTest, AllowsStoringOfSessionSharingId) {
.Times(AtLeast(0));
}
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto);
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();