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