1 /*
2 * Copyright (C) 2019 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_2TargetTest"
18 #include <android-base/logging.h>
19
20 #include <android/hardware/usb/1.2/IUsb.h>
21 #include <android/hardware/usb/1.2/IUsbCallback.h>
22 #include <android/hardware/usb/1.2/types.h>
23
24 #include <VtsHalHidlTargetCallbackBase.h>
25 #include <VtsHalHidlTargetTestBase.h>
26 #include <VtsHalHidlTargetTestEnvBase.h>
27 #include <log/log.h>
28 #include <stdlib.h>
29 #include <chrono>
30 #include <condition_variable>
31 #include <mutex>
32
33 using ::android::sp;
34 using ::android::hardware::hidl_array;
35 using ::android::hardware::hidl_memory;
36 using ::android::hardware::hidl_string;
37 using ::android::hardware::hidl_vec;
38 using ::android::hardware::Return;
39 using ::android::hardware::Void;
40 using ::android::hardware::usb::V1_0::PortDataRole;
41 using ::android::hardware::usb::V1_0::PortMode;
42 using ::android::hardware::usb::V1_0::PortPowerRole;
43 using ::android::hardware::usb::V1_0::PortRole;
44 using ::android::hardware::usb::V1_0::PortRoleType;
45 using ::android::hardware::usb::V1_0::Status;
46 using ::android::hardware::usb::V1_1::PortMode_1_1;
47 using ::android::hardware::usb::V1_1::PortStatus_1_1;
48 using ::android::hardware::usb::V1_2::ContaminantDetectionStatus;
49 using ::android::hardware::usb::V1_2::ContaminantProtectionMode;
50 using ::android::hardware::usb::V1_2::ContaminantProtectionStatus;
51 using ::android::hardware::usb::V1_2::IUsb;
52 using ::android::hardware::usb::V1_2::IUsbCallback;
53 using ::android::hardware::usb::V1_2::PortStatus;
54 using ::android::hidl::base::V1_0::IBase;
55
56 constexpr char kCallbackNameNotifyPortStatusChange_1_2[] = "notifyPortStatusChange_1_2";
57 const int kCallbackIdentifier = 2;
58
59 // Worst case wait time 20secs
60 #define WAIT_FOR_TIMEOUT std::chrono::milliseconds(20000)
61
62 class UsbClientCallbackArgs {
63 public:
64 // The last conveyed status of the USB ports.
65 // Stores information of currentt_data_role, power_role for all the USB ports
66 PortStatus usb_last_port_status;
67
68 // Status of the last role switch operation.
69 Status usb_last_status;
70
71 // Identifier for the usb callback object.
72 // Stores the cookie of the last invoked usb callback object.
73 int last_usb_cookie;
74 };
75
76 // Callback class for the USB HIDL hal.
77 // Usb Hal will call this object upon role switch or port query.
78 class UsbCallback : public ::testing::VtsHalHidlTargetCallbackBase<UsbClientCallbackArgs>,
79 public IUsbCallback {
80 int cookie;
81
82 public:
UsbCallback(int cookie)83 UsbCallback(int cookie) : cookie(cookie){};
84
85 virtual ~UsbCallback() = default;
86
87 // V1_0 Callback method for the port status.
88 // This should not be called so not signalling the Test here assuming that
89 // the test thread will timeout
notifyPortStatusChange(const hidl_vec<android::hardware::usb::V1_0::PortStatus> &,Status)90 Return<void> notifyPortStatusChange(const hidl_vec<android::hardware::usb::V1_0::PortStatus>&
91 /* currentPortStatus */,
92 Status /* retval */) override {
93 return Void();
94 };
95
96 // V1_1 Callback method for the port status.
97 // This should not be called so not signalling the Test here assuming that
98 // the test thread will timeout
notifyPortStatusChange_1_1(const hidl_vec<PortStatus_1_1> &,Status)99 Return<void> notifyPortStatusChange_1_1(const hidl_vec<PortStatus_1_1>& /* currentPortStatus */,
100 Status /* retval */) override {
101 return Void();
102 }
103
104 // This callback method should be used.
notifyPortStatusChange_1_2(const hidl_vec<PortStatus> & currentPortStatus,Status retval)105 Return<void> notifyPortStatusChange_1_2(const hidl_vec<PortStatus>& currentPortStatus,
106 Status retval) override {
107 UsbClientCallbackArgs arg;
108 if (retval == Status::SUCCESS) {
109 arg.usb_last_port_status.status_1_1.status.supportedModes =
110 currentPortStatus[0].status_1_1.status.supportedModes;
111 arg.usb_last_port_status.status_1_1.status.currentMode =
112 currentPortStatus[0].status_1_1.status.currentMode;
113 arg.usb_last_port_status.status_1_1.status.portName =
114 currentPortStatus[0].status_1_1.status.portName;
115 arg.usb_last_port_status.contaminantDetectionStatus =
116 currentPortStatus[0].contaminantDetectionStatus;
117 arg.usb_last_port_status.contaminantProtectionStatus =
118 currentPortStatus[0].contaminantProtectionStatus;
119 arg.usb_last_port_status.supportsEnableContaminantPresenceProtection =
120 currentPortStatus[0].supportsEnableContaminantPresenceProtection;
121 arg.usb_last_port_status.supportsEnableContaminantPresenceDetection =
122 currentPortStatus[0].supportsEnableContaminantPresenceDetection;
123 arg.usb_last_port_status.supportedContaminantProtectionModes =
124 currentPortStatus[0].supportedContaminantProtectionModes;
125 }
126 arg.usb_last_status = retval;
127 arg.last_usb_cookie = cookie;
128
129 NotifyFromCallback(kCallbackNameNotifyPortStatusChange_1_2, arg);
130 return Void();
131 }
132
133 // Callback method for the status of role switch operation.
134 // RoleSwitch operation has not changed since V1_0 so leaving
135 // the callback blank here.
notifyRoleSwitchStatus(const hidl_string &,const PortRole &,Status)136 Return<void> notifyRoleSwitchStatus(const hidl_string& /*portName*/,
137 const PortRole& /*newRole*/, Status /*retval*/) override {
138 return Void();
139 };
140 };
141
142 // Test environment for Usb HIDL HAL.
143 class UsbHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
144 public:
145 // get the test environment singleton
Instance()146 static UsbHidlEnvironment* Instance() {
147 static UsbHidlEnvironment* instance = new UsbHidlEnvironment;
148 return instance;
149 }
150
registerTestServices()151 virtual void registerTestServices() override { registerTestService<IUsb>(); }
152 };
153
154 // The main test class for the USB hidl HAL
155 class UsbHidlTest : public ::testing::VtsHalHidlTargetTestBase {
156 public:
SetUp()157 virtual void SetUp() override {
158 ALOGI(__FUNCTION__);
159 usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>();
160 ASSERT_NE(usb, nullptr);
161
162 usb_cb_2 = new UsbCallback(kCallbackIdentifier);
163 ASSERT_NE(usb_cb_2, nullptr);
164 usb_cb_2->SetWaitTimeout(kCallbackNameNotifyPortStatusChange_1_2, WAIT_FOR_TIMEOUT);
165 Return<void> ret = usb->setCallback(usb_cb_2);
166 ASSERT_TRUE(ret.isOk());
167 }
168
TearDown()169 virtual void TearDown() override { ALOGI("Teardown"); }
170
171 // USB hidl hal Proxy
172 sp<IUsb> usb;
173
174 // Callback objects for usb hidl
175 // Methods of these objects are called to notify port status updates.
176 sp<UsbCallback> usb_cb_1;
177 sp<UsbCallback> usb_cb_2;
178 };
179
180 /*
181 * Test to see if setCallback on V1_1 callback object succeeds.
182 * Callback oject is created and registered.
183 * Check to see if the hidl transaction succeeded.
184 */
TEST_F(UsbHidlTest,setCallback)185 TEST_F(UsbHidlTest, setCallback) {
186 usb_cb_1 = new UsbCallback(1);
187 ASSERT_NE(usb_cb_1, nullptr);
188 Return<void> ret = usb->setCallback(usb_cb_1);
189 ASSERT_TRUE(ret.isOk());
190 }
191
192 /*
193 * Check to see if querying type-c
194 * port status succeeds.
195 * HAL service should call notifyPortStatusChange_1_2
196 * instead of notifyPortStatusChange of V1_0/V1_1 interface
197 */
TEST_F(UsbHidlTest,queryPortStatus)198 TEST_F(UsbHidlTest, queryPortStatus) {
199 Return<void> ret = usb->queryPortStatus();
200 ASSERT_TRUE(ret.isOk());
201 auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
202 EXPECT_TRUE(res.no_timeout);
203 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
204 EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.currentMode);
205 EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.supportedModes);
206 EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
207 }
208
209 /*
210 * supportedContaminantProtectionModes is immutable.
211 * Check if supportedContaminantProtectionModes changes across queryPortStatus
212 * call.
213 */
TEST_F(UsbHidlTest,checkSupportedContaminantProtectionModes)214 TEST_F(UsbHidlTest, checkSupportedContaminantProtectionModes) {
215 Return<void> ret = usb->queryPortStatus();
216 ASSERT_TRUE(ret.isOk());
217 auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
218 EXPECT_TRUE(res.no_timeout);
219 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
220 EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.currentMode);
221 EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.supportedModes);
222 EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
223
224 uint32_t supportedContaminantProtectionModes = static_cast<uint32_t>(
225 res.args->usb_last_port_status.supportedContaminantProtectionModes);
226 for (int runs = 1; runs <= 10; runs++) {
227 ret = usb->queryPortStatus();
228 ASSERT_TRUE(ret.isOk());
229 res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
230 EXPECT_TRUE(res.no_timeout);
231 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
232 EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.currentMode);
233 EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.supportedModes);
234 EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
235 EXPECT_EQ(supportedContaminantProtectionModes,
236 static_cast<uint32_t>(
237 res.args->usb_last_port_status.supportedContaminantProtectionModes));
238 }
239 }
240
241 /*
242 * When supportsEnableContaminantPresenceDetection is set false,
243 * enableContaminantPresenceDetection should not enable/disable
244 * contaminantPresenceProtection.
245 */
TEST_F(UsbHidlTest,presenceDetectionSupportedCheck)246 TEST_F(UsbHidlTest, presenceDetectionSupportedCheck) {
247 Return<void> ret = usb->queryPortStatus();
248 ASSERT_TRUE(ret.isOk());
249 auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
250 EXPECT_TRUE(res.no_timeout);
251 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
252 EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
253
254 if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceDetection) {
255 for (int runs = 1; runs <= 10; runs++) {
256 bool currentStatus = !(res.args->usb_last_port_status.contaminantDetectionStatus ==
257 ContaminantDetectionStatus::DISABLED);
258
259 ret = usb->enableContaminantPresenceDetection(
260 res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus);
261 ASSERT_TRUE(ret.isOk());
262
263 res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
264 EXPECT_TRUE(res.no_timeout);
265 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
266 EXPECT_EQ(currentStatus, !(res.args->usb_last_port_status.contaminantDetectionStatus ==
267 ContaminantDetectionStatus::DISABLED));
268 }
269 }
270 }
271
272 /*
273 * enableContaminantPresenceDetection should succeed atleast 90% when supported.
274 */
TEST_F(UsbHidlTest,contaminantPresenceDetectionStability)275 TEST_F(UsbHidlTest, contaminantPresenceDetectionStability) {
276 int successCount = 0;
277 bool currentStatus;
278 bool supported = true;
279
280 Return<void> ret = usb->queryPortStatus();
281 ASSERT_TRUE(ret.isOk());
282 auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
283 EXPECT_TRUE(res.no_timeout);
284 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
285 EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
286
287 if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceDetection) return;
288
289 for (int count = 1; count <= 10; count++) {
290 currentStatus = !(res.args->usb_last_port_status.contaminantDetectionStatus ==
291 ContaminantDetectionStatus::DISABLED);
292
293 ret = usb->enableContaminantPresenceDetection(
294 res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus);
295 ASSERT_TRUE(ret.isOk());
296 res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
297 EXPECT_TRUE(res.no_timeout);
298 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
299 if (!currentStatus == !(res.args->usb_last_port_status.contaminantDetectionStatus ==
300 ContaminantDetectionStatus::DISABLED))
301 successCount++;
302 }
303
304 if (!supported) EXPECT_GE(successCount, 9);
305 }
306
307 /*
308 * When supportsEnableContaminantPresenceProtection is set false,
309 * enableContaminantPresenceProtection should not enable/disable
310 * contaminantPresenceProtection.
311 */
TEST_F(UsbHidlTest,presenceProtectionSupportedCheck)312 TEST_F(UsbHidlTest, presenceProtectionSupportedCheck) {
313 Return<void> ret = usb->queryPortStatus();
314 ASSERT_TRUE(ret.isOk());
315 auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
316 EXPECT_TRUE(res.no_timeout);
317 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
318 EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
319
320 if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceProtection) {
321 for (int runs = 1; runs <= 10; runs++) {
322 bool currentStatus = !(res.args->usb_last_port_status.contaminantProtectionStatus ==
323 ContaminantProtectionStatus::DISABLED);
324
325 ret = usb->enableContaminantPresenceProtection(
326 res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus);
327 ASSERT_TRUE(ret.isOk());
328
329 res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
330 EXPECT_TRUE(res.no_timeout);
331 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
332 EXPECT_EQ(currentStatus, !(res.args->usb_last_port_status.contaminantProtectionStatus ==
333 ContaminantProtectionStatus::DISABLED));
334 }
335 }
336 }
337
338 /*
339 * enableContaminantPresenceProtection should succeed atleast 90% when supported.
340 */
TEST_F(UsbHidlTest,contaminantPresenceProtectionStability)341 TEST_F(UsbHidlTest, contaminantPresenceProtectionStability) {
342 int successCount = 0;
343 bool currentStatus;
344 bool supported = true;
345
346 Return<void> ret = usb->queryPortStatus();
347 ASSERT_TRUE(ret.isOk());
348 auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
349 EXPECT_TRUE(res.no_timeout);
350 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
351 EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
352
353 if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceProtection) return;
354
355 for (int count = 1; count <= 10; count++) {
356 currentStatus = !(res.args->usb_last_port_status.contaminantProtectionStatus ==
357 ContaminantProtectionStatus::DISABLED);
358
359 ret = usb->enableContaminantPresenceProtection(
360 res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus);
361 ASSERT_TRUE(ret.isOk());
362 res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
363 EXPECT_TRUE(res.no_timeout);
364 EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie);
365 if (!currentStatus == !(res.args->usb_last_port_status.contaminantProtectionStatus ==
366 ContaminantProtectionStatus::DISABLED))
367 successCount++;
368 }
369
370 if (!supported) EXPECT_GE(successCount, 9);
371 }
372
main(int argc,char ** argv)373 int main(int argc, char** argv) {
374 ::testing::AddGlobalTestEnvironment(UsbHidlEnvironment::Instance());
375 ::testing::InitGoogleTest(&argc, argv);
376 UsbHidlEnvironment::Instance()->init(&argc, argv);
377 int status = RUN_ALL_TESTS();
378 ALOGI("Test result = %d", status);
379 return status;
380 }
381