Merge "Add test for type resolution."
diff --git a/nfc/1.0/default/Nfc.cpp b/nfc/1.0/default/Nfc.cpp
index 0759605..9d05fc2 100644
--- a/nfc/1.0/default/Nfc.cpp
+++ b/nfc/1.0/default/Nfc.cpp
@@ -51,21 +51,21 @@
 }
 
 
-INfc* HIDL_FETCH_INfc(const char *hal) {
+INfc* HIDL_FETCH_INfc(const char * /*name*/) {
     nfc_nci_device_t* nfc_device;
     int ret = 0;
     const hw_module_t* hw_module = NULL;
 
-    ret = hw_get_module (hal, &hw_module);
+    ret = hw_get_module (NFC_NCI_HARDWARE_MODULE_ID, &hw_module);
     if (ret == 0)
     {
         ret = nfc_nci_open (hw_module, &nfc_device);
         if (ret != 0) {
-            ALOGE ("nfc_nci_open %s failed: %d", hal, ret);
+            ALOGE ("nfc_nci_open failed: %d", ret);
         }
     }
     else
-        ALOGE ("hw_get_module %s failed: %d", hal, ret);
+        ALOGE ("hw_get_module failed: %d", ret);
 
     if (ret == 0) {
         return new Nfc(nfc_device);
diff --git a/nfc/1.0/vts/Android.mk b/nfc/1.0/vts/Android.mk
new file mode 100644
index 0000000..60cc723
--- /dev/null
+++ b/nfc/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/nfc/1.0/vts/Nfc.vts b/nfc/1.0/vts/Nfc.vts
new file mode 100644
index 0000000..5882bf5
--- /dev/null
+++ b/nfc/1.0/vts/Nfc.vts
@@ -0,0 +1,133 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "INfc"
+
+package: "android.hardware.nfc"
+
+import: "android.hardware.nfc@1.0::INfcClientCallback"
+import: "android.hardware.nfc@1.0::types"
+
+interface: {
+    api: {
+        name: "open"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::nfc::V1_0::NfcStatus"
+        }
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "INfcClientCallback"
+            is_callback: true
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            next: "write"
+            next: "coreInitialized"
+            next: "prediscover"
+            next: "powerCycle"
+            next: "controlGranted"
+        }
+    }
+
+    api: {
+        name: "write"
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+        callflow: {
+            next: "write"
+            next: "prediscover"
+            next: "coreInitialized"
+            next: "close"
+            next: "powerCycle"
+            next: "controlGranted"
+        }
+    }
+
+    api: {
+        name: "coreInitialized"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::nfc::V1_0::NfcStatus"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+        callflow: {
+            next: "write"
+            next: "prediscover"
+            next: "close"
+        }
+    }
+
+    api: {
+        name: "prediscover"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::nfc::V1_0::NfcStatus"
+        }
+        callflow: {
+            next: "write"
+            next: "close"
+            next: "coreInitialized"
+            next: "powerCycle"
+            next: "controlGranted"
+        }
+    }
+
+    api: {
+        name: "close"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::nfc::V1_0::NfcStatus"
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+    api: {
+        name: "controlGranted"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::nfc::V1_0::NfcStatus"
+        }
+        callflow: {
+            next: "write"
+            next: "close"
+            next: "prediscover"
+            next: "coreInitialized"
+            next: "powerCycle"
+        }
+    }
+
+    api: {
+        name: "powerCycle"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::nfc::V1_0::NfcStatus"
+        }
+        callflow: {
+            next: "write"
+            next: "coreInitialized"
+            next: "prediscover"
+            next: "controlGranted"
+            next: "close"
+        }
+    }
+
+}
diff --git a/nfc/1.0/vts/NfcClientCallback.vts b/nfc/1.0/vts/NfcClientCallback.vts
new file mode 100644
index 0000000..e2a3e5b
--- /dev/null
+++ b/nfc/1.0/vts/NfcClientCallback.vts
@@ -0,0 +1,33 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "INfcClientCallback"
+
+package: "android.hardware.nfc"
+
+import: "android.hardware.nfc@1.0::types"
+
+interface: {
+    api: {
+        name: "sendEvent"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "NfcEvent"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "NfcStatus"
+        }
+    }
+
+    api: {
+        name: "sendData"
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+}
diff --git a/nfc/1.0/vts/functional/Android.bp b/nfc/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..021f7c1
--- /dev/null
+++ b/nfc/1.0/vts/functional/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache 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.
+//
+
+cc_test {
+    name: "nfc_hidl_hal_test",
+    gtest: true,
+    srcs: ["nfc_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.nfc@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
diff --git a/nfc/1.0/vts/functional/nfc_hidl_hal_test.cpp b/nfc/1.0/vts/functional/nfc_hidl_hal_test.cpp
new file mode 100644
index 0000000..f5ed4d7
--- /dev/null
+++ b/nfc/1.0/vts/functional/nfc_hidl_hal_test.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache 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.
+ */
+
+#define LOG_TAG "nfc_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/nfc/1.0/INfc.h>
+#include <android/hardware/nfc/1.0/INfcClientCallback.h>
+#include <android/hardware/nfc/1.0/types.h>
+#include <hardware/nfc.h>
+
+#include <gtest/gtest.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+using ::android::hardware::nfc::V1_0::INfc;
+using ::android::hardware::nfc::V1_0::INfcClientCallback;
+using ::android::hardware::nfc::V1_0::NfcEvent;
+using ::android::hardware::nfc::V1_0::NfcStatus;
+using ::android::hardware::nfc::V1_0::NfcData;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+#define NFC_NCI_SERVICE_NAME "nfc_nci"
+
+/* NCI Commands */
+#define CORE_RESET_CMD \
+  { 0x20, 0x00, 0x01, 0x00 }
+#define CORE_CONN_CREATE_CMD \
+  { 0x20, 0x04, 0x02, 0x01, 0x00 }
+#define INVALID_COMMAND \
+  { 0x20, 0x00, 0x00 }
+#define FAULTY_DATA_PACKET \
+  { 0x00, 0x00, 0xFF }
+
+#define LOOP_BACK_HEADER_SIZE 3
+#define SYNTAX_ERROR 5
+#define NUMBER_LOOPS 3922
+#define VERSION 0x11
+#define TIMEOUT_PERIOD 5
+
+static bool passthrough = true;
+
+// The main test class for NFC HIDL HAL.
+class NfcHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    nfc_ = INfc::getService(NFC_NCI_SERVICE_NAME, passthrough);
+    ASSERT_NE(nfc_, nullptr);
+
+    nfc_cb_ = new NfcClientCallback(*this);
+    ASSERT_NE(nfc_cb_, nullptr);
+
+    count = 0;
+    last_event_ = NfcEvent::ERROR;
+    last_status_ = NfcStatus::FAILED;
+
+    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_);
+  }
+
+  virtual void TearDown() override {
+    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_);
+  }
+
+  /* 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();
+  }
+
+  /* Test code calls this function to wait for data/event callback */
+  inline std::cv_status wait() {
+    std::unique_lock<std::mutex> lock(mtx);
+
+    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;
+    }
+    count--;
+    return status;
+  }
+
+  /* Callback class for data & Event. */
+  class NfcClientCallback : public INfcClientCallback {
+    NfcHidlTest& parent_;
+
+   public:
+    NfcClientCallback(NfcHidlTest& parent) : parent_(parent){};
+
+    virtual ~NfcClientCallback() = default;
+
+    /* sendEvent callback function - Records the Event & Status
+     * and notifies the TEST
+     **/
+    Return<void> sendEvent(NfcEvent event, NfcStatus event_status) override {
+      parent_.last_event_ = event;
+      parent_.last_status_ = event_status;
+      parent_.notify();
+      return Void();
+    };
+
+    /* sendData callback function. Records the data and notifies the TEST*/
+    Return<void> sendData(const NfcData& data) override {
+      size_t size = parent_.last_data_.size();
+      parent_.last_data_.resize(size + 1);
+      parent_.last_data_[size] = data;
+      parent_.notify();
+      return Void();
+    };
+  };
+
+  sp<INfc> nfc_;
+  sp<INfcClientCallback> nfc_cb_;
+  NfcEvent last_event_;
+  NfcStatus last_status_;
+  hidl_vec<NfcData> last_data_;
+
+ private:
+  std::mutex mtx;
+  std::condition_variable cv;
+  int count;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class NfcHidlEnvironment : public ::testing::Environment {
+ public:
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+ private:
+};
+
+/*
+ * OpenAndClose:
+ * Makes an open call, waits for NfcEvent.OPEN_CPLT
+ * Immediately calls close() and waits for NfcEvent.CLOSE_CPLT
+ * Since open and close calls are a part of SetUp() and TearDown(),
+ * the function definition is intentionally kept empty
+ */
+TEST_F(NfcHidlTest, OpenAndClose) {}
+
+/*
+ * WriteCoreReset:
+ * Sends CORE_RESET_CMD
+ * Waits for CORE_RESET_RSP
+ * Checks the status and the version number
+ */
+TEST_F(NfcHidlTest, WriteCoreReset) {
+  std::vector<uint8_t> cmd = CORE_RESET_CMD;
+  NfcData data = cmd;
+  EXPECT_EQ(data.size(), nfc_->write(data));
+  // Wait for CORE_RESET_RSP
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(1ul, last_data_.size());
+  EXPECT_EQ(6ul, last_data_[0].size());
+  EXPECT_EQ((int)NfcStatus::OK, last_data_[0][3]);
+  EXPECT_GE(VERSION, last_data_[0][4]);
+}
+
+/*
+ * WriteInvalidCommand:
+ * Sends an invalid command
+ * Waits for response
+ * Checks SYNTAX_ERROR status
+ */
+TEST_F(NfcHidlTest, WriteInvalidCommand) {
+  // Send an Error Command
+  std::vector<uint8_t> cmd = INVALID_COMMAND;
+  NfcData data = cmd;
+  EXPECT_EQ(data.size(), nfc_->write(data));
+  // Wait for RSP
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(1ul, last_data_.size());
+  EXPECT_EQ(4ul, last_data_[0].size());
+  EXPECT_EQ(SYNTAX_ERROR, last_data_[0][3]);
+}
+
+/*
+ * WriteInvalidAndThenValidCommand:
+ * Sends an Faulty Data Packet
+ * Waits for CORE_INTERFACE_ERROR_NTF
+ * Checks SYNTAX_ERROR status
+ * Repeat for 100 times appending 0xFF each time to the packet
+ * Send CORE_CONN_CREATE_CMD for loop-back mode
+ * Check the response
+ */
+TEST_F(NfcHidlTest, WriteInvalidAndThenValidCommand) {
+  // Send an Error Data Packet
+  std::vector<uint8_t> cmd = FAULTY_DATA_PACKET;
+  NfcData data = cmd;
+  size_t size = data.size();
+
+  for (int i = 0; i < 100; i++) {
+    last_data_.resize(0);
+    data.resize(++size);
+    data[size - 1] = 0xFF;
+    EXPECT_EQ(data.size(), nfc_->write(data));
+    // Wait for CORE_INTERFACE_ERROR_NTF
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(1ul, last_data_.size());
+    EXPECT_EQ(5ul, last_data_[0].size());
+    EXPECT_EQ(0x60, last_data_[0][0]);
+    EXPECT_EQ(0x08, last_data_[0][1]);
+    EXPECT_EQ(0x02, last_data_[0][2]);
+    EXPECT_EQ(SYNTAX_ERROR, last_data_[0][3]);
+  }
+
+  cmd = CORE_CONN_CREATE_CMD;
+  data = cmd;
+  last_data_.resize(0);
+  EXPECT_EQ(data.size(), nfc_->write(data));
+  // Wait for CORE_CONN_CREATE_RSP
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(1ul, last_data_.size());
+  EXPECT_EQ(7ul, last_data_[0].size());
+  EXPECT_EQ((int)NfcStatus::OK, last_data_[0][3]);
+}
+/*
+ * Bandwidth:
+ * Sets the loop-back mode using CORE_CONN_CREATE_CMD
+ * Sends max payload size data
+ * Waits for the response
+ * Checks the data received
+ * Repeat to send total of 1Mb data
+ */
+TEST_F(NfcHidlTest, Bandwidth) {
+  std::vector<uint8_t> cmd = CORE_CONN_CREATE_CMD;
+  NfcData data = cmd;
+  EXPECT_EQ(data.size(), nfc_->write(data));
+  // Wait for CORE_CONN_CREATE_RSP
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(1ul, last_data_.size());
+  EXPECT_EQ(7ul, last_data_[0].size());
+  EXPECT_EQ((int)NfcStatus::OK, last_data_[0][3]);
+  uint8_t conn_id = last_data_[0][6];
+  uint32_t max_payload_size = last_data_[0][4];
+
+  for (int loops = 0; loops < NUMBER_LOOPS; loops++) {
+    last_data_.resize(0);
+    data.resize(max_payload_size + LOOP_BACK_HEADER_SIZE);
+    data[0] = conn_id;
+    data[1] = 0x00;
+    data[2] = max_payload_size;
+    for (uint32_t i = 0; i < max_payload_size; i++) {
+      data[i + LOOP_BACK_HEADER_SIZE] = i;
+    }
+    EXPECT_EQ(max_payload_size + LOOP_BACK_HEADER_SIZE, nfc_->write(data));
+    // Wait for data and CORE_CONN_CREDITS_NTF
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    // Check if the same data was recieved back
+    EXPECT_EQ(2ul, last_data_.size());
+    EXPECT_EQ(data.size(), last_data_[0].size());
+    for (size_t i = 0; i < data.size(); i++) {
+      EXPECT_EQ(data[i], last_data_[0][i]);
+    }
+
+    EXPECT_EQ(6ul, last_data_[1].size());
+    // Check if the credit is refilled to 1
+    EXPECT_EQ(1, last_data_[1][5]);
+  }
+}
+
+/*
+ * PowerCycle:
+ * Calls powerCycle()
+ * Waits for NfcEvent.OPEN_CPLT
+ * Checks status
+ */
+TEST_F(NfcHidlTest, PowerCycle) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->powerCycle());
+  // Wait for NfcEvent.OPEN_CPLT
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(NfcEvent::OPEN_CPLT, last_event_);
+  EXPECT_EQ(NfcStatus::OK, last_status_);
+}
+
+/*
+ * CoreInitialized:
+ * Calls coreInitialized()
+ * 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_);
+}
+
+/*
+ * ControlGranted:
+ * Calls controlGranted()
+ * Checks the return value
+ */
+TEST_F(NfcHidlTest, ControlGranted) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->controlGranted());
+}
+
+/* PreDiscover:
+ * Calls prediscover()
+ * Checks the return value
+ */
+TEST_F(NfcHidlTest, PreDiscover) {
+  EXPECT_EQ(NfcStatus::OK, nfc_->prediscover());
+}
+
+int main(int argc, char** argv) {
+  ::testing::AddGlobalTestEnvironment(new NfcHidlEnvironment);
+  ::testing::InitGoogleTest(&argc, argv);
+
+  for (int i = 0; i < argc; i++) {
+    if (strstr(argv[i], "passthrough=false") != nullptr) {
+      passthrough = false;
+      break;
+    }
+  }
+  std::system("svc nfc disable"); /* Turn off NFC */
+  sleep(5);
+
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+
+  std::system("svc nfc enable"); /* Turn on NFC */
+  sleep(5);
+
+  return status;
+}
diff --git a/nfc/1.0/vts/types.vts b/nfc/1.0/vts/types.vts
new file mode 100644
index 0000000..969a8af
--- /dev/null
+++ b/nfc/1.0/vts/types.vts
@@ -0,0 +1,72 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.nfc"
+
+attribute: {
+    name: "NfcEvent"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "OPEN_CPLT"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "CLOSE_CPLT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "POST_INIT_CPLT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "PRE_DISCOVER_CPLT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "REQUEST_CONTROL"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "RELEASE_CONTROL"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "ERROR"
+        scalar_value: {
+            uint32_t: 6
+        }
+    }
+}
+
+attribute: {
+    name: "NfcStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "OK"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "FAILED"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "ERR_TRANSPORT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "ERR_CMD_TIMEOUT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "REFUSED"
+        scalar_value: {
+            uint32_t: 4
+        }
+    }
+}
+
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index a2d961a..40e4024 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -40,6 +40,11 @@
         int32_t[3][5] matrix3x5;
     };
 
