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