Merge "Add android.hardware.consumerir@1.0 service."
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index c8fe2b6..3e1e2b9 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -55,4 +55,8 @@
     haveAStringVec(vec<string> vector) generates (vec<string> result);
 
     returnABunchOfStrings() generates (string a, string b, string c);
+
+    returnABitField() generates (bitfield<BitField> good);
+
+    size(uint32_t size) generates (uint32_t size);
 };
diff --git a/update-makefiles.sh b/update-makefiles.sh
index 0f89dfc..f153a84 100755
--- a/update-makefiles.sh
+++ b/update-makefiles.sh
@@ -5,6 +5,11 @@
   exit 1;
 fi
 
+if [ ! -d system/libhidl/transport ] ; then
+  echo "Where is system/libhidl/transport?";
+  exit 1;
+fi
+
 packages=$(pushd hardware/interfaces > /dev/null; \
            find . -type f -name \*.hal -exec dirname {} \; | sort -u | \
            cut -c3- | \
diff --git a/wifi/1.0/Android.mk b/wifi/1.0/Android.mk
index 7f158d4..254a15a 100644
--- a/wifi/1.0/Android.mk
+++ b/wifi/1.0/Android.mk
@@ -1176,25 +1176,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (RttChannelMap)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttChannelMap.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttChannelMap
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (RttConfig)
 #
 GEN := $(intermediates)/android/hardware/wifi/1.0/RttConfig.java
@@ -1214,63 +1195,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (RttDebugFormat)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttDebugFormat.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttDebugFormat
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (RttDebugInfo)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttDebugInfo.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttDebugInfo
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (RttDebugType)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttDebugType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttDebugType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (RttLciInformation)
 #
 GEN := $(intermediates)/android/hardware/wifi/1.0/RttLciInformation.java
@@ -3737,25 +3661,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (RttChannelMap)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttChannelMap.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttChannelMap
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (RttConfig)
 #
 GEN := $(intermediates)/android/hardware/wifi/1.0/RttConfig.java
@@ -3775,63 +3680,6 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
-# Build types.hal (RttDebugFormat)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttDebugFormat.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttDebugFormat
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (RttDebugInfo)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttDebugInfo.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttDebugInfo
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (RttDebugType)
-#
-GEN := $(intermediates)/android/hardware/wifi/1.0/RttDebugType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.wifi@1.0::types.RttDebugType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
 # Build types.hal (RttLciInformation)
 #
 GEN := $(intermediates)/android/hardware/wifi/1.0/RttLciInformation.java
diff --git a/wifi/1.0/IWifiRttController.hal b/wifi/1.0/IWifiRttController.hal
index 93b3d92..2f81176 100644
--- a/wifi/1.0/IWifiRttController.hal
+++ b/wifi/1.0/IWifiRttController.hal
@@ -83,45 +83,6 @@
       generates (WifiStatus status);
 
   /**
-   * API to start publishing the channel map on responder device in an NBD
-   * cluster.
-   * Responder device must take this request and schedule broadcasting the
-   * channel map in a NBD ranging attribute in a Service Discovery Frame.
-   * DE must automatically remove the ranging attribute from the OTA queue
-   * after number of Discovery Window specified by numDw where each
-   * Discovery Window is 512 TUs apart.
-   *
-   * @param cmdId command Id to use for this invocation.
-   * @param params Instance of |RttChannelMap|.
-   * @return status WifiStatus of the operation.
-   *         Possible status codes:
-   *         |WifiStatusCode.SUCCESS|,
-   *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
-   *         |WifiStatusCode.ERROR_INVALID_ARGS|,
-   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
-   *         |WifiStatusCode.ERROR_UNKNOWN|
-   */
-  setChannelMap(CommandId cmdId, RttChannelMap params, uint32_t numDw)
-      generates (WifiStatus status);
-
-  /**
-   * API to clear the channel map on the responder device in an NBD cluster.
-   * Responder device must cancel future ranging channel request, starting from
-   * next Discovery Window interval and must also stop broadcasting NBD
-   * ranging attribute in Service Discovery Frame.
-   *
-   * @param cmdId command Id corresponding to the original request.
-   * @return status WifiStatus of the operation.
-   *         Possible status codes:
-   *         |WifiStatusCode.SUCCESS|,
-   *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
-   *         |WifiStatusCode.ERROR_INVALID_ARGS|,
-   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
-   *         |WifiStatusCode.ERROR_UNKNOWN|
-   */
-  clearChannelMap(CommandId cmdId) generates (WifiStatus status);
-
-  /**
    * RTT capabilities of the device.
    *
    * @return status WifiStatus of the operation.
@@ -134,32 +95,6 @@
   getCapabilities() generates (WifiStatus status, RttCapabilities capabilities);
 
   /**
-   * Set configuration for debug.
-   *
-   * @param type debug level to be set.
-   * @return status WifiStatus of the operation.
-   *         Possible status codes:
-   *         |WifiStatusCode.SUCCESS|,
-   *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
-   *         |WifiStatusCode.ERROR_INVALID_ARGS|,
-   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
-   *         |WifiStatusCode.ERROR_UNKNOWN|
-   */
-  setDebugCfg(RttDebugType Type) generates (WifiStatus status);
-
-  /**
-   * Get the debug information.
-   *
-   * @return status WifiStatus of the operation.
-   *         Possible status codes:
-   *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
-   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
-   *         |WifiStatusCode.ERROR_UNKNOWN|
-   * @return info Instance of |RttDebugInfo|.
-   */
-  getDebugInfo() generates (WifiStatus status, RttDebugInfo info);
-
-  /**
    * API to configure the LCI(Location civic information).
    * Used in RTT Responder mode only.
    *
diff --git a/wifi/1.0/IWifiStaIface.hal b/wifi/1.0/IWifiStaIface.hal
index 41b2bad..7b514a7 100644
--- a/wifi/1.0/IWifiStaIface.hal
+++ b/wifi/1.0/IWifiStaIface.hal
@@ -45,9 +45,13 @@
      */
     LINK_LAYER_STATS = 1 << 2,
     /**
+     * If set indicates that the RSSI monitor APIs are supported.
+     */
+    RSSI_MONITOR = 1 << 3,
+    /**
      * Tracks connection packets' fate.
      */
-    DEBUG_PACKET_FATE_SUPPORTED = 1 << 3
+    DEBUG_PACKET_FATE_SUPPORTED = 1 << 4
   };
 
   /**
@@ -259,6 +263,44 @@
   getLinkLayerStats() generates (WifiStatus status, StaLinkLayerStats stats);
 
   /**
+   * Start RSSI monitoring on the currently connected access point.
+   * Once the monitoring is enabled,
+   * |IWifiStaIfaceEventCallback.onRssiThresholdBreached| callback must be
+   * invoked to indicate if the RSSI goes above |maxRssi| or below |minRssi|.
+   * Must fail if |StaIfaceCapabilityMask.RSSI_MONITOR| is not set.
+   *
+   * @param cmdId command Id to use for this invocation.
+   * @param maxRssi Maximum RSSI threshold.
+   * @param minRssi Minimum RSSI threshold.
+   * @return status WifiStatus of the operation.
+   *         Possible status codes:
+   *         |WifiStatusCode.SUCCESS|,
+   *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+   *         |WifiStatusCode.ERROR_ARGS_INVALID|,
+   *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+   *         |WifiStatusCode.ERROR_UNKNOWN|
+   */
+  startRssiMonitoring(CommandId cmdId, Rssi maxRssi, Rssi minRssi)
+      generates (WifiStatus status);
+
+  /**
+   * Stop RSSI monitoring.
+   * Must fail if |StaIfaceCapabilityMask.RSSI_MONITOR| is not set.
+   *
+   * @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_STARTED|,
+   *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+   *         |WifiStatusCode.ERROR_UNKNOWN|
+   */
+  stopRssiMonitoring(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/IWifiStaIfaceEventCallback.hal b/wifi/1.0/IWifiStaIfaceEventCallback.hal
index d47d40c..e8df4c2 100644
--- a/wifi/1.0/IWifiStaIfaceEventCallback.hal
+++ b/wifi/1.0/IWifiStaIfaceEventCallback.hal
@@ -20,6 +20,8 @@
   /**
    * Callback indicating that an ongoing background scan request has failed.
    * The background scan needs to be restarted to continue scanning.
+   *
+   * @param cmdId command ID corresponding to the request.
    */
   oneway onBackgroundScanFailure(CommandId cmdId);
 
@@ -28,7 +30,7 @@
    * |REPORT_EVENTS_FULL_RESULTS| flag set in
    * |StaBackgroundScanBucketParameters.eventReportScheme|.
    *
-   * @param cmdId command Id corresponding to the request.
+   * @param cmdId command ID corresponding to the request.
    * @parm result Full scan result for an AP.
    */
   oneway onBackgroundFullScanResult(CommandId cmdId, StaScanResult result);
@@ -39,8 +41,18 @@
    * |REPORT_EVENTS_EACH_SCAN| or one of the configured thresholds was
    * breached.
    *
-   * @param cmdId command Id corresponding to the request.
+   * @param cmdId command ID corresponding to the request.
    * @parm scanDatas List of scan result for all AP's seen since last callback.
    */
   oneway onBackgroundScanResults(CommandId cmdId, vec<StaScanData> scanDatas);
+
+  /**
+   * Called when the RSSI of the currently connected access point goes beyond the
+   * thresholds set via |IWifiStaIface.startRssiMonitoring|.
+   *
+   * @param cmdId command ID corresponding to the request.
+   * @param currBssid BSSID of the currently connected access point.
+   * @param currRssi RSSI of the currently connected access point.
+   */
+  oneway onRssiThresholdBreached(CommandId cmdId, Bssid currBssid, Rssi currRssi);
 };
diff --git a/wifi/1.0/default/Android.mk b/wifi/1.0/default/Android.mk
index 931a314..382d350 100644
--- a/wifi/1.0/default/Android.mk
+++ b/wifi/1.0/default/Android.mk
@@ -24,6 +24,7 @@
     wifi_ap_iface.cpp \
     wifi_chip.cpp \
     wifi_legacy_hal.cpp \
+    wifi_mode_controller.cpp \
     wifi_nan_iface.cpp \
     wifi_p2p_iface.cpp \
     wifi_rtt_controller.cpp \
@@ -39,6 +40,7 @@
     liblog \
     libnl \
     libutils \
+    libwifi-hal \
     libwifi-system
 LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL)
 LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index b4dcc0a..61a2c2c 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -26,7 +26,217 @@
 namespace implementation {
 namespace hidl_struct_util {
 
-uint8_t ConvertHidlReportEventFlagToLegacy(
+IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(
+    uint32_t feature) {
+  using HidlChipCaps = IWifiChip::ChipCapabilityMask;
+  switch (feature) {
+    case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED:
+      return HidlChipCaps::DEBUG_MEMORY_FIRMWARE_DUMP_SUPPORTED;
+    case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED:
+      return HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP_SUPPORTED;
+    case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED:
+      return HidlChipCaps::DEBUG_RING_BUFFER_CONNECT_EVENT_SUPPORTED;
+    case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED:
+      return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT_SUPPORTED;
+    case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED:
+      return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT_SUPPORTED;
+  };
+  CHECK(false) << "Unknown legacy feature: " << feature;
+  return {};
+}
+
+IWifiStaIface::StaIfaceCapabilityMask
+convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) {
+  using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
+  switch (feature) {
+    case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED:
+      return HidlStaIfaceCaps::DEBUG_PACKET_FATE_SUPPORTED;
+  };
+  CHECK(false) << "Unknown legacy feature: " << feature;
+  return {};
+}
+
+IWifiStaIface::StaIfaceCapabilityMask
+convertLegacyFeatureToHidlStaIfaceCapability(uint32_t feature) {
+  using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
+  switch (feature) {
+    case WIFI_FEATURE_GSCAN:
+      return HidlStaIfaceCaps::BACKGROUND_SCAN;
+    case WIFI_FEATURE_LINK_LAYER_STATS:
+      return HidlStaIfaceCaps::LINK_LAYER_STATS;
+    case WIFI_FEATURE_RSSI_MONITOR:
+      return HidlStaIfaceCaps::RSSI_MONITOR;
+  };
+  CHECK(false) << "Unknown legacy feature: " << feature;
+  return {};
+}
+
+bool convertLegacyFeaturesToHidlChipCapabilities(
+    uint32_t legacy_logger_feature_set, uint32_t* hidl_caps) {
+  if (!hidl_caps) {
+    return false;
+  }
+  *hidl_caps = 0;
+  using HidlChipCaps = IWifiChip::ChipCapabilityMask;
+  for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED,
+                             legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED,
+                             legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED,
+                             legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED,
+                             legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) {
+    if (feature & legacy_logger_feature_set) {
+      *hidl_caps |= convertLegacyLoggerFeatureToHidlChipCapability(feature);
+    }
+  }
+  // There is no flags for these 2 in the legacy feature set. Adding it to the
+  // set because all the current devices support it.
+  *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA_SUPPORTED;
+  *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
+  return true;
+}
+
+WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl(
+    uint32_t flag) {
+  switch (flag) {
+    case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES:
+      return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES;
+    case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES:
+      return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES;
+  };
+  CHECK(false) << "Unknown legacy flag: " << flag;
+  return {};
+}
+
+bool convertLegacyDebugRingBufferStatusToHidl(
+    const legacy_hal::wifi_ring_buffer_status& legacy_status,
+    WifiDebugRingBufferStatus* hidl_status) {
+  if (!hidl_status) {
+    return false;
+  }
+  hidl_status->ringName = reinterpret_cast<const char*>(legacy_status.name);
+  for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES,
+                          WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
+    if (flag & legacy_status.flags) {
+      hidl_status->flags |=
+          static_cast<std::underlying_type<WifiDebugRingBufferFlags>::type>(
+              convertLegacyDebugRingBufferFlagsToHidl(flag));
+    }
+  }
+  hidl_status->ringId = legacy_status.ring_id;
+  hidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size;
+  // Calculate free size of the ring the buffer. We don't need to send the
+  // exact read/write pointers that were there in the legacy HAL interface.
+  if (legacy_status.written_bytes >= legacy_status.read_bytes) {
+    hidl_status->freeSizeInBytes =
+        legacy_status.ring_buffer_byte_size -
+        (legacy_status.written_bytes - legacy_status.read_bytes);
+  } else {
+    hidl_status->freeSizeInBytes =
+        legacy_status.read_bytes - legacy_status.written_bytes;
+  }
+  hidl_status->verboseLevel = legacy_status.verbose_level;
+  return true;
+}
+
+bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
+    const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
+    std::vector<WifiDebugRingBufferStatus>* hidl_status_vec) {
+  if (!hidl_status_vec) {
+    return false;
+  }
+  hidl_status_vec->clear();
+  for (const auto& legacy_status : legacy_status_vec) {
+    WifiDebugRingBufferStatus hidl_status;
+    if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status,
+                                                  &hidl_status)) {
+      return false;
+    }
+    hidl_status_vec->push_back(hidl_status);
+  }
+  return true;
+}
+
+bool convertLegacyWakeReasonStatsToHidl(
+    const legacy_hal::WakeReasonStats& legacy_stats,
+    WifiDebugHostWakeReasonStats* hidl_stats) {
+  if (!hidl_stats) {
+    return false;
+  }
+  hidl_stats->totalCmdEventWakeCnt =
+      legacy_stats.wake_reason_cnt.total_cmd_event_wake;
+  hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt;
+  hidl_stats->totalDriverFwLocalWakeCnt =
+      legacy_stats.wake_reason_cnt.total_driver_fw_local_wake;
+  hidl_stats->driverFwLocalWakeCntPerType =
+      legacy_stats.driver_fw_local_wake_cnt;
+  hidl_stats->totalRxPacketWakeCnt =
+      legacy_stats.wake_reason_cnt.total_rx_data_wake;
+  hidl_stats->rxPktWakeDetails.rxUnicastCnt =
+      legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt;
+  hidl_stats->rxPktWakeDetails.rxMulticastCnt =
+      legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt;
+  hidl_stats->rxPktWakeDetails.rxBroadcastCnt =
+      legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt;
+  hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt =
+      legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
+          .ipv4_rx_multicast_addr_cnt;
+  hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt =
+      legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
+          .ipv6_rx_multicast_addr_cnt;
+  hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt =
+      legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
+          .other_rx_multicast_addr_cnt;
+  hidl_stats->rxIcmpPkWakeDetails.icmpPkt =
+      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt;
+  hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt =
+      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt;
+  hidl_stats->rxIcmpPkWakeDetails.icmp6Ra =
+      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra;
+  hidl_stats->rxIcmpPkWakeDetails.icmp6Na =
+      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na;
+  hidl_stats->rxIcmpPkWakeDetails.icmp6Ns =
+      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns;
+  return true;
+}
+
+bool convertLegacyFeaturesToHidlStaCapabilities(
+    uint32_t legacy_feature_set,
+    uint32_t legacy_logger_feature_set,
+    uint32_t* hidl_caps) {
+  if (!hidl_caps) {
+    return false;
+  }
+  *hidl_caps = 0;
+  using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
+  for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) {
+    if (feature & legacy_logger_feature_set) {
+      *hidl_caps |= convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature);
+    }
+  }
+  for (const auto feature : {WIFI_FEATURE_GSCAN,
+                             WIFI_FEATURE_LINK_LAYER_STATS,
+                             WIFI_FEATURE_RSSI_MONITOR}) {
+    if (feature & legacy_feature_set) {
+      *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
+    }
+  }
+  // There is no flag for this one in the legacy feature set. Adding it to the
+  // set because all the current devices support it.
+  *hidl_caps |= HidlStaIfaceCaps::APF;
+  return true;
+}
+
+bool convertLegacyApfCapabilitiesToHidl(
+    const legacy_hal::PacketFilterCapabilities& legacy_caps,
+    StaApfPacketFilterCapabilities* hidl_caps) {
+  if (!hidl_caps) {
+    return false;
+  }
+  hidl_caps->version = legacy_caps.version;
+  hidl_caps->maxLength = legacy_caps.max_len;
+  return true;
+}
+
+uint8_t convertHidlGscanReportEventFlagToLegacy(
     StaBackgroundScanBucketEventReportSchemeMask hidl_flag) {
   using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
   switch (hidl_flag) {
@@ -37,9 +247,54 @@
     case HidlFlag::NO_BATCH:
       return REPORT_EVENTS_NO_BATCH;
   };
+  CHECK(false);
 }
 
