1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Nanache 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 #include <android-base/logging.h>
18
19 #include <VtsCoreUtil.h>
20 #include <android/hardware/wifi/1.0/IWifi.h>
21 #include <android/hardware/wifi/1.0/IWifiNanIface.h>
22 #include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
23 #include <gtest/gtest.h>
24 #include <hidl/GtestPrinter.h>
25 #include <hidl/ServiceManagement.h>
26 #include <chrono>
27 #include <condition_variable>
28 #include <mutex>
29
30 #include "wifi_hidl_call_util.h"
31 #include "wifi_hidl_test_utils.h"
32
33 using namespace ::android::hardware::wifi::V1_0;
34
35 using ::android::sp;
36 using ::android::hardware::Return;
37 using ::android::hardware::Void;
38 using ::android::hardware::wifi::V1_0::IWifi;
39
40 #define TIMEOUT_PERIOD 10
41
42 /**
43 * Fixture to use for all NAN Iface HIDL interface tests.
44 */
45 class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
46 public:
SetUp()47 virtual void SetUp() override {
48 if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
49 GTEST_SKIP() << "Skipping this test since NAN is not supported.";
50
51 // Make sure test starts with a clean state
52 stopWifi(GetInstanceName());
53
54 iwifiNanIface = getWifiNanIface(GetInstanceName());
55 ASSERT_NE(nullptr, iwifiNanIface.get());
56 ASSERT_EQ(WifiStatusCode::SUCCESS,
57 HIDL_INVOKE(iwifiNanIface, registerEventCallback,
58 new WifiNanIfaceEventCallback(*this))
59 .code);
60 }
61
TearDown()62 virtual void TearDown() override { stopWifi(GetInstanceName()); }
63
64 /* Used as a mechanism to inform the test about data/event callback */
notify()65 inline void notify() {
66 std::unique_lock<std::mutex> lock(mtx_);
67 count_++;
68 cv_.notify_one();
69 }
70
71 enum CallbackType {
72 INVALID = -2,
73 ANY_CALLBACK = -1,
74
75 NOTIFY_CAPABILITIES_RESPONSE = 0,
76 NOTIFY_ENABLE_RESPONSE,
77 NOTIFY_CONFIG_RESPONSE,
78 NOTIFY_DISABLE_RESPONSE,
79 NOTIFY_START_PUBLISH_RESPONSE,
80 NOTIFY_STOP_PUBLISH_RESPONSE,
81 NOTIFY_START_SUBSCRIBE_RESPONSE,
82 NOTIFY_STOP_SUBSCRIBE_RESPONSE,
83 NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE,
84 NOTIFY_CREATE_DATA_INTERFACE_RESPONSE,
85 NOTIFY_DELETE_DATA_INTERFACE_RESPONSE,
86 NOTIFY_INITIATE_DATA_PATH_RESPONSE,
87 NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE,
88 NOTIFY_TERMINATE_DATA_PATH_RESPONSE,
89
90 EVENT_CLUSTER_EVENT,
91 EVENT_DISABLED,
92 EVENT_PUBLISH_TERMINATED,
93 EVENT_SUBSCRIBE_TERMINATED,
94 EVENT_MATCH,
95 EVENT_MATCH_EXPIRED,
96 EVENT_FOLLOWUP_RECEIVED,
97 EVENT_TRANSMIT_FOLLOWUP,
98 EVENT_DATA_PATH_REQUEST,
99 EVENT_DATA_PATH_CONFIRM,
100 EVENT_DATA_PATH_TERMINATED
101 };
102
103 /* Test code calls this function to wait for data/event callback */
104 /* Must set callbackType = INVALID before call this function */
wait(CallbackType waitForCallbackType)105 inline std::cv_status wait(CallbackType waitForCallbackType) {
106 std::unique_lock<std::mutex> lock(mtx_);
107
108 EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a non-void-returning method
109
110 std::cv_status status = std::cv_status::no_timeout;
111 auto now = std::chrono::system_clock::now();
112 while (count_ == 0) {
113 status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
114 if (status == std::cv_status::timeout) return status;
115 if (waitForCallbackType != ANY_CALLBACK && callbackType != INVALID
116 && callbackType != waitForCallbackType) {
117 count_--;
118 }
119 }
120 count_--;
121 return status;
122 }
123
124 class WifiNanIfaceEventCallback: public IWifiNanIfaceEventCallback {
125 WifiNanIfaceHidlTest& parent_;
126
127 public:
WifiNanIfaceEventCallback(WifiNanIfaceHidlTest & parent)128 WifiNanIfaceEventCallback(WifiNanIfaceHidlTest& parent) : parent_(parent) {};
129
130 virtual ~WifiNanIfaceEventCallback() = default;
131
notifyCapabilitiesResponse(uint16_t id,const WifiNanStatus & status,const NanCapabilities & capabilities)132 Return<void> notifyCapabilitiesResponse(
133 uint16_t id,
134 const WifiNanStatus& status,
135 const NanCapabilities& capabilities) override {
136 parent_.callbackType = NOTIFY_CAPABILITIES_RESPONSE;
137
138 parent_.id = id;
139 parent_.status = status;
140 parent_.capabilities = capabilities;
141
142 parent_.notify();
143 return Void();
144 }
145
notifyEnableResponse(uint16_t id,const WifiNanStatus & status)146 Return<void> notifyEnableResponse(
147 uint16_t id,
148 const WifiNanStatus& status) override {
149 parent_.callbackType = NOTIFY_ENABLE_RESPONSE;
150
151 parent_.id = id;
152 parent_.status = status;
153
154 parent_.notify();
155 return Void();
156 }
157
notifyConfigResponse(uint16_t id,const WifiNanStatus & status)158 Return<void> notifyConfigResponse(
159 uint16_t id,
160 const WifiNanStatus& status) override {
161 parent_.callbackType = NOTIFY_CONFIG_RESPONSE;
162
163 parent_.id = id;
164 parent_.status = status;
165
166 parent_.notify();
167 return Void();
168 }
169
notifyDisableResponse(uint16_t id,const WifiNanStatus & status)170 Return<void> notifyDisableResponse(
171 uint16_t id,
172 const WifiNanStatus& status) override {
173 parent_.callbackType = NOTIFY_DISABLE_RESPONSE;
174
175 parent_.id = id;
176 parent_.status = status;
177
178 parent_.notify();
179 return Void();
180 }
181
notifyStartPublishResponse(uint16_t id,const WifiNanStatus & status,uint8_t sessionId)182 Return<void> notifyStartPublishResponse(
183 uint16_t id,
184 const WifiNanStatus& status,
185 uint8_t sessionId) override {
186 parent_.callbackType = NOTIFY_START_PUBLISH_RESPONSE;
187
188 parent_.id = id;
189 parent_.status = status;
190 parent_.sessionId = sessionId;
191
192 parent_.notify();
193 return Void();
194 }
195
notifyStopPublishResponse(uint16_t id,const WifiNanStatus & status)196 Return<void> notifyStopPublishResponse(
197 uint16_t id,
198 const WifiNanStatus& status) override {
199 parent_.callbackType = NOTIFY_STOP_PUBLISH_RESPONSE;
200
201 parent_.id = id;
202 parent_.status = status;
203
204 parent_.notify();
205 return Void();
206 }
207
notifyStartSubscribeResponse(uint16_t id,const WifiNanStatus & status,uint8_t sessionId)208 Return<void> notifyStartSubscribeResponse(
209 uint16_t id,
210 const WifiNanStatus& status,
211 uint8_t sessionId) override {
212 parent_.callbackType = NOTIFY_START_SUBSCRIBE_RESPONSE;
213
214 parent_.id = id;
215 parent_.status = status;
216 parent_.sessionId = sessionId;
217
218 parent_.notify();
219 return Void();
220 }
221
notifyStopSubscribeResponse(uint16_t id,const WifiNanStatus & status)222 Return<void> notifyStopSubscribeResponse(
223 uint16_t id,
224 const WifiNanStatus& status) override {
225 parent_.callbackType = NOTIFY_STOP_SUBSCRIBE_RESPONSE;
226
227 parent_.id = id;
228 parent_.status = status;
229
230 parent_.notify();
231 return Void();
232 }
233
notifyTransmitFollowupResponse(uint16_t id,const WifiNanStatus & status)234 Return<void> notifyTransmitFollowupResponse(
235 uint16_t id,
236 const WifiNanStatus& status) override {
237 parent_.callbackType = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE;
238
239 parent_.id = id;
240 parent_.status = status;
241
242 parent_.notify();
243 return Void();
244 }
245
notifyCreateDataInterfaceResponse(uint16_t id,const WifiNanStatus & status)246 Return<void> notifyCreateDataInterfaceResponse(
247 uint16_t id,
248 const WifiNanStatus& status) override {
249 parent_.callbackType = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE;
250
251 parent_.id = id;
252 parent_.status = status;
253
254 parent_.notify();
255 return Void();
256 }
257
notifyDeleteDataInterfaceResponse(uint16_t id,const WifiNanStatus & status)258 Return<void> notifyDeleteDataInterfaceResponse(
259 uint16_t id,
260 const WifiNanStatus& status) override {
261 parent_.callbackType = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE;
262
263 parent_.id = id;
264 parent_.status = status;
265
266 parent_.notify();
267 return Void();
268 }
269
notifyInitiateDataPathResponse(uint16_t id,const WifiNanStatus & status,uint32_t ndpInstanceId)270 Return<void> notifyInitiateDataPathResponse(
271 uint16_t id,
272 const WifiNanStatus& status,
273 uint32_t ndpInstanceId) override {
274 parent_.callbackType = NOTIFY_INITIATE_DATA_PATH_RESPONSE;
275
276 parent_.id = id;
277 parent_.status = status;
278 parent_.ndpInstanceId = ndpInstanceId;
279
280 parent_.notify();
281 return Void();
282 }
283
notifyRespondToDataPathIndicationResponse(uint16_t id,const WifiNanStatus & status)284 Return<void> notifyRespondToDataPathIndicationResponse(
285 uint16_t id,
286 const WifiNanStatus& status) override {
287 parent_.callbackType = NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE;
288
289 parent_.id = id;
290 parent_.status = status;
291
292 parent_.notify();
293 return Void();
294 }
295
notifyTerminateDataPathResponse(uint16_t id,const WifiNanStatus & status)296 Return<void> notifyTerminateDataPathResponse(
297 uint16_t id,
298 const WifiNanStatus& status) override {
299 parent_.callbackType = NOTIFY_TERMINATE_DATA_PATH_RESPONSE;
300
301 parent_.id = id;
302 parent_.status = status;
303
304 parent_.notify();
305 return Void();
306 }
307
eventClusterEvent(const NanClusterEventInd & event)308 Return<void> eventClusterEvent(
309 const NanClusterEventInd& event) override {
310 parent_.callbackType = EVENT_CLUSTER_EVENT;
311
312 parent_.nanClusterEventInd = event;
313
314 parent_.notify();
315 return Void();
316 }
317
eventDisabled(const WifiNanStatus & status)318 Return<void> eventDisabled(
319 const WifiNanStatus& status) override {
320 parent_.callbackType = EVENT_DISABLED;
321
322 parent_.status = status;
323
324 parent_.notify();
325 return Void();
326 }
327
eventPublishTerminated(uint8_t sessionId,const WifiNanStatus & status)328 Return<void> eventPublishTerminated(
329 uint8_t sessionId,
330 const WifiNanStatus& status) override {
331 parent_.callbackType = EVENT_PUBLISH_TERMINATED;
332
333 parent_.sessionId = sessionId;
334 parent_.status = status;
335
336 parent_.notify();
337 return Void();
338 }
339
eventSubscribeTerminated(uint8_t sessionId,const WifiNanStatus & status)340 Return<void> eventSubscribeTerminated(
341 uint8_t sessionId,
342 const WifiNanStatus& status) override {
343 parent_.callbackType = EVENT_SUBSCRIBE_TERMINATED;
344
345 parent_.sessionId = sessionId;
346 parent_.status = status;
347
348 parent_.notify();
349 return Void();
350 }
351
eventMatch(const NanMatchInd & event)352 Return<void> eventMatch(
353 const NanMatchInd& event) override {
354 parent_.callbackType = EVENT_MATCH;
355
356 parent_.nanMatchInd = event;
357
358 parent_.notify();
359 return Void();
360 }
361
eventMatchExpired(uint8_t discoverySessionId,uint32_t peerId)362 Return<void> eventMatchExpired(
363 uint8_t discoverySessionId,
364 uint32_t peerId) override {
365 parent_.callbackType = EVENT_MATCH_EXPIRED;
366
367 parent_.sessionId = discoverySessionId;
368 parent_.peerId = peerId;
369
370 parent_.notify();
371 return Void();
372 }
373
eventFollowupReceived(const NanFollowupReceivedInd & event)374 Return<void> eventFollowupReceived(
375 const NanFollowupReceivedInd& event) override {
376 parent_.callbackType = EVENT_FOLLOWUP_RECEIVED;
377
378 parent_.nanFollowupReceivedInd = event;
379
380 parent_.notify();
381 return Void();
382 }
383
eventTransmitFollowup(uint16_t id,const WifiNanStatus & status)384 Return<void> eventTransmitFollowup(
385 uint16_t id,
386 const WifiNanStatus& status) override {
387 parent_.callbackType = EVENT_TRANSMIT_FOLLOWUP;
388
389 parent_.id = id;
390 parent_.status = status;
391
392 parent_.notify();
393 return Void();
394 }
395
eventDataPathRequest(const NanDataPathRequestInd & event)396 Return<void> eventDataPathRequest(
397 const NanDataPathRequestInd& event) override {
398 parent_.callbackType = EVENT_DATA_PATH_REQUEST;
399
400 parent_.nanDataPathRequestInd = event;
401
402 parent_.notify();
403 return Void();
404 }
405
eventDataPathConfirm(const NanDataPathConfirmInd & event)406 Return<void> eventDataPathConfirm(
407 const NanDataPathConfirmInd& event) override {
408 parent_.callbackType = EVENT_DATA_PATH_CONFIRM;
409
410 parent_.nanDataPathConfirmInd = event;
411
412 parent_.notify();
413 return Void();
414 }
415
eventDataPathTerminated(uint32_t ndpInstanceId)416 Return<void> eventDataPathTerminated(
417 uint32_t ndpInstanceId) override {
418 parent_.callbackType = EVENT_DATA_PATH_TERMINATED;
419
420 parent_.ndpInstanceId = ndpInstanceId;
421
422 parent_.notify();
423 return Void();
424 }
425 };
426
427 private:
428 // synchronization objects
429 std::mutex mtx_;
430 std::condition_variable cv_;
431 int count_;
432
433 protected:
434 android::sp<IWifiNanIface> iwifiNanIface;
435
436 // Data from IWifiNanIfaceEventCallback callbacks: this is the collection of all
437 // arguments to all callbacks. They are set by the callback (notifications or
438 // events) and can be retrieved by tests.
439 CallbackType callbackType;
440 uint16_t id;
441 WifiNanStatus status;
442 NanCapabilities capabilities;
443 uint8_t sessionId;
444 uint32_t ndpInstanceId;
445 NanClusterEventInd nanClusterEventInd;
446 NanMatchInd nanMatchInd;
447 uint32_t peerId;
448 NanFollowupReceivedInd nanFollowupReceivedInd;
449 NanDataPathRequestInd nanDataPathRequestInd;
450 NanDataPathConfirmInd nanDataPathConfirmInd;
451
GetInstanceName()452 std::string GetInstanceName() { return GetParam(); }
453 };
454
455 /*
456 * Create:
457 * Ensures that an instance of the IWifiNanIface proxy object is
458 * successfully created.
459 */
TEST_P(WifiNanIfaceHidlTest,Create)460 TEST_P(WifiNanIfaceHidlTest, Create) {
461 // The creation of a proxy object is tested as part of SetUp method.
462 }
463
464 /*
465 * Fail: use past destruction
466 * Ensure that API calls fail with ERROR_WIFI_IFACE_INVALID when using an interface once wifi
467 * is disabled.
468 */
TEST_P(WifiNanIfaceHidlTest,FailOnIfaceInvalid)469 TEST_P(WifiNanIfaceHidlTest, FailOnIfaceInvalid) {
470 stopWifi(GetInstanceName());
471 android::sp<IWifiNanIface> iwifiNanIface =
472 getWifiNanIface(GetInstanceName());
473 ASSERT_NE(nullptr, iwifiNanIface.get());
474 stopWifi(GetInstanceName());
475 sleep(5); // make sure that all chips/interfaces are invalidated
476 ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
477 HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, 0).code);
478 }
479
480 /*
481 * getCapabilitiesRequest: validate that returns capabilities.
482 */
TEST_P(WifiNanIfaceHidlTest,getCapabilitiesRequest)483 TEST_P(WifiNanIfaceHidlTest, getCapabilitiesRequest) {
484 uint16_t inputCmdId = 10;
485 callbackType = INVALID;
486 ASSERT_EQ(
487 WifiStatusCode::SUCCESS,
488 HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code);
489 // wait for a callback
490 ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE));
491 ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callbackType);
492 ASSERT_EQ(id, inputCmdId);
493
494 // check for reasonable capability values
495 EXPECT_GT(capabilities.maxConcurrentClusters, (unsigned int)0);
496 EXPECT_GT(capabilities.maxPublishes, (unsigned int)0);
497 EXPECT_GT(capabilities.maxSubscribes, (unsigned int)0);
498 EXPECT_EQ(capabilities.maxServiceNameLen, (unsigned int)255);
499 EXPECT_EQ(capabilities.maxMatchFilterLen, (unsigned int)255);
500 EXPECT_GT(capabilities.maxTotalMatchFilterLen, (unsigned int)255);
501 EXPECT_EQ(capabilities.maxServiceSpecificInfoLen, (unsigned int)255);
502 EXPECT_GE(capabilities.maxExtendedServiceSpecificInfoLen,
503 (unsigned int)255);
504 EXPECT_GT(capabilities.maxNdiInterfaces, (unsigned int)0);
505 EXPECT_GT(capabilities.maxNdpSessions, (unsigned int)0);
506 EXPECT_GT(capabilities.maxAppInfoLen, (unsigned int)0);
507 EXPECT_GT(capabilities.maxQueuedTransmitFollowupMsgs, (unsigned int)0);
508 EXPECT_GT(capabilities.maxSubscribeInterfaceAddresses, (unsigned int)0);
509 EXPECT_NE(capabilities.supportedCipherSuites, (unsigned int)0);
510 }
511
512 INSTANTIATE_TEST_SUITE_P(
513 PerInstance, WifiNanIfaceHidlTest,
514 testing::ValuesIn(
515 android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
516 android::hardware::PrintInstanceNameToString);
517