Index: components/scheduler/renderer/renderer_scheduler_impl.cc |
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc |
index 4b565314a7996816887d0a71aaca51161fe5515c..f05fc4994421f2659ea92e318bd8790098ae1f19 100644 |
--- a/components/scheduler/renderer/renderer_scheduler_impl.cc |
+++ b/components/scheduler/renderer/renderer_scheduler_impl.cc |
@@ -54,6 +54,10 @@ RendererSchedulerImpl::RendererSchedulerImpl( |
end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
&RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
+ suspend_timers_when_backgrounded_closure_.Reset( |
+ base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, |
+ weak_factory_.GetWeakPtr())); |
+ |
timer_task_runner_->AddTaskObserver( |
&MainThreadOnly().timer_task_cost_estimator_); |
@@ -81,6 +85,9 @@ RendererSchedulerImpl::MainThreadOnly::MainThreadOnly() |
current_policy_(Policy::NORMAL), |
timer_queue_suspend_count_(0), |
renderer_hidden_(false), |
+ renderer_backgrounded_(false), |
+ timer_queue_suspension_when_backgrounded_enabled_(false), |
+ timer_queue_suspended_when_backgrounded_(false), |
was_shutdown_(false) {} |
RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
@@ -231,6 +238,38 @@ void RendererSchedulerImpl::OnRendererVisible() { |
this, AsValue(helper_.Now())); |
} |
+void RendererSchedulerImpl::OnRendererBackgrounded() { |
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
+ "RendererSchedulerImpl::OnRendererBackgrounded"); |
+ helper_.CheckOnValidThread(); |
+ if (helper_.IsShutdown() || MainThreadOnly().renderer_backgrounded_) |
+ return; |
+ |
+ MainThreadOnly().renderer_backgrounded_ = true; |
+ if (!MainThreadOnly().timer_queue_suspension_when_backgrounded_enabled_) |
+ return; |
+ |
+ suspend_timers_when_backgrounded_closure_.Cancel(); |
+ base::TimeDelta suspend_timers_when_backgrounded_delay = |
+ base::TimeDelta::FromMilliseconds( |
+ kSuspendTimersWhenBackgroundedDelayMillis); |
+ control_task_runner_->PostDelayedTask( |
+ FROM_HERE, suspend_timers_when_backgrounded_closure_.callback(), |
+ suspend_timers_when_backgrounded_delay); |
+} |
+ |
+void RendererSchedulerImpl::OnRendererForegrounded() { |
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
+ "RendererSchedulerImpl::OnRendererForegrounded"); |
+ helper_.CheckOnValidThread(); |
+ if (helper_.IsShutdown() || !MainThreadOnly().renderer_backgrounded_) |
+ return; |
+ |
+ MainThreadOnly().renderer_backgrounded_ = false; |
+ suspend_timers_when_backgrounded_closure_.Cancel(); |
+ ResumeTimerQueueWhenForegrounded(); |
+} |
+ |
void RendererSchedulerImpl::EndIdlePeriod() { |
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
"RendererSchedulerImpl::EndIdlePeriod"); |
@@ -460,10 +499,12 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { |
TaskQueue::QueuePriority compositor_queue_priority = |
TaskQueue::NORMAL_PRIORITY; |
TaskQueue::QueuePriority loading_queue_priority = TaskQueue::NORMAL_PRIORITY; |
- TaskQueue::QueuePriority timer_queue_priority = |
- MainThreadOnly().timer_queue_suspend_count_ != 0 |
- ? TaskQueue::DISABLED_PRIORITY |
- : TaskQueue::NORMAL_PRIORITY; |
+ TaskQueue::QueuePriority timer_queue_priority = TaskQueue::NORMAL_PRIORITY; |
+ |
+ if (MainThreadOnly().timer_queue_suspend_count_ != 0 || |
+ MainThreadOnly().timer_queue_suspended_when_backgrounded_) { |
+ timer_queue_priority = TaskQueue::DISABLED_PRIORITY; |
+ } |
switch (new_policy) { |
case Policy::COMPOSITOR_PRIORITY: |
@@ -608,6 +649,12 @@ void RendererSchedulerImpl::ResumeTimerQueue() { |
ForceUpdatePolicy(); |
} |
+void RendererSchedulerImpl::SetTimerQueueSuspensionWhenBackgroundedEnabled( |
+ bool enabled) { |
+ // Note that this will only take effect for the next backgrounded signal. |
+ MainThreadOnly().timer_queue_suspension_when_backgrounded_enabled_ = enabled; |
+} |
+ |
// static |
const char* RendererSchedulerImpl::PolicyToString(Policy policy) { |
switch (policy) { |
@@ -649,6 +696,12 @@ RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
IdleHelper::IdlePeriodStateToString( |
idle_helper_.SchedulerIdlePeriodState())); |
state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_); |
+ state->SetBoolean("renderer_backgrounded", |
+ MainThreadOnly().renderer_backgrounded_); |
+ state->SetBoolean("timer_queue_suspended_when_backgrounded", |
+ MainThreadOnly().timer_queue_suspended_when_backgrounded_); |
+ state->SetInteger("timer_queue_suspend_count", |
+ MainThreadOnly().timer_queue_suspend_count_); |
state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
state->SetDouble("last_input_signal_time", |
(AnyThread().last_input_signal_time_ - base::TimeTicks()) |
@@ -710,4 +763,22 @@ bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const { |
kIdlePeriodStarvationThresholdMillis); |
} |
+void RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded() { |
+ DCHECK(MainThreadOnly().renderer_backgrounded_); |
+ if (MainThreadOnly().timer_queue_suspended_when_backgrounded_) |
+ return; |
+ |
+ MainThreadOnly().timer_queue_suspended_when_backgrounded_ = true; |
+ ForceUpdatePolicy(); |
+} |
+ |
+void RendererSchedulerImpl::ResumeTimerQueueWhenForegrounded() { |
+ DCHECK(!MainThreadOnly().renderer_backgrounded_); |
+ if (!MainThreadOnly().timer_queue_suspended_when_backgrounded_) |
+ return; |
+ |
+ MainThreadOnly().timer_queue_suspended_when_backgrounded_ = false; |
+ ForceUpdatePolicy(); |
+} |
+ |
} // namespace scheduler |