-bool convertHidlScanParamsToLegacy(
+StaScanDataFlagMask convertLegacyGscanDataFlagToHidl(uint8_t legacy_flag) {
+  switch (legacy_flag) {
+    case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED:
+      return StaScanDataFlagMask::INTERRUPTED;
+  };
+  CHECK(false) << "Unknown legacy flag: " << legacy_flag;
+  // To silence the compiler warning about reaching the end of non-void
+  // function.
+  return {};
+}
+
+bool convertLegacyGscanCapabilitiesToHidl(
+    const legacy_hal::wifi_gscan_capabilities& legacy_caps,
+    StaBackgroundScanCapabilities* hidl_caps) {
+  if (!hidl_caps) {
+    return false;
+  }
+  hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size;
+  hidl_caps->maxBuckets = legacy_caps.max_scan_buckets;
+  hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan;
+  hidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold;
+  return true;
+}
+
+legacy_hal::wifi_band convertHidlGscanBandToLegacy(StaBackgroundScanBand band) {
+  switch (band) {
+    case StaBackgroundScanBand::BAND_UNSPECIFIED:
+      return legacy_hal::WIFI_BAND_UNSPECIFIED;
+    case StaBackgroundScanBand::BAND_24GHZ:
+      return legacy_hal::WIFI_BAND_BG;
+    case StaBackgroundScanBand::BAND_5GHZ:
+      return legacy_hal::WIFI_BAND_A;
+    case StaBackgroundScanBand::BAND_5GHZ_DFS:
+      return legacy_hal::WIFI_BAND_A_DFS;
+    case StaBackgroundScanBand::BAND_5GHZ_WITH_DFS:
+      return legacy_hal::WIFI_BAND_A_WITH_DFS;
+    case StaBackgroundScanBand::BAND_24GHZ_5GHZ:
+      return legacy_hal::WIFI_BAND_ABG;
+    case StaBackgroundScanBand::BAND_24GHZ_5GHZ_WITH_DFS:
+      return legacy_hal::WIFI_BAND_ABG_WITH_DFS;
+  };
+  CHECK(false);
+}
+
+bool convertHidlGscanParamsToLegacy(
     const StaBackgroundScanParameters& hidl_scan_params,
     legacy_hal::wifi_scan_cmd_params* legacy_scan_params) {
   if (!legacy_scan_params) {
@@ -76,7 +331,7 @@
       if (hidl_bucket_spec.eventReportScheme &
           static_cast<std::underlying_type<HidlFlag>::type>(flag)) {
         legacy_bucket_spec.report_events |=
-            ConvertHidlReportEventFlagToLegacy(flag);
+            convertHidlGscanReportEventFlagToLegacy(flag);
       }
     }
     // TODO(b/33194311): Expose these max limits in the HIDL interface.
@@ -93,6 +348,18 @@
   return true;
 }
 
+bool convertLegacyIeToHidl(
+    const legacy_hal::wifi_information_element& legacy_ie,
+    WifiInformationElement* hidl_ie) {
+  if (!hidl_ie) {
+    return false;
+  }
+  hidl_ie->id = legacy_ie.id;
+  hidl_ie->data =
+      std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
+  return true;
+}
+
 bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob,
                                uint32_t ie_blob_len,
                                std::vector<WifiInformationElement>* hidl_ies) {
@@ -112,9 +379,9 @@
       return false;
     }
     WifiInformationElement hidl_ie;
-    hidl_ie.id = legacy_ie.id;
-    hidl_ie.data =
-        std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
+    if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) {
+      return false;
+    }
     hidl_ies->push_back(std::move(hidl_ie));
     next_ie += curr_ie_len;
   }
@@ -122,7 +389,7 @@
   return (next_ie == ies_end);
 }
 
-bool convertLegacyScanResultToHidl(
+bool convertLegacyGscanResultToHidl(
     const legacy_hal::wifi_scan_result& legacy_scan_result,
     bool has_ie_data,
     StaScanResult* hidl_scan_result) {
@@ -153,13 +420,19 @@
   return true;
 }
 
-bool convertLegacyCachedScanResultsToHidl(
+bool convertLegacyCachedGscanResultsToHidl(
     const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result,
     StaScanData* hidl_scan_data) {
   if (!hidl_scan_data) {
     return false;
   }
-  hidl_scan_data->flags = legacy_cached_scan_result.flags;
+  for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) {
+    if (legacy_cached_scan_result.flags & flag) {
+      hidl_scan_data->flags |=
+          static_cast<std::underlying_type<StaScanDataFlagMask>::type>(
+              convertLegacyGscanDataFlagToHidl(flag));
+    }
+  }
   hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned;
 
   CHECK(legacy_cached_scan_result.num_results >= 0 &&
@@ -169,7 +442,7 @@
        result_idx < legacy_cached_scan_result.num_results;
        result_idx++) {
     StaScanResult hidl_scan_result;
-    if (!convertLegacyScanResultToHidl(
+    if (!convertLegacyGscanResultToHidl(
             legacy_cached_scan_result.results[result_idx],
             false,
             &hidl_scan_result)) {
@@ -181,17 +454,18 @@
   return true;
 }
 
-bool convertLegacyVectorOfCachedScanResultsToHidl(
+bool convertLegacyVectorOfCachedGscanResultsToHidl(
     const std::vector<legacy_hal::wifi_cached_scan_results>&
         legacy_cached_scan_results,
     std::vector<StaScanData>* hidl_scan_datas) {
   if (!hidl_scan_datas) {
     return false;
   }
+  hidl_scan_datas->clear();
   for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) {
     StaScanData hidl_scan_data;
-    if (!convertLegacyCachedScanResultsToHidl(legacy_cached_scan_result,
-                                              &hidl_scan_data)) {
+    if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result,
+                                               &hidl_scan_data)) {
       return false;
     }
     hidl_scan_datas->push_back(hidl_scan_data);
@@ -199,6 +473,149 @@
   return true;
 }
 
+WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl(
+    legacy_hal::wifi_tx_packet_fate fate) {
+  switch (fate) {
+    case legacy_hal::TX_PKT_FATE_ACKED:
+      return WifiDebugTxPacketFate::ACKED;
+    case legacy_hal::TX_PKT_FATE_SENT:
+      return WifiDebugTxPacketFate::SENT;
+    case legacy_hal::TX_PKT_FATE_FW_QUEUED:
+      return WifiDebugTxPacketFate::FW_QUEUED;
+    case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID:
+      return WifiDebugTxPacketFate::FW_DROP_INVALID;
+    case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS:
+      return WifiDebugTxPacketFate::FW_DROP_NOBUFS;
+    case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER:
+      return WifiDebugTxPacketFate::FW_DROP_OTHER;
+    case legacy_hal::TX_PKT_FATE_DRV_QUEUED:
+      return WifiDebugTxPacketFate::DRV_QUEUED;
+    case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID:
+      return WifiDebugTxPacketFate::DRV_DROP_INVALID;
+    case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS:
+      return WifiDebugTxPacketFate::DRV_DROP_NOBUFS;
+    case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER:
+      return WifiDebugTxPacketFate::DRV_DROP_OTHER;
+  };
+  CHECK(false) << "Unknown legacy fate type: " << fate;
+}
+
+WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl(
+    legacy_hal::wifi_rx_packet_fate fate) {
+  switch (fate) {
+    case legacy_hal::RX_PKT_FATE_SUCCESS:
+      return WifiDebugRxPacketFate::SUCCESS;
+    case legacy_hal::RX_PKT_FATE_FW_QUEUED:
+      return WifiDebugRxPacketFate::FW_QUEUED;
+    case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER:
+      return WifiDebugRxPacketFate::FW_DROP_FILTER;
+    case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID:
+      return WifiDebugRxPacketFate::FW_DROP_INVALID;
+    case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS:
+      return WifiDebugRxPacketFate::FW_DROP_NOBUFS;
+    case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER:
+      return WifiDebugRxPacketFate::FW_DROP_OTHER;
+    case legacy_hal::RX_PKT_FATE_DRV_QUEUED:
+      return WifiDebugRxPacketFate::DRV_QUEUED;
+    case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER:
+      return WifiDebugRxPacketFate::DRV_DROP_FILTER;
+    case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID:
+      return WifiDebugRxPacketFate::DRV_DROP_INVALID;
+    case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS:
+      return WifiDebugRxPacketFate::DRV_DROP_NOBUFS;
+    case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER:
+      return WifiDebugRxPacketFate::DRV_DROP_OTHER;
+  };
+  CHECK(false) << "Unknown legacy fate type: " << fate;
+}
+
+WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl(
+    legacy_hal::frame_type type) {
+  switch (type) {
+    case legacy_hal::FRAME_TYPE_UNKNOWN:
+      return WifiDebugPacketFateFrameType::UNKNOWN;
+    case legacy_hal::FRAME_TYPE_ETHERNET_II:
+      return WifiDebugPacketFateFrameType::ETHERNET_II;
+    case legacy_hal::FRAME_TYPE_80211_MGMT:
+      return WifiDebugPacketFateFrameType::MGMT_80211;
+  };
+  CHECK(false) << "Unknown legacy frame type: " << type;
+}
+
+bool convertLegacyDebugPacketFateFrameToHidl(
+    const legacy_hal::frame_info& legacy_frame,
+    WifiDebugPacketFateFrameInfo* hidl_frame) {
+  if (!hidl_frame) {
+    return false;
+  }
+  hidl_frame->frameType =
+      convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type);
+  hidl_frame->frameLen = legacy_frame.frame_len;
+  hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec;
+  hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec;
+  const uint8_t* frame_begin = reinterpret_cast<const uint8_t*>(
+      legacy_frame.frame_content.ethernet_ii_bytes);
+  hidl_frame->frameContent =
+      std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len);
+  return true;
+}
+
+bool convertLegacyDebugTxPacketFateToHidl(
+    const legacy_hal::wifi_tx_report& legacy_fate,
+    WifiDebugTxPacketFateReport* hidl_fate) {
+  if (!hidl_fate) {
+    return false;
+  }
+  hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate);
+  return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
+                                                 &hidl_fate->frameInfo);
+}
+
+bool convertLegacyVectorOfDebugTxPacketFateToHidl(
+    const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
+    std::vector<WifiDebugTxPacketFateReport>* hidl_fates) {
+  if (!hidl_fates) {
+    return false;
+  }
+  hidl_fates->clear();
+  for (const auto& legacy_fate : legacy_fates) {
+    WifiDebugTxPacketFateReport hidl_fate;
+    if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) {
+      return false;
+    }
+    hidl_fates->push_back(hidl_fate);
+  }
+  return true;
+}
+
+bool convertLegacyDebugRxPacketFateToHidl(
+    const legacy_hal::wifi_rx_report& legacy_fate,
+    WifiDebugRxPacketFateReport* hidl_fate) {
+  if (!hidl_fate) {
+    return false;
+  }
+  hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate);
+  return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
+                                                 &hidl_fate->frameInfo);
+}
+
+bool convertLegacyVectorOfDebugRxPacketFateToHidl(
+    const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
+    std::vector<WifiDebugRxPacketFateReport>* hidl_fates) {
+  if (!hidl_fates) {
+    return false;
+  }
+  hidl_fates->clear();
+  for (const auto& legacy_fate : legacy_fates) {
+    WifiDebugRxPacketFateReport hidl_fate;
+    if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) {
+      return false;
+    }
+    hidl_fates->push_back(hidl_fate);
+  }
+  return true;
+}
+
 bool convertLegacyLinkLayerStatsToHidl(
     const legacy_hal::LinkLayerStats& legacy_stats,
     StaLinkLayerStats* hidl_stats) {
@@ -251,6 +668,971 @@
   hidl_stats->timeStampInMs = uptimeMillis();
   return true;
 }
