diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp index 9042075eb6..e0c92fe104 100644 --- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp +++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp @@ -36,11 +36,12 @@ using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; void stopFramework() { - ASSERT_EQ(std::system("svc wifi disable"), 0); + ASSERT_EQ(std::system("stop"), 0); + stopWifi(); sleep(5); } -void startFramework() { ASSERT_EQ(std::system("svc wifi enable"), 0); } +void startFramework() { ASSERT_EQ(std::system("start"), 0); } sp getWifi() { sp wifi = ::testing::VtsHalHidlTargetBaseTest::getService(); diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp index eb482c9f53..95c0e5daa5 100644 --- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -17,24 +17,427 @@ #include #include +#include #include +#include +#include +#include +#include "wifi_hidl_call_util.h" #include "wifi_hidl_test_utils.h" -using ::android::hardware::wifi::V1_0::IWifiNanIface; +using namespace ::android::hardware::wifi::V1_0; + +using ::android::hardware::Return; +using ::android::hardware::Void; using ::android::sp; +#define TIMEOUT_PERIOD 10 + /** * Fixture to use for all NAN Iface HIDL interface tests. */ class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetBaseTest { - public: - virtual void SetUp() override {} + public: + virtual void SetUp() override { + iwifiNanIface = getWifiNanIface(); + ASSERT_NE(nullptr, iwifiNanIface.get()); + ASSERT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, registerEventCallback, + new WifiNanIfaceEventCallback(*this)).code); + } - virtual void TearDown() override { stopWifi(); } + virtual void TearDown() override { + stopWifi(); + } - protected: + /* 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 + }; + + /* 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 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 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(); + } + }; + + private: + // synchronization objects + std::mutex mtx_; + std::condition_variable cv_; + int count_; + + protected: + android::sp 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; + NanDataPathConfirmInd nanDataPathConfirmInd; }; /* @@ -43,6 +446,49 @@ class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetBaseTest { * successfully created. */ TEST(WifiNanIfaceHidlTestNoFixture, Create) { - EXPECT_NE(nullptr, getWifiNanIface().get()); - stopWifi(); + ASSERT_NE(nullptr, getWifiNanIface().get()); + stopWifi(); +} + +/* + * Fail: use past destruction + * Ensure that API calls fail with ERROR_WIFI_IFACE_INVALID when using an interface once wifi + * is disabled. + */ +TEST(WifiNanIfaceHidlTestNoFixture, FailOnIfaceInvalid) { + android::sp iwifiNanIface = getWifiNanIface(); + ASSERT_NE(nullptr, iwifiNanIface.get()); + stopWifi(); + sleep(5); // make sure that all chips/interfaces are invalidated + ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, 0).code); +} + +/* + * getCapabilitiesRequest: validate that returns capabilities. + */ +TEST_F(WifiNanIfaceHidlTest, getCapabilitiesRequest) { + uint16_t inputCmdId = 10; + ASSERT_EQ(WifiStatusCode::SUCCESS, + HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code); + // wait for a callback + ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE)); + ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callbackType); + ASSERT_EQ(id, inputCmdId); + + // check for reasonable capability values + EXPECT_GT(capabilities.maxConcurrentClusters, (unsigned int) 0); + EXPECT_GT(capabilities.maxPublishes, (unsigned int) 0); + EXPECT_GT(capabilities.maxSubscribes, (unsigned int) 0); + EXPECT_EQ(capabilities.maxServiceNameLen, (unsigned int) 255); + EXPECT_EQ(capabilities.maxMatchFilterLen, (unsigned int) 255); + EXPECT_GT(capabilities.maxTotalMatchFilterLen, (unsigned int) 255); + EXPECT_EQ(capabilities.maxServiceSpecificInfoLen, (unsigned int) 255); + EXPECT_GE(capabilities.maxExtendedServiceSpecificInfoLen, (unsigned int) 255); + EXPECT_GT(capabilities.maxNdiInterfaces, (unsigned int) 0); + EXPECT_GT(capabilities.maxNdpSessions, (unsigned int) 0); + EXPECT_GT(capabilities.maxAppInfoLen, (unsigned int) 0); + EXPECT_GT(capabilities.maxQueuedTransmitFollowupMsgs, (unsigned int) 0); + EXPECT_GT(capabilities.maxSubscribeInterfaceAddresses, (unsigned int) 0); + EXPECT_NE(capabilities.supportedCipherSuites, (unsigned int) 0); }