Merge "Move FMQ tests to hardware/interfaces"
diff --git a/bluetooth/1.0/default/async_fd_watcher.cc b/bluetooth/1.0/default/async_fd_watcher.cc
index 287d007..2f23a69 100644
--- a/bluetooth/1.0/default/async_fd_watcher.cc
+++ b/bluetooth/1.0/default/async_fd_watcher.cc
@@ -19,6 +19,7 @@
 #include <algorithm>
 #include <atomic>
 #include <condition_variable>
+#include <map>
 #include <mutex>
 #include <thread>
 #include <vector>
@@ -26,6 +27,8 @@
 #include "sys/select.h"
 #include "unistd.h"
 
+static const int INVALID_FD = -1;
+
 namespace android {
 namespace hardware {
 namespace bluetooth {
@@ -36,8 +39,7 @@
   // Add file descriptor and callback
   {
     std::unique_lock<std::mutex> guard(internal_mutex_);
-    read_fd_ = file_descriptor;
-    cb_ = on_read_fd_ready_callback;
+    watched_fds_[file_descriptor] = on_read_fd_ready_callback;
   }
 
   // Start the thread if not started yet
@@ -58,7 +60,7 @@
   return 0;
 }
 
-void AsyncFdWatcher::StopWatchingFileDescriptor() { stopThread(); }
+void AsyncFdWatcher::StopWatchingFileDescriptors() { stopThread(); }
 
 AsyncFdWatcher::~AsyncFdWatcher() {}
 
@@ -90,8 +92,7 @@
 
   {
     std::unique_lock<std::mutex> guard(internal_mutex_);
-    cb_ = nullptr;
-    read_fd_ = -1;
+    watched_fds_.clear();
   }
 
   {
@@ -115,7 +116,11 @@
     fd_set read_fds;
     FD_ZERO(&read_fds);
     FD_SET(notification_listen_fd_, &read_fds);
-    FD_SET(read_fd_, &read_fds);
+    int max_read_fd = INVALID_FD;
+    for (auto& it : watched_fds_) {
+      FD_SET(it.first, &read_fds);
+      max_read_fd = std::max(max_read_fd, it.first);
+    }
 
     struct timeval timeout;
     struct timeval* timeout_ptr = NULL;
@@ -126,7 +131,7 @@
     }
 
     // Wait until there is data available to read on some FD.
-    int nfds = std::max(notification_listen_fd_, read_fd_);
+    int nfds = std::max(notification_listen_fd_, max_read_fd);
     int retval = select(nfds + 1, &read_fds, NULL, NULL, timeout_ptr);
 
     // There was some error.
@@ -153,10 +158,21 @@
       continue;
     }
 
-    // Invoke the data ready callback if appropriate.
-    if (FD_ISSET(read_fd_, &read_fds)) {
+    // Invoke the data ready callbacks if appropriate.
+    std::vector<decltype(watched_fds_)::value_type> saved_callbacks;
+    {
       std::unique_lock<std::mutex> guard(internal_mutex_);
-      if (cb_) cb_(read_fd_);
+      for (auto& it : watched_fds_) {
+        if (FD_ISSET(it.first, &read_fds)) {
+          saved_callbacks.push_back(it);
+        }
+      }
+    }
+
+    for (auto& it : saved_callbacks) {
+      if (it.second) {
+        it.second(it.first);
+      }
     }
   }
 }
diff --git a/bluetooth/1.0/default/async_fd_watcher.h b/bluetooth/1.0/default/async_fd_watcher.h
index 3f7ff54..358cbc3 100644
--- a/bluetooth/1.0/default/async_fd_watcher.h
+++ b/bluetooth/1.0/default/async_fd_watcher.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <map>
 #include <mutex>
 #include <thread>
 
@@ -36,7 +37,7 @@
                                  const ReadCallback& on_read_fd_ready_callback);
   int ConfigureTimeout(const std::chrono::milliseconds timeout,
                        const TimeoutCallback& on_timeout_callback);