+
+legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(
+    NanPublishType type) {
+  switch (type) {
+    case NanPublishType::UNSOLICITED:
+      return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED;
+    case NanPublishType::SOLICITED:
+      return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED;
+    case NanPublishType::UNSOLICITED_SOLICITED:
+      return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
+  };
+  CHECK(false);
+}
+
+legacy_hal::NanTxType convertHidlNanTxTypeToLegacy(NanTxType type) {
+  switch (type) {
+    case NanTxType::BROADCAST:
+      return legacy_hal::NAN_TX_TYPE_BROADCAST;
+    case NanTxType::UNICAST:
+      return legacy_hal::NAN_TX_TYPE_UNICAST;
+  };
+  CHECK(false);
+}
+
+legacy_hal::NanMatchAlg convertHidlNanMatchAlgToLegacy(NanMatchAlg type) {
+  switch (type) {
+    case NanMatchAlg::MATCH_ONCE:
+      return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE;
+    case NanMatchAlg::MATCH_CONTINUOUS:
+      return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS;
+    case NanMatchAlg::MATCH_NEVER:
+      return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER;
+  };
+  CHECK(false);
+}
+
+legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(
+    NanSubscribeType type) {
+  switch (type) {
+    case NanSubscribeType::ACTIVE:
+      return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE;
+    case NanSubscribeType::PASSIVE:
+      return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE;
+  };
+  CHECK(false);
+}
+
+legacy_hal::NanSRFType convertHidlNanSrfTypeToLegacy(NanSrfType type) {
+  switch (type) {
+    case NanSrfType::BLOOM_FILTER:
+      return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER;
+    case NanSrfType::PARTIAL_MAC_ADDR:
+      return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
+  };
+  CHECK(false);
+}
+
+legacy_hal::NanSRFIncludeType convertHidlNanSrfIncludeTypeToLegacy(
+    NanSrfIncludeType type) {
+  switch (type) {
+    case NanSrfIncludeType::DO_NOT_RESPOND:
+      return legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
+    case NanSrfIncludeType::RESPOND:
+      return legacy_hal::NAN_SRF_INCLUDE_RESPOND;
+  };
+  CHECK(false);
+}
+
+NanStatusType convertLegacyNanStatusTypeToHidl(
+    legacy_hal::NanStatusType /* type */) {
+  // TODO: The |NanStatusType| has changed in legacy HAL and no longer in sync
+  // with the HIDL interface.
+  return NanStatusType::SUCCESS;
+}
+
+NanResponseType convertLegacyNanResponseTypeToHidl(
+    legacy_hal::NanResponseType type) {
+  switch (type) {
+    case legacy_hal::NAN_RESPONSE_ENABLED:
+      return NanResponseType::ENABLED;
+    case legacy_hal::NAN_RESPONSE_DISABLED:
+      return NanResponseType::DISABLED;
+    case legacy_hal::NAN_RESPONSE_PUBLISH:
+      return NanResponseType::PUBLISH;
+    case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL:
+      return NanResponseType::PUBLISH_CANCEL;
+    case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP:
+      return NanResponseType::TRANSMIT_FOLLOWUP;
+    case legacy_hal::NAN_RESPONSE_SUBSCRIBE:
+      return NanResponseType::SUBSCRIBE;
+    case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL:
+      return NanResponseType::SUBSCRIBE_CANCEL;
+    case legacy_hal::NAN_RESPONSE_STATS:
+      // Not present in HIDL. Is going to be deprecated in legacy HAL as well.
+      CHECK(0);
+    case legacy_hal::NAN_RESPONSE_CONFIG:
+      return NanResponseType::CONFIG;
+    case legacy_hal::NAN_RESPONSE_TCA:
+      // Not present in HIDL. Is going to be deprecated in legacy HAL as well.
+      CHECK(0);
+    case legacy_hal::NAN_RESPONSE_ERROR:
+      return NanResponseType::ERROR;
+    case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
+      return NanResponseType::BEACON_SDF_PAYLOAD;
+    case legacy_hal::NAN_GET_CAPABILITIES:
+      return NanResponseType::GET_CAPABILITIES;
+    case legacy_hal::NAN_DP_INTERFACE_CREATE:
+      return NanResponseType::DP_INTERFACE_CREATE;
+    case legacy_hal::NAN_DP_INTERFACE_DELETE:
+      return NanResponseType::DP_INTERFACE_DELETE;
+    case legacy_hal::NAN_DP_INITIATOR_RESPONSE:
+      return NanResponseType::DP_INITIATOR_RESPONSE;
+    case legacy_hal::NAN_DP_RESPONDER_RESPONSE:
+      return NanResponseType::DP_RESPONDER_RESPONSE;
+    case legacy_hal::NAN_DP_END:
+      return NanResponseType::DP_END;
+  };
+  CHECK(false) << "Unknown legacy type: " << type;
+}
+
+bool convertHidlNanEnableRequestToLegacy(
+    const NanEnableRequest& hidl_request,
+    legacy_hal::NanEnableRequest* legacy_request) {
+  if (!legacy_request) {
+    return false;
+  }
+  legacy_request->master_pref = hidl_request.masterPref;
+  legacy_request->cluster_low = hidl_request.clusterLow;
+  legacy_request->cluster_high = hidl_request.clusterHigh;
+  legacy_request->config_support_5g = hidl_request.validSupport5gVal;
+  legacy_request->support_5g_val = hidl_request.support5gVal;
+  legacy_request->config_sid_beacon = hidl_request.validSidBeaconVal;
+  legacy_request->sid_beacon_val = hidl_request.sidBeaconVal;
+  legacy_request->config_2dot4g_rssi_close =
+      hidl_request.valid2dot4gRssiCloseVal;
+  legacy_request->rssi_close_2dot4g_val = hidl_request.rssiClose2dot4gVal;
+  legacy_request->config_2dot4g_rssi_middle =
+      hidl_request.valid2dot4gRssiMiddleVal;
+  legacy_request->rssi_middle_2dot4g_val = hidl_request.rssiMiddle2dot4gVal;
+  legacy_request->config_2dot4g_rssi_proximity =
+      hidl_request.valid2dot4gRssiProximityVal;
+  legacy_request->rssi_proximity_2dot4g_val =
+      hidl_request.rssiProximity2dot4gVal;
+  legacy_request->config_hop_count_limit = hidl_request.validHopCountLimitVal;
+  legacy_request->hop_count_limit_val = hidl_request.hopCountLimitVal;
+  legacy_request->config_2dot4g_support = hidl_request.valid2dot4gSupportVal;
+  legacy_request->support_2dot4g_val = hidl_request.support2dot4gVal;
+  legacy_request->config_2dot4g_beacons = hidl_request.valid2dot4gBeaconsVal;
+  legacy_request->beacon_2dot4g_val = hidl_request.beacon2dot4gVal;
+  legacy_request->config_2dot4g_sdf = hidl_request.valid2dot4gSdfVal;
+  legacy_request->sdf_2dot4g_val = hidl_request.sdf2dot4gVal;
+  legacy_request->config_5g_beacons = hidl_request.valid5gBeaconsVal;
+  legacy_request->beacon_5g_val = hidl_request.beacon5gVal;
+  legacy_request->config_5g_sdf = hidl_request.valid5gSdfVal;
+  legacy_request->sdf_5g_val = hidl_request.sdf5gVal;
+  legacy_request->config_5g_rssi_close = hidl_request.valid5gRssiCloseVal;
+  legacy_request->rssi_close_5g_val = hidl_request.rssiClose5gVal;
+  legacy_request->config_5g_rssi_middle = hidl_request.valid5gRssiMiddleVal;
+  legacy_request->rssi_middle_5g_val = hidl_request.rssiMiddle5gVal;
+  legacy_request->config_5g_rssi_close_proximity =
+      hidl_request.valid5gRssiCloseProximityVal;
+  legacy_request->rssi_close_proximity_5g_val =
+      hidl_request.rssiCloseProximity5gVal;
+  legacy_request->config_rssi_window_size = hidl_request.validRssiWindowSizeVal;
+  legacy_request->rssi_window_size_val = hidl_request.rssiWindowSizeVal;
+  legacy_request->config_oui = hidl_request.validOuiVal;
+  legacy_request->oui_val = hidl_request.ouiVal;
+  legacy_request->config_intf_addr = hidl_request.validIntfAddrVal;
+  CHECK(hidl_request.intfAddrVal.size() ==
+        sizeof(legacy_request->intf_addr_val));
+  memcpy(legacy_request->intf_addr_val,
+         hidl_request.intfAddrVal.data(),
+         hidl_request.intfAddrVal.size());
+  legacy_request->config_cluster_attribute_val =
+      hidl_request.configClusterAttributeVal;
+  legacy_request->config_scan_params = hidl_request.validScanParamsVal;
+  if (hidl_request.scanParamsVal.dwellTime.size() >
+      sizeof(legacy_request->scan_params_val.dwell_time)) {
+    return false;
+  }
+  memcpy(legacy_request->scan_params_val.dwell_time,
+         hidl_request.scanParamsVal.dwellTime.data(),
+         hidl_request.scanParamsVal.dwellTime.size());
+  if (hidl_request.scanParamsVal.scanPeriod.size() >
+      sizeof(legacy_request->scan_params_val.scan_period)) {
+    return false;
+  }
+  memcpy(legacy_request->scan_params_val.scan_period,
+         hidl_request.scanParamsVal.scanPeriod.data(),
+         hidl_request.scanParamsVal.scanPeriod.size());
+  legacy_request->config_random_factor_force =
+      hidl_request.validRandomFactorForceVal;
+  legacy_request->random_factor_force_val = hidl_request.randomFactorForceVal;
+  legacy_request->config_hop_count_force = hidl_request.validHopCountLimitVal;
+  legacy_request->hop_count_force_val = hidl_request.hopCountLimitVal;
+  legacy_request->config_24g_channel = hidl_request.valid24gChannelVal;
+  legacy_request->channel_24g_val = hidl_request.channel24gVal;
+  legacy_request->config_5g_channel = hidl_request.valid5gChannelVal;
+  legacy_request->channel_5g_val = hidl_request.channel5gVal;
+  return true;
+}
+
+bool convertHidlNanPublishRequestToLegacy(
+    const NanPublishRequest& hidl_request,
+    legacy_hal::NanPublishRequest* legacy_request) {
+  if (!legacy_request) {
+    return false;
+  }
+  legacy_request->publish_id = hidl_request.publishId;
+  legacy_request->ttl = hidl_request.ttl;
+  legacy_request->period = hidl_request.period;
+  legacy_request->publish_type =
+      convertHidlNanPublishTypeToLegacy(hidl_request.publishType);
+  legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType);
+  legacy_request->publish_count = hidl_request.publishCount;
+  if (hidl_request.serviceName.size() > sizeof(legacy_request->service_name)) {
+    return false;
+  }
+  legacy_request->service_name_len = hidl_request.serviceName.size();
+  memcpy(legacy_request->service_name,
+         hidl_request.serviceName.c_str(),
+         hidl_request.serviceName.size());
+  legacy_request->publish_match_indicator =
+      convertHidlNanMatchAlgToLegacy(hidl_request.publishMatchIndicator);
+  if (hidl_request.serviceSpecificInfo.size() >
+      sizeof(legacy_request->service_specific_info)) {
+    return false;
+  }
+  legacy_request->service_specific_info_len =
+      hidl_request.serviceSpecificInfo.size();
+  memcpy(legacy_request->service_specific_info,
+         hidl_request.serviceSpecificInfo.data(),
+         hidl_request.serviceSpecificInfo.size());
+  if (hidl_request.rxMatchFilter.size() >
+      sizeof(legacy_request->rx_match_filter)) {
+    return false;
+  }
+  legacy_request->rx_match_filter_len = hidl_request.rxMatchFilter.size();
+  memcpy(legacy_request->rx_match_filter,
+         hidl_request.rxMatchFilter.data(),
+         hidl_request.rxMatchFilter.size());
+  if (hidl_request.txMatchFilter.size() >
+      sizeof(legacy_request->tx_match_filter)) {
+    return false;
+  }
+  legacy_request->tx_match_filter_len = hidl_request.txMatchFilter.size();
+  memcpy(legacy_request->tx_match_filter,
+         hidl_request.txMatchFilter.data(),
+         hidl_request.txMatchFilter.size());
+  legacy_request->rssi_threshold_flag = hidl_request.useRssiThreshold;
+  legacy_request->connmap = hidl_request.connmap;
+  legacy_request->recv_indication_cfg = hidl_request.recvIndicationCfg;
+  return true;
+}
+
+bool convertHidlNanPublishCancelRequestToLegacy(
+    const NanPublishCancelRequest& hidl_request,
+    legacy_hal::NanPublishCancelRequest* legacy_request) {
+  legacy_request->publish_id = hidl_request.publishId;
+  return true;
+}
+
+bool convertHidlNanSubscribeRequestToLegacy(
+    const NanSubscribeRequest& hidl_request,
+    legacy_hal::NanSubscribeRequest* legacy_request) {
+  if (!legacy_request) {
+    return false;
+  }
+  legacy_request->subscribe_id = hidl_request.subscribeId;
+  legacy_request->ttl = hidl_request.ttl;
+  legacy_request->period = hidl_request.period;
+  legacy_request->subscribe_type =
+      convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType);
+  legacy_request->serviceResponseFilter =
+      convertHidlNanSrfTypeToLegacy(hidl_request.serviceResponseFilter);
+  legacy_request->serviceResponseInclude =
+      convertHidlNanSrfIncludeTypeToLegacy(hidl_request.serviceResponseInclude);
+  legacy_request->useServiceResponseFilter =
+      hidl_request.shouldUseServiceResponseFilter
+          ? legacy_hal::NAN_USE_SRF
+          : legacy_hal::NAN_DO_NOT_USE_SRF;
+  legacy_request->ssiRequiredForMatchIndication =
+      hidl_request.isSsiRequiredForMatchIndication
+          ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND
+          : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
+  legacy_request->subscribe_match_indicator =
+      convertHidlNanMatchAlgToLegacy(hidl_request.subscribeMatchIndicator);
+  legacy_request->subscribe_count = hidl_request.subscribeCount;
+  if (hidl_request.serviceName.size() > sizeof(legacy_request->service_name)) {
+    return false;
+  }
+  legacy_request->service_name_len = hidl_request.serviceName.size();
+  memcpy(legacy_request->service_name,
+         hidl_request.serviceName.c_str(),
+         hidl_request.serviceName.size());
+  if (hidl_request.serviceSpecificInfo.size() >
+      sizeof(legacy_request->service_specific_info)) {
+    return false;
+  }
+  legacy_request->service_specific_info_len =
+      hidl_request.serviceSpecificInfo.size();
+  memcpy(legacy_request->service_specific_info,
+         hidl_request.serviceSpecificInfo.data(),
+         hidl_request.serviceSpecificInfo.size());
+  if (hidl_request.rxMatchFilter.size() >
+      sizeof(legacy_request->rx_match_filter)) {
+    return false;
+  }
+  legacy_request->rx_match_filter_len = hidl_request.rxMatchFilter.size();
+  memcpy(legacy_request->rx_match_filter,
+         hidl_request.rxMatchFilter.data(),
+         hidl_request.rxMatchFilter.size());
+  if (hidl_request.txMatchFilter.size() >
+      sizeof(legacy_request->tx_match_filter)) {
+    return false;
+  }
+  legacy_request->tx_match_filter_len = hidl_request.txMatchFilter.size();
+  memcpy(legacy_request->tx_match_filter,
+         hidl_request.txMatchFilter.data(),
+         hidl_request.txMatchFilter.size());
+  legacy_request->rssi_threshold_flag = hidl_request.useRssiThreshold;
+  legacy_request->connmap = hidl_request.connmap;
+  if (hidl_request.intfAddr.size() > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
+    return false;
+  }
+  legacy_request->num_intf_addr_present = hidl_request.intfAddr.size();
+  for (uint32_t i = 0; i < hidl_request.intfAddr.size(); i++) {
+    CHECK(hidl_request.intfAddr[i].size() ==
+          sizeof(legacy_request->intf_addr[i]));
+    memcpy(legacy_request->intf_addr[i],
+           hidl_request.intfAddr[i].data(),
+           hidl_request.intfAddr[i].size());
+  }
+  legacy_request->recv_indication_cfg = hidl_request.recvIndicationCfg;
+  return true;
+}
+
+bool convertHidlNanSubscribeCancelRequestToLegacy(
+    const NanSubscribeCancelRequest& /* hidl_request */,
+    legacy_hal::NanSubscribeCancelRequest* /* legacy_request */) {
+  return false;
+}
+
+bool convertHidlNanTransmitFollowupRequestToLegacy(
+    const NanTransmitFollowupRequest& /* hidl_request */,
+    legacy_hal::NanTransmitFollowupRequest* /* legacy_request */) {
+  return false;
+}
+
+bool convertHidlNanConfigRequestToLegacy(
+    const NanConfigRequest& /* hidl_request */,
+    legacy_hal::NanConfigRequest* /* legacy_request */) {
+  return false;
+}
+
+bool convertHidlNanBeaconSdfPayloadRequestToLegacy(
+    const NanBeaconSdfPayloadRequest& /* hidl_request */,
+    legacy_hal::NanBeaconSdfPayloadRequest* /* legacy_request */) {
+  return false;
+}
+
+bool convertHidlNanDataPathInitiatorRequestToLegacy(
+    const NanDataPathInitiatorRequest& /* hidl_request */,
+    legacy_hal::NanDataPathInitiatorRequest* /* legacy_request */) {
+  return false;
+}
+
+bool convertHidlNanDataPathIndicationResponseToLegacy(
+    const NanDataPathIndicationResponse& /* hidl_response */,
+    legacy_hal::NanDataPathIndicationResponse* /* legacy_response */) {
+  return false;
+}
+
+bool convertHidlNanDataPathEndRequestToLegacy(
+    const NanDataPathEndRequest& /* hidl_request */,
+    legacy_hal::NanDataPathEndRequest* /* legacy_request */) {
+  return false;
+}
+
+bool convertLegacyNanResponseHeaderToHidl(
+    const legacy_hal::NanResponseMsg& legacy_response,
+    NanResponseMsgHeader* hidl_response) {
+  if (!hidl_response) {
+    return false;
+  }
+  hidl_response->status =
+      convertLegacyNanStatusTypeToHidl(legacy_response.status);
+  hidl_response->value = legacy_response.value;
+  hidl_response->responseType =
+      convertLegacyNanResponseTypeToHidl(legacy_response.response_type);
+  return true;
+}
+
+bool convertLegacyNanPublishResponseToHidl(
+    const legacy_hal::NanPublishResponse& /* legacy_response */,
+    NanPublishResponse* /* hidl_response */) {
+  return false;
+}
+
+bool convertLegacyNanSubscribeResponseToHidl(
+    const legacy_hal::NanSubscribeResponse& /* legacy_response */,
+    NanSubscribeResponse* /* hidl_response */) {
+  return false;
+}
+
+bool convertLegacyNanDataPathResponseToHidl(
+    const legacy_hal::NanDataPathRequestResponse& /* legacy_response */,
+    NanDataPathResponse* /* hidl_response */) {
+  return false;
+}
+
+bool convertLegacyNanCapabilitiesResponseToHidl(
+    const legacy_hal::NanCapabilities& /* legacy_response */,
+    NanCapabilitiesResponse* /* hidl_response */) {
+  return false;
+}
+
+bool convertLegacyNanPublishTerminatedIndToHidl(
+    const legacy_hal::NanPublishTerminatedInd& /* legacy_ind */,
+    NanPublishTerminatedInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanMatchIndToHidl(
+    const legacy_hal::NanMatchInd& /* legacy_ind */,
+    NanMatchInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanMatchExpiredIndToHidl(
+    const legacy_hal::NanMatchExpiredInd& /* legacy_ind */,
+    NanMatchExpiredInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanSubscribeTerminatedIndToHidl(
+    const legacy_hal::NanSubscribeTerminatedInd& /* legacy_ind */,
+    NanSubscribeTerminatedInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanFollowupIndToHidl(
+    const legacy_hal::NanFollowupInd& /* legacy_ind */,
+    NanFollowupInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanDiscEngEventIndToHidl(
+    const legacy_hal::NanDiscEngEventInd& /* legacy_ind */,
+    NanDiscEngEventInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanDisabledIndToHidl(
+    const legacy_hal::NanDisabledInd& /* legacy_ind */,
+    NanDisabledInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanBeaconSdfPayloadIndToHidl(
+    const legacy_hal::NanBeaconSdfPayloadInd& /* legacy_ind */,
+    NanBeaconSdfPayloadInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanDataPathRequestIndToHidl(
+    const legacy_hal::NanDataPathRequestInd& /* legacy_ind */,
+    NanDataPathRequestInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanDataPathConfirmIndToHidl(
+    const legacy_hal::NanDataPathConfirmInd& /* legacy_ind */,
+    NanDataPathConfirmInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanDataPathEndIndToHidl(
+    const legacy_hal::NanDataPathEndInd& /* legacy_ind */,
+    NanDataPathEndInd* /* hidl_ind */) {
+  return false;
+}
+
+bool convertLegacyNanTransmitFollowupIndToHidl(
+    const legacy_hal::NanTransmitFollowupInd& /* legacy_ind */,
+    NanTransmitFollowupInd* /* hidl_ind */) {
+  return false;
+}
+
+legacy_hal::wifi_rtt_type convertHidlRttTypeToLegacy(RttType type) {
+  switch (type) {
+    case RttType::ONE_SIDED:
+      return legacy_hal::RTT_TYPE_1_SIDED;
+    case RttType::TWO_SIDED:
+      return legacy_hal::RTT_TYPE_2_SIDED;
+  };
+  CHECK(false);
+}
+
+RttType convertLegacyRttTypeToHidl(legacy_hal::wifi_rtt_type type) {
+  switch (type) {
+    case legacy_hal::RTT_TYPE_1_SIDED:
+      return RttType::ONE_SIDED;
+    case legacy_hal::RTT_TYPE_2_SIDED:
+      return RttType::TWO_SIDED;
+  };
+  CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::rtt_peer_type convertHidlRttPeerTypeToLegacy(RttPeerType type) {
+  switch (type) {
+    case RttPeerType::AP:
+      return legacy_hal::RTT_PEER_AP;
+    case RttPeerType::STA:
+      return legacy_hal::RTT_PEER_STA;
+    case RttPeerType::P2P_GO:
+      return legacy_hal::RTT_PEER_P2P_GO;
+    case RttPeerType::P2P_CLIENT:
+      return legacy_hal::RTT_PEER_P2P_CLIENT;
+    case RttPeerType::NAN:
+      return legacy_hal::RTT_PEER_NAN;
+  };
+  CHECK(false);
+}
+
+legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy(
+    WifiChannelWidthInMhz type) {
+  switch (type) {
+    case WifiChannelWidthInMhz::WIDTH_20:
+      return legacy_hal::WIFI_CHAN_WIDTH_20;
+    case WifiChannelWidthInMhz::WIDTH_40:
+      return legacy_hal::WIFI_CHAN_WIDTH_40;
+    case WifiChannelWidthInMhz::WIDTH_80:
+      return legacy_hal::WIFI_CHAN_WIDTH_80;
+    case WifiChannelWidthInMhz::WIDTH_160:
+      return legacy_hal::WIFI_CHAN_WIDTH_160;
+    case WifiChannelWidthInMhz::WIDTH_80P80:
+      return legacy_hal::WIFI_CHAN_WIDTH_80P80;
+    case WifiChannelWidthInMhz::WIDTH_5:
+      return legacy_hal::WIFI_CHAN_WIDTH_5;
+    case WifiChannelWidthInMhz::WIDTH_10:
+      return legacy_hal::WIFI_CHAN_WIDTH_10;
+    case WifiChannelWidthInMhz::WIDTH_INVALID:
+      return legacy_hal::WIFI_CHAN_WIDTH_INVALID;
+  };
+  CHECK(false);
+}
+
+WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(
+    legacy_hal::wifi_channel_width type) {
+  switch (type) {
+    case legacy_hal::WIFI_CHAN_WIDTH_20:
+      return WifiChannelWidthInMhz::WIDTH_20;
+    case legacy_hal::WIFI_CHAN_WIDTH_40:
+      return WifiChannelWidthInMhz::WIDTH_40;
+    case legacy_hal::WIFI_CHAN_WIDTH_80:
+      return WifiChannelWidthInMhz::WIDTH_80;
+    case legacy_hal::WIFI_CHAN_WIDTH_160:
+      return WifiChannelWidthInMhz::WIDTH_160;
+    case legacy_hal::WIFI_CHAN_WIDTH_80P80:
+      return WifiChannelWidthInMhz::WIDTH_80P80;
+    case legacy_hal::WIFI_CHAN_WIDTH_5:
+      return WifiChannelWidthInMhz::WIDTH_5;
+    case legacy_hal::WIFI_CHAN_WIDTH_10:
+      return WifiChannelWidthInMhz::WIDTH_10;
+    case legacy_hal::WIFI_CHAN_WIDTH_INVALID:
+      return WifiChannelWidthInMhz::WIDTH_INVALID;
+  };
+  CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(RttPreamble type) {
+  switch (type) {
+    case RttPreamble::LEGACY:
+      return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY;
+    case RttPreamble::HT:
+      return legacy_hal::WIFI_RTT_PREAMBLE_HT;
+    case RttPreamble::VHT:
+      return legacy_hal::WIFI_RTT_PREAMBLE_VHT;
+  };
+  CHECK(false);
+}
+
+RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) {
+  switch (type) {
+    case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY:
+      return RttPreamble::LEGACY;
+    case legacy_hal::WIFI_RTT_PREAMBLE_HT:
+      return RttPreamble::HT;
+    case legacy_hal::WIFI_RTT_PREAMBLE_VHT:
+      return RttPreamble::VHT;
+  };
+  CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_rtt_bw convertHidlRttBwToLegacy(RttBw type) {
+  switch (type) {
+    case RttBw::BW_5MHZ:
+      return legacy_hal::WIFI_RTT_BW_5;
+    case RttBw::BW_10MHZ:
+      return legacy_hal::WIFI_RTT_BW_10;
+    case RttBw::BW_20MHZ:
+      return legacy_hal::WIFI_RTT_BW_20;
+    case RttBw::BW_40MHZ:
+      return legacy_hal::WIFI_RTT_BW_40;
+    case RttBw::BW_80MHZ:
+      return legacy_hal::WIFI_RTT_BW_80;
+    case RttBw::BW_160MHZ:
+      return legacy_hal::WIFI_RTT_BW_160;
+  };
+  CHECK(false);
+}
+
+RttBw convertLegacyRttBwToHidl(legacy_hal::wifi_rtt_bw type) {
+  switch (type) {
+    case legacy_hal::WIFI_RTT_BW_5:
+      return RttBw::BW_5MHZ;
+    case legacy_hal::WIFI_RTT_BW_10:
+      return RttBw::BW_10MHZ;
+    case legacy_hal::WIFI_RTT_BW_20:
+      return RttBw::BW_20MHZ;
+    case legacy_hal::WIFI_RTT_BW_40:
+      return RttBw::BW_40MHZ;
+    case legacy_hal::WIFI_RTT_BW_80:
+      return RttBw::BW_80MHZ;
+    case legacy_hal::WIFI_RTT_BW_160:
+      return RttBw::BW_160MHZ;
+  };
+  CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy(
+    RttMotionPattern type) {
+  switch (type) {
+    case RttMotionPattern::NOT_EXPECTED:
+      return legacy_hal::WIFI_MOTION_NOT_EXPECTED;
+    case RttMotionPattern::EXPECTED:
+      return legacy_hal::WIFI_MOTION_EXPECTED;
+    case RttMotionPattern::UNKNOWN:
+      return legacy_hal::WIFI_MOTION_UNKNOWN;
+  };
+  CHECK(false);
+}
+
+WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) {
+  switch (preamble) {
+    case 0:
+      return WifiRatePreamble::OFDM;
+    case 1:
+      return WifiRatePreamble::CCK;
+    case 2:
+      return WifiRatePreamble::HT;
+    case 3:
+      return WifiRatePreamble::VHT;
+    default:
+      return WifiRatePreamble::RESERVED;
+  };
+  CHECK(false) << "Unknown legacy preamble: " << preamble;
+}
+
+WifiRateNss convertLegacyWifiRateNssToHidl(uint8_t nss) {
+  switch (nss) {
+    case 0:
+      return WifiRateNss::NSS_1x1;
+    case 1:
+      return WifiRateNss::NSS_2x2;
+    case 2:
+      return WifiRateNss::NSS_3x3;
+    case 3:
+      return WifiRateNss::NSS_4x4;
+  };
+  CHECK(false) << "Unknown legacy nss: " << nss;
+  return {};
+}
+
+RttStatus convertLegacyRttStatusToHidl(legacy_hal::wifi_rtt_status status) {
+  switch (status) {
+    case legacy_hal::RTT_STATUS_SUCCESS:
+      return RttStatus::SUCCESS;
+    case legacy_hal::RTT_STATUS_FAILURE:
+      return RttStatus::FAILURE;
+    case legacy_hal::RTT_STATUS_FAIL_NO_RSP:
+      return RttStatus::FAIL_NO_RSP;
+    case legacy_hal::RTT_STATUS_FAIL_REJECTED:
+      return RttStatus::FAIL_REJECTED;
+    case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET:
+      return RttStatus::FAIL_NOT_SCHEDULED_YET;
+    case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT:
+      return RttStatus::FAIL_TM_TIMEOUT;
+    case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL:
+      return RttStatus::FAIL_AP_ON_DIFF_CHANNEL;
+    case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY:
+      return RttStatus::FAIL_NO_CAPABILITY;
+    case legacy_hal::RTT_STATUS_ABORTED:
+      return RttStatus::ABORTED;
+    case legacy_hal::RTT_STATUS_FAIL_INVALID_TS:
+      return RttStatus::FAIL_INVALID_TS;
+    case legacy_hal::RTT_STATUS_FAIL_PROTOCOL:
+      return RttStatus::FAIL_PROTOCOL;
+    case legacy_hal::RTT_STATUS_FAIL_SCHEDULE:
+      return RttStatus::FAIL_SCHEDULE;
+    case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER:
+      return RttStatus::FAIL_BUSY_TRY_LATER;
+    case legacy_hal::RTT_STATUS_INVALID_REQ:
+      return RttStatus::INVALID_REQ;
+    case legacy_hal::RTT_STATUS_NO_WIFI:
+      return RttStatus::NO_WIFI;
+    case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE:
+      return RttStatus::FAIL_FTM_PARAM_OVERRIDE;
+  };
+  CHECK(false) << "Unknown legacy status: " << status;
+}
+
+bool convertHidlWifiChannelInfoToLegacy(
+    const WifiChannelInfo& hidl_info,
+    legacy_hal::wifi_channel_info* legacy_info) {
+  if (!legacy_info) {
+    return false;
+  }
+  legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width);
+  legacy_info->center_freq = hidl_info.centerFreq;
+  legacy_info->center_freq0 = hidl_info.centerFreq0;
+  legacy_info->center_freq1 = hidl_info.centerFreq1;
+  return true;
+}
+
+bool convertLegacyWifiChannelInfoToHidl(
+    const legacy_hal::wifi_channel_info& legacy_info,
+    WifiChannelInfo* hidl_info) {
+  if (!hidl_info) {
+    return false;
+  }
+  hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width);
+  hidl_info->centerFreq = legacy_info.center_freq;
+  hidl_info->centerFreq0 = legacy_info.center_freq0;
+  hidl_info->centerFreq1 = legacy_info.center_freq1;
+  return true;
+}
+
+bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config,
+                                  legacy_hal::wifi_rtt_config* legacy_config) {
+  if (!legacy_config) {
+    return false;
+  }
+  CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr));
+  memcpy(legacy_config->addr, hidl_config.addr.data(), hidl_config.addr.size());
+  legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type);
+  legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer);
+  if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel,
+                                          &legacy_config->channel)) {
+    return false;
+  }
+  legacy_config->burst_period = hidl_config.burstPeriod;
+  legacy_config->num_burst = hidl_config.numBurst;
+  legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst;
+  legacy_config->num_retries_per_rtt_frame = hidl_config.numRetriesPerRttFrame;
+  legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr;
+  legacy_config->LCI_request = hidl_config.mustRequestLci;
+  legacy_config->LCR_request = hidl_config.mustRequestLcr;
+  legacy_config->burst_duration = hidl_config.burstDuration;
+  legacy_config->preamble =
+      convertHidlRttPreambleToLegacy(hidl_config.preamble);
+  legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw);
+  return true;
+}
+
+bool convertHidlVectorOfRttConfigToLegacy(
+    const std::vector<RttConfig>& hidl_configs,
+    std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
+  if (!legacy_configs) {
+    return false;
+  }
+  legacy_configs->clear();
+  for (const auto& hidl_config : hidl_configs) {
+    legacy_hal::wifi_rtt_config legacy_config;
+    if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) {
+      return false;
+    }
+    legacy_configs->push_back(legacy_config);
+  }
+  return true;
+}
+
+bool convertHidlRttLciInformationToLegacy(
+    const RttLciInformation& hidl_info,
+    legacy_hal::wifi_lci_information* legacy_info) {
+  if (!legacy_info) {
+    return false;
+  }
+  legacy_info->latitude = hidl_info.latitude;
+  legacy_info->longitude = hidl_info.longitude;
+  legacy_info->altitude = hidl_info.altitude;
+  legacy_info->latitude_unc = hidl_info.latitudeUnc;
+  legacy_info->longitude_unc = hidl_info.longitudeUnc;
+  legacy_info->altitude_unc = hidl_info.altitudeUnc;
+  legacy_info->motion_pattern =
+      convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern);
+  legacy_info->floor = hidl_info.floor;
+  legacy_info->height_above_floor = hidl_info.heightAboveFloor;
+  legacy_info->height_unc = hidl_info.heightUnc;
+  return true;
+}
+
+bool convertHidlRttLcrInformationToLegacy(
+    const RttLcrInformation& hidl_info,
+    legacy_hal::wifi_lcr_information* legacy_info) {
+  if (!legacy_info) {
+    return false;
+  }
+  CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code));
+  memcpy(legacy_info->country_code,
+         hidl_info.countryCode.data(),
+         hidl_info.countryCode.size());
+  if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) {
+    return false;
+  }
+  legacy_info->length = hidl_info.civicInfo.size();
+  memcpy(legacy_info->civic_info,
+         hidl_info.civicInfo.c_str(),
+         hidl_info.civicInfo.size());
+  return true;
+}
+
+bool convertHidlRttResponderToLegacy(
+    const RttResponder& hidl_responder,
+    legacy_hal::wifi_rtt_responder* legacy_responder) {
+  if (!legacy_responder) {
+    return false;
+  }
+  if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel,
+                                          &legacy_responder->channel)) {
+    return false;
+  }
+  legacy_responder->preamble =
+      convertHidlRttPreambleToLegacy(hidl_responder.preamble);
+  return true;
+}
+
+bool convertLegacyRttResponderToHidl(
+    const legacy_hal::wifi_rtt_responder& legacy_responder,
+    RttResponder* hidl_responder) {
+  if (!hidl_responder) {
+    return false;
+  }
+  if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel,
+                                          &hidl_responder->channel)) {
+    return false;
+  }
+  hidl_responder->preamble =
+      convertLegacyRttPreambleToHidl(legacy_responder.preamble);
+  return true;
+}
+
+bool convertLegacyRttCapabilitiesToHidl(
+    const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
+    RttCapabilities* hidl_capabilities) {
+  if (!hidl_capabilities) {
+    return false;
+  }
+  hidl_capabilities->rttOneSidedSupported =
+      legacy_capabilities.rtt_one_sided_supported;
+  hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported;
+  hidl_capabilities->lciSupported = legacy_capabilities.lci_support;
+  hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support;
+  hidl_capabilities->responderSupported =
+      legacy_capabilities.responder_supported;
+  for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY,
+                          legacy_hal::WIFI_RTT_PREAMBLE_HT,
+                          legacy_hal::WIFI_RTT_PREAMBLE_VHT}) {
+    if (legacy_capabilities.preamble_support & flag) {
+      hidl_capabilities->preambleSupport |=
+          static_cast<std::underlying_type<RttPreamble>::type>(
+              convertLegacyRttPreambleToHidl(flag));
+    }
+  }
+  for (const auto flag : {legacy_hal::WIFI_RTT_BW_5,
+                          legacy_hal::WIFI_RTT_BW_10,
+                          legacy_hal::WIFI_RTT_BW_20,
+                          legacy_hal::WIFI_RTT_BW_40,
+                          legacy_hal::WIFI_RTT_BW_80,
+                          legacy_hal::WIFI_RTT_BW_160}) {
+    if (legacy_capabilities.bw_support & flag) {
+      hidl_capabilities->bwSupport |=
+          static_cast<std::underlying_type<RttBw>::type>(
+              convertLegacyRttBwToHidl(flag));
+    }
+  }
+  hidl_capabilities->mcVersion = legacy_capabilities.mc_version;
+  return true;
+}
+
+bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
+                                     WifiRateInfo* hidl_rate) {
+  if (!hidl_rate) {
+    return false;
+  }
+  hidl_rate->preamble =
+      convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble);
+  hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss);
+  hidl_rate->bw = convertLegacyWifiChannelWidthToHidl(
+      static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw));
+  hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx;
+  hidl_rate->bitRateInKbps = legacy_rate.bitrate;
+  return true;
+}
+
+bool convertLegacyRttResultToHidl(
+    const legacy_hal::wifi_rtt_result& legacy_result, RttResult* hidl_result) {
+  if (!hidl_result) {
+    return false;
+  }
+  CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size());
+  memcpy(
+      hidl_result->addr.data(), legacy_result.addr, sizeof(legacy_result.addr));
+  hidl_result->burstNum = legacy_result.burst_num;
+  hidl_result->measurementNumber = legacy_result.measurement_number;
+  hidl_result->successNumber = legacy_result.success_number;
+  hidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer;
+  hidl_result->status = convertLegacyRttStatusToHidl(legacy_result.status);
+  hidl_result->retryAfterDuration = legacy_result.retry_after_duration;
+  hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type);
+  hidl_result->rssi = legacy_result.rssi;
+  hidl_result->rssiSpread = legacy_result.rssi_spread;
+  if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate,
+                                       &hidl_result->txRate)) {
+    return false;
+  }
+  if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate,
+                                       &hidl_result->rxRate)) {
+    return false;
+  }
+  hidl_result->rtt = legacy_result.rtt;
+  hidl_result->rttSd = legacy_result.rtt_sd;
+  hidl_result->rttSpread = legacy_result.rtt_spread;
+  hidl_result->distanceInMm = legacy_result.distance_mm;
+  hidl_result->distanceSdInMm = legacy_result.distance_sd_mm;
+  hidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm;
+  hidl_result->timeStampInUs = legacy_result.ts;
+  hidl_result->burstDurationInMs = legacy_result.burst_duration;
+  hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num;
+  if (!convertLegacyIeToHidl(*legacy_result.LCI, &hidl_result->lci)) {
+    return false;
+  }
+  if (!convertLegacyIeToHidl(*legacy_result.LCR, &hidl_result->lcr)) {
+    return false;
+  }
+  return true;
+}
+
+bool convertLegacyVectorOfRttResultToHidl(
+    const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
+    std::vector<RttResult>* hidl_results) {
+  if (!hidl_results) {
+    return false;
+  }
+  hidl_results->clear();
+  for (const auto legacy_result : legacy_results) {
+    RttResult hidl_result;
+    if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) {
+      return false;
+    }
+    hidl_results->push_back(hidl_result);
+  }
+  return true;
+}
 }  // namespace hidl_struct_util
 }  // namespace implementation
 }  // namespace V1_0
