Merge "wifi: Add support for multiple radio stats"
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index a89f8c0..fb93c5a 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -706,11 +706,17 @@
   hidl_stats->iface.wmeVoPktStats.retries =
       legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
   // radio legacy_stats conversion.
-  hidl_stats->radio.onTimeInMs = legacy_stats.radio.on_time;
-  hidl_stats->radio.txTimeInMs = legacy_stats.radio.tx_time;
-  hidl_stats->radio.rxTimeInMs = legacy_stats.radio.rx_time;
-  hidl_stats->radio.onTimeInMsForScan = legacy_stats.radio.on_time_scan;
-  hidl_stats->radio.txTimeInMsPerLevel = legacy_stats.radio_tx_time_per_levels;
+  std::vector<StaLinkLayerRadioStats> hidl_radios_stats;
+  for (const auto& legacy_radio_stats : legacy_stats.radios) {
+    StaLinkLayerRadioStats hidl_radio_stats;
+    hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time;
+    hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time;
+    hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time;
+    hidl_radio_stats.onTimeInMsForScan = legacy_radio_stats.stats.on_time_scan;
+    hidl_radio_stats.txTimeInMsPerLevel = legacy_radio_stats.tx_time_per_levels;
+    hidl_radios_stats.push_back(hidl_radio_stats);
+  }
+  hidl_stats->radios = hidl_radios_stats;
   // Timestamp in the HAL wrapper here since it's not provided in the legacy
   // HAL API.
   hidl_stats->timeStampInMs = uptimeMillis();
diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp
index f902e64..5fc0228 100644
--- a/wifi/1.0/default/wifi_legacy_hal.cpp
+++ b/wifi/1.0/default/wifi_legacy_hal.cpp
@@ -601,33 +601,37 @@
   LinkLayerStats link_stats{};
   LinkLayerStats* link_stats_ptr = &link_stats;
 
-  on_link_layer_stats_result_internal_callback = [&link_stats_ptr](
-      wifi_request_id /* id */,
-      wifi_iface_stat* iface_stats_ptr,
-      int num_radios,
-      wifi_radio_stat* radio_stats_ptr) {
-    if (iface_stats_ptr != nullptr) {
-      link_stats_ptr->iface = *iface_stats_ptr;
-      link_stats_ptr->iface.num_peers = 0;
-    } else {
-      LOG(ERROR) << "Invalid iface stats in link layer stats";
-    }
-    if (num_radios == 1 && radio_stats_ptr != nullptr) {
-      link_stats_ptr->radio = *radio_stats_ptr;
-      // Copy over the tx level array to the separate vector.
-      if (radio_stats_ptr->num_tx_levels > 0 &&
-          radio_stats_ptr->tx_time_per_levels != nullptr) {
-        link_stats_ptr->radio_tx_time_per_levels.assign(
-            radio_stats_ptr->tx_time_per_levels,
-            radio_stats_ptr->tx_time_per_levels +
-                radio_stats_ptr->num_tx_levels);
-      }
-      link_stats_ptr->radio.num_tx_levels = 0;
-      link_stats_ptr->radio.tx_time_per_levels = nullptr;
-    } else {
-      LOG(ERROR) << "Invalid radio stats in link layer stats";
-    }
-  };
+  on_link_layer_stats_result_internal_callback =
+      [&link_stats_ptr](wifi_request_id /* id */,
+                        wifi_iface_stat* iface_stats_ptr,
+                        int num_radios,
+                        wifi_radio_stat* radio_stats_ptr) {
+        if (iface_stats_ptr != nullptr) {
+          link_stats_ptr->iface = *iface_stats_ptr;
+          link_stats_ptr->iface.num_peers = 0;
+        } else {
+          LOG(ERROR) << "Invalid iface stats in link layer stats";
+        }
+        if (num_radios <= 0 || radio_stats_ptr == nullptr) {
+          LOG(ERROR) << "Invalid radio stats in link layer stats";
+          return;
+        }
+        for (int i = 0; i < num_radios; i++) {
+          LinkLayerRadioStats radio;
+          radio.stats = radio_stats_ptr[i];
+          // Copy over the tx level array to the separate vector.
+          if (radio_stats_ptr[i].num_tx_levels > 0 &&
+              radio_stats_ptr[i].tx_time_per_levels != nullptr) {
+            radio.tx_time_per_levels.assign(
+                radio_stats_ptr[i].tx_time_per_levels,
+                radio_stats_ptr[i].tx_time_per_levels +
+                    radio_stats_ptr[i].num_tx_levels);
+          }
+          radio.stats.num_tx_levels = 0;
+          radio.stats.tx_time_per_levels = nullptr;
+          link_stats_ptr->radios.push_back(radio);
+        }
+      };
 
   wifi_error status = global_func_table_.wifi_get_link_stats(
       0, wlan_interface_handle_, {onSyncLinkLayerStatsResult});
diff --git a/wifi/1.0/default/wifi_legacy_hal.h b/wifi/1.0/default/wifi_legacy_hal.h
index c8fd5bd..f79e62a 100644
--- a/wifi/1.0/default/wifi_legacy_hal.h
+++ b/wifi/1.0/default/wifi_legacy_hal.h
@@ -49,10 +49,14 @@
 // The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in
 // |wifi_radio_stat| structure in the legacy HAL API. Separate that out
 // into a separate return element to avoid passing pointers around.
+struct LinkLayerRadioStats {
+  wifi_radio_stat stats;
+  std::vector<uint32_t> tx_time_per_levels;
+};
+
 struct LinkLayerStats {
   wifi_iface_stat iface;
-  wifi_radio_stat radio;
-  std::vector<uint32_t> radio_tx_time_per_levels;
+  std::vector<LinkLayerRadioStats> radios;
 };
 #pragma GCC diagnostic pop
 
diff --git a/wifi/1.0/types.hal b/wifi/1.0/types.hal
index d90d5be..d3845c9 100644
--- a/wifi/1.0/types.hal
+++ b/wifi/1.0/types.hal
@@ -143,7 +143,7 @@
 /**
  * TimeStamp in milliseconds (ms).
  */
-typedef uint32_t TimeStampInMs;
+typedef uint64_t TimeStampInMs;
 
 /**
  * TimeStamp in microseconds (us).
@@ -478,7 +478,7 @@
  */
 struct StaLinkLayerStats {
   StaLinkLayerIfaceStats iface;
-  StaLinkLayerRadioStats radio;
+  vec<StaLinkLayerRadioStats> radios;
   /**
    * TimeStamp for each stats sample.
    * This is the absolute milliseconds from boot when these stats were