From c613904a69bc9de1553d0e9b4e60cf731bda0d50 Mon Sep 17 00:00:00 2001 From: Francis Tsui Date: Fri, 4 Oct 2024 15:35:55 -0700 Subject: [PATCH] allow API to request to disable wifi hotspot PiperOrigin-RevId: 682473971 --- connections/connection_options.h | 4 ++ .../implementation/base_pcp_handler.cc | 3 +- sharing/nearby_connections_manager_impl.cc | 16 ++++--- .../nearby_connections_manager_impl_test.cc | 47 +++++++++++++++++++ sharing/nearby_connections_service_impl.cc | 2 + sharing/nearby_connections_types.h | 26 ++++++++-- sharing/nearby_sharing_service_impl.cc | 8 +++- 7 files changed, 94 insertions(+), 12 deletions(-) diff --git a/connections/connection_options.h b/connections/connection_options.h index e2b382a0..6f25604a 100644 --- a/connections/connection_options.h +++ b/connections/connection_options.h @@ -52,6 +52,10 @@ struct ConnectionOptions : public OptionsBase { int keep_alive_interval_millis = 0; int keep_alive_timeout_millis = 0; + // If true, only use WiFi Hotspot for connection when Wifi LAN is not + // connected. + bool non_disruptive_hotspot_mode = false; + std::vector GetMediums() const; ConnectionInfo connection_info; }; diff --git a/connections/implementation/base_pcp_handler.cc b/connections/implementation/base_pcp_handler.cc index 9a785fb3..d90cd8ae 100644 --- a/connections/implementation/base_pcp_handler.cc +++ b/connections/implementation/base_pcp_handler.cc @@ -781,7 +781,8 @@ ConnectionInfo BasePcpHandler::FillConnectionInfo( if (!NearbyFlags::GetInstance().GetBoolFlag( config_package_nearby::nearby_connections_feature:: - kEnableWifiHotspotClient)) { + kEnableWifiHotspotClient) || + connection_options.non_disruptive_hotspot_mode) { // Remove Wi-Fi Hotspot if WiFi LAN is available. StripOutWifiHotspotMedium(connection_info); } diff --git a/sharing/nearby_connections_manager_impl.cc b/sharing/nearby_connections_manager_impl.cc index f3162000..d3cc41f3 100644 --- a/sharing/nearby_connections_manager_impl.cc +++ b/sharing/nearby_connections_manager_impl.cc @@ -127,6 +127,7 @@ std::string MediumSelectionToString(const MediumSelection& mediums) { if (mediums.ble) ss << "ble "; if (mediums.web_rtc) ss << "webrtc "; if (mediums.wifi_lan) ss << "wifilan "; + if (mediums.wifi_hotspot) ss << "wifihotspot "; ss << "}"; return ss.str(); @@ -349,7 +350,8 @@ void NearbyConnectionsManagerImpl::Connect( PowerLevel::kHighPower), /*wifi_lan=*/ ShouldEnableWifiLan(connectivity_manager_), - /*wifi_hotspot=*/transport_type == TransportType::kHighQuality); + /*wifi_hotspot=*/ + IsTransportTypeFlagsSet(transport_type, TransportType::kHighQuality)); NL_VLOG(1) << __func__ << ": " << "data_usage=" << static_cast(data_usage) << ", allowed_mediums=" @@ -396,10 +398,12 @@ void NearbyConnectionsManagerImpl::Connect( nearby_connections_service_->RequestConnection( kServiceId, endpoint_info, endpoint_id, - ConnectionOptions(std::move(allowed_mediums), - std::move(bluetooth_mac_address), - /*keep_alive_interval=*/std::nullopt, - /*keep_alive_timeout=*/std::nullopt), + ConnectionOptions( + std::move(allowed_mediums), std::move(bluetooth_mac_address), + /*keep_alive_interval=*/std::nullopt, + /*keep_alive_timeout=*/std::nullopt, + IsTransportTypeFlagsSet(transport_type, + TransportType::kHighQualityNonDisruptive)), std::move(connection_listener), [this, endpoint_id = std::string(endpoint_id)](ConnectionsStatus status) { MutexLock lock(&mutex_); @@ -410,7 +414,7 @@ void NearbyConnectionsManagerImpl::Connect( }); // Setup transfer manager. - if (transport_type == TransportType::kHighQuality) { + if (IsTransportTypeFlagsSet(transport_type, TransportType::kHighQuality)) { transfer_managers_[endpoint_id] = std::make_unique(context_, endpoint_id); } diff --git a/sharing/nearby_connections_manager_impl_test.cc b/sharing/nearby_connections_manager_impl_test.cc index 3a91b921..f4a92e79 100644 --- a/sharing/nearby_connections_manager_impl_test.cc +++ b/sharing/nearby_connections_manager_impl_test.cc @@ -533,6 +533,50 @@ TEST_F(NearbyConnectionsManagerImplTest, DiscoveryFlow) { kSynchronizationTimeOut)); } +TEST_F(NearbyConnectionsManagerImplTest, DisableWifiHotspot) { + SetConnectionType(ConnectivityManager::ConnectionType::kWifi); + + MediumSelection expected_mediums(/*bluetooth=*/true, + /*ble=*/false, + /*web_rtc=*/should_use_web_rtc_, + /*wifi_lan=*/should_use_wifilan_, + /*wifi_hotspot*/ true); + + // StartDiscovery will succeed. + NearbyConnectionsService::DiscoveryListener discovery_listener_remote; + testing::NiceMock discovery_listener; + StartDiscovery(discovery_listener_remote, DataUsage::WIFI_ONLY_DATA_USAGE, + discovery_listener); + + absl::Notification notification; + const std::vector local_endpoint_info(std::begin(kEndpointInfo), + std::end(kEndpointInfo)); + EXPECT_CALL(*nearby_connections_, RequestConnection) + .WillOnce([&](absl::string_view service_id, + const std::vector& endpoint_info, + absl::string_view endpoint_id, ConnectionOptions options, + NearbyConnectionsService::ConnectionListener listener, + std::function callback) { + EXPECT_EQ(service_id, kServiceId); + EXPECT_EQ(endpoint_info, local_endpoint_info); + EXPECT_EQ(endpoint_id, kRemoteEndpointId); + EXPECT_EQ(options.allowed_mediums.wifi_hotspot, true); + EXPECT_TRUE(options.non_disruptive_hotspot_mode); + std::move(callback)(Status::kSuccess); + notification.Notify(); + }); + + NearbyConnectionsManager::NearbyConnectionCallback connections_callback; + + nearby_connections_manager_->Connect( + local_endpoint_info, kRemoteEndpointId, + /*bluetooth_mac_address=*/std::nullopt, DataUsage::WIFI_ONLY_DATA_USAGE, + TransportType::kHighQualityNonDisruptive, connections_callback); + + EXPECT_TRUE( + notification.WaitForNotificationWithTimeout(kSynchronizationTimeOut)); +} + /******************************************************************************/ // Begin: NearbyConnectionsManagerImplTestConnectionMediums /******************************************************************************/ @@ -609,6 +653,9 @@ TEST_P(NearbyConnectionsManagerImplTestConnectionMediums, expected_mediums.bluetooth); EXPECT_EQ(options.allowed_mediums.web_rtc, expected_mediums.web_rtc); EXPECT_EQ(options.allowed_mediums.wifi_lan, expected_mediums.wifi_lan); + EXPECT_EQ(options.allowed_mediums.wifi_hotspot, + expected_mediums.wifi_hotspot); + EXPECT_FALSE(options.non_disruptive_hotspot_mode); std::move(callback)(Status::kSuccess); notification.Notify(); }); diff --git a/sharing/nearby_connections_service_impl.cc b/sharing/nearby_connections_service_impl.cc index 60fb86a9..a11da2a6 100644 --- a/sharing/nearby_connections_service_impl.cc +++ b/sharing/nearby_connections_service_impl.cc @@ -203,6 +203,8 @@ void NearbyConnectionsServiceImpl::RequestConnection( options.remote_bluetooth_mac_address = NcByteArray(std::string(mac_address.begin(), mac_address.end())); } + options.non_disruptive_hotspot_mode = + connection_options.non_disruptive_hotspot_mode; NcConnectionRequestInfo connection_request_info; connection_request_info.endpoint_info = NcByteArray(std::string(endpoint_info.begin(), endpoint_info.end())); diff --git a/sharing/nearby_connections_types.h b/sharing/nearby_connections_types.h index 1119bd09..5e495e07 100644 --- a/sharing/nearby_connections_types.h +++ b/sharing/nearby_connections_types.h @@ -283,11 +283,13 @@ struct ConnectionOptions { MediumSelection allowed_mediums, std::optional> remote_bluetooth_mac_address, std::optional keep_alive_interval, - std::optional keep_alive_timeout) { + std::optional keep_alive_timeout, + bool non_disruptive_hotspot_mode) { this->allowed_mediums = allowed_mediums; this->remote_bluetooth_mac_address = remote_bluetooth_mac_address; this->keep_alive_interval = keep_alive_interval; this->keep_alive_timeout = keep_alive_timeout; + this->non_disruptive_hotspot_mode = non_disruptive_hotspot_mode; } // Describes which mediums are allowed to be used for connection. Note that @@ -304,6 +306,9 @@ struct ConnectionOptions { // for this length of time. An unspecified or negative value will result in // the Nearby Connections default of 30 seconds being used. std::optional keep_alive_timeout; + // If true, only use WiFi Hotspot for connection when Wifi LAN is not + // connected. + bool non_disruptive_hotspot_mode = false; }; // The status of the payload transfer at the time of this update. @@ -485,8 +490,23 @@ struct Payload { } }; -// Transport type to decide whether to upgrade to a high quality medium. -enum class TransportType { kAny = 0, kNonDisruptive = 1, kHighQuality = 2 }; +// This is a bitmask field that determines the transport type to upgrade to. +enum class TransportType { + kAny = 0, + // Allows use of WiFi Hotspot for connection when Wifi LAN is not connected. + kNonDisruptive = 1, + // Allows use of Wifi Hotspot for connection. + kHighQuality = 2, + // kNonDisruptive | kHighQuality + kHighQualityNonDisruptive = 3, +}; + +// Returns true if all flags in `mask` are enabled in `transport_type`. +inline bool IsTransportTypeFlagsSet(TransportType transport_type, + TransportType mask) { + return (static_cast(transport_type) & + static_cast(mask)) == static_cast(mask); +} } // namespace sharing } // namespace nearby diff --git a/sharing/nearby_sharing_service_impl.cc b/sharing/nearby_sharing_service_impl.cc index 82922b13..c50683f0 100644 --- a/sharing/nearby_sharing_service_impl.cc +++ b/sharing/nearby_sharing_service_impl.cc @@ -3715,12 +3715,16 @@ TransportType NearbySharingServiceImpl::GetTransportType( const AttachmentContainer& container) const { if (container.GetTotalAttachmentsSize() > kAttachmentsSizeThresholdOverHighQualityMedium) { - NL_LOG(INFO) << __func__ << ": Transport type is kHighQuality"; + if (GetDisableWifiHotspotState()) { + LOG(INFO) << "Transport type is kHighQuality|kNonDisruptive"; + return TransportType::kHighQualityNonDisruptive; + } + LOG(INFO) << "Transport type is kHighQuality"; return TransportType::kHighQuality; } if (container.GetFileAttachments().empty()) { - NL_LOG(INFO) << __func__ << ": Transport type is kNonDisruptive"; + LOG(INFO) << "Transport type is kNonDisruptive"; return TransportType::kNonDisruptive; }