15a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang/*
25a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * Copyright (C) 2016 The Android Open Source Project
35a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang *
45a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * Licensed under the Apache License, Version 2.0 (the "License");
55a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * you may not use this file except in compliance with the License.
65a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * You may obtain a copy of the License at
75a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang *
85a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang *      http://www.apache.org/licenses/LICENSE-2.0
95a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang *
105a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * Unless required by applicable law or agreed to in writing, software
115a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * distributed under the License is distributed on an "AS IS" BASIS,
125a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * See the License for the specific language governing permissions and
145a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang * limitations under the License.
155a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang */
165a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
175a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang#ifndef WIFICOND_SCANNING_SCAN_UTILS_H_
185a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang#define WIFICOND_SCANNING_SCAN_UTILS_H_
195a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
2021ff4c7ad0b0ec8da8392c00eedbae022d6e21e5Ningyuan Wang#include <memory>
215a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang#include <vector>
225a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
235a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang#include <android-base/macros.h>
245a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
2514de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang#include "wificond/net/netlink_manager.h"
2614de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang
274d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wangnamespace com {
284d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wangnamespace android {
294d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wangnamespace server {
304d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wangnamespace wifi {
314d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wangnamespace wificond {
324d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang
334d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wangclass NativeScanResult;
340482e6d44600d35f159d9705050277196d6aa59cRoshan Piusclass RadioChainInfo;
354d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang
364d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang}  // namespace wificond
374d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang}  // namespace wifi
384d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang}  // namespace server
394d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang}  // namespace android
404d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang}  // namespace com
414d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang
425a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wangnamespace android {
435a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wangnamespace wificond {
445a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
451aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wangclass NL80211NestedAttr;
465a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wangclass NL80211Packet;
475a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
48dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wangstruct SchedScanIntervalSetting {
49dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang  struct ScanPlan {
50dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang    uint32_t interval_ms;
51dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang    uint32_t n_iterations;
52dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang  };
53dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang  std::vector<ScanPlan> plans;
54dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang  // After |plans| has been exhausted, scan at every
55dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang  // |final_interval_ms|.
56dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang  uint32_t final_interval_ms{0};
57dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang};
58dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang
595a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang// Provides scanning helper functions.
605a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wangclass ScanUtils {
615a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang public:
625a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  explicit ScanUtils(NetlinkManager* netlink_manager);
635a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  virtual ~ScanUtils();
645a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
655a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // Send 'get scan results' request to kernel and get the latest scan results.
665a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // |interface_index| is the index of interface we want to get scan results
675a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // from.
685a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // A vector of ScanResult object will be returned by |*out_scan_results|.
695a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // Returns true on success.
704d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang  virtual bool GetScanResult(
714d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang      uint32_t interface_index,
724d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang      std::vector<::com::android::server::wifi::wificond::NativeScanResult>* out_scan_results);
735a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
745a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // Send scan request to kernel for interface with index |interface_index|.
759d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |request_random_mac| If true, request device/driver to use a random MAC
769d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // address during scan. Requires |supports_random_mac_sched_scan|
7713b4064f889935091b0d55bbb056ec143972a9a4Ningyuan Wang  // address during scan.
789d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |scan_type| Type of scan to perform. One of,
799d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // |SCAN_TYPE_LOW_SPAN| (prioritize to reduce latency over other scan
809d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // performance attributes),
819d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // |SCAN_TYPE_LOW_POWER| (prioritize to reduce power consumption over other
829d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // scan performance attributes),
839d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // |SCAN_TYPE_HIGH_ACCURACY| (prioritize to increase accuracy over other scan
849d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // performance atrributes) OR
859d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // |SCAN_TYPE_DEFAULT| (no prioritization).
869d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |ssids| is a vector of ssids we request to scan, which mostly is used
875a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // for hidden networks.
885a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // If |ssids| is an empty vector, it will do a passive scan.
895a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // If |ssids| contains an empty string, it will a scan for all ssids.
909d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |freqs| is a vector of frequencies we request to scan.
915a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // If |freqs| is an empty vector, it will scan all supported frequencies.
929d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |error_code| contains the errno kernel replied when this returns false.
935a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // Returns true on success.
945a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  virtual bool Scan(uint32_t interface_index,
9513b4064f889935091b0d55bbb056ec143972a9a4Ningyuan Wang                    bool request_random_mac,
969d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius                    int scan_type,
975a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang                    const std::vector<std::vector<uint8_t>>& ssids,
98793978cb7f2f227f1ab28135caeb75dd4ed48e6cNingyuan Wang                    const std::vector<uint32_t>& freqs,
99793978cb7f2f227f1ab28135caeb75dd4ed48e6cNingyuan Wang                    int* error_code);
1005a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
101ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // Send scan request to kernel for interface with index |interface_index|.
1029d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |inteval_ms| is the expected scan interval in milliseconds.
1039d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |rssi_threshold_2g| is the minimum RSSI threshold value as a filter for
104c6ecdf8ea59f7de47edfd6161f059b8ab45d1f8fNingyuan Wang  // 2GHz band.
1059d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |rssi_threshold_5g| is the minimum RSSI threshold value as a filter for
106c6ecdf8ea59f7de47edfd6161f059b8ab45d1f8fNingyuan Wang  // 5GHz band.
1079d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |scan_ssids| is a vector of ssids we request to scan, which is mostly
108ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // used for hidden networks.
1099d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |request_random_mac| If true, request device/driver to use a random MAC
1109d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // address during scan. Requires |supports_random_mac_sched_scan|
1119d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |request_low_power|: If true, prioritize power consumption over
1129d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // other scan performance attributes.
1139d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // Requires |supports_low_power_oneshot_scan|.
1149d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |scan_ssids| is the list of ssids to actively scan for.
115ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // If |scan_ssids| is an empty vector, it will do a passive scan.
116ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // If |scan_ssids| contains an empty string, it will a scan for all ssids.
1179d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |match_ssids| is the list of ssids that we want to add as filters.
1189d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |freqs| is a vector of frequencies we request to scan.
119ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // If |freqs| is an empty vector, it will scan all supported frequencies.
1209d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius  // - |error_code| contains the errno kernel replied when this returns false.
121ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // Only BSSs match the |match_ssids| and |rssi_threshold| will be returned as
122ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // scan results.
123ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang  // Returns true on success.
12465b365fe4b6a99f9dab98515c1b96bd725cb56a8Ningyuan Wang  virtual bool StartScheduledScan(
125ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang      uint32_t interface_index,
126dfbe7e4e12824527fac840391f31d2b4a4578e3eNingyuan Wang      const SchedScanIntervalSetting& interval_setting,
127c6ecdf8ea59f7de47edfd6161f059b8ab45d1f8fNingyuan Wang      int32_t rssi_threshold_2g,
128c6ecdf8ea59f7de47edfd6161f059b8ab45d1f8fNingyuan Wang      int32_t rssi_threshold_5g,
12913b4064f889935091b0d55bbb056ec143972a9a4Ningyuan Wang      bool request_random_mac,
1309d096b2f0027b91e5eed40c0e2482d238cdf7c8aRoshan Pius      bool request_low_power,
131ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang      const std::vector<std::vector<uint8_t>>& scan_ssids,
132ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang      const std::vector<std::vector<uint8_t>>& match_ssids,
133793978cb7f2f227f1ab28135caeb75dd4ed48e6cNingyuan Wang      const std::vector<uint32_t>& freqs,
134793978cb7f2f227f1ab28135caeb75dd4ed48e6cNingyuan Wang      int* error_code);
135ebe363ff1e912429c1691a00a29bf6bc83e5c08aNingyuan Wang
1368044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // Stop existing scheduled scan on interface with index |interface_index|.
1378044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // Returns true on success.
1388044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // Returns false on error or when there is no scheduled scan running.
1398044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  virtual bool StopScheduledScan(uint32_t interface_index);
1408044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang
14133bbb8147436c2abf8f3e7b535b13b6c63bd3c64Daisuke Niwa  // Abort ongoing single scan on interface with index |interface_index|.
14233bbb8147436c2abf8f3e7b535b13b6c63bd3c64Daisuke Niwa  // Returns true on success.
14333bbb8147436c2abf8f3e7b535b13b6c63bd3c64Daisuke Niwa  virtual bool AbortScan(uint32_t interface_index);
14433bbb8147436c2abf8f3e7b535b13b6c63bd3c64Daisuke Niwa
1451aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang  // Visible for testing.
1461aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang  // Get a timestamp for the scan result |bss| represents.
1471aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang  // This timestamp records the time passed since boot when last time the
1481aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang  // AP was seen.
1491aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang  virtual bool GetBssTimestampForTesting(
1501aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang      const NL80211NestedAttr& bss,
1511aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang       uint64_t* last_seen_since_boot_microseconds);
1521aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang
15314de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  // Sign up to be notified when new scan results are available.
15414de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  // |handler| will be called when the kernel signals to wificond that a scan
15514de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  // has been completed on the given |interface_index|.  See the declaration of
15614de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  // OnScanResultsReadyHandler for documentation on the semantics of this
15714de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  // callback.
15814de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  virtual void SubscribeScanResultNotification(
15914de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang      uint32_t interface_index,
16014de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang      OnScanResultsReadyHandler handler);
16114de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang
16214de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  // Cancel the sign-up of receiving new scan result notification from
16314de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  // interface with index |interface_index|.
16414de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang  virtual void UnsubscribeScanResultNotification(uint32_t interface_index);
16514de8b2ce5ef49218e48002a3ac0728847e90372Ningyuan Wang
1668044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // Sign up to be notified when new scan results are available.
1678044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // |handler| will be called when the kernel signals to wificond that a
1688044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // scheduled scan has been completed on the given |interface_index|.
1698044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // See the declaration of OnSchedScanResultsReadyHandler for documentation
1708044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // on the semantics of this callback.
1718044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  virtual void SubscribeSchedScanResultNotification(
1728044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang      uint32_t interface_index,
1738044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang      OnSchedScanResultsReadyHandler handler);
1748044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang
1758044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // Cancel the sign-up of receiving new scheduled scan result notification from
1768044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  // interface with index |interface_index|.
1778044a946f4b350291ddd44c52db7ca34e21bad8fNingyuan Wang  virtual void UnsubscribeSchedScanResultNotification(uint32_t interface_index);
178a5cc66dc98eeb29138164f497bb0e39352df5f36Ningyuan Wang
1795a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang private:
1801aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang  bool GetBssTimestamp(const NL80211NestedAttr& bss,
1811aadd2c3781ee882e77dae2f4dc38fe3574fdca7Ningyuan Wang                       uint64_t* last_seen_since_boot_microseconds);
1820482e6d44600d35f159d9705050277196d6aa59cRoshan Pius  bool ParseRadioChainInfos(
1830482e6d44600d35f159d9705050277196d6aa59cRoshan Pius      const NL80211NestedAttr& bss,
1840482e6d44600d35f159d9705050277196d6aa59cRoshan Pius      std::vector<::com::android::server::wifi::wificond::RadioChainInfo>
1850482e6d44600d35f159d9705050277196d6aa59cRoshan Pius        *radio_chain_infos);
1865a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  bool GetSSIDFromInfoElement(const std::vector<uint8_t>& ie,
1875a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang                              std::vector<uint8_t>* ssid);
1885a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  // Converts a NL80211_CMD_NEW_SCAN_RESULTS packet to a ScanResult object.
1894d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang  bool ParseScanResult(
1904d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang      std::unique_ptr<const NL80211Packet> packet,
1914d882abea2a9956689d32820a5c13e9f9625e0daNingyuan Wang      ::com::android::server::wifi::wificond::NativeScanResult* scan_result);
1925a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
1935a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  NetlinkManager* netlink_manager_;
1945a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
1955a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang  DISALLOW_COPY_AND_ASSIGN(ScanUtils);
1965a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang};
1975a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
1985a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang}  // namespace wificond
1995a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang}  // namespace android
2005a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang
2015a34c89bf63f387c38b5e60e8c733de7051e22aeNingyuan Wang#endif  // WIFICOND_SCANNING_SCAN_UTILS_H_
202