TetherController: A followup change refactors getTetherStats

Test: build, atest
Change-Id: I2e72ae3e0c0d9e5fc8b52dc0d2f0c8f01e886789
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index 16f272c..d332e0c 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -77,6 +77,9 @@
 const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
 const char SEPARATOR[] = "|";
 constexpr const char kTcpBeLiberal[] = "/proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal";
+
+// Dummy interface name, the name needs to be longer than 16 characters so it can never conflict
+// with a real interface name. See also IFNAMSIZ.
 constexpr const char kBpfOffloadInterface[] = "BPFOffloadInterface";
 
 // Chosen to match AID_DNS_TETHER, as made "friendly" by fs_config_generator.py.
@@ -999,27 +1002,33 @@
         }
     }
 
-    if (mBpfStatsMap.isValid()) {
-        const auto processTetherStats = [this, &statsList](
-                                                const uint32_t& key, const TetherStatsValue& value,
-                                                const BpfMap<uint32_t, TetherStatsValue>&) {
-            auto ifname = mIfaceIndexNameMap.readValue(key);
-            if (!ifname.ok()) {
-                // Keep on going regardless to parse as much as possible.
-                return Result<void>();
-            }
-            addStats(statsList,
-                     {kBpfOffloadInterface, ifname.value().name,
-                      static_cast<int64_t>(value.rxBytes), static_cast<int64_t>(value.rxPackets),
-                      static_cast<int64_t>(value.txBytes), static_cast<int64_t>(value.txPackets)});
-            return Result<void>();
-        };
+    if (!mBpfStatsMap.isValid()) {
+        return statsList;
+    }
 
-        auto ret = mBpfStatsMap.iterateWithValue(processTetherStats);
-        if (!ret.ok()) {
-            // Ignore error to return the non-BPF tether stats result.
-            ALOGE("Error processing tether stats from BPF maps: %s", ret.error().message().c_str());
+    const auto processTetherStats = [this, &statsList](const uint32_t& key,
+                                                       const TetherStatsValue& value,
+                                                       const BpfMap<uint32_t, TetherStatsValue>&) {
+        auto ifname = mIfaceIndexNameMap.readValue(key);
+        if (!ifname.ok()) {
+            // Keep on going regardless to parse as much as possible.
+            return Result<void>();
         }
+        // Because the same interface name can have different interface IDs over time, there might
+        // already be a TetherStats in the list with this interface name. This is fine because
+        // addStats will increment an existing TetherStats if there is one in the list already,
+        // and add a new TetherStats to the list if there isn't.
+        addStats(statsList,
+                 {kBpfOffloadInterface, ifname.value().name, static_cast<int64_t>(value.rxBytes),
+                  static_cast<int64_t>(value.rxPackets), static_cast<int64_t>(value.txBytes),
+                  static_cast<int64_t>(value.txPackets)});
+        return Result<void>();
+    };
+
+    auto ret = mBpfStatsMap.iterateWithValue(processTetherStats);
+    if (!ret.ok()) {
+        // Ignore error to return the non-BPF tether stats result.
+        ALOGE("Error processing tether stats from BPF maps: %s", ret.error().message().c_str());
     }
 
     return statsList;