Commit 196c0eba authored by Etienne Bergeron's avatar Etienne Bergeron Committed by Chromium LUCI CQ

Avoid dispatching timezone notifications while suspended

This CL is delaying the WM_TIMECHANGE notifications to ensure it's
running while the computer is fully resumed from power suspend.
It is also batching multiple concurrent notifications if they
subsequent notifications occurred before the completion of the
initial one.

note: The thread controller already handle delayed tasks and power
management by not posting delayed task while computer is in power
suspended state.

Jank stackframe:

 tzset_nolock
 tzset
 icu_68::TimeZone::detectHostTimeZone()
 device::TimeZoneMonitor::DetectHostTimeZoneFromIcu()
 device::TimeZoneMonitorWin::OnWndProc(HWND__ *,unsigned int,unsigned __int64,__int64)
 gfx::SingletonHwnd::ProcessWindowMessage(HWND__ *,unsigned int,unsigned __int64,__int64,__int64 &,unsigned long)
 gfx::WindowImpl::OnWndProc(unsigned int,unsigned __int64,__int64)
 gfx::WindowImpl::WndProc(HWND__ *,unsigned int,unsigned __int64,__int64)
 base::win::WrappedWindowProc<&gfx::WindowImpl::WndProc(HWND__ *,unsigned int,unsigned __int64,__int64)>(HWND__ *,unsigned int,unsigned __int64,__int64)
 UserCallWinProcCheckWow
 DispatchMessageWorker
 base::MessagePumpForUI::ProcessMessageHelper(tagMSG const &)
 base::MessagePumpForUI::ProcessNextWindowsMessage()
 base::MessagePumpForUI::DoRunLoop()
 base::MessagePumpWin::Run(base::MessagePump::Delegate *)
 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool,base::TimeDelta)
 base::RunLoop::Run()

R=gab@chromium.org,fdoray@chromium.org

Bug: 1074036
Change-Id: I5b5d5fd945205a3d2eaacbbde274e9f8caf5136e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2582549
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841232}
parent 6218887c
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "third_party/icu/source/i18n/unicode/timezone.h" #include "third_party/icu/source/i18n/unicode/timezone.h"
#include "ui/gfx/win/singleton_hwnd_observer.h" #include "ui/gfx/win/singleton_hwnd_observer.h"
...@@ -24,21 +25,42 @@ class TimeZoneMonitorWin : public TimeZoneMonitor { ...@@ -24,21 +25,42 @@ class TimeZoneMonitorWin : public TimeZoneMonitor {
singleton_hwnd_observer_(new gfx::SingletonHwndObserver( singleton_hwnd_observer_(new gfx::SingletonHwndObserver(
base::BindRepeating(&TimeZoneMonitorWin::OnWndProc, base::BindRepeating(&TimeZoneMonitorWin::OnWndProc,
base::Unretained(this)))) {} base::Unretained(this)))) {}
TimeZoneMonitorWin(const TimeZoneMonitorWin&) = delete;
TimeZoneMonitorWin& operator=(const TimeZoneMonitorWin&) = delete;
~TimeZoneMonitorWin() override {} ~TimeZoneMonitorWin() override {}
private: private:
void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
if (message != WM_TIMECHANGE) { if (message == WM_TIMECHANGE && !pending_update_notification_tasks_) {
return; // Traces show that in some cases there are multiple WM_TIMECHANGE while
// performing a power resume. Only sending one is enough
// (http://crbug.com/1074036).
pending_update_notification_tasks_ = true;
// The notifications are sent through a delayed task to avoid running
// the observers code while the computer is still suspended. The thread
// controller is not dispatching delayed tasks uuntil the power resume
// signal is received.
constexpr auto kMinimalPostTaskDelay =
base::TimeDelta::FromMilliseconds(1);
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&TimeZoneMonitorWin::OnWmTimechangeReceived,
weak_ptr_factory_.GetWeakPtr()),
kMinimalPostTaskDelay);
} }
TRACE_EVENT0("browser", "TimeZoneMonitorWin::UpdateIcuAndNotifyClients"); }
void OnWmTimechangeReceived() {
TRACE_EVENT0("device", "TimeZoneMonitorWin::OnTimechangeReceived");
UpdateIcuAndNotifyClients(DetectHostTimeZoneFromIcu()); UpdateIcuAndNotifyClients(DetectHostTimeZoneFromIcu());
pending_update_notification_tasks_ = false;
} }
std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_; std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_;
bool pending_update_notification_tasks_ = false;
DISALLOW_COPY_AND_ASSIGN(TimeZoneMonitorWin); base::WeakPtrFactory<TimeZoneMonitorWin> weak_ptr_factory_{this};
}; };
// static // static
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment