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