diff --git a/wifi/1.0/default/hidl_struct_util.h b/wifi/1.0/default/hidl_struct_util.h
index 6c91e03..3ff94fd 100644
--- a/wifi/1.0/default/hidl_struct_util.h
+++ b/wifi/1.0/default/hidl_struct_util.h
@@ -36,29 +36,160 @@
 namespace implementation {
 namespace hidl_struct_util {
 
-// Convert hidl gscan params to legacy gscan params.
-bool convertHidlScanParamsToLegacy(
+// Chip conversion methods.
+bool convertLegacyFeaturesToHidlChipCapabilities(
+    uint32_t legacy_logger_feature_set, uint32_t* hidl_caps);
+bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
+    const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
+    std::vector<WifiDebugRingBufferStatus>* hidl_status_vec);
+bool convertLegacyWakeReasonStatsToHidl(
+    const legacy_hal::WakeReasonStats& legacy_stats,
+    WifiDebugHostWakeReasonStats* hidl_stats);
+
+// STA iface conversion methods.
+bool convertLegacyFeaturesToHidlStaCapabilities(
+    uint32_t legacy_feature_set,
+    uint32_t legacy_logger_feature_set,
+    uint32_t* hidl_caps);
+bool convertLegacyApfCapabilitiesToHidl(
+    const legacy_hal::PacketFilterCapabilities& legacy_caps,
+    StaApfPacketFilterCapabilities* hidl_caps);
+bool convertLegacyGscanCapabilitiesToHidl(
+    const legacy_hal::wifi_gscan_capabilities& legacy_caps,
+    StaBackgroundScanCapabilities* hidl_caps);
+legacy_hal::wifi_band convertHidlGscanBandToLegacy(StaBackgroundScanBand band);
+bool convertHidlGscanParamsToLegacy(
     const StaBackgroundScanParameters& hidl_scan_params,
     legacy_hal::wifi_scan_cmd_params* legacy_scan_params);
-// Convert the blob of packed IE elements to vector of
-// |WifiInformationElement| structures.
-bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob,
-                               uint32_t ie_blob_len,
-                               std::vector<WifiInformationElement>* hidl_ies);
 // |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11
 // Information Elements (IEs)
-bool convertLegacyScanResultToHidl(
+bool convertLegacyGscanResultToHidl(
     const legacy_hal::wifi_scan_result& legacy_scan_result,
     bool has_ie_data,
     StaScanResult* hidl_scan_result);
 // |cached_results| is assumed to not include IEs.
-bool convertLegacyVectorOfCachedScanResultsToHidl(
+bool convertLegacyVectorOfCachedGscanResultsToHidl(
     const std::vector<legacy_hal::wifi_cached_scan_results>&
         legacy_cached_scan_results,
     std::vector<StaScanData>* hidl_scan_datas);
 bool convertLegacyLinkLayerStatsToHidl(
     const legacy_hal::LinkLayerStats& legacy_stats,
     StaLinkLayerStats* hidl_stats);
+bool convertLegacyVectorOfDebugTxPacketFateToHidl(
+    const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
+    std::vector<WifiDebugTxPacketFateReport>* hidl_fates);
+bool convertLegacyVectorOfDebugRxPacketFateToHidl(
+    const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
+    std::vector<WifiDebugRxPacketFateReport>* hidl_fates);
+
+// NAN iface conversion methods.
+bool convertHidlNanEnableRequestToLegacy(
+    const NanEnableRequest& hidl_request,
+    legacy_hal::NanEnableRequest* legacy_request);
+bool convertHidlNanPublishRequestToLegacy(
+    const NanPublishRequest& hidl_request,
+    legacy_hal::NanPublishRequest* legacy_request);
+bool convertHidlNanPublishCancelRequestToLegacy(
+    const NanPublishCancelRequest& hidl_request,
+    legacy_hal::NanPublishCancelRequest* legacy_request);
+bool convertHidlNanSubscribeRequestToLegacy(
+    const NanSubscribeRequest& hidl_request,
+    legacy_hal::NanSubscribeRequest* legacy_request);
+bool convertHidlNanSubscribeCancelRequestToLegacy(
+    const NanSubscribeCancelRequest& hidl_request,
+    legacy_hal::NanSubscribeCancelRequest* legacy_request);
+bool convertHidlNanTransmitFollowupRequestToLegacy(
+    const NanTransmitFollowupRequest& hidl_request,
+    legacy_hal::NanTransmitFollowupRequest* legacy_request);
+bool convertHidlNanConfigRequestToLegacy(
+    const NanConfigRequest& hidl_request,
+    legacy_hal::NanConfigRequest* legacy_request);
+bool convertHidlNanBeaconSdfPayloadRequestToLegacy(
+    const NanBeaconSdfPayloadRequest& hidl_request,
+    legacy_hal::NanBeaconSdfPayloadRequest* legacy_request);
+bool convertHidlNanDataPathInitiatorRequestToLegacy(
+    const NanDataPathInitiatorRequest& hidl_request,
+    legacy_hal::NanDataPathInitiatorRequest* legacy_request);
+bool convertHidlNanDataPathIndicationResponseToLegacy(
+    const NanDataPathIndicationResponse& hidl_response,
+    legacy_hal::NanDataPathIndicationResponse* legacy_response);
+bool convertHidlNanDataPathEndRequestToLegacy(
+    const NanDataPathEndRequest& hidl_request,
+    legacy_hal::NanDataPathEndRequest* legacy_request);
+bool convertLegacyNanResponseHeaderToHidl(
+    const legacy_hal::NanResponseMsg& legacy_response,
+    NanResponseMsgHeader* hidl_response);
+bool convertLegacyNanPublishResponseToHidl(
+    const legacy_hal::NanPublishResponse& legacy_response,
+    NanPublishResponse* hidl_response);
+bool convertLegacyNanSubscribeResponseToHidl(
+    const legacy_hal::NanSubscribeResponse& legacy_response,
+    NanSubscribeResponse* hidl_response);
+bool convertLegacyNanDataPathResponseToHidl(
+    const legacy_hal::NanDataPathRequestResponse& legacy_response,
+    NanDataPathResponse* hidl_response);
+bool convertLegacyNanCapabilitiesResponseToHidl(
+    const legacy_hal::NanCapabilities& legacy_response,
+    NanCapabilitiesResponse* hidl_response);
+bool convertLegacyNanPublishTerminatedIndToHidl(
+    const legacy_hal::NanPublishTerminatedInd& legacy_ind,
+    NanPublishTerminatedInd* hidl_ind);
+bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind,
+                                    NanMatchInd* hidl_ind);
+bool convertLegacyNanMatchExpiredIndToHidl(
+    const legacy_hal::NanMatchExpiredInd& legacy_ind,
+    NanMatchExpiredInd* hidl_ind);
+bool convertLegacyNanSubscribeTerminatedIndToHidl(
+    const legacy_hal::NanSubscribeTerminatedInd& legacy_ind,
+    NanSubscribeTerminatedInd* hidl_ind);
+bool convertLegacyNanFollowupIndToHidl(
+    const legacy_hal::NanFollowupInd& legacy_ind, NanFollowupInd* hidl_ind);
+bool convertLegacyNanDiscEngEventIndToHidl(
+    const legacy_hal::NanDiscEngEventInd& legacy_ind,
+    NanDiscEngEventInd* hidl_ind);
+bool convertLegacyNanDisabledIndToHidl(
+    const legacy_hal::NanDisabledInd& legacy_ind, NanDisabledInd* hidl_ind);
+bool convertLegacyNanBeaconSdfPayloadIndToHidl(
+    const legacy_hal::NanBeaconSdfPayloadInd& legacy_ind,
+    NanBeaconSdfPayloadInd* hidl_ind);
+bool convertLegacyNanDataPathRequestIndToHidl(
+    const legacy_hal::NanDataPathRequestInd& legacy_ind,
+    NanDataPathRequestInd* hidl_ind);
+bool convertLegacyNanDataPathConfirmIndToHidl(
+    const legacy_hal::NanDataPathConfirmInd& legacy_ind,
+    NanDataPathConfirmInd* hidl_ind);
+bool convertLegacyNanDataPathEndIndToHidl(
+    const legacy_hal::NanDataPathEndInd& legacy_ind,
+    NanDataPathEndInd* hidl_ind);
+bool convertLegacyNanTransmitFollowupIndToHidl(
+    const legacy_hal::NanTransmitFollowupInd& legacy_ind,
+    NanTransmitFollowupInd* hidl_ind);
+
+// RTT controller conversion methods.
+bool convertHidlVectorOfRttConfigToLegacy(
+    const std::vector<RttConfig>& hidl_configs,
+    std::vector<legacy_hal::wifi_rtt_config>* legacy_configs);
+bool convertHidlRttLciInformationToLegacy(
+    const RttLciInformation& hidl_info,
+    legacy_hal::wifi_lci_information* legacy_info);
+bool convertHidlRttLcrInformationToLegacy(
+    const RttLcrInformation& hidl_info,
+    legacy_hal::wifi_lcr_information* legacy_info);
+bool convertHidlRttResponderToLegacy(
+    const RttResponder& hidl_responder,
+    legacy_hal::wifi_rtt_responder* legacy_responder);
+bool convertHidlWifiChannelInfoToLegacy(
+    const WifiChannelInfo& hidl_info,
+    legacy_hal::wifi_channel_info* legacy_info);
+bool convertLegacyRttResponderToHidl(
+    const legacy_hal::wifi_rtt_responder& legacy_responder,
+    RttResponder* hidl_responder);
+bool convertLegacyRttCapabilitiesToHidl(
+    const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
+    RttCapabilities* hidl_capabilities);
+bool convertLegacyVectorOfRttResultToHidl(
+    const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
+    std::vector<RttResult>* hidl_results);
 }  // namespace hidl_struct_util
 }  // namespace implementation
 }  // namespace V1_0
