Add HAL support for IEEE 802.11 az ranging

Bug: 295619650
Test: m
Change-Id: Ieba17a1414afa8fddca7d0d87e786c760c6789e5
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 99420bd..95ff7a2 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -2418,8 +2418,11 @@
     switch (type) {
         case RttType::ONE_SIDED:
             return legacy_hal::RTT_TYPE_1_SIDED;
-        case RttType::TWO_SIDED:
-            return legacy_hal::RTT_TYPE_2_SIDED;
+        case RttType::TWO_SIDED_11MC:
+            // Same as RttType::TWO_SIDED
+            return legacy_hal::RTT_TYPE_2_SIDED_11MC;
+        case RttType::TWO_SIDED_11AZ_NTB:
+            return legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB;
     };
     CHECK(false);
 }
@@ -2428,8 +2431,11 @@
     switch (type) {
         case legacy_hal::RTT_TYPE_1_SIDED:
             return RttType::ONE_SIDED;
-        case legacy_hal::RTT_TYPE_2_SIDED:
-            return RttType::TWO_SIDED;
+        case legacy_hal::RTT_TYPE_2_SIDED_11MC:
+            // Same as legacy_hal::RTT_TYPE_2_SIDED
+            return RttType::TWO_SIDED_11MC;
+        case legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB:
+            return RttType::TWO_SIDED_11AZ_NTB;
     };
     CHECK(false) << "Unknown legacy type: " << type;
 }
@@ -2509,6 +2515,8 @@
             return legacy_hal::WIFI_RTT_PREAMBLE_HE;
         case RttPreamble::EHT:
             return legacy_hal::WIFI_RTT_PREAMBLE_EHT;
+        case RttPreamble::INVALID:
+            return legacy_hal::WIFI_RTT_PREAMBLE_INVALID;
     };
     CHECK(false);
 }
@@ -2525,6 +2533,8 @@
             return RttPreamble::HE;
         case legacy_hal::WIFI_RTT_PREAMBLE_EHT:
             return RttPreamble::EHT;
+        case legacy_hal::WIFI_RTT_PREAMBLE_INVALID:
+            return RttPreamble::INVALID;
     };
     CHECK(false) << "Unknown legacy type: " << type;
 }
@@ -2714,6 +2724,21 @@
     return true;
 }
 
