diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp index 918e4a456b..c5a6e8417e 100644 --- a/wifi/1.2/vts/functional/Android.bp +++ b/wifi/1.2/vts/functional/Android.bp @@ -29,3 +29,18 @@ cc_test { "android.hardware.wifi@1.2", ], } + +cc_test { + name: "VtsHalWifiNanV1_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "VtsHalWifiV1_2TargetTest.cpp", + "wifi_nan_iface_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + ], +} diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp new file mode 100644 index 0000000000..cc36faeafc --- /dev/null +++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Nanache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" + +using namespace ::android::hardware::wifi::V1_0; +using namespace ::android::hardware::wifi::V1_2; + +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +#define TIMEOUT_PERIOD 10 + +android::sp +getWifiNanIface_1_2() { + return android::hardware::wifi::V1_2::IWifiNanIface::castFrom( + getWifiNanIface()); +} + +/** + * Fixture to use for all NAN Iface HIDL interface tests. + */ +class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + virtual void SetUp() override { + iwifiNanIface = getWifiNanIface_1_2(); + ASSERT_NE(nullptr, iwifiNanIface.get()); + ASSERT_EQ(WifiStatusCode::SUCCESS, + HIDL_INVOKE(iwifiNanIface, registerEventCallback_1_2, + new WifiNanIfaceEventCallback(*this)) + .code); + } + + virtual void TearDown() override { stopWifi(); } + + /* Used as a mechanism to inform the test about data/event callback */ + inline void notify() { + std::unique_lock lock(mtx_); + count_++; + cv_.notify_one(); + } + + enum CallbackType { + INVALID = -2, + ANY_CALLBACK = -1, + + NOTIFY_CAPABILITIES_RESPONSE = 0, + NOTIFY_ENABLE_RESPONSE, + NOTIFY_CONFIG_RESPONSE, + NOTIFY_DISABLE_RESPONSE, + NOTIFY_START_PUBLISH_RESPONSE, + NOTIFY_STOP_PUBLISH_RESPONSE, + NOTIFY_START_SUBSCRIBE_RESPONSE, + NOTIFY_STOP_SUBSCRIBE_RESPONSE, + NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE, + NOTIFY_CREATE_DATA_INTERFACE_RESPONSE, + NOTIFY_DELETE_DATA_INTERFACE_RESPONSE, + NOTIFY_INITIATE_DATA_PATH_RESPONSE, + NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE, + NOTIFY_TERMINATE_DATA_PATH_RESPONSE, + + EVENT_CLUSTER_EVENT, + EVENT_DISABLED, + EVENT_PUBLISH_TERMINATED, + EVENT_SUBSCRIBE_TERMINATED, + EVENT_MATCH, + EVENT_MATCH_EXPIRED, + EVENT_FOLLOWUP_RECEIVED, + EVENT_TRANSMIT_FOLLOWUP, + EVENT_DATA_PATH_REQUEST, + EVENT_DATA_PATH_CONFIRM, + EVENT_DATA_PATH_TERMINATED, + EVENT_DATA_PATH_CONFIRM_1_2, + EVENT_DATA_PATH_SCHEDULE_UPDATE + }; + + /* Test code calls this function to wait for data/event callback */ + inline std::cv_status wait(CallbackType waitForCallbackType) { + std::unique_lock lock(mtx_); + + EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a + // non-void-returning method + + callbackType = INVALID; + std::cv_status status = std::cv_status::no_timeout; + auto now = std::chrono::system_clock::now(); + while (count_ == 0) { + status = cv_.wait_until(lock, + now + std::chrono::seconds(TIMEOUT_PERIOD)); + if (status == std::cv_status::timeout) return status; + if (waitForCallbackType != ANY_CALLBACK && + callbackType != INVALID && + callbackType != waitForCallbackType) { + count_--; + } + } + count_--; + return status; + } + + class WifiNanIfaceEventCallback + : public ::android::hardware::wifi::V1_2::IWifiNanIfaceEventCallback { + WifiNanIfaceHidlTest& parent_; + + public: + WifiNanIfaceEventCallback(WifiNanIfaceHidlTest& parent) + : parent_(parent){}; + + virtual ~WifiNanIfaceEventCallback() = default; + + Return notifyCapabilitiesResponse( + uint16_t id, const WifiNanStatus& status, + const NanCapabilities& capabilities) override { + parent_.callbackType = NOTIFY_CAPABILITIES_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.capabilities = capabilities; + + parent_.notify(); + return Void(); + } + + Return notifyEnableResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_ENABLE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyConfigResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_CONFIG_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyDisableResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_DISABLE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyStartPublishResponse(uint16_t id, + const WifiNanStatus& status, + uint8_t sessionId) override { + parent_.callbackType = NOTIFY_START_PUBLISH_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.sessionId = sessionId; + + parent_.notify(); + return Void(); + } + + Return notifyStopPublishResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_STOP_PUBLISH_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyStartSubscribeResponse(uint16_t id, + const WifiNanStatus& status, + uint8_t sessionId) override { + parent_.callbackType = NOTIFY_START_SUBSCRIBE_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.sessionId = sessionId; + + parent_.notify(); + return Void(); + } + + Return notifyStopSubscribeResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_STOP_SUBSCRIBE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyTransmitFollowupResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyCreateDataInterfaceResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyDeleteDataInterfaceResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyInitiateDataPathResponse( + uint16_t id, const WifiNanStatus& status, + uint32_t ndpInstanceId) override { + parent_.callbackType = NOTIFY_INITIATE_DATA_PATH_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.ndpInstanceId = ndpInstanceId; + + parent_.notify(); + return Void(); + } + + Return notifyRespondToDataPathIndicationResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = + NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyTerminateDataPathResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_TERMINATE_DATA_PATH_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventClusterEvent( + const NanClusterEventInd& event) override { + parent_.callbackType = EVENT_CLUSTER_EVENT; + + parent_.nanClusterEventInd = event; + + parent_.notify(); + return Void(); + } + + Return eventDisabled(const WifiNanStatus& status) override { + parent_.callbackType = EVENT_DISABLED; + + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventPublishTerminated( + uint8_t sessionId, const WifiNanStatus& status) override { + parent_.callbackType = EVENT_PUBLISH_TERMINATED; + + parent_.sessionId = sessionId; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventSubscribeTerminated( + uint8_t sessionId, const WifiNanStatus& status) override { + parent_.callbackType = EVENT_SUBSCRIBE_TERMINATED; + + parent_.sessionId = sessionId; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventMatch(const NanMatchInd& event) override { + parent_.callbackType = EVENT_MATCH; + + parent_.nanMatchInd = event; + + parent_.notify(); + return Void(); + } + + Return eventMatchExpired(uint8_t discoverySessionId, + uint32_t peerId) override { + parent_.callbackType = EVENT_MATCH_EXPIRED; + + parent_.sessionId = discoverySessionId; + parent_.peerId = peerId; + + parent_.notify(); + return Void(); + } + + Return eventFollowupReceived( + const NanFollowupReceivedInd& event) override { + parent_.callbackType = EVENT_FOLLOWUP_RECEIVED; + + parent_.nanFollowupReceivedInd = event; + + parent_.notify(); + return Void(); + } + + Return eventTransmitFollowup( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = EVENT_TRANSMIT_FOLLOWUP; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventDataPathRequest( + const NanDataPathRequestInd& event) override { + parent_.callbackType = EVENT_DATA_PATH_REQUEST; + + parent_.nanDataPathRequestInd = event; + + parent_.notify(); + return Void(); + } + + Return eventDataPathConfirm( + const ::android::hardware::wifi::V1_0::NanDataPathConfirmInd& event) + override { + parent_.callbackType = EVENT_DATA_PATH_CONFIRM; + + parent_.nanDataPathConfirmInd = event; + + parent_.notify(); + return Void(); + } + + Return eventDataPathTerminated(uint32_t ndpInstanceId) override { + parent_.callbackType = EVENT_DATA_PATH_TERMINATED; + + parent_.ndpInstanceId = ndpInstanceId; + + parent_.notify(); + return Void(); + } + + Return eventDataPathConfirm_1_2( + const ::android::hardware::wifi::V1_2::NanDataPathConfirmInd& event) + override { + parent_.callbackType = EVENT_DATA_PATH_CONFIRM_1_2; + + parent_.nanDataPathConfirmInd_1_2 = event; + + parent_.notify(); + return Void(); + } + + Return eventDataPathScheduleUpdate( + const NanDataPathScheduleUpdateInd& event) override { + parent_.callbackType = EVENT_DATA_PATH_SCHEDULE_UPDATE; + + parent_.nanDataPathScheduleUpdateInd = event; + + parent_.notify(); + return Void(); + } + }; + + private: + // synchronization objects + std::mutex mtx_; + std::condition_variable cv_; + int count_; + + protected: + android::sp<::android::hardware::wifi::V1_2::IWifiNanIface> iwifiNanIface; + + // Data from IWifiNanIfaceEventCallback callbacks: this is the collection of + // all arguments to all callbacks. They are set by the callback + // (notifications or events) and can be retrieved by tests. + CallbackType callbackType; + uint16_t id; + WifiNanStatus status; + NanCapabilities capabilities; + uint8_t sessionId; + uint32_t ndpInstanceId; + NanClusterEventInd nanClusterEventInd; + NanMatchInd nanMatchInd; + uint32_t peerId; + NanFollowupReceivedInd nanFollowupReceivedInd; + NanDataPathRequestInd nanDataPathRequestInd; + ::android::hardware::wifi::V1_0::NanDataPathConfirmInd + nanDataPathConfirmInd; + ::android::hardware::wifi::V1_2::NanDataPathConfirmInd + nanDataPathConfirmInd_1_2; + NanDataPathScheduleUpdateInd nanDataPathScheduleUpdateInd; +}; + +/* + * Create: + * Ensures that an instance of the IWifiNanIface proxy object is + * successfully created. + */ +TEST(WifiNanIfaceHidlTestNoFixture, Create) { + ASSERT_NE(nullptr, getWifiNanIface_1_2().get()); + stopWifi(); +} + +/* + * enableRequest_1_2InvalidArgs: validate that fails with invalid arguments + */ +TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2InvalidArgs) { + uint16_t inputCmdId = 10; + NanEnableRequest nanEnableRequest = {}; + NanConfigRequestSupplemental nanConfigRequestSupp = {}; + ASSERT_EQ(WifiStatusCode::SUCCESS, + HIDL_INVOKE(iwifiNanIface, enableRequest_1_2, inputCmdId, + nanEnableRequest, nanConfigRequestSupp) + .code); + // wait for a callback + ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE)); + ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callbackType); + ASSERT_EQ(id, inputCmdId); + ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS); +} + +/* + * enableRequest_1_2ShimInvalidArgs: validate that fails with invalid arguments + * to the shim + */ +TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2ShimInvalidArgs) { + uint16_t inputCmdId = 10; + NanEnableRequest nanEnableRequest = {}; + nanEnableRequest.configParams.numberOfPublishServiceIdsInBeacon = + 128; // must be <= 127 + NanConfigRequestSupplemental nanConfigRequestSupp = {}; + ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, + HIDL_INVOKE(iwifiNanIface, enableRequest_1_2, inputCmdId, + nanEnableRequest, nanConfigRequestSupp) + .code); +} + +/* + * configRequest_1_2InvalidArgs: validate that fails with invalid arguments + */ +TEST_F(WifiNanIfaceHidlTest, configRequest_1_2InvalidArgs) { + uint16_t inputCmdId = 10; + NanConfigRequest nanConfigRequest = {}; + NanConfigRequestSupplemental nanConfigRequestSupp = {}; + ASSERT_EQ(WifiStatusCode::SUCCESS, + HIDL_INVOKE(iwifiNanIface, configRequest_1_2, inputCmdId, + nanConfigRequest, nanConfigRequestSupp) + .code); + // wait for a callback + ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CONFIG_RESPONSE)); + ASSERT_EQ(NOTIFY_CONFIG_RESPONSE, callbackType); + ASSERT_EQ(id, inputCmdId); + ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS); +} + +/* + * configRequest_1_2ShimInvalidArgs: validate that fails with invalid arguments + * to the shim + */ +TEST_F(WifiNanIfaceHidlTest, configRequest_1_2ShimInvalidArgs) { + uint16_t inputCmdId = 10; + NanConfigRequest nanConfigRequest = {}; + nanConfigRequest.numberOfPublishServiceIdsInBeacon = 128; // must be <= 127 + NanConfigRequestSupplemental nanConfigRequestSupp = {}; + ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, + HIDL_INVOKE(iwifiNanIface, configRequest_1_2, inputCmdId, + nanConfigRequest, nanConfigRequestSupp) + .code); +}