diff --git a/wifi/1.0/default/wifi.cpp b/wifi/1.0/default/wifi.cpp
index 19f7e53..30adcc0 100644
--- a/wifi/1.0/default/wifi.cpp
+++ b/wifi/1.0/default/wifi.cpp
@@ -34,6 +34,7 @@
 
 Wifi::Wifi()
     : legacy_hal_(new legacy_hal::WifiLegacyHal()),
+      mode_controller_(new mode_controller::WifiModeController()),
       run_state_(RunState::STOPPED) {}
 
 bool Wifi::isValid() {
@@ -96,25 +97,29 @@
     return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
                             "HAL is stopping");
   }
-
-  LOG(INFO) << "Starting HAL";
-  legacy_hal::wifi_error legacy_status = legacy_hal_->start();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to start Wifi HAL: "
-               << legacyErrorToString(legacy_status);
-    return createWifiStatusFromLegacyError(legacy_status,
-                                           "Failed to start HAL");
+  WifiStatus wifi_status = initializeLegacyHal();
+  if (wifi_status.code == WifiStatusCode::SUCCESS) {
+    // Create the chip instance once the HAL is started.
+    chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_);
+    run_state_ = RunState::STARTED;
+    for (const auto& callback : event_callbacks_) {
+      if (!callback->onStart().getStatus().isOk()) {
+        LOG(ERROR) << "Failed to invoke onStart callback";
+      };
+    }
+    for (const auto& callback : event_callbacks_) {
+      if (!callback->onFailure(wifi_status).getStatus().isOk()) {
+        LOG(ERROR) << "Failed to invoke onFailure callback";
+      }
+    }
+  } else {
+    for (const auto& callback : event_callbacks_) {
+      if (!callback->onFailure(wifi_status).getStatus().isOk()) {
+        LOG(ERROR) << "Failed to invoke onFailure callback";
+      }
+    }
   }
-
-  // Create the chip instance once the HAL is started.
-  chip_ = new WifiChip(kChipId, legacy_hal_);
-  run_state_ = RunState::STARTED;
-  for (const auto& callback : event_callbacks_) {
-    if (!callback->onStart().getStatus().isOk()) {
-      LOG(ERROR) << "Failed to invoke onStart callback";
-    };
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+  return wifi_status;
 }
 
 WifiStatus Wifi::stopInternal() {
@@ -124,34 +129,21 @@
     return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
                             "HAL is stopping");
   }
-
-  LOG(INFO) << "Stopping HAL";
-  run_state_ = RunState::STOPPING;
-  const auto on_complete_callback_ = [&]() {
-    if (chip_.get()) {
-      chip_->invalidate();
-    }
-    chip_.clear();
-    run_state_ = RunState::STOPPED;
+  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController();
+  if (wifi_status.code == WifiStatusCode::SUCCESS) {
     for (const auto& callback : event_callbacks_) {
       if (!callback->onStop().getStatus().isOk()) {
         LOG(ERROR) << "Failed to invoke onStop callback";
       };
     }
-  };
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_->stop(on_complete_callback_);
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to stop Wifi HAL: "
-               << legacyErrorToString(legacy_status);
-    WifiStatus wifi_status =
-        createWifiStatusFromLegacyError(legacy_status, "Failed to stop HAL");
+  } else {
     for (const auto& callback : event_callbacks_) {
-      callback->onFailure(wifi_status);
+      if (!callback->onFailure(wifi_status).getStatus().isOk()) {
+        LOG(ERROR) << "Failed to invoke onFailure callback";
+      }
     }
-    return wifi_status;
   }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+  return wifi_status;
 }
 
 std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {
@@ -171,6 +163,41 @@
   }
   return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
 }
+
+WifiStatus Wifi::initializeLegacyHal() {
+  LOG(INFO) << "Initializing legacy HAL";
+  legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    LOG(ERROR) << "Failed to initialize legacy HAL: "
+               << legacyErrorToString(legacy_status);
+    return createWifiStatusFromLegacyError(legacy_status);
+  }
+  return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() {
+  LOG(INFO) << "Stopping legacy HAL";
+  run_state_ = RunState::STOPPING;
+  const auto on_complete_callback_ = [&]() {
+    if (chip_.get()) {
+      chip_->invalidate();
+    }
+    chip_.clear();
+    run_state_ = RunState::STOPPED;
+  };
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_->stop(on_complete_callback_);
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    LOG(ERROR) << "Failed to stop legacy HAL: "
+               << legacyErrorToString(legacy_status);
+    return createWifiStatusFromLegacyError(legacy_status);
+  }
+  if (!mode_controller_->deinitialize()) {
+    LOG(ERROR) << "Failed to deinitialize firmware mode controller";
+    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+  }
+  return createWifiStatus(WifiStatusCode::SUCCESS);
+}
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace wifi
diff --git a/wifi/1.0/default/wifi.h b/wifi/1.0/default/wifi.h
index 7872303..40d3552 100644
--- a/wifi/1.0/default/wifi.h
+++ b/wifi/1.0/default/wifi.h
@@ -25,6 +25,7 @@
 
 #include "wifi_chip.h"
 #include "wifi_legacy_hal.h"
+#include "wifi_mode_controller.h"
 
 namespace android {
 namespace hardware {
@@ -62,9 +63,13 @@
   std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
   std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
 
+  WifiStatus initializeLegacyHal();
+  WifiStatus stopLegacyHalAndDeinitializeModeController();
+
   // Instance is created in this root level |IWifi| HIDL interface object
   // and shared with all the child HIDL interface objects.
   std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+  std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
   RunState run_state_;
   std::vector<sp<IWifiEventCallback>> event_callbacks_;
   sp<WifiChip> chip_;
diff --git a/wifi/1.0/default/wifi_chip.cpp b/wifi/1.0/default/wifi_chip.cpp
index 3ab6052..af19491 100644
--- a/wifi/1.0/default/wifi_chip.cpp
+++ b/wifi/1.0/default/wifi_chip.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include "hidl_return_util.h"
+#include "hidl_struct_util.h"
 #include "wifi_chip.h"
 #include "wifi_status_util.h"
 
@@ -24,6 +25,12 @@
 using android::sp;
 using android::hardware::hidl_vec;
 using android::hardware::hidl_string;
+using android::hardware::wifi::V1_0::IWifiChip;
+using android::hardware::wifi::V1_0::IfaceType;
+
+constexpr uint32_t kStaChipModeId = 0;
+constexpr uint32_t kApChipModeId = 1;
+constexpr uint32_t kInvalidModeId = UINT32_MAX;
 
 template <typename Iface>
 void invalidateAndClear(sp<Iface>& iface) {
@@ -41,9 +48,15 @@
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
-WifiChip::WifiChip(ChipId chip_id,
-                   const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : chip_id_(chip_id), legacy_hal_(legacy_hal), is_valid_(true) {}
+WifiChip::WifiChip(
+    ChipId chip_id,
+    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+    const std::weak_ptr<mode_controller::WifiModeController> mode_controller)
+    : chip_id_(chip_id),
+      legacy_hal_(legacy_hal),
+      mode_controller_(mode_controller),
+      is_valid_(true),
+      current_mode_id_(kInvalidModeId) {}
 
 void WifiChip::invalidate() {
   invalidateAndRemoveAllIfaces();
@@ -295,25 +308,101 @@
 }
 
 std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
-  // TODO add implementation
-  return {createWifiStatus(WifiStatusCode::SUCCESS), 0};
+  legacy_hal::wifi_error legacy_status;
+  uint32_t legacy_logger_feature_set;
+  std::tie(legacy_status, legacy_logger_feature_set) =
+      legacy_hal_.lock()->getLoggerSupportedFeatureSet();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), 0};
+  }
+  uint32_t hidl_caps;
+  if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
+          legacy_logger_feature_set, &hidl_caps)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
 std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
 WifiChip::getAvailableModesInternal() {
-  // TODO add implementation
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  // The chip combination supported for current devices is fixed for now with
+  // 2 separate modes of operation:
+  // Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN iface operations
+  // concurrently.
+  // Mode 2 (AP mode): Will support 1 AP iface operations.
+  // TODO (b/32997844): Read this from some device specific flags in the
+  // makefile.
+  // STA mode iface combinations.
+  const IWifiChip::ChipIfaceCombinationLimit
+      sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
+  const IWifiChip::ChipIfaceCombinationLimit
+      sta_chip_iface_combination_limit_2 = {{IfaceType::P2P, IfaceType::NAN},
+                                            1};
+  const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
+      {sta_chip_iface_combination_limit_1, sta_chip_iface_combination_limit_2}};
+  const IWifiChip::ChipMode sta_chip_mode = {kStaChipModeId,
+                                             {sta_chip_iface_combination}};
+  // AP mode iface combinations.
+  const IWifiChip::ChipIfaceCombinationLimit ap_chip_iface_combination_limit = {
+      {IfaceType::AP}, 1};
+  const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
+      {ap_chip_iface_combination_limit}};
+  const IWifiChip::ChipMode ap_chip_mode = {kApChipModeId,
+                                            {ap_chip_iface_combination}};
+  return {createWifiStatus(WifiStatusCode::SUCCESS),
+          {sta_chip_mode, ap_chip_mode}};
 }
 
