Handle system standby

PiperOrigin-RevId: 949324299
This commit is contained in:
Francis Tsui
2026-07-16 20:12:13 -07:00
committed by Copybara-Service
parent 953d9ea26c
commit 4301bc4fce
8 changed files with 215 additions and 6 deletions
@@ -307,6 +307,9 @@ Status P2pClusterPcpHandler::StopAdvertisingImpl(ClientProxy* client) {
<< bluetooth_classic_advertiser_client_id_;
}
wifi_lan_medium_.StopAdvertising(client->GetAdvertisingServiceId());
wifi_lan_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId());
bluetooth_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId());
ble_medium_.StopAdvertising(client->GetAdvertisingServiceId());
ble_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId());
@@ -316,9 +319,6 @@ Status P2pClusterPcpHandler::StopAdvertisingImpl(ClientProxy* client) {
client->GetAdvertisingServiceId());
}
wifi_lan_medium_.StopAdvertising(client->GetAdvertisingServiceId());
wifi_lan_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId());
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_connections_feature::kEnableAwdl)) {
awdl_medium_.StopAdvertising(client->GetAdvertisingServiceId());
@@ -16,6 +16,7 @@
#define PLATFORM_API_DEVICE_INFO_H_
#include <cstddef>
#include <cstdint>
#include <functional>
#include <optional>
#include <string>
@@ -39,6 +40,7 @@ class DeviceInfo {
kWindows,
kMacOS
};
enum class SuspendResumeEvent { kSuspend, kResume };
virtual ~DeviceInfo() = default;
@@ -69,6 +71,14 @@ class DeviceInfo {
// Control device sleep
virtual bool PreventSleep() = 0;
virtual bool AllowSleep() = 0;
// Monitor suspend/resume events.
// Returns a listener id that can be used to unregister the listener.
virtual int64_t RegisterSuspendResumeListener(
std::function<void(SuspendResumeEvent)> callback) {
return 0;
}
virtual void UnregisterSuspendResumeListener(int64_t listener_id) {}
};
template <typename Sink>
@@ -72,7 +72,13 @@ cc_library(
"timer.h",
"utils.h",
],
defines = ["_SILENCE_CLANG_COROUTINE_MESSAGE"],
defines = [
"_SILENCE_CLANG_COROUTINE_MESSAGE",
"_WIN32_WINNT=_WIN32_WINNT_WIN10",
],
linkopts = [
"powrprof.lib",
],
tags = ["windows"],
visibility = ["//visibility:private"],
deps = [
@@ -14,13 +14,19 @@
#include "internal/platform/implementation/windows/device_info.h"
// clang-format off
#include <shlobj_core.h>
#include <windows.h>
#include <wtsapi32.h>
#include <powrprof.h>
#include <powerbase.h>
// clang-format on
#include <cstdint>
#include <functional>
#include <optional>
#include <string>
#include <utility>
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
@@ -30,10 +36,19 @@
#include "internal/platform/implementation/windows/device_paths.h"
#include "internal/platform/implementation/windows/string_utils.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/logging.h"
namespace nearby::windows {
namespace {
using ::nearby::windows::string_utils::WideStringToString;
} // namespace
DeviceInfo::~DeviceInfo() {
if (suspend_resume_notification_handle_ != nullptr) {
PowerUnregisterSuspendResumeNotification(
suspend_resume_notification_handle_);
}
}
std::optional<std::string> DeviceInfo::GetOsDeviceName() const {
std::optional<std::wstring> device_name = GetDnsHostName();
@@ -113,4 +128,61 @@ bool DeviceInfo::AllowSleep() {
return session_manager_.AllowSleep();
}
ULONG DeviceInfo::PowerSuspendResumeCallback(PVOID context, ULONG type,
PVOID setting) {
api::DeviceInfo::SuspendResumeEvent event;
switch (type) {
case PBT_APMSUSPEND:
event = api::DeviceInfo::SuspendResumeEvent::kSuspend;
break;
case PBT_APMRESUMESUSPEND:
event = api::DeviceInfo::SuspendResumeEvent::kResume;
break;
default:
return 0;
}
DeviceInfo* device_info = static_cast<DeviceInfo*>(context);
device_info->OnSuspendResumeEvent(event);
return 0;
}
int64_t DeviceInfo::RegisterSuspendResumeListener(
std::function<void(api::DeviceInfo::SuspendResumeEvent)> callback) {
absl::MutexLock lock(suspend_resume_mutex_);
int64_t listener_id = ++next_suspend_resume_listener_id_;
suspend_resume_listeners_.emplace(listener_id, std::move(callback));
if (suspend_resume_listeners_.size() == 1) {
DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS subscribe_params;
subscribe_params.Callback = PowerSuspendResumeCallback;
subscribe_params.Context = this;
PowerRegisterSuspendResumeNotification(
DEVICE_NOTIFY_CALLBACK, &subscribe_params,
&suspend_resume_notification_handle_);
}
return listener_id;
}
void DeviceInfo::UnregisterSuspendResumeListener(int64_t listener_id) {
absl::MutexLock lock(suspend_resume_mutex_);
suspend_resume_listeners_.erase(listener_id);
if (suspend_resume_listeners_.empty()) {
if (suspend_resume_notification_handle_ != nullptr) {
PowerUnregisterSuspendResumeNotification(
suspend_resume_notification_handle_);
}
suspend_resume_notification_handle_ = nullptr;
}
}
void DeviceInfo::OnSuspendResumeEvent(
api::DeviceInfo::SuspendResumeEvent event) {
LOG(INFO) << "OnSuspendResumeEvent: "
<< (event == DeviceInfo::SuspendResumeEvent::kSuspend ? "kSuspend"
: "kResume");
absl::MutexLock lock(suspend_resume_mutex_);
for (auto& it : suspend_resume_listeners_) {
it.second(event);
}
}
} // namespace nearby::windows
@@ -15,11 +15,19 @@
#ifndef PLATFORM_IMPL_WINDOWS_DEVICE_INFO_H_
#define PLATFORM_IMPL_WINDOWS_DEVICE_INFO_H_
// clang-format off
#include <windows.h>
#include <powerbase.h>
// clang-format on
#include <cstdint>
#include <functional>
#include <optional>
#include <string>
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/base/file_path.h"
@@ -31,7 +39,7 @@ namespace windows {
class DeviceInfo : public api::DeviceInfo {
public:
~DeviceInfo() override = default;
~DeviceInfo() override;
std::optional<std::string> GetOsDeviceName() const override;
api::DeviceInfo::DeviceType GetDeviceType() const override;
@@ -51,9 +59,26 @@ class DeviceInfo : public api::DeviceInfo {
bool PreventSleep() override;
bool AllowSleep() override;
int64_t RegisterSuspendResumeListener(
std::function<void(api::DeviceInfo::SuspendResumeEvent)> callback)
override;
void UnregisterSuspendResumeListener(int64_t listener_id) override;
private:
static ULONG PowerSuspendResumeCallback(PVOID context, ULONG type,
PVOID setting);
void OnSuspendResumeEvent(SuspendResumeEvent event);
mutable absl::Mutex mutex_;
SessionManager session_manager_ ABSL_GUARDED_BY(mutex_);
absl::Mutex suspend_resume_mutex_;
int64_t next_suspend_resume_listener_id_ ABSL_GUARDED_BY(
suspend_resume_mutex_) = 0;
absl::flat_hash_map<
int64_t, absl::AnyInvocable<void(SuspendResumeEvent)>>
suspend_resume_listeners_ ABSL_GUARDED_BY(suspend_resume_mutex_);
HPOWERNOTIFY suspend_resume_notification_handle_
ABSL_GUARDED_BY(suspend_resume_mutex_) = nullptr;
};
} // namespace windows
@@ -61,6 +61,9 @@ constexpr auto kShowAutoUpdateSetting =
// The default time in milliseconds a cached entry can be in LOST state.
constexpr auto kDiscoveryCacheLostExpiryMs =
flags::Flag<int64_t>(kConfigPackage, "45658774", 15000);
// When true, enable suspend resume listener.
constexpr auto kEnableSuspendResumeListener =
flags::Flag<bool>(kConfigPackage, "45815625", false);
// When true, enable wifi hotspot medium for HP Realtek devices.
constexpr auto kEnableWifiHotspotForHpRealtekDevices =
flags::Flag<bool>(kConfigPackage, "45673628", false);
@@ -105,6 +108,7 @@ inline absl::btree_map<int, const flags::Flag<bool>&> GetBoolFlags() {
{45411589, kEnableRetryResumeTransfer},
{45459748, kEnableSendingDesktopEvents},
{45409033, kShowAutoUpdateSetting},
{45815625, kEnableSuspendResumeListener},
{45673628, kEnableWifiHotspotForHpRealtekDevices},
{45683539, kUseAlternateServiceUuidForDiscovery},
{45776229, kEnableBackup},
+83
View File
@@ -44,6 +44,7 @@
#include "absl/strings/escaping.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "internal/base/file_path.h"
@@ -134,6 +135,12 @@ constexpr absl::Duration kProcessShutdownPendingTimerDelay = // NOLINT
absl::Seconds(15);
constexpr absl::Duration kProcessNetworkChangeTimerDelay = absl::Seconds(1);
// Delay invalidating the surface state after a resume event.
// Network activities can cause system to resume for short periods before
// suspending again. This delay allows us to ignore those and only resume
// fully when the system is stable.
constexpr absl::Duration kResumeDelay = absl::Milliseconds(500);
// The maximum number of certificate downloads that can be performed during a
// discovery session.
// Assuming a 2min discovery session and 10s download interval.
@@ -337,6 +344,13 @@ NearbySharingServiceImpl::NearbySharingServiceImpl(
OnLockStateChanged(screen_status ==
nearby::api::DeviceInfo::ScreenStatus::kLocked);
});
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::
kEnableSuspendResumeListener)) {
suspend_resume_listener_id_ =
device_info_.RegisterSuspendResumeListener(absl::bind_front(
&NearbySharingServiceImpl::OnSuspendResumeEvent, this));
}
account_manager_.AddObserver(this);
settings_->AddSettingsObserver(this);
@@ -384,6 +398,8 @@ void NearbySharingServiceImpl::Shutdown(
background_receive_callbacks_map_.clear();
device_info_.UnregisterScreenLockedListener(kScreenStateListenerName);
device_info_.UnregisterSuspendResumeListener(
suspend_resume_listener_id_);
settings_->RemoveSettingsObserver(this);
@@ -1415,6 +1431,42 @@ void NearbySharingServiceImpl::OnLockStateChanged(bool locked) {
});
}
void NearbySharingServiceImpl::OnSuspendResumeEvent(
nearby::api::DeviceInfo::SuspendResumeEvent event) {
bool suspended =
event == nearby::api::DeviceInfo::SuspendResumeEvent::kSuspend;
{
absl::MutexLock lock(suspend_mutex_);
suspended_ = suspended;
if (!suspended) {
resume_delay_timer_ = std::make_unique<ThreadTimer>(
*service_thread_, "suspend_resume_timer", kResumeDelay, [this]() {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
return;
}
}
LOG(INFO) << "InvalidateSurfaceState due to system resume";
InvalidateSurfaceState();
});
}
}
if (suspended) {
RunOnNearbySharingServiceThread("on_suspend", [this]() {
LOG(INFO) << "InvalidateSurfaceState due to system suspend";
{
absl::MutexLock lock(suspend_mutex_);
if (!suspended_) {
return;
}
resume_delay_timer_.reset();
}
InvalidateSurfaceState();
});
}
}
void NearbySharingServiceImpl::AdapterPresentChanged(
sharing::api::BluetoothAdapter* adapter, bool present) {
RunOnNearbySharingServiceThread("bt_adapter_present_changed", [this, adapter,
@@ -1873,6 +1925,16 @@ void NearbySharingServiceImpl::InvalidateSendSurfaceState() {
}
void NearbySharingServiceImpl::InvalidateScanningState() {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
StopScanning();
VLOG(1) << __func__
<< ": Stopping discovery because the system is suspended.";
return;
}
}
// Stop scanning when screen is off.
if (is_screen_locked_) {
StopScanning();
@@ -1910,6 +1972,17 @@ void NearbySharingServiceImpl::InvalidateScanningState() {
}
void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
StopFastInitiationAdvertising();
VLOG(1) << __func__
<< ": Stopping fast initiation advertising because the "
"system is suspended.";
return;
}
}
// Screen is off. Do no work.
if (is_screen_locked_) {
StopFastInitiationAdvertising();
@@ -1949,6 +2022,16 @@ void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
}
void NearbySharingServiceImpl::InvalidateAdvertisingState() {
{
absl::MutexLock lock(suspend_mutex_);
if (suspended_) {
StopAdvertising();
VLOG(1) << __func__
<< ": Stopping advertising because the system is suspended.";
return;
}
}
bool supports_advertising_on_lock_screen =
NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::
+9
View File
@@ -31,6 +31,7 @@
#include "location/nearby/sharing/lib/rpc/sharing_rpc_client.h"
#include "location/nearby/sharing/lib/sync/sync_manager.h"
#include "absl/base/nullability.h"
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/functional/any_invocable.h"
@@ -219,6 +220,9 @@ class NearbySharingServiceImpl
// Handle the state changes of screen lock.
void OnLockStateChanged(bool locked);
void OnSuspendResumeEvent(
nearby::api::DeviceInfo::SuspendResumeEvent event);
// Handle the state changes of bluetooth adapter.
void AdapterPresentChanged(sharing::api::BluetoothAdapter* adapter,
bool present) override;
@@ -550,6 +554,11 @@ class NearbySharingServiceImpl
proto::DeviceVisibility last_advertised_device_visibility_ =
proto::DeviceVisibility::DEVICE_VISIBILITY_UNSPECIFIED;
bool advertising_on_screen_locked_ = false;
int64_t suspend_resume_listener_id_ = 0;
absl::Mutex suspend_mutex_;
bool suspended_ ABSL_GUARDED_BY(suspend_mutex_) = false;
std::unique_ptr<ThreadTimer> resume_delay_timer_
ABSL_GUARDED_BY(suspend_mutex_);
};
} // namespace nearby::sharing