Remove need to request precise location permission to get original wifi network profile name.

PiperOrigin-RevId: 816807149
This commit is contained in:
Francis Tsui
2025-10-08 12:09:58 -07:00
committed by Copybara-Service
parent 6383b6e7d1
commit 2143967802
3 changed files with 118 additions and 115 deletions
@@ -153,7 +153,7 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
std::unique_ptr<api::WifiHotspotServerSocket>
WifiHotspotMedium::ListenForService(int port) {
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
LOG(INFO) << __func__
<< " :Start to listen connection from WiFi Hotspot client.";
@@ -172,7 +172,7 @@ WifiHotspotMedium::ListenForService(int port) {
// Setup close notifier after listen started.
server_socket->SetCloseNotifier([this]() {
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
LOG(INFO) << "Server socket was closed.";
medium_status_ &= (~kMediumStatusAccepting);
server_socket_ptr_ = nullptr;
@@ -189,7 +189,7 @@ WifiHotspotMedium::ListenForService(int port) {
bool WifiHotspotMedium::StartWifiHotspot(
HotspotCredentials* hotspot_credentials) {
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
VLOG(1) << __func__ << ": Start to create WiFi Hotspot.";
if (IsBeaconing()) {
@@ -268,7 +268,7 @@ bool WifiHotspotMedium::StartWifiHotspot(
bool WifiHotspotMedium::StopWifiHotspot() {
// Need to use Win32 API to deregister the Dnssd instance
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
if (!IsBeaconing()) {
LOG(WARNING) << "Cannot stop SoftAP because no SoftAP is started.";
@@ -329,7 +329,7 @@ fire_and_forget WifiHotspotMedium::OnStatusChanged(
// Publisher is stopped. Need to clean up the publisher.
{
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
if (publisher_ != nullptr) {
LOG(ERROR) << "Windows WiFi Hotspot cleanup.";
listener_.ConnectionRequested(connection_requested_token_);
@@ -378,7 +378,7 @@ fire_and_forget WifiHotspotMedium::OnConnectionRequested(
bool WifiHotspotMedium::ConnectWifiHotspot(
HotspotCredentials* hotspot_credentials) {
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
try {
if (IsConnected()) {
@@ -386,8 +386,6 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
wifi_hotspot_native_.DisconnectWifiNetwork();
}
wifi_hotspot_native_.BackupWifiProfile();
// Initialize Intel PIE scan if it is installed.
bool intel_wifi_started = false;
if (NearbyFlags::GetInstance().GetBoolFlag(
@@ -489,7 +487,7 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
}
bool WifiHotspotMedium::DisconnectWifiHotspot() {
absl::MutexLock lock(&mutex_);
absl::MutexLock lock(mutex_);
if (!IsConnected()) {
LOG(WARNING) << "Cannot disconnect SoftAP because it is not connected.";
@@ -26,7 +26,9 @@
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "absl/base/nullability.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
@@ -100,36 +102,36 @@ WifiHotspotNative::~WifiHotspotNative() {
bool WifiHotspotNative::ConnectToWifiNetwork(
HotspotCredentials* hotspot_credentials) {
absl::MutexLock lock(&mutex_);
GUID interface_guid = GetInterfaceGuid();
if (interface_guid == GUID_NULL) {
LOG(ERROR) << "No available WLAN Interface to use.";
return false;
}
if (!SetWlanProfile(interface_guid, hotspot_credentials)) {
LOG(ERROR) << "Failed to set WLAN profile.";
return false;
{
absl::MutexLock lock(mutex_);
if (!SetWlanProfile(interface_guid, hotspot_credentials)) {
LOG(ERROR) << "Failed to set WLAN profile.";
return false;
}
backup_profile_name_.clear();
if (!ConnectToWifiNetworkInternal(interface_guid,
string_utils::StringToWideString(
std::string(kHotspotProfileName)))) {
RemoveCreatedWlanProfile(interface_guid);
return false;
}
}
if (!ConnectToWifiNetworkInternal(
interface_guid,
string_utils::StringToWideString(std::string(kHotspotProfileName)))) {
RemoveCreatedWlanProfile(interface_guid);
return false;
}
LOG(ERROR) << "Connect to Wifi network successfully.";
return true;
}
bool WifiHotspotNative::DisconnectWifiNetwork() {
absl::MutexLock lock(&mutex_);
GUID interface_guid = GetInterfaceGuid();
if (interface_guid == GUID_NULL) {
LOG(ERROR) << "No available WLAN Interface to use.";
return false;
}
absl::MutexLock lock(mutex_);
DWORD result = WlanDisconnect(
/*hClientHandle=*/wifi_, /*pInterfaceGuid=*/&interface_guid,
/*pReserved=*/nullptr);
@@ -142,15 +144,16 @@ bool WifiHotspotNative::DisconnectWifiNetwork() {
}
bool WifiHotspotNative::Scan(absl::string_view ssid) {
absl::MutexLock lock(&mutex_);
GUID interface_guid = GetInterfaceGuid();
if (interface_guid == GUID_NULL) {
LOG(ERROR) << "No available WLAN Interface to use.";
return false;
}
if (!RegisterWlanNotificationCallback()) {
WlanNotificationContext context = {
.wifi_hotspot_native = *this,
};
absl::MutexLock lock(mutex_);
if (!RegisterWlanNotificationCallback(&context)) {
LOG(ERROR) << "Failed to register WLAN notification callback.";
return false;
}
@@ -187,16 +190,10 @@ bool WifiHotspotNative::Scan(absl::string_view ssid) {
return true;
}
void WifiHotspotNative::TriggerConnected(const std::wstring& profile_name) {
void WifiHotspotNative::TriggerConnected() {
if (connect_latch_ == nullptr) {
return;
}
if (profile_name != connecting_profile_name_) {
return;
}
LOG(INFO) << "Connected to expected WLAN network";
connect_latch_->CountDown();
}
@@ -243,24 +240,59 @@ void WifiHotspotNative::WlanNotificationCallback(
VLOG(1) << "WlanNotificationCallback is called with notification code "
<< wlan_notification_data->NotificationCode;
if (wlan_notification_data->NotificationCode ==
wlan_notification_acm_connection_complete) {
// Make sure the connected WLAN profile is the one we set.
PWLAN_CONNECTION_NOTIFICATION_DATA data =
static_cast<PWLAN_CONNECTION_NOTIFICATION_DATA>(
wlan_notification_data->pData);
WifiHotspotNative* wifi_hotspot_native =
static_cast<WifiHotspotNative*>(context);
std::wstring profile_name = std::wstring(data->strProfileName);
LOG(INFO) << "Connected to Wifi hotspot "
<< string_utils::WideStringToString(profile_name);
wifi_hotspot_native->TriggerConnected(profile_name);
} else if (wlan_notification_data->NotificationCode ==
wlan_notification_acm_scan_list_refresh) {
LOG(INFO) << "Scan list refreshed.";
WifiHotspotNative* wifi_hotspot_native =
static_cast<WifiHotspotNative*>(context);
wifi_hotspot_native->TriggerNetworkRefreshed();
WlanNotificationContext* wlan_context =
static_cast<WlanNotificationContext*>(context);
switch (wlan_notification_data->NotificationCode) {
case wlan_notification_acm_connection_start: {
PWLAN_CONNECTION_NOTIFICATION_DATA data =
static_cast<PWLAN_CONNECTION_NOTIFICATION_DATA>(
wlan_notification_data->pData);
wlan_context->got_connecting_event = true;
LOG(INFO) << "Start connecting to profile "
<< string_utils::WideStringToString(
std::wstring(data->strProfileName));
break;
}
case wlan_notification_acm_connection_complete: {
// Make sure the connected WLAN profile is the one we set.
PWLAN_CONNECTION_NOTIFICATION_DATA data =
static_cast<PWLAN_CONNECTION_NOTIFICATION_DATA>(
wlan_notification_data->pData);
std::string profile_name =
string_utils::WideStringToString(std::wstring(data->strProfileName));
LOG(INFO) << "Completed connection to profile: " << profile_name
<< " code: " << data->wlanReasonCode;
if (wlan_context->connecting_profile_name != data->strProfileName) {
break;
}
wlan_context->connection_code = data->wlanReasonCode;
wlan_context->wifi_hotspot_native.TriggerConnected();
break;
}
case wlan_notification_acm_scan_list_refresh: {
LOG(INFO) << "Scan list refreshed.";
wlan_context->wifi_hotspot_native.TriggerNetworkRefreshed();
break;
}
case wlan_notification_acm_disconnecting: {
// We use these events to get the profile name of the original network
// the client is connected to so that we can restore it later.
PWLAN_CONNECTION_NOTIFICATION_DATA data =
static_cast<WLAN_CONNECTION_NOTIFICATION_DATA*>(
wlan_notification_data->pData);
// Ignore if we already started connecting to new network, the disconnect
// event will not be the one we want.
if (!wlan_context->got_connecting_event) {
wlan_context->original_profile_name =
std::wstring(data->strProfileName);
LOG(INFO) << "Disconnecting from previous profile: "
<< wlan_context->original_profile_name;
}
break;
}
default: {
break;
}
}
}
@@ -303,8 +335,11 @@ bool WifiHotspotNative::ConnectToWifiNetworkInternal(
LOG(ERROR) << "Profile name is empty.";
return false;
}
if (!RegisterWlanNotificationCallback()) {
WlanNotificationContext context = {
.wifi_hotspot_native = *this,
.connecting_profile_name = profile_name,
};
if (!RegisterWlanNotificationCallback(&context)) {
LOG(ERROR) << "Failed to register WLAN notification callback.";
return false;
}
@@ -319,8 +354,6 @@ bool WifiHotspotNative::ConnectToWifiNetworkInternal(
parameters.dot11BssType = dot11_BSS_type_infrastructure;
parameters.dwFlags = 0;
connecting_profile_name_ = profile_name;
DWORD result =
WlanConnect(/*hClientHandle=*/wifi_, /*pInterfaceGuid=*/&interface_guid,
/*pConnectionParameters=*/&parameters, /*pReserved=*/nullptr);
@@ -339,17 +372,24 @@ bool WifiHotspotNative::ConnectToWifiNetworkInternal(
LOG(ERROR) << "Connect to Wifi hotspot timed out.";
return false;
}
if (context.connection_code != WLAN_REASON_CODE_SUCCESS) {
LOG(ERROR) << "Failed to connect to Wifi hotspot, code: "
<< context.connection_code;
return false;
}
connect_latch_ = nullptr;
backup_profile_name_ = std::move(context.original_profile_name);
return true;
}
bool WifiHotspotNative::RegisterWlanNotificationCallback() {
bool WifiHotspotNative::RegisterWlanNotificationCallback(
WlanNotificationContext* absl_nonnull context) {
DWORD result = WlanRegisterNotification(
/*hClientHandle=*/wifi_, /*dwNotifSource=*/WLAN_NOTIFICATION_SOURCE_ACM,
/*bIgnoreDuplicate=*/TRUE,
/*funcCallback=*/WifiHotspotNative::WlanNotificationCallback,
/*pCallbackContext=*/this, /*pReserved=*/nullptr,
/*pCallbackContext=*/context, /*pReserved=*/nullptr,
/*pdwPrevNotifSource=*/nullptr);
if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Failed to register WLAN notification with error: " << result;
@@ -429,61 +469,13 @@ bool WifiHotspotNative::RemoveWlanProfile(GUID interface_guid,
return true;
}
std::optional<std::wstring> WifiHotspotNative::GetConnectedProfileNameInternal()
const {
PWLAN_INTERFACE_INFO_LIST interfaces = nullptr;
DWORD result =
WlanEnumInterfaces(/*hClientHandle=*/wifi_, /*pReserved=*/nullptr,
/*ppInterfaceList=*/&interfaces);
if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Failed to enum WLAN interfaces with error: " << result;
return std::nullopt;
}
for (DWORD i = 0; i < interfaces->dwNumberOfItems; i++) {
WLAN_CONNECTION_ATTRIBUTES* connect_info = nullptr;
DWORD connect_info_size = sizeof(WLAN_CONNECTION_ATTRIBUTES);
result = WlanQueryInterface(
/*hClientHandle=*/wifi_,
/*pInterfaceGuid=*/&interfaces->InterfaceInfo[i].InterfaceGuid,
/*OpCode=*/wlan_intf_opcode_current_connection, /*pReserved=*/nullptr,
/*pdwDataSize=*/&connect_info_size,
/*ppData=*/(PVOID*)&connect_info, /*pWlanOpcodeValueType=*/nullptr);
if (result == ERROR_SUCCESS && connect_info != nullptr) {
if (connect_info->isState == wlan_interface_state_connected) {
std::wstring profile_name = std::wstring(connect_info->strProfileName);
WlanFreeMemory(connect_info);
if (interfaces != nullptr) {
WlanFreeMemory(interfaces);
}
return profile_name;
}
WlanFreeMemory(connect_info);
}
}
WlanFreeMemory(interfaces);
return std::nullopt;
}
bool WifiHotspotNative::BackupWifiProfile() {
absl::MutexLock lock(&mutex_);
std::optional<std::wstring> profile_name = GetConnectedProfileNameInternal();
if (profile_name.has_value()) {
backup_profile_name_ = *profile_name;
return true;
}
backup_profile_name_.clear();
return false;
}
bool WifiHotspotNative::RestoreWifiProfile() {
absl::MutexLock lock(&mutex_);
GUID interface_guid = GetInterfaceGuid();
if (interface_guid == GUID_NULL) {
LOG(ERROR) << "No available WLAN Interface to use.";
return false;
}
absl::MutexLock lock(mutex_);
RemoveCreatedWlanProfile(interface_guid);
if (backup_profile_name_.empty()) {
LOG(ERROR) << "No backup WLAN profile to restore.";
@@ -26,6 +26,7 @@
#include <optional>
#include <string>
#include "absl/base/nullability.h"
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
@@ -43,15 +44,25 @@ class WifiHotspotNative {
ABSL_LOCKS_EXCLUDED(mutex_);
bool DisconnectWifiNetwork() ABSL_LOCKS_EXCLUDED(mutex_);
bool BackupWifiProfile() ABSL_LOCKS_EXCLUDED(mutex_);
bool RestoreWifiProfile() ABSL_LOCKS_EXCLUDED(mutex_);
bool Scan(absl::string_view ssid) ABSL_LOCKS_EXCLUDED(mutex_);
void TriggerConnected(const std::wstring& profile_name);
void TriggerNetworkRefreshed();
private:
// Context for WLAN notification callback.
struct WlanNotificationContext {
WifiHotspotNative& wifi_hotspot_native;
// This is reset to false when we start connecting to a new network, and set
// to true when we receive the connecting event.
bool got_connecting_event = false;
// Original profile name is captured when a disconnecting event is received
// before a connecting event.
std::wstring original_profile_name;
// The profile name of the network we are trying to connect to.
std::wstring connecting_profile_name;
WLAN_REASON_CODE connection_code = WLAN_REASON_CODE_UNKNOWN;
};
static void WlanNotificationCallback(
PWLAN_NOTIFICATION_DATA wlan_notification_data, PVOID context);
std::wstring BuildWlanProfile(absl::string_view ssid,
@@ -60,7 +71,9 @@ class WifiHotspotNative {
bool ConnectToWifiNetworkInternal(GUID interface_guid,
const std::wstring& profile_name)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool RegisterWlanNotificationCallback();
bool RegisterWlanNotificationCallback(
WlanNotificationContext* absl_nonnull context)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool UnregisterWlanNotificationCallback();
bool SetWlanProfile(GUID interface_guid,
HotspotCredentials* hotspot_credentials)
@@ -69,16 +82,16 @@ class WifiHotspotNative {
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool RemoveWlanProfile(GUID interface_guid, const std::wstring& profile_name)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
std::optional<std::wstring> GetConnectedProfileNameInternal() const;
void TriggerConnected();
void TriggerNetworkRefreshed();
mutable absl::Mutex mutex_;
HANDLE wifi_ = nullptr;
std::wstring connecting_profile_name_;
std::string scanning_ssid_;
std::unique_ptr<CountDownLatch> connect_latch_;
std::unique_ptr<CountDownLatch> scan_latch_;
std::wstring backup_profile_name_ ABSL_GUARDED_BY(mutex_);
std::wstring backup_profile_name_;
};
} // namespace windows