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