release-request-f4ecf242-5d1c-45e0-8c7c-ede48d1a9e82-for-git_oc-release-4111650 snap-temp-L02200000075283731

Change-Id: I3d7c67d104e4f144b4e980503ba16c3ceef4c6eb
diff --git a/scanning/scan_utils.cpp b/scanning/scan_utils.cpp
index 5199e2b..42c55b2 100644
--- a/scanning/scan_utils.cpp
+++ b/scanning/scan_utils.cpp
@@ -151,17 +151,11 @@
       // These scan results are considered as malformed.
       return false;
     }
-    uint64_t tsf;
-    if (!bss.GetAttributeValue(NL80211_BSS_TSF, &tsf)) {
-      LOG(ERROR) << "Failed to get TSF from scan result packet";
+    uint64_t last_seen_since_boot;
+    if (!GetBssTimestamp(bss, &last_seen_since_boot)) {
+      // Logging is done inside |GetBssTimestamp|.
       return false;
     }
-    uint64_t beacon_tsf;
-    if (bss.GetAttributeValue(NL80211_BSS_BEACON_TSF, &beacon_tsf)) {
-      if (beacon_tsf > tsf) {
-        tsf = beacon_tsf;
-      }
-    }
     int32_t signal;
     if (!bss.GetAttributeValue(NL80211_BSS_SIGNAL_MBM, &signal)) {
       LOG(ERROR) << "Failed to get Signal Strength from scan result packet";
@@ -181,7 +175,26 @@
     }
 
     *scan_result =
-        NativeScanResult(ssid, bssid, ie, freq, signal, tsf, capability, associated);
+        NativeScanResult(ssid, bssid, ie, freq, signal,
+                         last_seen_since_boot, capability, associated);
+  }
+  return true;
+}
+
+bool ScanUtils::GetBssTimestamp(const NL80211NestedAttr& bss,
+                                uint64_t* last_seen_since_boot){
+  if (!bss.GetAttributeValue(NL80211_BSS_LAST_SEEN_BOOTTIME,
+                             last_seen_since_boot)) {
+    // Fall back to use TSF if we can't find NL80211_BSS_LAST_SEEN_BOOTTIME
+    // attribute.
+    if (!bss.GetAttributeValue(NL80211_BSS_TSF, last_seen_since_boot)) {
+      LOG(ERROR) << "Failed to get TSF from scan result packet";
+      return false;
+    }
+    uint64_t beacon_tsf;
+    if (bss.GetAttributeValue(NL80211_BSS_BEACON_TSF, &beacon_tsf)) {
+      *last_seen_since_boot = std::max(*last_seen_since_boot, beacon_tsf);
+    }
   }
   return true;
 }
diff --git a/scanning/scan_utils.h b/scanning/scan_utils.h
index 84baeec..dc3768e 100644
--- a/scanning/scan_utils.h
+++ b/scanning/scan_utils.h
@@ -42,6 +42,7 @@
 namespace wificond {
 
 class NL80211Packet;
+class NL80211NestedAttr;
 
 // Provides scanning helper functions.
 class ScanUtils {
@@ -136,6 +137,12 @@
   // interface with index |interface_index|.
   virtual void UnsubscribeSchedScanResultNotification(uint32_t interface_index);
 
+  // Visible for testing.
+  // Get a timestamp for the scan result |bss| represents.
+  // This timestamp records the time passed since boot when last time the
+  // AP was seen.
+  virtual bool GetBssTimestamp(const NL80211NestedAttr& bss,
+                               uint64_t* last_seen_since_boot);
  private:
   bool GetSSIDFromInfoElement(const std::vector<uint8_t>& ie,
                               std::vector<uint8_t>* ssid);
diff --git a/tests/scan_utils_unittest.cpp b/tests/scan_utils_unittest.cpp
index 3dbfe21..33ca4f8 100644
--- a/tests/scan_utils_unittest.cpp
+++ b/tests/scan_utils_unittest.cpp
@@ -176,5 +176,41 @@
       kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}));
 }
 
+TEST_F(ScanUtilsTest, CanPrioritizeLastSeenSinceBootNetlinkAttribute) {
+  constexpr uint64_t kLastSeenTimestamp = 123456;
+  constexpr uint64_t kBssTsfTimestamp = 654321;
+  NL80211NestedAttr bss(NL80211_ATTR_BSS);
+  bss.AddAttribute(
+      NL80211Attr<uint64_t>(NL80211_BSS_LAST_SEEN_BOOTTIME, kLastSeenTimestamp));
+  bss.AddAttribute(
+      NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestamp));
+  uint64_t timestamp;
+  EXPECT_TRUE(scan_utils_.GetBssTimestamp(bss, &timestamp));
+  EXPECT_EQ(kLastSeenTimestamp, timestamp);
+}
+
+TEST_F(ScanUtilsTest, CanHandleMissingLastSeenSinceBootNetlinkAttribute) {
+  constexpr uint64_t kBssTsfTimestamp = 654321;
+  NL80211NestedAttr bss(NL80211_ATTR_BSS);
+  bss.AddAttribute(
+      NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestamp));
+  uint64_t timestamp;
+  EXPECT_TRUE(scan_utils_.GetBssTimestamp(bss, &timestamp));
+  EXPECT_EQ(kBssTsfTimestamp, timestamp);
+}
+
+TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon) {
+  constexpr uint64_t kBssBeaconTsfTimestamp = 654321;
+  constexpr uint64_t kBssTsfTimestamp = kBssBeaconTsfTimestamp + 2000;
+  NL80211NestedAttr bss(NL80211_ATTR_BSS);
+  bss.AddAttribute(
+      NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF, kBssBeaconTsfTimestamp));
+  bss.AddAttribute(
+      NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestamp));
+  uint64_t timestamp;
+  EXPECT_TRUE(scan_utils_.GetBssTimestamp(bss, &timestamp));
+  EXPECT_EQ(kBssTsfTimestamp, timestamp);
+}
+
 }  // namespace wificond
 }  // namespace android