+    struct NestedStruct {
+        int32_t a;
+        vec<T> matrices;
+    };
+
     @Fragile @NoReally(very="yes", array={"a","b","c"})
     oneway doThis(float param);
 
@@ -64,4 +69,6 @@
     returnABitField() generates (bitfield<BitField> good);
 
     size(uint32_t size) generates (uint32_t size);
+
+    getNestedStructs() generates(vec<NestedStruct> data);
 };
diff --git a/tests/msgq/1.0/ITestMsgQ.hal b/tests/msgq/1.0/ITestMsgQ.hal
index e000f55..3ed1b37 100644
--- a/tests/msgq/1.0/ITestMsgQ.hal
+++ b/tests/msgq/1.0/ITestMsgQ.hal
@@ -93,6 +93,15 @@
     oneway requestBlockingRead(int32_t count);
 
     /*
+     * This method requests the service to trigger a blocking read using
+     * default Event Flag notification bits defined by the MessageQueue class.
+     *
+     * @param count Number of messages to read.
+     *
+     */
+    oneway requestBlockingReadDefaultEventFlagBits(int32_t count);
+
+    /*
      * This method requests the service to repeatedly trigger blocking reads.
      *
      * @param count Number of messages to read in a single blocking read.
diff --git a/wifi/1.0/IWifiStaIface.hal b/wifi/1.0/IWifiStaIface.hal
index 98af043..0d6b560 100644
--- a/wifi/1.0/IWifiStaIface.hal
+++ b/wifi/1.0/IWifiStaIface.hal
@@ -81,9 +81,13 @@
      */
     TDLS_OFFCHANNEL = 1 << 11,
     /**
+     * Support for keep alive packet offload.
+     */
+    KEEP_ALIVE = 1 << 12,
+    /**
      * Support for tracking connection packets' fate.
      */
