diff --git a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp index 4dd98ceaed..71b893a813 100644 --- a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp +++ b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp @@ -245,6 +245,7 @@ class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest { SessionId openSession(); void closeSession(const SessionId& sessionId); + hidl_vec loadKeys(const SessionId& sessionId, const KeyType& type); sp getDecryptMemory(size_t size, size_t index); protected: @@ -312,6 +313,70 @@ void DrmHalClearkeyPluginTest::closeSession(const SessionId& sessionId) { EXPECT_EQ(Status::OK, result); } +/** + * Helper method to load keys for subsequent decrypt tests. + * These tests use predetermined key request/response to + * avoid requiring a round trip to a license server. + */ +hidl_vec DrmHalClearkeyPluginTest::loadKeys( + const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) { + hidl_vec initData = { + // BMFF box header (4 bytes size + 'pssh') + 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68, + // full box header (version = 1 flags = 0) + 0x01, 0x00, 0x00, 0x00, + // system id + 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, + 0x52, 0xe2, 0xfb, 0x4b, + // number of key ids + 0x00, 0x00, 0x00, 0x01, + // key id + 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d, + 0x1e, 0xd0, 0x0d, 0x1e, + // size of data, must be zero + 0x00, 0x00, 0x00, 0x00}; + + hidl_vec expectedKeyRequest = { + 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, + 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b, + 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, + 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x74, + 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d}; + + hidl_vec knownKeyResponse = { + 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, + 0x6b, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, + 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 0x41, 0x59, 0x65, + 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b, 0x56, 0x39, 0x41, + 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, + 0x22, 0x3a, 0x22, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, + 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34, + 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a}; + + hidl_string mimeType = "video/mp4"; + KeyedVector optionalParameters; + auto res = drmPlugin->getKeyRequest( + sessionId, initData, mimeType, type, optionalParameters, + [&](Status status, const hidl_vec& request, + KeyRequestType requestType, const hidl_string&) { + EXPECT_EQ(Status::OK, status); + EXPECT_EQ(KeyRequestType::INITIAL, requestType); + EXPECT_EQ(request, expectedKeyRequest); + }); + EXPECT_OK(res); + + hidl_vec keySetId; + res = drmPlugin->provideKeyResponse( + sessionId, knownKeyResponse, + [&](Status status, const hidl_vec& myKeySetId) { + EXPECT_EQ(Status::OK, status); + EXPECT_EQ(0u, myKeySetId.size()); + keySetId = myKeySetId; + }); + EXPECT_OK(res); + return keySetId; +} + /** * Test that a session can be opened and closed */ @@ -470,6 +535,30 @@ TEST_F(DrmHalClearkeyPluginTest, RemoveKeysNewSession) { closeSession(sessionId); } +/** + * Test that ClearKey cannot handle key restoring. + * Expected message is Status::ERROR_DRM_CANNOT_HANDLE. + */ +TEST_F(DrmHalClearkeyPluginTest, RestoreKeysCannotHandle) { + hidl_vec keySetId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + SessionId sessionId = openSession(); + Status status = drmPlugin->restoreKeys(sessionId, keySetId); + EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); + closeSession(sessionId); +} + +/** + * Test that restoreKeys fails with a null key set ID. + * Error message is expected to be Status::BAD_VALUE. + */ +TEST_F(DrmHalClearkeyPluginTest, RestoreKeysNull) { + SessionId sessionId = openSession(); + hidl_vec nullKeySetId; + Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId); + EXPECT_EQ(Status::BAD_VALUE, status); + closeSession(sessionId); +} + /** * Test that the clearkey plugin doesn't support getting * secure stops. @@ -831,7 +920,6 @@ TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) { class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest { public: - void loadKeys(const SessionId& sessionId); void fillRandom(const sp& memory); hidl_array toHidlArray(const vector& vec) { EXPECT_EQ(16u, vec.size()); @@ -845,67 +933,6 @@ class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest { const hidl_vec& subSamples, const vector& key); }; -/** - * Helper method to load keys for subsequent decrypt tests. - * These tests use predetermined key request/response to - * avoid requiring a round trip to a license server. - */ -void DrmHalClearkeyDecryptTest::loadKeys(const SessionId& sessionId) { - hidl_vec initData = { - // BMFF box header (4 bytes size + 'pssh') - 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68, - // full box header (version = 1 flags = 0) - 0x01, 0x00, 0x00, 0x00, - // system id - 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, - 0x1e, 0x52, 0xe2, 0xfb, 0x4b, - // number of key ids - 0x00, 0x00, 0x00, 0x01, - // key id - 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, - 0x0d, 0x1e, 0xd0, 0x0d, 0x1e, - // size of data, must be zero - 0x00, 0x00, 0x00, 0x00}; - - hidl_vec expectedKeyRequest = { - 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, - 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b, - 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, - 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x74, - 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d}; - - hidl_vec knownKeyResponse = { - 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, - 0x6b, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, - 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 0x41, 0x59, 0x65, - 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b, 0x56, 0x39, 0x41, - 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, - 0x22, 0x3a, 0x22, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, - 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34, - 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a}; - - hidl_string mimeType = "video/mp4"; - KeyedVector optionalParameters; - auto res = drmPlugin->getKeyRequest( - sessionId, initData, mimeType, KeyType::STREAMING, - optionalParameters, - [&](Status status, const hidl_vec& request, - KeyRequestType requestType, const hidl_string&) { - EXPECT_EQ(Status::OK, status); - EXPECT_EQ(KeyRequestType::INITIAL, requestType); - EXPECT_EQ(request, expectedKeyRequest); - }); - EXPECT_OK(res); - - res = drmPlugin->provideKeyResponse( - sessionId, knownKeyResponse, - [&](Status status, const hidl_vec& keySetId) { - EXPECT_EQ(Status::OK, status); - EXPECT_EQ(0u, keySetId.size()); - }); - EXPECT_OK(res); -} - void DrmHalClearkeyDecryptTest::fillRandom(const sp& memory) { random_device rd; mt19937 rand(rd()); diff --git a/drm/1.0/vts/functional/drm_hal_vendor_module_api.h b/drm/1.0/vts/functional/drm_hal_vendor_module_api.h index 73e0cfe933..2c49ab606b 100644 --- a/drm/1.0/vts/functional/drm_hal_vendor_module_api.h +++ b/drm/1.0/vts/functional/drm_hal_vendor_module_api.h @@ -157,18 +157,31 @@ class DrmHalVTSVendorModule_V1 : public DrmHalVTSVendorModule { */ const std::map optionalParameters; + /** + * Define license policy attributes for the content configuration. + * These attributes can affect which tests are able to be applied. + */ + struct Policy { + /** + * Indicate if the license policy allows offline playback. + * Content configurated with this policy supports KeyType::OFFLINE + * key requests/responses. A vendor module should provide at least + * one content configuration where allowOffline is true if the drm + * scheme supports offline content. + */ + bool allowOffline; + } policy; + /** * The keys that will be available once the keys are loaded */ struct Key { /** * Indicate if the key content is configured to require secure - * buffers, - * where the output buffers are protected and cannot be accessed. - * A vendor module should provide some content configurations where - * isSecure is false, to allow decrypt result verification tests to - * be - * run. + * buffers, where the output buffers are protected and cannot be + * accessed by the non-secure cpu. A vendor module should provide + * at least one content configurations where isSecure is false, to + * allow decrypt result verification tests to be run. */ bool isSecure; diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp index fec43cffde..90608b921c 100644 --- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp +++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp @@ -142,6 +142,7 @@ class DrmHalVendorFactoryTest : public testing::TestWithParam { TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) { const char* kVendorStr = "Vendor module "; + size_t count = 0; for (auto config : contentConfigurations) { ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name"; ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr @@ -157,7 +158,9 @@ TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) { ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr << " has zero length key value"; } + count++; } + EXPECT_NE(0u, count); } /** @@ -299,6 +302,10 @@ class DrmHalVendorPluginTest : public DrmHalVendorFactoryTest { SessionId openSession(); void closeSession(const SessionId& sessionId); sp getDecryptMemory(size_t size, size_t index); + KeyedVector toHidlKeyedVector(const map& params); + hidl_vec loadKeys(const SessionId& sessionId, + const ContentConfiguration& configuration, + const KeyType& type); protected: sp drmPlugin; @@ -389,6 +396,64 @@ void DrmHalVendorPluginTest::closeSession(const SessionId& sessionId) { EXPECT_EQ(Status::OK, status); } +KeyedVector DrmHalVendorPluginTest::toHidlKeyedVector( + const map& params) { + std::vector stdKeyedVector; + for (auto it = params.begin(); it != params.end(); ++it) { + KeyValue keyValue; + keyValue.key = it->first; + keyValue.value = it->second; + stdKeyedVector.push_back(keyValue); + } + return KeyedVector(stdKeyedVector); +} + +/** + * Helper method to load keys for subsequent decrypt tests. + * These tests use predetermined key request/response to + * avoid requiring a round trip to a license server. + */ +hidl_vec DrmHalVendorPluginTest::loadKeys( + const SessionId& sessionId, const ContentConfiguration& configuration, + const KeyType& type = KeyType::STREAMING) { + hidl_vec keyRequest; + auto res = drmPlugin->getKeyRequest( + sessionId, configuration.initData, configuration.mimeType, type, + toHidlKeyedVector(configuration.optionalParameters), + [&](Status status, const hidl_vec& request, + KeyRequestType type, const hidl_string&) { + EXPECT_EQ(Status::OK, status) << "Failed to get " + "key request for configuration " + << configuration.name; + EXPECT_EQ(type, KeyRequestType::INITIAL); + EXPECT_NE(request.size(), 0u) << "Expected key request size" + " to have length > 0 bytes"; + keyRequest = request; + }); + EXPECT_OK(res); + + /** + * Get key response from vendor module + */ + hidl_vec keyResponse = + vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl); + + EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size " + "to have length > 0 bytes"; + + hidl_vec keySetId; + res = drmPlugin->provideKeyResponse( + sessionId, keyResponse, + [&](Status status, const hidl_vec& myKeySetId) { + EXPECT_EQ(Status::OK, status) << "Failure providing " + "key response for configuration " + << configuration.name; + keySetId = myKeySetId; + }); + EXPECT_OK(res); + return keySetId; +} + /** * Test that a session can be opened and closed */ @@ -487,6 +552,56 @@ TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) { closeSession(sessionId); } +/** + * Test that keys are successfully restored to a new session + * for all content having a policy that allows offline use. + */ +TEST_P(DrmHalVendorPluginTest, RestoreKeys) { + for (auto config : contentConfigurations) { + if (config.policy.allowOffline) { + auto sessionId = openSession(); + hidl_vec keySetId = + loadKeys(sessionId, config, KeyType::OFFLINE); + closeSession(sessionId); + sessionId = openSession(); + EXPECT_NE(0u, keySetId.size()); + Status status = drmPlugin->restoreKeys(sessionId, keySetId); + EXPECT_EQ(Status::OK, status); + closeSession(sessionId); + } + } +} + +/** + * Test that restoreKeys fails with a null key set ID. + * Error message is expected to be Status::BAD_VALUE. + */ +TEST_P(DrmHalVendorPluginTest, RestoreKeysNull) { + SessionId sessionId = openSession(); + hidl_vec nullKeySetId; + Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId); + EXPECT_EQ(Status::BAD_VALUE, status); + closeSession(sessionId); +} + +/** + * Test that restoreKeys fails to restore keys to a closed + * session. Error message is expected to be + * Status::ERROR_DRM_SESSION_NOT_OPENED. + */ +TEST_P(DrmHalVendorPluginTest, RestoreKeysClosedSession) { + for (auto config : contentConfigurations) { + auto sessionId = openSession(); + hidl_vec keySetId = loadKeys(sessionId, config); + EXPECT_NE(0u, keySetId.size()); + closeSession(sessionId); + sessionId = openSession(); + closeSession(sessionId); + Status status = drmPlugin->restoreKeys(sessionId, keySetId); + EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); + } +} + /** * Test that the plugin either doesn't support getting * secure stops, or has no secure stops available after @@ -821,7 +936,6 @@ TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderInvalidMimeType) { * configurations */ TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) { - const char* kVendorStr = "Vendor module "; for (auto config : contentConfigurations) { for (auto key : config.keys) { if (key.isSecure) { @@ -1060,10 +1174,7 @@ class DrmHalVendorDecryptTest : public DrmHalVendorPluginTest { virtual ~DrmHalVendorDecryptTest() {} protected: - void loadKeys(const SessionId& sessionId, - const ContentConfiguration& configuration); void fillRandom(const sp& memory); - KeyedVector toHidlKeyedVector(const map& params); hidl_array toHidlArray(const vector& vec) { EXPECT_EQ(vec.size(), 16u); return hidl_array(&vec[0]); @@ -1080,63 +1191,6 @@ class DrmHalVendorDecryptTest : public DrmHalVendorPluginTest { const hidl_vec& subSamples, const vector& key); }; -KeyedVector DrmHalVendorDecryptTest::toHidlKeyedVector( - const map& params) { - std::vector stdKeyedVector; - for (auto it = params.begin(); it != params.end(); ++it) { - KeyValue keyValue; - keyValue.key = it->first; - keyValue.value = it->second; - stdKeyedVector.push_back(keyValue); - } - return KeyedVector(stdKeyedVector); -} - -/** - * Helper method to load keys for subsequent decrypt tests. - * These tests use predetermined key request/response to - * avoid requiring a round trip to a license server. - */ -void DrmHalVendorDecryptTest::loadKeys(const SessionId& sessionId, - const ContentConfiguration& configuration) { - hidl_vec keyRequest; - auto res = drmPlugin->getKeyRequest( - sessionId, configuration.initData, configuration.mimeType, - KeyType::STREAMING, - toHidlKeyedVector(configuration.optionalParameters), - [&](Status status, const hidl_vec& request, - KeyRequestType type, const hidl_string&) { - EXPECT_EQ(Status::OK, status) - << "Failed to get " - "key request for configuration " - << configuration.name; - EXPECT_EQ(type, KeyRequestType::INITIAL); - EXPECT_NE(request.size(), 0u) << "Expected key request size" - " to have length > 0 bytes"; - keyRequest = request; - }); - EXPECT_OK(res); - - /** - * Get key response from vendor module - */ - hidl_vec keyResponse = - vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl); - - EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size " - "to have length > 0 bytes"; - - res = drmPlugin->provideKeyResponse( - sessionId, keyResponse, - [&](Status status, const hidl_vec&) { - EXPECT_EQ(Status::OK, status) - << "Failure providing " - "key response for configuration " - << configuration.name; - }); - EXPECT_OK(res); -} - void DrmHalVendorDecryptTest::fillRandom(const sp& memory) { random_device rd; mt19937 rand(rd());