+bool convertAidlRttConfigToLegacyV3(const RttConfig& aidl_config,
+                                    legacy_hal::wifi_rtt_config_v3* legacy_config) {
+    if (!legacy_config) {
+        return false;
+    }
+    *legacy_config = {};
+    if (!convertAidlRttConfigToLegacy(aidl_config, &(legacy_config->rtt_config))) {
+        return false;
+    }
+    legacy_config->tx_ltf_repetition_count = aidl_config.txLtfRepetitionCount;
+    legacy_config->ntb_min_measurement_time_millis = aidl_config.ntbMinMeasurementTimeMillis;
+    legacy_config->ntb_max_measurement_time_millis = aidl_config.ntbMaxMeasurementTimeMillis;
+    return true;
+}
+
 bool convertAidlVectorOfRttConfigToLegacy(
         const std::vector<RttConfig>& aidl_configs,
         std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
@@ -2723,7 +2748,24 @@
     *legacy_configs = {};
     for (const auto& aidl_config : aidl_configs) {
         legacy_hal::wifi_rtt_config legacy_config;
-        if (!convertAidlRttConfigToLegacy(aidl_config, &legacy_config)) {
+        if (!convertAidlRttConfigToLegacy(aidl_config, &(legacy_config))) {
+            return false;
+        }
+        legacy_configs->push_back(legacy_config);
+    }
+    return true;
+}
+
+bool convertAidlVectorOfRttConfigToLegacyV3(
+        const std::vector<RttConfig>& aidl_configs,
+        std::vector<legacy_hal::wifi_rtt_config_v3>* legacy_configs) {
+    if (!legacy_configs) {
+        return false;
+    }
+    *legacy_configs = {};
+    for (const auto& aidl_config : aidl_configs) {
+        legacy_hal::wifi_rtt_config_v3 legacy_config;
+        if (!convertAidlRttConfigToLegacyV3(aidl_config, &legacy_config)) {
             return false;
         }
         legacy_configs->push_back(legacy_config);
@@ -2792,6 +2834,34 @@
     return true;
 }
 
+RttPreamble convertLegacyRttPreambleBitmapToAidl(byte legacyPreambleBitmap) {
+    int32_t aidlPreambleBitmap = 0;
+    for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, legacy_hal::WIFI_RTT_PREAMBLE_HT,
+                            legacy_hal::WIFI_RTT_PREAMBLE_VHT, legacy_hal::WIFI_RTT_PREAMBLE_HE,
+                            legacy_hal::WIFI_RTT_PREAMBLE_EHT}) {
+        if (legacyPreambleBitmap & flag) {
+            aidlPreambleBitmap |= static_cast<std::underlying_type<RttPreamble>::type>(
+                    convertLegacyRttPreambleToAidl(flag));
+        }
+    }
+
+    return static_cast<RttPreamble>(aidlPreambleBitmap);
+}
+
+RttBw convertLegacyRttBwBitmapToAidl(byte legacyBwBitmap) {
+    int32_t aidlBwBitmap = 0;
+    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,
+          legacy_hal::WIFI_RTT_BW_320}) {
+        if (legacyBwBitmap & flag) {
+            aidlBwBitmap |=
+                    static_cast<std::underlying_type<RttBw>::type>(convertLegacyRttBwToAidl(flag));
+        }
+    }
+    return static_cast<RttBw>(aidlBwBitmap);
+}
+
 bool convertLegacyRttCapabilitiesToAidl(
         const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
         RttCapabilities* aidl_capabilities) {
@@ -2804,28 +2874,44 @@
     aidl_capabilities->lciSupported = legacy_capabilities.lci_support;
     aidl_capabilities->lcrSupported = legacy_capabilities.lcr_support;
     aidl_capabilities->responderSupported = legacy_capabilities.responder_supported;
-    int32_t preambleSupport = 0;
-    for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, legacy_hal::WIFI_RTT_PREAMBLE_HT,
-                            legacy_hal::WIFI_RTT_PREAMBLE_VHT, legacy_hal::WIFI_RTT_PREAMBLE_HE,
-                            legacy_hal::WIFI_RTT_PREAMBLE_EHT}) {
-        if (legacy_capabilities.preamble_support & flag) {
-            preambleSupport |= static_cast<std::underlying_type<RttPreamble>::type>(
-                    convertLegacyRttPreambleToAidl(flag));
-        }
-    }
-    aidl_capabilities->preambleSupport = static_cast<RttPreamble>(preambleSupport);
-    int32_t bwSupport = 0;
-    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,
-          legacy_hal::WIFI_RTT_BW_320}) {
-        if (legacy_capabilities.bw_support & flag) {
-            bwSupport |=
-                    static_cast<std::underlying_type<RttBw>::type>(convertLegacyRttBwToAidl(flag));
-        }
-    }
-    aidl_capabilities->bwSupport = static_cast<RttBw>(bwSupport);
+    aidl_capabilities->preambleSupport =
+            convertLegacyRttPreambleBitmapToAidl(legacy_capabilities.preamble_support);
+    aidl_capabilities->bwSupport = convertLegacyRttBwBitmapToAidl(legacy_capabilities.bw_support);
     aidl_capabilities->mcVersion = legacy_capabilities.mc_version;
