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
30using namespace ::android::hardware::wifi::V1_0;
31
32using ::android::hardware::Return;
33using ::android::hardware::Void;
34using ::android::sp;
35
36#define TIMEOUT_PERIOD 10
37
38/**
39 * Fixture to use for all NAN Iface HIDL interface tests.
40 */
41class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
42  public:
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
50    virtual void TearDown() override {
51      stopWifi();
52    }
53
54    /* Used as a mechanism to inform the test about data/event callback */
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 */
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:
118      WifiNanIfaceEventCallback(WifiNanIfaceHidlTest& parent) : parent_(parent) {};
119
120      virtual ~WifiNanIfaceEventCallback() = default;
121
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */
448TEST(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 */
458TEST(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 */
470TEST_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