blob: ed3bd6e7db6e138b456045ba2886f7306b11c720 [file] [log] [blame]
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -08001/*
2 * Copyright (C) 2021 The Android Open Source Probject
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 "UsbAidlTest"
18#include <android-base/logging.h>
19
20#include <aidl/android/hardware/usb/IUsb.h>
21#include <aidl/android/hardware/usb/IUsbCallback.h>
22#include <aidl/android/hardware/usb/BnUsbCallback.h>
23#include <aidl/android/hardware/usb/PortDataRole.h>
24#include <aidl/android/hardware/usb/PortMode.h>
25#include <aidl/android/hardware/usb/PortPowerRole.h>
26#include <aidl/android/hardware/usb/PortRole.h>
27#include <aidl/android/hardware/usb/PortStatus.h>
28#include <aidl/android/hardware/usb/Status.h>
29#include <aidl/Vintf.h>
30#include <aidl/Gtest.h>
31
32#include <android/binder_auto_utils.h>
33#include <android/binder_manager.h>
34#include <android/binder_process.h>
35#include <gtest/gtest.h>
36
37#include <log/log.h>
38#include <stdlib.h>
39#include <chrono>
40#include <condition_variable>
41#include <mutex>
42
43#define TIMEOUT_PERIOD 10
44
45using ::aidl::android::hardware::usb::BnUsbCallback;
46using ::aidl::android::hardware::usb::IUsb;
47using ::aidl::android::hardware::usb::IUsbCallback;
48using ::aidl::android::hardware::usb::PortDataRole;
49using ::aidl::android::hardware::usb::PortMode;
50using ::aidl::android::hardware::usb::PortPowerRole;
51using ::aidl::android::hardware::usb::PortRole;
52using ::aidl::android::hardware::usb::PortStatus;
53using ::aidl::android::hardware::usb::Status;
54
55using ::ndk::ScopedAStatus;
56using ::ndk::SpAIBinder;
57using std::vector;
58using std::shared_ptr;
59using std::string;
60
61// The main test class for the USB aidl hal
62class UsbAidlTest : public testing::TestWithParam<std::string> {
63 public:
64 // Callback class for the USB aidl hal.
65 // Usb Hal will call this object upon role switch or port query.
66 class UsbCallback : public BnUsbCallback {
67 UsbAidlTest& parent_;
68 int cookie;
69
70 public:
71 UsbCallback(UsbAidlTest& parent, int cookie)
72 : parent_(parent), cookie(cookie){};
73
74 virtual ~UsbCallback() = default;
75
76 // Callback method for the port status.
77 ScopedAStatus notifyPortStatusChange(const vector<PortStatus>& currentPortStatus,
78 Status retval) override {
79 if (retval == Status::SUCCESS && currentPortStatus.size() > 0) {
80 parent_.usb_last_port_status.portName =
81 currentPortStatus[0].portName.c_str();
82 parent_.usb_last_port_status.currentDataRole =
83 currentPortStatus[0].currentDataRole;
84 parent_.usb_last_port_status.currentPowerRole =
85 currentPortStatus[0].currentPowerRole;
86 parent_.usb_last_port_status.currentMode =
87 currentPortStatus[0].currentMode;
88 }
89 parent_.usb_last_cookie = cookie;
90 return ScopedAStatus::ok();
91 }
92
93 // Callback method for the status of role switch operation.
94 ScopedAStatus notifyRoleSwitchStatus(const string& /*portName*/, const PortRole& newRole,
95 Status retval, int64_t transactionId) override {
96 parent_.usb_last_status = retval;
97 parent_.usb_last_cookie = cookie;
98 parent_.usb_last_port_role = newRole;
99 parent_.usb_role_switch_done = true;
100 parent_.last_transactionId = transactionId;
101 parent_.notify();
102 return ScopedAStatus::ok();
103 }
104
105 // Callback method for the status of enableUsbData operation
106 ScopedAStatus notifyEnableUsbDataStatus(const string& /*portName*/, bool /*enable*/,
107 Status /*retval*/, int64_t transactionId) override {
108 parent_.last_transactionId = transactionId;
109 parent_.usb_last_cookie = cookie;
110 parent_.enable_usb_data_done = true;
111 parent_.notify();
112 return ScopedAStatus::ok();
113 }
114
Badhri Jagan Sridharanf8832352022-01-23 09:17:04 -0800115 // Callback method for the status of enableUsbData operation
116 ScopedAStatus notifyEnableUsbDataWhileDockedStatus(const string& /*portName*/,
117 Status /*retval*/,
118 int64_t transactionId) override {
119 parent_.last_transactionId = transactionId;
120 parent_.usb_last_cookie = cookie;
121 parent_.enable_usb_data_while_docked_done = true;
122 parent_.notify();
123 return ScopedAStatus::ok();
124 }
125
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -0800126 // Callback method for the status of enableContaminantPresenceDetection
127 ScopedAStatus notifyContaminantEnabledStatus(const string& /*portName*/, bool /*enable*/,
128 Status /*retval*/, int64_t transactionId) override {
129 parent_.last_transactionId = transactionId;
130 parent_.usb_last_cookie = cookie;
131 parent_.enable_contaminant_done = true;
132 parent_.notify();
133 return ScopedAStatus::ok();
134 }
135
136 // Callback method for the status of queryPortStatus operation
137 ScopedAStatus notifyQueryPortStatus(const string& /*portName*/, Status /*retval*/,
138 int64_t transactionId) override {
139 parent_.last_transactionId = transactionId;
140 parent_.notify();
141 return ScopedAStatus::ok();
142 }
Badhri Jagan Sridharan6f67c562022-01-17 19:13:08 -0800143
144 // Callback method for the status of limitPowerTransfer operation
145 ScopedAStatus notifyLimitPowerTransferStatus(const string& /*portName*/, bool /*limit*/,
146 Status /*retval*/, int64_t transactionId) override {
147 parent_.last_transactionId = transactionId;
148 parent_.usb_last_cookie = cookie;
149 parent_.limit_power_transfer_done = true;
150 parent_.notify();
151 return ScopedAStatus::ok();
152 }
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -0800153 };
154
155 virtual void SetUp() override {
156 ALOGI("Setup");
157 usb = IUsb::fromBinder(
158 SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
159 ASSERT_NE(usb, nullptr);
160
161 usb_cb_2 = ::ndk::SharedRefBase::make<UsbCallback>(*this, 2);
162 ASSERT_NE(usb_cb_2, nullptr);
163 const auto& ret = usb->setCallback(usb_cb_2);
164 ASSERT_TRUE(ret.isOk());
165 }
166
167 virtual void TearDown() override { ALOGI("Teardown"); }
168
169 // Used as a mechanism to inform the test about data/event callback.
170 inline void notify() {
171 std::unique_lock<std::mutex> lock(usb_mtx);
172 usb_count++;
173 usb_cv.notify_one();
174 }
175
176 // Test code calls this function to wait for data/event callback.
177 inline std::cv_status wait() {
178 std::unique_lock<std::mutex> lock(usb_mtx);
179
180 std::cv_status status = std::cv_status::no_timeout;
181 auto now = std::chrono::system_clock::now();
182 while (usb_count == 0) {
183 status =
184 usb_cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
185 if (status == std::cv_status::timeout) {
186 ALOGI("timeout");
187 return status;
188 }
189 }
190 usb_count--;
191 return status;
192 }
193
194 // USB aidl hal Proxy
195 shared_ptr<IUsb> usb;
196
197 // Callback objects for usb aidl
198 // Methods of these objects are called to notify port status updates.
199 shared_ptr<IUsbCallback> usb_cb_1, usb_cb_2;
200
201 // The last conveyed status of the USB ports.
202 // Stores information of currentt_data_role, power_role for all the USB ports
203 PortStatus usb_last_port_status;
204
205 // Status of the last role switch operation.
206 Status usb_last_status;
207
208 // Port role information of the last role switch operation.
209 PortRole usb_last_port_role;
210
211 // Flag to indicate the invocation of role switch callback.
212 bool usb_role_switch_done;
213
214 // Flag to indicate the invocation of notifyContaminantEnabledStatus callback.
215 bool enable_contaminant_done;
216
217 // Flag to indicate the invocation of notifyEnableUsbDataStatus callback.
218 bool enable_usb_data_done;
219
Badhri Jagan Sridharanf8832352022-01-23 09:17:04 -0800220 // Flag to indicate the invocation of notifyEnableUsbDataWhileDockedStatus callback.
221 bool enable_usb_data_while_docked_done;
222
Badhri Jagan Sridharan6f67c562022-01-17 19:13:08 -0800223 // Flag to indicate the invocation of notifyLimitPowerTransferStatus callback.
224 bool limit_power_transfer_done;
225
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -0800226 // Stores the cookie of the last invoked usb callback object.
227 int usb_last_cookie;
228
229 // Last transaction ID that was recorded.
230 int64_t last_transactionId;
231 // synchronization primitives to coordinate between main test thread
232 // and the callback thread.
233 std::mutex usb_mtx;
234 std::condition_variable usb_cv;
235 int usb_count = 0;
236};
237
238/*
239 * Test to see if setCallback succeeds.
240 * Callback object is created and registered.
241 */
242TEST_P(UsbAidlTest, setCallback) {
243 ALOGI("UsbAidlTest setCallback start");
244 usb_cb_1 = ::ndk::SharedRefBase::make<UsbCallback>(*this, 1);
245 ASSERT_NE(usb_cb_1, nullptr);
246 const auto& ret = usb->setCallback(usb_cb_1);
247 ASSERT_TRUE(ret.isOk());
248 ALOGI("UsbAidlTest setCallback end");
249}
250
251/*
252 * Check to see if querying type-c
253 * port status succeeds.
254 * The callback parameters are checked to see if the transaction id
255 * matches.
256 */
257TEST_P(UsbAidlTest, queryPortStatus) {
258 ALOGI("UsbAidlTest queryPortStatus start");
259 int64_t transactionId = rand() % 10000;
260 const auto& ret = usb->queryPortStatus(transactionId);
261 ASSERT_TRUE(ret.isOk());
262 EXPECT_EQ(std::cv_status::no_timeout, wait());
263 EXPECT_EQ(2, usb_last_cookie);
264 EXPECT_EQ(transactionId, last_transactionId);
265 ALOGI("UsbAidlTest queryPortStatus end: %s", usb_last_port_status.portName.c_str());
266}
267
268/*
269 * Trying to switch a non-existent port should fail.
270 * This test case tried to switch the port with empty
271 * name which is expected to fail.
272 * The callback parameters are checked to see if the transaction id
273 * matches.
274 */
275TEST_P(UsbAidlTest, switchEmptyPort) {
276 ALOGI("UsbAidlTest switchEmptyPort start");
277 PortRole role;
278 role.set<PortRole::powerRole>(PortPowerRole::SOURCE);
279 int64_t transactionId = rand() % 10000;
280 const auto& ret = usb->switchRole("", role, transactionId);
281 ASSERT_TRUE(ret.isOk());
282 EXPECT_EQ(std::cv_status::no_timeout, wait());
283 EXPECT_EQ(Status::ERROR, usb_last_status);
284 EXPECT_EQ(transactionId, last_transactionId);
285 EXPECT_EQ(2, usb_last_cookie);
286 ALOGI("UsbAidlTest switchEmptyPort end");
287}
288
289/*
290 * Test switching the power role of usb port.
291 * Test case queries the usb ports present in device.
292 * If there is at least one usb port, a power role switch
293 * to SOURCE is attempted for the port.
294 * The callback parameters are checked to see if the transaction id
295 * matches.
296 */
297TEST_P(UsbAidlTest, switchPowerRole) {
298 ALOGI("UsbAidlTest switchPowerRole start");
299 PortRole role;
300 role.set<PortRole::powerRole>(PortPowerRole::SOURCE);
301 int64_t transactionId = rand() % 10000;
302 const auto& ret = usb->queryPortStatus(transactionId);
303 ASSERT_TRUE(ret.isOk());
304 EXPECT_EQ(std::cv_status::no_timeout, wait());
305 EXPECT_EQ(2, usb_last_cookie);
306 EXPECT_EQ(transactionId, last_transactionId);
307
308 if (!usb_last_port_status.portName.empty()) {
309 string portBeingSwitched = usb_last_port_status.portName;
310 ALOGI("switchPower role portname:%s", portBeingSwitched.c_str());
311 usb_role_switch_done = false;
312 transactionId = rand() % 10000;
313 const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId);
314 ASSERT_TRUE(ret.isOk());
315
316 std::cv_status waitStatus = wait();
317 while (waitStatus == std::cv_status::no_timeout &&
318 usb_role_switch_done == false)
319 waitStatus = wait();
320
321 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
322 EXPECT_EQ(2, usb_last_cookie);
323 EXPECT_EQ(transactionId, last_transactionId);
324 }
325 ALOGI("UsbAidlTest switchPowerRole end");
326}
327
328/*
329 * Test switching the data role of usb port.
330 * Test case queries the usb ports present in device.
331 * If there is at least one usb port, a data role switch
332 * to device is attempted for the port.
333 * The callback parameters are checked to see if transaction id
334 * matches.
335 */
336TEST_P(UsbAidlTest, switchDataRole) {
337 ALOGI("UsbAidlTest switchDataRole start");
338 PortRole role;
339 role.set<PortRole::dataRole>(PortDataRole::DEVICE);
340 int64_t transactionId = rand() % 10000;
341 const auto& ret = usb->queryPortStatus(transactionId);
342 ASSERT_TRUE(ret.isOk());
343 EXPECT_EQ(std::cv_status::no_timeout, wait());
344 EXPECT_EQ(2, usb_last_cookie);
345 EXPECT_EQ(transactionId, last_transactionId);
346
347 if (!usb_last_port_status.portName.empty()) {
348 string portBeingSwitched = usb_last_port_status.portName;
349 ALOGI("portname:%s", portBeingSwitched.c_str());
350 usb_role_switch_done = false;
351 transactionId = rand() % 10000;
352 const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId);
353 ASSERT_TRUE(ret.isOk());
354
355 std::cv_status waitStatus = wait();
356 while (waitStatus == std::cv_status::no_timeout &&
357 usb_role_switch_done == false)
358 waitStatus = wait();
359
360 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
361 EXPECT_EQ(2, usb_last_cookie);
362 EXPECT_EQ(transactionId, last_transactionId);
363 }
364 ALOGI("UsbAidlTest switchDataRole end");
365}
366
367/*
368 * Test enabling contaminant presence detection of the port.
369 * Test case queries the usb ports present in device.
370 * If there is at least one usb port, enabling contaminant detection
371 * is attempted for the port.
372 * The callback parameters are checked to see if transaction id
373 * matches.
374 */
375TEST_P(UsbAidlTest, enableContaminantPresenceDetection) {
376 ALOGI("UsbAidlTest enableContaminantPresenceDetection start");
377 int64_t transactionId = rand() % 10000;
378 const auto& ret = usb->queryPortStatus(transactionId);
379 ASSERT_TRUE(ret.isOk());
380 EXPECT_EQ(std::cv_status::no_timeout, wait());
381 EXPECT_EQ(2, usb_last_cookie);
382 EXPECT_EQ(transactionId, last_transactionId);
383
384 if (!usb_last_port_status.portName.empty()) {
385 ALOGI("portname:%s", usb_last_port_status.portName.c_str());
386 enable_contaminant_done = false;
387 transactionId = rand() % 10000;
388 const auto& ret = usb->enableContaminantPresenceDetection(usb_last_port_status.portName,
389 true, transactionId);
390 ASSERT_TRUE(ret.isOk());
391
392 std::cv_status waitStatus = wait();
393 while (waitStatus == std::cv_status::no_timeout &&
394 enable_contaminant_done == false)
395 waitStatus = wait();
396
397 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
398 EXPECT_EQ(2, usb_last_cookie);
399 EXPECT_EQ(transactionId, last_transactionId);
400 }
401 ALOGI("UsbAidlTest enableContaminantPresenceDetection end");
402}
403
404/*
405 * Test enabling Usb data of the port.
406 * Test case queries the usb ports present in device.
407 * If there is at least one usb port, enabling Usb data is attempted
408 * for the port.
409 * The callback parameters are checked to see if transaction id
410 * matches.
411 */
412TEST_P(UsbAidlTest, enableUsbData) {
413 ALOGI("UsbAidlTest enableUsbData start");
414 int64_t transactionId = rand() % 10000;
415 const auto& ret = usb->queryPortStatus(transactionId);
416 ASSERT_TRUE(ret.isOk());
417 EXPECT_EQ(std::cv_status::no_timeout, wait());
418 EXPECT_EQ(2, usb_last_cookie);
419 EXPECT_EQ(transactionId, last_transactionId);
420
421 if (!usb_last_port_status.portName.empty()) {
422 ALOGI("portname:%s", usb_last_port_status.portName.c_str());
423 enable_usb_data_done = false;
424 transactionId = rand() % 10000;
425 const auto& ret = usb->enableUsbData(usb_last_port_status.portName, true, transactionId);
426 ASSERT_TRUE(ret.isOk());
427
428 std::cv_status waitStatus = wait();
429 while (waitStatus == std::cv_status::no_timeout &&
430 enable_usb_data_done == false)
431 waitStatus = wait();
432
433 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
434 EXPECT_EQ(2, usb_last_cookie);
435 EXPECT_EQ(transactionId, last_transactionId);
436 }
437 ALOGI("UsbAidlTest enableUsbData end");
438}
439
Badhri Jagan Sridharan6f67c562022-01-17 19:13:08 -0800440/*
Badhri Jagan Sridharanf8832352022-01-23 09:17:04 -0800441 * Test enabling Usb data while being docked.
442 * Test case queries the usb ports present in device.
443 * If there is at least one usb port, enabling Usb data while docked
444 * is attempted for the port.
445 * The callback parameters are checked to see if transaction id
446 * matches.
447 */
448TEST_P(UsbAidlTest, enableUsbDataWhileDocked) {
449 ALOGI("UsbAidlTest enableUsbDataWhileDocked start");
450 int64_t transactionId = rand() % 10000;
451 const auto& ret = usb->queryPortStatus(transactionId);
452 ASSERT_TRUE(ret.isOk());
453 EXPECT_EQ(std::cv_status::no_timeout, wait());
454 EXPECT_EQ(2, usb_last_cookie);
455 EXPECT_EQ(transactionId, last_transactionId);
456
457 if (!usb_last_port_status.portName.empty()) {
458 ALOGI("portname:%s", usb_last_port_status.portName.c_str());
459 enable_usb_data_while_docked_done = false;
460 transactionId = rand() % 10000;
461 const auto& ret = usb->enableUsbDataWhileDocked(usb_last_port_status.portName, transactionId);
462 ASSERT_TRUE(ret.isOk());
463
464 std::cv_status waitStatus = wait();
465 while (waitStatus == std::cv_status::no_timeout &&
466 enable_usb_data_while_docked_done == false)
467 waitStatus = wait();
468
469 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
470 EXPECT_EQ(2, usb_last_cookie);
471 EXPECT_EQ(transactionId, last_transactionId);
472 }
473 ALOGI("UsbAidlTest enableUsbDataWhileDocked end");
474}
475
476/*
Badhri Jagan Sridharan6f67c562022-01-17 19:13:08 -0800477 * Test enabling Usb data of the port.
478 * Test case queries the usb ports present in device.
479 * If there is at least one usb port, relaxing limit power transfer
480 * is attempted for the port.
481 * The callback parameters are checked to see if transaction id
482 * matches.
483 */
484TEST_P(UsbAidlTest, limitPowerTransfer) {
485 ALOGI("UsbAidlTest limitPowerTransfer start");
486 int64_t transactionId = rand() % 10000;
487 const auto& ret = usb->queryPortStatus(transactionId);
488 ASSERT_TRUE(ret.isOk());
489 EXPECT_EQ(std::cv_status::no_timeout, wait());
490 EXPECT_EQ(2, usb_last_cookie);
491 EXPECT_EQ(transactionId, last_transactionId);
492
493 if (!usb_last_port_status.portName.empty()) {
494 ALOGI("portname:%s", usb_last_port_status.portName.c_str());
495 limit_power_transfer_done = false;
496 transactionId = rand() % 10000;
497 const auto& ret = usb->limitPowerTransfer(usb_last_port_status.portName, false, transactionId);
498 ASSERT_TRUE(ret.isOk());
499
500 std::cv_status waitStatus = wait();
501 while (waitStatus == std::cv_status::no_timeout &&
502 limit_power_transfer_done == false)
503 waitStatus = wait();
504
505 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
506 EXPECT_EQ(2, usb_last_cookie);
507 EXPECT_EQ(transactionId, last_transactionId);
508 }
509 ALOGI("UsbAidlTest limitPowerTransfer end");
510}
511
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -0800512GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbAidlTest);
513INSTANTIATE_TEST_SUITE_P(
514 PerInstance, UsbAidlTest,
515 testing::ValuesIn(::android::getAidlHalInstanceNames(IUsb::descriptor)),
516 ::android::PrintInstanceNameToString);
517
518int main(int argc, char** argv) {
519 ::testing::InitGoogleTest(&argc, argv);
520 ABinderProcess_setThreadPoolMaxThreadCount(1);
521 ABinderProcess_startThreadPool();
522 return RUN_ALL_TESTS();
523}