-    DEBUG_PACKET_FATE = 1 << 12
+    DEBUG_PACKET_FATE = 1 << 13
   };
 
   /**
@@ -379,6 +383,55 @@
   setRoamingState(StaRoamingState state) generates (WifiStatus status);
 
   /**
+   * Enable/Disable Neighbour discovery offload functionality in the firmware.
+   *
+   * @param enable true to enable, false to disable.
+   * @return status WifiStatus of the operation.
+   *         Possible status codes:
+   *         |WifiStatusCode.SUCCESS|,
+   *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+   *         |WifiStatusCode.ERROR_UNKNOWN|
+   */
+  enableNdOffload(bool enable) generates (WifiStatus status);
+
+  /**
+   * Start sending the specified keep alive packets periodically.
+   *
+   * @param cmdId command Id to use for this invocation.
+   * @param ipPacketData IP packet contents to be transmitted.
+   * @param etherType 16 bit ether type to be set in the ethernet frame
+   *        transmitted.
+   * @param srcAddress Source MAC address of the packet.
+   * @param dstAddress Destination MAC address of the packet.
+   * @param periodInMs Interval at which this packet must be transmitted.
+   * @return status WifiStatus of the operation.
+   *         Possible status codes:
+   *         |WifiStatusCode.SUCCESS|,
+   *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+   *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+   *         |WifiStatusCode.ERROR_UNKNOWN|
+   */
+  startSendingKeepAlivePackets(
+      CommandId cmdId, vec<uint8_t> ipPacketData, uint16_t etherType,
+      MacAddress srcAddress, MacAddress dstAddress, uint32_t periodInMs)
+      generates (WifiStatus status);
+
+  /**
+   * Stop sending the specified keep alive packets.
+   *
+   * @param cmdId command Id corresponding to the request.
+   * @return status WifiStatus of the operation.
+   *         Possible status codes:
+   *         |WifiStatusCode.SUCCESS|,
+   *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+   *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+   *         |WifiStatusCode.ERROR_UNKNOWN|
+   */
+  stopSendingKeepAlivePackets(CommandId cmdId) generates (WifiStatus status);
+
+  /**
    * API to start packet fate monitoring.
    * - Once stared, monitoring must remain active until HAL is unloaded.
    * - When HAL is unloaded, all packet fate buffers must be cleared.
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index 9cc57bb..80cc56e 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -82,6 +82,8 @@
       return HidlStaIfaceCaps::TDLS;
     case WIFI_FEATURE_TDLS_OFFCHANNEL:
       return HidlStaIfaceCaps::TDLS_OFFCHANNEL;
+    case WIFI_FEATURE_MKEEP_ALIVE:
+      return HidlStaIfaceCaps::KEEP_ALIVE;
   };
   CHECK(false) << "Unknown legacy feature: " << feature;
   return {};
@@ -239,7 +241,8 @@
                              WIFI_FEATURE_HOTSPOT,
                              WIFI_FEATURE_PNO,
                              WIFI_FEATURE_TDLS,
-                             WIFI_FEATURE_TDLS_OFFCHANNEL}) {
+                             WIFI_FEATURE_TDLS_OFFCHANNEL,
+                             WIFI_FEATURE_MKEEP_ALIVE}) {
     if (feature & legacy_feature_set) {
       *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
     }
diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp
index 3b99e60..3bfd2bb 100644
--- a/wifi/1.0/default/wifi_legacy_hal.cpp
+++ b/wifi/1.0/default/wifi_legacy_hal.cpp
@@ -633,15 +633,46 @@
   return {status, caps};
 }
 
+wifi_error WifiLegacyHal::configureRoaming(const wifi_roaming_config& config) {
+  wifi_roaming_config config_internal = config;
+  return global_func_table_.wifi_configure_roaming(wlan_interface_handle_,
+                                                   &config_internal);
+}
+
 wifi_error WifiLegacyHal::enableFirmwareRoaming(fw_roaming_state_t state) {
   return global_func_table_.wifi_enable_firmware_roaming(wlan_interface_handle_,
                                                          state);
 }
 
-wifi_error WifiLegacyHal::configureRoaming(const wifi_roaming_config& config) {
-  wifi_roaming_config config_internal = config;
-  return global_func_table_.wifi_configure_roaming(wlan_interface_handle_,
-                                                   &config_internal);
+wifi_error WifiLegacyHal::configureNdOffload(bool enable) {
+  return global_func_table_.wifi_configure_nd_offload(wlan_interface_handle_,
+                                                      enable);
+}
+
+wifi_error WifiLegacyHal::startSendingOffloadedPacket(
+    uint32_t cmd_id,
+    const std::vector<uint8_t>& ip_packet_data,
+    const std::array<uint8_t, 6>& src_address,
+    const std::array<uint8_t, 6>& dst_address,
+    uint32_t period_in_ms) {
+  std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
+  std::vector<uint8_t> src_address_internal(
+      src_address.data(), src_address.data() + src_address.size());
+  std::vector<uint8_t> dst_address_internal(
+      dst_address.data(), dst_address.data() + dst_address.size());
+  return global_func_table_.wifi_start_sending_offloaded_packet(
+      cmd_id,
+      wlan_interface_handle_,
+      ip_packet_data_internal.data(),
+      ip_packet_data_internal.size(),
+      src_address_internal.data(),
+      dst_address_internal.data(),
+      period_in_ms);
+}
+
+wifi_error WifiLegacyHal::stopSendingOffloadedPacket(uint32_t cmd_id) {
+  return global_func_table_.wifi_stop_sending_offloaded_packet(
+      cmd_id, wlan_interface_handle_);
 }
 
 std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet() {
diff --git a/wifi/1.0/default/wifi_legacy_hal.h b/wifi/1.0/default/wifi_legacy_hal.h
index b585314..a3ac075 100644
--- a/wifi/1.0/default/wifi_legacy_hal.h
+++ b/wifi/1.0/default/wifi_legacy_hal.h
@@ -182,8 +182,16 @@
                                      on_threshold_breached_callback);
   wifi_error stopRssiMonitoring(wifi_request_id id);
   std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities();
-  wifi_error enableFirmwareRoaming(fw_roaming_state_t state);
   wifi_error configureRoaming(const wifi_roaming_config& config);
+  wifi_error enableFirmwareRoaming(fw_roaming_state_t state);
+  wifi_error configureNdOffload(bool enable);
+  wifi_error startSendingOffloadedPacket(
+      uint32_t cmd_id,
+      const std::vector<uint8_t>& ip_packet_data,
+      const std::array<uint8_t, 6>& src_address,
+      const std::array<uint8_t, 6>& dst_address,
+      uint32_t period_in_ms);
+  wifi_error stopSendingOffloadedPacket(uint32_t cmd_id);
   // Logger/debug functions.
   std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet();
   wifi_error startPktFateMonitoring();
diff --git a/wifi/1.0/default/wifi_sta_iface.cpp b/wifi/1.0/default/wifi_sta_iface.cpp
index e48978e..a00c5bc 100644
--- a/wifi/1.0/default/wifi_sta_iface.cpp
+++ b/wifi/1.0/default/wifi_sta_iface.cpp
@@ -212,6 +212,44 @@
                          state);
 }
 
+Return<void> WifiStaIface::enableNdOffload(bool enable,
+                                           enableNdOffload_cb hidl_status_cb) {
+  return validateAndCall(this,
+                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                         &WifiStaIface::enableNdOffloadInternal,
+                         hidl_status_cb,
+                         enable);
+}
+
+Return<void> WifiStaIface::startSendingKeepAlivePackets(
+    uint32_t cmd_id,
+    const hidl_vec<uint8_t>& ip_packet_data,
+    uint16_t ether_type,
+    const hidl_array<uint8_t, 6>& src_address,
+    const hidl_array<uint8_t, 6>& dst_address,
+    uint32_t period_in_ms,
+    startSendingKeepAlivePackets_cb hidl_status_cb) {
+  return validateAndCall(this,
+                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                         &WifiStaIface::startSendingKeepAlivePacketsInternal,
+                         hidl_status_cb,
+                         cmd_id,
+                         ip_packet_data,
+                         ether_type,
+                         src_address,
+                         dst_address,
+                         period_in_ms);
+}
+
+Return<void> WifiStaIface::stopSendingKeepAlivePackets(
+    uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) {
+  return validateAndCall(this,
+                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                         &WifiStaIface::stopSendingKeepAlivePacketsInternal,
+                         hidl_status_cb,
+                         cmd_id);
+}
+
 Return<void> WifiStaIface::startDebugPacketFateMonitoring(
     startDebugPacketFateMonitoring_cb hidl_status_cb) {
   return validateAndCall(this,
@@ -498,6 +536,31 @@
   return createWifiStatusFromLegacyError(legacy_status);
 }
 
+WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->configureNdOffload(enable);
+  return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
+    uint32_t cmd_id,
+    const std::vector<uint8_t>& ip_packet_data,
+    uint16_t /* ether_type */,
+    const std::array<uint8_t, 6>& src_address,
+    const std::array<uint8_t, 6>& dst_address,
+    uint32_t period_in_ms) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->startSendingOffloadedPacket(
+          cmd_id, ip_packet_data, src_address, dst_address, period_in_ms);
+  return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->stopSendingOffloadedPacket(cmd_id);
+  return createWifiStatusFromLegacyError(legacy_status);
+}
+
 WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
   legacy_hal::wifi_error legacy_status =
       legacy_hal_.lock()->startPktFateMonitoring();
