blob: bab5a3af59e6776b46ee9dc7969102e3b4ef0aab [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
115 // Callback method for the status of enableContaminantPresenceDetection
116 ScopedAStatus notifyContaminantEnabledStatus(const string& /*portName*/, bool /*enable*/,
117 Status /*retval*/, int64_t transactionId) override {
118 parent_.last_transactionId = transactionId;
119 parent_.usb_last_cookie = cookie;
120 parent_.enable_contaminant_done = true;
121 parent_.notify();
122 return ScopedAStatus::ok();
123 }
124
125 // Callback method for the status of queryPortStatus operation
126 ScopedAStatus notifyQueryPortStatus(const string& /*portName*/, Status /*retval*/,
127 int64_t transactionId) override {
128 parent_.last_transactionId = transactionId;
129 parent_.notify();
130 return ScopedAStatus::ok();
131 }
Badhri Jagan Sridharan6f67c562022-01-17 19:13:08 -0800132
133 // Callback method for the status of limitPowerTransfer operation
134 ScopedAStatus notifyLimitPowerTransferStatus(const string& /*portName*/, bool /*limit*/,
135 Status /*retval*/, int64_t transactionId) override {
136 parent_.last_transactionId = transactionId;
137 parent_.usb_last_cookie = cookie;
138 parent_.limit_power_transfer_done = true;
139 parent_.notify();
140 return ScopedAStatus::ok();
141 }
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -0800142 };
143
144 virtual void SetUp() override {
145 ALOGI("Setup");
146 usb = IUsb::fromBinder(
147 SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
148 ASSERT_NE(usb, nullptr);
149
150 usb_cb_2 = ::ndk::SharedRefBase::make<UsbCallback>(*this, 2);
151 ASSERT_NE(usb_cb_2, nullptr);
152 const auto& ret = usb->setCallback(usb_cb_2);
153 ASSERT_TRUE(ret.isOk());
154 }
155
156 virtual void TearDown() override { ALOGI("Teardown"); }
157
158 // Used as a mechanism to inform the test about data/event callback.
159 inline void notify() {
160 std::unique_lock<std::mutex> lock(usb_mtx);
161 usb_count++;
162 usb_cv.notify_one();
163 }
164
165 // Test code calls this function to wait for data/event callback.
166 inline std::cv_status wait() {
167 std::unique_lock<std::mutex> lock(usb_mtx);
168
169 std::cv_status status = std::cv_status::no_timeout;
170 auto now = std::chrono::system_clock::now();
171 while (usb_count == 0) {
172 status =
173 usb_cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
174 if (status == std::cv_status::timeout) {
175 ALOGI("timeout");
176 return status;
177 }
178 }
179 usb_count--;
180 return status;
181 }
182
183 // USB aidl hal Proxy
184 shared_ptr<IUsb> usb;
185
186 // Callback objects for usb aidl
187 // Methods of these objects are called to notify port status updates.
188 shared_ptr<IUsbCallback> usb_cb_1, usb_cb_2;
189
190 // The last conveyed status of the USB ports.
191 // Stores information of currentt_data_role, power_role for all the USB ports
192 PortStatus usb_last_port_status;
193
194 // Status of the last role switch operation.
195 Status usb_last_status;
196
197 // Port role information of the last role switch operation.
198 PortRole usb_last_port_role;
199
200 // Flag to indicate the invocation of role switch callback.
201 bool usb_role_switch_done;
202
203 // Flag to indicate the invocation of notifyContaminantEnabledStatus callback.
204 bool enable_contaminant_done;
205
206 // Flag to indicate the invocation of notifyEnableUsbDataStatus callback.
207 bool enable_usb_data_done;
208
Badhri Jagan Sridharan6f67c562022-01-17 19:13:08 -0800209 // Flag to indicate the invocation of notifyLimitPowerTransferStatus callback.
210 bool limit_power_transfer_done;
211
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -0800212 // Stores the cookie of the last invoked usb callback object.
213 int usb_last_cookie;
214
215 // Last transaction ID that was recorded.
216 int64_t last_transactionId;
217 // synchronization primitives to coordinate between main test thread
218 // and the callback thread.
219 std::mutex usb_mtx;
220 std::condition_variable usb_cv;
221 int usb_count = 0;
222};
223
224/*
225 * Test to see if setCallback succeeds.
226 * Callback object is created and registered.
227 */
228TEST_P(UsbAidlTest, setCallback) {
229 ALOGI("UsbAidlTest setCallback start");
230 usb_cb_1 = ::ndk::SharedRefBase::make<UsbCallback>(*this, 1);
231 ASSERT_NE(usb_cb_1, nullptr);
232 const auto& ret = usb->setCallback(usb_cb_1);
233 ASSERT_TRUE(ret.isOk());
234 ALOGI("UsbAidlTest setCallback end");
235}
236
237/*
238 * Check to see if querying type-c
239 * port status succeeds.
240 * The callback parameters are checked to see if the transaction id
241 * matches.
242 */
243TEST_P(UsbAidlTest, queryPortStatus) {
244 ALOGI("UsbAidlTest queryPortStatus start");
245 int64_t transactionId = rand() % 10000;
246 const auto& ret = usb->queryPortStatus(transactionId);
247 ASSERT_TRUE(ret.isOk());
248 EXPECT_EQ(std::cv_status::no_timeout, wait());
249 EXPECT_EQ(2, usb_last_cookie);
250 EXPECT_EQ(transactionId, last_transactionId);
251 ALOGI("UsbAidlTest queryPortStatus end: %s", usb_last_port_status.portName.c_str());
252}
253
254/*
255 * Trying to switch a non-existent port should fail.
256 * This test case tried to switch the port with empty
257 * name which is expected to fail.
258 * The callback parameters are checked to see if the transaction id
259 * matches.
260 */
261TEST_P(UsbAidlTest, switchEmptyPort) {
262 ALOGI("UsbAidlTest switchEmptyPort start");
263 PortRole role;
264 role.set<PortRole::powerRole>(PortPowerRole::SOURCE);
265 int64_t transactionId = rand() % 10000;
266 const auto& ret = usb->switchRole("", role, transactionId);
267 ASSERT_TRUE(ret.isOk());
268 EXPECT_EQ(std::cv_status::no_timeout, wait());
269 EXPECT_EQ(Status::ERROR, usb_last_status);
270 EXPECT_EQ(transactionId, last_transactionId);
271 EXPECT_EQ(2, usb_last_cookie);
272 ALOGI("UsbAidlTest switchEmptyPort end");
273}
274
275/*
276 * Test switching the power role of usb port.
277 * Test case queries the usb ports present in device.
278 * If there is at least one usb port, a power role switch
279 * to SOURCE is attempted for the port.
280 * The callback parameters are checked to see if the transaction id
281 * matches.
282 */
283TEST_P(UsbAidlTest, switchPowerRole) {
284 ALOGI("UsbAidlTest switchPowerRole start");
285 PortRole role;
286 role.set<PortRole::powerRole>(PortPowerRole::SOURCE);
287 int64_t transactionId = rand() % 10000;
288 const auto& ret = usb->queryPortStatus(transactionId);
289 ASSERT_TRUE(ret.isOk());
290 EXPECT_EQ(std::cv_status::no_timeout, wait());
291 EXPECT_EQ(2, usb_last_cookie);
292 EXPECT_EQ(transactionId, last_transactionId);
293
294 if (!usb_last_port_status.portName.empty()) {
295 string portBeingSwitched = usb_last_port_status.portName;
296 ALOGI("switchPower role portname:%s", portBeingSwitched.c_str());
297 usb_role_switch_done = false;
298 transactionId = rand() % 10000;
299 const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId);
300 ASSERT_TRUE(ret.isOk());
301
302 std::cv_status waitStatus = wait();
303 while (waitStatus == std::cv_status::no_timeout &&
304 usb_role_switch_done == false)
305 waitStatus = wait();
306
307 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
308 EXPECT_EQ(2, usb_last_cookie);
309 EXPECT_EQ(transactionId, last_transactionId);
310 }
311 ALOGI("UsbAidlTest switchPowerRole end");
312}
313
314/*
315 * Test switching the data role of usb port.
316 * Test case queries the usb ports present in device.
317 * If there is at least one usb port, a data role switch
318 * to device is attempted for the port.
319 * The callback parameters are checked to see if transaction id
320 * matches.
321 */
322TEST_P(UsbAidlTest, switchDataRole) {
323 ALOGI("UsbAidlTest switchDataRole start");
324 PortRole role;
325 role.set<PortRole::dataRole>(PortDataRole::DEVICE);
326 int64_t transactionId = rand() % 10000;
327 const auto& ret = usb->queryPortStatus(transactionId);
328 ASSERT_TRUE(ret.isOk());
329 EXPECT_EQ(std::cv_status::no_timeout, wait());
330 EXPECT_EQ(2, usb_last_cookie);
331 EXPECT_EQ(transactionId, last_transactionId);
332
333 if (!usb_last_port_status.portName.empty()) {
334 string portBeingSwitched = usb_last_port_status.portName;
335 ALOGI("portname:%s", portBeingSwitched.c_str());
336 usb_role_switch_done = false;
337 transactionId = rand() % 10000;
338 const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId);
339 ASSERT_TRUE(ret.isOk());
340
341 std::cv_status waitStatus = wait();
342 while (waitStatus == std::cv_status::no_timeout &&
343 usb_role_switch_done == false)
344 waitStatus = wait();
345
346 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
347 EXPECT_EQ(2, usb_last_cookie);
348 EXPECT_EQ(transactionId, last_transactionId);
349 }
350 ALOGI("UsbAidlTest switchDataRole end");
351}
352
353/*
354 * Test enabling contaminant presence detection of the port.
355 * Test case queries the usb ports present in device.
356 * If there is at least one usb port, enabling contaminant detection
357 * is attempted for the port.
358 * The callback parameters are checked to see if transaction id
359 * matches.
360 */
361TEST_P(UsbAidlTest, enableContaminantPresenceDetection) {
362 ALOGI("UsbAidlTest enableContaminantPresenceDetection start");
363 int64_t transactionId = rand() % 10000;
364 const auto& ret = usb->queryPortStatus(transactionId);
365 ASSERT_TRUE(ret.isOk());
366 EXPECT_EQ(std::cv_status::no_timeout, wait());
367 EXPECT_EQ(2, usb_last_cookie);
368 EXPECT_EQ(transactionId, last_transactionId);
369
370 if (!usb_last_port_status.portName.empty()) {
371 ALOGI("portname:%s", usb_last_port_status.portName.c_str());
372 enable_contaminant_done = false;
373 transactionId = rand() % 10000;
374 const auto& ret = usb->enableContaminantPresenceDetection(usb_last_port_status.portName,
375 true, transactionId);
376 ASSERT_TRUE(ret.isOk());
377
378 std::cv_status waitStatus = wait();
379 while (waitStatus == std::cv_status::no_timeout &&
380 enable_contaminant_done == false)
381 waitStatus = wait();
382
383 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
384 EXPECT_EQ(2, usb_last_cookie);
385 EXPECT_EQ(transactionId, last_transactionId);
386 }
387 ALOGI("UsbAidlTest enableContaminantPresenceDetection end");
388}
389
390/*
391 * Test enabling Usb data of the port.
392 * Test case queries the usb ports present in device.
393 * If there is at least one usb port, enabling Usb data is attempted
394 * for the port.
395 * The callback parameters are checked to see if transaction id
396 * matches.
397 */
398TEST_P(UsbAidlTest, enableUsbData) {
399 ALOGI("UsbAidlTest enableUsbData start");
400 int64_t transactionId = rand() % 10000;
401 const auto& ret = usb->queryPortStatus(transactionId);
402 ASSERT_TRUE(ret.isOk());
403 EXPECT_EQ(std::cv_status::no_timeout, wait());
404 EXPECT_EQ(2, usb_last_cookie);
405 EXPECT_EQ(transactionId, last_transactionId);
406
407 if (!usb_last_port_status.portName.empty()) {
408 ALOGI("portname:%s", usb_last_port_status.portName.c_str());
409 enable_usb_data_done = false;
410 transactionId = rand() % 10000;
411 const auto& ret = usb->enableUsbData(usb_last_port_status.portName, true, transactionId);
412 ASSERT_TRUE(ret.isOk());
413
414 std::cv_status waitStatus = wait();
415 while (waitStatus == std::cv_status::no_timeout &&
416 enable_usb_data_done == false)
417 waitStatus = wait();
418
419 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
420 EXPECT_EQ(2, usb_last_cookie);
421 EXPECT_EQ(transactionId, last_transactionId);
422 }
423 ALOGI("UsbAidlTest enableUsbData end");
424}
425
Badhri Jagan Sridharan6f67c562022-01-17 19:13:08 -0800426/*
427 * Test enabling Usb data of the port.
428 * Test case queries the usb ports present in device.
429 * If there is at least one usb port, relaxing limit power transfer
430 * is attempted for the port.
431 * The callback parameters are checked to see if transaction id
432 * matches.
433 */
434TEST_P(UsbAidlTest, limitPowerTransfer) {
435 ALOGI("UsbAidlTest limitPowerTransfer start");
436 int64_t transactionId = rand() % 10000;
437 const auto& ret = usb->queryPortStatus(transactionId);
438 ASSERT_TRUE(ret.isOk());
439 EXPECT_EQ(std::cv_status::no_timeout, wait());
440 EXPECT_EQ(2, usb_last_cookie);
441 EXPECT_EQ(transactionId, last_transactionId);
442
443 if (!usb_last_port_status.portName.empty()) {
444 ALOGI("portname:%s", usb_last_port_status.portName.c_str());
445 limit_power_transfer_done = false;
446 transactionId = rand() % 10000;
447 const auto& ret = usb->limitPowerTransfer(usb_last_port_status.portName, false, transactionId);
448 ASSERT_TRUE(ret.isOk());
449
450 std::cv_status waitStatus = wait();
451 while (waitStatus == std::cv_status::no_timeout &&
452 limit_power_transfer_done == false)
453 waitStatus = wait();
454
455 EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
456 EXPECT_EQ(2, usb_last_cookie);
457 EXPECT_EQ(transactionId, last_transactionId);
458 }
459 ALOGI("UsbAidlTest limitPowerTransfer end");
460}
461
Badhri Jagan Sridharanaef9dec2021-12-27 14:02:56 -0800462GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbAidlTest);
463INSTANTIATE_TEST_SUITE_P(
464 PerInstance, UsbAidlTest,
465 testing::ValuesIn(::android::getAidlHalInstanceNames(IUsb::descriptor)),
466 ::android::PrintInstanceNameToString);
467
468int main(int argc, char** argv) {
469 ::testing::InitGoogleTest(&argc, argv);
470 ABinderProcess_setThreadPoolMaxThreadCount(1);
471 ABinderProcess_startThreadPool();
472 return RUN_ALL_TESTS();
473}