1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "drm_hal_vendor_test@1.0"
18
19 #include <android/hardware/drm/1.0/ICryptoFactory.h>
20 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
21 #include <android/hardware/drm/1.0/IDrmFactory.h>
22 #include <android/hardware/drm/1.0/IDrmPlugin.h>
23 #include <android/hardware/drm/1.0/IDrmPluginListener.h>
24 #include <android/hardware/drm/1.0/types.h>
25 #include <android/hidl/allocator/1.0/IAllocator.h>
26 #include <gtest/gtest.h>
27 #include <hidlmemory/mapping.h>
28 #include <log/log.h>
29 #include <memory>
30 #include <openssl/aes.h>
31 #include <random>
32
33 #include "drm_hal_vendor_module_api.h"
34 #include "vendor_modules.h"
35 #include <VtsHalHidlTargetCallbackBase.h>
36 #include <VtsHalHidlTargetTestBase.h>
37
38 using ::android::hardware::drm::V1_0::BufferType;
39 using ::android::hardware::drm::V1_0::DestinationBuffer;
40 using ::android::hardware::drm::V1_0::EventType;
41 using ::android::hardware::drm::V1_0::ICryptoFactory;
42 using ::android::hardware::drm::V1_0::ICryptoPlugin;
43 using ::android::hardware::drm::V1_0::IDrmFactory;
44 using ::android::hardware::drm::V1_0::IDrmPlugin;
45 using ::android::hardware::drm::V1_0::IDrmPluginListener;
46 using ::android::hardware::drm::V1_0::KeyedVector;
47 using ::android::hardware::drm::V1_0::KeyRequestType;
48 using ::android::hardware::drm::V1_0::KeyStatus;
49 using ::android::hardware::drm::V1_0::KeyStatusType;
50 using ::android::hardware::drm::V1_0::KeyType;
51 using ::android::hardware::drm::V1_0::KeyValue;
52 using ::android::hardware::drm::V1_0::Mode;
53 using ::android::hardware::drm::V1_0::Pattern;
54 using ::android::hardware::drm::V1_0::SecureStop;
55 using ::android::hardware::drm::V1_0::SecureStopId;
56 using ::android::hardware::drm::V1_0::SessionId;
57 using ::android::hardware::drm::V1_0::SharedBuffer;
58 using ::android::hardware::drm::V1_0::Status;
59 using ::android::hardware::drm::V1_0::SubSample;
60
61 using ::android::hardware::hidl_array;
62 using ::android::hardware::hidl_memory;
63 using ::android::hardware::hidl_string;
64 using ::android::hardware::hidl_vec;
65 using ::android::hardware::Return;
66 using ::android::hardware::Void;
67 using ::android::hidl::allocator::V1_0::IAllocator;
68 using ::android::hidl::memory::V1_0::IMemory;
69 using ::android::sp;
70
71 using std::string;
72 using std::unique_ptr;
73 using std::random_device;
74 using std::map;
75 using std::mt19937;
76 using std::vector;
77
78 using ContentConfiguration = ::DrmHalVTSVendorModule_V1::ContentConfiguration;
79 using Key = ::DrmHalVTSVendorModule_V1::ContentConfiguration::Key;
80 using VtsTestBase = ::testing::VtsHalHidlTargetTestBase;
81
82 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
83 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
84
85 #define RETURN_IF_SKIPPED \
86 if (!vendorModule->isInstalled()) { \
87 std::cout << "[ SKIPPED ] This drm scheme not supported." << \
88 " library:" << GetParam() << " service-name:" << \
89 vendorModule->getServiceName() << std::endl; \
90 return; \
91 }
92
93 static const uint8_t kInvalidUUID[16] = {
94 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
95 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
96 };
97
98 static drm_vts::VendorModules* gVendorModules = nullptr;
99
100 // Test environment for drm
101 class DrmHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
102 public:
103 // get the test environment singleton
Instance()104 static DrmHidlEnvironment* Instance() {
105 static DrmHidlEnvironment* instance = new DrmHidlEnvironment;
106 return instance;
107 }
108
registerTestServices()109 void registerTestServices() override {
110 registerTestService<ICryptoFactory>();
111 registerTestService<IDrmFactory>();
112 setServiceCombMode(::testing::HalServiceCombMode::NO_COMBINATION);
113 }
114
115 private:
DrmHidlEnvironment()116 DrmHidlEnvironment() {}
117
118 GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment);
119 };
120
121 class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
122 public:
DrmHalVendorFactoryTest()123 DrmHalVendorFactoryTest()
124 : vendorModule(static_cast<DrmHalVTSVendorModule_V1*>(
125 gVendorModules->getModule(GetParam()))),
126 contentConfigurations(vendorModule->getContentConfigurations()) {}
127
~DrmHalVendorFactoryTest()128 virtual ~DrmHalVendorFactoryTest() {}
129
SetUp()130 virtual void SetUp() {
131 const ::testing::TestInfo* const test_info =
132 ::testing::UnitTest::GetInstance()->current_test_info();
133 ALOGD("Running test %s.%s from vendor module %s",
134 test_info->test_case_name(), test_info->name(),
135 GetParam().c_str());
136
137 ASSERT_NE(nullptr, vendorModule.get());
138
139 // First try the binderized service name provided by the vendor module.
140 // If that fails, which it can on non-binderized devices, try the default
141 // service.
142 string name = vendorModule->getServiceName();
143 drmFactory = VtsTestBase::getService<IDrmFactory>(name);
144 if (drmFactory == nullptr) {
145 drmFactory = VtsTestBase::getService<IDrmFactory>();
146 }
147 ASSERT_NE(nullptr, drmFactory.get());
148
149 // Do the same for the crypto factory
150 cryptoFactory = VtsTestBase::getService<ICryptoFactory>(name);
151 if (cryptoFactory == nullptr) {
152 cryptoFactory = VtsTestBase::getService<ICryptoFactory>();
153 }
154 ASSERT_NE(nullptr, cryptoFactory.get());
155
156 // If drm scheme not installed skip subsequent tests
157 if (!drmFactory->isCryptoSchemeSupported(getVendorUUID())) {
158 vendorModule->setInstalled(false);
159 return;
160 }
161 }
162
TearDown()163 virtual void TearDown() override {}
164
165 protected:
getVendorUUID()166 hidl_array<uint8_t, 16> getVendorUUID() {
167 vector<uint8_t> uuid = vendorModule->getUUID();
168 return hidl_array<uint8_t, 16>(&uuid[0]);
169 }
170
171 sp<IDrmFactory> drmFactory;
172 sp<ICryptoFactory> cryptoFactory;
173 unique_ptr<DrmHalVTSVendorModule_V1> vendorModule;
174 const vector<ContentConfiguration> contentConfigurations;
175 };
176
TEST_P(DrmHalVendorFactoryTest,ValidateConfigurations)177 TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
178 const char* kVendorStr = "Vendor module ";
179 size_t count = 0;
180 for (const auto& config : contentConfigurations) {
181 ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
182 ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
183 << "has no serverUrl";
184 ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
185 << "has no init data";
186 ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
187 << "has no mime type";
188 ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
189 for (const auto& key : config.keys) {
190 ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
191 << " has zero length keyId";
192 ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
193 << " has zero length key value";
194 }
195 count++;
196 }
197 EXPECT_NE(0u, count);
198 }
199
200 /**
201 * Ensure the factory doesn't support an invalid scheme UUID
202 */
TEST_P(DrmHalVendorFactoryTest,InvalidPluginNotSupported)203 TEST_P(DrmHalVendorFactoryTest, InvalidPluginNotSupported) {
204 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(kInvalidUUID));
205 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(kInvalidUUID));
206 }
207
208 /**
209 * Ensure the factory doesn't support an empty UUID
210 */
TEST_P(DrmHalVendorFactoryTest,EmptyPluginUUIDNotSupported)211 TEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) {
212 hidl_array<uint8_t, 16> emptyUUID;
213 memset(emptyUUID.data(), 0, 16);
214 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
215 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
216 }
217
218 /**
219 * Check if the factory supports the scheme uuid in the config.
220 */
TEST_P(DrmHalVendorFactoryTest,PluginConfigUUIDSupported)221 TEST_P(DrmHalVendorFactoryTest, PluginConfigUUIDSupported) {
222 RETURN_IF_SKIPPED;
223 EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getVendorUUID()));
224 EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getVendorUUID()));
225 }
226
227 /**
228 * Ensure empty content type is not supported
229 */
TEST_P(DrmHalVendorFactoryTest,EmptyContentTypeNotSupported)230 TEST_P(DrmHalVendorFactoryTest, EmptyContentTypeNotSupported) {
231 hidl_string empty;
232 EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
233 }
234
235 /**
236 * Ensure invalid content type is not supported
237 */
TEST_P(DrmHalVendorFactoryTest,InvalidContentTypeNotSupported)238 TEST_P(DrmHalVendorFactoryTest, InvalidContentTypeNotSupported) {
239 hidl_string invalid("abcdabcd");
240 EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
241 }
242
243 /**
244 * Ensure valid content types in the configs are supported
245 */
TEST_P(DrmHalVendorFactoryTest,ValidContentTypeSupported)246 TEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) {
247 RETURN_IF_SKIPPED;
248 for (const auto& config : contentConfigurations) {
249 EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType));
250 }
251 }
252
253 /**
254 * Ensure vendor drm plugin can be created
255 */
TEST_P(DrmHalVendorFactoryTest,CreateVendorDrmPlugin)256 TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
257 RETURN_IF_SKIPPED;
258 hidl_string packageName("android.hardware.drm.test");
259 auto res = drmFactory->createPlugin(
260 getVendorUUID(), packageName,
261 [&](Status status, const sp<IDrmPlugin>& plugin) {
262 EXPECT_EQ(Status::OK, status);
263 EXPECT_NE(nullptr, plugin.get());
264 });
265 EXPECT_OK(res);
266 }
267
268 /**
269 * Ensure vendor crypto plugin can be created
270 */
TEST_P(DrmHalVendorFactoryTest,CreateVendorCryptoPlugin)271 TEST_P(DrmHalVendorFactoryTest, CreateVendorCryptoPlugin) {
272 RETURN_IF_SKIPPED;
273 hidl_vec<uint8_t> initVec;
274 auto res = cryptoFactory->createPlugin(
275 getVendorUUID(), initVec,
276 [&](Status status, const sp<ICryptoPlugin>& plugin) {
277 EXPECT_EQ(Status::OK, status);
278 EXPECT_NE(nullptr, plugin.get());
279 });
280 EXPECT_OK(res);
281 }
282
283 /**
284 * Ensure invalid drm plugin can't be created
285 */
TEST_P(DrmHalVendorFactoryTest,CreateInvalidDrmPlugin)286 TEST_P(DrmHalVendorFactoryTest, CreateInvalidDrmPlugin) {
287 RETURN_IF_SKIPPED;
288 hidl_string packageName("android.hardware.drm.test");
289 auto res = drmFactory->createPlugin(
290 kInvalidUUID, packageName,
291 [&](Status status, const sp<IDrmPlugin>& plugin) {
292 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
293 EXPECT_EQ(nullptr, plugin.get());
294 });
295 EXPECT_OK(res);
296 }
297
298 /**
299 * Ensure invalid crypto plugin can't be created
300 */
TEST_P(DrmHalVendorFactoryTest,CreateInvalidCryptoPlugin)301 TEST_P(DrmHalVendorFactoryTest, CreateInvalidCryptoPlugin) {
302 RETURN_IF_SKIPPED;
303 hidl_vec<uint8_t> initVec;
304 auto res = cryptoFactory->createPlugin(
305 kInvalidUUID, initVec,
306 [&](Status status, const sp<ICryptoPlugin>& plugin) {
307 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
308 EXPECT_EQ(nullptr, plugin.get());
309 });
310 EXPECT_OK(res);
311 }
312
313 class DrmHalVendorPluginTest : public DrmHalVendorFactoryTest {
314 public:
~DrmHalVendorPluginTest()315 virtual ~DrmHalVendorPluginTest() {}
SetUp()316 virtual void SetUp() override {
317 // Create factories
318 DrmHalVendorFactoryTest::SetUp();
319 RETURN_IF_SKIPPED;
320
321 hidl_string packageName("android.hardware.drm.test");
322 auto res = drmFactory->createPlugin(
323 getVendorUUID(), packageName,
324 [this](Status status, const sp<IDrmPlugin>& plugin) {
325 EXPECT_EQ(Status::OK, status);
326 ASSERT_NE(nullptr, plugin.get());
327 drmPlugin = plugin;
328 });
329 ASSERT_OK(res);
330
331 hidl_vec<uint8_t> initVec;
332 res = cryptoFactory->createPlugin(
333 getVendorUUID(), initVec,
334 [this](Status status, const sp<ICryptoPlugin>& plugin) {
335 EXPECT_EQ(Status::OK, status);
336 ASSERT_NE(nullptr, plugin.get());
337 cryptoPlugin = plugin;
338 });
339 ASSERT_OK(res);
340 }
341
TearDown()342 virtual void TearDown() override {}
343
344 SessionId openSession();
345 void closeSession(const SessionId& sessionId);
346 sp<IMemory> getDecryptMemory(size_t size, size_t index);
347 KeyedVector toHidlKeyedVector(const map<string, string>& params);
348 hidl_vec<uint8_t> loadKeys(const SessionId& sessionId,
349 const ContentConfiguration& configuration,
350 const KeyType& type);
351
352 protected:
353 sp<IDrmPlugin> drmPlugin;
354 sp<ICryptoPlugin> cryptoPlugin;
355 };
356
357 /**
358 * DrmPlugin tests
359 */
360
361 /**
362 * Test that a DRM plugin can handle provisioning. While
363 * it is not required that a DRM scheme require provisioning,
364 * it should at least return appropriate status values. If
365 * a provisioning request is returned, it is passed to the
366 * vendor module which should provide a provisioning response
367 * that is delivered back to the HAL.
368 */
369
TEST_P(DrmHalVendorPluginTest,DoProvisioning)370 TEST_P(DrmHalVendorPluginTest, DoProvisioning) {
371 RETURN_IF_SKIPPED;
372 hidl_string certificateType;
373 hidl_string certificateAuthority;
374 hidl_vec<uint8_t> provisionRequest;
375 hidl_string defaultUrl;
376 auto res = drmPlugin->getProvisionRequest(
377 certificateType, certificateAuthority,
378 [&](Status status, const hidl_vec<uint8_t>& request,
379 const hidl_string& url) {
380 if (status == Status::OK) {
381 EXPECT_NE(request.size(), 0u);
382 provisionRequest = request;
383 defaultUrl = url;
384 } else if (status == Status::ERROR_DRM_CANNOT_HANDLE) {
385 EXPECT_EQ(0u, request.size());
386 }
387 });
388 EXPECT_OK(res);
389
390 if (provisionRequest.size() > 0) {
391 vector<uint8_t> response = vendorModule->handleProvisioningRequest(
392 provisionRequest, defaultUrl);
393 ASSERT_NE(0u, response.size());
394
395 auto res = drmPlugin->provideProvisionResponse(
396 response, [&](Status status, const hidl_vec<uint8_t>&,
397 const hidl_vec<uint8_t>&) {
398 EXPECT_EQ(Status::OK, status);
399 });
400 EXPECT_OK(res);
401 }
402 }
403
404 /**
405 * The DRM HAL should return BAD_VALUE if an empty provisioning
406 * response is provided.
407 */
TEST_P(DrmHalVendorPluginTest,ProvideEmptyProvisionResponse)408 TEST_P(DrmHalVendorPluginTest, ProvideEmptyProvisionResponse) {
409 RETURN_IF_SKIPPED;
410 hidl_vec<uint8_t> response;
411 auto res = drmPlugin->provideProvisionResponse(
412 response, [&](Status status, const hidl_vec<uint8_t>&,
413 const hidl_vec<uint8_t>&) {
414 EXPECT_EQ(Status::BAD_VALUE, status);
415 });
416 EXPECT_OK(res);
417 }
418
419 /**
420 * Helper method to open a session and verify that a non-empty
421 * session ID is returned
422 */
openSession()423 SessionId DrmHalVendorPluginTest::openSession() {
424 SessionId sessionId;
425
426 auto res = drmPlugin->openSession([&](Status status, const SessionId& id) {
427 EXPECT_EQ(Status::OK, status);
428 EXPECT_NE(id.size(), 0u);
429 sessionId = id;
430 });
431 EXPECT_OK(res);
432 return sessionId;
433 }
434
435 /**
436 * Helper method to close a session
437 */
closeSession(const SessionId & sessionId)438 void DrmHalVendorPluginTest::closeSession(const SessionId& sessionId) {
439 Status status = drmPlugin->closeSession(sessionId);
440 EXPECT_EQ(Status::OK, status);
441 }
442
toHidlKeyedVector(const map<string,string> & params)443 KeyedVector DrmHalVendorPluginTest::toHidlKeyedVector(
444 const map<string, string>& params) {
445 std::vector<KeyValue> stdKeyedVector;
446 for (auto it = params.begin(); it != params.end(); ++it) {
447 KeyValue keyValue;
448 keyValue.key = it->first;
449 keyValue.value = it->second;
450 stdKeyedVector.push_back(keyValue);
451 }
452 return KeyedVector(stdKeyedVector);
453 }
454
455 /**
456 * Helper method to load keys for subsequent decrypt tests.
457 * These tests use predetermined key request/response to
458 * avoid requiring a round trip to a license server.
459 */
loadKeys(const SessionId & sessionId,const ContentConfiguration & configuration,const KeyType & type=KeyType::STREAMING)460 hidl_vec<uint8_t> DrmHalVendorPluginTest::loadKeys(
461 const SessionId& sessionId, const ContentConfiguration& configuration,
462 const KeyType& type = KeyType::STREAMING) {
463 hidl_vec<uint8_t> keyRequest;
464 auto res = drmPlugin->getKeyRequest(
465 sessionId, configuration.initData, configuration.mimeType, type,
466 toHidlKeyedVector(configuration.optionalParameters),
467 [&](Status status, const hidl_vec<uint8_t>& request,
468 KeyRequestType type, const hidl_string&) {
469 EXPECT_EQ(Status::OK, status) << "Failed to get "
470 "key request for configuration "
471 << configuration.name;
472 EXPECT_EQ(type, KeyRequestType::INITIAL);
473 EXPECT_NE(request.size(), 0u) << "Expected key request size"
474 " to have length > 0 bytes";
475 keyRequest = request;
476 });
477 EXPECT_OK(res);
478
479 /**
480 * Get key response from vendor module
481 */
482 hidl_vec<uint8_t> keyResponse =
483 vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl);
484
485 EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size "
486 "to have length > 0 bytes";
487
488 hidl_vec<uint8_t> keySetId;
489 res = drmPlugin->provideKeyResponse(
490 sessionId, keyResponse,
491 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
492 EXPECT_EQ(Status::OK, status) << "Failure providing "
493 "key response for configuration "
494 << configuration.name;
495 keySetId = myKeySetId;
496 });
497 EXPECT_OK(res);
498 return keySetId;
499 }
500
501 /**
502 * Test that a session can be opened and closed
503 */
TEST_P(DrmHalVendorPluginTest,OpenCloseSession)504 TEST_P(DrmHalVendorPluginTest, OpenCloseSession) {
505 RETURN_IF_SKIPPED;
506 auto sessionId = openSession();
507 closeSession(sessionId);
508 }
509
510 /**
511 * Test that attempting to close an invalid (empty) sessionId
512 * is prohibited with the documented error code.
513 */
TEST_P(DrmHalVendorPluginTest,CloseInvalidSession)514 TEST_P(DrmHalVendorPluginTest, CloseInvalidSession) {
515 RETURN_IF_SKIPPED;
516 SessionId invalidSessionId;
517 Status status = drmPlugin->closeSession(invalidSessionId);
518 EXPECT_EQ(Status::BAD_VALUE, status);
519 }
520
521 /**
522 * Test that attempting to close a valid session twice
523 * is prohibited with the documented error code.
524 */
TEST_P(DrmHalVendorPluginTest,CloseClosedSession)525 TEST_P(DrmHalVendorPluginTest, CloseClosedSession) {
526 RETURN_IF_SKIPPED;
527 auto sessionId = openSession();
528 closeSession(sessionId);
529 Status status = drmPlugin->closeSession(sessionId);
530 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
531 }
532
533 /**
534 * A get key request should fail if no sessionId is provided
535 */
TEST_P(DrmHalVendorPluginTest,GetKeyRequestNoSession)536 TEST_P(DrmHalVendorPluginTest, GetKeyRequestNoSession) {
537 RETURN_IF_SKIPPED;
538 SessionId invalidSessionId;
539 hidl_vec<uint8_t> initData;
540 hidl_string mimeType = "video/mp4";
541 KeyedVector optionalParameters;
542 auto res = drmPlugin->getKeyRequest(
543 invalidSessionId, initData, mimeType, KeyType::STREAMING,
544 optionalParameters,
545 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
546 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
547 EXPECT_OK(res);
548 }
549
550 /**
551 * Test that an empty sessionID returns BAD_VALUE
552 */
TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptySessionId)553 TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptySessionId) {
554 RETURN_IF_SKIPPED;
555 SessionId session;
556
557 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65,
558 0x79, 0x73, 0x22, 0x3a};
559 auto res = drmPlugin->provideKeyResponse(
560 session, keyResponse,
561 [&](Status status, const hidl_vec<uint8_t>& keySetId) {
562 EXPECT_EQ(Status::BAD_VALUE, status);
563 EXPECT_EQ(keySetId.size(), 0u);
564 });
565 EXPECT_OK(res);
566 }
567
568 /**
569 * Test that an empty key response returns BAD_VALUE
570 */
TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptyResponse)571 TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptyResponse) {
572 RETURN_IF_SKIPPED;
573 SessionId session = openSession();
574 hidl_vec<uint8_t> emptyResponse;
575 auto res = drmPlugin->provideKeyResponse(
576 session, emptyResponse,
577 [&](Status status, const hidl_vec<uint8_t>& keySetId) {
578 EXPECT_EQ(Status::BAD_VALUE, status);
579 EXPECT_EQ(keySetId.size(), 0u);
580 });
581 EXPECT_OK(res);
582 closeSession(session);
583 }
584
585 /**
586 * Test that a removeKeys on an empty sessionID returns BAD_VALUE
587 */
TEST_P(DrmHalVendorPluginTest,RemoveKeysEmptySessionId)588 TEST_P(DrmHalVendorPluginTest, RemoveKeysEmptySessionId) {
589 RETURN_IF_SKIPPED;
590 SessionId sessionId;
591 Status status = drmPlugin->removeKeys(sessionId);
592 EXPECT_TRUE(status == Status::BAD_VALUE);
593 }
594
595 /**
596 * Test that remove keys returns okay on an initialized session
597 * that has no keys.
598 */
TEST_P(DrmHalVendorPluginTest,RemoveKeysNewSession)599 TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) {
600 RETURN_IF_SKIPPED;
601 SessionId sessionId = openSession();
602 Status status = drmPlugin->removeKeys(sessionId);
603 EXPECT_TRUE(status == Status::OK);
604 closeSession(sessionId);
605 }
606
607 /**
608 * Test that keys are successfully restored to a new session
609 * for all content having a policy that allows offline use.
610 */
TEST_P(DrmHalVendorPluginTest,RestoreKeys)611 TEST_P(DrmHalVendorPluginTest, RestoreKeys) {
612 RETURN_IF_SKIPPED;
613 for (const auto& config : contentConfigurations) {
614 if (config.policy.allowOffline) {
615 auto sessionId = openSession();
616 hidl_vec<uint8_t> keySetId =
617 loadKeys(sessionId, config, KeyType::OFFLINE);
618 closeSession(sessionId);
619 sessionId = openSession();
620 EXPECT_NE(0u, keySetId.size());
621 Status status = drmPlugin->restoreKeys(sessionId, keySetId);
622 EXPECT_EQ(Status::OK, status);
623 closeSession(sessionId);
624 }
625 }
626 }
627
628 /**
629 * Test that restoreKeys fails with a null key set ID.
630 * Error message is expected to be Status::BAD_VALUE.
631 */
TEST_P(DrmHalVendorPluginTest,RestoreKeysNull)632 TEST_P(DrmHalVendorPluginTest, RestoreKeysNull) {
633 RETURN_IF_SKIPPED;
634 SessionId sessionId = openSession();
635 hidl_vec<uint8_t> nullKeySetId;
636 Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId);
637 EXPECT_EQ(Status::BAD_VALUE, status);
638 closeSession(sessionId);
639 }
640
641 /**
642 * Test that restoreKeys fails to restore keys to a closed
643 * session. Error message is expected to be
644 * Status::ERROR_DRM_SESSION_NOT_OPENED.
645 */
TEST_P(DrmHalVendorPluginTest,RestoreKeysClosedSession)646 TEST_P(DrmHalVendorPluginTest, RestoreKeysClosedSession) {
647 RETURN_IF_SKIPPED;
648 for (const auto& config : contentConfigurations) {
649 if (config.policy.allowOffline) {
650 auto sessionId = openSession();
651 hidl_vec<uint8_t> keySetId =
652 loadKeys(sessionId, config, KeyType::OFFLINE);
653 EXPECT_NE(0u, keySetId.size());
654 closeSession(sessionId);
655 sessionId = openSession();
656 closeSession(sessionId);
657 Status status = drmPlugin->restoreKeys(sessionId, keySetId);
658 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
659 }
660 }
661 }
662
663 /**
664 * Test that the plugin either doesn't support getting
665 * secure stops, or has no secure stops available after
666 * clearing them.
667 */
TEST_P(DrmHalVendorPluginTest,GetSecureStops)668 TEST_P(DrmHalVendorPluginTest, GetSecureStops) {
669 RETURN_IF_SKIPPED;
670 // There may be secure stops, depending on if there were keys
671 // loaded and unloaded previously. Clear them to get to a known
672 // state, then make sure there are none.
673 auto res = drmPlugin->getSecureStops(
674 [&](Status status, const hidl_vec<SecureStop>&) {
675 if (status != Status::OK) {
676 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
677 }
678 });
679 EXPECT_OK(res);
680
681 res = drmPlugin->getSecureStops(
682 [&](Status status, const hidl_vec<SecureStop>& secureStops) {
683 if (status == Status::OK) {
684 EXPECT_EQ(secureStops.size(), 0u);
685 } else {
686 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
687 }
688 });
689 EXPECT_OK(res);
690 }
691
692 /**
693 * Test that the clearkey plugin returns BAD_VALUE if
694 * an empty ssid is provided.
695 */
TEST_P(DrmHalVendorPluginTest,GetSecureStopEmptySSID)696 TEST_P(DrmHalVendorPluginTest, GetSecureStopEmptySSID) {
697 RETURN_IF_SKIPPED;
698 SecureStopId ssid;
699 auto res = drmPlugin->getSecureStop(
700 ssid, [&](Status status, const SecureStop&) {
701 EXPECT_EQ(Status::BAD_VALUE, status);
702 });
703 EXPECT_OK(res);
704 }
705
706 /**
707 * Test that releasing all secure stops either isn't supported
708 * or is completed successfully
709 */
TEST_P(DrmHalVendorPluginTest,ReleaseAllSecureStops)710 TEST_P(DrmHalVendorPluginTest, ReleaseAllSecureStops) {
711 RETURN_IF_SKIPPED;
712 Status status = drmPlugin->releaseAllSecureStops();
713 EXPECT_TRUE(status == Status::OK ||
714 status == Status::ERROR_DRM_CANNOT_HANDLE);
715 }
716
717 /**
718 * Releasing a secure stop without first getting one and sending it to the
719 * server to get a valid SSID should return ERROR_DRM_INVALID_STATE.
720 * This is an optional API so it can also return CANNOT_HANDLE.
721 */
TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopSequenceError)722 TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopSequenceError) {
723 RETURN_IF_SKIPPED;
724 SecureStopId ssid = {1, 2, 3, 4};
725 Status status = drmPlugin->releaseSecureStop(ssid);
726 EXPECT_TRUE(status == Status::ERROR_DRM_INVALID_STATE ||
727 status == Status::ERROR_DRM_CANNOT_HANDLE);
728 }
729
730 /**
731 * Test that releasing a specific secure stop with an empty ssid
732 * return BAD_VALUE. This is an optional API so it can also return
733 * CANNOT_HANDLE.
734 */
TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopEmptySSID)735 TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopEmptySSID) {
736 RETURN_IF_SKIPPED;
737 SecureStopId ssid;
738 Status status = drmPlugin->releaseSecureStop(ssid);
739 EXPECT_TRUE(status == Status::BAD_VALUE ||
740 status == Status::ERROR_DRM_CANNOT_HANDLE);
741 }
742
743 /**
744 * The following five tests verify that the properties
745 * defined in the MediaDrm API are supported by
746 * the plugin.
747 */
TEST_P(DrmHalVendorPluginTest,GetVendorProperty)748 TEST_P(DrmHalVendorPluginTest, GetVendorProperty) {
749 RETURN_IF_SKIPPED;
750 auto res = drmPlugin->getPropertyString(
751 "vendor", [&](Status status, const hidl_string& value) {
752 EXPECT_EQ(Status::OK, status);
753 EXPECT_NE(value.size(), 0u);
754 });
755 EXPECT_OK(res);
756 }
757
TEST_P(DrmHalVendorPluginTest,GetVersionProperty)758 TEST_P(DrmHalVendorPluginTest, GetVersionProperty) {
759 RETURN_IF_SKIPPED;
760 auto res = drmPlugin->getPropertyString(
761 "version", [&](Status status, const hidl_string& value) {
762 EXPECT_EQ(Status::OK, status);
763 EXPECT_NE(value.size(), 0u);
764 });
765 EXPECT_OK(res);
766 }
767
TEST_P(DrmHalVendorPluginTest,GetDescriptionProperty)768 TEST_P(DrmHalVendorPluginTest, GetDescriptionProperty) {
769 RETURN_IF_SKIPPED;
770 auto res = drmPlugin->getPropertyString(
771 "description", [&](Status status, const hidl_string& value) {
772 EXPECT_EQ(Status::OK, status);
773 EXPECT_NE(value.size(), 0u);
774 });
775 EXPECT_OK(res);
776 }
777
TEST_P(DrmHalVendorPluginTest,GetAlgorithmsProperty)778 TEST_P(DrmHalVendorPluginTest, GetAlgorithmsProperty) {
779 RETURN_IF_SKIPPED;
780 auto res = drmPlugin->getPropertyString(
781 "algorithms", [&](Status status, const hidl_string& value) {
782 if (status == Status::OK) {
783 EXPECT_NE(value.size(), 0u);
784 } else {
785 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
786 }
787 });
788 EXPECT_OK(res);
789 }
790
TEST_P(DrmHalVendorPluginTest,GetPropertyUniqueDeviceID)791 TEST_P(DrmHalVendorPluginTest, GetPropertyUniqueDeviceID) {
792 RETURN_IF_SKIPPED;
793 auto res = drmPlugin->getPropertyByteArray(
794 "deviceUniqueId",
795 [&](Status status, const hidl_vec<uint8_t>& value) {
796 if (status == Status::OK) {
797 EXPECT_NE(value.size(), 0u);
798 } else {
799 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
800 }
801 });
802 EXPECT_OK(res);
803 }
804
805 /**
806 * Test that attempting to read invalid string and byte array
807 * properties returns the documented error code.
808 */
TEST_P(DrmHalVendorPluginTest,GetInvalidStringProperty)809 TEST_P(DrmHalVendorPluginTest, GetInvalidStringProperty) {
810 RETURN_IF_SKIPPED;
811 auto res = drmPlugin->getPropertyString(
812 "invalid", [&](Status status, const hidl_string&) {
813 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
814 });
815 EXPECT_OK(res);
816 }
817
TEST_P(DrmHalVendorPluginTest,GetInvalidByteArrayProperty)818 TEST_P(DrmHalVendorPluginTest, GetInvalidByteArrayProperty) {
819 RETURN_IF_SKIPPED;
820 auto res = drmPlugin->getPropertyByteArray(
821 "invalid", [&](Status status, const hidl_vec<uint8_t>&) {
822 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
823 });
824 EXPECT_OK(res);
825 }
826
827 /**
828 * Test that setting invalid string and byte array properties returns
829 * the expected status value.
830 */
TEST_P(DrmHalVendorPluginTest,SetStringPropertyNotSupported)831 TEST_P(DrmHalVendorPluginTest, SetStringPropertyNotSupported) {
832 RETURN_IF_SKIPPED;
833 EXPECT_EQ(drmPlugin->setPropertyString("awefijaeflijwef", "value"),
834 Status::ERROR_DRM_CANNOT_HANDLE);
835 }
836
TEST_P(DrmHalVendorPluginTest,SetByteArrayPropertyNotSupported)837 TEST_P(DrmHalVendorPluginTest, SetByteArrayPropertyNotSupported) {
838 RETURN_IF_SKIPPED;
839 hidl_vec<uint8_t> value;
840 EXPECT_EQ(drmPlugin->setPropertyByteArray("awefijaeflijwef", value),
841 Status::ERROR_DRM_CANNOT_HANDLE);
842 }
843
844 /**
845 * Test that setting an invalid cipher algorithm returns
846 * the expected status value.
847 */
TEST_P(DrmHalVendorPluginTest,SetCipherInvalidAlgorithm)848 TEST_P(DrmHalVendorPluginTest, SetCipherInvalidAlgorithm) {
849 RETURN_IF_SKIPPED;
850 SessionId session = openSession();
851 hidl_string algorithm;
852 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
853 EXPECT_EQ(Status::BAD_VALUE, status);
854 closeSession(session);
855 }
856
857 /**
858 * Test that setting a cipher algorithm with no session returns
859 * the expected status value.
860 */
TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithmNoSession)861 TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithmNoSession) {
862 RETURN_IF_SKIPPED;
863 SessionId session;
864 hidl_string algorithm = "AES/CBC/NoPadding";
865 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
866 EXPECT_EQ(Status::BAD_VALUE, status);
867 }
868
869 /**
870 * Test that setting a valid cipher algorithm returns
871 * the expected status value. It is not required that all
872 * vendor modules support this algorithm, but they must
873 * either accept it or return ERROR_DRM_CANNOT_HANDLE
874 */
TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithm)875 TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithm) {
876 RETURN_IF_SKIPPED;
877 SessionId session = openSession();
878 ;
879 hidl_string algorithm = "AES/CBC/NoPadding";
880 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
881 EXPECT_TRUE(status == Status::OK ||
882 status == Status::ERROR_DRM_CANNOT_HANDLE);
883 closeSession(session);
884 }
885
886 /**
887 * Test that setting an invalid mac algorithm returns
888 * the expected status value.
889 */
TEST_P(DrmHalVendorPluginTest,SetMacInvalidAlgorithm)890 TEST_P(DrmHalVendorPluginTest, SetMacInvalidAlgorithm) {
891 RETURN_IF_SKIPPED;
892 SessionId session = openSession();
893 hidl_string algorithm;
894 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
895 EXPECT_EQ(Status::BAD_VALUE, status);
896 closeSession(session);
897 }
898
899 /**
900 * Test that setting a mac algorithm with no session returns
901 * the expected status value.
902 */
TEST_P(DrmHalVendorPluginTest,SetMacNullAlgorithmNoSession)903 TEST_P(DrmHalVendorPluginTest, SetMacNullAlgorithmNoSession) {
904 RETURN_IF_SKIPPED;
905 SessionId session;
906 hidl_string algorithm = "HmacSHA256";
907 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
908 EXPECT_EQ(Status::BAD_VALUE, status);
909 }
910
911 /**
912 * Test that setting a valid mac algorithm returns
913 * the expected status value. It is not required that all
914 * vendor modules support this algorithm, but they must
915 * either accept it or return ERROR_DRM_CANNOT_HANDLE
916 */
TEST_P(DrmHalVendorPluginTest,SetMacAlgorithm)917 TEST_P(DrmHalVendorPluginTest, SetMacAlgorithm) {
918 RETURN_IF_SKIPPED;
919 SessionId session = openSession();
920 hidl_string algorithm = "HmacSHA256";
921 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
922 EXPECT_TRUE(status == Status::OK ||
923 status == Status::ERROR_DRM_CANNOT_HANDLE);
924 closeSession(session);
925 }
926
927 /**
928 * The Generic* methods provide general purpose crypto operations
929 * that may be used for applications other than DRM. They leverage
930 * the hardware root of trust and secure key distribution mechanisms
931 * of a DRM system to enable app-specific crypto functionality where
932 * the crypto keys are not exposed outside of the trusted execution
933 * environment.
934 *
935 * Generic encrypt/decrypt/sign/verify should fail on invalid
936 * inputs, e.g. empty sessionId
937 */
TEST_P(DrmHalVendorPluginTest,GenericEncryptNoSession)938 TEST_P(DrmHalVendorPluginTest, GenericEncryptNoSession) {
939 RETURN_IF_SKIPPED;
940 SessionId session;
941 hidl_vec<uint8_t> keyId, input, iv;
942 auto res = drmPlugin->encrypt(
943 session, keyId, input, iv,
944 [&](Status status, const hidl_vec<uint8_t>&) {
945 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
946 });
947 EXPECT_OK(res);
948 }
949
TEST_P(DrmHalVendorPluginTest,GenericDecryptNoSession)950 TEST_P(DrmHalVendorPluginTest, GenericDecryptNoSession) {
951 RETURN_IF_SKIPPED;
952 SessionId session;
953 hidl_vec<uint8_t> keyId, input, iv;
954 auto res = drmPlugin->decrypt(
955 session, keyId, input, iv,
956 [&](Status status, const hidl_vec<uint8_t>&) {
957 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
958 });
959 EXPECT_OK(res);
960 }
961
TEST_P(DrmHalVendorPluginTest,GenericSignNoSession)962 TEST_P(DrmHalVendorPluginTest, GenericSignNoSession) {
963 RETURN_IF_SKIPPED;
964 SessionId session;
965 hidl_vec<uint8_t> keyId, message;
966 auto res = drmPlugin->sign(
967 session, keyId, message,
968 [&](Status status, const hidl_vec<uint8_t>&) {
969 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
970 });
971 EXPECT_OK(res);
972 }
973
TEST_P(DrmHalVendorPluginTest,GenericVerifyNoSession)974 TEST_P(DrmHalVendorPluginTest, GenericVerifyNoSession) {
975 RETURN_IF_SKIPPED;
976 SessionId session;
977 hidl_vec<uint8_t> keyId, message, signature;
978 auto res = drmPlugin->verify(
979 session, keyId, message, signature, [&](Status status, bool) {
980 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
981 });
982 EXPECT_OK(res);
983 }
984
TEST_P(DrmHalVendorPluginTest,GenericSignRSANoSession)985 TEST_P(DrmHalVendorPluginTest, GenericSignRSANoSession) {
986 RETURN_IF_SKIPPED;
987 SessionId session;
988 hidl_string algorithm;
989 hidl_vec<uint8_t> message, wrappedKey;
990 auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey,
991 [&](Status status, const hidl_vec<uint8_t>&) {
992 EXPECT_EQ(Status::BAD_VALUE, status);
993 });
994 EXPECT_OK(res);
995 }
996
997 /**
998 * Exercise the requiresSecureDecoderComponent method. Additional tests
999 * will verify positive cases with specific vendor content configurations.
1000 * Below we just test the negative cases.
1001 */
1002
1003 /**
1004 * Verify that requiresSecureDecoderComponent handles empty mimetype.
1005 */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderEmptyMimeType)1006 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderEmptyMimeType) {
1007 RETURN_IF_SKIPPED;
1008 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent(""));
1009 }
1010
1011 /**
1012 * Verify that requiresSecureDecoderComponent handles invalid mimetype.
1013 */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderInvalidMimeType)1014 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderInvalidMimeType) {
1015 RETURN_IF_SKIPPED;
1016 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("bad"));
1017 }
1018
1019 /**
1020 * Verify that requiresSecureDecoderComponent returns true for secure
1021 * configurations
1022 */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderConfig)1023 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
1024 RETURN_IF_SKIPPED;
1025 for (const auto& config : contentConfigurations) {
1026 for (const auto& key : config.keys) {
1027 if (key.isSecure) {
1028 EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType));
1029 break;
1030 }
1031 }
1032 }
1033 }
1034
1035 /**
1036 * Event Handling tests
1037 */
1038 struct ListenerEventArgs {
1039 EventType eventType;
1040 SessionId sessionId;
1041 hidl_vec<uint8_t> data;
1042 int64_t expiryTimeInMS;
1043 hidl_vec<KeyStatus> keyStatusList;
1044 bool hasNewUsableKey;
1045 };
1046
1047 const char *kCallbackEvent = "SendEvent";
1048 const char *kCallbackExpirationUpdate = "SendExpirationUpdate";
1049 const char *kCallbackKeysChange = "SendKeysChange";
1050
1051 class TestDrmPluginListener
1052 : public ::testing::VtsHalHidlTargetCallbackBase<ListenerEventArgs>,
1053 public IDrmPluginListener {
1054 public:
TestDrmPluginListener()1055 TestDrmPluginListener() {
1056 SetWaitTimeoutDefault(std::chrono::milliseconds(500));
1057 }
~TestDrmPluginListener()1058 virtual ~TestDrmPluginListener() {}
1059
sendEvent(EventType eventType,const hidl_vec<uint8_t> & sessionId,const hidl_vec<uint8_t> & data)1060 virtual Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
1061 const hidl_vec<uint8_t>& data) override {
1062 ListenerEventArgs args;
1063 args.eventType = eventType;
1064 args.sessionId = sessionId;
1065 args.data = data;
1066 NotifyFromCallback(kCallbackEvent, args);
1067 return Void();
1068 }
1069
sendExpirationUpdate(const hidl_vec<uint8_t> & sessionId,int64_t expiryTimeInMS)1070 virtual Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
1071 int64_t expiryTimeInMS) override {
1072 ListenerEventArgs args;
1073 args.sessionId = sessionId;
1074 args.expiryTimeInMS = expiryTimeInMS;
1075 NotifyFromCallback(kCallbackExpirationUpdate, args);
1076 return Void();
1077 }
1078
sendKeysChange(const hidl_vec<uint8_t> & sessionId,const hidl_vec<KeyStatus> & keyStatusList,bool hasNewUsableKey)1079 virtual Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
1080 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) override {
1081 ListenerEventArgs args;
1082 args.sessionId = sessionId;
1083 args.keyStatusList = keyStatusList;
1084 args.hasNewUsableKey = hasNewUsableKey;
1085 NotifyFromCallback(kCallbackKeysChange, args);
1086 return Void();
1087 }
1088 };
1089
1090
1091 /**
1092 * Simulate the plugin sending events. Make sure the listener
1093 * gets them.
1094 */
TEST_P(DrmHalVendorPluginTest,ListenerEvents)1095 TEST_P(DrmHalVendorPluginTest, ListenerEvents) {
1096 RETURN_IF_SKIPPED;
1097 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
1098 drmPlugin->setListener(listener);
1099 auto sessionId = openSession();
1100 hidl_vec<uint8_t> data = {0, 1, 2};
1101 EventType eventTypes[] = {EventType::PROVISION_REQUIRED,
1102 EventType::KEY_NEEDED,
1103 EventType::KEY_EXPIRED,
1104 EventType::VENDOR_DEFINED,
1105 EventType::SESSION_RECLAIMED};
1106 for (auto eventType : eventTypes) {
1107 drmPlugin->sendEvent(eventType, sessionId, data);
1108 auto result = listener->WaitForCallback(kCallbackEvent);
1109 EXPECT_TRUE(result.no_timeout);
1110 EXPECT_TRUE(result.args);
1111 EXPECT_EQ(eventType, result.args->eventType);
1112 EXPECT_EQ(sessionId, result.args->sessionId);
1113 EXPECT_EQ(data, result.args->data);
1114 }
1115 closeSession(sessionId);
1116 }
1117
1118 /**
1119 * Simulate the plugin sending expiration updates and make sure
1120 * the listener gets them.
1121 */
TEST_P(DrmHalVendorPluginTest,ListenerExpirationUpdate)1122 TEST_P(DrmHalVendorPluginTest, ListenerExpirationUpdate) {
1123 RETURN_IF_SKIPPED;
1124 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
1125 drmPlugin->setListener(listener);
1126 auto sessionId = openSession();
1127 drmPlugin->sendExpirationUpdate(sessionId, 100);
1128 auto result = listener->WaitForCallback(kCallbackExpirationUpdate);
1129 EXPECT_TRUE(result.no_timeout);
1130 EXPECT_TRUE(result.args);
1131 EXPECT_EQ(sessionId, result.args->sessionId);
1132 EXPECT_EQ(100, result.args->expiryTimeInMS);
1133 closeSession(sessionId);
1134 }
1135
1136 /**
1137 * Simulate the plugin sending keys change and make sure
1138 * the listener gets them.
1139 */
TEST_P(DrmHalVendorPluginTest,ListenerKeysChange)1140 TEST_P(DrmHalVendorPluginTest, ListenerKeysChange) {
1141 RETURN_IF_SKIPPED;
1142 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
1143 drmPlugin->setListener(listener);
1144 auto sessionId = openSession();
1145 const hidl_vec<KeyStatus> keyStatusList = {
1146 {{1}, KeyStatusType::USABLE},
1147 {{2}, KeyStatusType::EXPIRED},
1148 {{3}, KeyStatusType::OUTPUTNOTALLOWED},
1149 {{4}, KeyStatusType::STATUSPENDING},
1150 {{5}, KeyStatusType::INTERNALERROR},
1151 };
1152
1153 drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
1154 auto result = listener->WaitForCallback(kCallbackKeysChange);
1155 EXPECT_TRUE(result.no_timeout);
1156 EXPECT_TRUE(result.args);
1157 EXPECT_EQ(sessionId, result.args->sessionId);
1158 EXPECT_EQ(keyStatusList, result.args->keyStatusList);
1159 closeSession(sessionId);
1160 }
1161
1162 /**
1163 * Negative listener tests. Call send methods with no
1164 * listener set.
1165 */
TEST_P(DrmHalVendorPluginTest,NotListening)1166 TEST_P(DrmHalVendorPluginTest, NotListening) {
1167 RETURN_IF_SKIPPED;
1168 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
1169 drmPlugin->setListener(listener);
1170 drmPlugin->setListener(nullptr);
1171
1172 SessionId sessionId;
1173 hidl_vec<uint8_t> data;
1174 hidl_vec<KeyStatus> keyStatusList;
1175 drmPlugin->sendEvent(EventType::PROVISION_REQUIRED, sessionId, data);
1176 drmPlugin->sendExpirationUpdate(sessionId, 100);
1177 drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
1178 auto result = listener->WaitForCallbackAny(
1179 {kCallbackEvent, kCallbackExpirationUpdate, kCallbackKeysChange});
1180 EXPECT_FALSE(result.no_timeout);
1181 }
1182
1183
1184 /**
1185 * CryptoPlugin tests
1186 */
1187
1188 /**
1189 * Exercise the NotifyResolution API. There is no observable result,
1190 * just call the method for coverage.
1191 */
TEST_P(DrmHalVendorPluginTest,NotifyResolution)1192 TEST_P(DrmHalVendorPluginTest, NotifyResolution) {
1193 RETURN_IF_SKIPPED;
1194 cryptoPlugin->notifyResolution(1920, 1080);
1195 }
1196
1197 /**
1198 * getDecryptMemory allocates memory for decryption, then sets it
1199 * as a shared buffer base in the crypto hal. The allocated and
1200 * mapped IMemory is returned.
1201 *
1202 * @param size the size of the memory segment to allocate
1203 * @param the index of the memory segment which will be used
1204 * to refer to it for decryption.
1205 */
getDecryptMemory(size_t size,size_t index)1206 sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
1207 size_t index) {
1208 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
1209 EXPECT_NE(nullptr, ashmemAllocator.get());
1210
1211 hidl_memory hidlMemory;
1212 auto res = ashmemAllocator->allocate(
1213 size, [&](bool success, const hidl_memory& memory) {
1214 EXPECT_EQ(success, true);
1215 EXPECT_EQ(memory.size(), size);
1216 hidlMemory = memory;
1217 });
1218
1219 EXPECT_OK(res);
1220
1221 sp<IMemory> mappedMemory = mapMemory(hidlMemory);
1222 EXPECT_NE(nullptr, mappedMemory.get());
1223 res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
1224 EXPECT_OK(res);
1225 return mappedMemory;
1226 }
1227
1228 /**
1229 * Exercise the setMediaDrmSession method. setMediaDrmSession
1230 * is used to associate a drm session with a crypto session.
1231 */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSession)1232 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSession) {
1233 RETURN_IF_SKIPPED;
1234 auto sessionId = openSession();
1235 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1236 EXPECT_EQ(Status::OK, status);
1237 closeSession(sessionId);
1238 }
1239
1240 /**
1241 * setMediaDrmSession with a closed session id
1242 */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionClosedSession)1243 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionClosedSession) {
1244 RETURN_IF_SKIPPED;
1245 auto sessionId = openSession();
1246 closeSession(sessionId);
1247 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1248 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
1249 }
1250
1251 /**
1252 * setMediaDrmSession with a empty session id: BAD_VALUE
1253 */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionEmptySession)1254 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) {
1255 RETURN_IF_SKIPPED;
1256 SessionId sessionId;
1257 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1258 EXPECT_EQ(Status::BAD_VALUE, status);
1259 }
1260
1261 /**
1262 * Decrypt tests
1263 */
1264
1265 class DrmHalVendorDecryptTest : public DrmHalVendorPluginTest {
1266 public:
1267 DrmHalVendorDecryptTest() = default;
~DrmHalVendorDecryptTest()1268 virtual ~DrmHalVendorDecryptTest() {}
1269
1270 protected:
1271 void fillRandom(const sp<IMemory>& memory);
toHidlArray(const vector<uint8_t> & vec)1272 hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
1273 EXPECT_EQ(vec.size(), 16u);
1274 return hidl_array<uint8_t, 16>(&vec[0]);
1275 }
1276 hidl_vec<KeyValue> queryKeyStatus(SessionId sessionId);
1277 void removeKeys(SessionId sessionId);
1278 uint32_t decrypt(Mode mode, bool isSecure,
1279 const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
1280 const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
1281 const vector<uint8_t>& key, Status expectedStatus);
1282 void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
1283 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
1284 void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
1285 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
1286 };
1287
fillRandom(const sp<IMemory> & memory)1288 void DrmHalVendorDecryptTest::fillRandom(const sp<IMemory>& memory) {
1289 random_device rd;
1290 mt19937 rand(rd());
1291 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) {
1292 auto p = static_cast<uint32_t*>(
1293 static_cast<void*>(memory->getPointer()));
1294 p[i] = rand();
1295 }
1296 }
1297
queryKeyStatus(SessionId sessionId)1298 hidl_vec<KeyValue> DrmHalVendorDecryptTest::queryKeyStatus(SessionId sessionId) {
1299 hidl_vec<KeyValue> keyStatus;
1300 auto res = drmPlugin->queryKeyStatus(sessionId,
1301 [&](Status status, KeyedVector info) {
1302 EXPECT_EQ(Status::OK, status);
1303 keyStatus = info;
1304 });
1305 EXPECT_OK(res);
1306 return keyStatus;
1307 }
1308
removeKeys(SessionId sessionId)1309 void DrmHalVendorDecryptTest::removeKeys(SessionId sessionId) {
1310 auto res = drmPlugin->removeKeys(sessionId);
1311 EXPECT_OK(res);
1312 }
1313
decrypt(Mode mode,bool isSecure,const hidl_array<uint8_t,16> & keyId,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const Pattern & pattern,const vector<uint8_t> & key,Status expectedStatus)1314 uint32_t DrmHalVendorDecryptTest::decrypt(Mode mode, bool isSecure,
1315 const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
1316 const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
1317 const vector<uint8_t>& key, Status expectedStatus) {
1318 const size_t kSegmentIndex = 0;
1319
1320 uint8_t localIv[AES_BLOCK_SIZE];
1321 memcpy(localIv, iv, AES_BLOCK_SIZE);
1322
1323 size_t totalSize = 0;
1324 for (size_t i = 0; i < subSamples.size(); i++) {
1325 totalSize += subSamples[i].numBytesOfClearData;
1326 totalSize += subSamples[i].numBytesOfEncryptedData;
1327 }
1328
1329 // The first totalSize bytes of shared memory is the encrypted
1330 // input, the second totalSize bytes is the decrypted output.
1331 sp<IMemory> sharedMemory =
1332 getDecryptMemory(totalSize * 2, kSegmentIndex);
1333
1334 SharedBuffer sourceBuffer = {
1335 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
1336 fillRandom(sharedMemory);
1337
1338 DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
1339 {.bufferId = kSegmentIndex,
1340 .offset = totalSize,
1341 .size = totalSize},
1342 .secureMemory = nullptr};
1343 uint64_t offset = 0;
1344 uint32_t bytesWritten = 0;
1345 auto res = cryptoPlugin->decrypt(isSecure, keyId, localIv, mode, pattern,
1346 subSamples, sourceBuffer, offset, destBuffer,
1347 [&](Status status, uint32_t count, string detailedError) {
1348 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
1349 detailedError;
1350 bytesWritten = count;
1351 });
1352 EXPECT_OK(res);
1353
1354 if (bytesWritten != totalSize) {
1355 return bytesWritten;
1356 }
1357 uint8_t* base = static_cast<uint8_t*>(
1358 static_cast<void*>(sharedMemory->getPointer()));
1359
1360 // generate reference vector
1361 vector<uint8_t> reference(totalSize);
1362
1363 memcpy(localIv, iv, AES_BLOCK_SIZE);
1364 switch (mode) {
1365 case Mode::UNENCRYPTED:
1366 memcpy(&reference[0], base, totalSize);
1367 break;
1368 case Mode::AES_CTR:
1369 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key);
1370 break;
1371 case Mode::AES_CBC:
1372 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key);
1373 break;
1374 case Mode::AES_CBC_CTS:
1375 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
1376 break;
1377 }
1378
1379 // compare reference to decrypted data which is at base + total size
1380 EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]),
1381 static_cast<void*>(base + totalSize), totalSize))
1382 << "decrypt data mismatch";
1383 return totalSize;
1384 }
1385
1386 /**
1387 * Decrypt a list of clear+encrypted subsamples using the specified key
1388 * in AES-CTR mode
1389 */
aes_ctr_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1390 void DrmHalVendorDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
1391 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1392 const vector<uint8_t>& key) {
1393
1394 AES_KEY decryptionKey;
1395 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1396
1397 size_t offset = 0;
1398 unsigned blockOffset = 0;
1399 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
1400 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
1401
1402 for (size_t i = 0; i < subSamples.size(); i++) {
1403 const SubSample& subSample = subSamples[i];
1404
1405 if (subSample.numBytesOfClearData > 0) {
1406 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1407 offset += subSample.numBytesOfClearData;
1408 }
1409
1410 if (subSample.numBytesOfEncryptedData > 0) {
1411 AES_ctr128_encrypt(src + offset, dest + offset,
1412 subSample.numBytesOfEncryptedData, &decryptionKey,
1413 iv, previousEncryptedCounter, &blockOffset);
1414 offset += subSample.numBytesOfEncryptedData;
1415 }
1416 }
1417 }
1418
1419 /**
1420 * Decrypt a list of clear+encrypted subsamples using the specified key
1421 * in AES-CBC mode
1422 */
aes_cbc_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1423 void DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
1424 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1425 const vector<uint8_t>& key) {
1426 AES_KEY decryptionKey;
1427 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1428
1429 size_t offset = 0;
1430 for (size_t i = 0; i < subSamples.size(); i++) {
1431 const SubSample& subSample = subSamples[i];
1432
1433 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1434 offset += subSample.numBytesOfClearData;
1435
1436 AES_cbc_encrypt(src + offset, dest + offset, subSample.numBytesOfEncryptedData,
1437 &decryptionKey, iv, 0 /* decrypt */);
1438 offset += subSample.numBytesOfEncryptedData;
1439 }
1440 }
1441
1442
1443 /**
1444 * Test key status with empty session id, should return BAD_VALUE
1445 */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusInvalidSession)1446 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusInvalidSession) {
1447 RETURN_IF_SKIPPED;
1448 SessionId sessionId;
1449 auto res = drmPlugin->queryKeyStatus(sessionId,
1450 [&](Status status, KeyedVector /* info */) {
1451 EXPECT_EQ(Status::BAD_VALUE, status);
1452 });
1453 EXPECT_OK(res);
1454 }
1455
1456
1457 /**
1458 * Test key status. There should be no key status prior to loading keys
1459 */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusWithNoKeys)1460 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusWithNoKeys) {
1461 RETURN_IF_SKIPPED;
1462 auto sessionId = openSession();
1463 auto keyStatus = queryKeyStatus(sessionId);
1464 EXPECT_EQ(0u, keyStatus.size());
1465 closeSession(sessionId);
1466 }
1467
1468
1469 /**
1470 * Test key status. There should be key status after loading keys.
1471 */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatus)1472 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) {
1473 RETURN_IF_SKIPPED;
1474 for (const auto& config : contentConfigurations) {
1475 auto sessionId = openSession();
1476 loadKeys(sessionId, config);
1477 auto keyStatus = queryKeyStatus(sessionId);
1478 EXPECT_NE(0u, keyStatus.size());
1479 closeSession(sessionId);
1480 }
1481 }
1482
1483 /**
1484 * Positive decrypt test. "Decrypt" a single clear segment and verify.
1485 */
TEST_P(DrmHalVendorDecryptTest,ClearSegmentTest)1486 TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
1487 RETURN_IF_SKIPPED;
1488 for (const auto& config : contentConfigurations) {
1489 for (const auto& key : config.keys) {
1490 const size_t kSegmentSize = 1024;
1491 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1492 const Pattern noPattern = {0, 0};
1493 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1494 .numBytesOfEncryptedData = 0}};
1495 auto sessionId = openSession();
1496 loadKeys(sessionId, config);
1497
1498 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1499 EXPECT_EQ(Status::OK, status);
1500
1501 uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
1502 &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1503 EXPECT_EQ(kSegmentSize, byteCount);
1504
1505 closeSession(sessionId);
1506 }
1507 }
1508 }
1509
1510 /**
1511 * Positive decrypt test. Decrypt a single segment using aes_ctr.
1512 * Verify data matches.
1513 */
TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTest)1514 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) {
1515 RETURN_IF_SKIPPED;
1516 for (const auto& config : contentConfigurations) {
1517 for (const auto& key : config.keys) {
1518 const size_t kSegmentSize = 1024;
1519 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1520 const Pattern noPattern = {0, 0};
1521 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1522 .numBytesOfEncryptedData = 0}};
1523 auto sessionId = openSession();
1524 loadKeys(sessionId, config);
1525
1526 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1527 EXPECT_EQ(Status::OK, status);
1528
1529 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId),
1530 &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1531 EXPECT_EQ(kSegmentSize, byteCount);
1532
1533 closeSession(sessionId);
1534 }
1535 }
1536 }
1537
1538 /**
1539 * Negative decrypt test. Decrypt without loading keys.
1540 */
TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTestNoKeys)1541 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
1542 RETURN_IF_SKIPPED;
1543 for (const auto& config : contentConfigurations) {
1544 for (const auto& key : config.keys) {
1545 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1546 const Pattern noPattern = {0, 0};
1547 const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1548 .numBytesOfEncryptedData = 256}};
1549 auto sessionId = openSession();
1550
1551 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1552 EXPECT_EQ(Status::OK, status);
1553
1554 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1555 toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1556 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
1557 EXPECT_EQ(0u, byteCount);
1558
1559 closeSession(sessionId);
1560 }
1561 }
1562 }
1563
1564 /**
1565 * Test key removal. Load keys then remove them and verify that
1566 * decryption can't be performed.
1567 */
TEST_P(DrmHalVendorDecryptTest,AttemptDecryptWithKeysRemoved)1568 TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
1569 RETURN_IF_SKIPPED;
1570 for (const auto& config : contentConfigurations) {
1571 for (const auto& key : config.keys) {
1572 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1573 const Pattern noPattern = {0, 0};
1574 const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1575 .numBytesOfEncryptedData = 256}};
1576 auto sessionId = openSession();
1577
1578 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1579 EXPECT_EQ(Status::OK, status);
1580
1581 loadKeys(sessionId, config);
1582 removeKeys(sessionId);
1583
1584 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1585 toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1586 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
1587 EXPECT_EQ(0u, byteCount);
1588
1589 closeSession(sessionId);
1590 }
1591 }
1592 }
1593
1594
1595 /**
1596 * Instantiate the set of test cases for each vendor module
1597 */
1598
1599 INSTANTIATE_TEST_CASE_P(
1600 DrmHalVendorFactoryTestCases, DrmHalVendorFactoryTest,
1601 testing::ValuesIn(gVendorModules->getPathList()));
1602
1603 INSTANTIATE_TEST_CASE_P(
1604 DrmHalVendorPluginTestCases, DrmHalVendorPluginTest,
1605 testing::ValuesIn(gVendorModules->getPathList()));
1606
1607 INSTANTIATE_TEST_CASE_P(
1608 DrmHalVendorDecryptTestCases, DrmHalVendorDecryptTest,
1609 testing::ValuesIn(gVendorModules->getPathList()));
1610
main(int argc,char ** argv)1611 int main(int argc, char** argv) {
1612 #if defined(__LP64__)
1613 const char* kModulePath = "/data/local/tmp/64/lib";
1614 #else
1615 const char* kModulePath = "/data/local/tmp/32/lib";
1616 #endif
1617 gVendorModules = new drm_vts::VendorModules(kModulePath);
1618 if (gVendorModules->getPathList().size() == 0) {
1619 std::cerr << "WARNING: No vendor modules found in " << kModulePath <<
1620 ", all vendor tests will be skipped" << std::endl;
1621 }
1622 ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
1623 ::testing::InitGoogleTest(&argc, argv);
1624 DrmHidlEnvironment::Instance()->init(&argc, argv);
1625 int status = RUN_ALL_TESTS();
1626 ALOGI("Test result = %d", status);
1627 return status;
1628 }
1629