diff --git a/wifi/1.0/default/wifi_sta_iface.h b/wifi/1.0/default/wifi_sta_iface.h
index 90126cd..311c991 100644
--- a/wifi/1.0/default/wifi_sta_iface.h
+++ b/wifi/1.0/default/wifi_sta_iface.h
@@ -83,6 +83,18 @@
                                 configureRoaming_cb hidl_status_cb) override;
   Return<void> setRoamingState(StaRoamingState state,
                                setRoamingState_cb hidl_status_cb) override;
+  Return<void> enableNdOffload(bool enable,
+                               enableNdOffload_cb hidl_status_cb) override;
+  Return<void> startSendingKeepAlivePackets(
+      uint32_t cmd_id,
+      const hidl_vec<uint8_t>& ip_packet_data,
+      uint16_t ether_type,
+      const hidl_array<uint8_t, 6>& src_address,
+      const hidl_array<uint8_t, 6>& dst_address,
+      uint32_t period_in_ms,
+      startSendingKeepAlivePackets_cb hidl_status_cb) override;
+  Return<void> stopSendingKeepAlivePackets(
+      uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) override;
   Return<void> startDebugPacketFateMonitoring(
       startDebugPacketFateMonitoring_cb hidl_status_cb) override;
   Return<void> stopDebugPacketFateMonitoring(
@@ -121,6 +133,15 @@
   getRoamingCapabilitiesInternal();
   WifiStatus configureRoamingInternal(const StaRoamingConfig& config);
   WifiStatus setRoamingStateInternal(StaRoamingState state);
+  WifiStatus enableNdOffloadInternal(bool enable);
+  WifiStatus startSendingKeepAlivePacketsInternal(
+      uint32_t cmd_id,
+      const std::vector<uint8_t>& ip_packet_data,
+      uint16_t ether_type,
+      const std::array<uint8_t, 6>& src_address,
+      const std::array<uint8_t, 6>& dst_address,
+      uint32_t period_in_ms);
+  WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id);
   WifiStatus startDebugPacketFateMonitoringInternal();
   WifiStatus stopDebugPacketFateMonitoringInternal();
   std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
diff --git a/wifi/supplicant/1.0/ISupplicantP2pIface.hal b/wifi/supplicant/1.0/ISupplicantP2pIface.hal
index 0fa19c8..35985fc 100644
--- a/wifi/supplicant/1.0/ISupplicantP2pIface.hal
+++ b/wifi/supplicant/1.0/ISupplicantP2pIface.hal
@@ -261,12 +261,12 @@
   /**
    * Set up a P2P group owner manually (i.e., without group owner
    * negotiation with a specific peer). This is also known as autonomous
-   * group owner. Optional |persistent| may be used to specify restart of a
-   * persistent group.
+   * group owner. Optional |persistentNetworkId| may be used to specify
+   * restart of a persistent group.
    *
    * @param persistent Used to request a persistent group to be formed.
    * @param persistentNetworkId Used to specify the restart of a persistent
-   *        group.
+   *        group. Set to UINT32_MAX for a non-persistent group.
    * @return status Status of the operation.
    *         Possible status codes:
    *         |SupplicantStatusCode.SUCCESS|,