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