1 /*
2 * Copyright (C) 2019 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.2/IWifiNanIfaceEventCallback.h>
21 #include <android/hardware/wifi/1.4/IWifi.h>
22 #include <android/hardware/wifi/1.4/IWifiNanIface.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 using namespace ::android::hardware::wifi::V1_2;
35 using namespace ::android::hardware::wifi::V1_4;
36
37 using ::android::sp;
38 using ::android::hardware::Return;
39 using ::android::hardware::Void;
40
41 #define TIMEOUT_PERIOD 10
42
getWifiNanIface_1_4(const std::string & instance_name)43 android::sp<android::hardware::wifi::V1_4::IWifiNanIface> getWifiNanIface_1_4(
44 const std::string& instance_name) {
45 return android::hardware::wifi::V1_4::IWifiNanIface::castFrom(
46 getWifiNanIface(instance_name));
47 }
48
49 /**
50 * Fixture to use for all NAN Iface HIDL interface tests.
51 */
52 class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
53 public:
SetUp()54 virtual void SetUp() override {
55 if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
56 GTEST_SKIP() << "Skipping this test since NAN is not supported.";
57 // Make sure to start with a clean state
58 stopWifi(GetInstanceName());
59
60 iwifiNanIface = getWifiNanIface_1_4(GetInstanceName());
61 ASSERT_NE(nullptr, iwifiNanIface.get());
62 ASSERT_EQ(WifiStatusCode::SUCCESS,
63 HIDL_INVOKE(iwifiNanIface, registerEventCallback_1_2,
64 new WifiNanIfaceEventCallback(*this))
65 .code);
66 }
67
TearDown()68 virtual void TearDown() override { stopWifi(GetInstanceName()); }
69
70 /* Used as a mechanism to inform the test about data/event callback */
notify()71 inline void notify() {
72 std::unique_lock<std::mutex> lock(mtx_);
73 count_++;
74 cv_.notify_one();
75 }
76
77 enum CallbackType {
78 INVALID = -2,
79 ANY_CALLBACK = -1,
80
81 NOTIFY_CAPABILITIES_RESPONSE = 0,
82 NOTIFY_ENABLE_RESPONSE,
83 NOTIFY_CONFIG_RESPONSE,
84 NOTIFY_DISABLE_RESPONSE,
85 NOTIFY_START_PUBLISH_RESPONSE,
86 NOTIFY_STOP_PUBLISH_RESPONSE,
87 NOTIFY_START_SUBSCRIBE_RESPONSE,
88 NOTIFY_STOP_SUBSCRIBE_RESPONSE,
89 NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE,
90 NOTIFY_CREATE_DATA_INTERFACE_RESPONSE,
91 NOTIFY_DELETE_DATA_INTERFACE_RESPONSE,
92 NOTIFY_INITIATE_DATA_PATH_RESPONSE,
93 NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE,
94 NOTIFY_TERMINATE_DATA_PATH_RESPONSE,
95
96 EVENT_CLUSTER_EVENT,
97 EVENT_DISABLED,
98 EVENT_PUBLISH_TERMINATED,
99 EVENT_SUBSCRIBE_TERMINATED,
100 EVENT_MATCH,
101 EVENT_MATCH_EXPIRED,
102 EVENT_FOLLOWUP_RECEIVED,
103 EVENT_TRANSMIT_FOLLOWUP,
104 EVENT_DATA_PATH_REQUEST,
105 EVENT_DATA_PATH_CONFIRM,
106 EVENT_DATA_PATH_TERMINATED,
107 EVENT_DATA_PATH_CONFIRM_1_2,
108 EVENT_DATA_PATH_SCHEDULE_UPDATE
109 };
110
111 /* Test code calls this function to wait for data/event callback */
112 /* Must set callbackType = INVALID before call this function */
wait(CallbackType waitForCallbackType)113 inline std::cv_status wait(CallbackType waitForCallbackType) {
114 std::unique_lock<std::mutex> lock(mtx_);
115
116 EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a
117 // non-void-returning method
118
119 std::cv_status status = std::cv_status::no_timeout;
120 auto now = std::chrono::system_clock::now();
121 while (count_ == 0) {
122 status = cv_.wait_until(lock,
123 now + std::chrono::seconds(TIMEOUT_PERIOD));
124 if (status == std::cv_status::timeout) return status;
125 if (waitForCallbackType != ANY_CALLBACK &&
126 callbackType != INVALID &&
127 callbackType != waitForCallbackType) {
128 count_--;
129 }
130 }
131 count_--;
132 return status;
133 }
134
135 class WifiNanIfaceEventCallback
136 : public ::android::hardware::wifi::V1_2::IWifiNanIfaceEventCallback {
137 WifiNanIfaceHidlTest& parent_;
138
139 public:
WifiNanIfaceEventCallback(WifiNanIfaceHidlTest & parent)140 WifiNanIfaceEventCallback(WifiNanIfaceHidlTest& parent)
141 : parent_(parent){};
142
143 virtual ~WifiNanIfaceEventCallback() = default;
144
notifyCapabilitiesResponse(uint16_t id,const WifiNanStatus & status,const NanCapabilities & capabilities)145 Return<void> notifyCapabilitiesResponse(
146 uint16_t id, const WifiNanStatus& status,
147 const NanCapabilities& capabilities) override {
148 parent_.callbackType = NOTIFY_CAPABILITIES_RESPONSE;
149
150 parent_.id = id;
151 parent_.status = status;
152 parent_.capabilities = capabilities;
153
154 parent_.notify();
155 return Void();
156 }
157
notifyEnableResponse(uint16_t id,const WifiNanStatus & status)158 Return<void> notifyEnableResponse(
159 uint16_t id, const WifiNanStatus& status) override {
160 parent_.callbackType = NOTIFY_ENABLE_RESPONSE;
161
162 parent_.id = id;
163 parent_.status = status;
164
165 parent_.notify();
166 return Void();
167 }
168
notifyConfigResponse(uint16_t id,const WifiNanStatus & status)169 Return<void> notifyConfigResponse(
170 uint16_t id, const WifiNanStatus& status) override {
171 parent_.callbackType = NOTIFY_CONFIG_RESPONSE;
172
173 parent_.id = id;
174 parent_.status = status;
175
176 parent_.notify();
177 return Void();
178 }
179
notifyDisableResponse(uint16_t id,const WifiNanStatus & status)180 Return<void> notifyDisableResponse(
181 uint16_t id, const WifiNanStatus& status) override {
182 parent_.callbackType = NOTIFY_DISABLE_RESPONSE;
183
184 parent_.id = id;
185 parent_.status = status;
186
187 parent_.notify();
188 return Void();
189 }
190
notifyStartPublishResponse(uint16_t id,const WifiNanStatus & status,uint8_t sessionId)191 Return<void> notifyStartPublishResponse(uint16_t id,
192 const WifiNanStatus& status,
193 uint8_t sessionId) override {
194 parent_.callbackType = NOTIFY_START_PUBLISH_RESPONSE;
195
196 parent_.id = id;
197 parent_.status = status;
198 parent_.sessionId = sessionId;
199
200 parent_.notify();
201 return Void();
202 }
203
notifyStopPublishResponse(uint16_t id,const WifiNanStatus & status)204 Return<void> notifyStopPublishResponse(
205 uint16_t id, const WifiNanStatus& status) override {
206 parent_.callbackType = NOTIFY_STOP_PUBLISH_RESPONSE;
207
208 parent_.id = id;
209 parent_.status = status;
210
211 parent_.notify();
212 return Void();
213 }
214
notifyStartSubscribeResponse(uint16_t id,const WifiNanStatus & status,uint8_t sessionId)215 Return<void> notifyStartSubscribeResponse(uint16_t id,
216 const WifiNanStatus& status,
217 uint8_t sessionId) override {
218 parent_.callbackType = NOTIFY_START_SUBSCRIBE_RESPONSE;
219
220 parent_.id = id;
221 parent_.status = status;
222 parent_.sessionId = sessionId;
223
224 parent_.notify();
225 return Void();
226 }
227
notifyStopSubscribeResponse(uint16_t id,const WifiNanStatus & status)228 Return<void> notifyStopSubscribeResponse(
229 uint16_t id, const WifiNanStatus& status) override {
230 parent_.callbackType = NOTIFY_STOP_SUBSCRIBE_RESPONSE;
231
232 parent_.id = id;
233 parent_.status = status;
234
235 parent_.notify();
236 return Void();
237 }
238
notifyTransmitFollowupResponse(uint16_t id,const WifiNanStatus & status)239 Return<void> notifyTransmitFollowupResponse(
240 uint16_t id, const WifiNanStatus& status) override {
241 parent_.callbackType = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE;
242
243 parent_.id = id;
244 parent_.status = status;
245
246 parent_.notify();
247 return Void();
248 }
249
notifyCreateDataInterfaceResponse(uint16_t id,const WifiNanStatus & status)250 Return<void> notifyCreateDataInterfaceResponse(
251 uint16_t id, const WifiNanStatus& status) override {
252 parent_.callbackType = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE;
253
254 parent_.id = id;
255 parent_.status = status;
256
257 parent_.notify();
258 return Void();
259 }
260
notifyDeleteDataInterfaceResponse(uint16_t id,const WifiNanStatus & status)261 Return<void> notifyDeleteDataInterfaceResponse(
262 uint16_t id, const WifiNanStatus& status) override {
263 parent_.callbackType = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE;
264
265 parent_.id = id;
266 parent_.status = status;
267
268 parent_.notify();
269 return Void();
270 }
271
notifyInitiateDataPathResponse(uint16_t id,const WifiNanStatus & status,uint32_t ndpInstanceId)272 Return<void> notifyInitiateDataPathResponse(
273 uint16_t id, 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, const WifiNanStatus& status) override {
287 parent_.callbackType =
288 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, 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(const WifiNanStatus& status) override {
319 parent_.callbackType = EVENT_DISABLED;
320
321 parent_.status = status;
322
323 parent_.notify();
324 return Void();
325 }
326
eventPublishTerminated(uint8_t sessionId,const WifiNanStatus & status)327 Return<void> eventPublishTerminated(
328 uint8_t sessionId, const WifiNanStatus& status) override {
329 parent_.callbackType = EVENT_PUBLISH_TERMINATED;
330
331 parent_.sessionId = sessionId;
332 parent_.status = status;
333
334 parent_.notify();
335 return Void();
336 }
337
eventSubscribeTerminated(uint8_t sessionId,const WifiNanStatus & status)338 Return<void> eventSubscribeTerminated(
339 uint8_t sessionId, const WifiNanStatus& status) override {
340 parent_.callbackType = EVENT_SUBSCRIBE_TERMINATED;
341
342 parent_.sessionId = sessionId;
343 parent_.status = status;
344
345 parent_.notify();
346 return Void();
347 }
348
eventMatch(const NanMatchInd & event)349 Return<void> eventMatch(const NanMatchInd& event) override {
350 parent_.callbackType = EVENT_MATCH;
351
352 parent_.nanMatchInd = event;
353
354 parent_.notify();
355 return Void();
356 }
357
eventMatchExpired(uint8_t discoverySessionId,uint32_t peerId)358 Return<void> eventMatchExpired(uint8_t discoverySessionId,
359 uint32_t peerId) override {
360 parent_.callbackType = EVENT_MATCH_EXPIRED;
361
362 parent_.sessionId = discoverySessionId;
363 parent_.peerId = peerId;
364
365 parent_.notify();
366 return Void();
367 }
368
eventFollowupReceived(const NanFollowupReceivedInd & event)369 Return<void> eventFollowupReceived(
370 const NanFollowupReceivedInd& event) override {
371 parent_.callbackType = EVENT_FOLLOWUP_RECEIVED;
372
373 parent_.nanFollowupReceivedInd = event;
374
375 parent_.notify();
376 return Void();
377 }
378
eventTransmitFollowup(uint16_t id,const WifiNanStatus & status)379 Return<void> eventTransmitFollowup(
380 uint16_t id, const WifiNanStatus& status) override {
381 parent_.callbackType = EVENT_TRANSMIT_FOLLOWUP;
382
383 parent_.id = id;
384 parent_.status = status;
385
386 parent_.notify();
387 return Void();
388 }
389
eventDataPathRequest(const NanDataPathRequestInd & event)390 Return<void> eventDataPathRequest(
391 const NanDataPathRequestInd& event) override {
392 parent_.callbackType = EVENT_DATA_PATH_REQUEST;
393
394 parent_.nanDataPathRequestInd = event;
395
396 parent_.notify();
397 return Void();
398 }
399
eventDataPathConfirm(const::android::hardware::wifi::V1_0::NanDataPathConfirmInd & event)400 Return<void> eventDataPathConfirm(
401 const ::android::hardware::wifi::V1_0::NanDataPathConfirmInd& event)
402 override {
403 parent_.callbackType = EVENT_DATA_PATH_CONFIRM;
404
405 parent_.nanDataPathConfirmInd = event;
406
407 parent_.notify();
408 return Void();
409 }
410
eventDataPathTerminated(uint32_t ndpInstanceId)411 Return<void> eventDataPathTerminated(uint32_t ndpInstanceId) override {
412 parent_.callbackType = EVENT_DATA_PATH_TERMINATED;
413
414 parent_.ndpInstanceId = ndpInstanceId;
415
416 parent_.notify();
417 return Void();
418 }
419
eventDataPathConfirm_1_2(const::android::hardware::wifi::V1_2::NanDataPathConfirmInd & event)420 Return<void> eventDataPathConfirm_1_2(
421 const ::android::hardware::wifi::V1_2::NanDataPathConfirmInd& event)
422 override {
423 parent_.callbackType = EVENT_DATA_PATH_CONFIRM_1_2;
424
425 parent_.nanDataPathConfirmInd_1_2 = event;
426
427 parent_.notify();
428 return Void();
429 }
430
eventDataPathScheduleUpdate(const NanDataPathScheduleUpdateInd & event)431 Return<void> eventDataPathScheduleUpdate(
432 const NanDataPathScheduleUpdateInd& event) override {
433 parent_.callbackType = EVENT_DATA_PATH_SCHEDULE_UPDATE;
434
435 parent_.nanDataPathScheduleUpdateInd = event;
436
437 parent_.notify();
438 return Void();
439 }
440 };
441
442 private:
443 // synchronization objects
444 std::mutex mtx_;
445 std::condition_variable cv_;
446 int count_ = 0;
447
448 protected:
449 android::sp<::android::hardware::wifi::V1_4::IWifiNanIface> iwifiNanIface;
450
451 // Data from IWifiNanIfaceEventCallback callbacks: this is the collection of
452 // all arguments to all callbacks. They are set by the callback
453 // (notifications or events) and can be retrieved by tests.
454 CallbackType callbackType;
455 uint16_t id;
456 WifiNanStatus status;
457 NanCapabilities capabilities;
458 uint8_t sessionId;
459 uint32_t ndpInstanceId;
460 NanClusterEventInd nanClusterEventInd;
461 NanMatchInd nanMatchInd;
462 uint32_t peerId;
463 NanFollowupReceivedInd nanFollowupReceivedInd;
464 NanDataPathRequestInd nanDataPathRequestInd;
465 ::android::hardware::wifi::V1_0::NanDataPathConfirmInd
466 nanDataPathConfirmInd;
467 ::android::hardware::wifi::V1_2::NanDataPathConfirmInd
468 nanDataPathConfirmInd_1_2;
469 NanDataPathScheduleUpdateInd nanDataPathScheduleUpdateInd;
470
GetInstanceName()471 std::string GetInstanceName() { return GetParam(); }
472 };
473
474 /*
475 * Create:
476 * Ensures that an instance of the IWifiNanIface proxy object is
477 * successfully created.
478 */
TEST_P(WifiNanIfaceHidlTest,Create)479 TEST_P(WifiNanIfaceHidlTest, Create) {
480 // The creation of a proxy object is tested as part of SetUp method.
481 }
482
483 /*
484 * enableRequest_1_4InvalidArgs: validate that fails with invalid arguments
485 */
TEST_P(WifiNanIfaceHidlTest,enableRequest_1_4InvalidArgs)486 TEST_P(WifiNanIfaceHidlTest, enableRequest_1_4InvalidArgs) {
487 uint16_t inputCmdId = 10;
488 callbackType = INVALID;
489 ::android::hardware::wifi::V1_4::NanEnableRequest nanEnableRequest = {};
490 NanConfigRequestSupplemental nanConfigRequestSupp = {};
491 ASSERT_EQ(WifiStatusCode::SUCCESS,
492 HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId,
493 nanEnableRequest, nanConfigRequestSupp)
494 .code);
495 // wait for a callback
496 ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE));
497 ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callbackType);
498 ASSERT_EQ(id, inputCmdId);
499 ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS);
500 }
501
502 /*
503 * enableRequest_1_4ShimInvalidArgs: validate that fails with invalid arguments
504 * to the shim
505 */
TEST_P(WifiNanIfaceHidlTest,enableRequest_1_4ShimInvalidArgs)506 TEST_P(WifiNanIfaceHidlTest, enableRequest_1_4ShimInvalidArgs) {
507 uint16_t inputCmdId = 10;
508 ::android::hardware::wifi::V1_4::NanEnableRequest nanEnableRequest = {};
509 nanEnableRequest.configParams.numberOfPublishServiceIdsInBeacon =
510 128; // must be <= 127
511 NanConfigRequestSupplemental nanConfigRequestSupp = {};
512 ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS,
513 HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId,
514 nanEnableRequest, nanConfigRequestSupp)
515 .code);
516 }
517
518 /*
519 * configRequest_1_4InvalidArgs: validate that fails with invalid arguments
520 */
TEST_P(WifiNanIfaceHidlTest,configRequest_1_4InvalidArgs)521 TEST_P(WifiNanIfaceHidlTest, configRequest_1_4InvalidArgs) {
522 uint16_t inputCmdId = 10;
523 callbackType = INVALID;
524 ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {};
525 NanConfigRequestSupplemental nanConfigRequestSupp = {};
526 ASSERT_EQ(WifiStatusCode::SUCCESS,
527 HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId,
528 nanConfigRequest, nanConfigRequestSupp)
529 .code);
530 // wait for a callback
531 ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CONFIG_RESPONSE));
532 ASSERT_EQ(NOTIFY_CONFIG_RESPONSE, callbackType);
533 ASSERT_EQ(id, inputCmdId);
534 ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS);
535 }
536
537 /*
538 * configRequest_1_4ShimInvalidArgs: validate that fails with invalid arguments
539 * to the shim
540 */
TEST_P(WifiNanIfaceHidlTest,configRequest_1_4ShimInvalidArgs)541 TEST_P(WifiNanIfaceHidlTest, configRequest_1_4ShimInvalidArgs) {
542 uint16_t inputCmdId = 10;
543 ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {};
544 nanConfigRequest.numberOfPublishServiceIdsInBeacon = 128; // must be <= 127
545 NanConfigRequestSupplemental nanConfigRequestSupp = {};
546 ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS,
547 HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId,
548 nanConfigRequest, nanConfigRequestSupp)
549 .code);
550 }
551
552 INSTANTIATE_TEST_SUITE_P(
553 PerInstance, WifiNanIfaceHidlTest,
554 testing::ValuesIn(android::hardware::getAllHalInstanceNames(
555 ::android::hardware::wifi::V1_4::IWifi::descriptor)),
556 android::hardware::PrintInstanceNameToString);
557