-  void StopWatchingFileDescriptor();
+  void StopWatchingFileDescriptors();
 
  private:
   AsyncFdWatcher(const AsyncFdWatcher&) = delete;
@@ -52,10 +53,9 @@
   std::mutex internal_mutex_;
   std::mutex timeout_mutex_;
 
-  int read_fd_;
+  std::map<int, ReadCallback> watched_fds_;
   int notification_listen_fd_;
   int notification_write_fd_;
-  ReadCallback cb_;
   TimeoutCallback timeout_cb_;
   std::chrono::milliseconds timeout_ms_;
 };
diff --git a/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc b/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc
index a7f5bda..b0c533c 100644
--- a/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc
+++ b/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc
@@ -14,6 +14,8 @@
 // limitations under the License.
 //
 
+#define LOG_TAG "async_fd_watcher_unittest"
+
 #include "async_fd_watcher.h"
 #include <gtest/gtest.h>
 #include <cstdint>
@@ -122,8 +124,8 @@
   }
 
   void CleanUpServer() {
-    async_fd_watcher_.StopWatchingFileDescriptor();
-    conn_watcher_.StopWatchingFileDescriptor();
+    async_fd_watcher_.StopWatchingFileDescriptors();
+    conn_watcher_.StopWatchingFileDescriptors();
     close(socket_fd_);
   }
 
@@ -211,7 +213,7 @@
   });
 
   ConnectClient();
-  conn_watcher.StopWatchingFileDescriptor();
+  conn_watcher.StopWatchingFileDescriptors();
   close(socket_fd);
 }
 
@@ -233,7 +235,7 @@
   EXPECT_FALSE(timed_out);
   sleep(1);
   EXPECT_TRUE(timed_out);
-  conn_watcher.StopWatchingFileDescriptor();
+  conn_watcher.StopWatchingFileDescriptors();
   close(socket_fd);
 }
 
@@ -265,10 +267,64 @@
   sleep(1);
   EXPECT_TRUE(timed_out);
   EXPECT_TRUE(timed_out2);
-  conn_watcher.StopWatchingFileDescriptor();
+  conn_watcher.StopWatchingFileDescriptors();
   close(socket_fd);
 }
 
