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 "VtsHalUsbV1_0TargetTest"
     18 #include <android-base/logging.h>
     19 
     20 #include <android/hardware/usb/1.0/IUsb.h>
     21 #include <android/hardware/usb/1.0/IUsbCallback.h>
     22 #include <android/hardware/usb/1.0/types.h>
     23 
     24 #include <VtsHalHidlTargetTestBase.h>
     25 #include <log/log.h>
     26 #include <stdlib.h>
     27 #include <chrono>
     28 #include <condition_variable>
     29 #include <mutex>
     30 
     31 #define TIMEOUT_PERIOD 10
     32 
     33 using ::android::hardware::usb::V1_0::IUsbCallback;
     34 using ::android::hardware::usb::V1_0::IUsb;
     35 using ::android::hardware::usb::V1_0::PortDataRole;
     36 using ::android::hardware::usb::V1_0::PortMode;
     37 using ::android::hardware::usb::V1_0::PortPowerRole;
     38 using ::android::hardware::usb::V1_0::PortRole;
     39 using ::android::hardware::usb::V1_0::PortRoleType;
     40 using ::android::hardware::usb::V1_0::PortStatus;
     41 using ::android::hardware::usb::V1_0::Status;
     42 using ::android::hidl::base::V1_0::IBase;
     43 using ::android::hardware::hidl_array;
     44 using ::android::hardware::hidl_memory;
     45 using ::android::hardware::hidl_string;
     46 using ::android::hardware::hidl_vec;
     47 using ::android::hardware::Return;
     48 using ::android::hardware::Void;
     49 using ::android::sp;
     50 
     51 // The main test class for the USB hidl HAL
     52 class UsbHidlTest : public ::testing::VtsHalHidlTargetTestBase {
     53  public:
     54   // Callback class for the USB HIDL hal.
     55   // Usb Hal will call this object upon role switch or port query.
     56   class UsbCallback : public IUsbCallback {
     57     UsbHidlTest& parent_;
     58     int cookie;
     59 
     60    public:
     61     UsbCallback(UsbHidlTest& parent, int cookie)
     62         : parent_(parent), cookie(cookie){};
     63 
     64     virtual ~UsbCallback() = default;
     65 
     66     // Callback method for the port status.
     67     Return<void> notifyPortStatusChange(
     68         const hidl_vec<PortStatus>& currentPortStatus, Status retval) override {
     69       if (retval == Status::SUCCESS) {
     70         parent_.usb_last_port_status.portName =
     71             currentPortStatus[0].portName.c_str();
     72         parent_.usb_last_port_status.currentDataRole =
     73             currentPortStatus[0].currentDataRole;
     74         parent_.usb_last_port_status.currentPowerRole =
     75             currentPortStatus[0].currentPowerRole;
     76         parent_.usb_last_port_status.currentMode =
     77             currentPortStatus[0].currentMode;
     78       }
     79       parent_.usb_last_cookie = cookie;
     80       parent_.notify();
     81       return Void();
     82     };
     83 
     84     // Callback method for the status of role switch operation.
     85     Return<void> notifyRoleSwitchStatus(const hidl_string& /*portName*/,
     86                                         const PortRole& newRole,
     87                                         Status retval) override {
     88       parent_.usb_last_status = retval;
     89       parent_.usb_last_cookie = cookie;
     90       parent_.usb_last_port_role = newRole;
     91       parent_.usb_role_switch_done = true;
     92       parent_.notify();
     93       return Void();
     94     };
     95   };
     96 
     97   virtual void SetUp() override {
     98     ALOGI("Setup");
     99     usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>();
    100     ASSERT_NE(usb, nullptr);
    101 
    102     usb_cb_2 = new UsbCallback(*this, 2);
    103     ASSERT_NE(usb_cb_2, nullptr);
    104     Return<void> ret = usb->setCallback(usb_cb_2);
    105     ASSERT_TRUE(ret.isOk());
    106   }
    107 
    108   virtual void TearDown() override { ALOGI("Teardown"); }
    109 
    110   // Used as a mechanism to inform the test about data/event callback.
    111   inline void notify() {
    112     std::unique_lock<std::mutex> lock(usb_mtx);
    113     usb_count++;
    114     usb_cv.notify_one();
    115   }
    116 
    117   // Test code calls this function to wait for data/event callback.
    118   inline std::cv_status wait() {
    119     std::unique_lock<std::mutex> lock(usb_mtx);
    120 
    121     std::cv_status status = std::cv_status::no_timeout;
    122     auto now = std::chrono::system_clock::now();
    123     while (usb_count == 0) {
    124       status =
    125           usb_cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
    126       if (status == std::cv_status::timeout) {
    127         ALOGI("timeout");
    128         return status;
    129       }
    130     }
    131     usb_count--;
    132     return status;
    133   }
    134 
    135   // USB hidl hal Proxy
    136   sp<IUsb> usb;
    137 
    138   // Callback objects for usb hidl
    139   // Methods of these objects are called to notify port status updates.
    140   sp<IUsbCallback> usb_cb_1, usb_cb_2;
    141 
    142   // The last conveyed status of the USB ports.
    143   // Stores information of currentt_data_role, power_role for all the USB ports
    144   PortStatus usb_last_port_status;
    145 
    146   // Status of the last role switch operation.
    147   Status usb_last_status;
    148 
    149   // Port role information of the last role switch operation.
    150   PortRole usb_last_port_role;
    151 
    152   // Flag to indicate the invocation of role switch callback.
    153   bool usb_role_switch_done;
    154 
    155   // Identifier for the usb callback object.
    156   // Stores the cookie of the last invoked usb callback object.
    157   int usb_last_cookie;
    158 
    159   // synchronization primitives to coordinate between main test thread
    160   // and the callback thread.
    161   std::mutex usb_mtx;
    162   std::condition_variable usb_cv;
    163   int usb_count;
    164 };
    165 
    166 /*
    167  * Test to see if setCallback succeeds.
    168  * Callback oject is created and registered.
    169  * Check to see if the hidl transaction succeeded.
    170  */
    171 TEST_F(UsbHidlTest, setCallback) {
    172   usb_cb_1 = new UsbCallback(*this, 1);
    173   ASSERT_NE(usb_cb_1, nullptr);
    174   Return<void> ret = usb->setCallback(usb_cb_1);
    175   ASSERT_TRUE(ret.isOk());
    176 }
    177 
    178 /*
    179  * Check to see if querying type-c
    180  * port status succeeds.
    181  */
    182 TEST_F(UsbHidlTest, queryPortStatus) {
    183   Return<void> ret = usb->queryPortStatus();
    184   ASSERT_TRUE(ret.isOk());
    185   EXPECT_EQ(std::cv_status::no_timeout, wait());
    186   EXPECT_EQ(2, usb_last_cookie);
    187   ALOGI("rightafter: %s", usb_last_port_status.portName.c_str());
    188 }
    189 
    190 /*
    191  * Trying to switch a non-existent port should fail.
    192  * This test case tried to switch the port with empty
    193  * name which is expected to fail.
    194  */
    195 TEST_F(UsbHidlTest, switchEmptyPort) {
    196   struct PortRole role;
    197   role.type = PortRoleType::DATA_ROLE;
    198 
    199   Return<void> ret = usb->switchRole("", role);
    200   ASSERT_TRUE(ret.isOk());
    201   EXPECT_EQ(std::cv_status::no_timeout, wait());
    202   EXPECT_EQ(Status::ERROR, usb_last_status);
    203   EXPECT_EQ(2, usb_last_cookie);
    204 }
    205 
    206 /*
    207  * Test switching the mode of usb port.
    208  * Test case queries the usb ports present in device.
    209  * If there is atleast one usb port, a mode switch
    210  * to DFP is attempted for the port.
    211  * The callback parametes are checked to see if the mode
    212  * switch was successfull. Upon success, Status::SUCCESS
    213  * is expected to be returned.
    214  */
    215 TEST_F(UsbHidlTest, switchModetoDFP) {
    216   struct PortRole role;
    217   role.type = PortRoleType::MODE;
    218   role.role = static_cast<uint32_t>(PortMode::DFP);
    219 
    220   Return<void> ret = usb->queryPortStatus();
    221   ASSERT_TRUE(ret.isOk());
    222   EXPECT_EQ(std::cv_status::no_timeout, wait());
    223   EXPECT_EQ(2, usb_last_cookie);
    224 
    225   if (!usb_last_port_status.portName.empty()) {
    226     hidl_string portBeingSwitched = usb_last_port_status.portName;
    227     ALOGI("mode portname:%s", portBeingSwitched.c_str());
    228     usb_role_switch_done = false;
    229     Return<void> ret = usb->switchRole(portBeingSwitched.c_str(), role);
    230     ASSERT_TRUE(ret.isOk());
    231 
    232     std::cv_status waitStatus = wait();
    233     while (waitStatus == std::cv_status::no_timeout &&
    234            usb_role_switch_done == false)
    235       waitStatus = wait();
    236 
    237     EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
    238     EXPECT_EQ(2, usb_last_cookie);
    239 
    240     EXPECT_EQ(static_cast<uint32_t>(PortRoleType::MODE),
    241               static_cast<uint32_t>(usb_last_port_role.type));
    242     if (usb_last_status == Status::SUCCESS) {
    243       EXPECT_EQ(static_cast<uint32_t>(PortMode::DFP),
    244                 static_cast<uint32_t>(usb_last_port_role.role));
    245     } else {
    246       EXPECT_NE(static_cast<uint32_t>(PortMode::UFP),
    247                 static_cast<uint32_t>(usb_last_port_role.role));
    248     }
    249   }
    250 }
    251 
    252 /*
    253  * Test switching the power role of usb port.
    254  * Test case queries the usb ports present in device.
    255  * If there is atleast one usb port, a power role switch
    256  * to SOURCE is attempted for the port.
    257  * The callback parametes are checked to see if the power role
    258  * switch was successfull. Upon success, Status::SUCCESS
    259  * is expected to be returned.
    260  */
    261 
    262 TEST_F(UsbHidlTest, switchPowerRole) {
    263   struct PortRole role;
    264   role.type = PortRoleType::POWER_ROLE;
    265   role.role = static_cast<uint32_t>(PortPowerRole::SOURCE);
    266 
    267   Return<void> ret = usb->queryPortStatus();
    268   ASSERT_TRUE(ret.isOk());
    269   EXPECT_EQ(std::cv_status::no_timeout, wait());
    270   EXPECT_EQ(2, usb_last_cookie);
    271 
    272   if (!usb_last_port_status.portName.empty()) {
    273     hidl_string portBeingSwitched = usb_last_port_status.portName;
    274     ALOGI("switchPower role portname:%s", portBeingSwitched.c_str());
    275     usb_role_switch_done = false;
    276     Return<void> ret = usb->switchRole(portBeingSwitched.c_str(), role);
    277     ASSERT_TRUE(ret.isOk());
    278 
    279     std::cv_status waitStatus = wait();
    280     while (waitStatus == std::cv_status::no_timeout &&
    281            usb_role_switch_done == false)
    282       waitStatus = wait();
    283 
    284     EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
    285     EXPECT_EQ(2, usb_last_cookie);
    286 
    287     EXPECT_EQ(static_cast<uint32_t>(PortRoleType::POWER_ROLE),
    288               static_cast<uint32_t>(usb_last_port_role.type));
    289     if (usb_last_status == Status::SUCCESS) {
    290       EXPECT_EQ(static_cast<uint32_t>(PortPowerRole::SOURCE),
    291                 static_cast<uint32_t>(usb_last_port_role.role));
    292     } else {
    293       EXPECT_NE(static_cast<uint32_t>(PortPowerRole::SINK),
    294                 static_cast<uint32_t>(usb_last_port_role.role));
    295     }
    296   }
    297 }
    298 
    299 /*
    300  * Test switching the data role of usb port.
    301  * Test case queries the usb ports present in device.
    302  * If there is atleast one usb port, a power role switch
    303  * to HOST is attempted for the port.
    304  * The callback parametes are checked to see if the power role
    305  * switch was successfull. Upon success, Status::SUCCESS
    306  * is expected to be returned.
    307  */
    308 TEST_F(UsbHidlTest, switchDataRole) {
    309   struct PortRole role;
    310   role.type = PortRoleType::DATA_ROLE;
    311   role.role = static_cast<uint32_t>(PortDataRole::HOST);
    312 
    313   Return<void> ret = usb->queryPortStatus();
    314   ASSERT_TRUE(ret.isOk());
    315   EXPECT_EQ(std::cv_status::no_timeout, wait());
    316   EXPECT_EQ(2, usb_last_cookie);
    317 
    318   if (!usb_last_port_status.portName.empty()) {
    319     hidl_string portBeingSwitched = usb_last_port_status.portName;
    320     ALOGI("portname:%s", portBeingSwitched.c_str());
    321     usb_role_switch_done = false;
    322     Return<void> ret = usb->switchRole(portBeingSwitched.c_str(), role);
    323     ASSERT_TRUE(ret.isOk());
    324 
    325     std::cv_status waitStatus = wait();
    326     while (waitStatus == std::cv_status::no_timeout &&
    327            usb_role_switch_done == false)
    328       waitStatus = wait();
    329 
    330     EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
    331     EXPECT_EQ(2, usb_last_cookie);
    332 
    333     EXPECT_EQ(static_cast<uint32_t>(PortRoleType::DATA_ROLE),
    334               static_cast<uint32_t>(usb_last_port_role.type));
    335     if (usb_last_status == Status::SUCCESS) {
    336       EXPECT_EQ(static_cast<uint32_t>(PortDataRole::HOST),
    337                 static_cast<uint32_t>(usb_last_port_role.role));
    338     } else {
    339       EXPECT_NE(static_cast<uint32_t>(PortDataRole::DEVICE),
    340                 static_cast<uint32_t>(usb_last_port_role.role));
    341     }
    342   }
    343 }
    344 
    345 int main(int argc, char** argv) {
    346   ::testing::InitGoogleTest(&argc, argv);
    347   int status = RUN_ALL_TESTS();
    348   ALOGI("Test result = %d", status);
    349   return status;
    350 }
    351