diff --git a/Package.swift b/Package.swift index 45fd27b3..4f55fd1d 100644 --- a/Package.swift +++ b/Package.swift @@ -437,6 +437,7 @@ let package = Package( "connections/implementation/mediums/lost_entity_tracker_test.cc", "connections/implementation/mediums/bluetooth_radio_test.cc", "connections/implementation/mediums/wifi_hotspot_test.cc", + "connections/implementation/mediums/wifi_test.cc", "connections/implementation/endpoint_channel_manager_test.cc", "connections/implementation/bwu_manager_test.cc", "connections/implementation/base_bwu_handler_test.cc", @@ -462,6 +463,8 @@ let package = Package( "internal/platform/uuid_test.cc", "internal/platform/wifi_hotspot_test.cc", "internal/platform/wifi_lan_test.cc", + "internal/platform/wifi_test.cc", + "internal/platform/wifi_utils_test.cc", "internal/platform/condition_variable_test.cc", "internal/platform/thread_check_nocompile_test.py", "internal/platform/bluetooth_classic_test.cc", diff --git a/connections/implementation/base_pcp_handler.cc b/connections/implementation/base_pcp_handler.cc index 942f81e7..187947aa 100644 --- a/connections/implementation/base_pcp_handler.cc +++ b/connections/implementation/base_pcp_handler.cc @@ -548,11 +548,31 @@ Status BasePcpHandler::RequestConnection( // Generate the nonce to use for this connection. std::int32_t nonce = prng_.NextInt32(); + bool is_supports_5_ghz = false; + std::string bssid = ""; + std::int32_t ap_frequency = -1; + std::string ip_address = ""; + if (mediums_->GetWifi().IsAvailable()) { + is_supports_5_ghz = + mediums_->GetWifi().GetCapability().supports_5_ghz; + + api::WifiInformation& wifi_info = + mediums_->GetWifi().GetInformation(); + bssid = wifi_info.bssid; + ap_frequency = wifi_info.ap_frequency; + ip_address = wifi_info.ip_address_4_bytes; + NEARBY_LOGS(INFO) << "Query for WIFI information: is_supports_5_ghz=" + << is_supports_5_ghz << "; bssid=" << bssid + << "; ap_frequency=" << ap_frequency + << "Mhz; ip_address in bytes format=" << ip_address; + } + // The first message we have to send, after connecting, is to tell the // endpoint about ourselves. Exception write_exception = WriteConnectionRequestFrame( channel.get(), client->GetLocalEndpointId(), info.endpoint_info, - nonce, GetSupportedConnectionMediumsByPriority(connection_options), + nonce, is_supports_5_ghz, bssid, ap_frequency, ip_address, + GetSupportedConnectionMediumsByPriority(connection_options), connection_options.keep_alive_interval_millis, connection_options.keep_alive_timeout_millis); if (!write_exception.Ok()) { @@ -710,12 +730,14 @@ bool BasePcpHandler::CanReceiveIncomingConnection(ClientProxy* client) const { Exception BasePcpHandler::WriteConnectionRequestFrame( EndpointChannel* endpoint_channel, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, std::int32_t nonce, + bool supports_5_ghz, const std::string& bssid, std::int32_t ap_frequency, + const std::string& ip_address, const std::vector& supported_mediums, std::int32_t keep_alive_interval_millis, std::int32_t keep_alive_timeout_millis) { return endpoint_channel->Write(parser::ForConnectionRequest( - local_endpoint_id, local_endpoint_info, nonce, /*supports_5_ghz =*/false, - /*bssid=*/std::string{}, supported_mediums, keep_alive_interval_millis, + local_endpoint_id, local_endpoint_info, nonce, supports_5_ghz, bssid, + ap_frequency, ip_address, supported_mediums, keep_alive_interval_millis, keep_alive_timeout_millis)); } diff --git a/connections/implementation/base_pcp_handler.h b/connections/implementation/base_pcp_handler.h index 7b9b47ca..305a7c31 100644 --- a/connections/implementation/base_pcp_handler.h +++ b/connections/implementation/base_pcp_handler.h @@ -387,6 +387,8 @@ class BasePcpHandler : public PcpHandler, static Exception WriteConnectionRequestFrame( EndpointChannel* endpoint_channel, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, std::int32_t nonce, + bool supports_5_ghz, const std::string& bssid, std::int32_t ap_frequency, + const std::string& ip_address, const std::vector& supported_mediums, std::int32_t keep_alive_interval_millis, std::int32_t keep_alive_timeout_millis); diff --git a/connections/implementation/endpoint_manager_test.cc b/connections/implementation/endpoint_manager_test.cc index a60ca416..7c827006 100644 --- a/connections/implementation/endpoint_manager_test.cc +++ b/connections/implementation/endpoint_manager_test.cc @@ -195,9 +195,10 @@ TEST_F(EndpointManagerTest, RegisterFrameProcessorWorks) { auto endpoint_channel = std::make_unique(); auto connect_request = std::make_unique(); ByteArray endpoint_info{"endpoint_name"}; - auto read_data = - parser::ForConnectionRequest("endpoint_id", endpoint_info, 1234, false, - "", std::vector{Medium::BLE}, 0, 0); + auto read_data = parser::ForConnectionRequest( + "endpoint_id", endpoint_info, 1234, false, "", 2412, "8xqT", + std::vector{Medium::BLE}, 0, + 0); EXPECT_CALL(*connect_request, OnIncomingFrame); EXPECT_CALL(*connect_request, OnEndpointDisconnect); EXPECT_CALL(*endpoint_channel, Read()) diff --git a/connections/implementation/mediums/BUILD b/connections/implementation/mediums/BUILD index 71d3faae..afefd618 100644 --- a/connections/implementation/mediums/BUILD +++ b/connections/implementation/mediums/BUILD @@ -32,6 +32,7 @@ cc_library( "bluetooth_radio.h", "mediums.h", "webrtc_stub.h", + "wifi.h", "wifi_hotspot.h", "wifi_lan.h", ], @@ -101,6 +102,7 @@ cc_test( "lost_entity_tracker_test.cc", "wifi_hotspot_test.cc", "wifi_lan_test.cc", + "wifi_test.cc", ], defines = ["NO_WEBRTC"], shard_count = 16, diff --git a/connections/implementation/mediums/mediums.cc b/connections/implementation/mediums/mediums.cc index 051562b3..bc686c1b 100644 --- a/connections/implementation/mediums/mediums.cc +++ b/connections/implementation/mediums/mediums.cc @@ -26,6 +26,8 @@ Ble& Mediums::GetBle() { return ble_; } BleV2& Mediums::GetBleV2() { return ble_v2_; } +Wifi& Mediums::GetWifi() { return wifi_; } + WifiLan& Mediums::GetWifiLan() { return wifi_lan_; } WifiHotspot& Mediums::GetWifiHotspot() { return wifi_hotspot_; } diff --git a/connections/implementation/mediums/mediums.h b/connections/implementation/mediums/mediums.h index 28a9c95c..aa4743c8 100644 --- a/connections/implementation/mediums/mediums.h +++ b/connections/implementation/mediums/mediums.h @@ -24,6 +24,7 @@ #else #include "connections/implementation/mediums/webrtc.h" #endif +#include "connections/implementation/mediums/wifi.h" #include "connections/implementation/mediums/wifi_hotspot.h" #include "connections/implementation/mediums/wifi_lan.h" @@ -49,6 +50,9 @@ class Mediums { // Returns a handle to the Ble medium. BleV2& GetBleV2(); + // Returns a handle to the Wifi medium. + Wifi& GetWifi(); + // Returns a handle to the Wifi-Lan medium. WifiLan& GetWifiLan(); @@ -71,6 +75,7 @@ class Mediums { BluetoothClassic bluetooth_classic_{bluetooth_radio_}; Ble ble_{bluetooth_radio_}; BleV2 ble_v2_{bluetooth_radio_}; + Wifi wifi_; WifiLan wifi_lan_; WifiHotspot wifi_hotspot_; mediums::WebRtc webrtc_; diff --git a/connections/implementation/mediums/wifi.h b/connections/implementation/mediums/wifi.h new file mode 100644 index 00000000..34caa6d6 --- /dev/null +++ b/connections/implementation/mediums/wifi.h @@ -0,0 +1,80 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CORE_INTERNAL_MEDIUMS_WIFI_H_ +#define CORE_INTERNAL_MEDIUMS_WIFI_H_ + +// #include "internal/platform/mutex.h" +#include + +#include "internal/platform/mutex_lock.h" +#include "internal/platform/wifi.h" + +namespace location { +namespace nearby { +namespace connections { + +class Wifi { + public: + Wifi() = default; + ~Wifi() = default; + // Not copyable or movable + Wifi(const Wifi&) = delete; + Wifi& operator=(const Wifi&) = delete; + Wifi(Wifi&&) = delete; + Wifi& operator=(Wifi&&) = delete; + + // Returns true, if Wifi Medium are supported by a platform. + bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_) { + MutexLock lock(&mutex_); + return IsAvailableLocked(); + } + + api::WifiCapability& GetCapability() { + MutexLock lock(&mutex_); + return medium_.GetCapability(); + } + + api::WifiInformation& GetInformation() { + MutexLock lock(&mutex_); + return medium_.GetInformation(); + } + + bool VerifyInternetConnectivity() { + MutexLock lock(&mutex_); + return medium_.VerifyInternetConnectivity(); + } + + std::string GetIpAddress() const { + MutexLock lock(&mutex_); + return medium_.GetIpAddress(); + } + + private: + mutable Mutex mutex_; + WifiMedium medium_ ABSL_GUARDED_BY(mutex_); + + // Same as IsAvailable(), but must be called with mutex_ held. + bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) { + if (medium_.IsValid()) return medium_.IsInterfaceValid(); + + return false; + } +}; + +} // namespace connections +} // namespace nearby +} // namespace location + +#endif // CORE_INTERNAL_MEDIUMS_WIFI_H_ diff --git a/connections/implementation/mediums/wifi_test.cc b/connections/implementation/mediums/wifi_test.cc new file mode 100644 index 00000000..2488a0fc --- /dev/null +++ b/connections/implementation/mediums/wifi_test.cc @@ -0,0 +1,49 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "connections/implementation/mediums/wifi.h" + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace location { +namespace nearby { +namespace connections { +namespace { + +TEST(WifiTest, ConstructorDestructorWorks) { + Wifi wifi_a; + Wifi wifi_b; + + if (wifi_a.IsAvailable() && wifi_b.IsAvailable()) { + // Make sure we can create 2 distinct mediums. + EXPECT_NE(&wifi_a, &wifi_b); + } + // TODO(b/233324423): Add test coverage for wifi.h +} + +TEST(WifiTest, CanGetCapability) { + // TODO(b/233324423): Add test coverage for wifi.h +} + +TEST(WifiTest, CanInformation) { + // TODO(b/233324423): Add test coverage for wifi.h +} + + +} // namespace +} // namespace connections +} // namespace nearby +} // namespace location diff --git a/connections/implementation/offline_frames.cc b/connections/implementation/offline_frames.cc index 41829302..5294a482 100644 --- a/connections/implementation/offline_frames.cc +++ b/connections/implementation/offline_frames.cc @@ -66,6 +66,8 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id, const ByteArray& endpoint_info, std::int32_t nonce, bool supports_5_ghz, const std::string& bssid, + std::int32_t ap_frequency, + const std::string& ip_address, const std::vector& mediums, std::int32_t keep_alive_interval_millis, std::int32_t keep_alive_timeout_millis) { @@ -84,6 +86,8 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id, auto* medium_metadata = connection_request->mutable_medium_metadata(); medium_metadata->set_supports_5_ghz(supports_5_ghz); if (!bssid.empty()) medium_metadata->set_bssid(bssid); + medium_metadata->set_ap_frequency(ap_frequency); + if (!ip_address.empty()) medium_metadata->set_ip_address(ip_address); if (!mediums.empty()) { for (const auto& medium : mediums) { connection_request->add_mediums(MediumToConnectionRequestMedium(medium)); diff --git a/connections/implementation/offline_frames.h b/connections/implementation/offline_frames.h index 3dc52290..462de6f4 100644 --- a/connections/implementation/offline_frames.h +++ b/connections/implementation/offline_frames.h @@ -46,6 +46,8 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id, const ByteArray& endpoint_info, std::int32_t nonce, bool supports_5_ghz, const std::string& bssid, + std::int32_t ap_frequency, + const std::string& ip_address, const std::vector& mediums, std::int32_t keep_alive_interval_millis, std::int32_t keep_alive_timeout_millis); diff --git a/connections/implementation/offline_frames_test.cc b/connections/implementation/offline_frames_test.cc index d34e431f..d434b6cf 100644 --- a/connections/implementation/offline_frames_test.cc +++ b/connections/implementation/offline_frames_test.cc @@ -40,6 +40,8 @@ constexpr absl::string_view kEndpointName{"XYZ"}; constexpr int kNonce = 1234; constexpr bool kSupports5ghz = true; constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"}; +constexpr int kApFrequency = 2412; +constexpr absl::string_view kIp4Bytes = {"8xqT"}; constexpr std::array kMediums = { Medium::MDNS, Medium::BLUETOOTH, Medium::WIFI_HOTSPOT, Medium::BLE, Medium::WIFI_LAN, Medium::WIFI_AWARE, @@ -95,7 +97,7 @@ TEST(OfflineFramesTest, CanGenerateConnectionRequest) { endpoint_name: "XYZ" endpoint_info: "XYZ" nonce: 1234 - medium_metadata: < supports_5_ghz: true bssid: "FF:FF:FF:FF:FF:FF" > + medium_metadata: < supports_5_ghz: true bssid: "FF:FF:FF:FF:FF:FF" ip_address: "8xqT" ap_frequency: 2412 > mediums: MDNS mediums: BLUETOOTH mediums: WIFI_HOTSPOT @@ -111,9 +113,10 @@ TEST(OfflineFramesTest, CanGenerateConnectionRequest) { >)pb"; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); + kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes), + std::vector>(kMediums.begin(), + kMediums.end()), + kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); diff --git a/connections/implementation/offline_frames_validator_test.cc b/connections/implementation/offline_frames_validator_test.cc index e70e251d..04cd73e6 100644 --- a/connections/implementation/offline_frames_validator_test.cc +++ b/connections/implementation/offline_frames_validator_test.cc @@ -35,6 +35,8 @@ constexpr absl::string_view kEndpointName{"XYZ"}; constexpr int kNonce = 1234; constexpr bool kSupports5ghz = true; constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"}; +constexpr int kApFrequency = 2412; +constexpr absl::string_view kIp4Bytes = {"8xqT"}; constexpr int kStatusAccepted = 0; constexpr absl::string_view kSsid = "ssid"; constexpr absl::string_view kPassword = "password"; @@ -57,9 +59,10 @@ TEST(OfflineFramesValidatorTest, ValidatesAsOkWithValidConnectionRequestFrame) { ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); + kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes), + std::vector>(kMediums.begin(), + kMediums.end()), + kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); @@ -73,9 +76,10 @@ TEST(OfflineFramesValidatorTest, ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); + kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes), + std::vector>(kMediums.begin(), + kMediums.end()), + kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto* v1_frame = offline_frame.mutable_v1(); @@ -93,9 +97,10 @@ TEST(OfflineFramesValidatorTest, std::string empty_enpoint_id; ByteArray bytes = ForConnectionRequest( empty_enpoint_id, ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); + kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes), + std::vector>(kMediums.begin(), + kMediums.end()), + kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); @@ -110,7 +115,9 @@ TEST(OfflineFramesValidatorTest, ByteArray empty_endpoint_info; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), empty_endpoint_info, kNonce, kSupports5ghz, - std::string(kBssid), std::vector(kMediums.begin(), kMediums.end()), + std::string(kBssid), kApFrequency, std::string(kIp4Bytes), + std::vector>(kMediums.begin(), + kMediums.end()), kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); @@ -126,7 +133,9 @@ TEST(OfflineFramesValidatorTest, std::string empty_bssid; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, empty_bssid, std::vector(kMediums.begin(), kMediums.end()), + kSupports5ghz, empty_bssid, kApFrequency, std::string(kIp4Bytes), + std::vector>(kMediums.begin(), + kMediums.end()), kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); @@ -142,8 +151,8 @@ TEST(OfflineFramesValidatorTest, std::vector empty_mediums; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), empty_mediums, - kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); + kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes), + empty_mediums, kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); diff --git a/internal/platform/BUILD b/internal/platform/BUILD index 02870d32..6ea26e6b 100644 --- a/internal/platform/BUILD +++ b/internal/platform/BUILD @@ -334,14 +334,17 @@ cc_library( "file.cc", "wifi_hotspot.cc", "wifi_lan.cc", + "wifi_utils.cc", ], hdrs = [ "ble.h", "ble_v2.h", "bluetooth_adapter.h", "bluetooth_classic.h", + "wifi.h", "wifi_hotspot.h", "wifi_lan.h", + "wifi_utils.h", ], copts = ["-DCORE_ADAPTER_DLL"], defines = ["NO_WEBRTC"], @@ -350,6 +353,7 @@ cc_library( "//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__", "//internal/analytics:__subpackages__", "//internal/platform:__pkg__", + "//internal/platform/implementation:__subpackages__", ], deps = [ ":logging", @@ -390,6 +394,8 @@ cc_test( "uuid_test.cc", "wifi_hotspot_test.cc", "wifi_lan_test.cc", + "wifi_test.cc", + "wifi_utils_test.cc", ], copts = ["-DCORE_ADAPTER_DLL"], defines = ["NO_WEBRTC"], diff --git a/internal/platform/implementation/wifi.h b/internal/platform/implementation/wifi.h index 1f0f5b75..21c85ed0 100644 --- a/internal/platform/implementation/wifi.h +++ b/internal/platform/implementation/wifi.h @@ -46,6 +46,39 @@ enum class WifiConnectionStatus { kAuthFailure = 3, }; +// WIFI Band type. +enum class WifiBandType { + kUnknown = 0, + kBand24Ghz = 1, + kBand5Ghz = 2, + kBand6Ghz = 3, + kBand60Ghz = 4, +}; + +// Native WIFI's capablity parameters +struct WifiCapability { + bool supports_5_ghz = false; + bool supports_6_ghz = false; +}; + +// Native WIFI's information parameters +struct WifiInformation { + // Is this WIFI interface connected to AP or not + bool is_connected; + // AP's SSID if connected + std::string ssid; + // WiFi LAN BSSID, in the form of a six-byte MAC address: XX:XX:XX:XX:XX:XX + std::string bssid; + // The frequency of the WiFi LAN AP(in MHz, or -1 is not associated with an AP + // over WiFi). + std::int32_t ap_frequency; + // The interface's IP address in the form of "xx.xx.xx.xx" + std::string ip_address_dot_decimal; + // IP address, in network byte order: the highest order byte of the address is + // in byte[0]. + std::string ip_address_4_bytes; +}; + // Represents a WiFi network found during a call to WifiMedium#scan(). class WifiScanResult { public: @@ -66,6 +99,12 @@ class WifiMedium { public: virtual ~WifiMedium() {} + virtual bool IsInterfaceValid() const = 0; + + virtual WifiCapability& GetCapability() = 0; + + virtual WifiInformation& GetInformation() = 0; + class ScanResultCallback { public: virtual ~ScanResultCallback() = default; diff --git a/internal/platform/implementation/windows/BUILD b/internal/platform/implementation/windows/BUILD index b6a958a1..bc47babe 100644 --- a/internal/platform/implementation/windows/BUILD +++ b/internal/platform/implementation/windows/BUILD @@ -73,6 +73,7 @@ cc_library( visibility = ["//visibility:private"], deps = [ "//internal/platform:base", + "//internal/platform:comm", "//internal/platform:types", "//internal/platform/implementation:comm", "//internal/platform/implementation:types", @@ -124,6 +125,7 @@ cc_library( "wifi_lan_medium.cc", "wifi_lan_server_socket.cc", "wifi_lan_socket.cc", + "wifi_medium.cc", ], copts = ["-Ithird_party/nearby/internal/platform/implementation/windows/generated"], defines = ["_SILENCE_CLANG_COROUTINE_MESSAGE"], diff --git a/internal/platform/implementation/windows/generated/BUILD b/internal/platform/implementation/windows/generated/BUILD index 441241c7..d7049d68 100644 --- a/internal/platform/implementation/windows/generated/BUILD +++ b/internal/platform/implementation/windows/generated/BUILD @@ -32,6 +32,7 @@ cc_library( "comsuppwd.lib", "setupapi.lib", "dnsapi.lib", + "wlanapi.lib", ], textual_hdrs = glob(["**/*.h"]), visibility = [ diff --git a/internal/platform/implementation/windows/platform.cc b/internal/platform/implementation/windows/platform.cc index a74bf4d7..6cda5c07 100644 --- a/internal/platform/implementation/windows/platform.cc +++ b/internal/platform/implementation/windows/platform.cc @@ -227,7 +227,7 @@ ImplementationPlatform::CreateServerSyncMedium() { // TODO(b/184975123): replace with real implementation. std::unique_ptr ImplementationPlatform::CreateWifiMedium() { - return std::unique_ptr(); + return std::make_unique(); } std::unique_ptr ImplementationPlatform::CreateWifiLanMedium() { diff --git a/internal/platform/implementation/windows/wifi.h b/internal/platform/implementation/windows/wifi.h index 2fdfa27e..366847d7 100644 --- a/internal/platform/implementation/windows/wifi.h +++ b/internal/platform/implementation/windows/wifi.h @@ -15,12 +15,29 @@ #ifndef PLATFORM_IMPL_WINDOWS_WIFI_H_ #define PLATFORM_IMPL_WINDOWS_WIFI_H_ +#include +#include +#include +#include + +// Nearby connections headers #include "internal/platform/implementation/wifi.h" +#include "internal/platform/wifi_utils.h" + +// WinRT headers +#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.h" +#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.Collections.h" +#include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Connectivity.h" namespace location { namespace nearby { namespace windows { +using ::winrt::Windows::Networking::HostName; +using ::winrt::Windows::Networking::HostNameType; +using ::winrt::Windows::Networking::Connectivity::ConnectionProfile; +using ::winrt::Windows::Networking::Connectivity::NetworkInformation; + // Represents a WiFi network found during a call to WifiMedium#scan(). class WifiScanResult : public api::WifiScanResult { public: @@ -46,9 +63,15 @@ class WifiScanResult : public api::WifiScanResult { // Container of operations that can be performed over the WiFi medium. class WifiMedium : public api::WifiMedium { public: - // TODO(b/184975123): replace with real implementation. + WifiMedium(); ~WifiMedium() override = default; + bool IsInterfaceValid() const override; + + api::WifiCapability& GetCapability() override { return wifi_capability_; } + + api::WifiInformation& GetInformation() override; + class ScanResultCallback : public api::WifiMedium::ScanResultCallback { public: // TODO(b/184975123): replace with real implementation. @@ -88,7 +111,16 @@ class WifiMedium : public api::WifiMedium { // Returns the local device's IP address in the IPv4 dotted-quad format. // TODO(b/184975123): replace with real implementation. - std::string GetIpAddress() override { return "Un-implemented"; } + std::string GetIpAddress() override; + + private: + // Since the WIFI interface capability won't change in the connection session, + // we only need to querry it once at the beginning + void InitCapability(); + + bool wifi_interface_valid_; + api::WifiCapability wifi_capability_; + api::WifiInformation wifi_information_; }; } // namespace windows diff --git a/internal/platform/implementation/windows/wifi_medium.cc b/internal/platform/implementation/windows/wifi_medium.cc new file mode 100644 index 00000000..5950ed78 --- /dev/null +++ b/internal/platform/implementation/windows/wifi_medium.cc @@ -0,0 +1,228 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/strings/str_format.h" +#include "internal/platform/implementation/windows/wifi.h" +#include "internal/platform/implementation/windows/utils.h" +#include "internal/platform/logging.h" + +namespace location { +namespace nearby { +namespace windows { + +namespace { + constexpr int kMacAddrLen = 6; + constexpr int kDefaultApFreq = -1; +} // namespace + + +WifiMedium::WifiMedium() { + InitCapability(); +} + +PWLAN_INTERFACE_INFO_LIST EnumInterface(PHANDLE client_handle) { + DWORD client_version = 2; + DWORD negotiated_version = 0; + DWORD result = 0; + + /* variables used for WlanEnumInterfaces */ + PWLAN_INTERFACE_INFO_LIST p_intf_list = NULL; + + result = + WlanOpenHandle(client_version, NULL, &negotiated_version, client_handle); + if (result != ERROR_SUCCESS) { + NEARBY_LOGS(INFO) << "WlanOpenHandle failed with error: " << result; + return p_intf_list; + } + + result = WlanEnumInterfaces(*client_handle, NULL, &p_intf_list); + if (result != ERROR_SUCCESS) { + NEARBY_LOGS(INFO) << "WlanEnumInterfaces failed with error: " << result; + } + return p_intf_list; +} + +bool WifiMedium::IsInterfaceValid() const { + return wifi_interface_valid_; +} + +void WifiMedium::InitCapability() { + HANDLE client_handle = NULL; + + /* variables used for WlanEnumInterfaces */ + PWLAN_INTERFACE_INFO_LIST p_intf_list = NULL; + PWLAN_INTERFACE_INFO p_intf_info = NULL; + PWLAN_INTERFACE_CAPABILITY p_intf_capability = NULL; + + wifi_capability_.supports_5_ghz = false; + wifi_capability_.supports_6_ghz = false; + wifi_interface_valid_ = false; + + p_intf_list = EnumInterface(&client_handle); + if (!client_handle) { + NEARBY_LOGS(INFO) << "Client Handle is NULL"; + return; + } + if (!p_intf_list) { + NEARBY_LOGS(INFO) << "WlanEnumInterfaces failed with error: "; + return; + } + wifi_interface_valid_ = true; + + for (int i = 0; i < (int)p_intf_list->dwNumberOfItems; i++) { + p_intf_info = (WLAN_INTERFACE_INFO*)&p_intf_list->InterfaceInfo[i]; + if (WlanGetInterfaceCapability(client_handle, &p_intf_info->InterfaceGuid, + NULL, &p_intf_capability) != ERROR_SUCCESS) { + NEARBY_LOGS(INFO) << "Get Capability failed"; + WlanFreeMemory(p_intf_list); + p_intf_list = NULL; + return; + } + + for (int j = 0; j < p_intf_capability->dwNumberOfSupportedPhys; j++) { + if (p_intf_capability->dot11PhyTypes[j] == dot11_phy_type_ofdm) + wifi_capability_.supports_5_ghz = true; + } + } + + WlanFreeMemory(p_intf_capability); + p_intf_capability = NULL; + WlanFreeMemory(p_intf_list); + p_intf_list = NULL; +} + +api::WifiInformation& WifiMedium::GetInformation() { + HANDLE client_handle = NULL; + PWLAN_AVAILABLE_NETWORK_LIST pWLAN_AVAILABLE_NETWORK_LIST = NULL; + DWORD result = 0; + DWORD connect_info_size = sizeof(WLAN_CONNECTION_ATTRIBUTES); + WLAN_OPCODE_VALUE_TYPE op_code_value_type = wlan_opcode_value_type_invalid; + + /* variables used for WlanEnumInterfaces */ + PWLAN_INTERFACE_INFO_LIST p_intf_list = NULL; + PWLAN_INTERFACE_INFO p_intf_info = NULL; + PWLAN_CONNECTION_ATTRIBUTES p_connect_info = NULL; + ULONG* channel = NULL; + + wifi_information_.is_connected = false; + wifi_information_.ap_frequency = kDefaultApFreq; + + p_intf_list = EnumInterface(&client_handle); + if (!client_handle) { + NEARBY_LOGS(INFO) << "Client Handle is NULL"; + return wifi_information_; + } + if (!p_intf_list) { + NEARBY_LOGS(INFO) << "WlanEnumInterfaces failed with error: "; + return wifi_information_; + } + + for (int i = 0; i < (int)p_intf_list->dwNumberOfItems; i++) { + p_intf_info = (WLAN_INTERFACE_INFO*)&p_intf_list->InterfaceInfo[i]; + if (p_intf_info->isState == wlan_interface_state_connected) { + NEARBY_LOGS(INFO) << "Found connected WIFI interface No: " << i; + wifi_information_.is_connected = true; + + DWORD channel_size; + result = WlanQueryInterface(client_handle, &p_intf_info->InterfaceGuid, + wlan_intf_opcode_channel_number, NULL, + &channel_size, (PVOID*)&channel, + &op_code_value_type); + if (result != ERROR_SUCCESS) { + NEARBY_LOGS(INFO) << "WlanQueryInterface error = " << result; + } else { + wifi_information_.ap_frequency = + WifiUtils::ConvertChannelToFrequencyMhz( + *channel, api::WifiBandType::kUnknown); + NEARBY_LOGS(INFO) << "Frequency: " << *channel << "; ap_frequency: " + << wifi_information_.ap_frequency; + WlanFreeMemory(channel); + channel = NULL; + } + + result = WlanQueryInterface(client_handle, &p_intf_info->InterfaceGuid, + wlan_intf_opcode_current_connection, NULL, + &connect_info_size, (PVOID*)&p_connect_info, + &op_code_value_type); + if (result != ERROR_SUCCESS) { + NEARBY_LOGS(INFO) << "WlanQueryInterface error = " << result; + WlanFreeMemory(p_intf_list); + p_intf_list = NULL; + return wifi_information_; + } + + wifi_information_.ssid.resize( + p_connect_info->wlanAssociationAttributes.dot11Ssid.uSSIDLength); + std::memcpy( + wifi_information_.ssid.data(), + reinterpret_cast( + p_connect_info->wlanAssociationAttributes.dot11Ssid.ucSSID), + wifi_information_.ssid.size()); + NEARBY_LOGS(INFO) << "wifi ssid is: " << wifi_information_.ssid + << "; length is:" << wifi_information_.ssid.length(); + + char str_tmp[kMacAddrLen]; + strncpy(str_tmp, + reinterpret_cast( + p_connect_info->wlanAssociationAttributes.dot11Bssid), + kMacAddrLen); + wifi_information_.bssid = absl::StrFormat( + "%2llx:%2llx:%2llx:%2llx:%2llx:%2llx", str_tmp[0], str_tmp[1], + str_tmp[2], str_tmp[3], str_tmp[4], str_tmp[5]); + NEARBY_LOGS(INFO) << "wifi bssid is: " << wifi_information_.bssid; + } + } + + WlanFreeMemory(p_connect_info); + p_connect_info = NULL; + WlanFreeMemory(p_intf_list); + p_intf_list = NULL; + + wifi_information_.ip_address_dot_decimal = GetIpAddress(); + wifi_information_.ip_address_4_bytes = ipaddr_dotdecimal_to_4bytes_string( + wifi_information_.ip_address_dot_decimal); + + return wifi_information_; +} + +std::string WifiMedium::GetIpAddress() { + auto host_names = NetworkInformation::GetHostNames(); + for (auto host_name : host_names) { + if (host_name.IPInformation() != nullptr && + host_name.IPInformation().NetworkAdapter() != nullptr && + host_name.Type() == HostNameType::Ipv4) { + std::string ipv4_s = winrt::to_string(host_name.ToString()); + NEARBY_LOGS(INFO) << "Found IP: " << ipv4_s; + + auto profile = host_name.IPInformation() + .NetworkAdapter() + .GetConnectedProfileAsync() + .get(); + if (profile.IsWlanConnectionProfile()) { + if ( wifi_information_.ssid == winrt::to_string( + profile.WlanConnectionProfileDetails().GetConnectedSsid())) { + NEARBY_LOGS(INFO) + << "SSID of this IP matches with this WIFI interface's SSID:" + << wifi_information_.ssid << ", return this IP"; + return ipv4_s; + } + } + } + } + return {}; +} + +} // namespace windows +} // namespace nearby +} // namespace location diff --git a/internal/platform/wifi.h b/internal/platform/wifi.h new file mode 100644 index 00000000..d1d0785c --- /dev/null +++ b/internal/platform/wifi.h @@ -0,0 +1,76 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "internal/platform/implementation/platform.h" +#include "internal/platform/implementation/wifi.h" + + +#ifndef PLATFORM_PUBLIC_WIFI_H_ +#define PLATFORM_PUBLIC_WIFI_H_ + + + +namespace location { +namespace nearby { + +class WifiMedium { + public: + using Platform = api::ImplementationPlatform; + + WifiMedium() : impl_(Platform::CreateWifiMedium()) {} + ~WifiMedium() = default; + + api::WifiCapability& GetCapability() { + CHECK(impl_); + return impl_->GetCapability(); + } + + api::WifiInformation& GetInformation() { + CHECK(impl_); + return impl_->GetInformation(); + } + + bool IsInterfaceValid() const { + CHECK(impl_); + return impl_->IsInterfaceValid(); + } + + bool VerifyInternetConnectivity() { + CHECK(impl_); + return impl_->VerifyInternetConnectivity(); + } + + std::string GetIpAddress() const { + CHECK(impl_); + return impl_->GetIpAddress(); + } + + bool IsValid() const { return impl_ != nullptr; } + + api::WifiMedium& GetImpl() { + CHECK(impl_); + return *impl_; + } + + private: + // Mutex mutex_; + std::unique_ptr impl_; +}; + +} // namespace nearby +} // namespace location + +#endif // PLATFORM_PUBLIC_WIFI_H_ diff --git a/internal/platform/wifi_test.cc b/internal/platform/wifi_test.cc new file mode 100644 index 00000000..2ed11076 --- /dev/null +++ b/internal/platform/wifi_test.cc @@ -0,0 +1,46 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/platform/wifi.h" + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace location { +namespace nearby { +namespace { + +TEST(WifiMediumTest, ConstructorDestructorWorks) { + WifiMedium wifi_a; + WifiMedium wifi_b; + + if (wifi_a.IsValid() && wifi_b.IsValid()) { + // Make sure we can create 2 distinct mediums. + EXPECT_NE(&wifi_a.GetImpl(), &wifi_a.GetImpl()); + } + // TODO(b/233324423): Add test coverage for wifi.h +} + +TEST(WifiMediumTest, CanGetCapability) { + // TODO(b/233324423): Add test coverage for wifi.h +} + +TEST(WifiMediumTest, CanInformation) { + // TODO(b/233324423): Add test coverage for wifi.h +} + +} // namespace +} // namespace nearby +} // namespace location diff --git a/internal/platform/wifi_utils.cc b/internal/platform/wifi_utils.cc new file mode 100644 index 00000000..2f99312a --- /dev/null +++ b/internal/platform/wifi_utils.cc @@ -0,0 +1,96 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/platform/wifi_utils.h" + +namespace location { +namespace nearby { + +// Utility function to convert channel number to frequency in MHz +// @param channel to convert +// @return center frequency in Mhz of the channel, return "kUnspecified" if no +// match +// Add band support later +int WifiUtils::ConvertChannelToFrequencyMhz(int channel, WifiBandType band) { + if (band == WifiBandType::kUnknown || band == WifiBandType::kBand24Ghz || + band == WifiBandType::kBand5Ghz) { + if (channel == 14) { + return 2484; + } else if (channel >= kBand24GhzFirstChNum && + channel <= kBand24GhzLastChNum) { + return ((channel - kBand24GhzFirstChNum) * 5) + kBand24GhzStartFreqMhz; + } else if (channel >= kBand5GhzFirstChNum && + channel <= kBand5GhzLastChNum) { + return ((channel - kBand5GhzFirstChNum) * 5) + kBand5GhzStartFreqMhz; + } else { + return kUnspecified; + } + } + + if (band == WifiBandType::kBand6Ghz) { + if (channel >= kBand6GhzFirstChNum && + channel <= kBand6GhzLastChNum) { + if (channel == 2) { + return kBand6GhzOpClass136Ch2FreqMhz; + } + return ((channel - kBand6GhzFirstChNum) * 5) + + kBand6GhzStartFreqMhz; + } else { + return kUnspecified; + } + } + + if (band == WifiBandType::kBand60Ghz) { + if (channel >= kBand60GhzFirstChNum && + channel <= kBand60GhzLastChNum) { + return ((channel - kBand60GhzFirstChNum) * 2160) + + kBand60GhzStartFreqMhz; + } else { + return kUnspecified; + } + } + + return kUnspecified; +} + +// Utility function to convert frequency in MHz to channel number +// @param freqMhz frequency in MHz +// @return channel number associated with given frequency, return "kUnspecified" +// if no match +int WifiUtils::ConvertFrequencyMhzToChannel(int freq_mhz) { + // Special case + if (freq_mhz == kBand24GhzEndFreqMhz) { + return 14; + } else if (freq_mhz >= kBand24GhzStartFreqMhz && + freq_mhz <= kBand24GhzEndFreqMhz) { + return (freq_mhz - kBand24GhzStartFreqMhz) / 5 + kBand24GhzFirstChNum; + } else if (freq_mhz >= kBand5GhzStartFreqMhz && + freq_mhz <= kBand5GhzEndFreqMhz) { + return (freq_mhz - kBand5GhzStartFreqMhz) / 5 + kBand5GhzFirstChNum; + } else if (freq_mhz >= kBand6GhzStartFreqMhz && + freq_mhz <= kBand6GhzEndFreqMhz) { + if (freq_mhz == kBand6GhzOpClass136Ch2FreqMhz) { + return 2; + } + return (freq_mhz - kBand6GhzStartFreqMhz) / 5 + kBand6GhzFirstChNum; + } else if (freq_mhz >= kBand60GhzStartFreqMhz && + freq_mhz <= kBand60GhzEndFreqMhz) { + return (freq_mhz - kBand60GhzStartFreqMhz) / 2160 + kBand60GhzFirstChNum; + } + + return kUnspecified; +} + +} // namespace nearby +} // namespace location diff --git a/internal/platform/wifi_utils.h b/internal/platform/wifi_utils.h new file mode 100644 index 00000000..a7b90454 --- /dev/null +++ b/internal/platform/wifi_utils.h @@ -0,0 +1,55 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PLATFORM_BASE_WIFI_UTILS_H_ +#define PLATFORM_BASE_WIFI_UTILS_H_ + +#include "internal/platform/implementation/wifi.h" + +namespace location { +namespace nearby { + +using location::nearby::api::WifiBandType; + +class WifiUtils { + public: + static constexpr int kUnspecified = -1; + static constexpr int kBand24GhzFirstChNum = 1; + static constexpr int kBand24GhzLastChNum = 14; + static constexpr int kBand24GhzStartFreqMhz = 2412; + static constexpr int kBand24GhzEndFreqMhz = 2484; + static constexpr int kBand5GhzFirstChNum = 32; + static constexpr int kBand5GhzLastChNum = 177; + static constexpr int kBand5GhzStartFreqMhz = 5160; + static constexpr int kBand5GhzEndFreqMhz = 5885; + static constexpr int kBand6GhzFirstChNum = 1; + static constexpr int kBand6GhzLastChNum = 233; + static constexpr int kBand6GhzStartFreqMhz = 5955; + static constexpr int kBand6GhzEndFreqMhz = 7115; + static constexpr int kBand6GhzPscStartMhz = 5975; + static constexpr int kBand6GhzPscStepSizeMhz = 80; + static constexpr int kBand6GhzOpClass136Ch2FreqMhz = 5935; + static constexpr int kBand60GhzFirstChNum = 1; + static constexpr int kBand60GhzLastChNum = 6; + static constexpr int kBand60GhzStartFreqMhz = 58320; + static constexpr int kBand60GhzEndFreqMhz = 70200; + + static int ConvertChannelToFrequencyMhz(int channel, WifiBandType band_type); + static int ConvertFrequencyMhzToChannel(int freq_mhz); +}; + +} // namespace nearby +} // namespace location + +#endif // PLATFORM_BASE_WIFI_UTILS_H_ diff --git a/internal/platform/wifi_utils_test.cc b/internal/platform/wifi_utils_test.cc new file mode 100644 index 00000000..04cc392a --- /dev/null +++ b/internal/platform/wifi_utils_test.cc @@ -0,0 +1,91 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/platform/wifi_utils.h" + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace location { +namespace nearby { +namespace { + +constexpr int kChan6Num_2G = 9; +constexpr int kChan6NumFreq_2G = 2452; + +constexpr int kChan48Num_5G = 48; +constexpr int kChan48NumFreq_5G = 5240; + +constexpr int kChan69Num_6G = 69; +constexpr int kChan69NumFreq_6G = 6295; + +constexpr int kChan4Num_60G = 4; +constexpr int kChan4NumFreq_60G = 64800; + +constexpr int kChan20Num_2G_NotExist = 20; +constexpr int kChan180Num_5G_NotExist = 180; +constexpr int kChan0Num_6G_NotExist = 0; +constexpr int kChan30Num_60G_NotExist = 30; + +constexpr int kFreqNotExist = 1002; + + + +TEST(WifiUtilsTest, ConvertChannelToFrequency) { + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan6Num_2G, + WifiBandType::kUnknown), + kChan6NumFreq_2G); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan6Num_2G, + WifiBandType::kBand24Ghz), + kChan6NumFreq_2G); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan48Num_5G, + WifiBandType::kBand5Ghz), + kChan48NumFreq_5G); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan69Num_6G, + WifiBandType::kBand6Ghz), + kChan69NumFreq_6G); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan4Num_60G, + WifiBandType::kBand60Ghz), + kChan4NumFreq_60G); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan20Num_2G_NotExist, + WifiBandType::kBand24Ghz), + WifiUtils::kUnspecified); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan180Num_5G_NotExist, + WifiBandType::kBand5Ghz), + WifiUtils::kUnspecified); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan0Num_6G_NotExist, + WifiBandType::kBand6Ghz), + WifiUtils::kUnspecified); + EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan30Num_60G_NotExist, + WifiBandType::kBand60Ghz), + WifiUtils::kUnspecified);} + +TEST(WifiUtilsTest, ConvertFrequencyToChannel) { + EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan6NumFreq_2G), + kChan6Num_2G); + EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan48NumFreq_5G), + kChan48Num_5G); + EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan69NumFreq_6G), + kChan69Num_6G); + EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan4NumFreq_60G), + kChan4Num_60G); + EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kFreqNotExist), + WifiUtils::kUnspecified); +} + +} // namespace +} // namespace nearby +} // namespace location +