• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_clearkey_test@1.1"
18 
19 #include <android/hardware/drm/1.1/ICryptoFactory.h>
20 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
21 #include <android/hardware/drm/1.1/IDrmFactory.h>
22 #include <android/hardware/drm/1.0/IDrmPlugin.h>
23 #include <android/hardware/drm/1.1/IDrmPlugin.h>
24 #include <android/hardware/drm/1.0/types.h>
25 #include <android/hardware/drm/1.1/types.h>
26 #include <android/hidl/allocator/1.0/IAllocator.h>
27 #include <android/hidl/manager/1.0/IServiceManager.h>
28 #include <gtest/gtest.h>
29 #include <hidl/HidlSupport.h>
30 #include <hidl/ServiceManagement.h>
31 #include <hidlmemory/mapping.h>
32 #include <log/log.h>
33 #include <memory>
34 #include <openssl/aes.h>
35 #include <random>
36 
37 #include "VtsHalHidlTargetTestBase.h"
38 #include "VtsHalHidlTargetTestEnvBase.h"
39 
40 namespace drm = ::android::hardware::drm;
41 using ::android::hardware::drm::V1_0::BufferType;
42 using ::android::hardware::drm::V1_0::DestinationBuffer;
43 using ::android::hardware::drm::V1_0::ICryptoPlugin;
44 using ::android::hardware::drm::V1_0::KeyedVector;
45 using ::android::hardware::drm::V1_0::KeyValue;
46 using ::android::hardware::drm::V1_0::KeyType;
47 using ::android::hardware::drm::V1_0::Mode;
48 using ::android::hardware::drm::V1_0::Pattern;
49 using ::android::hardware::drm::V1_0::SecureStop;
50 using ::android::hardware::drm::V1_0::SecureStopId;
51 using ::android::hardware::drm::V1_0::SessionId;
52 using ::android::hardware::drm::V1_0::SharedBuffer;
53 using ::android::hardware::drm::V1_0::Status;
54 using ::android::hardware::drm::V1_0::SubSample;
55 using ::android::hardware::drm::V1_0::SubSample;
56 
57 using ::android::hardware::drm::V1_1::DrmMetricGroup;
58 using ::android::hardware::drm::V1_1::HdcpLevel;
59 using ::android::hardware::drm::V1_1::ICryptoFactory;
60 using ::android::hardware::drm::V1_1::IDrmFactory;
61 using ::android::hardware::drm::V1_1::IDrmPlugin;
62 using ::android::hardware::drm::V1_1::KeyRequestType;
63 using ::android::hardware::drm::V1_1::SecureStopRelease;
64 using ::android::hardware::drm::V1_1::SecurityLevel;
65 using ::android::hardware::drm::V1_1::SecurityLevel;
66 
67 using ::android::hardware::hidl_array;
68 using ::android::hardware::hidl_string;
69 using ::android::hardware::hidl_memory;
70 using ::android::hardware::hidl_vec;
71 using ::android::hardware::Return;
72 using ::android::hidl::allocator::V1_0::IAllocator;
73 using ::android::hidl::memory::V1_0::IMemory;
74 using ::android::sp;
75 
76 using std::string;
77 using std::unique_ptr;
78 using std::random_device;
79 using std::map;
80 using std::mt19937;
81 using std::vector;
82 
83 /**
84  * These clearkey tests use white box knowledge of the legacy clearkey
85  * plugin to verify that the HIDL HAL services and interfaces are working.
86  * It is not intended to verify any vendor's HAL implementation. If you
87  * are looking for vendor HAL tests, see drm_hal_vendor_test.cpp
88  */
89 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
90 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
91 
92 // To be used in mpd to specify drm scheme for players
93 static const uint8_t kClearKeyUUID[16] = {
94     0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
95     0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
96 
97 // Test environment for drm
98 class DrmHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
99    public:
100     // get the test environment singleton
Instance()101     static DrmHidlEnvironment* Instance() {
102         static DrmHidlEnvironment* instance = new DrmHidlEnvironment;
103         return instance;
104     }
105 
HidlSetUp()106     virtual void HidlSetUp() override { ALOGI("SetUp DrmHidlEnvironment"); }
107 
HidlTearDown()108     virtual void HidlTearDown() override { ALOGI("TearDown DrmHidlEnvironment"); }
109 
registerTestServices()110     void registerTestServices() override {
111         registerTestService<ICryptoFactory>();
112         registerTestService<IDrmFactory>();
113         setServiceCombMode(::testing::HalServiceCombMode::NO_COMBINATION);
114     }
115 
116    private:
DrmHidlEnvironment()117     DrmHidlEnvironment() {}
118 
119     GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment);
120 };
121 
122 
123 class DrmHalClearkeyTest : public ::testing::VtsHalHidlTargetTestBase {
124 public:
SetUp()125     virtual void SetUp() override {
126         const ::testing::TestInfo* const test_info =
127                 ::testing::UnitTest::GetInstance()->current_test_info();
128 
129         ALOGD("DrmHalClearkeyTest: Running test %s.%s", test_info->test_case_name(),
130                 test_info->name());
131 
132         auto manager = android::hardware::defaultServiceManager();
133         ASSERT_NE(nullptr, manager.get());
134         manager->listByInterface(IDrmFactory::descriptor,
135                 [&](const hidl_vec<hidl_string> &registered) {
136                     for (const auto &instance : registered) {
137                         sp<IDrmFactory> drmFactory =
138                                 ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(instance);
139                         drmPlugin = createDrmPlugin(drmFactory);
140                         if (drmPlugin != nullptr) {
141                             break;
142                         }
143                     }
144                 }
145             );
146 
147         manager->listByInterface(ICryptoFactory::descriptor,
148                 [&](const hidl_vec<hidl_string> &registered) {
149                     for (const auto &instance : registered) {
150                         sp<ICryptoFactory> cryptoFactory =
151                                 ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(instance);
152                         cryptoPlugin = createCryptoPlugin(cryptoFactory);
153                         if (cryptoPlugin != nullptr) {
154                             break;
155                         }
156                     }
157                 }
158             );
159 
160         ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find clearkey drm@1.1 plugin";
161         ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find clearkey crypto@1.1 plugin";
162     }
163 
164 
TearDown()165     virtual void TearDown() override {}
166 
167     SessionId openSession();
168     SessionId openSession(SecurityLevel level);
169     void closeSession(const SessionId& sessionId);
170     hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
171 
172   private:
createDrmPlugin(sp<IDrmFactory> drmFactory)173     sp<IDrmPlugin> createDrmPlugin(sp<IDrmFactory> drmFactory) {
174         if (drmFactory == nullptr) {
175             return nullptr;
176         }
177         sp<IDrmPlugin> plugin = nullptr;
178         auto res = drmFactory->createPlugin(
179                 kClearKeyUUID, "",
180                         [&](Status status, const sp<drm::V1_0::IDrmPlugin>& pluginV1_0) {
181                     EXPECT_EQ(Status::OK, status);
182                     plugin = IDrmPlugin::castFrom(pluginV1_0);
183                 });
184 
185         if (!res.isOk()) {
186             ALOGE("createDrmPlugin remote call failed");
187         }
188         return plugin;
189     }
190 
createCryptoPlugin(sp<ICryptoFactory> cryptoFactory)191     sp<ICryptoPlugin> createCryptoPlugin(sp<ICryptoFactory> cryptoFactory) {
192         if (cryptoFactory == nullptr) {
193             return nullptr;
194         }
195         sp<ICryptoPlugin> plugin = nullptr;
196         hidl_vec<uint8_t> initVec;
197         auto res = cryptoFactory->createPlugin(
198                 kClearKeyUUID, initVec,
199                         [&](Status status, const sp<drm::V1_0::ICryptoPlugin>& pluginV1_0) {
200                     EXPECT_EQ(Status::OK, status);
201                     plugin = pluginV1_0;
202                 });
203         if (!res.isOk()) {
204             ALOGE("createCryptoPlugin remote call failed");
205         }
206         return plugin;
207     }
208 
209 protected:
210  template <typename CT>
ValueEquals(DrmMetricGroup::ValueType type,const std::string & expected,const CT & actual)211  bool ValueEquals(DrmMetricGroup::ValueType type, const std::string& expected, const CT& actual) {
212      return type == DrmMetricGroup::ValueType::STRING_TYPE && expected == actual.stringValue;
213  }
214 
215  template <typename CT>
ValueEquals(DrmMetricGroup::ValueType type,const int64_t expected,const CT & actual)216  bool ValueEquals(DrmMetricGroup::ValueType type, const int64_t expected, const CT& actual) {
217      return type == DrmMetricGroup::ValueType::INT64_TYPE && expected == actual.int64Value;
218  }
219 
220  template <typename CT>
ValueEquals(DrmMetricGroup::ValueType type,const double expected,const CT & actual)221  bool ValueEquals(DrmMetricGroup::ValueType type, const double expected, const CT& actual) {
222      return type == DrmMetricGroup::ValueType::DOUBLE_TYPE && expected == actual.doubleValue;
223  }
224 
225  template <typename AT, typename VT>
ValidateMetricAttributeAndValue(const DrmMetricGroup::Metric & metric,const std::string & attributeName,const AT & attributeValue,const std::string & componentName,const VT & componentValue)226  bool ValidateMetricAttributeAndValue(const DrmMetricGroup::Metric& metric,
227                                       const std::string& attributeName, const AT& attributeValue,
228                                       const std::string& componentName, const VT& componentValue) {
229      bool validAttribute = false;
230      bool validComponent = false;
231      for (const DrmMetricGroup::Attribute& attribute : metric.attributes) {
232          if (attribute.name == attributeName &&
233              ValueEquals(attribute.type, attributeValue, attribute)) {
234              validAttribute = true;
235          }
236      }
237      for (const DrmMetricGroup::Value& value : metric.values) {
238          if (value.componentName == componentName &&
239              ValueEquals(value.type, componentValue, value)) {
240              validComponent = true;
241          }
242      }
243      return validAttribute && validComponent;
244  }
245 
246  template <typename AT, typename VT>
ValidateMetricAttributeAndValue(const hidl_vec<DrmMetricGroup> & metricGroups,const std::string & metricName,const std::string & attributeName,const AT & attributeValue,const std::string & componentName,const VT & componentValue)247  bool ValidateMetricAttributeAndValue(const hidl_vec<DrmMetricGroup>& metricGroups,
248                                       const std::string& metricName,
249                                       const std::string& attributeName, const AT& attributeValue,
250                                       const std::string& componentName, const VT& componentValue) {
251      bool foundMetric = false;
252      for (const auto& group : metricGroups) {
253          for (const auto& metric : group.metrics) {
254              if (metric.name == metricName) {
255                  foundMetric = foundMetric || ValidateMetricAttributeAndValue(
256                                                   metric, attributeName, attributeValue,
257                                                   componentName, componentValue);
258              }
259          }
260      }
261      return foundMetric;
262  }
263 
264  sp<IDrmPlugin> drmPlugin;
265  sp<ICryptoPlugin> cryptoPlugin;
266 };
267 
268 
269 /**
270  * Helper method to open a session and verify that a non-empty
271  * session ID is returned
272  */
openSession()273 SessionId DrmHalClearkeyTest::openSession() {
274     SessionId sessionId;
275 
276     auto res = drmPlugin->openSession(
277             [&sessionId](Status status, const SessionId& id) {
278                 EXPECT_EQ(Status::OK, status);
279                 EXPECT_NE(0u, id.size());
280                 sessionId = id;
281             });
282     EXPECT_OK(res);
283     return sessionId;
284 }
285 
286 /**
287  * Helper method to open as session using V1.1 API
288  */
openSession(SecurityLevel level)289 SessionId DrmHalClearkeyTest::openSession(SecurityLevel level) {
290     SessionId sessionId;
291 
292     auto res = drmPlugin->openSession_1_1(level,
293             [&sessionId](Status status, const SessionId& id) {
294                 EXPECT_EQ(Status::OK, status);
295                 EXPECT_NE(0u, id.size());
296                 sessionId = id;
297             });
298     EXPECT_OK(res);
299     return sessionId;
300 }
301 
302 
303 /**
304  * Helper method to close a session
305  */
closeSession(const SessionId & sessionId)306 void DrmHalClearkeyTest::closeSession(const SessionId& sessionId) {
307     EXPECT_TRUE(drmPlugin->closeSession(sessionId).isOk());
308 }
309 
310 /**
311  * Helper method to load keys for subsequent decrypt tests.
312  * These tests use predetermined key request/response to
313  * avoid requiring a round trip to a license server.
314  */
loadKeys(const SessionId & sessionId,const KeyType & type=KeyType::STREAMING)315 hidl_vec<uint8_t> DrmHalClearkeyTest::loadKeys(
316     const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
317     hidl_vec<uint8_t> initData = {
318         // BMFF box header (4 bytes size + 'pssh')
319         0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
320         // full box header (version = 1 flags = 0)
321         0x01, 0x00, 0x00, 0x00,
322         // system id
323         0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
324         0x1e, 0x52, 0xe2, 0xfb, 0x4b,
325         // number of key ids
326         0x00, 0x00, 0x00, 0x01,
327         // key id
328         0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
329         0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
330         // size of data, must be zero
331         0x00, 0x00, 0x00, 0x00};
332 
333     hidl_vec<uint8_t> expectedKeyRequest = {
334         0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65,
335         0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74,
336         0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a,
337         0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
338 
339     hidl_vec<uint8_t> knownKeyResponse = {
340         0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22,
341         0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59,
342         0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e,
343         0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f,
344         0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65,
345         0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
346 
347     hidl_string mimeType = "video/mp4";
348     KeyedVector optionalParameters;
349     auto res = drmPlugin->getKeyRequest_1_1(
350         sessionId, initData, mimeType, type, optionalParameters,
351         [&](Status status, const hidl_vec<uint8_t>& request,
352             KeyRequestType requestType, const hidl_string&) {
353             EXPECT_EQ(Status::OK, status);
354             EXPECT_EQ(KeyRequestType::INITIAL, requestType);
355             EXPECT_EQ(request, expectedKeyRequest);
356         });
357     EXPECT_OK(res);
358 
359     hidl_vec<uint8_t> keySetId;
360     res = drmPlugin->provideKeyResponse(
361         sessionId, knownKeyResponse,
362         [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
363             EXPECT_EQ(Status::OK, status);
364             EXPECT_EQ(0u, myKeySetId.size());
365             keySetId = myKeySetId;
366         });
367     EXPECT_OK(res);
368     return keySetId;
369 }
370 
371 /**
372  * Test openSession negative case: security level higher than supported
373  */
TEST_F(DrmHalClearkeyTest,OpenSessionBadLevel)374 TEST_F(DrmHalClearkeyTest, OpenSessionBadLevel) {
375     auto res = drmPlugin->openSession_1_1(SecurityLevel::HW_SECURE_ALL,
376             [&](Status status, const SessionId& /* id */) {
377                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
378             });
379     EXPECT_OK(res);
380 }
381 
382 /**
383  * Test getKeyRequest_1_1 via loadKeys
384  */
TEST_F(DrmHalClearkeyTest,GetKeyRequest)385 TEST_F(DrmHalClearkeyTest, GetKeyRequest) {
386     auto sessionId = openSession();
387     loadKeys(sessionId);
388     closeSession(sessionId);
389 }
390 
391 /**
392  * A get key request should fail if no sessionId is provided
393  */
TEST_F(DrmHalClearkeyTest,GetKeyRequestNoSession)394 TEST_F(DrmHalClearkeyTest, GetKeyRequestNoSession) {
395     SessionId invalidSessionId;
396     hidl_vec<uint8_t> initData;
397     hidl_string mimeType = "video/mp4";
398     KeyedVector optionalParameters;
399     auto res = drmPlugin->getKeyRequest_1_1(
400             invalidSessionId, initData, mimeType, KeyType::STREAMING,
401             optionalParameters,
402             [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
403                 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
404     EXPECT_OK(res);
405 }
406 
407 /**
408  * The clearkey plugin doesn't support offline key requests.
409  * Test that the plugin returns the expected error code in
410  * this case.
411  */
TEST_F(DrmHalClearkeyTest,GetKeyRequestOfflineKeyTypeNotSupported)412 TEST_F(DrmHalClearkeyTest, GetKeyRequestOfflineKeyTypeNotSupported) {
413     auto sessionId = openSession();
414     hidl_vec<uint8_t> initData;
415     hidl_string mimeType = "video/mp4";
416     KeyedVector optionalParameters;
417 
418     auto res = drmPlugin->getKeyRequest_1_1(
419             sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters,
420             [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
421                 const hidl_string&) {
422                 // Clearkey plugin doesn't support offline key type
423                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
424             });
425     EXPECT_OK(res);
426     closeSession(sessionId);
427 }
428 
429 /**
430  * Test that the plugin returns valid connected and max HDCP levels
431  */
TEST_F(DrmHalClearkeyTest,GetHdcpLevels)432 TEST_F(DrmHalClearkeyTest, GetHdcpLevels) {
433     auto res = drmPlugin->getHdcpLevels(
434             [&](Status status, const HdcpLevel &connectedLevel,
435                 const HdcpLevel &maxLevel) {
436                 EXPECT_EQ(Status::OK, status);
437                 EXPECT_GE(connectedLevel, HdcpLevel::HDCP_NONE);
438                 EXPECT_LE(maxLevel, HdcpLevel::HDCP_NO_OUTPUT);
439             });
440     EXPECT_OK(res);
441 }
442 
443 /**
444  * Since getHdcpLevels only queries information there are no
445  * negative cases.
446  */
447 
448 /**
449  * Test that the plugin returns default open and max session counts
450  */
TEST_F(DrmHalClearkeyTest,GetDefaultSessionCounts)451 TEST_F(DrmHalClearkeyTest, GetDefaultSessionCounts) {
452     auto res = drmPlugin->getNumberOfSessions(
453             [&](Status status, uint32_t currentSessions,
454                     uint32_t maxSessions) {
455                 EXPECT_EQ(Status::OK, status);
456                 EXPECT_GE(maxSessions, (uint32_t)8);
457                 EXPECT_GE(currentSessions, (uint32_t)0);
458                 EXPECT_LE(currentSessions, maxSessions);
459             });
460     EXPECT_OK(res);
461 }
462 
463 /**
464  * Test that the plugin returns valid open and max session counts
465  * after a session is opened.
466  */
TEST_F(DrmHalClearkeyTest,GetOpenSessionCounts)467 TEST_F(DrmHalClearkeyTest, GetOpenSessionCounts) {
468     uint32_t initialSessions = 0;
469     auto res = drmPlugin->getNumberOfSessions(
470             [&](Status status, uint32_t currentSessions,
471                     uint32_t maxSessions) {
472                 EXPECT_EQ(Status::OK, status);
473                 EXPECT_GE(maxSessions, (uint32_t)8);
474                 EXPECT_GE(currentSessions, (uint32_t)0);
475                 EXPECT_LE(currentSessions, maxSessions);
476                 initialSessions = currentSessions;
477             });
478     EXPECT_OK(res);
479 
480     SessionId session = openSession();
481     res = drmPlugin->getNumberOfSessions(
482             [&](Status status, uint32_t currentSessions,
483                     uint32_t /*maxSessions*/) {
484                 EXPECT_EQ(Status::OK, status);
485                 EXPECT_EQ(currentSessions, initialSessions + 1);
486             });
487     EXPECT_OK(res);
488 
489     closeSession(session);
490     res = drmPlugin->getNumberOfSessions(
491             [&](Status status, uint32_t currentSessions,
492                     uint32_t /*maxSessions*/) {
493                 EXPECT_EQ(Status::OK, status);
494                 EXPECT_EQ(currentSessions, initialSessions);
495             });
496     EXPECT_OK(res);
497 }
498 
499 /**
500  * Since getNumberOfSessions only queries information there are no
501  * negative cases.
502  */
503 
504 /**
505  * Test that the plugin returns the same security level
506  * by default as when it is requested explicitly
507  */
TEST_F(DrmHalClearkeyTest,GetDefaultSecurityLevel)508 TEST_F(DrmHalClearkeyTest, GetDefaultSecurityLevel) {
509     SessionId session = openSession();
510     SecurityLevel defaultLevel;
511     auto res = drmPlugin->getSecurityLevel(session,
512             [&](Status status, SecurityLevel level) {
513                 EXPECT_EQ(Status::OK, status);
514                 defaultLevel = level;
515             });
516     EXPECT_OK(res);
517     closeSession(session);
518 
519     session = openSession(defaultLevel);
520     res = drmPlugin->getSecurityLevel(session,
521             [&](Status status, SecurityLevel level) {
522                 EXPECT_EQ(Status::OK, status);
523                 EXPECT_EQ(level, defaultLevel);
524             });
525     EXPECT_OK(res);
526     closeSession(session);
527 }
528 
529 /**
530  * Test that the plugin returns the lowest security level
531  * when it is requested
532  */
TEST_F(DrmHalClearkeyTest,GetSecurityLevel)533 TEST_F(DrmHalClearkeyTest, GetSecurityLevel) {
534     SessionId session = openSession(SecurityLevel::SW_SECURE_CRYPTO);
535     auto res = drmPlugin->getSecurityLevel(session,
536             [&](Status status, SecurityLevel level) {
537                 EXPECT_EQ(Status::OK, status);
538                 EXPECT_EQ(level, SecurityLevel::SW_SECURE_CRYPTO);
539             });
540     EXPECT_OK(res);
541     closeSession(session);
542 }
543 
544 /**
545  * Test that the plugin returns the documented error
546  * when requesting the security level for an invalid sessionId
547  */
TEST_F(DrmHalClearkeyTest,GetSecurityLevelInvalidSessionId)548 TEST_F(DrmHalClearkeyTest, GetSecurityLevelInvalidSessionId) {
549     SessionId session;
550     auto res = drmPlugin->getSecurityLevel(session,
551             [&](Status status, SecurityLevel /*level*/) {
552                 EXPECT_EQ(Status::BAD_VALUE, status);
553             });
554     EXPECT_OK(res);
555 }
556 
557 /**
558  * Test metrics are set appropriately for open and close operations.
559  */
TEST_F(DrmHalClearkeyTest,GetMetricsOpenClose)560 TEST_F(DrmHalClearkeyTest, GetMetricsOpenClose) {
561     SessionId sessionId = openSession();
562     // The first close should be successful.
563     closeSession(sessionId);
564     // The second close should fail (not opened).
565     EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, drmPlugin->closeSession(sessionId));
566 
567     auto res = drmPlugin->getMetrics([this](Status status, hidl_vec<DrmMetricGroup> metricGroups) {
568         EXPECT_EQ(Status::OK, status);
569 
570         // Verify the open_session metric.
571         EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "open_session", "status",
572                                                     (int64_t)0, "count", (int64_t)1));
573         // Verify the close_session - success metric.
574         EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
575                                                     (int64_t)0, "count", (int64_t)1));
576         // Verify the close_session - error metric.
577         EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
578                                                     (int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
579                                                     "count", (int64_t)1));
580     });
581     EXPECT_OK(res);
582 }
583 
584 /**
585  * Since getMetrics only queries information there are no
586  * negative cases.
587  */
588 
589 /**
590  * Test that there are no secure stop ids after clearing them
591  */
TEST_F(DrmHalClearkeyTest,GetSecureStopIdsCleared)592 TEST_F(DrmHalClearkeyTest, GetSecureStopIdsCleared) {
593     auto stat = drmPlugin->removeAllSecureStops();
594     EXPECT_OK(stat);
595 
596     bool ok = drmPlugin->getSecureStopIds(
597             [&](Status status, const hidl_vec<SecureStopId>& ids) {
598                 EXPECT_EQ(Status::OK, status);
599                 EXPECT_EQ(0u, ids.size());
600             }).isOk();
601     EXPECT_TRUE(ok);
602 }
603 
604 /**
605  * Test that there are secure stop ids after loading keys once
606  */
TEST_F(DrmHalClearkeyTest,GetSecureStopIdsOnce)607 TEST_F(DrmHalClearkeyTest, GetSecureStopIdsOnce) {
608     auto stat = drmPlugin->removeAllSecureStops();
609     EXPECT_OK(stat);
610 
611     auto sessionId = openSession();
612     loadKeys(sessionId);
613     closeSession(sessionId);
614 
615     auto res = drmPlugin->getSecureStopIds(
616             [&](Status status, const hidl_vec<SecureStopId>& ids) {
617                 EXPECT_EQ(Status::OK, status);
618                 EXPECT_EQ(1u, ids.size());
619             });
620     EXPECT_OK(res);
621 
622     stat = drmPlugin->removeAllSecureStops();
623     EXPECT_OK(stat);
624 
625     res = drmPlugin->getSecureStopIds(
626             [&](Status status, const hidl_vec<SecureStopId>& ids) {
627                 EXPECT_EQ(Status::OK, status);
628                 EXPECT_EQ(0u, ids.size());
629             });
630     EXPECT_OK(res);
631 }
632 
633 /**
634  * Since getSecureStopIds only queries information there are no
635  * negative cases.
636  */
637 
638 /**
639  * Test that the clearkey plugin reports no secure stops when
640  * there are none.
641  */
TEST_F(DrmHalClearkeyTest,GetNoSecureStops)642 TEST_F(DrmHalClearkeyTest, GetNoSecureStops) {
643     auto stat = drmPlugin->removeAllSecureStops();
644     EXPECT_OK(stat);
645 
646     auto res = drmPlugin->getSecureStops(
647             [&](Status status, const hidl_vec<SecureStop>& stops) {
648                 EXPECT_EQ(Status::OK, status);
649                 EXPECT_EQ(0u, stops.size());
650             });
651     EXPECT_OK(res);
652 }
653 
654 /**
655  * Test get/remove of one secure stop
656  */
TEST_F(DrmHalClearkeyTest,GetOneSecureStopAndRemoveIt)657 TEST_F(DrmHalClearkeyTest, GetOneSecureStopAndRemoveIt) {
658     auto stat = drmPlugin->removeAllSecureStops();
659     EXPECT_OK(stat);
660 
661     auto sessionId = openSession();
662     loadKeys(sessionId);
663     closeSession(sessionId);
664 
665     auto res = drmPlugin->getSecureStops(
666             [&](Status status, const hidl_vec<SecureStop>& stops) {
667                 EXPECT_EQ(Status::OK, status);
668                 EXPECT_EQ(1u, stops.size());
669             });
670     EXPECT_OK(res);
671 
672     stat = drmPlugin->removeAllSecureStops();
673     EXPECT_OK(stat);
674 
675     res = drmPlugin->getSecureStops(
676             [&](Status status, const hidl_vec<SecureStop>& stops) {
677                 EXPECT_EQ(Status::OK, status);
678                 EXPECT_EQ(0u, stops.size());
679             });
680     EXPECT_OK(res);
681 }
682 
683 /**
684  * Since getSecureStops only queries information there are no
685  * negative cases.
686  */
687 
688 /**
689  * Test that there are no secure stops after clearing them
690  */
TEST_F(DrmHalClearkeyTest,GetSecureStopsCleared)691 TEST_F(DrmHalClearkeyTest, GetSecureStopsCleared) {
692     auto stat = drmPlugin->removeAllSecureStops();
693     EXPECT_OK(stat);
694 
695     auto res = drmPlugin->getSecureStops(
696             [&](Status status, const hidl_vec<SecureStop>& stops) {
697                 EXPECT_EQ(Status::OK, status);
698                 EXPECT_EQ(0u, stops.size());
699             });
700     EXPECT_OK(res);
701 }
702 
703 /**
704  * Test that there are secure stops after loading keys once
705  */
TEST_F(DrmHalClearkeyTest,GetSecureStopsOnce)706 TEST_F(DrmHalClearkeyTest, GetSecureStopsOnce) {
707     auto stat = drmPlugin->removeAllSecureStops();
708     EXPECT_OK(stat);
709 
710     auto sessionId = openSession();
711     loadKeys(sessionId);
712     closeSession(sessionId);
713 
714     auto res = drmPlugin->getSecureStops(
715             [&](Status status, const hidl_vec<SecureStop>& stops) {
716                 EXPECT_EQ(Status::OK, status);
717                 EXPECT_EQ(1u, stops.size());
718             });
719     EXPECT_OK(res);
720 
721     stat = drmPlugin->removeAllSecureStops();
722     EXPECT_OK(stat);
723 
724     res = drmPlugin->getSecureStops(
725             [&](Status status, const hidl_vec<SecureStop>& stops) {
726                 EXPECT_EQ(Status::OK, status);
727                 EXPECT_EQ(0u, stops.size());
728             });
729     EXPECT_OK(res);
730 }
731 
732 /**
733  * Since getSecureStops only queries information there are no
734  * negative cases.
735  */
736 
737 /**
738  * Test that releasing a secure stop with empty
739  * release message fails with the documented error
740  */
TEST_F(DrmHalClearkeyTest,ReleaseEmptySecureStop)741 TEST_F(DrmHalClearkeyTest, ReleaseEmptySecureStop) {
742     SecureStopRelease emptyRelease = {.opaqueData = hidl_vec<uint8_t>()};
743     Status status = drmPlugin->releaseSecureStops(emptyRelease);
744     EXPECT_EQ(Status::BAD_VALUE, status);
745 }
746 
747 /**
748  * Helper function to create a secure release message for
749  * a secure stop. The clearkey secure stop release format
750  * is just a count followed by the secure stop opaque data.
751  */
makeSecureRelease(const SecureStop & stop)752 SecureStopRelease makeSecureRelease(const SecureStop &stop) {
753     std::vector<uint8_t> stopData = stop.opaqueData;
754     std::vector<uint8_t> buffer;
755     std::string count = "0001";
756 
757     auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
758     buffer.insert(it + count.size(), stopData.begin(), stopData.end());
759     SecureStopRelease release = { .opaqueData = hidl_vec<uint8_t>(buffer) };
760     return release;
761 }
762 
763 /**
764  * Test that releasing one secure stop works
765  */
TEST_F(DrmHalClearkeyTest,ReleaseOneSecureStop)766 TEST_F(DrmHalClearkeyTest, ReleaseOneSecureStop) {
767 
768     auto stat = drmPlugin->removeAllSecureStops();
769     EXPECT_OK(stat);
770 
771     auto sessionId = openSession();
772     loadKeys(sessionId);
773     closeSession(sessionId);
774 
775     SecureStopRelease release;
776     auto res = drmPlugin->getSecureStops(
777             [&](Status status, const hidl_vec<SecureStop>& stops) {
778                 EXPECT_EQ(Status::OK, status);
779                 EXPECT_EQ(1u, stops.size());
780                 release = makeSecureRelease(stops[0]);
781             });
782     EXPECT_OK(res);
783 
784     stat = drmPlugin->releaseSecureStops(release);
785     EXPECT_OK(stat);
786 
787     res = drmPlugin->getSecureStops(
788             [&](Status status, const hidl_vec<SecureStop>& stops) {
789                 EXPECT_EQ(Status::OK, status);
790                 EXPECT_EQ(0u, stops.size());
791             });
792     EXPECT_OK(res);
793 }
794 
795 
796 /**
797  * Test that removing a secure stop with an empty ID returns
798  * documented error
799  */
TEST_F(DrmHalClearkeyTest,RemoveEmptySecureStopId)800 TEST_F(DrmHalClearkeyTest, RemoveEmptySecureStopId) {
801     hidl_vec<uint8_t> emptyId;
802     auto stat = drmPlugin->removeSecureStop(emptyId);
803     EXPECT_OK(stat);
804     EXPECT_EQ(Status::BAD_VALUE, stat);
805 }
806 
807 /**
808  * Test that removing a secure stop after it has already
809  * been removed fails with the documented error code.
810  */
TEST_F(DrmHalClearkeyTest,RemoveRemovedSecureStopId)811 TEST_F(DrmHalClearkeyTest, RemoveRemovedSecureStopId) {
812     auto stat = drmPlugin->removeAllSecureStops();
813     EXPECT_OK(stat);
814 
815     auto sessionId = openSession();
816     loadKeys(sessionId);
817     closeSession(sessionId);
818     SecureStopId ssid;
819 
820     auto res = drmPlugin->getSecureStopIds(
821             [&](Status status, const hidl_vec<SecureStopId>& ids) {
822                 EXPECT_EQ(Status::OK, status);
823                 EXPECT_EQ(1u, ids.size());
824                 ssid = ids[0];
825             });
826     EXPECT_OK(res);
827 
828     stat = drmPlugin->removeAllSecureStops();
829     EXPECT_OK(stat);
830 
831     Status status = drmPlugin->removeSecureStop(ssid);
832     EXPECT_EQ(Status::BAD_VALUE, status);
833 }
834 
835 /**
836  * Test that removing a secure stop by id works
837  */
TEST_F(DrmHalClearkeyTest,RemoveSecureStopById)838 TEST_F(DrmHalClearkeyTest, RemoveSecureStopById) {
839     auto stat = drmPlugin->removeAllSecureStops();
840     EXPECT_OK(stat);
841 
842     auto sessionId = openSession();
843     loadKeys(sessionId);
844     closeSession(sessionId);
845     SecureStopId ssid;
846 
847     auto res = drmPlugin->getSecureStopIds(
848             [&](Status status, const hidl_vec<SecureStopId>& ids) {
849                 EXPECT_EQ(Status::OK, status);
850                 EXPECT_EQ(1u, ids.size());
851                 ssid = ids[0];
852             });
853     EXPECT_OK(res);
854 
855     stat = drmPlugin->removeSecureStop(ssid);
856     EXPECT_OK(stat);
857 
858     res = drmPlugin->getSecureStopIds(
859             [&](Status status, const hidl_vec<SecureStopId>& ids) {
860                 EXPECT_EQ(Status::OK, status);
861                 EXPECT_EQ(0u, ids.size());
862             });
863     EXPECT_OK(res);
864 }
865 
866 
main(int argc,char ** argv)867 int main(int argc, char** argv) {
868     ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
869     ::testing::InitGoogleTest(&argc, argv);
870     DrmHidlEnvironment::Instance()->init(&argc, argv);
871     int status = RUN_ALL_TESTS();
872     ALOGI("Test result = %d", status);
873     return status;
874 }
875