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