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