+    // Initialize 11az parameters to default
+    aidl_capabilities->azPreambleSupport = RttPreamble::INVALID;
+    aidl_capabilities->azBwSupport = RttBw::BW_UNSPECIFIED;
+    aidl_capabilities->ntbInitiatorSupported = false;
+    aidl_capabilities->ntbResponderSupported = false;
+    aidl_capabilities->maxTxLtfRepetitionCount = 0;
+    return true;
+}
+
+bool convertLegacyRttCapabilitiesV3ToAidl(
+        const legacy_hal::wifi_rtt_capabilities_v3& legacy_capabilities_v3,
+        RttCapabilities* aidl_capabilities) {
+    if (!aidl_capabilities) {
+        return false;
+    }
+    *aidl_capabilities = {};
+    aidl_capabilities->rttOneSidedSupported =
+            legacy_capabilities_v3.rtt_capab.rtt_one_sided_supported;
+    aidl_capabilities->rttFtmSupported = legacy_capabilities_v3.rtt_capab.rtt_ftm_supported;
+    aidl_capabilities->lciSupported = legacy_capabilities_v3.rtt_capab.lci_support;
+    aidl_capabilities->lcrSupported = legacy_capabilities_v3.rtt_capab.lcr_support;
+    aidl_capabilities->responderSupported = legacy_capabilities_v3.rtt_capab.responder_supported;
+    aidl_capabilities->preambleSupport =
+            convertLegacyRttPreambleBitmapToAidl(legacy_capabilities_v3.rtt_capab.preamble_support);
+    aidl_capabilities->bwSupport =
+            convertLegacyRttBwBitmapToAidl(legacy_capabilities_v3.rtt_capab.bw_support);
+    aidl_capabilities->mcVersion = legacy_capabilities_v3.rtt_capab.mc_version;
+    aidl_capabilities->azPreambleSupport =
+            convertLegacyRttPreambleBitmapToAidl(legacy_capabilities_v3.az_preamble_support);
+    aidl_capabilities->azBwSupport =
+            convertLegacyRttBwBitmapToAidl(legacy_capabilities_v3.az_bw_support);
+    aidl_capabilities->ntbInitiatorSupported = legacy_capabilities_v3.ntb_initiator_supported;
+    aidl_capabilities->ntbResponderSupported = legacy_capabilities_v3.ntb_responder_supported;
+    aidl_capabilities->maxTxLtfRepetitionCount = legacy_capabilities_v3.max_tx_ltf_repetition_count;
     return true;
 }
 
@@ -2900,6 +2986,9 @@
         }
         aidl_result.channelFreqMHz = 0;
         aidl_result.packetBw = RttBw::BW_UNSPECIFIED;
+        aidl_result.txLtfRepetitionCount = 0;
+        aidl_result.ntbMinMeasurementTimeMillis = 0;
+        aidl_result.ntbMaxMeasurementTimeMillis = 0;
         aidl_results->push_back(aidl_result);
     }
     return true;
@@ -2920,6 +3009,33 @@
         aidl_result.channelFreqMHz =
                 legacy_result->frequency != UNSPECIFIED ? legacy_result->frequency : 0;
         aidl_result.packetBw = convertLegacyRttBwToAidl(legacy_result->packet_bw);
