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