-WifiStatus WifiChip::configureChipInternal(uint32_t /* mode_id */) {
-  invalidateAndRemoveAllIfaces();
-  // TODO add implementation
+WifiStatus WifiChip::configureChipInternal(uint32_t mode_id) {
+  if (mode_id != kStaChipModeId && mode_id != kApChipModeId) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  if (mode_id == current_mode_id_) {
+    LOG(DEBUG) << "Already in the specified mode " << mode_id;
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+  }
+  // If the chip is already configured in a different mode, stop
+  // the legacy HAL and then start it after firmware mode change.
+  if (current_mode_id_ != kInvalidModeId) {
+    invalidateAndRemoveAllIfaces();
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop([]() {});
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+      LOG(ERROR) << "Failed to stop legacy HAL: "
+                 << legacyErrorToString(legacy_status);
+      // TODO(b/33038823): Need to invoke onChipReconfigureFailure()
+      return createWifiStatusFromLegacyError(legacy_status);
+    }
+  }
+  bool success;
+  if (mode_id == kStaChipModeId) {
+    success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
+  } else {
+    success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
+  }
+  if (!success) {
+    // TODO(b/33038823): Need to invoke onChipReconfigureFailure()
+    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+  }
+  legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    LOG(ERROR) << "Failed to start legacy HAL: "
+               << legacyErrorToString(legacy_status);
+    // TODO(b/33038823): Need to invoke onChipReconfigureFailure()
+    return createWifiStatusFromLegacyError(legacy_status);
+  }
+  for (const auto& callback : event_callbacks_) {
+    callback->onChipReconfigured(mode_id);
+  }
+  current_mode_id_ = mode_id;
   return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
 std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
-  // TODO add implementation
-  return {createWifiStatus(WifiStatusCode::SUCCESS), 0};
+  if (current_mode_id_ == kInvalidModeId) {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
+            current_mode_id_};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
 }
 
 std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
@@ -376,7 +465,9 @@
 }
 
 std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
-  // TODO(b/31997422): Disallow this based on the chip combination.
+  if (current_mode_id_ != kApChipModeId || ap_iface_.get()) {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+  }
   std::string ifname = legacy_hal_.lock()->getApIfaceName();
   ap_iface_ = new WifiApIface(ifname, legacy_hal_);
   return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_};
@@ -401,7 +492,11 @@
 }
 
 std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
-  // TODO(b/31997422): Disallow this based on the chip combination.
+  // Only 1 of NAN or P2P iface can be active at a time.
+  if (current_mode_id_ != kStaChipModeId || nan_iface_.get() ||
+      p2p_iface_.get()) {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+  }
   std::string ifname = legacy_hal_.lock()->getNanIfaceName();
   nan_iface_ = new WifiNanIface(ifname, legacy_hal_);
   return {createWifiStatus(WifiStatusCode::SUCCESS), nan_iface_};
@@ -426,7 +521,11 @@
 }
 
 std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
-  // TODO(b/31997422): Disallow this based on the chip combination.
+  // Only 1 of NAN or P2P iface can be active at a time.
+  if (current_mode_id_ != kStaChipModeId || p2p_iface_.get() ||
+      nan_iface_.get()) {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+  }
   std::string ifname = legacy_hal_.lock()->getP2pIfaceName();
   p2p_iface_ = new WifiP2pIface(ifname, legacy_hal_);
   return {createWifiStatus(WifiStatusCode::SUCCESS), p2p_iface_};
@@ -451,7 +550,9 @@
 }
 
 std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
-  // TODO(b/31997422): Disallow this based on the chip combination.
+  if (current_mode_id_ != kStaChipModeId || sta_iface_.get()) {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+  }
   std::string ifname = legacy_hal_.lock()->getStaIfaceName();
   sta_iface_ = new WifiStaIface(ifname, legacy_hal_);
   return {createWifiStatus(WifiStatusCode::SUCCESS), sta_iface_};
@@ -484,29 +585,61 @@
 
 std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
 WifiChip::getDebugRingBuffersStatusInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  std::vector<legacy_hal::wifi_ring_buffer_status>
+      legacy_ring_buffer_status_vec;
+  std::tie(legacy_status, legacy_ring_buffer_status_vec) =
+      legacy_hal_.lock()->getRingBuffersStatus();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec;
+  if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl(
+          legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS),
+          hidl_ring_buffer_status_vec};
 }
 
 WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
-    const hidl_string& /* ring_name */,
-    WifiDebugRingBufferVerboseLevel /* verbose_level */,
-    uint32_t /* max_interval_in_sec */,
-    uint32_t /* min_data_size_in_bytes */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    const hidl_string& ring_name,
+    WifiDebugRingBufferVerboseLevel verbose_level,
+    uint32_t max_interval_in_sec,
+    uint32_t min_data_size_in_bytes) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->startRingBufferLogging(
+          ring_name,
+          static_cast<
+              std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
+              verbose_level),
+          max_interval_in_sec,
+          min_data_size_in_bytes);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(
-    const hidl_string& /* ring_name */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    const hidl_string& ring_name) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->getRingBufferData(ring_name);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
 WifiChip::getDebugHostWakeReasonStatsInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  legacy_hal::WakeReasonStats legacy_stats;
+  std::tie(legacy_status, legacy_stats) =
+      legacy_hal_.lock()->getWakeReasonStats();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  WifiDebugHostWakeReasonStats hidl_stats;
+  if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats,
+                                                            &hidl_stats)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
 }
 
 }  // namespace implementation
diff --git a/wifi/1.0/default/wifi_chip.h b/wifi/1.0/default/wifi_chip.h
index c1a7173..764445f 100644
--- a/wifi/1.0/default/wifi_chip.h
+++ b/wifi/1.0/default/wifi_chip.h
@@ -24,6 +24,7 @@
 
 #include "wifi_ap_iface.h"
 #include "wifi_legacy_hal.h"
+#include "wifi_mode_controller.h"
 #include "wifi_nan_iface.h"
 #include "wifi_p2p_iface.h"
 #include "wifi_rtt_controller.h"
@@ -42,8 +43,10 @@
  */
 class WifiChip : public IWifiChip {
  public:
-  WifiChip(ChipId chip_id,
-           const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+  WifiChip(
+      ChipId chip_id,
+      const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+      const std::weak_ptr<mode_controller::WifiModeController> mode_controller);
   // HIDL does not provide a built-in mechanism to let the server invalidate
   // a HIDL interface object after creation. If any client process holds onto
   // a reference to the object in their context, any method calls on that
@@ -156,6 +159,7 @@
 
   ChipId chip_id_;
   std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+  std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
   std::vector<sp<IWifiChipEventCallback>> event_callbacks_;
   sp<WifiApIface> ap_iface_;
   sp<WifiNanIface> nan_iface_;
@@ -163,6 +167,7 @@
   sp<WifiStaIface> sta_iface_;
   std::vector<sp<WifiRttController>> rtt_controllers_;
   bool is_valid_;
+  uint32_t current_mode_id_;
 
   DISALLOW_COPY_AND_ASSIGN(WifiChip);
 };
diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp
index 560a273..bf61d83 100644
--- a/wifi/1.0/default/wifi_legacy_hal.cpp
+++ b/wifi/1.0/default/wifi_legacy_hal.cpp
@@ -18,10 +18,11 @@
 
 #include <android-base/logging.h>
 #include <cutils/properties.h>
-#include <wifi_system/interface_tool.h>
 
 #include "wifi_legacy_hal.h"
 
+using android::wifi_system::InterfaceTool;
+
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -89,16 +90,25 @@
 // Callback to be invoked for link layer stats results.
 std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
     on_link_layer_stats_result_internal_callback;
-void onLinkLayerStatsDataResult(wifi_request_id id,
-                                wifi_iface_stat* iface_stat,
-                                int num_radios,
-                                wifi_radio_stat* radio_stat) {
+void onLinkLayerStatsResult(wifi_request_id id,
+                            wifi_iface_stat* iface_stat,
+                            int num_radios,
+                            wifi_radio_stat* radio_stat) {
   if (on_link_layer_stats_result_internal_callback) {
     on_link_layer_stats_result_internal_callback(
         id, iface_stat, num_radios, radio_stat);
   }
 }
 
+// Callback to be invoked for rssi threshold breach.
+std::function<void((wifi_request_id, uint8_t*, int8_t))>
+    on_rssi_threshold_breached_internal_callback;
+void onRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, int8_t rssi) {
+  if (on_rssi_threshold_breached_internal_callback) {
+    on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
+  }
+}
+
 // Callback to be invoked for ring buffer data indication.
 std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
     on_ring_buffer_data_internal_callback;
@@ -241,12 +251,7 @@
       wlan_interface_handle_(nullptr),
       awaiting_event_loop_termination_(false) {}
 
-wifi_error WifiLegacyHal::start() {
-  // Ensure that we're starting in a good state.
-  CHECK(!global_handle_ && !wlan_interface_handle_ &&
-        !awaiting_event_loop_termination_);
-
-  android::wifi_system::InterfaceTool if_tool;
+wifi_error WifiLegacyHal::initialize() {
   // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool
   // for now is this function call which we can directly call.
   wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
@@ -254,13 +259,19 @@
     LOG(ERROR) << "Failed to initialize legacy hal function table";
     return WIFI_ERROR_UNKNOWN;
   }
-  if (!if_tool.SetWifiUpState(true)) {
+  return WIFI_SUCCESS;
+}
+
+wifi_error WifiLegacyHal::start() {
+  // Ensure that we're starting in a good state.
+  CHECK(global_func_table_.wifi_initialize && !global_handle_ &&
+        !wlan_interface_handle_ && !awaiting_event_loop_termination_);
+  if (!iface_tool_.SetWifiUpState(true)) {
     LOG(ERROR) << "Failed to set WiFi interface up";
     return WIFI_ERROR_UNKNOWN;
   }
-
   LOG(INFO) << "Starting legacy HAL";
-  status = global_func_table_.wifi_initialize(&global_handle_);
+  wifi_error status = global_func_table_.wifi_initialize(&global_handle_);
   if (status != WIFI_SUCCESS || !global_handle_) {
     LOG(ERROR) << "Failed to retrieve global handle";
     return status;
@@ -280,10 +291,11 @@
   LOG(INFO) << "Stopping legacy HAL";
   on_stop_complete_internal_callback = [&](wifi_handle handle) {
     CHECK_EQ(global_handle_, handle) << "Handle mismatch";
-    on_stop_complete_user_callback();
     // Invalidate all the internal pointers now that the HAL is
     // stopped.
     invalidate();
+    iface_tool_.SetWifiUpState(false);
+    on_stop_complete_user_callback();
   };
   awaiting_event_loop_termination_ = true;
   global_func_table_.wifi_cleanup(global_handle_, onStopComplete);
@@ -534,11 +546,57 @@
   };
 
   wifi_error status = global_func_table_.wifi_get_link_stats(
-      0, wlan_interface_handle_, {onLinkLayerStatsDataResult});
+      0, wlan_interface_handle_, {onLinkLayerStatsResult});
   on_link_layer_stats_result_internal_callback = nullptr;
   return {status, link_stats};
 }
 
+wifi_error WifiLegacyHal::startRssiMonitoring(
+    wifi_request_id id,
+    int8_t max_rssi,
+    int8_t min_rssi,
+    const on_rssi_threshold_breached_callback&
+        on_threshold_breached_user_callback) {
+  if (on_rssi_threshold_breached_internal_callback) {
+    return WIFI_ERROR_NOT_AVAILABLE;
+  }
+  on_rssi_threshold_breached_internal_callback =
+      [on_threshold_breached_user_callback](
+          wifi_request_id id, uint8_t* bssid_ptr, int8_t rssi) {
+        if (!bssid_ptr) {
+          return;
+        }
+        std::array<uint8_t, 6> bssid_arr;
+        // |bssid_ptr| pointer is assumed to have 6 bytes for the mac address.
+        std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
+        on_threshold_breached_user_callback(id, bssid_arr, rssi);
+      };
+  wifi_error status =
+      global_func_table_.wifi_start_rssi_monitoring(id,
+                                                    wlan_interface_handle_,
+                                                    max_rssi,
+                                                    min_rssi,
+                                                    {onRssiThresholdBreached});
+  if (status != WIFI_SUCCESS) {
+    on_rssi_threshold_breached_internal_callback = nullptr;
+  }
+  return status;
+}
+
+wifi_error WifiLegacyHal::stopRssiMonitoring(wifi_request_id id) {
+  if (!on_rssi_threshold_breached_internal_callback) {
+    return WIFI_ERROR_NOT_AVAILABLE;
+  }
+  wifi_error status =
+      global_func_table_.wifi_stop_rssi_monitoring(id, wlan_interface_handle_);
+  // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
+  // other error should be treated as the end of background scan.
+  if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+    on_rssi_threshold_breached_internal_callback = nullptr;
+  }
+  return status;
+}
+
 std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet() {
   uint32_t supported_features;
   wifi_error status = global_func_table_.wifi_get_logger_supported_feature_set(
@@ -697,11 +755,16 @@
   };
 
   std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
-  return global_func_table_.wifi_rtt_range_request(id,
-                                                   wlan_interface_handle_,
-                                                   rtt_configs.size(),
-                                                   rtt_configs_internal.data(),
-                                                   {onRttResults});
+  wifi_error status =
+      global_func_table_.wifi_rtt_range_request(id,
+                                                wlan_interface_handle_,
+                                                rtt_configs.size(),
+                                                rtt_configs_internal.data(),
+                                                {onRttResults});
+  if (status != WIFI_SUCCESS) {
+    on_rtt_results_internal_callback = nullptr;
+  }
+  return status;
 }
 
 wifi_error WifiLegacyHal::cancelRttRangeRequest(
@@ -974,8 +1037,6 @@
   }
   LOG(VERBOSE) << "Legacy HAL event loop terminated";
   awaiting_event_loop_termination_ = false;
-  android::wifi_system::InterfaceTool if_tool;
-  if_tool.SetWifiUpState(false);
 }
 
 std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
@@ -1016,6 +1077,7 @@
   on_gscan_event_internal_callback = nullptr;
   on_gscan_full_result_internal_callback = nullptr;
   on_link_layer_stats_result_internal_callback = nullptr;
+  on_rssi_threshold_breached_internal_callback = nullptr;
   on_ring_buffer_data_internal_callback = nullptr;
   on_rtt_results_internal_callback = nullptr;
   on_nan_notify_response_user_callback = nullptr;
diff --git a/wifi/1.0/default/wifi_legacy_hal.h b/wifi/1.0/default/wifi_legacy_hal.h
index 62b773e..b68fa50 100644
--- a/wifi/1.0/default/wifi_legacy_hal.h
+++ b/wifi/1.0/default/wifi_legacy_hal.h
@@ -21,6 +21,8 @@
 #include <thread>
 #include <vector>
 
+#include <wifi_system/interface_tool.h>
+
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -99,6 +101,10 @@
 using on_gscan_results_callback = std::function<void(
     wifi_request_id, const std::vector<wifi_cached_scan_results>&)>;
 
+// Invoked when the rssi value breaches the thresholds set.
+using on_rssi_threshold_breached_callback =
+    std::function<void(wifi_request_id, std::array<uint8_t, 6>, int8_t)>;
+
 // Callback for RTT range request results.
 // Rtt results contain IE info and are hence passed by reference, to
 // preserve the |LCI| and |LCR| pointers. Callee must not retain
@@ -125,7 +131,9 @@
   std::string getP2pIfaceName();
   std::string getStaIfaceName();
 
-  // Initialize the legacy HAL and start the event looper thread.
+  // Initialize the legacy HAL function table.
+  wifi_error initialize();
+  // Start the legacy HAL and the event looper thread.
   wifi_error start();
   // Deinitialize the legacy HAL and stop the event looper thread.
   wifi_error stop(const std::function<void()>& on_complete_callback);