+        aidl_result.txLtfRepetitionCount = 0;
+        aidl_result.ntbMinMeasurementTimeMillis = 0;
+        aidl_result.ntbMaxMeasurementTimeMillis = 0;
+        aidl_results->push_back(aidl_result);
+    }
+    return true;
+}
+
+bool convertLegacyVectorOfRttResultV3ToAidl(
+        const std::vector<const legacy_hal::wifi_rtt_result_v3*>& legacy_results,
+        std::vector<RttResult>* aidl_results) {
+    if (!aidl_results) {
+        return false;
+    }
+    *aidl_results = {};
+    for (const auto legacy_result : legacy_results) {
+        RttResult aidl_result;
+        if (!convertLegacyRttResultToAidl(legacy_result->rtt_result.rtt_result, &aidl_result)) {
+            return false;
+        }
+        aidl_result.channelFreqMHz = legacy_result->rtt_result.frequency != UNSPECIFIED
+                                             ? legacy_result->rtt_result.frequency
+                                             : 0;
+        aidl_result.packetBw = convertLegacyRttBwToAidl(legacy_result->rtt_result.packet_bw);
+        aidl_result.txLtfRepetitionCount = legacy_result->tx_ltf_repetition_count;
+        aidl_result.ntbMinMeasurementTimeMillis = legacy_result->ntb_min_measurement_time_millis;
+        aidl_result.ntbMaxMeasurementTimeMillis = legacy_result->ntb_max_measurement_time_millis;
         aidl_results->push_back(aidl_result);
     }
     return true;
diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h
index e4ff963..3b9c81d 100644
--- a/wifi/aidl/default/aidl_struct_util.h
+++ b/wifi/aidl/default/aidl_struct_util.h
@@ -148,6 +148,10 @@
 // RTT controller conversion methods.
 bool convertAidlVectorOfRttConfigToLegacy(const std::vector<RttConfig>& aidl_configs,
                                           std::vector<legacy_hal::wifi_rtt_config>* legacy_configs);
+bool convertAidlVectorOfRttConfigToLegacyV3(
+        const std::vector<RttConfig>& aidl_configs,
+        std::vector<legacy_hal::wifi_rtt_config_v3>* legacy_configs);
+
 bool convertAidlRttLciInformationToLegacy(const RttLciInformation& aidl_info,
                                           legacy_hal::wifi_lci_information* legacy_info);
 bool convertAidlRttLcrInformationToLegacy(const RttLcrInformation& aidl_info,
@@ -161,12 +165,19 @@
 bool convertLegacyRttCapabilitiesToAidl(
         const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
         RttCapabilities* aidl_capabilities);
+bool convertLegacyRttCapabilitiesV3ToAidl(
+        const legacy_hal::wifi_rtt_capabilities_v3& legacy_capabilities_v3,
+        RttCapabilities* aidl_capabilities);
+
 bool convertLegacyVectorOfRttResultToAidl(
         const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
         std::vector<RttResult>* aidl_results);
 bool convertLegacyVectorOfRttResultV2ToAidl(
         const std::vector<const legacy_hal::wifi_rtt_result_v2*>& legacy_results,
         std::vector<RttResult>* aidl_results);
+bool convertLegacyVectorOfRttResultV3ToAidl(
+        const std::vector<const legacy_hal::wifi_rtt_result_v3*>& legacy_results,
+        std::vector<RttResult>* aidl_results);
 uint32_t convertAidlWifiBandToLegacyMacBand(WifiBand band);
 uint32_t convertAidlWifiIfaceModeToLegacy(uint32_t aidl_iface_mask);
 uint32_t convertAidlUsableChannelFilterToLegacy(uint32_t aidl_filter_mask);
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
index 209670b..c411f29 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -183,10 +183,13 @@
         on_rtt_results_internal_callback;
 std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result_v2* rtt_results_v2[])>
         on_rtt_results_internal_callback_v2;
+std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result_v3* rtt_results_v3[])>
+        on_rtt_results_internal_callback_v3;
 
 void invalidateRttResultsCallbacks() {
     on_rtt_results_internal_callback = nullptr;
     on_rtt_results_internal_callback_v2 = nullptr;
+    on_rtt_results_internal_callback_v3 = nullptr;
 };
 
 void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) {
@@ -206,6 +209,15 @@
     }
 }
 
+void onAsyncRttResultsV3(wifi_request_id id, unsigned num_results,
+                         wifi_rtt_result_v3* rtt_results_v3[]) {
+    const auto lock = aidl_sync_util::acquireGlobalLock();
+    if (on_rtt_results_internal_callback_v3) {
+        on_rtt_results_internal_callback_v3(id, num_results, rtt_results_v3);
+        invalidateRttResultsCallbacks();
+    }
+}
+
 // Callbacks for the various NAN operations.
 // NOTE: These have very little conversions to perform before invoking the user
 // callbacks.
@@ -1251,6 +1263,38 @@
     return status;
 }
 
+wifi_error WifiLegacyHal::startRttRangeRequestV3(
+        const std::string& iface_name, wifi_request_id id,
+        const std::vector<wifi_rtt_config_v3>& rtt_configs,
+        const on_rtt_results_callback_v3& on_results_user_callback_v3) {
+    if (on_rtt_results_internal_callback_v3) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+
+    on_rtt_results_internal_callback_v3 = [on_results_user_callback_v3](
+                                                  wifi_request_id id, unsigned num_results,
+                                                  wifi_rtt_result_v3* rtt_results_v3[]) {
+        if (num_results > 0 && !rtt_results_v3) {
+            LOG(ERROR) << "Unexpected nullptr in RTT v3 results";
+            return;
+        }
+        std::vector<const wifi_rtt_result_v3*> rtt_results_vec_v3;
+        std::copy_if(rtt_results_v3, rtt_results_v3 + num_results,
+                     back_inserter(rtt_results_vec_v3),
+                     [](wifi_rtt_result_v3* rtt_result_v3) { return rtt_result_v3 != nullptr; });
+        on_results_user_callback_v3(id, rtt_results_vec_v3);
+    };
+
+    std::vector<wifi_rtt_config_v3> rtt_configs_internal(rtt_configs);
+    wifi_error status = global_func_table_.wifi_rtt_range_request_v3(
+            id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(),
+            {onAsyncRttResultsV3});
+    if (status != WIFI_SUCCESS) {
+        invalidateRttResultsCallbacks();
+    }
+    return status;
+}
+
 wifi_error WifiLegacyHal::startRttRangeRequest(
         const std::string& iface_name, wifi_request_id id,
         const std::vector<wifi_rtt_config>& rtt_configs,
@@ -1327,6 +1371,14 @@
     return {status, rtt_caps};
 }
 
