• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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