From d9b90be205c00633aba02361b86429d3c247d2d6 Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Wed, 25 Jan 2017 18:40:40 -0800 Subject: [PATCH] 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 --- libwvdrmengine/mediadrm/Android.mk | 2 + .../mediadrm/include_hidl/WVDrmPlugin.h | 34 +- .../mediadrm/src_hidl/WVDrmPlugin.cpp | 127 +++++-- .../mediadrm/test/WVDrmPlugin_test.cpp | 344 ++++++++++++------ 4 files changed, 369 insertions(+), 138 deletions(-) diff --git a/libwvdrmengine/mediadrm/Android.mk b/libwvdrmengine/mediadrm/Android.mk index 7f62ba5d..a598a349 100644 --- a/libwvdrmengine/mediadrm/Android.mk +++ b/libwvdrmengine/mediadrm/Android.mk @@ -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 \ diff --git a/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h index 3206a95d..40601cd2 100644 --- a/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h +++ b/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h @@ -309,17 +309,39 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, const std::string mEmptyString; } mPropertySet; - std::string mAppPackageName; + 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 const mCDM; - CdmIdentifier mCdmIdentifier; WVGenericCryptoInterface* mCrypto; map mCryptoSessions; sp mListener; - const std::string& appPackageName() const { - return mAppPackageName; - } - status_t queryProperty(const std::string& property, std::string& stringValue) const; diff --git a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp index bd439c29..616b4188 100644 --- a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp @@ -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& 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::iterator mapIterator; @@ -127,7 +135,8 @@ Return 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 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 WVDrmPlugin::restoreKeys(const hidl_vec& 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 request; if (isCdmResponseTypeSuccess(res)) { @@ -440,21 +447,21 @@ Return 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, - &cdmWrappedKey); + CdmResponseType res = mCDM->HandleProvisioningResponse( + mCdmIdentifierBuilder.get_identifier(), cdmResponse, &cdmCertificate, + &cdmWrappedKey); if (isCdmResponseTypeSuccess(res)) { certificate = StrToVector(cdmCertificate); wrappedKey = StrToVector(cdmWrappedKey); @@ -594,7 +601,7 @@ Return 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 WVDrmPlugin::getPropertyByteArray( Vector 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 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(hash), SHA256_DIGEST_LENGTH); + } +} + } // namespace widevine } // namespace V1_0 } // namespace drm diff --git a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp index 17a12013..d4de9f1c 100644 --- a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp +++ b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp @@ -18,6 +18,7 @@ #include #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("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> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -315,11 +321,14 @@ TEST_F(WVDrmPluginTest, ClosesSessions) { android::sp> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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 hKeySetId) { @@ -575,7 +594,9 @@ TEST_F(WVDrmPluginTest, HandlesPrivacyCertCaseOfAddKey) { android::sp> cdm = new StrictMock(); StrictMock 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 > listener = new StrictMock(); @@ -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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -642,11 +665,14 @@ TEST_F(WVDrmPluginTest, RemovesKeys) { android::sp> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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 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(hLicenseStatus)) { ASSERT_EQ(Status::OK, status); @@ -713,7 +745,9 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) { android::sp> cdm = new StrictMock(); StrictMock 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 hRequest, hidl_string defaultUrl) { @@ -746,7 +781,9 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) { android::sp> cdm = new StrictMock(); StrictMock 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 cert; Vector key; + WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto); plugin.provideProvisionResponse( toHidlVec(response), [&](Status status, hidl_vec /* cert */, @@ -778,13 +816,16 @@ TEST_F(WVDrmPluginTest, UnprovisionsDevice) { android::sp> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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 cert; Vector 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,32 +891,48 @@ TEST_F(WVDrmPluginTest, UnprovisionsOrigin) { } TEST_F(WVDrmPluginTest, WillNotUnprovisionWithoutOrigin) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - std::string appPackageName; - WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto); + // 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); + } - Vector cert; - Vector key; - Vector specialResponse; - specialResponse.appendArray(kUnprovisionResponse, kUnprovisionResponseSize); + // TODO(juce): b/34548395 Make sure this API version is correct. + if (firstApiLevel >= 26) { + android::sp> cdm = new StrictMock(); + StrictMock 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, Unprovision(_, _)) - .Times(0); + Vector cert; + Vector key; + Vector specialResponse; + specialResponse.appendArray(kUnprovisionResponse, kUnprovisionResponseSize); - plugin.provideProvisionResponse( - toHidlVec(specialResponse), - [&](Status status, hidl_vec /* cert */, - hidl_vec /* key */) { - EXPECT_NE(Status::OK, status); - }); + EXPECT_CALL(*cdm, Unprovision(_, _)) + .Times(0); + + WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto); + plugin.provideProvisionResponse( + toHidlVec(specialResponse), + [&](Status status, hidl_vec /* cert */, + hidl_vec /* key */) { + EXPECT_NE(Status::OK, status); + }); + } } TEST_F(WVDrmPluginTest, MuxesOriginUnprovisioningErrors) { android::sp> cdm = new StrictMock(); StrictMock 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 cert; Vector 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> cdm = new StrictMock(); StrictMock 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 > 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 hSecureStops) { ASSERT_EQ(Status::OK, status); @@ -972,15 +1041,19 @@ TEST_F(WVDrmPluginTest, ReleasesAllSecureStops) { android::sp> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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 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 vectorResult) { - ASSERT_EQ(Status::OK, status); - std::vector 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> cdm = new StrictMock(); StrictMock 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 vectorResult; @@ -1172,7 +1241,9 @@ TEST_F(WVDrmPluginTest, DoesNotSetUnknownProperties) { android::sp> cdm = new StrictMock(); StrictMock 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 value; value.appendArray(valueRaw, kValueSize); @@ -1196,7 +1268,9 @@ TEST_F(WVDrmPluginTest, FailsGenericMethodsWithoutAnAlgorithmSet) { android::sp> cdm = new StrictMock(); StrictMock 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 keyId; Vector 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -1262,7 +1338,9 @@ TEST_F(WVDrmPluginTest, CallsGenericEncrypt) { android::sp> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -1329,7 +1409,9 @@ TEST_F(WVDrmPluginTest, CallsGenericDecrypt) { android::sp> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -1396,7 +1480,9 @@ TEST_F(WVDrmPluginTest, CallsGenericSign) { android::sp> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -1458,7 +1546,7 @@ TEST_F(WVDrmPluginTest, CallsGenericSign) { plugin.sign(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message), [&](Status status, hidl_vec signature) { ASSERT_EQ(Status::OK, status); - ASSERT_NE(0u, signature.size()); + ASSERT_NE(0u, signature.size()); }); } @@ -1466,7 +1554,9 @@ TEST_F(WVDrmPluginTest, CallsGenericVerify) { android::sp> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -1552,10 +1644,12 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) { android::sp> cdm = new StrictMock(); StrictMock 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 /* hSessionId */) { ASSERT_EQ(Status::OK, status); }); @@ -1575,36 +1670,39 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) { TEST_F(WVDrmPluginTest, UnregistersForAllEventsOnDestruction) { android::sp> cdm = new StrictMock(); StrictMock crypto; + std::string appPackageName; + 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]; + FILE* fp = fopen("/dev/urandom", "r"); + fread(sessionIdRaw1, sizeof(uint8_t), kSessionIdSize, fp); + fread(sessionIdRaw2, sizeof(uint8_t), kSessionIdSize, fp); + fclose(fp); + + CdmSessionId cdmSessionId1(sessionIdRaw1, sessionIdRaw1 + kSessionIdSize); + CdmSessionId cdmSessionId2(sessionIdRaw2, sessionIdRaw2 + kSessionIdSize); + + EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId1), + testing::Return(wvcdm::NO_ERROR))) + .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId2), + testing::Return(wvcdm::NO_ERROR))); + + EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId1, _)) + .WillOnce(Invoke(setSessionIdOnMap<4>)); + + EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId2, _)) + .WillOnce(Invoke(setSessionIdOnMap<5>)); + + EXPECT_CALL(*cdm, CloseSession(_)) + .Times(AtLeast(0)); { - std::string appPackageName; WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto); - uint8_t sessionIdRaw1[kSessionIdSize]; - uint8_t sessionIdRaw2[kSessionIdSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(sessionIdRaw1, sizeof(uint8_t), kSessionIdSize, fp); - fread(sessionIdRaw2, sizeof(uint8_t), kSessionIdSize, fp); - fclose(fp); - - CdmSessionId cdmSessionId1(sessionIdRaw1, sessionIdRaw1 + kSessionIdSize); - CdmSessionId cdmSessionId2(sessionIdRaw2, sessionIdRaw2 + kSessionIdSize); - - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId1), - testing::Return(wvcdm::NO_ERROR))) - .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId2), - testing::Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId1, _)) - .WillOnce(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId2, _)) - .WillOnce(Invoke(setSessionIdOnMap<5>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - plugin.openSession([&](Status status, hidl_vec /* hSessionId */) { ASSERT_EQ(Status::OK, status); }); @@ -1620,7 +1718,9 @@ TEST_F(WVDrmPluginTest, DISABLED_MarshalsEvents) { android::sp> cdm = new StrictMock(); StrictMock 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 > listener = new StrictMock(); @@ -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> cdm = new StrictMock(); StrictMock 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 > listener = new StrictMock(); @@ -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 /* hSessionId */) { @@ -1736,7 +1840,9 @@ TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) { android::sp> cdm = new StrictMock(); StrictMock 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 /* hSessionId */) { ASSERT_EQ(Status::OK, status); }); @@ -1774,7 +1882,9 @@ TEST_F(WVDrmPluginTest, CanSetAppId) { android::sp> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -2052,7 +2176,9 @@ TEST_F(WVDrmPluginTest, CanSetServiceCertificate) { android::sp> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear(); @@ -2124,7 +2252,9 @@ TEST_F(WVDrmPluginTest, CanSetSessionSharing) { android::sp> cdm = new StrictMock(); StrictMock 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> cdm = new StrictMock(); StrictMock 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 hSessionId) { ASSERT_EQ(Status::OK, status); sessionId.clear();