+std::pair<wifi_error, wifi_rtt_capabilities_v3> WifiLegacyHal::getRttCapabilitiesV3(
+        const std::string& iface_name) {
+    wifi_rtt_capabilities_v3 rtt_caps_v3;
+    wifi_error status = global_func_table_.wifi_get_rtt_capabilities_v3(getIfaceHandle(iface_name),
+                                                                        &rtt_caps_v3);
+    return {status, rtt_caps_v3};
+}
+
 std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
         const std::string& iface_name) {
     wifi_rtt_responder rtt_responder;
diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h
index 6f012ec..0f49f42 100644
--- a/wifi/aidl/default/wifi_legacy_hal.h
+++ b/wifi/aidl/default/wifi_legacy_hal.h
@@ -215,6 +215,8 @@
 using ::RTT_STATUS_SUCCESS;
 using ::RTT_TYPE_1_SIDED;
 using ::RTT_TYPE_2_SIDED;
+using ::RTT_TYPE_2_SIDED_11AZ_NTB;
+using ::RTT_TYPE_2_SIDED_11MC;
 using ::RX_PKT_FATE_DRV_DROP_FILTER;
 using ::RX_PKT_FATE_DRV_DROP_INVALID;
 using ::RX_PKT_FATE_DRV_DROP_NOBUFS;
@@ -350,16 +352,20 @@
 using ::WIFI_RTT_BW_80;
 using ::WIFI_RTT_BW_UNSPECIFIED;
 using ::wifi_rtt_capabilities;
+using ::wifi_rtt_capabilities_v3;
 using ::wifi_rtt_config;
+using ::wifi_rtt_config_v3;
 using ::wifi_rtt_preamble;
 using ::WIFI_RTT_PREAMBLE_EHT;
 using ::WIFI_RTT_PREAMBLE_HE;
 using ::WIFI_RTT_PREAMBLE_HT;
+using ::WIFI_RTT_PREAMBLE_INVALID;
 using ::WIFI_RTT_PREAMBLE_LEGACY;
 using ::WIFI_RTT_PREAMBLE_VHT;
 using ::wifi_rtt_responder;
 using ::wifi_rtt_result;
 using ::wifi_rtt_result_v2;
+using ::wifi_rtt_result_v3;
 using ::wifi_rtt_status;
 using ::wifi_rtt_type;
 using ::wifi_rx_packet_fate;
@@ -486,6 +492,8 @@
         std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
 using on_rtt_results_callback_v2 =
         std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result_v2*>&)>;
+using on_rtt_results_callback_v3 =
+        std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result_v3*>&)>;
 
 // Callback for ring buffer data.
 using on_ring_buffer_data_callback = std::function<void(
@@ -660,9 +668,15 @@
                                     const std::vector<wifi_rtt_config>& rtt_configs,
                                     const on_rtt_results_callback& on_results_callback,
                                     const on_rtt_results_callback_v2& on_results_callback_v2);
+    wifi_error startRttRangeRequestV3(const std::string& iface_name, wifi_request_id id,
+                                      const std::vector<wifi_rtt_config_v3>& rtt_configs,
+                                      const on_rtt_results_callback_v3& on_results_callback);
+
     wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id,
                                      const std::vector<std::array<uint8_t, ETH_ALEN>>& mac_addrs);
     std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(const std::string& iface_name);
+    std::pair<wifi_error, wifi_rtt_capabilities_v3> getRttCapabilitiesV3(
+            const std::string& iface_name);
     std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(const std::string& iface_name);
     wifi_error enableRttResponder(const std::string& iface_name, wifi_request_id id,
                                   const wifi_channel_info& channel_hint, uint32_t max_duration_secs,
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
index b5196c9..3d59c65 100644
--- a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
@@ -179,6 +179,8 @@
     populateStubFor(&hal_fn->wifi_set_scan_mode);
     populateStubFor(&hal_fn->wifi_set_mlo_mode);
     populateStubFor(&hal_fn->wifi_get_supported_iface_concurrency_matrix);
+    populateStubFor(&hal_fn->wifi_get_rtt_capabilities_v3);
+    populateStubFor(&hal_fn->wifi_rtt_range_request_v3);
     return true;
 }
 
