Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80054133 authored by Etan Cohen's avatar Etan Cohen
Browse files

[AWARE] VTS baseline

Modified Wi-Fi test setup/tear-down to shutdown and start the
Android framework. The framework competes with the VTS to control
the HAL and so must be disabled for the duration of the test.

Added framework to support VTS testing with the Wi-Fi Aware (NAN)
interface.

Added all callback types (notifications, events) with ability to
wait for such callbacks.

Bug: 35276551
Test: gtest pass
Change-Id: I50847fccad457c2b225ba7f2e1760b4dbb4d363f
parent b59f873a
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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<IWifi> getWifi() {
    sp<IWifi> wifi = ::testing::VtsHalHidlTargetBaseTest::getService<IWifi>();
+453 −7
Original line number Diff line number Diff line
@@ -17,24 +17,427 @@
#include <android-base/logging.h>

#include <android/hardware/wifi/1.0/IWifiNanIface.h>
#include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>

#include <VtsHalHidlTargetBaseTest.h>
#include <chrono>
#include <condition_variable>
#include <mutex>

#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 {}
    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();
    }

    /* Used as a mechanism to inform the test about data/event callback */
    inline void notify() {
      std::unique_lock<std::mutex> 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<std::mutex> 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<void> 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<void> notifyEnableResponse(
            uint16_t id,
            const WifiNanStatus& status) override {
        parent_.callbackType = NOTIFY_ENABLE_RESPONSE;

        parent_.id = id;
        parent_.status = status;

        parent_.notify();
        return Void();
      }

      Return<void> notifyConfigResponse(
            uint16_t id,
            const WifiNanStatus& status) override {
        parent_.callbackType = NOTIFY_CONFIG_RESPONSE;

        parent_.id = id;
        parent_.status = status;

        parent_.notify();
        return Void();
      }

      Return<void> notifyDisableResponse(
            uint16_t id,
            const WifiNanStatus& status) override {
        parent_.callbackType = NOTIFY_DISABLE_RESPONSE;

        parent_.id = id;
        parent_.status = status;

        parent_.notify();
        return Void();
      }

      Return<void> 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<void> 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<void> 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<void> 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<void> 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<void> 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<void> 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<void> notifyInitiateDataPathResponse(
            uint16_t id,
            const WifiNanStatus& status,
            uint32_t ndpInstanceId) override {
        parent_.callbackType = NOTIFY_INITIATE_DATA_PATH_RESPONSE;

    virtual void TearDown() override { stopWifi(); }
        parent_.id = id;
        parent_.status = status;
        parent_.ndpInstanceId = ndpInstanceId;

        parent_.notify();
        return Void();
      }

      Return<void> 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<void> 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<void> eventClusterEvent(
            const NanClusterEventInd& event) override {
        parent_.callbackType = EVENT_CLUSTER_EVENT;

        parent_.nanClusterEventInd = event;

        parent_.notify();
        return Void();
      }

      Return<void> eventDisabled(
            const WifiNanStatus& status) override {
        parent_.callbackType = EVENT_DISABLED;

        parent_.status = status;

        parent_.notify();
        return Void();
      }

      Return<void> eventPublishTerminated(
            uint8_t sessionId,
            const WifiNanStatus& status) override {
        parent_.callbackType = EVENT_PUBLISH_TERMINATED;

        parent_.sessionId = sessionId;
        parent_.status = status;

        parent_.notify();
        return Void();
      }

      Return<void> eventSubscribeTerminated(
            uint8_t sessionId,
            const WifiNanStatus& status) override {
        parent_.callbackType = EVENT_SUBSCRIBE_TERMINATED;

        parent_.sessionId = sessionId;
        parent_.status = status;

        parent_.notify();
        return Void();
      }

      Return<void> eventMatch(
            const NanMatchInd& event) override {
        parent_.callbackType = EVENT_MATCH;

        parent_.nanMatchInd = event;

        parent_.notify();
        return Void();
      }

      Return<void> eventMatchExpired(
            uint8_t discoverySessionId,
            uint32_t peerId) override {
        parent_.callbackType = EVENT_MATCH_EXPIRED;

        parent_.sessionId = discoverySessionId;
        parent_.peerId = peerId;

        parent_.notify();
        return Void();
      }

      Return<void> eventFollowupReceived(
            const NanFollowupReceivedInd& event) override {
        parent_.callbackType = EVENT_FOLLOWUP_RECEIVED;

        parent_.nanFollowupReceivedInd = event;

        parent_.notify();
        return Void();
      }

      Return<void> eventTransmitFollowup(
            uint16_t id,
            const WifiNanStatus& status) override {
        parent_.callbackType = EVENT_TRANSMIT_FOLLOWUP;

        parent_.id = id;
        parent_.status = status;

        parent_.notify();
        return Void();
      }

      Return<void> eventDataPathRequest(
            const NanDataPathRequestInd& event) override {
        parent_.callbackType = EVENT_DATA_PATH_REQUEST;

        parent_.nanDataPathRequestInd = event;

        parent_.notify();
        return Void();
      }

      Return<void> eventDataPathConfirm(
            const NanDataPathConfirmInd& event) override {
        parent_.callbackType = EVENT_DATA_PATH_CONFIRM;

        parent_.nanDataPathConfirmInd = event;

        parent_.notify();
        return Void();
      }

      Return<void> 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> 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());
  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> 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);
}