+// Use a single AsyncFdWatcher to watch two file descriptors.
+TEST_F(AsyncFdWatcherSocketTest, WatchTwoFileDescriptors) {
+  int sockfd[2];
+  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
+  bool cb1_called = false;
+  bool* cb1_called_ptr = &cb1_called;
+  bool cb2_called = false;
+  bool* cb2_called_ptr = &cb2_called;
+
+  AsyncFdWatcher watcher;
+  watcher.WatchFdForNonBlockingReads(sockfd[0], [cb1_called_ptr](int fd) {
+    char read_buf[1] = {0};
+    int n = TEMP_FAILURE_RETRY(read(fd, read_buf, sizeof(read_buf)));
+    ASSERT_TRUE(n == sizeof(read_buf));
+    ASSERT_TRUE(read_buf[0] == '1');
+    *cb1_called_ptr = true;
+  });
+
+  watcher.WatchFdForNonBlockingReads(sockfd[1], [cb2_called_ptr](int fd) {
+    char read_buf[1] = {0};
+    int n = TEMP_FAILURE_RETRY(read(fd, read_buf, sizeof(read_buf)));
+    ASSERT_TRUE(n == sizeof(read_buf));
+    ASSERT_TRUE(read_buf[0] == '2');
+    *cb2_called_ptr = true;
+  });
+
+  // Fail if the test doesn't pass within 3 seconds
+  watcher.ConfigureTimeout(std::chrono::seconds(3), [this]() {
+    bool connection_timeout = true;
+    ASSERT_FALSE(connection_timeout);
+  });
+
+  EXPECT_FALSE(cb1_called);
+  EXPECT_FALSE(cb2_called);
+
+  char one_buf[1] = {'1'};
+  TEMP_FAILURE_RETRY(write(sockfd[1], one_buf, sizeof(one_buf)));
+
+  sleep(1);
+
+  EXPECT_TRUE(cb1_called);
+  EXPECT_FALSE(cb2_called);
+
+  char two_buf[1] = {'2'};
+  TEMP_FAILURE_RETRY(write(sockfd[0], two_buf, sizeof(two_buf)));
+
+  sleep(1);
+
+  EXPECT_TRUE(cb1_called);
+  EXPECT_TRUE(cb2_called);
+
+  watcher.StopWatchingFileDescriptors();
+}
+
 // Use two AsyncFdWatchers to set up a server socket.
 TEST_F(AsyncFdWatcherSocketTest, ClientServer) {
   ConfigureServer();
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index 3878129..2c55d1c 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -274,7 +274,7 @@
 }
 
 void VendorInterface::Close() {
-  fd_watcher_.StopWatchingFileDescriptor();
+  fd_watcher_.StopWatchingFileDescriptors();
 
   if (lib_interface_ != nullptr) {
     bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
diff --git a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
index 5b6089d..4aa6d7e 100644
--- a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
+++ b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
@@ -325,18 +325,42 @@
 }
 
 /*
+ * PowerCycleAfterClose:
+ * Calls powerCycle() after close()
+ * Checks status
+ */
+TEST_F(NfcHidlTest, PowerCycleAfterClose) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->close());
+  // Wait for CLOSE_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::CLOSE_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+
+  EXPECT_EQ(NfcStatus::FAILED, nfc_->powerCycle());
+
+  EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+  // Wait for OPEN_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::OPEN_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+}
+
+/*
  * CoreInitialized:
- * Calls coreInitialized()
+ * Calls coreInitialized() with different data
  * Waits for NfcEvent.POST_INIT_CPLT
  */
 TEST_F(NfcHidlTest, CoreInitialized) {
   NfcData data;
   data.resize(1);
-  data[0] = 0;
-  EXPECT_EQ(NfcStatus::OK, nfc_->coreInitialized(data));
-  // Wait for NfcEvent.POST_INIT_CPLT
-  EXPECT_EQ(std::cv_status::no_timeout, wait());
-  EXPECT_EQ(NfcEvent::POST_INIT_CPLT, last_event_);
+  for (int i = 0; i <= 6; i++)
+  {
+    data[0] = i;
+    EXPECT_EQ(NfcStatus::OK, nfc_->coreInitialized(data));
+    // Wait for NfcEvent.POST_INIT_CPLT
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(NfcEvent::POST_INIT_CPLT, last_event_);
+  }
 }
 
 /*
@@ -348,6 +372,27 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->controlGranted());
 }
 
+/*
+ * ControlGrantedAfterClose:
+ * Call controlGranted() after close
+ * Checks the return value
+ */
+TEST_F(NfcHidlTest, ControlGrantedAfterClose) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->close());
+  // Wait for CLOSE_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::CLOSE_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+
+  EXPECT_EQ(NfcStatus::OK, nfc_->controlGranted());
+
+  EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+  // Wait for OPEN_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::OPEN_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+}
+
 /* PreDiscover:
  * Calls prediscover()
  * Checks the return value
@@ -356,6 +401,59 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->prediscover());
 }
 
+/*
+ * PreDiscoverAfterClose:
+ * Call prediscover() after close
+ * Checks the return value
+ */
+TEST_F(NfcHidlTest, PreDiscoverAfterClose) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->close());
+  // Wait for CLOSE_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::CLOSE_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+
+  EXPECT_EQ(NfcStatus::OK, nfc_->prediscover());
+
+  EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+  // Wait for OPEN_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::OPEN_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+}
+
+/*
+ * CloseAfterClose:
+ * Calls close() multiple times
+ * Checks status
+ */
+TEST_F(NfcHidlTest, CloseAfterClose) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->close());
+  // Wait for CLOSE_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::CLOSE_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+
+  EXPECT_EQ(NfcStatus::FAILED, nfc_->close());
+
+  EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+  // Wait for OPEN_CPLT event
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::OPEN_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+}
+
+
+/*
+ * OpenAfterOpen:
+ * Calls open() multiple times
+ * Checks status
+ */
+TEST_F(NfcHidlTest, OpenAfterOpen) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+  EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+}
+
 int main(int argc, char** argv) {
   ::testing::AddGlobalTestEnvironment(new NfcHidlEnvironment);
   ::testing::InitGoogleTest(&argc, argv);
diff --git a/radio/1.0/IRadio.hal b/radio/1.0/IRadio.hal
index a8c9d93..b3e3e98 100644
--- a/radio/1.0/IRadio.hal
+++ b/radio/1.0/IRadio.hal
@@ -731,20 +731,6 @@
     oneway getDataCallList(int32_t serial);
 
     /*
-     * Indicates the current state of the screen. When the screen is off, the
-     * Radio must notify the baseband to suppress certain notifications (eg,
-     * signal strength and changes in LAC/CID or BID/SID/NID/latitude/longitude)
-     * in an effort to conserve power. These notifications must resume when the
-     * screen is on.
-     *
-     * @param serial Serial number of request.
-     * @param enable true = screen on, false = screen off.
-     *
-     * Response function is IRadioResponse.sendScreenStateResponse()
-     */
-    oneway sendScreenState(int32_t serial, bool enable);
-
-    /*
      * Enables/disables supplementary service related notifications from the network.
      * Notifications are reported via unsolSuppSvcNotification().
      *
diff --git a/radio/1.0/IRadioResponse.hal b/radio/1.0/IRadioResponse.hal
index 11a1d03..cd0899a 100644
--- a/radio/1.0/IRadioResponse.hal
+++ b/radio/1.0/IRadioResponse.hal
@@ -928,17 +928,6 @@
      *   RadioError:NONE
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:INVALID_ARGUMENTS
-     *   RadioError:GENERIC_FAILURE
-     */
-    oneway sendScreenStateResponse(RadioResponseInfo info);
-
-    /*
-     * @param info Response info struct containing response type, serial no. and error
-     *
-     * Valid errors returned:
-     *   RadioError:NONE
-     *   RadioError:RADIO_NOT_AVAILABLE
-     *   RadioError:INVALID_ARGUMENTS
      *   RadioError:SIM_BUSY
      *   RadioError:NO_MEMORY
      *   RadioError:SYSTEM_ERR
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_utils.h b/radio/1.0/vts/functional/radio_hidl_hal_utils.h
index 0429226..1c58a97 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/radio_hidl_hal_utils.h
@@ -234,8 +234,6 @@
     Return<void> sendOemRilRequestStringsResponse(const RadioResponseInfo& info,
             const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& data);
 
-    Return<void> sendScreenStateResponse(const RadioResponseInfo& info);
-
     Return<void> setSuppServiceNotificationsResponse(
             const RadioResponseInfo& info);
 
diff --git a/radio/1.0/vts/functional/radio_response.cpp b/radio/1.0/vts/functional/radio_response.cpp
index 2b4f10f..64b09c9 100644
--- a/radio/1.0/vts/functional/radio_response.cpp
+++ b/radio/1.0/vts/functional/radio_response.cpp
@@ -314,11 +314,6 @@
     return Void();
 }
 
-Return<void> RadioResponse::sendScreenStateResponse(
-        const RadioResponseInfo& /*info*/) {
-    return Void();
-}
-
 Return<void> RadioResponse::setSuppServiceNotificationsResponse(
         const RadioResponseInfo& /*info*/) {
     return Void();
diff --git a/wifi/1.0/default/android.hardware.wifi@1.0-service.rc b/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
index c0ae4d4..696b1f9 100644
--- a/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
@@ -1,4 +1,4 @@
 service wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
     class hal
     user wifi
-    group wifi
+    group wifi gps
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 9042075..e0c92fe 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_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>();
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 eb482c9..95c0e5d 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 <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 {}
+  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<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;
+
+        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 @@
  * 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> 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);
 }