Home | History | Annotate | Download | only in functional
      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 (at) 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
    101     static DrmHidlEnvironment* Instance() {
    102         static DrmHidlEnvironment* instance = new DrmHidlEnvironment;
    103         return instance;
    104     }
    105 
    106     virtual void HidlSetUp() override { ALOGI("SetUp DrmHidlEnvironment"); }
    107 
    108     virtual void HidlTearDown() override { ALOGI("TearDown DrmHidlEnvironment"); }
    109 
    110     void registerTestServices() override {
    111         registerTestService<ICryptoFactory>();
    112         registerTestService<IDrmFactory>();
    113         setServiceCombMode(::testing::HalServiceCombMode::NO_COMBINATION);
    114     }
    115 
    116    private:
    117     DrmHidlEnvironment() {}
    118 
    119     GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment);
    120 };
    121 
    122 
    123 class DrmHalClearkeyTest : public ::testing::VtsHalHidlTargetTestBase {
    124 public:
    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 (at) 1.1 plugin";
    161         ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find clearkey crypto (at) 1.1 plugin";
    162     }
    163 
    164 
    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:
    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 
    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>
    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>
    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>
    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>
    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 (DrmMetricGroup::Attribute attribute : metric.attributes) {
    232          if (attribute.name == attributeName &&
    233              ValueEquals(attribute.type, attributeValue, attribute)) {
    234              validAttribute = true;
    235          }
    236      }
    237      for (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>
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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