@@ -163,6 +171,13 @@
   wifi_error enableLinkLayerStats(bool debug);
   wifi_error disableLinkLayerStats();
   std::pair<wifi_error, LinkLayerStats> getLinkLayerStats();
+  // RSSI monitor functions.
+  wifi_error startRssiMonitoring(wifi_request_id id,
+                                 int8_t max_rssi,
+                                 int8_t min_rssi,
+                                 const on_rssi_threshold_breached_callback&
+                                     on_threshold_breached_callback);
+  wifi_error stopRssiMonitoring(wifi_request_id id);
   // Logger/debug functions.
   std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet();
   wifi_error startPktFateMonitoring();
@@ -245,6 +260,7 @@
   wifi_interface_handle wlan_interface_handle_;
   // Flag to indicate if we have initiated the cleanup of legacy HAL.
   bool awaiting_event_loop_termination_;
+  wifi_system::InterfaceTool iface_tool_;
 };
 
 }  // namespace legacy_hal
diff --git a/wifi/1.0/default/wifi_mode_controller.cpp b/wifi/1.0/default/wifi_mode_controller.cpp
new file mode 100644
index 0000000..42dd9ad
--- /dev/null
+++ b/wifi/1.0/default/wifi_mode_controller.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <private/android_filesystem_config.h>
+
+#include "wifi_mode_controller.h"
+
+using android::hardware::wifi::V1_0::IfaceType;
+using android::wifi_hal::DriverTool;
+
+namespace {
+int convertIfaceTypeToFirmwareMode(IfaceType type) {
+  int mode;
+  switch (type) {
+    case IfaceType::AP:
+      mode = DriverTool::kFirmwareModeAp;
+      break;
+    case IfaceType::P2P:
+      mode = DriverTool::kFirmwareModeP2p;
+      break;
+    case IfaceType::NAN:
+      // NAN is exposed in STA mode currently.
+      mode = DriverTool::kFirmwareModeSta;
+      break;
+    case IfaceType::STA:
+      mode = DriverTool::kFirmwareModeSta;
+      break;
+  }
+  return mode;
+}
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_0 {
+namespace implementation {
+namespace mode_controller {
+
+WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}
+
+bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) {
+  return driver_tool_->IsFirmwareModeChangeNeeded(
+      convertIfaceTypeToFirmwareMode(type));
+}
+
+bool WifiModeController::changeFirmwareMode(IfaceType type) {
+  if (!driver_tool_->LoadDriver()) {
+    LOG(ERROR) << "Failed to load WiFi driver";
+    return false;
+  }
+  if (!driver_tool_->IsFirmwareModeChangeNeeded(
+          convertIfaceTypeToFirmwareMode(type))) {
+    LOG(ERROR) << "Failed to change firmware mode";
+    return false;
+  }
+  return true;
+}
+
+bool WifiModeController::deinitialize() {
+  if (!driver_tool_->UnloadDriver()) {
+    LOG(ERROR) << "Failed to unload WiFi driver";
+    return false;
+  }
+  return true;
+}
+}  // namespace mode_controller
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.0/default/wifi_mode_controller.h b/wifi/1.0/default/wifi_mode_controller.h
new file mode 100644
index 0000000..a4147a9
--- /dev/null
+++ b/wifi/1.0/default/wifi_mode_controller.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef WIFI_MODE_CONTROLLER_H_
+#define WIFI_MODE_CONTROLLER_H_
+
+#include <wifi_hal/driver_tool.h>
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_0 {
+namespace implementation {
+namespace mode_controller {
+/**
+ * Class that encapsulates all firmware mode configuration.
+ * This class will perform the necessary firmware reloads to put the chip in the
+ * required state (essentially a wrapper over DriverTool).
+ */
+class WifiModeController {
+ public:
+  WifiModeController();
+
+  // Checks if a firmware mode change is necessary to support the specified
+  // iface type operations.
+  bool isFirmwareModeChangeNeeded(IfaceType type);
+  // Change the firmware mode to support the specified iface type operations.
+  bool changeFirmwareMode(IfaceType type);
+  // Unload the driver. This should be invoked whenever |IWifi.stop()| is
+  // invoked.
+  bool deinitialize();
+
+ private:
+  std::unique_ptr<wifi_hal::DriverTool> driver_tool_;
+};
+
+}  // namespace mode_controller
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_MODE_CONTROLLER_H_
diff --git a/wifi/1.0/default/wifi_nan_iface.cpp b/wifi/1.0/default/wifi_nan_iface.cpp
index 48e75a5..a897520 100644
--- a/wifi/1.0/default/wifi_nan_iface.cpp
+++ b/wifi/1.0/default/wifi_nan_iface.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include "hidl_return_util.h"
+#include "hidl_struct_util.h"
 #include "wifi_nan_iface.h"
 #include "wifi_status_util.h"
 
@@ -30,7 +31,47 @@
 WifiNanIface::WifiNanIface(
     const std::string& ifname,
     const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
+    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
+  // Register all the callbacks here. these should be valid for the lifetime
+  // of the object. Whenever the mode changes legacy HAL will remove
+  // all of these callbacks.
+  legacy_hal::NanCallbackHandlers callback_handlers;
+
+  // Callback for response.
+  callback_handlers.on_notify_response = [&](
+      legacy_hal::transaction_id id, const legacy_hal::NanResponseMsg& msg) {
+    NanResponseMsgHeader hidl_header;
+    if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(msg,
+                                                                &hidl_header)) {
+      LOG(ERROR) << "Failed to convert nan response header";
+      return;
+    }
+    // TODO: This is a union in the legacy HAL. Need to convert to appropriate
+    // callback based on type.
+    // Assuming |NanPublishResponseMsg| type here.
+    NanPublishResponse hidl_body;
+    if (!hidl_struct_util::convertLegacyNanPublishResponseToHidl(
+            msg.body.publish_response, &hidl_body)) {
+      LOG(ERROR) << "Failed to convert nan publish response";
+      return;
+    }
+    NanPublishResponseMsg hidl_msg;
+    hidl_msg.header = hidl_header;
+    hidl_msg.body = hidl_body;
+    for (const auto& callback : event_callbacks_) {
+      if (!callback->notifyPublishResponse(id, hidl_msg).getStatus().isOk()) {
+        LOG(ERROR) << "Failed to invoke the callback";
+      }
+    }
+  };
+  // TODO: Register the remaining callbacks.
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->nanRegisterCallbackHandlers(callback_handlers);
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
+    invalidate();
+  }
+}
 
 void WifiNanIface::invalidate() {
   legacy_hal_.reset();
@@ -258,33 +299,60 @@
   return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-WifiStatus WifiNanIface::enableRequestInternal(
-    uint32_t /* cmd_id */, const NanEnableRequest& /* msg */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiNanIface::enableRequestInternal(uint32_t cmd_id,
+                                               const NanEnableRequest& msg) {
+  legacy_hal::NanEnableRequest legacy_msg;
+  if (!hidl_struct_util::convertHidlNanEnableRequestToLegacy(msg,
+                                                             &legacy_msg)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->nanEnableRequest(cmd_id, legacy_msg);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiNanIface::disableRequestInternal(uint32_t /* cmd_id */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiNanIface::disableRequestInternal(uint32_t cmd_id) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->nanDisableRequest(cmd_id);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiNanIface::publishRequestInternal(
-    uint32_t /* cmd_id */, const NanPublishRequest& /* msg */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiNanIface::publishRequestInternal(uint32_t cmd_id,
+                                                const NanPublishRequest& msg) {
+  legacy_hal::NanPublishRequest legacy_msg;
+  if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg,
+                                                              &legacy_msg)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->nanPublishRequest(cmd_id, legacy_msg);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiNanIface::publishCancelRequestInternal(
-    uint32_t /* cmd_id */, const NanPublishCancelRequest& /* msg */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    uint32_t cmd_id, const NanPublishCancelRequest& msg) {
+  legacy_hal::NanPublishCancelRequest legacy_msg;
+  if (!hidl_struct_util::convertHidlNanPublishCancelRequestToLegacy(
+          msg, &legacy_msg)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->nanPublishCancelRequest(cmd_id, legacy_msg);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
+
 WifiStatus WifiNanIface::subscribeRequestInternal(
-    uint32_t /* cmd_id */, const NanSubscribeRequest& /* msg */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    uint32_t cmd_id, const NanSubscribeRequest& msg) {
+  legacy_hal::NanSubscribeRequest legacy_msg;
+  if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(msg,
+                                                                &legacy_msg)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->nanSubscribeRequest(cmd_id, legacy_msg);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
+
 WifiStatus WifiNanIface::subscribeCancelRequestInternal(
     uint32_t /* cmd_id */, const NanSubscribeCancelRequest& /* msg */) {
   // TODO implement
diff --git a/wifi/1.0/default/wifi_rtt_controller.cpp b/wifi/1.0/default/wifi_rtt_controller.cpp
index 6ac0629..f18feae 100644
--- a/wifi/1.0/default/wifi_rtt_controller.cpp
+++ b/wifi/1.0/default/wifi_rtt_controller.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include "hidl_return_util.h"
+#include "hidl_struct_util.h"
 #include "wifi_rtt_controller.h"
 #include "wifi_status_util.h"
 
@@ -42,6 +43,11 @@
   return is_valid_;
 }
 
+std::vector<sp<IWifiRttControllerEventCallback>>
+WifiRttController::getEventCallbacks() {
+  return event_callbacks_;
+}
+
 Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
   return validateAndCall(this,
                          WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
@@ -83,28 +89,6 @@
                          addrs);
 }
 
-Return<void> WifiRttController::setChannelMap(uint32_t cmd_id,
-                                              const RttChannelMap& params,
-                                              uint32_t num_dw,
-                                              setChannelMap_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::setChannelMapInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         params,
-                         num_dw);
-}
-
-Return<void> WifiRttController::clearChannelMap(
-    uint32_t cmd_id, clearChannelMap_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::clearChannelMapInternal,
-                         hidl_status_cb,
-                         cmd_id);
-}
-
 Return<void> WifiRttController::getCapabilities(
     getCapabilities_cb hidl_status_cb) {
   return validateAndCall(this,
@@ -113,22 +97,6 @@
                          hidl_status_cb);
 }
 
-Return<void> WifiRttController::setDebugCfg(RttDebugType type,
-                                            setDebugCfg_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::setDebugCfgInternal,
-                         hidl_status_cb,
-                         type);
-}
-
-Return<void> WifiRttController::getDebugInfo(getDebugInfo_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::getDebugInfoInternal,
-                         hidl_status_cb);
-}
-
 Return<void> WifiRttController::setLci(uint32_t cmd_id,
                                        const RttLciInformation& lci,
                                        setLci_cb hidl_status_cb) {
@@ -162,7 +130,7 @@
 Return<void> WifiRttController::enableResponder(
     uint32_t cmd_id,
     const WifiChannelInfo& channel_hint,
-    uint32_t maxDurationSeconds,
+    uint32_t max_duration_seconds,
     const RttResponder& info,
     enableResponder_cb hidl_status_cb) {
   return validateAndCall(this,
@@ -171,7 +139,7 @@
                          hidl_status_cb,
                          cmd_id,
                          channel_hint,
-                         maxDurationSeconds,
+                         max_duration_seconds,
                          info);
 }
 
@@ -197,77 +165,130 @@
 }
 
 WifiStatus WifiRttController::rangeRequestInternal(
-    uint32_t /* cmd_id */, const std::vector<RttConfig>& /* rtt_configs */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    uint32_t cmd_id, const std::vector<RttConfig>& rtt_configs) {
+  std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
+  if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(
+          rtt_configs, &legacy_configs)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  android::wp<WifiRttController> weak_ptr_this(this);
+  const auto& on_results_callback = [weak_ptr_this](
+      legacy_hal::wifi_request_id id,
+      const std::vector<const legacy_hal::wifi_rtt_result*>& results) {
+    const auto shared_ptr_this = weak_ptr_this.promote();
+    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+      LOG(ERROR) << "Callback invoked on an invalid object";
+      return;
+    }
+    std::vector<RttResult> hidl_results;
+    if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(
+            results, &hidl_results)) {
+      LOG(ERROR) << "Failed to convert rtt results to HIDL structs";
+      return;
+    }
+    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+      callback->onResults(id, hidl_results);
+    }
+  };
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->startRttRangeRequest(
+          cmd_id, legacy_configs, on_results_callback);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiRttController::rangeCancelInternal(
-    uint32_t /* cmd_id */,
-    const std::vector<hidl_array<uint8_t, 6>>& /* addrs */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiRttController::setChannelMapInternal(
-    uint32_t /* cmd_id */,
-    const RttChannelMap& /* params */,
-    uint32_t /* num_dw */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiRttController::clearChannelMapInternal(uint32_t /* cmd_id */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) {
+  std::vector<std::array<uint8_t, 6>> legacy_addrs;
+  for (const auto& addr : addrs) {
+    legacy_addrs.push_back(addr);
+  }
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->cancelRttRangeRequest(cmd_id, legacy_addrs);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 std::pair<WifiStatus, RttCapabilities>
 WifiRttController::getCapabilitiesInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  legacy_hal::wifi_rtt_capabilities legacy_caps;
+  std::tie(legacy_status, legacy_caps) =
+      legacy_hal_.lock()->getRttCapabilities();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  RttCapabilities hidl_caps;
+  if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps,
+                                                            &hidl_caps)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
-WifiStatus WifiRttController::setDebugCfgInternal(RttDebugType /* type */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id,
+                                             const RttLciInformation& lci) {
+  legacy_hal::wifi_lci_information legacy_lci;
+  if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci,
+                                                              &legacy_lci)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->setRttLci(cmd_id, legacy_lci);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
-std::pair<WifiStatus, RttDebugInfo> WifiRttController::getDebugInfoInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
-}
-
-WifiStatus WifiRttController::setLciInternal(
-    uint32_t /* cmd_id */, const RttLciInformation& /* lci */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiRttController::setLcrInternal(
-    uint32_t /* cmd_id */, const RttLcrInformation& /* lcr */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id,
+                                             const RttLcrInformation& lcr) {
+  legacy_hal::wifi_lcr_information legacy_lcr;
+  if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr,
+                                                              &legacy_lcr)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->setRttLcr(cmd_id, legacy_lcr);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 std::pair<WifiStatus, RttResponder>
 WifiRttController::getResponderInfoInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  legacy_hal::wifi_rtt_responder legacy_responder;
+  std::tie(legacy_status, legacy_responder) =
+      legacy_hal_.lock()->getRttResponderInfo();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  RttResponder hidl_responder;
+  if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder,
+                                                         &hidl_responder)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder};
 }
 
 WifiStatus WifiRttController::enableResponderInternal(
-    uint32_t /* cmd_id */,
-    const WifiChannelInfo& /* channel_hint */,
-    uint32_t /* maxDurationSeconds */,
-    const RttResponder& /* info */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    uint32_t cmd_id,
+    const WifiChannelInfo& channel_hint,
+    uint32_t max_duration_seconds,
+    const RttResponder& info) {
+  legacy_hal::wifi_channel_info legacy_channel_info;
+  if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(
+          channel_hint, &legacy_channel_info)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_rtt_responder legacy_responder;
+  if (!hidl_struct_util::convertHidlRttResponderToLegacy(info,
+                                                         &legacy_responder)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableRttResponder(
+      cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiRttController::disableResponderInternal(uint32_t /* cmd_id */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->disableRttResponder(cmd_id);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 }  // namespace implementation
 }  // namespace V1_0
diff --git a/wifi/1.0/default/wifi_rtt_controller.h b/wifi/1.0/default/wifi_rtt_controller.h
index 3dd5340..7c0abca 100644
--- a/wifi/1.0/default/wifi_rtt_controller.h
+++ b/wifi/1.0/default/wifi_rtt_controller.h
@@ -40,6 +40,7 @@
   // Refer to |WifiChip::invalidate()|.
   void invalidate();
   bool isValid();
+  std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks();
 
   // HIDL methods exposed.
   Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;
@@ -52,16 +53,7 @@
   Return<void> rangeCancel(uint32_t cmd_id,
                            const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
                            rangeCancel_cb hidl_status_cb) override;
-  Return<void> setChannelMap(uint32_t cmd_id,
-                             const RttChannelMap& params,
-                             uint32_t num_dw,
-                             setChannelMap_cb hidl_status_cb) override;
-  Return<void> clearChannelMap(uint32_t cmd_id,
-                               clearChannelMap_cb hidl_status_cb) override;
   Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
-  Return<void> setDebugCfg(RttDebugType type,
-                           setDebugCfg_cb hidl_status_cb) override;
-  Return<void> getDebugInfo(getDebugInfo_cb hidl_status_cb) override;
   Return<void> setLci(uint32_t cmd_id,
                       const RttLciInformation& lci,
                       setLci_cb hidl_status_cb) override;
@@ -71,7 +63,7 @@
   Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override;
   Return<void> enableResponder(uint32_t cmd_id,
                                const WifiChannelInfo& channel_hint,
-                               uint32_t maxDurationSeconds,
+                               uint32_t max_duration_seconds,
                                const RttResponder& info,
                                enableResponder_cb hidl_status_cb) override;
   Return<void> disableResponder(uint32_t cmd_id,
@@ -86,19 +78,13 @@
                                   const std::vector<RttConfig>& rtt_configs);
   WifiStatus rangeCancelInternal(
       uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs);
-  WifiStatus setChannelMapInternal(uint32_t cmd_id,
-                                   const RttChannelMap& params,
-                                   uint32_t num_dw);
-  WifiStatus clearChannelMapInternal(uint32_t cmd_id);
   std::pair<WifiStatus, RttCapabilities> getCapabilitiesInternal();
-  WifiStatus setDebugCfgInternal(RttDebugType type);
-  std::pair<WifiStatus, RttDebugInfo> getDebugInfoInternal();
   WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci);
   WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr);
   std::pair<WifiStatus, RttResponder> getResponderInfoInternal();
   WifiStatus enableResponderInternal(uint32_t cmd_id,
                                      const WifiChannelInfo& channel_hint,
-                                     uint32_t maxDurationSeconds,
+                                     uint32_t max_duration_seconds,
                                      const RttResponder& info);
   WifiStatus disableResponderInternal(uint32_t cmd_id);
 
diff --git a/wifi/1.0/default/wifi_sta_iface.cpp b/wifi/1.0/default/wifi_sta_iface.cpp
index 6365032..c91a99b 100644
--- a/wifi/1.0/default/wifi_sta_iface.cpp
+++ b/wifi/1.0/default/wifi_sta_iface.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include "hidl_return_util.h"
+#include "hidl_struct_util.h"
 #include "wifi_sta_iface.h"
 #include "wifi_status_util.h"
 
@@ -42,6 +43,10 @@
   return is_valid_;
 }
 
+std::vector<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
+  return event_callbacks_;
+}
+
 Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) {
   return validateAndCall(this,
                          WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -158,6 +163,29 @@
                          hidl_status_cb);
 }
 
