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