diff --git a/wifi/aidl/default/wifi_rtt_controller.cpp b/wifi/aidl/default/wifi_rtt_controller.cpp
index a5f6768..9dee45c 100644
--- a/wifi/aidl/default/wifi_rtt_controller.cpp
+++ b/wifi/aidl/default/wifi_rtt_controller.cpp
@@ -136,11 +136,45 @@
 
 ndk::ScopedAStatus WifiRttController::rangeRequestInternal(
         int32_t cmd_id, const std::vector<RttConfig>& rtt_configs) {
+    // Try 11mc & 11az ranging (v3)
+    std::vector<legacy_hal::wifi_rtt_config_v3> legacy_configs_v3;
+    if (!aidl_struct_util::convertAidlVectorOfRttConfigToLegacyV3(rtt_configs,
+                                                                  &legacy_configs_v3)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    std::weak_ptr<WifiRttController> weak_ptr_this = weak_ptr_this_;
+    const auto& on_results_callback_v3 =
+            [weak_ptr_this](legacy_hal::wifi_request_id id,
+                            const std::vector<const legacy_hal::wifi_rtt_result_v3*>& results) {
+                const auto shared_ptr_this = weak_ptr_this.lock();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "v3 Callback invoked on an invalid object";
+                    return;
+                }
+                std::vector<RttResult> aidl_results;
+                if (!aidl_struct_util::convertLegacyVectorOfRttResultV3ToAidl(results,
+                                                                              &aidl_results)) {
+                    LOG(ERROR) << "Failed to convert rtt results v3 to AIDL structs";
+                    return;
+                }
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->onResults(id, aidl_results).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the v3 callback";
+                    }
+                }
+            };
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequestV3(
+            ifname_, cmd_id, legacy_configs_v3, on_results_callback_v3);
+
+    if (legacy_status != legacy_hal::WIFI_ERROR_NOT_SUPPORTED) {
+        return createWifiStatusFromLegacyError(legacy_status);
+    }
+
+    // Fallback to 11mc ranging.
     std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
     if (!aidl_struct_util::convertAidlVectorOfRttConfigToLegacy(rtt_configs, &legacy_configs)) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
-    std::weak_ptr<WifiRttController> weak_ptr_this = weak_ptr_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) {
@@ -181,7 +215,7 @@
                     }
                 }
             };
-    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequest(
+    legacy_status = legacy_hal_.lock()->startRttRangeRequest(
             ifname_, cmd_id, legacy_configs, on_results_callback, on_results_callback_v2);
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -201,13 +235,29 @@
 
 std::pair<RttCapabilities, ndk::ScopedAStatus> WifiRttController::getCapabilitiesInternal() {
     legacy_hal::wifi_error legacy_status;
-    legacy_hal::wifi_rtt_capabilities legacy_caps;
-    std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_);
+    legacy_hal::wifi_rtt_capabilities_v3 legacy_caps_v3;
+    std::tie(legacy_status, legacy_caps_v3) = legacy_hal_.lock()->getRttCapabilitiesV3(ifname_);
+    // Try v3 API first, if it is not supported fallback.
+    if (legacy_status == legacy_hal::WIFI_ERROR_NOT_SUPPORTED) {
+        legacy_hal::wifi_rtt_capabilities legacy_caps;
+        std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_);
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            return {RttCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
+        }
+
+        RttCapabilities aidl_caps;
+        if (!aidl_struct_util::convertLegacyRttCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+            return {RttCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+        }
+        return {aidl_caps, ndk::ScopedAStatus::ok()};
+    }
+
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {RttCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
     }
+
     RttCapabilities aidl_caps;
-    if (!aidl_struct_util::convertLegacyRttCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+    if (!aidl_struct_util::convertLegacyRttCapabilitiesV3ToAidl(legacy_caps_v3, &aidl_caps)) {
         return {RttCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
     }
     return {aidl_caps, ndk::ScopedAStatus::ok()};