+Return<void> WifiStaIface::startRssiMonitoring(
+    uint32_t cmd_id,
+    int32_t max_rssi,
+    int32_t min_rssi,
+    startRssiMonitoring_cb hidl_status_cb) {
+  return validateAndCall(this,
+                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                         &WifiStaIface::startRssiMonitoringInternal,
+                         hidl_status_cb,
+                         cmd_id,
+                         max_rssi,
+                         min_rssi);
+}
+
+Return<void> WifiStaIface::stopRssiMonitoring(
+    uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) {
+  return validateAndCall(this,
+                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                         &WifiStaIface::stopRssiMonitoringInternal,
+                         hidl_status_cb,
+                         cmd_id);
+}
+
 Return<void> WifiStaIface::startDebugPacketFateMonitoring(
     startDebugPacketFateMonitoring_cb hidl_status_cb) {
   return validateAndCall(this,
@@ -206,83 +234,249 @@
 }
 
 std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), 0};
+  legacy_hal::wifi_error legacy_status;
+  uint32_t legacy_feature_set;
+  std::tie(legacy_status, legacy_feature_set) =
+      legacy_hal_.lock()->getSupportedFeatureSet();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), 0};
+  }
+  uint32_t legacy_logger_feature_set;
+  std::tie(legacy_status, legacy_logger_feature_set) =
+      legacy_hal_.lock()->getLoggerSupportedFeatureSet();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), 0};
+  }
+  uint32_t hidl_caps;
+  if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
+          legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
 std::pair<WifiStatus, StaApfPacketFilterCapabilities>
 WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  legacy_hal::PacketFilterCapabilities legacy_caps;
+  std::tie(legacy_status, legacy_caps) =
+      legacy_hal_.lock()->getPacketFilterCapabilities();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  StaApfPacketFilterCapabilities hidl_caps;
+  if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps,
+                                                            &hidl_caps)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
 WifiStatus WifiStaIface::installApfPacketFilterInternal(
-    uint32_t /* cmd_id */, const std::vector<uint8_t>& /* program */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    uint32_t /* cmd_id */, const std::vector<uint8_t>& program) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->setPacketFilter(program);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 std::pair<WifiStatus, StaBackgroundScanCapabilities>
 WifiStaIface::getBackgroundScanCapabilitiesInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  legacy_hal::wifi_gscan_capabilities legacy_caps;
+  std::tie(legacy_status, legacy_caps) =
+      legacy_hal_.lock()->getGscanCapabilities();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  StaBackgroundScanCapabilities hidl_caps;
+  if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps,
+                                                              &hidl_caps)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
 std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
 WifiStaIface::getValidFrequenciesForBackgroundScanInternal(
-    StaBackgroundScanBand /* band */) {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+    StaBackgroundScanBand band) {
+  static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch");
+  legacy_hal::wifi_error legacy_status;
+  std::vector<uint32_t> valid_frequencies;
+  std::tie(legacy_status, valid_frequencies) =
+      legacy_hal_.lock()->getValidFrequenciesForGscan(
+          hidl_struct_util::convertHidlGscanBandToLegacy(band));
+  return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
 }
 
 WifiStatus WifiStaIface::startBackgroundScanInternal(
-    uint32_t /* cmd_id */, const StaBackgroundScanParameters& /* params */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+    uint32_t cmd_id, const StaBackgroundScanParameters& params) {
+  legacy_hal::wifi_scan_cmd_params legacy_params;
+  if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params,
+                                                        &legacy_params)) {
+    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+  }
+  android::wp<WifiStaIface> weak_ptr_this(this);
+  const auto& on_failure_callback =
+      [weak_ptr_this](legacy_hal::wifi_request_id id) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+          LOG(ERROR) << "Callback invoked on an invalid object";
+          return;
+        }
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+          callback->onBackgroundScanFailure(id);
+        }
+      };
+  const auto& on_results_callback = [weak_ptr_this](
+      legacy_hal::wifi_request_id id,
+      const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
+    const auto shared_ptr_this = weak_ptr_this.promote();
+    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+      LOG(ERROR) << "Callback invoked on an invalid object";
+      return;
+    }
+    std::vector<StaScanData> hidl_scan_datas;
+    if (!hidl_struct_util::convertLegacyVectorOfCachedGscanResultsToHidl(
+            results, &hidl_scan_datas)) {
+      LOG(ERROR) << "Failed to convert scan results to HIDL structs";
+      return;
+    }
+    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+      callback->onBackgroundScanResults(id, hidl_scan_datas);
+    }
+  };
+  const auto& on_full_result_callback = [weak_ptr_this](
+      legacy_hal::wifi_request_id id,
+      const legacy_hal::wifi_scan_result* result,
+      uint32_t /* buckets_scanned */) {
+    const auto shared_ptr_this = weak_ptr_this.promote();
+    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+      LOG(ERROR) << "Callback invoked on an invalid object";
+      return;
+    }
+    StaScanResult hidl_scan_result;
+    if (!hidl_struct_util::convertLegacyGscanResultToHidl(
+            *result, true, &hidl_scan_result)) {
+      LOG(ERROR) << "Failed to convert full scan results to HIDL structs";
+      return;
+    }
+    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+      callback->onBackgroundFullScanResult(id, hidl_scan_result);
+    }
+  };
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->startGscan(cmd_id,
+                                     legacy_params,
+                                     on_failure_callback,
+                                     on_results_callback,
+                                     on_full_result_callback);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t /* cmd_id */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) {
+  legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopGscan(cmd_id);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(
-    bool /* debug */) {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->enableLinkLayerStats(debug);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->disableLinkLayerStats();
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 std::pair<WifiStatus, StaLinkLayerStats>
 WifiStaIface::getLinkLayerStatsInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  legacy_hal::LinkLayerStats legacy_stats;
+  std::tie(legacy_status, legacy_stats) =
+      legacy_hal_.lock()->getLinkLayerStats();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  StaLinkLayerStats hidl_stats;
+  if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
+                                                           &hidl_stats)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
+}
+
+WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id,
+                                                     int32_t max_rssi,
+                                                     int32_t min_rssi) {
+  android::wp<WifiStaIface> weak_ptr_this(this);
+  const auto& on_threshold_breached_callback = [weak_ptr_this](
+      legacy_hal::wifi_request_id id,
+      std::array<uint8_t, 6> bssid,
+      int8_t rssi) {
+    const auto shared_ptr_this = weak_ptr_this.promote();
+    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+      LOG(ERROR) << "Callback invoked on an invalid object";
+      return;
+    }
+    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+      callback->onRssiThresholdBreached(id, bssid, rssi);
+    }
+  };
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->startRssiMonitoring(
+          cmd_id, max_rssi, min_rssi, on_threshold_breached_callback);
+  return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) {
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->stopRssiMonitoring(cmd_id);
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+  legacy_hal::wifi_error legacy_status =
+      legacy_hal_.lock()->startPktFateMonitoring();
+  return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiStaIface::stopDebugPacketFateMonitoringInternal() {
-  // TODO implement
-  return createWifiStatus(WifiStatusCode::SUCCESS);
+  // There is no stop in legacy HAL implementation.
+  return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
 std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
 WifiStaIface::getDebugTxPacketFatesInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  std::vector<legacy_hal::wifi_tx_report> legacy_fates;
+  std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  std::vector<WifiDebugTxPacketFateReport> hidl_fates;
+  if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(
+          legacy_fates, &hidl_fates)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
 }
 
 std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
 WifiStaIface::getDebugRxPacketFatesInternal() {
-  // TODO implement
-  return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+  legacy_hal::wifi_error legacy_status;
+  std::vector<legacy_hal::wifi_rx_report> legacy_fates;
+  std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates();
+  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+    return {createWifiStatusFromLegacyError(legacy_status), {}};
+  }
+  std::vector<WifiDebugRxPacketFateReport> hidl_fates;
+  if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(
+          legacy_fates, &hidl_fates)) {
+    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+  }
+  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
 }
 
 }  // namespace implementation
diff --git a/wifi/1.0/default/wifi_sta_iface.h b/wifi/1.0/default/wifi_sta_iface.h
index 09a883c..b4f2721 100644
--- a/wifi/1.0/default/wifi_sta_iface.h
+++ b/wifi/1.0/default/wifi_sta_iface.h
@@ -39,6 +39,7 @@
   // Refer to |WifiChip::invalidate()|.
   void invalidate();
   bool isValid();
+  std::vector<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
 
   // HIDL methods exposed.
   Return<void> getName(getName_cb hidl_status_cb) override;
@@ -69,6 +70,13 @@
   Return<void> disableLinkLayerStatsCollection(
       disableLinkLayerStatsCollection_cb hidl_status_cb) override;
   Return<void> getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) override;
+  Return<void> startRssiMonitoring(
+      uint32_t cmd_id,
+      int32_t max_rssi,
+      int32_t min_rssi,
+      startRssiMonitoring_cb hidl_status_cb) override;
+  Return<void> stopRssiMonitoring(
+      uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override;
   Return<void> startDebugPacketFateMonitoring(
       startDebugPacketFateMonitoring_cb hidl_status_cb) override;
   Return<void> stopDebugPacketFateMonitoring(
@@ -99,6 +107,10 @@
   WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
   WifiStatus disableLinkLayerStatsCollectionInternal();
   std::pair<WifiStatus, StaLinkLayerStats> getLinkLayerStatsInternal();
+  WifiStatus startRssiMonitoringInternal(uint32_t cmd_id,
+                                         int32_t max_rssi,
+                                         int32_t min_rssi);
+  WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
   WifiStatus startDebugPacketFateMonitoringInternal();
   WifiStatus stopDebugPacketFateMonitoringInternal();
   std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
diff --git a/wifi/1.0/types.hal b/wifi/1.0/types.hal
index 9e53377..8dd33b5 100644
--- a/wifi/1.0/types.hal
+++ b/wifi/1.0/types.hal
@@ -491,7 +491,7 @@
    * Indicates that a scan was interrupted/did not occur so results may be
    * incomplete.
    */
-  WIFI_SCAN_FLAG_INTERRUPTED = 1 << 0,
+  INTERRUPTED = 1 << 0,
 };
 
 /**
@@ -2183,13 +2183,6 @@
 };
 
 /**
- * NBD ranging channel map.
- */
-struct RttChannelMap {
-  WifiChannelInMhz[32] availablity;
-};
-
-/**
  * RTT Capabilities.
  */
 struct RttCapabilities {
@@ -2231,45 +2224,6 @@
 };
 
 /**
- * Debugging definitions.
- */
-enum RttDebugType : uint32_t {
-  DISABLE,
-  LOG,
-  PROTO,
-  BURST,
-  ACCURACY,
-  LOGDETAIL,
-};
-
-enum RttDebugFormat : uint32_t {
-  TXT,
-  BINARY,
-};
-
-/**
- * Debug info.
- */
-struct RttDebugInfo {
-  /**
-   * Version info.
-   */
-  uint32_t version;
-  /**
-   * Debug data type.
-   */
-  RttDebugType type;
-  /**
-   * Debug data format.
-   */
-  RttDebugFormat format;
-  /**
-   * Debug data content.
-   */
-  vec<uint8_t> data;
-};
-
-/**
  * Structs for setting LCI/LCR information to be provided to a requestor.
  */
 enum RttMotionPattern : uint32_t {
@@ -3053,7 +3007,7 @@
  */
 struct WifiDebugTxPacketFateReport {
   WifiDebugTxPacketFate fate;
-  WifiDebugPacketFateFrameInfo frameInf;
+  WifiDebugPacketFateFrameInfo frameInfo;
 };
 
 /**
diff --git a/wifi/supplicant/1.0/ISupplicantP2pIface.hal b/wifi/supplicant/1.0/ISupplicantP2pIface.hal
index 48a4f5b..0cdac2d 100644
--- a/wifi/supplicant/1.0/ISupplicantP2pIface.hal
+++ b/wifi/supplicant/1.0/ISupplicantP2pIface.hal
@@ -37,11 +37,7 @@
     /**
      * Keypad pin method configuration - pin is entered on device.
      */
-    KEYPAD,
-    /**
-     * Label pin method configuration - pin is labelled on device.
-     */
-    LABEL
+    KEYPAD
   };
 
   enum GroupCapabilityMask : uint32_t {
@@ -55,6 +51,15 @@
   };
 
   /**
+   * Use to specify a range of frequencies.
+   * For example: 2412-2432,2462,5000-6000, etc.
+   */
+  struct FreqRange {
+      uint32_t min;
+      uint32_t max;
+  };
+
+  /**
    * Register for callbacks from this interface.
    *
    * These callbacks are invoked for events that are specific to this interface.
@@ -97,7 +102,7 @@
    *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
    *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
    */
-  setSsidPostfix(string postfix) generates (SupplicantStatus status);
+  setSsidPostfix(vec<uint8_t> postfix) generates (SupplicantStatus status);
 
   /**
    * Set the Maximum idle time in seconds for P2P groups.
@@ -106,6 +111,7 @@
    * associated stations in the group. As a P2P client, this means no
    * group owner seen in scan results.
    *
+   * @param groupIfName Group interface name to use.
    * @param timeoutInSec Timeout value in seconds.
    * @return status Status of the operation.
    *         Possible status codes:
@@ -113,11 +119,13 @@
    *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
    *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
    */
-  setGroupIdle(uint32_t timeoutInSec) generates (SupplicantStatus status);
+  setGroupIdle(string groupIfName, uint32_t timeoutInSec)
+      generates (SupplicantStatus status);
 
   /**
    * Turn on/off power save mode for the interface.
    *
+   * @param groupIfName Group interface name to use.
    * @param enable Indicate if power save is to be turned on/off.
    * @return status Status of the operation.
    *         Possible status codes:
@@ -126,7 +134,8 @@
    *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
    *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
    */
-  setPowerSave(bool enable) generates (SupplicantStatus status);
+  setPowerSave(string groupIfName, bool enable)
+      generates (SupplicantStatus status);
 
   /**
    * Initiate a P2P service discovery with an optional timeout.
@@ -192,11 +201,11 @@
    */
   connect(MacAddress peerAddress,
           WpsProvisionMethod provisionMethod,
-          vec<uint8_t> preSelectedPin,
+          string preSelectedPin,
           bool joinExistingGroup,
           bool persistent,
           uint32_t goIntent)
-      generates (SupplicantStatus status, vec<uint8_t> generatedPin);
+      generates (SupplicantStatus status, string generatedPin);
 
   /**
    * Cancel an ongoing P2P group formation and joining-a-group related
@@ -358,6 +367,21 @@
       generates (SupplicantStatus status);
 
   /**
+   * Set P2P disallowed frequency ranges.
+   *
+   * Specify ranges of frequencies that are disallowed for any p2p operations.
+
+   * @param ranges List of ranges which needs to be disallowed.
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+   */
+  setDisallowedFrequencies(vec<FreqRange> ranges)
+      generates (SupplicantStatus status);
+
+  /**
    * Gets the operational SSID of the device.
    *
    * @param peerAddress MAC address of the peer.
diff --git a/wifi/supplicant/1.0/ISupplicantStaIface.hal b/wifi/supplicant/1.0/ISupplicantStaIface.hal
index 868758e..31706cd 100644
--- a/wifi/supplicant/1.0/ISupplicantStaIface.hal
+++ b/wifi/supplicant/1.0/ISupplicantStaIface.hal
@@ -28,7 +28,7 @@
    * Access Network Query Protocol info ID elements
    * for IEEE Std 802.11u-2011.
    */
-  enum AnqpInfoId : uint32_t {
+  enum AnqpInfoId : uint16_t {
     VENUE_NAME = 258,
     ROAMING_CONSORTIUM = 261,
     IP_ADDR_TYPE_AVAILABILITY = 262,
@@ -42,7 +42,7 @@
    * for Hotspot 2.0.
    */
   enum Hs20AnqpSubtypes : uint32_t {
-    OPERATOR_FRIENDLY_NAME = 2,
+    OPERATOR_FRIENDLY_NAME = 3,
     WAN_METRICS = 4,
     CONNECTION_CAPABILITY = 5,
     OSU_PROVIDERS_LIST = 8,