1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "cc/scheduler/scheduler.h"
6 
7 #include <stddef.h>
8 
9 #include <string>
10 #include <vector>
11 
12 #include "base/auto_reset.h"
13 #include "base/bind.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/numerics/safe_conversions.h"
17 #include "base/run_loop.h"
18 #include "base/test/test_mock_time_task_runner.h"
19 #include "base/time/time.h"
20 #include "base/trace_event/trace_event.h"
21 #include "cc/metrics/begin_main_frame_metrics.h"
22 #include "cc/metrics/event_metrics.h"
23 #include "cc/test/scheduler_test_common.h"
24 #include "components/viz/common/frame_sinks/begin_frame_args.h"
25 #include "components/viz/test/begin_frame_args_test.h"
26 #include "components/viz/test/fake_delay_based_time_source.h"
27 #include "components/viz/test/fake_external_begin_frame_source.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 
31 #define EXPECT_ACTIONS(...) \
32   EXPECT_THAT(client_->Actions(), ::testing::ElementsAre(__VA_ARGS__))
33 
34 #define EXPECT_NO_ACTION() EXPECT_THAT(client_->Actions(), ::testing::IsEmpty())
35 
36 #define EXPECT_SCOPED(statements) \
37   {                               \
38     SCOPED_TRACE("");             \
39     statements;                   \
40   }
41 
42 namespace cc {
43 namespace {
44 
45 base::TimeDelta kSlowDuration = base::TimeDelta::FromSeconds(1);
46 base::TimeDelta kFastDuration = base::TimeDelta::FromMilliseconds(1);
47 
48 class FakeSchedulerClient : public SchedulerClient,
49                             public viz::FakeExternalBeginFrameSource::Client {
50  public:
FakeSchedulerClient()51   FakeSchedulerClient() { Reset(); }
52 
Reset()53   void Reset() {
54     actions_.clear();
55     will_begin_impl_frame_causes_redraw_ = false;
56     will_begin_impl_frame_requests_one_begin_impl_frame_ = false;
57     invalidate_needs_redraw_ = true;
58     draw_will_happen_ = true;
59     swap_will_happen_if_draw_happens_ = true;
60     num_draws_ = 0;
61     last_begin_main_frame_args_ = viz::BeginFrameArgs();
62     last_begin_frame_ack_ = viz::BeginFrameAck();
63   }
64 
set_scheduler(TestScheduler * scheduler)65   void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; }
66 
needs_begin_frames()67   bool needs_begin_frames() { return scheduler_->begin_frames_expected(); }
num_draws() const68   int num_draws() const { return num_draws_; }
invalidate_needs_redraw() const69   bool invalidate_needs_redraw() const { return invalidate_needs_redraw_; }
Actions() const70   const std::vector<std::string> Actions() const {
71     return std::vector<std::string>(actions_.begin(), actions_.end());
72   }
posted_begin_impl_frame_deadline() const73   base::TimeTicks posted_begin_impl_frame_deadline() const {
74     return posted_begin_impl_frame_deadline_;
75   }
76 
frame_interval() const77   base::TimeDelta frame_interval() const { return frame_interval_; }
78 
ActionIndex(const char * action) const79   int ActionIndex(const char* action) const {
80     for (size_t i = 0; i < actions_.size(); i++)
81       if (!strcmp(actions_[i], action))
82         return base::checked_cast<int>(i);
83     return -1;
84   }
85 
HasAction(const char * action) const86   bool HasAction(const char* action) const { return ActionIndex(action) >= 0; }
87 
SetWillBeginImplFrameRequestsOneBeginImplFrame(bool request)88   void SetWillBeginImplFrameRequestsOneBeginImplFrame(bool request) {
89     will_begin_impl_frame_requests_one_begin_impl_frame_ = request;
90   }
SetWillBeginImplFrameCausesRedraw(bool causes_redraw)91   void SetWillBeginImplFrameCausesRedraw(bool causes_redraw) {
92     will_begin_impl_frame_causes_redraw_ = causes_redraw;
93   }
SetInvalidateNeedsRedraw(bool needs_redraw)94   void SetInvalidateNeedsRedraw(bool needs_redraw) {
95     invalidate_needs_redraw_ = needs_redraw;
96   }
SetDrawWillHappen(bool draw_will_happen)97   void SetDrawWillHappen(bool draw_will_happen) {
98     draw_will_happen_ = draw_will_happen;
99   }
SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens)100   void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
101     swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
102   }
SetAutomaticSubmitCompositorFrameAck(bool automatic_ack)103   void SetAutomaticSubmitCompositorFrameAck(bool automatic_ack) {
104     automatic_ack_ = automatic_ack;
105   }
SetWillBeginImplFrameMightHaveDamage(bool might_have_damage)106   void SetWillBeginImplFrameMightHaveDamage(bool might_have_damage) {
107     will_begin_impl_frame_might_have_damage_ = might_have_damage;
108   }
109   // SchedulerClient implementation.
WillBeginImplFrame(const viz::BeginFrameArgs & args)110   bool WillBeginImplFrame(const viz::BeginFrameArgs& args) override {
111     EXPECT_FALSE(inside_begin_impl_frame_);
112     EXPECT_FALSE(inside_action_);
113     base::AutoReset<bool> mark_inside(&inside_action_, true);
114     inside_begin_impl_frame_ = true;
115     PushAction("WillBeginImplFrame");
116     if (will_begin_impl_frame_requests_one_begin_impl_frame_)
117       scheduler_->SetNeedsOneBeginImplFrame();
118     if (will_begin_impl_frame_causes_redraw_)
119       scheduler_->SetNeedsRedraw();
120     return will_begin_impl_frame_might_have_damage_;
121   }
DidFinishImplFrame()122   void DidFinishImplFrame() override {
123     EXPECT_TRUE(inside_begin_impl_frame_);
124     EXPECT_FALSE(inside_action_);
125     base::AutoReset<bool> mark_inside(&inside_action_, true);
126     inside_begin_impl_frame_ = false;
127   }
DidNotProduceFrame(const viz::BeginFrameAck & ack,FrameSkippedReason reason)128   void DidNotProduceFrame(const viz::BeginFrameAck& ack,
129                           FrameSkippedReason reason) override {
130     EXPECT_FALSE(inside_action_);
131     base::AutoReset<bool> mark_inside(&inside_action_, true);
132     last_begin_frame_ack_ = ack;
133   }
134 
WillNotReceiveBeginFrame()135   void WillNotReceiveBeginFrame() override {}
136 
ScheduledActionSendBeginMainFrame(const viz::BeginFrameArgs & args)137   void ScheduledActionSendBeginMainFrame(
138       const viz::BeginFrameArgs& args) override {
139     EXPECT_FALSE(inside_action_);
140     base::AutoReset<bool> mark_inside(&inside_action_, true);
141     PushAction("ScheduledActionSendBeginMainFrame");
142     last_begin_main_frame_args_ = args;
143   }
FrameIntervalUpdated(base::TimeDelta interval)144   void FrameIntervalUpdated(base::TimeDelta interval) override {
145     frame_interval_ = interval;
146   }
147 
last_begin_main_frame_args()148   const viz::BeginFrameArgs& last_begin_main_frame_args() {
149     return last_begin_main_frame_args_;
150   }
151 
last_begin_frame_ack()152   const viz::BeginFrameAck& last_begin_frame_ack() {
153     return last_begin_frame_ack_;
154   }
155 
ScheduledActionDrawIfPossible()156   DrawResult ScheduledActionDrawIfPossible() override {
157     EXPECT_FALSE(inside_action_);
158     base::AutoReset<bool> mark_inside(&inside_action_, true);
159     PushAction("ScheduledActionDrawIfPossible");
160     num_draws_++;
161     DrawResult result =
162         draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
163     bool swap_will_happen =
164         draw_will_happen_ && swap_will_happen_if_draw_happens_;
165     if (swap_will_happen) {
166       last_begin_frame_ack_ = scheduler_->CurrentBeginFrameAckForActiveTree();
167       scheduler_->DidSubmitCompositorFrame(0, EventMetricsSet());
168 
169       if (automatic_ack_)
170         scheduler_->DidReceiveCompositorFrameAck();
171     }
172     return result;
173   }
ScheduledActionDrawForced()174   DrawResult ScheduledActionDrawForced() override {
175     EXPECT_FALSE(inside_action_);
176     base::AutoReset<bool> mark_inside(&inside_action_, true);
177     PushAction("ScheduledActionDrawForced");
178     last_begin_frame_ack_ = scheduler_->CurrentBeginFrameAckForActiveTree();
179     return DRAW_SUCCESS;
180   }
ScheduledActionCommit()181   void ScheduledActionCommit() override {
182     EXPECT_FALSE(inside_action_);
183     base::AutoReset<bool> mark_inside(&inside_action_, true);
184     PushAction("ScheduledActionCommit");
185     scheduler_->DidCommit();
186   }
ScheduledActionActivateSyncTree()187   void ScheduledActionActivateSyncTree() override {
188     EXPECT_FALSE(inside_action_);
189     base::AutoReset<bool> mark_inside(&inside_action_, true);
190     PushAction("ScheduledActionActivateSyncTree");
191   }
ScheduledActionBeginLayerTreeFrameSinkCreation()192   void ScheduledActionBeginLayerTreeFrameSinkCreation() override {
193     EXPECT_FALSE(inside_action_);
194     base::AutoReset<bool> mark_inside(&inside_action_, true);
195     PushAction("ScheduledActionBeginLayerTreeFrameSinkCreation");
196   }
ScheduledActionPrepareTiles()197   void ScheduledActionPrepareTiles() override {
198     EXPECT_FALSE(inside_action_);
199     base::AutoReset<bool> mark_inside(&inside_action_, true);
200     PushAction("ScheduledActionPrepareTiles");
201     scheduler_->WillPrepareTiles();
202     scheduler_->DidPrepareTiles();
203   }
ScheduledActionInvalidateLayerTreeFrameSink(bool needs_redraw)204   void ScheduledActionInvalidateLayerTreeFrameSink(bool needs_redraw) override {
205     EXPECT_FALSE(inside_action_);
206     base::AutoReset<bool> mark_inside(&inside_action_, true);
207     invalidate_needs_redraw_ = needs_redraw;
208     actions_.push_back("ScheduledActionInvalidateLayerTreeFrameSink");
209   }
ScheduledActionPerformImplSideInvalidation()210   void ScheduledActionPerformImplSideInvalidation() override {
211     EXPECT_FALSE(inside_action_);
212     base::AutoReset<bool> mark_inside(&inside_action_, true);
213     PushAction("ScheduledActionPerformImplSideInvalidation");
214   }
215 
SendBeginMainFrameNotExpectedSoon()216   void SendBeginMainFrameNotExpectedSoon() override {
217     EXPECT_FALSE(inside_action_);
218     base::AutoReset<bool> mark_inside(&inside_action_, true);
219     PushAction("SendBeginMainFrameNotExpectedSoon");
220   }
221 
ScheduledActionBeginMainFrameNotExpectedUntil(base::TimeTicks time)222   void ScheduledActionBeginMainFrameNotExpectedUntil(
223       base::TimeTicks time) override {
224     EXPECT_FALSE(inside_action_);
225     base::AutoReset<bool> mark_inside(&inside_action_, true);
226     PushAction("ScheduledActionBeginMainFrameNotExpectedUntil");
227   }
228 
IsInsideBeginImplFrame() const229   bool IsInsideBeginImplFrame() const { return inside_begin_impl_frame_; }
230 
InsideBeginImplFrame(bool state)231   base::RepeatingCallback<bool(void)> InsideBeginImplFrame(bool state) {
232     return base::BindRepeating(
233         &FakeSchedulerClient::InsideBeginImplFrameCallback,
234         base::Unretained(this), state);
235   }
236 
IsCurrentFrame(int last_frame_number) const237   bool IsCurrentFrame(int last_frame_number) const {
238     return scheduler_->current_frame_number() == last_frame_number;
239   }
240 
FrameHasNotAdvancedCallback()241   base::RepeatingCallback<bool(void)> FrameHasNotAdvancedCallback() {
242     return base::BindRepeating(&FakeSchedulerClient::IsCurrentFrame,
243                                base::Unretained(this),
244                                scheduler_->current_frame_number());
245   }
246 
PushAction(const char * description)247   void PushAction(const char* description) {
248     actions_.push_back(description);
249   }
250 
251   // FakeExternalBeginFrameSource::Client implementation.
OnAddObserver(viz::BeginFrameObserver * obs)252   void OnAddObserver(viz::BeginFrameObserver* obs) override {
253     PushAction("AddObserver(this)");
254   }
OnRemoveObserver(viz::BeginFrameObserver * obs)255   void OnRemoveObserver(viz::BeginFrameObserver* obs) override {
256     PushAction("RemoveObserver(this)");
257   }
258 
CompositedAnimationsCount() const259   size_t CompositedAnimationsCount() const override { return 0; }
MainThreadAnimationsCount() const260   size_t MainThreadAnimationsCount() const override { return 0; }
HasCustomPropertyAnimations() const261   bool HasCustomPropertyAnimations() const override { return false; }
CurrentFrameHadRAF() const262   bool CurrentFrameHadRAF() const override { return false; }
NextFrameHasPendingRAF() const263   bool NextFrameHasPendingRAF() const override { return false; }
264 
265  protected:
InsideBeginImplFrameCallback(bool state)266   bool InsideBeginImplFrameCallback(bool state) {
267     return inside_begin_impl_frame_ == state;
268   }
269 
270   bool inside_action_ = false;
271   bool inside_begin_impl_frame_ = false;
272   bool will_begin_impl_frame_causes_redraw_;
273   bool will_begin_impl_frame_requests_one_begin_impl_frame_;
274   bool invalidate_needs_redraw_ = true;
275   bool draw_will_happen_;
276   bool swap_will_happen_if_draw_happens_;
277   bool automatic_ack_ = true;
278   bool will_begin_impl_frame_might_have_damage_ = true;
279   int num_draws_;
280   viz::BeginFrameArgs last_begin_main_frame_args_;
281   viz::BeginFrameAck last_begin_frame_ack_;
282   base::TimeTicks posted_begin_impl_frame_deadline_;
283   std::vector<const char*> actions_;
284   TestScheduler* scheduler_ = nullptr;
285   base::TimeDelta frame_interval_;
286 };
287 
288 enum BeginFrameSourceType {
289   EXTERNAL_BFS,
290   UNTHROTTLED_BFS,
291   THROTTLED_BFS,
292 };
293 
294 class SchedulerTestTaskRunner : public base::TestMockTimeTaskRunner {
295  public:
SchedulerTestTaskRunner()296   SchedulerTestTaskRunner()
297       : base::TestMockTimeTaskRunner(
298             base::TestMockTimeTaskRunner::Type::kStandalone) {
299     AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(110000));
300   }
301 
RunUntilTime(base::TimeTicks end_time)302   void RunUntilTime(base::TimeTicks end_time) {
303     FastForwardBy(end_time - NowTicks());
304   }
305 
306   // Runs all tasks posted before this call.
RunPendingTasks()307   void RunPendingTasks() {
308     base::circular_deque<base::TestPendingTask> tasks = TakePendingTasks();
309     while (!tasks.empty()) {
310       base::TestPendingTask task = std::move(tasks.front());
311       tasks.pop_front();
312       // Set clock to the beginning of task and run it.
313       AdvanceMockTickClock(task.GetTimeToRun() - NowTicks());
314       std::move(task.task).Run();
315     }
316   }
317 
318   // Runs tasks while condition is met.
319   // Condition is being checked when task exists and before it gets selected.
RunTasksWhile(base::RepeatingCallback<bool ()> condition)320   void RunTasksWhile(base::RepeatingCallback<bool()> condition) {
321     run_condition_ = condition;
322     FastForwardUntilNoTasksRemain();
323     run_condition_ = base::nullopt;
324     // We've moved all the pending tasks away to break the execution loop,
325     // now we should restore them.
326     while (!tasks_to_requeue_.empty()) {
327       base::TestPendingTask task = std::move(tasks_to_requeue_.front());
328       tasks_to_requeue_.pop_front();
329       PostDelayedTask(task.location, std::move(task.task),
330                       task.GetTimeToRun() - NowTicks());
331     }
332   }
333 
334  protected:
OnBeforeSelectingTask()335   void OnBeforeSelectingTask() override {
336     // Avoid potential infinite loops.
337     ASSERT_LT(++task_count_, 100u);
338 
339     if (run_condition_ && HasPendingTask() && !run_condition_->Run()) {
340       // Execution will not continue because we move all the pending tasks away.
341       tasks_to_requeue_ = TakePendingTasks();
342     }
343   }
344 
345  private:
346   ~SchedulerTestTaskRunner() override = default;  // Ref-counted.
347 
348   size_t task_count_ = 0u;
349   base::Optional<base::RepeatingCallback<bool()>> run_condition_;
350   base::circular_deque<base::TestPendingTask> tasks_to_requeue_;
351 };
352 
353 class SchedulerTest : public testing::Test {
354  public:
SchedulerTest()355   SchedulerTest()
356       : task_runner_(base::MakeRefCounted<SchedulerTestTaskRunner>()),
357         fake_external_begin_frame_source_(nullptr),
358         fake_compositor_timing_history_(nullptr) {}
359 
360   ~SchedulerTest() override = default;
361 
362  protected:
CreateScheduler(BeginFrameSourceType bfs_type)363   TestScheduler* CreateScheduler(BeginFrameSourceType bfs_type) {
364     viz::BeginFrameSource* frame_source = nullptr;
365     unthrottled_frame_source_.reset(new viz::BackToBackBeginFrameSource(
366         std::make_unique<viz::FakeDelayBasedTimeSource>(
367             task_runner_->GetMockTickClock(), task_runner_.get())));
368     fake_external_begin_frame_source_.reset(
369         new viz::FakeExternalBeginFrameSource(1.0, false));
370     fake_external_begin_frame_source_->SetClient(client_.get());
371     synthetic_frame_source_ = std::make_unique<viz::DelayBasedBeginFrameSource>(
372         std::make_unique<viz::FakeDelayBasedTimeSource>(
373             task_runner_->GetMockTickClock(), task_runner_.get()),
374         viz::BeginFrameSource::kNotRestartableId);
375     switch (bfs_type) {
376       case EXTERNAL_BFS:
377         frame_source = fake_external_begin_frame_source_.get();
378         break;
379       case UNTHROTTLED_BFS:
380         frame_source = unthrottled_frame_source_.get();
381         break;
382       case THROTTLED_BFS:
383         frame_source = synthetic_frame_source_.get();
384         break;
385     }
386     DCHECK(frame_source);
387 
388     std::unique_ptr<FakeCompositorTimingHistory>
389         fake_compositor_timing_history = FakeCompositorTimingHistory::Create(
390             scheduler_settings_.using_synchronous_renderer_compositor);
391     fake_compositor_timing_history_ = fake_compositor_timing_history.get();
392 
393     scheduler_.reset(new TestScheduler(
394         task_runner_->GetMockTickClock(), client_.get(), scheduler_settings_, 0,
395         task_runner_.get(), std::move(fake_compositor_timing_history)));
396     client_->set_scheduler(scheduler_.get());
397     scheduler_->SetBeginFrameSource(frame_source);
398 
399     // Use large estimates by default to avoid latency recovery in most tests.
400     fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
401 
402     return scheduler_.get();
403   }
404 
SetUpScheduler(BeginFrameSourceType bfs_type,std::unique_ptr<FakeSchedulerClient> client)405   void SetUpScheduler(BeginFrameSourceType bfs_type,
406                       std::unique_ptr<FakeSchedulerClient> client) {
407     client_ = std::move(client);
408     CreateScheduler(bfs_type);
409     EXPECT_SCOPED(InitializeLayerTreeFrameSinkAndFirstCommit());
410   }
411 
SetUpScheduler(BeginFrameSourceType bfs_type)412   void SetUpScheduler(BeginFrameSourceType bfs_type) {
413     SetUpScheduler(bfs_type, std::make_unique<FakeSchedulerClient>());
414   }
415 
SetUpSchedulerWithNoLayerTreeFrameSink(BeginFrameSourceType bfs_type)416   void SetUpSchedulerWithNoLayerTreeFrameSink(BeginFrameSourceType bfs_type) {
417     client_ = std::make_unique<FakeSchedulerClient>();
418     CreateScheduler(bfs_type);
419   }
420 
421   // As this function contains EXPECT macros, to allow debugging it should be
422   // called inside EXPECT_SCOPED like so;
423   //   EXPECT_SCOPED(
424   //       client.InitializeLayerTreeFrameSinkAndFirstCommit(scheduler));
InitializeLayerTreeFrameSinkAndFirstCommit()425   void InitializeLayerTreeFrameSinkAndFirstCommit() {
426     TRACE_EVENT0(
427         "cc", "SchedulerUnitTest::InitializeLayerTreeFrameSinkAndFirstCommit");
428     DCHECK(scheduler_);
429 
430     // Check the client doesn't have any actions queued when calling this
431     // function.
432     EXPECT_NO_ACTION();
433     EXPECT_FALSE(scheduler_->begin_frames_expected());
434 
435     // Start the initial LayerTreeFrameSink creation.
436     scheduler_->SetVisible(true);
437     scheduler_->SetCanDraw(true);
438     EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
439 
440     client_->Reset();
441 
442     // We don't see anything happening until the first impl frame.
443     scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
444     scheduler_->SetNeedsBeginMainFrame();
445     EXPECT_TRUE(scheduler_->begin_frames_expected());
446     EXPECT_FALSE(client_->IsInsideBeginImplFrame());
447     client_->Reset();
448 
449     {
450       SCOPED_TRACE("Do first frame to commit after initialize.");
451       AdvanceFrame();
452 
453       task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMilliseconds(1));
454       scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
455       scheduler_->NotifyReadyToCommit(nullptr);
456       scheduler_->NotifyReadyToActivate();
457       scheduler_->NotifyReadyToDraw();
458 
459       EXPECT_FALSE(scheduler_->CommitPending());
460 
461       if (scheduler_settings_.using_synchronous_renderer_compositor) {
462         scheduler_->SetNeedsRedraw();
463         bool resourceless_software_draw = false;
464         bool skip_draw = false;
465         scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
466                                                 skip_draw);
467       } else {
468         // Run the posted deadline task.
469         EXPECT_TRUE(client_->IsInsideBeginImplFrame());
470         task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
471       }
472 
473       EXPECT_FALSE(client_->IsInsideBeginImplFrame());
474     }
475 
476     client_->Reset();
477 
478     {
479       SCOPED_TRACE(
480           "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
481       AdvanceFrame();
482 
483       if (!scheduler_settings_.using_synchronous_renderer_compositor) {
484         // Run the posted deadline task.
485         EXPECT_TRUE(client_->IsInsideBeginImplFrame());
486         task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
487       }
488 
489       EXPECT_FALSE(client_->IsInsideBeginImplFrame());
490     }
491 
492     EXPECT_FALSE(scheduler_->begin_frames_expected());
493 
494     if (scheduler_->begin_frame_source() ==
495         fake_external_begin_frame_source_.get()) {
496       // Expect the last viz::BeginFrameAck to be for last BeginFrame, which
497       // didn't cause damage.
498       uint64_t last_begin_frame_number =
499           fake_external_begin_frame_source_->next_begin_frame_number() - 1;
500       bool has_damage = false;
501       EXPECT_EQ(
502           viz::BeginFrameAck(fake_external_begin_frame_source_->source_id(),
503                              last_begin_frame_number, has_damage),
504           client_->last_begin_frame_ack());
505     }
506 
507     client_->Reset();
508   }
509 
510   // As this function contains EXPECT macros, to allow debugging it should be
511   // called inside EXPECT_SCOPED like so;
512   //   EXPECT_SCOPED(client.AdvanceFrame());
AdvanceFrame(bool animate_only=false)513   void AdvanceFrame(bool animate_only = false) {
514     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
515                  "FakeSchedulerClient::AdvanceFrame");
516 
517     // Send the next BeginFrame message if using an external source, otherwise
518     // it will be already in the task queue.
519     if (scheduler_->begin_frame_source() ==
520         fake_external_begin_frame_source_.get()) {
521       EXPECT_TRUE(scheduler_->begin_frames_expected());
522       // Run the deadline first if we're inside the previous frame.
523       if (client_->IsInsideBeginImplFrame())
524         task_runner_->RunPendingTasks();
525       SendNextBeginFrame(animate_only);
526     } else {
527       task_runner_->RunTasksWhile(client_->FrameHasNotAdvancedCallback());
528     }
529   }
530 
SendNextBeginFrame(bool animate_only=false)531   viz::BeginFrameArgs SendNextBeginFrame(bool animate_only = false) {
532     DCHECK_EQ(scheduler_->begin_frame_source(),
533               fake_external_begin_frame_source_.get());
534     // Creep the time forward so that any viz::BeginFrameArgs is not equal to
535     // the last one otherwise we violate the viz::BeginFrameSource contract.
536     task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
537     viz::BeginFrameArgs args =
538         fake_external_begin_frame_source_->CreateBeginFrameArgs(
539             BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
540     args.animate_only = animate_only;
541     fake_external_begin_frame_source_->TestOnBeginFrame(args);
542     return args;
543   }
544 
fake_external_begin_frame_source() const545   viz::FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
546     return fake_external_begin_frame_source_.get();
547   }
548 
SetShouldDeferInvalidationForMainFrame(bool defer)549   void SetShouldDeferInvalidationForMainFrame(bool defer) {
550     // Set the CompositorTimingHistory so that main thread is identified to be
551     // fast or slow.
552     base::TimeDelta delta;
553     if (!defer)
554       delta = base::TimeDelta::FromSeconds(1);
555     fake_compositor_timing_history_
556         ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(delta);
557     fake_compositor_timing_history_
558         ->SetBeginMainFrameQueueDurationCriticalEstimate(delta);
559     fake_compositor_timing_history_
560         ->SetBeginMainFrameQueueDurationNotCriticalEstimate(delta);
561     fake_compositor_timing_history_->SetDrawDurationEstimate(base::TimeDelta());
562   }
563 
564   void AdvanceAndMissOneFrame();
565   void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame);
566   void ImplFrameSkippedAfterLateAck(bool is_already_receiving_begin_frames,
567                                     bool receive_ack_before_deadline);
568   void ImplFrameNotSkippedAfterLateAck();
569   void BeginFramesNotFromClient(BeginFrameSourceType bfs_type);
570   void BeginFramesNotFromClient_IsDrawThrottled(BeginFrameSourceType bfs_type);
571   bool BeginMainFrameOnCriticalPath(TreePriority tree_priority,
572                                     ScrollHandlerState scroll_handler_state,
573                                     base::TimeDelta durations);
574 
575   scoped_refptr<SchedulerTestTaskRunner> task_runner_;
576   std::unique_ptr<viz::FakeExternalBeginFrameSource>
577       fake_external_begin_frame_source_;
578   std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_frame_source_;
579   std::unique_ptr<viz::SyntheticBeginFrameSource> unthrottled_frame_source_;
580   SchedulerSettings scheduler_settings_;
581   std::unique_ptr<FakeSchedulerClient> client_;
582   std::unique_ptr<TestScheduler> scheduler_;
583   FakeCompositorTimingHistory* fake_compositor_timing_history_;
584 };
585 
TEST_F(SchedulerTest,InitializeLayerTreeFrameSinkDoesNotBeginImplFrame)586 TEST_F(SchedulerTest, InitializeLayerTreeFrameSinkDoesNotBeginImplFrame) {
587   SetUpSchedulerWithNoLayerTreeFrameSink(EXTERNAL_BFS);
588   scheduler_->SetVisible(true);
589   scheduler_->SetCanDraw(true);
590 
591   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
592   client_->Reset();
593   scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
594   EXPECT_NO_ACTION();
595 }
596 
TEST_F(SchedulerTest,Stop)597 TEST_F(SchedulerTest, Stop) {
598   SetUpScheduler(EXTERNAL_BFS);
599 
600   scheduler_->SetNeedsBeginMainFrame();
601   EXPECT_ACTIONS("AddObserver(this)");
602   client_->Reset();
603 
604   // No scheduled actions are performed after Stop. WillBeginImplFrame is only
605   // a notification and not an action performed by the scheduler.
606   scheduler_->Stop();
607   EXPECT_SCOPED(AdvanceFrame());
608   EXPECT_ACTIONS("WillBeginImplFrame");
609   client_->Reset();
610 }
611 
TEST_F(SchedulerTest,VideoNeedsBeginFrames)612 TEST_F(SchedulerTest, VideoNeedsBeginFrames) {
613   SetUpScheduler(EXTERNAL_BFS);
614 
615   scheduler_->SetVideoNeedsBeginFrames(true);
616   EXPECT_ACTIONS("AddObserver(this)");
617   EXPECT_TRUE(scheduler_->begin_frames_expected());
618 
619   client_->Reset();
620   EXPECT_SCOPED(AdvanceFrame());
621   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
622   // WillBeginImplFrame is responsible for sending BeginFrames to video.
623   EXPECT_ACTIONS("WillBeginImplFrame");
624 
625   client_->Reset();
626   EXPECT_SCOPED(AdvanceFrame());
627   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
628   EXPECT_ACTIONS("WillBeginImplFrame");
629 
630   client_->Reset();
631   scheduler_->SetVideoNeedsBeginFrames(false);
632   EXPECT_NO_ACTION();
633 
634   client_->Reset();
635   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
636   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
637   EXPECT_ACTIONS("RemoveObserver(this)");
638   EXPECT_FALSE(scheduler_->begin_frames_expected());
639 }
640 
TEST_F(SchedulerTest,RequestCommit)641 TEST_F(SchedulerTest, RequestCommit) {
642   SetUpScheduler(EXTERNAL_BFS);
643 
644   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
645   scheduler_->SetNeedsBeginMainFrame();
646   EXPECT_ACTIONS("AddObserver(this)");
647   client_->Reset();
648 
649   EXPECT_SCOPED(AdvanceFrame());
650   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
651   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
652   EXPECT_TRUE(scheduler_->begin_frames_expected());
653   client_->Reset();
654 
655   // If we don't swap on the deadline, we wait for the next BeginFrame.
656   task_runner_->RunPendingTasks();  // Run posted deadline.
657   EXPECT_NO_ACTION();
658   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
659   EXPECT_TRUE(scheduler_->begin_frames_expected());
660   client_->Reset();
661 
662   // NotifyReadyToCommit should trigger the commit.
663   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
664   scheduler_->NotifyReadyToCommit(nullptr);
665   EXPECT_ACTIONS("ScheduledActionCommit");
666   EXPECT_TRUE(scheduler_->begin_frames_expected());
667   client_->Reset();
668 
669   // NotifyReadyToActivate should trigger the activation.
670   scheduler_->NotifyReadyToActivate();
671   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
672   EXPECT_TRUE(scheduler_->begin_frames_expected());
673   client_->Reset();
674 
675   // BeginImplFrame should prepare the draw.
676   EXPECT_SCOPED(AdvanceFrame());
677   EXPECT_ACTIONS("WillBeginImplFrame");
678   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
679   EXPECT_TRUE(scheduler_->begin_frames_expected());
680   client_->Reset();
681 
682   // BeginImplFrame deadline should draw.
683   task_runner_->RunPendingTasks();  // Run posted deadline.
684   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
685   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
686   EXPECT_TRUE(scheduler_->begin_frames_expected());
687   client_->Reset();
688 
689   // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
690   // to avoid excessive toggles.
691   EXPECT_SCOPED(AdvanceFrame());
692   EXPECT_ACTIONS("WillBeginImplFrame");
693   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
694   client_->Reset();
695 
696   task_runner_->RunPendingTasks();  // Run posted deadline.
697   EXPECT_ACTIONS("RemoveObserver(this)");
698   client_->Reset();
699 }
700 
TEST_F(SchedulerTest,RequestCommitAfterSetDeferBeginMainFrame)701 TEST_F(SchedulerTest, RequestCommitAfterSetDeferBeginMainFrame) {
702   SetUpScheduler(EXTERNAL_BFS);
703 
704   scheduler_->SetDeferBeginMainFrame(true);
705 
706   scheduler_->SetNeedsBeginMainFrame();
707   EXPECT_NO_ACTION();
708 
709   client_->Reset();
710   task_runner_->RunPendingTasks();
711   // There are no pending tasks or actions.
712   EXPECT_NO_ACTION();
713   EXPECT_FALSE(scheduler_->begin_frames_expected());
714 
715   client_->Reset();
716   scheduler_->SetDeferBeginMainFrame(false);
717   EXPECT_ACTIONS("AddObserver(this)");
718 
719   // Start new BeginMainFrame after defer commit is off.
720   client_->Reset();
721   EXPECT_SCOPED(AdvanceFrame());
722   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
723   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
724 }
725 
TEST_F(SchedulerTest,DeferBeginMainFrameWithRedraw)726 TEST_F(SchedulerTest, DeferBeginMainFrameWithRedraw) {
727   SetUpScheduler(EXTERNAL_BFS);
728 
729   scheduler_->SetDeferBeginMainFrame(true);
730 
731   scheduler_->SetNeedsBeginMainFrame();
732   EXPECT_NO_ACTION();
733 
734   // The SetNeedsRedraw will override the SetDeferBeginMainFrame(true), to
735   // allow a begin frame to be needed.
736   client_->Reset();
737   scheduler_->SetNeedsRedraw();
738   EXPECT_ACTIONS("AddObserver(this)");
739 
740   client_->Reset();
741   AdvanceFrame();
742   // BeginMainFrame is not sent during the defer commit is on.
743   EXPECT_ACTIONS("WillBeginImplFrame");
744 
745   client_->Reset();
746   task_runner_->RunPendingTasks();  // Run posted deadline.
747   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
748   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
749   EXPECT_TRUE(scheduler_->begin_frames_expected());
750 
751   client_->Reset();
752   AdvanceFrame();
753   EXPECT_ACTIONS("WillBeginImplFrame");
754 }
755 
TEST_F(SchedulerTest,RequestCommitAfterBeginMainFrameSent)756 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
757   SetUpScheduler(EXTERNAL_BFS);
758 
759   // SetNeedsBeginMainFrame should begin the frame.
760   scheduler_->SetNeedsBeginMainFrame();
761   EXPECT_ACTIONS("AddObserver(this)");
762 
763   client_->Reset();
764   EXPECT_SCOPED(AdvanceFrame());
765   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
766   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
767 
768   EXPECT_TRUE(scheduler_->begin_frames_expected());
769   client_->Reset();
770 
771   // Now SetNeedsBeginMainFrame again. Calling here means we need a second
772   // commit.
773   scheduler_->SetNeedsBeginMainFrame();
774   EXPECT_NO_ACTION();
775   client_->Reset();
776 
777   // Finish the first commit.
778   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
779   scheduler_->NotifyReadyToCommit(nullptr);
780   EXPECT_ACTIONS("ScheduledActionCommit");
781   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
782   client_->Reset();
783 
784   // Activate it.
785   scheduler_->NotifyReadyToActivate();
786   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
787   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
788   client_->Reset();
789 
790   task_runner_->RunPendingTasks();  // Run posted deadline.
791   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
792   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
793 
794   // Because we just swapped, the Scheduler should also request the next
795   // BeginImplFrame from the LayerTreeFrameSink.
796   EXPECT_TRUE(scheduler_->begin_frames_expected());
797   client_->Reset();
798   // Since another commit is needed, the next BeginImplFrame should initiate
799   // the second commit.
800   EXPECT_SCOPED(AdvanceFrame());
801   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
802   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
803   client_->Reset();
804 
805   // Finishing the commit before the deadline should post a new deadline task
806   // to trigger the deadline early.
807   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
808   scheduler_->NotifyReadyToCommit(nullptr);
809   EXPECT_ACTIONS("ScheduledActionCommit");
810   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
811   client_->Reset();
812   scheduler_->NotifyReadyToActivate();
813   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
814   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
815   client_->Reset();
816   task_runner_->RunPendingTasks();  // Run posted deadline.
817   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
818   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
819   EXPECT_TRUE(scheduler_->begin_frames_expected());
820   client_->Reset();
821 
822   // On the next BeginImplFrame, verify we go back to a quiescent state and
823   // no longer request BeginImplFrames.
824   EXPECT_SCOPED(AdvanceFrame());
825   task_runner_->RunPendingTasks();  // Run posted deadline.
826   EXPECT_FALSE(scheduler_->begin_frames_expected());
827   client_->Reset();
828 }
829 
830 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
831  public:
SchedulerClientThatsetNeedsDrawInsideDraw()832   SchedulerClientThatsetNeedsDrawInsideDraw()
833       : FakeSchedulerClient(), request_redraws_(false) {}
834 
SetRequestRedrawsInsideDraw(bool enable)835   void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
836 
ScheduledActionDrawIfPossible()837   DrawResult ScheduledActionDrawIfPossible() override {
838     // Only SetNeedsRedraw the first time this is called
839     if (request_redraws_) {
840       scheduler_->SetNeedsRedraw();
841     }
842     return FakeSchedulerClient::ScheduledActionDrawIfPossible();
843   }
844 
ScheduledActionDrawForced()845   DrawResult ScheduledActionDrawForced() override {
846     NOTREACHED();
847     return DRAW_SUCCESS;
848   }
849 
850  private:
851   bool request_redraws_;
852 };
853 
854 // Tests for two different situations:
855 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
856 //    a ScheduledActionDraw
857 // 2. the scheduler drawing twice inside a single tick
TEST_F(SchedulerTest,RequestRedrawInsideDraw)858 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
859   SchedulerClientThatsetNeedsDrawInsideDraw* client =
860       new SchedulerClientThatsetNeedsDrawInsideDraw;
861   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
862   client->SetRequestRedrawsInsideDraw(true);
863 
864   scheduler_->SetNeedsRedraw();
865   EXPECT_TRUE(scheduler_->RedrawPending());
866   EXPECT_TRUE(client->needs_begin_frames());
867   EXPECT_EQ(0, client->num_draws());
868 
869   EXPECT_SCOPED(AdvanceFrame());
870   task_runner_->RunPendingTasks();  // Run posted deadline.
871   EXPECT_EQ(1, client->num_draws());
872   EXPECT_TRUE(scheduler_->RedrawPending());
873   EXPECT_TRUE(client->needs_begin_frames());
874 
875   client->SetRequestRedrawsInsideDraw(false);
876 
877   EXPECT_SCOPED(AdvanceFrame());
878   task_runner_->RunPendingTasks();  // Run posted deadline.
879   EXPECT_EQ(2, client_->num_draws());
880   EXPECT_FALSE(scheduler_->RedrawPending());
881   EXPECT_TRUE(client->needs_begin_frames());
882 
883   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
884   // swap.
885   EXPECT_SCOPED(AdvanceFrame());
886   task_runner_->RunPendingTasks();  // Run posted deadline.
887   EXPECT_EQ(2, client->num_draws());
888   EXPECT_FALSE(scheduler_->RedrawPending());
889   EXPECT_FALSE(client->needs_begin_frames());
890 }
891 
892 // Test that requesting redraw inside a failed draw doesn't lose the request.
TEST_F(SchedulerTest,RequestRedrawInsideFailedDraw)893 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
894   SchedulerClientThatsetNeedsDrawInsideDraw* client =
895       new SchedulerClientThatsetNeedsDrawInsideDraw;
896   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
897 
898   client->SetRequestRedrawsInsideDraw(true);
899   client->SetDrawWillHappen(false);
900 
901   scheduler_->SetNeedsRedraw();
902   EXPECT_TRUE(scheduler_->RedrawPending());
903   EXPECT_TRUE(client->needs_begin_frames());
904   EXPECT_EQ(0, client->num_draws());
905 
906   // Fail the draw.
907   EXPECT_SCOPED(AdvanceFrame());
908   task_runner_->RunPendingTasks();  // Run posted deadline.
909   EXPECT_EQ(1, client->num_draws());
910 
911   // We have a commit pending and the draw failed, and we didn't lose the redraw
912   // request.
913   EXPECT_TRUE(scheduler_->CommitPending());
914   EXPECT_TRUE(scheduler_->RedrawPending());
915   EXPECT_TRUE(client->needs_begin_frames());
916 
917   client->SetRequestRedrawsInsideDraw(false);
918 
919   // Fail the draw again.
920   EXPECT_SCOPED(AdvanceFrame());
921   task_runner_->RunPendingTasks();  // Run posted deadline.
922   EXPECT_EQ(2, client->num_draws());
923   EXPECT_TRUE(scheduler_->CommitPending());
924   EXPECT_TRUE(scheduler_->RedrawPending());
925   EXPECT_TRUE(client->needs_begin_frames());
926 
927   // Draw successfully.
928   client->SetDrawWillHappen(true);
929   EXPECT_SCOPED(AdvanceFrame());
930   task_runner_->RunPendingTasks();  // Run posted deadline.
931   EXPECT_EQ(3, client->num_draws());
932   EXPECT_TRUE(scheduler_->CommitPending());
933   EXPECT_FALSE(scheduler_->RedrawPending());
934   EXPECT_TRUE(client->needs_begin_frames());
935 }
936 
937 class SchedulerClientThatSetNeedsBeginMainFrameInsideDraw
938     : public FakeSchedulerClient {
939  public:
SchedulerClientThatSetNeedsBeginMainFrameInsideDraw()940   SchedulerClientThatSetNeedsBeginMainFrameInsideDraw()
941       : set_needs_commit_on_next_draw_(false) {}
942 
ScheduledActionDrawIfPossible()943   DrawResult ScheduledActionDrawIfPossible() override {
944     // Only SetNeedsBeginMainFrame the first time this is called
945     if (set_needs_commit_on_next_draw_) {
946       scheduler_->SetNeedsBeginMainFrame();
947       set_needs_commit_on_next_draw_ = false;
948     }
949     return FakeSchedulerClient::ScheduledActionDrawIfPossible();
950   }
951 
ScheduledActionDrawForced()952   DrawResult ScheduledActionDrawForced() override {
953     NOTREACHED();
954     return DRAW_SUCCESS;
955   }
956 
SetNeedsBeginMainFrameOnNextDraw()957   void SetNeedsBeginMainFrameOnNextDraw() {
958     set_needs_commit_on_next_draw_ = true;
959   }
960 
961  private:
962   bool set_needs_commit_on_next_draw_;
963 };
964 
965 // Tests for the scheduler infinite-looping on SetNeedsBeginMainFrame requests
966 // that happen inside a ScheduledActionDraw
TEST_F(SchedulerTest,RequestCommitInsideDraw)967 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
968   SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
969       new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
970   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
971 
972   EXPECT_FALSE(client->needs_begin_frames());
973   scheduler_->SetNeedsRedraw();
974   EXPECT_TRUE(scheduler_->RedrawPending());
975   EXPECT_EQ(0, client->num_draws());
976   EXPECT_TRUE(client->needs_begin_frames());
977 
978   client->SetNeedsBeginMainFrameOnNextDraw();
979   EXPECT_SCOPED(AdvanceFrame());
980   client->SetNeedsBeginMainFrameOnNextDraw();
981   task_runner_->RunPendingTasks();  // Run posted deadline.
982   EXPECT_EQ(1, client->num_draws());
983   EXPECT_TRUE(scheduler_->CommitPending());
984   EXPECT_TRUE(client->needs_begin_frames());
985   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
986   scheduler_->NotifyReadyToCommit(nullptr);
987   scheduler_->NotifyReadyToActivate();
988 
989   EXPECT_SCOPED(AdvanceFrame());
990   task_runner_->RunPendingTasks();  // Run posted deadline.
991   EXPECT_EQ(2, client->num_draws());
992 
993   EXPECT_FALSE(scheduler_->RedrawPending());
994   EXPECT_FALSE(scheduler_->CommitPending());
995   EXPECT_TRUE(client->needs_begin_frames());
996 
997   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
998   // swap.
999   EXPECT_SCOPED(AdvanceFrame());
1000   task_runner_->RunPendingTasks();  // Run posted deadline.
1001   EXPECT_EQ(2, client->num_draws());
1002   EXPECT_FALSE(scheduler_->RedrawPending());
1003   EXPECT_FALSE(scheduler_->CommitPending());
1004   EXPECT_FALSE(client->needs_begin_frames());
1005 }
1006 
1007 // Tests that when a draw fails then the pending commit should not be dropped.
TEST_F(SchedulerTest,RequestCommitInsideFailedDraw)1008 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
1009   SchedulerClientThatsetNeedsDrawInsideDraw* client =
1010       new SchedulerClientThatsetNeedsDrawInsideDraw;
1011   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1012 
1013   client->SetDrawWillHappen(false);
1014 
1015   scheduler_->SetNeedsRedraw();
1016   EXPECT_TRUE(scheduler_->RedrawPending());
1017   EXPECT_TRUE(client->needs_begin_frames());
1018   EXPECT_EQ(0, client->num_draws());
1019 
1020   // Fail the draw.
1021   EXPECT_SCOPED(AdvanceFrame());
1022   task_runner_->RunPendingTasks();  // Run posted deadline.
1023   EXPECT_EQ(1, client->num_draws());
1024 
1025   // We have a commit pending and the draw failed, and we didn't lose the commit
1026   // request.
1027   EXPECT_TRUE(scheduler_->CommitPending());
1028   EXPECT_TRUE(scheduler_->RedrawPending());
1029   EXPECT_TRUE(client->needs_begin_frames());
1030 
1031   // Fail the draw again.
1032   EXPECT_SCOPED(AdvanceFrame());
1033 
1034   task_runner_->RunPendingTasks();  // Run posted deadline.
1035   EXPECT_EQ(2, client->num_draws());
1036   EXPECT_TRUE(scheduler_->CommitPending());
1037   EXPECT_TRUE(scheduler_->RedrawPending());
1038   EXPECT_TRUE(client->needs_begin_frames());
1039 
1040   // Draw successfully.
1041   client->SetDrawWillHappen(true);
1042   EXPECT_SCOPED(AdvanceFrame());
1043   task_runner_->RunPendingTasks();  // Run posted deadline.
1044   EXPECT_EQ(3, client->num_draws());
1045   EXPECT_TRUE(scheduler_->CommitPending());
1046   EXPECT_FALSE(scheduler_->RedrawPending());
1047   EXPECT_TRUE(client->needs_begin_frames());
1048 }
1049 
TEST_F(SchedulerTest,NoSwapWhenDrawFails)1050 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
1051   SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
1052       new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
1053   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1054 
1055   scheduler_->SetNeedsRedraw();
1056   EXPECT_TRUE(scheduler_->RedrawPending());
1057   EXPECT_TRUE(client->needs_begin_frames());
1058   EXPECT_EQ(0, client->num_draws());
1059 
1060   // Draw successfully, this starts a new frame.
1061   client->SetNeedsBeginMainFrameOnNextDraw();
1062   EXPECT_SCOPED(AdvanceFrame());
1063   task_runner_->RunPendingTasks();  // Run posted deadline.
1064   EXPECT_EQ(1, client->num_draws());
1065 
1066   scheduler_->SetNeedsRedraw();
1067   EXPECT_TRUE(scheduler_->RedrawPending());
1068   EXPECT_TRUE(client->needs_begin_frames());
1069 
1070   // Fail to draw, this should not start a frame.
1071   client->SetDrawWillHappen(false);
1072   client->SetNeedsBeginMainFrameOnNextDraw();
1073   EXPECT_SCOPED(AdvanceFrame());
1074   task_runner_->RunPendingTasks();  // Run posted deadline.
1075   EXPECT_EQ(2, client->num_draws());
1076 }
1077 
1078 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
1079  public:
ScheduledActionDrawIfPossible()1080   DrawResult ScheduledActionDrawIfPossible() override {
1081     scheduler_->SetNeedsPrepareTiles();
1082     return FakeSchedulerClient::ScheduledActionDrawIfPossible();
1083   }
1084 };
1085 
1086 // Test prepare tiles is independant of draws.
TEST_F(SchedulerTest,PrepareTiles)1087 TEST_F(SchedulerTest, PrepareTiles) {
1088   SchedulerClientNeedsPrepareTilesInDraw* client =
1089       new SchedulerClientNeedsPrepareTilesInDraw;
1090   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1091 
1092   // Request both draw and prepare tiles. PrepareTiles shouldn't
1093   // be trigged until BeginImplFrame.
1094   client->Reset();
1095   scheduler_->SetNeedsPrepareTiles();
1096   scheduler_->SetNeedsRedraw();
1097   EXPECT_TRUE(scheduler_->RedrawPending());
1098   EXPECT_TRUE(scheduler_->PrepareTilesPending());
1099   EXPECT_TRUE(client->needs_begin_frames());
1100   EXPECT_EQ(0, client->num_draws());
1101   EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
1102   EXPECT_FALSE(client->HasAction("ScheduledActionDrawIfPossible"));
1103 
1104   // We have no immediate actions to perform, so the BeginImplFrame should post
1105   // the deadline task.
1106   client->Reset();
1107   EXPECT_SCOPED(AdvanceFrame());
1108   EXPECT_ACTIONS("WillBeginImplFrame");
1109   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1110 
1111   // On the deadline, the actions should have occured in the right order.
1112   client->Reset();
1113   task_runner_->RunPendingTasks();  // Run posted deadline.
1114   EXPECT_EQ(1, client->num_draws());
1115   EXPECT_TRUE(client->HasAction("ScheduledActionDrawIfPossible"));
1116   EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1117   EXPECT_LT(client->ActionIndex("ScheduledActionDrawIfPossible"),
1118             client->ActionIndex("ScheduledActionPrepareTiles"));
1119   EXPECT_FALSE(scheduler_->RedrawPending());
1120   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1121   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1122 
1123   // Request a draw. We don't need a PrepareTiles yet.
1124   client->Reset();
1125   scheduler_->SetNeedsRedraw();
1126   EXPECT_TRUE(scheduler_->RedrawPending());
1127   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1128   EXPECT_TRUE(client->needs_begin_frames());
1129   EXPECT_EQ(0, client->num_draws());
1130 
1131   // We have no immediate actions to perform, so the BeginImplFrame should post
1132   // the deadline task.
1133   client->Reset();
1134   EXPECT_SCOPED(AdvanceFrame());
1135   EXPECT_ACTIONS("WillBeginImplFrame");
1136   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1137 
1138   // Draw. The draw will trigger SetNeedsPrepareTiles, and
1139   // then the PrepareTiles action will be triggered after the Draw.
1140   // Afterwards, neither a draw nor PrepareTiles are pending.
1141   client->Reset();
1142   task_runner_->RunPendingTasks();  // Run posted deadline.
1143   EXPECT_EQ(1, client->num_draws());
1144   EXPECT_TRUE(client->HasAction("ScheduledActionDrawIfPossible"));
1145   EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1146   EXPECT_LT(client->ActionIndex("ScheduledActionDrawIfPossible"),
1147             client->ActionIndex("ScheduledActionPrepareTiles"));
1148   EXPECT_FALSE(scheduler_->RedrawPending());
1149   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1150   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1151 
1152   // We need a BeginImplFrame where we don't swap to go idle.
1153   client->Reset();
1154   EXPECT_SCOPED(AdvanceFrame());
1155   EXPECT_ACTIONS("WillBeginImplFrame");
1156   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1157   client->Reset();
1158   task_runner_->RunPendingTasks();  // Run posted deadline.
1159   EXPECT_ACTIONS("RemoveObserver(this)");
1160   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1161   EXPECT_EQ(0, client->num_draws());
1162 
1163   // Now trigger a PrepareTiles outside of a draw. We will then need
1164   // a begin-frame for the PrepareTiles, but we don't need a draw.
1165   client->Reset();
1166   EXPECT_FALSE(client->needs_begin_frames());
1167   scheduler_->SetNeedsPrepareTiles();
1168   EXPECT_TRUE(client->needs_begin_frames());
1169   EXPECT_TRUE(scheduler_->PrepareTilesPending());
1170   EXPECT_FALSE(scheduler_->RedrawPending());
1171 
1172   // BeginImplFrame. There will be no draw, only PrepareTiles.
1173   client->Reset();
1174   EXPECT_SCOPED(AdvanceFrame());
1175   EXPECT_ACTIONS("WillBeginImplFrame");
1176   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1177   client->Reset();
1178   task_runner_->RunPendingTasks();  // Run posted deadline.
1179   EXPECT_EQ(0, client->num_draws());
1180   EXPECT_FALSE(client->HasAction("ScheduledActionDrawIfPossible"));
1181   EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1182   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1183 }
1184 
1185 // Test that PrepareTiles only happens once per frame.  If an external caller
1186 // initiates it, then the state machine should not PrepareTiles on that frame.
TEST_F(SchedulerTest,PrepareTilesOncePerFrame)1187 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1188   SetUpScheduler(EXTERNAL_BFS);
1189 
1190   // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1191   // again.
1192   scheduler_->SetNeedsPrepareTiles();
1193   scheduler_->SetNeedsRedraw();
1194   client_->Reset();
1195   EXPECT_SCOPED(AdvanceFrame());
1196   EXPECT_ACTIONS("WillBeginImplFrame");
1197   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1198 
1199   EXPECT_TRUE(scheduler_->PrepareTilesPending());
1200   scheduler_->WillPrepareTiles();
1201   scheduler_->DidPrepareTiles();  // An explicit PrepareTiles.
1202   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1203 
1204   client_->Reset();
1205   task_runner_->RunPendingTasks();  // Run posted deadline.
1206   EXPECT_EQ(1, client_->num_draws());
1207   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1208   EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1209   EXPECT_FALSE(scheduler_->RedrawPending());
1210   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1211   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1212 
1213   // Next frame without DidPrepareTiles should PrepareTiles with draw.
1214   scheduler_->SetNeedsPrepareTiles();
1215   scheduler_->SetNeedsRedraw();
1216   client_->Reset();
1217   EXPECT_SCOPED(AdvanceFrame());
1218   EXPECT_ACTIONS("WillBeginImplFrame");
1219   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1220 
1221   client_->Reset();
1222   task_runner_->RunPendingTasks();  // Run posted deadline.
1223   EXPECT_EQ(1, client_->num_draws());
1224   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1225   EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1226   EXPECT_LT(client_->ActionIndex("ScheduledActionDrawIfPossible"),
1227             client_->ActionIndex("ScheduledActionPrepareTiles"));
1228   EXPECT_FALSE(scheduler_->RedrawPending());
1229   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1230   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1231 
1232   // If we get another DidPrepareTiles within the same frame, we should
1233   // not PrepareTiles on the next frame.
1234   scheduler_->WillPrepareTiles();
1235   scheduler_->DidPrepareTiles();  // An explicit PrepareTiles.
1236   scheduler_->SetNeedsPrepareTiles();
1237   scheduler_->SetNeedsRedraw();
1238   client_->Reset();
1239   EXPECT_SCOPED(AdvanceFrame());
1240   EXPECT_ACTIONS("WillBeginImplFrame");
1241   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1242 
1243   EXPECT_TRUE(scheduler_->PrepareTilesPending());
1244 
1245   client_->Reset();
1246   task_runner_->RunPendingTasks();  // Run posted deadline.
1247   EXPECT_EQ(1, client_->num_draws());
1248   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1249   EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1250   EXPECT_FALSE(scheduler_->RedrawPending());
1251   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1252 
1253   // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1254   // frame. This verifies we don't alternate calling PrepareTiles once and
1255   // twice.
1256   EXPECT_TRUE(scheduler_->PrepareTilesPending());
1257   scheduler_->WillPrepareTiles();
1258   scheduler_->DidPrepareTiles();  // An explicit PrepareTiles.
1259   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1260   scheduler_->SetNeedsPrepareTiles();
1261   scheduler_->SetNeedsRedraw();
1262   client_->Reset();
1263   EXPECT_SCOPED(AdvanceFrame());
1264   EXPECT_ACTIONS("WillBeginImplFrame");
1265   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1266 
1267   EXPECT_TRUE(scheduler_->PrepareTilesPending());
1268 
1269   client_->Reset();
1270   task_runner_->RunPendingTasks();  // Run posted deadline.
1271   EXPECT_EQ(1, client_->num_draws());
1272   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1273   EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1274   EXPECT_FALSE(scheduler_->RedrawPending());
1275   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1276 
1277   // Next frame without DidPrepareTiles should PrepareTiles with draw.
1278   scheduler_->SetNeedsPrepareTiles();
1279   scheduler_->SetNeedsRedraw();
1280   client_->Reset();
1281   EXPECT_SCOPED(AdvanceFrame());
1282   EXPECT_ACTIONS("WillBeginImplFrame");
1283   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1284 
1285   client_->Reset();
1286   task_runner_->RunPendingTasks();  // Run posted deadline.
1287   EXPECT_EQ(1, client_->num_draws());
1288   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1289   EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1290   EXPECT_LT(client_->ActionIndex("ScheduledActionDrawIfPossible"),
1291             client_->ActionIndex("ScheduledActionPrepareTiles"));
1292   EXPECT_FALSE(scheduler_->RedrawPending());
1293   EXPECT_FALSE(scheduler_->PrepareTilesPending());
1294   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1295 }
1296 
TEST_F(SchedulerTest,DidPrepareTilesPreventsPrepareTilesForOneFrame)1297 TEST_F(SchedulerTest, DidPrepareTilesPreventsPrepareTilesForOneFrame) {
1298   std::unique_ptr<SchedulerClientNeedsPrepareTilesInDraw> client =
1299       base::WrapUnique(new SchedulerClientNeedsPrepareTilesInDraw);
1300   SetUpScheduler(EXTERNAL_BFS, std::move(client));
1301 
1302   client_->Reset();
1303   scheduler_->SetNeedsRedraw();
1304   EXPECT_ACTIONS("AddObserver(this)");
1305 
1306   client_->Reset();
1307   EXPECT_SCOPED(AdvanceFrame());
1308   EXPECT_ACTIONS("WillBeginImplFrame");
1309   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1310 
1311   client_->Reset();
1312   task_runner_->RunPendingTasks();  // Run posted deadline.
1313   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1314   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
1315                  "ScheduledActionPrepareTiles");
1316 
1317   // We don't want to hinder scheduled prepare tiles for more than one frame
1318   // even if we call unscheduled prepare tiles many times.
1319   for (int i = 0; i < 10; i++) {
1320     scheduler_->WillPrepareTiles();
1321     scheduler_->DidPrepareTiles();
1322   }
1323 
1324   client_->Reset();
1325   scheduler_->SetNeedsRedraw();
1326   EXPECT_SCOPED(AdvanceFrame());
1327   EXPECT_ACTIONS("WillBeginImplFrame");
1328   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1329 
1330   // No scheduled prepare tiles because we've already counted a prepare tiles in
1331   // between frames.
1332   client_->Reset();
1333   task_runner_->RunPendingTasks();  // Run posted deadline.
1334   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1335   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
1336 
1337   client_->Reset();
1338   scheduler_->SetNeedsRedraw();
1339   EXPECT_SCOPED(AdvanceFrame());
1340   EXPECT_ACTIONS("WillBeginImplFrame");
1341   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1342 
1343   // Resume scheduled prepare tiles.
1344   client_->Reset();
1345   task_runner_->RunPendingTasks();  // Run posted deadline.
1346   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1347   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
1348                  "ScheduledActionPrepareTiles");
1349 }
1350 
TEST_F(SchedulerTest,TriggerBeginFrameDeadlineEarly)1351 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1352   SchedulerClientNeedsPrepareTilesInDraw* client =
1353       new SchedulerClientNeedsPrepareTilesInDraw;
1354   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1355 
1356   scheduler_->SetNeedsRedraw();
1357   EXPECT_SCOPED(AdvanceFrame());
1358 
1359   // The deadline should be zero since there is no work other than drawing
1360   // pending.
1361   EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1362 }
1363 
TEST_F(SchedulerTest,WaitForReadyToDrawDoNotPostDeadline)1364 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1365   SchedulerClientNeedsPrepareTilesInDraw* client =
1366       new SchedulerClientNeedsPrepareTilesInDraw;
1367   scheduler_settings_.commit_to_active_tree = true;
1368   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1369 
1370   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1371   scheduler_->SetNeedsBeginMainFrame();
1372   EXPECT_ACTIONS("AddObserver(this)");
1373   client_->Reset();
1374 
1375   // Begin new frame.
1376   EXPECT_SCOPED(AdvanceFrame());
1377   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1378   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1379 
1380   client_->Reset();
1381   scheduler_->NotifyReadyToCommit(nullptr);
1382   EXPECT_ACTIONS("ScheduledActionCommit");
1383 
1384   client_->Reset();
1385   scheduler_->NotifyReadyToActivate();
1386   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
1387 
1388   // Scheduler won't post deadline in the mode.
1389   client_->Reset();
1390   task_runner_->RunPendingTasks();  // Try to run posted deadline.
1391   // There is no posted deadline.
1392   EXPECT_NO_ACTION();
1393 
1394   // Scheduler received ready to draw signal, and posted deadline.
1395   scheduler_->NotifyReadyToDraw();
1396   client_->Reset();
1397   task_runner_->RunPendingTasks();  // Run posted deadline.
1398   EXPECT_EQ(1, client_->num_draws());
1399   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1400 }
1401 
TEST_F(SchedulerTest,WaitForReadyToDrawCancelledWhenLostLayerTreeFrameSink)1402 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostLayerTreeFrameSink) {
1403   SchedulerClientNeedsPrepareTilesInDraw* client =
1404       new SchedulerClientNeedsPrepareTilesInDraw;
1405   scheduler_settings_.commit_to_active_tree = true;
1406   SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1407 
1408   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1409   scheduler_->SetNeedsBeginMainFrame();
1410   EXPECT_ACTIONS("AddObserver(this)");
1411   client_->Reset();
1412 
1413   // Begin new frame.
1414   EXPECT_SCOPED(AdvanceFrame());
1415   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1416   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1417 
1418   client_->Reset();
1419   scheduler_->NotifyReadyToCommit(nullptr);
1420   EXPECT_ACTIONS("ScheduledActionCommit");
1421 
1422   client_->Reset();
1423   scheduler_->NotifyReadyToActivate();
1424   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
1425 
1426   // Scheduler won't post deadline in the mode.
1427   client_->Reset();
1428   task_runner_->RunPendingTasks();  // Try to run posted deadline.
1429   // There is no posted deadline.
1430   EXPECT_NO_ACTION();
1431 
1432   // Scheduler loses LayerTreeFrameSink, and stops waiting for ready to draw
1433   // signal.
1434   client_->Reset();
1435   scheduler_->DidLoseLayerTreeFrameSink();
1436   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1437   task_runner_->RunPendingTasks();  // Run posted deadline.
1438   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
1439                  "RemoveObserver(this)");
1440 }
1441 
AdvanceAndMissOneFrame()1442 void SchedulerTest::AdvanceAndMissOneFrame() {
1443   // Impl thread hits deadline before commit finishes.
1444   scheduler_->SetNeedsBeginMainFrame();
1445   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1446   EXPECT_SCOPED(AdvanceFrame());
1447   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1448   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1449   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1450   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1451   scheduler_->NotifyReadyToCommit(nullptr);
1452   scheduler_->NotifyReadyToActivate();
1453   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1454                  "ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
1455                  "ScheduledActionActivateSyncTree");
1456   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1457   client_->Reset();
1458 }
1459 
CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame)1460 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
1461     bool expect_send_begin_main_frame) {
1462   AdvanceAndMissOneFrame();
1463 
1464   scheduler_->SetNeedsBeginMainFrame();
1465   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1466   EXPECT_SCOPED(AdvanceFrame());
1467   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1468   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1469   EXPECT_EQ(expect_send_begin_main_frame,
1470             scheduler_->MainThreadMissedLastDeadline());
1471   EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
1472   EXPECT_EQ(expect_send_begin_main_frame,
1473             client_->HasAction("ScheduledActionSendBeginMainFrame"));
1474 }
1475 
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateBeginFrame)1476 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateBeginFrame) {
1477   // If a begin frame is delivered extremely late (because the browser has
1478   // some contention), make sure that the main frame is not skipped even
1479   // if it can activate before the deadline.
1480   SetUpScheduler(EXTERNAL_BFS);
1481   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1482 
1483   AdvanceAndMissOneFrame();
1484   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1485   scheduler_->SetNeedsBeginMainFrame();
1486 
1487   // Advance frame and create a begin frame.
1488   task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
1489   viz::BeginFrameArgs args =
1490       fake_external_begin_frame_source_->CreateBeginFrameArgs(
1491           BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
1492 
1493   // Deliver this begin frame super late.
1494   task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval() *
1495                                      100);
1496   fake_external_begin_frame_source_->TestOnBeginFrame(args);
1497 
1498   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1499   EXPECT_EQ(true, scheduler_->MainThreadMissedLastDeadline());
1500   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
1501                  "ScheduledActionDrawIfPossible");
1502 }
1503 
TEST_F(SchedulerTest,FrameIntervalUpdated)1504 TEST_F(SchedulerTest, FrameIntervalUpdated) {
1505   // Verify that the SchedulerClient gets updates when the begin frame interval
1506   // changes.
1507   SetUpScheduler(EXTERNAL_BFS);
1508   constexpr uint64_t kSourceId = viz::BeginFrameArgs::kStartingSourceId;
1509   uint64_t sequence_number = viz::BeginFrameArgs::kStartingFrameNumber;
1510 
1511   base::TimeDelta interval = base::TimeDelta::FromMicroseconds(
1512       base::Time::kMicrosecondsPerSecond / 120.0);
1513 
1514   // Send BeginFrameArgs with 120hz refresh rate and confirm client gets update.
1515   scheduler_->SetNeedsRedraw();
1516   task_runner_->AdvanceMockTickClock(interval);
1517   viz::BeginFrameArgs args1 = viz::BeginFrameArgs::Create(
1518       BEGINFRAME_FROM_HERE, kSourceId, sequence_number++,
1519       task_runner_->NowTicks(), task_runner_->NowTicks() + interval, interval,
1520       viz::BeginFrameArgs::NORMAL);
1521   fake_external_begin_frame_source_->TestOnBeginFrame(args1);
1522   EXPECT_EQ(client_->frame_interval(), interval);
1523 
1524   // Send another BeginFrameArgs with 120hz refresh rate that arrives late. Even
1525   // though the interval between begin frames arriving is bigger than |interval|
1526   // the client only hears the interval specified in BeginFrameArgs.
1527   scheduler_->SetNeedsRedraw();
1528   const base::TimeDelta late_delta = base::TimeDelta::FromMilliseconds(4);
1529   task_runner_->AdvanceMockTickClock(interval + late_delta);
1530   viz::BeginFrameArgs args2 = viz::BeginFrameArgs::Create(
1531       BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, args1.deadline,
1532       args1.deadline + interval, interval, viz::BeginFrameArgs::NORMAL);
1533   fake_external_begin_frame_source_->TestOnBeginFrame(args2);
1534   EXPECT_EQ(client_->frame_interval(), interval);
1535 
1536   // Change the interval for 90hz refresh rate.
1537   interval = base::TimeDelta::FromMicroseconds(
1538       base::Time::kMicrosecondsPerSecond / 90.0);
1539 
1540   // Send BeginFrameArgs with 90hz refresh rate and confirm client gets update.
1541   scheduler_->SetNeedsRedraw();
1542   task_runner_->AdvanceMockTickClock(args2.deadline - task_runner_->NowTicks());
1543   viz::BeginFrameArgs args3 = viz::BeginFrameArgs::Create(
1544       BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, args2.deadline,
1545       args2.deadline + interval, interval, viz::BeginFrameArgs::NORMAL);
1546   fake_external_begin_frame_source_->TestOnBeginFrame(args3);
1547   EXPECT_EQ(client_->frame_interval(), interval);
1548 
1549   // Send BeginFrameArgs with zero interval. This isn't a valid interval and
1550   // client shouldn't find out about it.
1551   scheduler_->SetNeedsRedraw();
1552   task_runner_->AdvanceMockTickClock(interval);
1553   viz::BeginFrameArgs args4 = viz::BeginFrameArgs::Create(
1554       BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, args3.deadline,
1555       args3.deadline + interval, base::TimeDelta(),
1556       viz::BeginFrameArgs::NORMAL);
1557   fake_external_begin_frame_source_->TestOnBeginFrame(args4);
1558   EXPECT_EQ(client_->frame_interval(), interval);
1559 }
1560 
TEST_F(SchedulerTest,MainFrameSkippedAfterLateCommit)1561 TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) {
1562   SetUpScheduler(EXTERNAL_BFS);
1563   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1564 
1565   bool expect_send_begin_main_frame = false;
1566   EXPECT_SCOPED(
1567       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1568 }
1569 
1570 // Response times of BeginMainFrame's without the critical path flag set
1571 // should not affect whether we recover latency or not.
TEST_F(SchedulerTest,MainFrameSkippedAfterLateCommit_LongMainFrameQueueDurationNotCritical)1572 TEST_F(SchedulerTest,
1573        MainFrameSkippedAfterLateCommit_LongMainFrameQueueDurationNotCritical) {
1574   SetUpScheduler(EXTERNAL_BFS);
1575   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1576   fake_compositor_timing_history_
1577       ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
1578 
1579   bool expect_send_begin_main_frame = false;
1580   EXPECT_SCOPED(
1581       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1582 }
1583 
1584 // Response times of BeginMainFrame's with the critical path flag set
1585 // should affect whether we recover latency or not.
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_LongMainFrameQueueDurationCritical)1586 TEST_F(SchedulerTest,
1587        MainFrameNotSkippedAfterLateCommit_LongMainFrameQueueDurationCritical) {
1588   SetUpScheduler(EXTERNAL_BFS);
1589   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1590   fake_compositor_timing_history_
1591       ->SetBeginMainFrameQueueDurationCriticalEstimate(kSlowDuration);
1592   fake_compositor_timing_history_
1593       ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
1594 
1595   bool expect_send_begin_main_frame = true;
1596   EXPECT_SCOPED(
1597       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1598 }
1599 
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode)1600 TEST_F(SchedulerTest,
1601        MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) {
1602   SetUpScheduler(EXTERNAL_BFS);
1603   scheduler_->SetTreePrioritiesAndScrollState(
1604       SMOOTHNESS_TAKES_PRIORITY,
1605       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
1606   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1607 
1608   bool expect_send_begin_main_frame = true;
1609   EXPECT_SCOPED(
1610       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1611 }
1612 
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong)1613 TEST_F(SchedulerTest,
1614        MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) {
1615   SetUpScheduler(EXTERNAL_BFS);
1616   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1617   fake_compositor_timing_history_
1618       ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(kSlowDuration);
1619 
1620   bool expect_send_begin_main_frame = true;
1621   EXPECT_SCOPED(
1622       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1623 }
1624 
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong)1625 TEST_F(SchedulerTest,
1626        MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) {
1627   SetUpScheduler(EXTERNAL_BFS);
1628   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1629   fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1630       kSlowDuration);
1631 
1632   bool expect_send_begin_main_frame = true;
1633   EXPECT_SCOPED(
1634       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1635 }
1636 
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong)1637 TEST_F(SchedulerTest,
1638        MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) {
1639   SetUpScheduler(EXTERNAL_BFS);
1640   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1641   fake_compositor_timing_history_->SetActivateDurationEstimate(kSlowDuration);
1642 
1643   bool expect_send_begin_main_frame = true;
1644   EXPECT_SCOPED(
1645       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1646 }
1647 
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong)1648 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) {
1649   SetUpScheduler(EXTERNAL_BFS);
1650   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1651   fake_compositor_timing_history_->SetDrawDurationEstimate(kSlowDuration);
1652 
1653   bool expect_send_begin_main_frame = true;
1654   EXPECT_SCOPED(
1655       CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1656 }
1657 
1658 // If the BeginMainFrame aborts, it doesn't actually insert a frame into the
1659 // queue, which means there is no latency to recover.
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateBeginMainFrameAbort)1660 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateBeginMainFrameAbort) {
1661   SetUpScheduler(EXTERNAL_BFS);
1662 
1663   // Use fast estimates so we think we can recover latency if needed.
1664   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1665 
1666   // Impl thread hits deadline before BeginMainFrame aborts.
1667   scheduler_->SetNeedsBeginMainFrame();
1668   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1669   EXPECT_SCOPED(AdvanceFrame());
1670   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1671                  "ScheduledActionSendBeginMainFrame");
1672   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1673   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1674   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1675   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1676   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1677 
1678   // After aborting the frame, make sure we don't skip the
1679   // next BeginMainFrame.
1680   client_->Reset();
1681   scheduler_->BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
1682   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1683   scheduler_->SetNeedsBeginMainFrame();
1684   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1685   EXPECT_SCOPED(AdvanceFrame());
1686   EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
1687   EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1688   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1689   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1690   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1691 }
1692 
1693 // If the BeginMainFrame aborts, it doesn't actually insert a frame into the
1694 // queue, which means there is no latency to recover.
TEST_F(SchedulerTest,MainFrameNotSkippedAfterCanDrawChanges)1695 TEST_F(SchedulerTest, MainFrameNotSkippedAfterCanDrawChanges) {
1696   SetUpScheduler(EXTERNAL_BFS);
1697 
1698   // Use fast estimates so we think we can recover latency if needed.
1699   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1700 
1701   // Impl thread hits deadline before BeginMainFrame aborts.
1702   scheduler_->SetNeedsBeginMainFrame();
1703   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1704   EXPECT_SCOPED(AdvanceFrame());
1705   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1706                  "ScheduledActionSendBeginMainFrame");
1707   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1708   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1709   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1710   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1711   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1712 
1713   // Make us abort the upcoming draw.
1714   client_->Reset();
1715   scheduler_->NotifyReadyToCommit(nullptr);
1716   scheduler_->NotifyReadyToActivate();
1717   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree");
1718   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1719   scheduler_->SetCanDraw(false);
1720   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1721 
1722   // Make CanDraw true after activation.
1723   client_->Reset();
1724   scheduler_->SetCanDraw(true);
1725   EXPECT_NO_ACTION();
1726   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1727 
1728   // Make sure we don't skip the next BeginMainFrame.
1729   client_->Reset();
1730   scheduler_->SetNeedsBeginMainFrame();
1731   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1732   EXPECT_SCOPED(AdvanceFrame());
1733   EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
1734   EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1735   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1736   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1737   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1738 }
1739 
TEST_F(SchedulerTest,MainFrameNotSkippedWhenNoTimingHistory)1740 TEST_F(SchedulerTest, MainFrameNotSkippedWhenNoTimingHistory) {
1741   SetUpScheduler(EXTERNAL_BFS);
1742 
1743   // Use fast estimates so we think we can recover latency if needed.
1744   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1745 
1746   // Impl thread hits deadline before BeginMainFrame commits.
1747   scheduler_->SetNeedsBeginMainFrame();
1748   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1749   EXPECT_SCOPED(AdvanceFrame());
1750   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1751                  "ScheduledActionSendBeginMainFrame");
1752   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1753   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1754   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1755   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1756   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1757 
1758   // Commit after the deadline.
1759   client_->Reset();
1760   scheduler_->NotifyReadyToCommit(nullptr);
1761   scheduler_->NotifyReadyToActivate();
1762   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree");
1763   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1764 
1765   // Clear the timing history. Make sure we don't skip the main frame until we
1766   // have history from at least one frame.
1767   client_->Reset();
1768   scheduler_->SetNeedsBeginMainFrame();
1769   scheduler_->ClearHistory();
1770   EXPECT_SCOPED(AdvanceFrame());
1771   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1772 }
1773 
ImplFrameSkippedAfterLateAck(bool is_already_receiving_begin_frames,bool receive_ack_before_deadline)1774 void SchedulerTest::ImplFrameSkippedAfterLateAck(
1775     bool is_already_receiving_begin_frames,
1776     bool receive_ack_before_deadline) {
1777   // To get into a high latency state, this test disables automatic swap acks.
1778   client_->SetAutomaticSubmitCompositorFrameAck(false);
1779 
1780   // Draw and swap for first BeginFrame
1781   client_->Reset();
1782   scheduler_->SetNeedsBeginMainFrame();
1783   scheduler_->SetNeedsRedraw();
1784   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1785   SendNextBeginFrame();
1786   if (is_already_receiving_begin_frames) {
1787     EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1788   } else {
1789     EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1790                    "ScheduledActionSendBeginMainFrame");
1791   }
1792 
1793   client_->Reset();
1794   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1795   scheduler_->NotifyReadyToCommit(nullptr);
1796   scheduler_->NotifyReadyToActivate();
1797   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1798   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1799   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
1800                  "ScheduledActionDrawIfPossible");
1801 
1802   // Verify we skip every other frame if the swap ack consistently
1803   // comes back late.
1804   for (int i = 0; i < 10; i++) {
1805     // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
1806     // BeginImplFrame puts the impl thread in high latency mode.
1807     client_->Reset();
1808     scheduler_->SetNeedsBeginMainFrame();
1809     scheduler_->SetNeedsRedraw();
1810     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1811     SendNextBeginFrame();
1812     // Verify that we skip the BeginImplFrame
1813     EXPECT_NO_ACTION();
1814     EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1815     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1816 
1817     // Verify that we do not perform any actions after we are no longer
1818     // swap throttled.
1819     client_->Reset();
1820     if (receive_ack_before_deadline) {
1821       // It shouldn't matter if the swap ack comes back before the deadline...
1822       scheduler_->DidReceiveCompositorFrameAck();
1823       task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1824     } else {
1825       // ... or after the deadline.
1826       task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1827       scheduler_->DidReceiveCompositorFrameAck();
1828     }
1829     EXPECT_NO_ACTION();
1830 
1831     // Verify that we start the next BeginImplFrame and continue normally
1832     // after having just skipped a BeginImplFrame.
1833     client_->Reset();
1834     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1835     SendNextBeginFrame();
1836     EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1837 
1838     client_->Reset();
1839     scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1840     scheduler_->NotifyReadyToCommit(nullptr);
1841     scheduler_->NotifyReadyToActivate();
1842     task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1843     EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
1844                    "ScheduledActionDrawIfPossible");
1845   }
1846 }
1847 
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_FastEstimates_SubmitAckThenDeadline)1848 TEST_F(SchedulerTest,
1849        ImplFrameSkippedAfterLateAck_FastEstimates_SubmitAckThenDeadline) {
1850   SetUpScheduler(EXTERNAL_BFS);
1851   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1852 
1853   bool is_already_receiving_begin_frames = false;
1854   bool receive_ack_before_deadline = true;
1855   EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1856                                              receive_ack_before_deadline));
1857 }
1858 
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_FastEstimates_DeadlineThenSubmitAck)1859 TEST_F(SchedulerTest,
1860        ImplFrameSkippedAfterLateAck_FastEstimates_DeadlineThenSubmitAck) {
1861   SetUpScheduler(EXTERNAL_BFS);
1862   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1863 
1864   bool is_already_receiving_begin_frames = false;
1865   bool receive_ack_before_deadline = false;
1866   EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1867                                              receive_ack_before_deadline));
1868 }
1869 
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_LongMainFrameQueueDurationNotCritical)1870 TEST_F(SchedulerTest,
1871        ImplFrameSkippedAfterLateAck_LongMainFrameQueueDurationNotCritical) {
1872   SetUpScheduler(EXTERNAL_BFS);
1873   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1874   fake_compositor_timing_history_
1875       ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
1876 
1877   bool is_already_receiving_begin_frames = false;
1878   bool receive_ack_before_deadline = false;
1879   EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1880                                              receive_ack_before_deadline));
1881 }
1882 
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_ImplLatencyTakesPriority)1883 TEST_F(SchedulerTest, ImplFrameSkippedAfterLateAck_ImplLatencyTakesPriority) {
1884   SetUpScheduler(EXTERNAL_BFS);
1885 
1886   // Even if every estimate related to the main thread is slow, we should
1887   // still expect to recover impl thread latency if the draw is fast and we
1888   // are in impl latency takes priority.
1889   client_->Reset();
1890   scheduler_->SetTreePrioritiesAndScrollState(
1891       SMOOTHNESS_TAKES_PRIORITY,
1892       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
1893   fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
1894   fake_compositor_timing_history_->SetDrawDurationEstimate(kFastDuration);
1895   EXPECT_ACTIONS("AddObserver(this)");
1896 
1897   bool is_already_receiving_begin_frames = true;
1898   bool receive_ack_before_deadline = false;
1899   EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1900                                              receive_ack_before_deadline));
1901 }
1902 
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_OnlyImplSideUpdatesExpected)1903 TEST_F(SchedulerTest,
1904        ImplFrameSkippedAfterLateAck_OnlyImplSideUpdatesExpected) {
1905   // This tests that we recover impl thread latency when there are no commits.
1906   SetUpScheduler(EXTERNAL_BFS);
1907 
1908   // To get into a high latency state, this test disables automatic swap acks.
1909   client_->SetAutomaticSubmitCompositorFrameAck(false);
1910 
1911   // Even if every estimate related to the main thread is slow, we should
1912   // still expect to recover impl thread latency if there are no commits from
1913   // the main thread.
1914   fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
1915   fake_compositor_timing_history_->SetDrawDurationEstimate(kFastDuration);
1916 
1917   // Draw and swap for first BeginFrame
1918   client_->Reset();
1919   scheduler_->SetNeedsRedraw();
1920   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1921   SendNextBeginFrame();
1922   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame");
1923 
1924   client_->Reset();
1925   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1926   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1927   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
1928 
1929   // Verify we skip every other frame if the swap ack consistently
1930   // comes back late.
1931   for (int i = 0; i < 10; i++) {
1932     // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
1933     // BeginImplFrame puts the impl thread in high latency mode.
1934     client_->Reset();
1935     scheduler_->SetNeedsRedraw();
1936     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1937     SendNextBeginFrame();
1938     // Verify that we skip the BeginImplFrame
1939     EXPECT_NO_ACTION();
1940     EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1941     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1942 
1943     // Verify that we do not perform any actions after we are no longer
1944     // swap throttled.
1945     client_->Reset();
1946     scheduler_->DidReceiveCompositorFrameAck();
1947     EXPECT_NO_ACTION();
1948 
1949     // Verify that we start the next BeginImplFrame and continue normally
1950     // after having just skipped a BeginImplFrame.
1951     client_->Reset();
1952     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1953     SendNextBeginFrame();
1954     EXPECT_ACTIONS("WillBeginImplFrame");
1955 
1956     client_->Reset();
1957     // Deadline should be immediate.
1958     EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1959     task_runner_->RunUntilTime(task_runner_->NowTicks());
1960     EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1961     EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
1962   }
1963 }
1964 
ImplFrameNotSkippedAfterLateAck()1965 void SchedulerTest::ImplFrameNotSkippedAfterLateAck() {
1966   // To get into a high latency state, this test disables automatic swap acks.
1967   client_->SetAutomaticSubmitCompositorFrameAck(false);
1968 
1969   // Draw and swap for first BeginFrame
1970   client_->Reset();
1971   scheduler_->SetNeedsBeginMainFrame();
1972   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1973   SendNextBeginFrame();
1974   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1975                  "ScheduledActionSendBeginMainFrame");
1976 
1977   client_->Reset();
1978   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1979   scheduler_->NotifyReadyToCommit(nullptr);
1980   scheduler_->NotifyReadyToActivate();
1981   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1982   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1983   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
1984                  "ScheduledActionDrawIfPossible");
1985 
1986   // Verify impl thread consistently operates in high latency mode
1987   // without skipping any frames.
1988   for (int i = 0; i < 10; i++) {
1989     // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
1990     // frame
1991     // puts the impl thread in high latency mode.
1992     client_->Reset();
1993     scheduler_->SetNeedsBeginMainFrame();
1994     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1995     SendNextBeginFrame();
1996     EXPECT_ACTIONS("WillBeginImplFrame");
1997     EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1998     EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1999 
2000     client_->Reset();
2001     scheduler_->DidReceiveCompositorFrameAck();
2002     scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2003     scheduler_->NotifyReadyToCommit(nullptr);
2004     scheduler_->NotifyReadyToActivate();
2005     task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2006 
2007     // Verify that we don't skip the actions of the BeginImplFrame
2008     EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
2009                    "ScheduledActionActivateSyncTree",
2010                    "ScheduledActionDrawIfPossible");
2011   }
2012 }
2013 
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_MainFrameQueueDurationCriticalTooLong)2014 TEST_F(SchedulerTest,
2015        ImplFrameNotSkippedAfterLateAck_MainFrameQueueDurationCriticalTooLong) {
2016   SetUpScheduler(EXTERNAL_BFS);
2017   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2018   fake_compositor_timing_history_
2019       ->SetBeginMainFrameQueueDurationCriticalEstimate(kSlowDuration);
2020   fake_compositor_timing_history_
2021       ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
2022   EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2023 }
2024 
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_CommitEstimateTooLong)2025 TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateAck_CommitEstimateTooLong) {
2026   SetUpScheduler(EXTERNAL_BFS);
2027   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2028   fake_compositor_timing_history_
2029       ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(kSlowDuration);
2030   EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2031 }
2032 
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_ReadyToActivateEstimateTooLong)2033 TEST_F(SchedulerTest,
2034        ImplFrameNotSkippedAfterLateAck_ReadyToActivateEstimateTooLong) {
2035   SetUpScheduler(EXTERNAL_BFS);
2036   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2037   fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
2038       kSlowDuration);
2039   EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2040 }
2041 
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_ActivateEstimateTooLong)2042 TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateAck_ActivateEstimateTooLong) {
2043   SetUpScheduler(EXTERNAL_BFS);
2044   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2045   fake_compositor_timing_history_->SetActivateDurationEstimate(kSlowDuration);
2046   EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2047 }
2048 
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_DrawEstimateTooLong)2049 TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateAck_DrawEstimateTooLong) {
2050   SetUpScheduler(EXTERNAL_BFS);
2051   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2052   fake_compositor_timing_history_->SetDrawDurationEstimate(kSlowDuration);
2053   EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2054 }
2055 
TEST_F(SchedulerTest,MainFrameThenImplFrameSkippedAfterLateCommitAndLateAck)2056 TEST_F(SchedulerTest, MainFrameThenImplFrameSkippedAfterLateCommitAndLateAck) {
2057   // Set up client with custom estimates.
2058   // This test starts off with expensive estimates to prevent latency recovery
2059   // initially, then lowers the estimates to enable it once both the main
2060   // and impl threads are in a high latency mode.
2061   SetUpScheduler(EXTERNAL_BFS);
2062   fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
2063 
2064   // To get into a high latency state, this test disables automatic swap acks.
2065   client_->SetAutomaticSubmitCompositorFrameAck(false);
2066 
2067   // Impl thread hits deadline before commit finishes to make
2068   // MainThreadMissedLastDeadline true
2069   client_->Reset();
2070   scheduler_->SetNeedsBeginMainFrame();
2071   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2072   EXPECT_SCOPED(AdvanceFrame());
2073   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2074   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2075   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2076   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2077   scheduler_->NotifyReadyToCommit(nullptr);
2078   scheduler_->NotifyReadyToActivate();
2079   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2080 
2081   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
2082                  "ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
2083                  "ScheduledActionActivateSyncTree");
2084 
2085   // Draw and swap for first commit, start second commit.
2086   client_->Reset();
2087   scheduler_->SetNeedsBeginMainFrame();
2088   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2089   EXPECT_SCOPED(AdvanceFrame());
2090   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2091   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2092   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2093   scheduler_->NotifyReadyToCommit(nullptr);
2094   scheduler_->NotifyReadyToActivate();
2095 
2096   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2097                  "ScheduledActionDrawIfPossible", "ScheduledActionCommit",
2098                  "ScheduledActionActivateSyncTree");
2099 
2100   // Don't call scheduler_->DidReceiveCompositorFrameAck() until after next
2101   // frame
2102   // to put the impl thread in a high latency mode.
2103   client_->Reset();
2104   scheduler_->SetNeedsBeginMainFrame();
2105   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2106   EXPECT_SCOPED(AdvanceFrame());
2107   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2108   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2109 
2110   EXPECT_ACTIONS("WillBeginImplFrame");
2111   // Note: BeginMainFrame and swap are skipped here because of
2112   // swap ack backpressure, not because of latency recovery.
2113   EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
2114   EXPECT_FALSE(client_->HasAction("ScheduledActionDrawIfPossible"));
2115   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2116 
2117   // Lower estimates so that the scheduler will attempt latency recovery.
2118   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2119 
2120   // Now that both threads are in a high latency mode, make sure we
2121   // skip the BeginMainFrame, then the BeginImplFrame, but not both
2122   // at the same time.
2123 
2124   // Verify we skip BeginMainFrame first.
2125   client_->Reset();
2126   // Previous commit request is still outstanding.
2127   EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
2128   EXPECT_TRUE(scheduler_->IsDrawThrottled());
2129   SendNextBeginFrame();
2130   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2131   scheduler_->DidReceiveCompositorFrameAck();
2132   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2133 
2134   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2135   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
2136 
2137   // Verify we skip the BeginImplFrame second.
2138   client_->Reset();
2139   // Previous commit request is still outstanding.
2140   EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
2141   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2142   SendNextBeginFrame();
2143   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2144   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2145   scheduler_->DidReceiveCompositorFrameAck();
2146   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2147 
2148   EXPECT_NO_ACTION();
2149 
2150   // Then verify we operate in a low latency mode.
2151   client_->Reset();
2152   // Previous commit request is still outstanding.
2153   EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
2154   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2155   SendNextBeginFrame();
2156   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2157   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2158   scheduler_->NotifyReadyToCommit(nullptr);
2159   scheduler_->NotifyReadyToActivate();
2160   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2161   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2162   scheduler_->DidReceiveCompositorFrameAck();
2163   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2164 
2165   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2166                  "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2167                  "ScheduledActionDrawIfPossible");
2168 }
2169 
BeginFramesNotFromClient(BeginFrameSourceType bfs_type)2170 void SchedulerTest::BeginFramesNotFromClient(BeginFrameSourceType bfs_type) {
2171   SetUpScheduler(bfs_type);
2172 
2173   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame
2174   // without calling SetNeedsBeginFrame.
2175   scheduler_->SetNeedsBeginMainFrame();
2176   EXPECT_NO_ACTION();
2177   client_->Reset();
2178 
2179   EXPECT_SCOPED(AdvanceFrame());
2180   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2181   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2182   client_->Reset();
2183 
2184   // Can't run the deadline task because it can race with begin frame for the
2185   // SyntheticBFS case.
2186   EXPECT_SCOPED(AdvanceFrame());
2187   EXPECT_ACTIONS("WillBeginImplFrame");
2188   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2189   client_->Reset();
2190 
2191   // NotifyReadyToCommit should trigger the commit.
2192   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2193   scheduler_->NotifyReadyToCommit(nullptr);
2194   EXPECT_ACTIONS("ScheduledActionCommit");
2195   client_->Reset();
2196 
2197   // NotifyReadyToActivate should trigger the activation.
2198   scheduler_->NotifyReadyToActivate();
2199   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2200   client_->Reset();
2201 
2202   // BeginImplFrame deadline should draw. The following BeginImplFrame deadline
2203   // should SetNeedsBeginFrame(false) to avoid excessive toggles.
2204   EXPECT_SCOPED(AdvanceFrame());
2205   EXPECT_ACTIONS("ScheduledActionDrawIfPossible", "WillBeginImplFrame");
2206   client_->Reset();
2207 
2208   // Make sure SetNeedsBeginFrame isn't called on the client
2209   // when the BeginFrame is no longer needed.
2210   task_runner_->RunPendingTasks();  // Run posted deadline.
2211   EXPECT_NO_ACTION();
2212   client_->Reset();
2213 }
2214 
TEST_F(SchedulerTest,SyntheticBeginFrames)2215 TEST_F(SchedulerTest, SyntheticBeginFrames) {
2216   BeginFramesNotFromClient(THROTTLED_BFS);
2217 }
2218 
TEST_F(SchedulerTest,UnthrottledBeginFrames)2219 TEST_F(SchedulerTest, UnthrottledBeginFrames) {
2220   BeginFramesNotFromClient(UNTHROTTLED_BFS);
2221 }
2222 
BeginFramesNotFromClient_IsDrawThrottled(BeginFrameSourceType bfs_type)2223 void SchedulerTest::BeginFramesNotFromClient_IsDrawThrottled(
2224     BeginFrameSourceType bfs_type) {
2225   SetUpScheduler(bfs_type);
2226 
2227   // Set the draw duration estimate to zero so that deadlines are accurate.
2228   fake_compositor_timing_history_->SetDrawDurationEstimate(base::TimeDelta());
2229 
2230   // To test swap ack throttling, this test disables automatic swap acks.
2231   client_->SetAutomaticSubmitCompositorFrameAck(false);
2232 
2233   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2234   client_->Reset();
2235   scheduler_->SetNeedsBeginMainFrame();
2236   EXPECT_NO_ACTION();
2237   client_->Reset();
2238 
2239   // Trigger the first BeginImplFrame and BeginMainFrame
2240   EXPECT_SCOPED(AdvanceFrame());
2241   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2242   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2243   client_->Reset();
2244 
2245   // NotifyReadyToCommit should trigger the pending commit.
2246   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2247   scheduler_->NotifyReadyToCommit(nullptr);
2248   EXPECT_ACTIONS("ScheduledActionCommit");
2249   client_->Reset();
2250 
2251   // NotifyReadyToActivate should trigger the activation and draw.
2252   scheduler_->NotifyReadyToActivate();
2253   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2254   client_->Reset();
2255 
2256   // Swapping will put us into a swap throttled state.
2257   // Run posted deadline.
2258   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2259   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2260   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2261   client_->Reset();
2262 
2263   // While swap throttled, BeginFrames should trigger BeginImplFrames,
2264   // but not a BeginMainFrame or draw.
2265   scheduler_->SetNeedsBeginMainFrame();
2266   scheduler_->SetNeedsRedraw();
2267   EXPECT_SCOPED(AdvanceFrame());  // Run posted BeginFrame.
2268   EXPECT_ACTIONS("WillBeginImplFrame");
2269   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2270   client_->Reset();
2271 
2272   base::TimeTicks before_deadline, after_deadline;
2273 
2274   // The deadline is set to the regular deadline.
2275   before_deadline = task_runner_->NowTicks();
2276   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2277   after_deadline = task_runner_->NowTicks();
2278   // We can't do an equality comparison here because the scheduler uses a fudge
2279   // factor that's an internal implementation detail.
2280   EXPECT_GT(after_deadline, before_deadline);
2281   EXPECT_LT(after_deadline,
2282             before_deadline + viz::BeginFrameArgs::DefaultInterval());
2283   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2284   client_->Reset();
2285 
2286   EXPECT_SCOPED(AdvanceFrame());  // Run posted BeginFrame.
2287   EXPECT_ACTIONS("WillBeginImplFrame");
2288   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2289   client_->Reset();
2290 
2291   // Take us out of a swap throttled state.
2292   scheduler_->DidReceiveCompositorFrameAck();
2293   EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
2294   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2295   client_->Reset();
2296 
2297   // The deadline is set to the regular deadline.
2298   before_deadline = task_runner_->NowTicks();
2299   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2300   after_deadline = task_runner_->NowTicks();
2301   // We can't do an equality comparison here because the scheduler uses a fudge
2302   // factor that's an internal implementation detail.
2303   EXPECT_GT(after_deadline, before_deadline);
2304   EXPECT_LT(after_deadline,
2305             before_deadline + viz::BeginFrameArgs::DefaultInterval());
2306   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2307   client_->Reset();
2308 }
2309 
TEST_F(SchedulerTest,SyntheticBeginFrames_IsDrawThrottled)2310 TEST_F(SchedulerTest, SyntheticBeginFrames_IsDrawThrottled) {
2311   BeginFramesNotFromClient_IsDrawThrottled(THROTTLED_BFS);
2312 }
2313 
TEST_F(SchedulerTest,UnthrottledBeginFrames_IsDrawThrottled)2314 TEST_F(SchedulerTest, UnthrottledBeginFrames_IsDrawThrottled) {
2315   BeginFramesNotFromClient_IsDrawThrottled(UNTHROTTLED_BFS);
2316 }
2317 
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterLayerTreeFrameSinkIsInitialized)2318 TEST_F(SchedulerTest,
2319        DidLoseLayerTreeFrameSinkAfterLayerTreeFrameSinkIsInitialized) {
2320   SetUpSchedulerWithNoLayerTreeFrameSink(EXTERNAL_BFS);
2321 
2322   scheduler_->SetVisible(true);
2323   scheduler_->SetCanDraw(true);
2324 
2325   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
2326   client_->Reset();
2327   scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
2328   EXPECT_NO_ACTION();
2329 
2330   scheduler_->DidLoseLayerTreeFrameSink();
2331   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
2332 }
2333 
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterBeginFrameStarted)2334 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkAfterBeginFrameStarted) {
2335   SetUpScheduler(EXTERNAL_BFS);
2336 
2337   // SetNeedsBeginMainFrame should begin the frame.
2338   scheduler_->SetNeedsBeginMainFrame();
2339   EXPECT_ACTIONS("AddObserver(this)");
2340 
2341   client_->Reset();
2342   EXPECT_SCOPED(AdvanceFrame());
2343   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2344   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2345 
2346   client_->Reset();
2347   scheduler_->DidLoseLayerTreeFrameSink();
2348   // RemoveObserver(this) is not called until the end of the frame.
2349   EXPECT_NO_ACTION();
2350 
2351   client_->Reset();
2352   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2353   scheduler_->NotifyReadyToCommit(nullptr);
2354   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree");
2355 
2356   client_->Reset();
2357   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2358   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2359                  "RemoveObserver(this)");
2360 }
2361 
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterBeginFrameStartedWithHighLatency)2362 TEST_F(SchedulerTest,
2363        DidLoseLayerTreeFrameSinkAfterBeginFrameStartedWithHighLatency) {
2364   SetUpScheduler(EXTERNAL_BFS);
2365 
2366   // SetNeedsBeginMainFrame should begin the frame.
2367   scheduler_->SetNeedsBeginMainFrame();
2368   EXPECT_ACTIONS("AddObserver(this)");
2369 
2370   client_->Reset();
2371   EXPECT_SCOPED(AdvanceFrame());
2372   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2373   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2374 
2375   client_->Reset();
2376   scheduler_->DidLoseLayerTreeFrameSink();
2377   // Do nothing when impl frame is in deadine pending state.
2378   EXPECT_NO_ACTION();
2379 
2380   client_->Reset();
2381   // Run posted deadline.
2382   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2383   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2384   // OnBeginImplFrameDeadline didn't schedule LayerTreeFrameSink creation
2385   // because
2386   // main frame is not yet completed.
2387   EXPECT_ACTIONS("RemoveObserver(this)");
2388   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2389 
2390   // BeginImplFrame is not started.
2391   client_->Reset();
2392   task_runner_->RunUntilTime(task_runner_->NowTicks() +
2393                              base::TimeDelta::FromMilliseconds(10));
2394   EXPECT_NO_ACTION();
2395   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2396 
2397   client_->Reset();
2398   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2399   scheduler_->NotifyReadyToCommit(nullptr);
2400   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2401                  "ScheduledActionBeginLayerTreeFrameSinkCreation");
2402 }
2403 
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterReadyToCommit)2404 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkAfterReadyToCommit) {
2405   SetUpScheduler(EXTERNAL_BFS);
2406 
2407   // SetNeedsBeginMainFrame should begin the frame.
2408   scheduler_->SetNeedsBeginMainFrame();
2409   EXPECT_ACTIONS("AddObserver(this)");
2410 
2411   client_->Reset();
2412   EXPECT_SCOPED(AdvanceFrame());
2413   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2414   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2415 
2416   client_->Reset();
2417   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2418   scheduler_->NotifyReadyToCommit(nullptr);
2419   EXPECT_ACTIONS("ScheduledActionCommit");
2420 
2421   client_->Reset();
2422   scheduler_->DidLoseLayerTreeFrameSink();
2423   // Sync tree should be forced to activate.
2424   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2425 
2426   // RemoveObserver(this) is not called until the end of the frame.
2427   client_->Reset();
2428   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2429   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2430                  "RemoveObserver(this)");
2431 }
2432 
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterSetNeedsPrepareTiles)2433 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkAfterSetNeedsPrepareTiles) {
2434   SetUpScheduler(EXTERNAL_BFS);
2435 
2436   scheduler_->SetNeedsPrepareTiles();
2437   scheduler_->SetNeedsRedraw();
2438   EXPECT_ACTIONS("AddObserver(this)");
2439 
2440   client_->Reset();
2441   EXPECT_SCOPED(AdvanceFrame());
2442   EXPECT_ACTIONS("WillBeginImplFrame");
2443   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2444 
2445   client_->Reset();
2446   scheduler_->DidLoseLayerTreeFrameSink();
2447   // RemoveObserver(this) is not called until the end of the frame.
2448   EXPECT_NO_ACTION();
2449 
2450   client_->Reset();
2451   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2452   EXPECT_ACTIONS("ScheduledActionPrepareTiles",
2453                  "ScheduledActionBeginLayerTreeFrameSinkCreation",
2454                  "RemoveObserver(this)");
2455 }
2456 
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkWithDelayBasedBeginFrameSource)2457 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkWithDelayBasedBeginFrameSource) {
2458   SetUpScheduler(THROTTLED_BFS);
2459 
2460   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2461   EXPECT_FALSE(scheduler_->begin_frames_expected());
2462   scheduler_->SetNeedsBeginMainFrame();
2463   EXPECT_TRUE(scheduler_->begin_frames_expected());
2464 
2465   client_->Reset();
2466   AdvanceFrame();
2467   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2468   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2469   EXPECT_TRUE(scheduler_->begin_frames_expected());
2470 
2471   // NotifyReadyToCommit should trigger the commit.
2472   client_->Reset();
2473   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2474   scheduler_->NotifyReadyToCommit(nullptr);
2475   EXPECT_ACTIONS("ScheduledActionCommit");
2476   EXPECT_TRUE(scheduler_->begin_frames_expected());
2477 
2478   // NotifyReadyToActivate should trigger the activation.
2479   client_->Reset();
2480   scheduler_->NotifyReadyToActivate();
2481   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2482   EXPECT_TRUE(scheduler_->begin_frames_expected());
2483 
2484   client_->Reset();
2485   scheduler_->DidLoseLayerTreeFrameSink();
2486   // RemoveObserver(this) is not called until the end of the frame.
2487   EXPECT_NO_ACTION();
2488   EXPECT_TRUE(scheduler_->begin_frames_expected());
2489 
2490   client_->Reset();
2491   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2492   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
2493   EXPECT_FALSE(scheduler_->begin_frames_expected());
2494 }
2495 
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkWhenIdle)2496 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkWhenIdle) {
2497   SetUpScheduler(EXTERNAL_BFS);
2498 
2499   // SetNeedsBeginMainFrame should begin the frame.
2500   scheduler_->SetNeedsBeginMainFrame();
2501   EXPECT_ACTIONS("AddObserver(this)");
2502 
2503   client_->Reset();
2504   EXPECT_SCOPED(AdvanceFrame());
2505   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2506   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2507 
2508   client_->Reset();
2509   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2510   scheduler_->NotifyReadyToCommit(nullptr);
2511   EXPECT_ACTIONS("ScheduledActionCommit");
2512 
2513   client_->Reset();
2514   scheduler_->NotifyReadyToActivate();
2515   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2516 
2517   client_->Reset();
2518   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2519   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2520 
2521   // Idle time between BeginFrames.
2522   client_->Reset();
2523   scheduler_->DidLoseLayerTreeFrameSink();
2524   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2525                  "RemoveObserver(this)");
2526 }
2527 
TEST_F(SchedulerTest,ScheduledActionActivateAfterBecomingInvisible)2528 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2529   SetUpScheduler(EXTERNAL_BFS);
2530 
2531   // SetNeedsBeginMainFrame should begin the frame.
2532   scheduler_->SetNeedsBeginMainFrame();
2533   EXPECT_ACTIONS("AddObserver(this)");
2534 
2535   client_->Reset();
2536   EXPECT_SCOPED(AdvanceFrame());
2537   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2538   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2539 
2540   client_->Reset();
2541   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2542   scheduler_->NotifyReadyToCommit(nullptr);
2543   EXPECT_ACTIONS("ScheduledActionCommit");
2544   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2545 
2546   client_->Reset();
2547   scheduler_->SetVisible(false);
2548   task_runner_->RunPendingTasks();  // Run posted deadline.
2549 
2550   // Sync tree should be forced to activate.
2551   EXPECT_ACTIONS("ScheduledActionActivateSyncTree", "RemoveObserver(this)");
2552 }
2553 
TEST_F(SchedulerTest,ScheduledActionActivateAfterBeginFrameSourcePaused)2554 TEST_F(SchedulerTest, ScheduledActionActivateAfterBeginFrameSourcePaused) {
2555   SetUpScheduler(EXTERNAL_BFS);
2556 
2557   // SetNeedsBeginMainFrame should begin the frame.
2558   scheduler_->SetNeedsBeginMainFrame();
2559   EXPECT_ACTIONS("AddObserver(this)");
2560 
2561   client_->Reset();
2562   EXPECT_SCOPED(AdvanceFrame());
2563   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2564   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2565 
2566   client_->Reset();
2567   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2568   scheduler_->NotifyReadyToCommit(nullptr);
2569   EXPECT_ACTIONS("ScheduledActionCommit");
2570   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2571 
2572   client_->Reset();
2573   fake_external_begin_frame_source_->SetPaused(true);
2574   task_runner_->RunPendingTasks();  // Run posted deadline.
2575 
2576   // Sync tree should be forced to activate.
2577   // Pausing the begin frame source aborts the draw. Then
2578   // ProactiveBeginFrameWanted is no longer true, so the scheduler stops
2579   // listening for begin frames.
2580   EXPECT_ACTIONS("ScheduledActionActivateSyncTree", "RemoveObserver(this)");
2581 }
2582 
2583 // Tests to ensure frame sources can be successfully changed while drawing.
TEST_F(SchedulerTest,SwitchFrameSourceToUnthrottled)2584 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2585   SetUpScheduler(EXTERNAL_BFS);
2586 
2587   // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2588   scheduler_->SetNeedsRedraw();
2589   EXPECT_ACTIONS("AddObserver(this)");
2590   client_->Reset();
2591 
2592   EXPECT_SCOPED(AdvanceFrame());
2593   EXPECT_ACTIONS("WillBeginImplFrame");
2594   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2595   EXPECT_TRUE(scheduler_->begin_frames_expected());
2596   client_->Reset();
2597   task_runner_->RunPendingTasks();  // Run posted deadline.
2598   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2599   scheduler_->SetNeedsRedraw();
2600 
2601   // Switch to an unthrottled frame source.
2602   scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
2603   client_->Reset();
2604 
2605   // Unthrottled frame source will immediately begin a new frame.
2606   task_runner_->RunPendingTasks();  // Run posted BeginFrame.
2607   EXPECT_ACTIONS("WillBeginImplFrame");
2608   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2609   client_->Reset();
2610 
2611   // If we don't swap on the deadline, we wait for the next BeginFrame.
2612   task_runner_->RunPendingTasks();  // Run posted deadline.
2613   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2614   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2615   client_->Reset();
2616 }
2617 
2618 // Tests to ensure frame sources can be successfully changed while a frame
2619 // deadline is pending.
TEST_F(SchedulerTest,SwitchFrameSourceToUnthrottledBeforeDeadline)2620 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
2621   SetUpScheduler(EXTERNAL_BFS);
2622 
2623   // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2624   scheduler_->SetNeedsRedraw();
2625   EXPECT_ACTIONS("AddObserver(this)");
2626   client_->Reset();
2627 
2628   EXPECT_SCOPED(AdvanceFrame());
2629   EXPECT_ACTIONS("WillBeginImplFrame");
2630 
2631   // Switch to an unthrottled frame source before the frame deadline is hit.
2632   scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
2633   client_->Reset();
2634 
2635   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2636   EXPECT_TRUE(scheduler_->begin_frames_expected());
2637   client_->Reset();
2638 
2639   task_runner_->RunPendingTasks();  // Run posted deadline.
2640   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
2641                  // Unthrottled frame source will immediately begin a new frame.
2642                  "WillBeginImplFrame");
2643   scheduler_->SetNeedsRedraw();
2644   client_->Reset();
2645 
2646   task_runner_->RunPendingTasks();  // Run posted deadline.
2647   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2648   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2649   client_->Reset();
2650 }
2651 
2652 // Tests to ensure that the active frame source can successfully be changed from
2653 // unthrottled to throttled.
TEST_F(SchedulerTest,SwitchFrameSourceToThrottled)2654 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
2655   SetUpScheduler(UNTHROTTLED_BFS);
2656 
2657   scheduler_->SetNeedsRedraw();
2658   EXPECT_NO_ACTION();
2659   client_->Reset();
2660 
2661   task_runner_->RunPendingTasks();  // Run posted BeginFrame.
2662   EXPECT_ACTIONS("WillBeginImplFrame");
2663   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2664   client_->Reset();
2665 
2666   task_runner_->RunPendingTasks();  // Run posted deadline.
2667   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2668   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2669   client_->Reset();
2670 
2671   // Switch to a throttled frame source.
2672   scheduler_->SetBeginFrameSource(fake_external_begin_frame_source_.get());
2673   client_->Reset();
2674 
2675   // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2676   scheduler_->SetNeedsRedraw();
2677   task_runner_->RunPendingTasks();
2678   EXPECT_NO_ACTION();
2679   client_->Reset();
2680 
2681   EXPECT_SCOPED(AdvanceFrame());
2682   EXPECT_ACTIONS("WillBeginImplFrame");
2683   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2684   EXPECT_TRUE(scheduler_->begin_frames_expected());
2685   client_->Reset();
2686   task_runner_->RunPendingTasks();  // Run posted deadline.
2687   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2688 }
2689 
TEST_F(SchedulerTest,SwitchFrameSourceToNullInsideDeadline)2690 TEST_F(SchedulerTest, SwitchFrameSourceToNullInsideDeadline) {
2691   SetUpScheduler(EXTERNAL_BFS);
2692 
2693   scheduler_->SetNeedsRedraw();
2694   EXPECT_ACTIONS("AddObserver(this)");
2695   client_->Reset();
2696 
2697   EXPECT_SCOPED(AdvanceFrame());
2698   EXPECT_ACTIONS("WillBeginImplFrame");
2699   client_->Reset();
2700 
2701   // Switch to a null frame source.
2702   scheduler_->SetBeginFrameSource(nullptr);
2703   EXPECT_ACTIONS("RemoveObserver(this)");
2704   client_->Reset();
2705 
2706   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2707   task_runner_->RunPendingTasks();  // Run posted deadline.
2708   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2709   EXPECT_FALSE(scheduler_->begin_frames_expected());
2710   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2711   client_->Reset();
2712 
2713   // AdvanceFrame helper can't be used here because there's no deadline posted.
2714   scheduler_->SetNeedsRedraw();
2715   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2716   EXPECT_NO_ACTION();
2717   client_->Reset();
2718 
2719   scheduler_->SetNeedsBeginMainFrame();
2720   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2721   EXPECT_NO_ACTION();
2722   client_->Reset();
2723 
2724   // Switch back to the same source, make sure frames continue to be produced.
2725   scheduler_->SetBeginFrameSource(fake_external_begin_frame_source_.get());
2726   EXPECT_ACTIONS("AddObserver(this)");
2727   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2728   client_->Reset();
2729 
2730   EXPECT_SCOPED(AdvanceFrame());
2731   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2732   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2733   client_->Reset();
2734 
2735   task_runner_->RunPendingTasks();
2736   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2737 }
2738 
2739 // This test maskes sure that switching a frame source when not observing
2740 // such as when not visible also works.
TEST_F(SchedulerTest,SwitchFrameSourceWhenNotObserving)2741 TEST_F(SchedulerTest, SwitchFrameSourceWhenNotObserving) {
2742   SetUpScheduler(EXTERNAL_BFS);
2743 
2744   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2745   scheduler_->SetNeedsBeginMainFrame();
2746   EXPECT_ACTIONS("AddObserver(this)");
2747   client_->Reset();
2748 
2749   // Begin new frame.
2750   EXPECT_SCOPED(AdvanceFrame());
2751   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2752   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2753 
2754   client_->Reset();
2755   scheduler_->NotifyReadyToCommit(nullptr);
2756   EXPECT_ACTIONS("ScheduledActionCommit");
2757 
2758   client_->Reset();
2759   scheduler_->NotifyReadyToActivate();
2760   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2761 
2762   // Scheduler loses LayerTreeFrameSink, and stops waiting for ready to draw
2763   // signal.
2764   client_->Reset();
2765   scheduler_->DidLoseLayerTreeFrameSink();
2766   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2767   task_runner_->RunPendingTasks();
2768   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2769                  "RemoveObserver(this)");
2770 
2771   // Changing begin frame source doesn't do anything.
2772   // The unthrottled source doesn't print Add/RemoveObserver like the fake one.
2773   client_->Reset();
2774   scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
2775   EXPECT_NO_ACTION();
2776 
2777   client_->Reset();
2778   scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
2779   EXPECT_NO_ACTION();
2780 
2781   client_->Reset();
2782   scheduler_->SetNeedsBeginMainFrame();
2783   EXPECT_NO_ACTION();
2784 
2785   client_->Reset();
2786   EXPECT_SCOPED(AdvanceFrame());
2787   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2788 }
2789 
2790 // Tests to ensure that we send a ScheduledActionBeginMainFrameNotExpectedUntil
2791 // when expected.
TEST_F(SchedulerTest,ScheduledActionBeginMainFrameNotExpectedUntil)2792 TEST_F(SchedulerTest, ScheduledActionBeginMainFrameNotExpectedUntil) {
2793   SetUpScheduler(EXTERNAL_BFS);
2794 
2795   scheduler_->SetNeedsRedraw();
2796   EXPECT_ACTIONS("AddObserver(this)");
2797   client_->Reset();
2798 
2799   EXPECT_SCOPED(AdvanceFrame());
2800   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2801   task_runner_->RunPendingTasks();
2802   EXPECT_ACTIONS("WillBeginImplFrame",
2803                  "ScheduledActionBeginMainFrameNotExpectedUntil",
2804                  "ScheduledActionDrawIfPossible");
2805 }
2806 
2807 // Tests to ensure that BeginMainFrameNotExpectedUntil is only sent once within
2808 // the same frame.
TEST_F(SchedulerTest,ScheduledActionBeginMainFrameNotExpectedUntilSentOnlyOncePerFrame)2809 TEST_F(SchedulerTest,
2810        ScheduledActionBeginMainFrameNotExpectedUntilSentOnlyOncePerFrame) {
2811   SetUpScheduler(EXTERNAL_BFS);
2812 
2813   scheduler_->SetNeedsRedraw();
2814   EXPECT_ACTIONS("AddObserver(this)");
2815   client_->Reset();
2816 
2817   EXPECT_SCOPED(AdvanceFrame());
2818   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2819   task_runner_->RunPendingTasks();
2820   EXPECT_ACTIONS("WillBeginImplFrame",
2821                  "ScheduledActionBeginMainFrameNotExpectedUntil",
2822                  "ScheduledActionDrawIfPossible");
2823   client_->Reset();
2824 
2825   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(false);
2826   task_runner_->RunPendingTasks();
2827   EXPECT_NO_ACTION();
2828 
2829   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2830   task_runner_->RunPendingTasks();
2831   EXPECT_NO_ACTION();
2832 }
2833 
2834 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoon_Requested)2835 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon_Requested) {
2836   SetUpScheduler(EXTERNAL_BFS);
2837 
2838   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2839   scheduler_->SetNeedsBeginMainFrame();
2840   EXPECT_ACTIONS("AddObserver(this)");
2841   client_->Reset();
2842 
2843   // Trigger a frame draw.
2844   EXPECT_SCOPED(AdvanceFrame());
2845   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2846   scheduler_->NotifyReadyToCommit(nullptr);
2847   scheduler_->NotifyReadyToActivate();
2848   task_runner_->RunPendingTasks();
2849   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2850                  "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2851                  "ScheduledActionDrawIfPossible");
2852   client_->Reset();
2853 
2854   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2855 
2856   EXPECT_SCOPED(AdvanceFrame());
2857   EXPECT_ACTIONS("WillBeginImplFrame",
2858                  "ScheduledActionBeginMainFrameNotExpectedUntil");
2859   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2860   client_->Reset();
2861 
2862   // The BeginImplFrame deadline should SetNeedsBeginFrame(false) and send a
2863   // SendBeginMainFrameNotExpectedSoon.
2864   task_runner_->RunPendingTasks();  // Run posted deadline.
2865   EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon", "RemoveObserver(this)");
2866   client_->Reset();
2867 }
2868 
2869 // Tests to ensure that we dont't send a BeginMainFrameNotExpectedSoon when
2870 // possible but not requested.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoon_Unrequested)2871 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon_Unrequested) {
2872   SetUpScheduler(EXTERNAL_BFS);
2873 
2874   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2875   scheduler_->SetNeedsBeginMainFrame();
2876   EXPECT_ACTIONS("AddObserver(this)");
2877   client_->Reset();
2878 
2879   // Trigger a frame draw.
2880   EXPECT_SCOPED(AdvanceFrame());
2881   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2882   scheduler_->NotifyReadyToCommit(nullptr);
2883   scheduler_->NotifyReadyToActivate();
2884   task_runner_->RunPendingTasks();
2885   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2886                  "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2887                  "ScheduledActionDrawIfPossible");
2888   client_->Reset();
2889 
2890   EXPECT_SCOPED(AdvanceFrame());
2891   EXPECT_ACTIONS("WillBeginImplFrame");
2892   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2893   client_->Reset();
2894 
2895   // The BeginImplFrame deadline should SetNeedsBeginFrame(false), but doesn't
2896   // send a SendBeginMainFrameNotExpectedSoon as it's not been requested by the
2897   // main thread.
2898   task_runner_->RunPendingTasks();  // Run posted deadline.
2899   EXPECT_ACTIONS("RemoveObserver(this)");
2900   client_->Reset();
2901 
2902   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2903 
2904   EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
2905 }
2906 
2907 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon only once per
2908 // frame.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoonOnlyOncePerFrame)2909 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoonOnlyOncePerFrame) {
2910   SetUpScheduler(EXTERNAL_BFS);
2911 
2912   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2913   scheduler_->SetNeedsBeginMainFrame();
2914   EXPECT_ACTIONS("AddObserver(this)");
2915   client_->Reset();
2916 
2917   // Trigger a frame draw.
2918   EXPECT_SCOPED(AdvanceFrame());
2919   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2920   scheduler_->NotifyReadyToCommit(nullptr);
2921   scheduler_->NotifyReadyToActivate();
2922   task_runner_->RunPendingTasks();
2923   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2924                  "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2925                  "ScheduledActionDrawIfPossible");
2926   client_->Reset();
2927 
2928   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2929 
2930   EXPECT_SCOPED(AdvanceFrame());
2931   EXPECT_ACTIONS("WillBeginImplFrame",
2932                  "ScheduledActionBeginMainFrameNotExpectedUntil");
2933   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2934   client_->Reset();
2935 
2936   task_runner_->RunPendingTasks();  // Run posted deadline.
2937   EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon", "RemoveObserver(this)");
2938   client_->Reset();
2939 
2940   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(false);
2941   EXPECT_NO_ACTION();
2942 
2943   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2944   EXPECT_NO_ACTION();
2945 }
2946 
2947 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon in situations
2948 // where the client doesn't want messages when we first stopped observing
2949 // BeginFrames but later does.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoon_AlreadyIdle)2950 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon_AlreadyIdle) {
2951   SetUpScheduler(EXTERNAL_BFS);
2952 
2953   // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2954   scheduler_->SetNeedsBeginMainFrame();
2955   EXPECT_ACTIONS("AddObserver(this)");
2956   client_->Reset();
2957 
2958   // Trigger a frame draw.
2959   EXPECT_SCOPED(AdvanceFrame());
2960   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2961   scheduler_->NotifyReadyToCommit(nullptr);
2962   scheduler_->NotifyReadyToActivate();
2963   task_runner_->RunPendingTasks();
2964   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2965                  "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2966                  "ScheduledActionDrawIfPossible");
2967   client_->Reset();
2968 
2969   EXPECT_SCOPED(AdvanceFrame());
2970   task_runner_->RunPendingTasks();  // Run posted deadline.
2971   EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
2972   client_->Reset();
2973 
2974   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2975   EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
2976 }
2977 
2978 // This tests to ensure BeginMainFrameNotExpectedSoon is sent during idle
2979 // periods if (1) it initially wasn't sent because the message wasn't needed at
2980 // the time, and (2) the BeginMainFrameNotExpectedUntil was already sent in the
2981 // frame (crbug.com/893653).
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoonDuringIdleIfNeeded)2982 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoonDuringIdleIfNeeded) {
2983   SetUpScheduler(EXTERNAL_BFS);
2984 
2985   scheduler_->SetNeedsRedraw();
2986   EXPECT_ACTIONS("AddObserver(this)");
2987   client_->Reset();
2988 
2989   EXPECT_SCOPED(AdvanceFrame());
2990   task_runner_->RunPendingTasks();
2991   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
2992   client_->Reset();
2993 
2994   EXPECT_SCOPED(AdvanceFrame());
2995   EXPECT_ACTIONS("WillBeginImplFrame");
2996   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2997   client_->Reset();
2998 
2999   // Toggle WantsBeginMainFrameNotExpected while inside BeginImplFrame. This
3000   // causes the BeginMainFrameNotExpectedUntil message to get sent and the
3001   // BeginMainFrameNotExpectedSoon message to be withheld.
3002   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
3003   EXPECT_ACTIONS("ScheduledActionBeginMainFrameNotExpectedUntil");
3004   client_->Reset();
3005   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(false);
3006   task_runner_->RunPendingTasks();
3007   EXPECT_ACTIONS("RemoveObserver(this)");
3008   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3009   client_->Reset();
3010 
3011   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
3012   EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
3013 }
3014 
3015 // This tests to ensure BeginMainFrameNotExpectedSoon is sent during idle
3016 // periods if (1) it initially wasn't sent because the message wasn't needed at
3017 // the time, and (2) |scheduler_|.visible() is false.
TEST_F(SchedulerTest,ScheduledActionBeginMainFrameNotSoonSentDuringIdleIfNeededNotVisible)3018 TEST_F(SchedulerTest,
3019        ScheduledActionBeginMainFrameNotSoonSentDuringIdleIfNeededNotVisible) {
3020   SetUpScheduler(EXTERNAL_BFS);
3021 
3022   scheduler_->SetNeedsRedraw();
3023   EXPECT_ACTIONS("AddObserver(this)");
3024   client_->Reset();
3025 
3026   EXPECT_SCOPED(AdvanceFrame());
3027   task_runner_->RunPendingTasks();
3028   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
3029   client_->Reset();
3030 
3031   EXPECT_SCOPED(AdvanceFrame());
3032   EXPECT_ACTIONS("WillBeginImplFrame");
3033   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3034   client_->Reset();
3035 
3036   scheduler_->SetVisible(false);
3037 
3038   task_runner_->RunPendingTasks();
3039   EXPECT_ACTIONS("RemoveObserver(this)");
3040   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3041 
3042   // The scheduler won't send BeginMainFrameNotExpectedUntil messages while not
3043   // visible, but it needs to send a BeginMainFrameNotExpectedSoon to let the
3044   // client know it's gone idle.
3045   client_->Reset();
3046   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
3047   EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
3048 }
3049 
TEST_F(SchedulerTest,SynchronousCompositorAnimation)3050 TEST_F(SchedulerTest, SynchronousCompositorAnimation) {
3051   scheduler_settings_.using_synchronous_renderer_compositor = true;
3052   SetUpScheduler(EXTERNAL_BFS);
3053 
3054   scheduler_->SetNeedsOneBeginImplFrame();
3055   EXPECT_ACTIONS("AddObserver(this)");
3056   client_->Reset();
3057 
3058   // Testing the case where animation ticks a fling scroll.
3059   client_->SetWillBeginImplFrameCausesRedraw(true);
3060   // The animation isn't done so it'll cause another tick in the future.
3061   client_->SetWillBeginImplFrameRequestsOneBeginImplFrame(true);
3062 
3063   // Next vsync.
3064   AdvanceFrame();
3065   EXPECT_ACTIONS("WillBeginImplFrame",
3066                  "ScheduledActionInvalidateLayerTreeFrameSink");
3067   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3068   client_->Reset();
3069 
3070   // Android onDraw. This doesn't consume the single begin frame request.
3071   scheduler_->SetNeedsRedraw();
3072   bool resourceless_software_draw = false;
3073   bool skip_draw = false;
3074   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3075                                           skip_draw);
3076   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3077   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3078   client_->Reset();
3079 
3080   // The animation inside of WillBeginImplFrame changes stuff on the screen, but
3081   // ends here, so does not cause another frame to happen.
3082   client_->SetWillBeginImplFrameCausesRedraw(true);
3083 
3084   // Next vsync.
3085   AdvanceFrame();
3086   EXPECT_ACTIONS("WillBeginImplFrame",
3087                  "ScheduledActionInvalidateLayerTreeFrameSink");
3088   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3089   client_->Reset();
3090 
3091   // Android onDraw.
3092   scheduler_->SetNeedsRedraw();
3093   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3094                                           skip_draw);
3095   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3096   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3097   client_->Reset();
3098 
3099   // Idle on next vsync, as the animation has completed.
3100   AdvanceFrame();
3101   EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3102   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3103   client_->Reset();
3104 }
3105 
TEST_F(SchedulerTest,SynchronousCompositorOnDrawDuringIdle)3106 TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) {
3107   scheduler_settings_.using_synchronous_renderer_compositor = true;
3108   SetUpScheduler(EXTERNAL_BFS);
3109 
3110   scheduler_->SetNeedsRedraw();
3111   bool resourceless_software_draw = false;
3112   bool skip_draw = false;
3113   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3114                                           skip_draw);
3115   EXPECT_ACTIONS("AddObserver(this)", "ScheduledActionDrawIfPossible");
3116   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3117   client_->Reset();
3118 
3119   // Idle on next vsync.
3120   AdvanceFrame();
3121   EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3122   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3123   client_->Reset();
3124 }
3125 
TEST_F(SchedulerTest,InvalidateLayerTreeFrameSinkWhenCannotDraw)3126 TEST_F(SchedulerTest, InvalidateLayerTreeFrameSinkWhenCannotDraw) {
3127   scheduler_settings_.using_synchronous_renderer_compositor = true;
3128   SetUpScheduler(EXTERNAL_BFS);
3129 
3130   scheduler_->SetCanDraw(false);
3131 
3132   scheduler_->SetNeedsRedraw();
3133   EXPECT_ACTIONS("AddObserver(this)");
3134   client_->Reset();
3135 
3136   // Do not invalidate in next BeginFrame.
3137   EXPECT_SCOPED(AdvanceFrame());
3138   EXPECT_ACTIONS("WillBeginImplFrame");
3139   client_->Reset();
3140 
3141   // Redraw is not cleared.
3142   EXPECT_TRUE(scheduler_->RedrawPending());
3143 
3144   scheduler_->SetCanDraw(true);
3145 
3146   // Do invalidate in next BeginFrame.
3147   EXPECT_SCOPED(AdvanceFrame());
3148   EXPECT_ACTIONS("WillBeginImplFrame",
3149                  "ScheduledActionInvalidateLayerTreeFrameSink");
3150   client_->Reset();
3151 
3152   bool resourceless_software_draw = false;
3153   bool skip_draw = false;
3154   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3155                                           skip_draw);
3156   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3157   EXPECT_FALSE(scheduler_->RedrawPending());
3158 }
3159 
TEST_F(SchedulerTest,NeedsPrepareTilesInvalidates)3160 TEST_F(SchedulerTest, NeedsPrepareTilesInvalidates) {
3161   // This is to test that SetNeedsPrepareTiles causes invalidates even if
3162   // CanDraw is false.
3163   scheduler_settings_.using_synchronous_renderer_compositor = true;
3164   SetUpScheduler(EXTERNAL_BFS);
3165 
3166   scheduler_->SetCanDraw(false);
3167 
3168   scheduler_->SetNeedsPrepareTiles();
3169   EXPECT_ACTIONS("AddObserver(this)");
3170   client_->Reset();
3171 
3172   // Do not invalidate in next BeginFrame.
3173   EXPECT_SCOPED(AdvanceFrame());
3174   EXPECT_ACTIONS("WillBeginImplFrame",
3175                  "ScheduledActionInvalidateLayerTreeFrameSink");
3176   client_->Reset();
3177 }
3178 
TEST_F(SchedulerTest,SetNeedsOneBeginImplFrame)3179 TEST_F(SchedulerTest, SetNeedsOneBeginImplFrame) {
3180   SetUpScheduler(EXTERNAL_BFS);
3181 
3182   EXPECT_FALSE(scheduler_->begin_frames_expected());
3183 
3184   // Request a frame, should kick the source.
3185   scheduler_->SetNeedsOneBeginImplFrame();
3186   EXPECT_ACTIONS("AddObserver(this)");
3187   client_->Reset();
3188 
3189   // The incoming WillBeginImplFrame will request another one.
3190   client_->SetWillBeginImplFrameRequestsOneBeginImplFrame(true);
3191 
3192   // Next vsync, the first requested frame happens.
3193   EXPECT_SCOPED(AdvanceFrame());
3194   EXPECT_ACTIONS("WillBeginImplFrame");
3195   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3196   client_->Reset();
3197 
3198   // We don't request another frame here.
3199 
3200   // Next vsync, the second requested frame happens (the one requested inside
3201   // the previous frame's begin impl frame step).
3202   EXPECT_SCOPED(AdvanceFrame());
3203   EXPECT_ACTIONS("WillBeginImplFrame");
3204   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3205   client_->Reset();
3206 
3207   // End that frame's deadline.
3208   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
3209   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3210 
3211   // Scheduler shuts down the source now that no begin frame is requested.
3212   EXPECT_ACTIONS("RemoveObserver(this)");
3213 }
3214 
TEST_F(SchedulerTest,AbortEarlyIfNoDamage)3215 TEST_F(SchedulerTest, AbortEarlyIfNoDamage) {
3216   SetUpScheduler(EXTERNAL_BFS);
3217 
3218   // WillBeginImplFrame will return false, so draws should never be scheduled
3219   // and client_->num_draws() should stay at 0.
3220   client_->SetWillBeginImplFrameMightHaveDamage(false);
3221 
3222   scheduler_->SetNeedsRedraw();
3223   EXPECT_EQ(0, client_->num_draws());
3224   EXPECT_ACTIONS("AddObserver(this)");
3225 
3226   EXPECT_SCOPED(AdvanceFrame());
3227   task_runner_->RunPendingTasks();  // Run posted deadline.
3228   // Should not try to schedule a draw. (ScheduledActionDrawIfPossible should
3229   // not appear.)
3230   // When the frame is aborted, the scheduler does not ask for a proactive begin
3231   // frame, so stop listening for begin frames.
3232   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
3233                  "RemoveObserver(this)");
3234   EXPECT_EQ(0, client_->num_draws());
3235 
3236   scheduler_->SetNeedsRedraw();
3237   EXPECT_SCOPED(AdvanceFrame());
3238   task_runner_->RunPendingTasks();  // Run posted deadline.
3239   EXPECT_EQ(0, client_->num_draws());
3240 }
3241 
TEST_F(SchedulerTest,SkipDraw)3242 TEST_F(SchedulerTest, SkipDraw) {
3243   scheduler_settings_.using_synchronous_renderer_compositor = true;
3244   SetUpScheduler(EXTERNAL_BFS);
3245 
3246   scheduler_->SetNeedsOneBeginImplFrame();
3247   EXPECT_ACTIONS("AddObserver(this)");
3248   client_->Reset();
3249 
3250   client_->SetWillBeginImplFrameCausesRedraw(true);
3251 
3252   // Next vsync.
3253   AdvanceFrame();
3254   EXPECT_ACTIONS("WillBeginImplFrame",
3255                  "ScheduledActionInvalidateLayerTreeFrameSink");
3256   EXPECT_TRUE(client_->invalidate_needs_redraw());
3257   client_->Reset();
3258 
3259   // Android onDraw. This doesn't consume the single begin frame request.
3260   scheduler_->SetNeedsPrepareTiles();
3261   bool resourceless_software_draw = false;
3262   bool skip_draw = false;
3263   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3264                                           skip_draw);
3265   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3266                  "ScheduledActionPrepareTiles");
3267   client_->Reset();
3268 
3269   // Next vsync.
3270   scheduler_->SetNeedsPrepareTiles();
3271   AdvanceFrame();
3272   EXPECT_ACTIONS("WillBeginImplFrame",
3273                  "ScheduledActionInvalidateLayerTreeFrameSink");
3274   EXPECT_FALSE(client_->invalidate_needs_redraw());
3275   client_->Reset();
3276 
3277   // Android onDraw.
3278   scheduler_->SetNeedsRedraw();
3279   scheduler_->SetNeedsPrepareTiles();
3280   client_->SetInvalidateNeedsRedraw(false);
3281   skip_draw = true;
3282   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3283                                           skip_draw);
3284   EXPECT_ACTIONS("ScheduledActionPrepareTiles");
3285   client_->Reset();
3286 }
3287 
TEST_F(SchedulerTest,SynchronousCompositorCommitAndVerifyBeginFrameAcks)3288 TEST_F(SchedulerTest, SynchronousCompositorCommitAndVerifyBeginFrameAcks) {
3289   scheduler_settings_.using_synchronous_renderer_compositor = true;
3290   SetUpScheduler(EXTERNAL_BFS);
3291 
3292   scheduler_->SetNeedsBeginMainFrame();
3293   EXPECT_ACTIONS("AddObserver(this)");
3294   client_->Reset();
3295 
3296   // Next vsync.
3297   viz::BeginFrameArgs args = SendNextBeginFrame();
3298   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3299   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3300 
3301   bool has_damage = false;
3302   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3303             client_->last_begin_frame_ack());
3304   client_->Reset();
3305 
3306   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3307   EXPECT_NO_ACTION();
3308 
3309   // Next vsync.
3310   args = SendNextBeginFrame();
3311   EXPECT_ACTIONS("WillBeginImplFrame");
3312   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3313 
3314   has_damage = false;
3315   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3316             client_->last_begin_frame_ack());
3317   client_->Reset();
3318 
3319   scheduler_->NotifyReadyToCommit(nullptr);
3320   EXPECT_ACTIONS("ScheduledActionCommit");
3321   client_->Reset();
3322 
3323   scheduler_->NotifyReadyToActivate();
3324   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3325   client_->Reset();
3326 
3327   // Next vsync.
3328   args = SendNextBeginFrame();
3329   EXPECT_ACTIONS("WillBeginImplFrame",
3330                  "ScheduledActionInvalidateLayerTreeFrameSink");
3331   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3332 
3333   // No damage, since not drawn yet.
3334   // TODO(eseckler): In the future, |has_damage = false| will prevent us from
3335   // filtering this ack (in CompositorExternalBeginFrameSource) and instead
3336   // forwarding the one attached to the later submitted CompositorFrame.
3337   has_damage = false;
3338   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3339             client_->last_begin_frame_ack());
3340   client_->Reset();
3341 
3342   // Android onDraw.
3343   scheduler_->SetNeedsRedraw();
3344   bool resourceless_software_draw = false;
3345   bool skip_draw = false;
3346   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3347                                           skip_draw);
3348   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3349   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3350   client_->Reset();
3351 
3352   // Idle on next vsync.
3353   args = SendNextBeginFrame();
3354   EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3355   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3356 
3357   has_damage = false;
3358   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3359             client_->last_begin_frame_ack());
3360   client_->Reset();
3361 }
3362 
3363 class SchedulerClientSetNeedsPrepareTilesOnDraw : public FakeSchedulerClient {
3364  public:
SchedulerClientSetNeedsPrepareTilesOnDraw()3365   SchedulerClientSetNeedsPrepareTilesOnDraw() : FakeSchedulerClient() {}
3366 
3367  protected:
ScheduledActionDrawIfPossible()3368   DrawResult ScheduledActionDrawIfPossible() override {
3369     scheduler_->SetNeedsPrepareTiles();
3370     return FakeSchedulerClient::ScheduledActionDrawIfPossible();
3371   }
3372 };
3373 
TEST_F(SchedulerTest,SynchronousCompositorPrepareTilesOnDraw)3374 TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) {
3375   scheduler_settings_.using_synchronous_renderer_compositor = true;
3376 
3377   std::unique_ptr<FakeSchedulerClient> client =
3378       base::WrapUnique(new SchedulerClientSetNeedsPrepareTilesOnDraw);
3379   SetUpScheduler(EXTERNAL_BFS, std::move(client));
3380 
3381   scheduler_->SetNeedsRedraw();
3382   EXPECT_ACTIONS("AddObserver(this)");
3383   client_->Reset();
3384 
3385   // Next vsync.
3386   EXPECT_SCOPED(AdvanceFrame());
3387   EXPECT_ACTIONS("WillBeginImplFrame",
3388                  "ScheduledActionInvalidateLayerTreeFrameSink");
3389   client_->Reset();
3390 
3391   // Android onDraw.
3392   scheduler_->SetNeedsRedraw();
3393   bool resourceless_software_draw = false;
3394   bool skip_draw = false;
3395   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3396                                           skip_draw);
3397   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3398                  "ScheduledActionPrepareTiles");
3399   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3400   EXPECT_FALSE(scheduler_->PrepareTilesPending());
3401   client_->Reset();
3402 
3403   // Android onDraw.
3404   scheduler_->SetNeedsRedraw();
3405   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3406                                           skip_draw);
3407   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3408                  "ScheduledActionPrepareTiles");
3409   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3410   EXPECT_FALSE(scheduler_->PrepareTilesPending());
3411   client_->Reset();
3412 
3413   // Next vsync.
3414   EXPECT_SCOPED(AdvanceFrame());
3415   EXPECT_FALSE(scheduler_->PrepareTilesPending());
3416   EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3417   EXPECT_FALSE(scheduler_->begin_frames_expected());
3418   client_->Reset();
3419 }
3420 
3421 // Synchronous compositor does not require the active tree to be drawn at least
3422 // once before the next activation. This test verifies two commit-activate
3423 // cycles without draw work correctly.
TEST_F(SchedulerTest,SynchronousCompositorAllowsActivateBeforeDraw)3424 TEST_F(SchedulerTest, SynchronousCompositorAllowsActivateBeforeDraw) {
3425   scheduler_settings_.using_synchronous_renderer_compositor = true;
3426 
3427   std::unique_ptr<FakeSchedulerClient> client =
3428       base::WrapUnique(new SchedulerClientSetNeedsPrepareTilesOnDraw);
3429   SetUpScheduler(EXTERNAL_BFS, std::move(client));
3430 
3431   scheduler_->SetNeedsRedraw();
3432   EXPECT_ACTIONS("AddObserver(this)");
3433   client_->Reset();
3434 
3435   // Next vsync.
3436   scheduler_->SetNeedsBeginMainFrame();
3437   EXPECT_SCOPED(AdvanceFrame());
3438   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
3439                  "ScheduledActionInvalidateLayerTreeFrameSink");
3440   client_->Reset();
3441 
3442   // Commit and activate.
3443   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3444   scheduler_->NotifyReadyToCommit(nullptr);
3445   EXPECT_ACTIONS("ScheduledActionCommit");
3446   client_->Reset();
3447   scheduler_->NotifyReadyToActivate();
3448   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3449   client_->Reset();
3450 
3451   // No Draw.
3452 
3453   // Next vsync.
3454   scheduler_->SetNeedsBeginMainFrame();
3455   EXPECT_SCOPED(AdvanceFrame());
3456   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
3457                  "ScheduledActionInvalidateLayerTreeFrameSink");
3458   client_->Reset();
3459 
3460   // Commit and activate.
3461   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3462   scheduler_->NotifyReadyToCommit(nullptr);
3463   EXPECT_ACTIONS("ScheduledActionCommit");
3464   client_->Reset();
3465   scheduler_->NotifyReadyToActivate();
3466   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3467   client_->Reset();
3468 }
3469 
TEST_F(SchedulerTest,SetNeedsRedrawFromWillBeginImplFrame)3470 TEST_F(SchedulerTest, SetNeedsRedrawFromWillBeginImplFrame) {
3471   client_ = std::make_unique<FakeSchedulerClient>();
3472   CreateScheduler(EXTERNAL_BFS);
3473 
3474   scheduler_->SetVisible(true);
3475   scheduler_->SetCanDraw(true);
3476   client_->SetWillBeginImplFrameCausesRedraw(true);
3477 
3478   scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
3479   scheduler_->SetNeedsBeginMainFrame();
3480 
3481   AdvanceFrame();
3482   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
3483                  "AddObserver(this)", "WillBeginImplFrame",
3484                  "ScheduledActionSendBeginMainFrame");
3485   EXPECT_TRUE(scheduler_->RedrawPending());
3486   // WillBeginFrame calls Scheduler::SetNeedsRedraw, which could try to run
3487   // another action. If none of the EXPECT_FALSE(inside_action_)s in
3488   // FakeSchedulerClient fail, we know we didn't re-enter the scheduler.
3489 }
3490 
TEST_F(SchedulerTest,SynchronousCompositorSendBeginMainFrameWhileIdle)3491 TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) {
3492   scheduler_settings_.using_synchronous_renderer_compositor = true;
3493   SetUpScheduler(EXTERNAL_BFS);
3494 
3495   scheduler_->SetNeedsRedraw();
3496   EXPECT_ACTIONS("AddObserver(this)");
3497   client_->Reset();
3498 
3499   // Next vsync.
3500   EXPECT_SCOPED(AdvanceFrame());
3501   EXPECT_ACTIONS("WillBeginImplFrame",
3502                  "ScheduledActionInvalidateLayerTreeFrameSink");
3503   client_->Reset();
3504 
3505   // Android onDraw.
3506   scheduler_->SetNeedsRedraw();
3507   bool resourceless_software_draw = false;
3508   bool skip_draw = false;
3509   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3510                                           skip_draw);
3511   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3512   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3513   EXPECT_FALSE(scheduler_->PrepareTilesPending());
3514   client_->Reset();
3515 
3516   // Simulate SetNeedsBeginMainFrame due to input event.
3517   scheduler_->SetNeedsBeginMainFrame();
3518   EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
3519   client_->Reset();
3520 
3521   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3522   scheduler_->NotifyReadyToCommit(nullptr);
3523   EXPECT_ACTIONS("ScheduledActionCommit");
3524   client_->Reset();
3525 
3526   scheduler_->NotifyReadyToActivate();
3527   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3528   client_->Reset();
3529 
3530   // Next vsync.
3531   EXPECT_SCOPED(AdvanceFrame());
3532   EXPECT_ACTIONS("WillBeginImplFrame",
3533                  "ScheduledActionInvalidateLayerTreeFrameSink");
3534   client_->Reset();
3535 
3536   // Android onDraw.
3537   scheduler_->SetNeedsRedraw();
3538   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3539                                           skip_draw);
3540   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3541   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3542   EXPECT_FALSE(scheduler_->PrepareTilesPending());
3543   client_->Reset();
3544 
3545   // Simulate SetNeedsBeginMainFrame due to input event.
3546   scheduler_->SetNeedsBeginMainFrame();
3547   EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
3548   client_->Reset();
3549 }
3550 
TEST_F(SchedulerTest,SynchronousCompositorResourcelessOnDrawWhenInvisible)3551 TEST_F(SchedulerTest, SynchronousCompositorResourcelessOnDrawWhenInvisible) {
3552   scheduler_settings_.using_synchronous_renderer_compositor = true;
3553   SetUpScheduler(EXTERNAL_BFS);
3554 
3555   scheduler_->SetVisible(false);
3556 
3557   scheduler_->SetNeedsRedraw();
3558   bool resourceless_software_draw = true;
3559   bool skip_draw = false;
3560   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3561                                           skip_draw);
3562   // SynchronousCompositor has to draw regardless of visibility.
3563   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3564   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3565   client_->Reset();
3566 }
3567 
TEST_F(SchedulerTest,AuthoritativeVSyncInterval)3568 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
3569   SetUpScheduler(THROTTLED_BFS);
3570   base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval();
3571   base::TimeDelta authoritative_interval =
3572       base::TimeDelta::FromMilliseconds(33);
3573 
3574   scheduler_->SetNeedsBeginMainFrame();
3575   EXPECT_SCOPED(AdvanceFrame());
3576 
3577   EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
3578 
3579   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3580   scheduler_->NotifyReadyToCommit(nullptr);
3581   scheduler_->NotifyReadyToActivate();
3582   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
3583 
3584   // Test changing the interval on the frame source external to the scheduler.
3585   synthetic_frame_source_->OnUpdateVSyncParameters(task_runner_->NowTicks(),
3586                                                    authoritative_interval);
3587 
3588   EXPECT_SCOPED(AdvanceFrame());
3589 
3590   // At the next BeginFrame, authoritative interval is used instead of previous
3591   // interval.
3592   EXPECT_NE(initial_interval, scheduler_->BeginImplFrameInterval());
3593   EXPECT_EQ(authoritative_interval, scheduler_->BeginImplFrameInterval());
3594 }
3595 
TEST_F(SchedulerTest,ImplLatencyTakesPriority)3596 TEST_F(SchedulerTest, ImplLatencyTakesPriority) {
3597   SetUpScheduler(THROTTLED_BFS);
3598 
3599   scheduler_->SetTreePrioritiesAndScrollState(
3600       SMOOTHNESS_TAKES_PRIORITY,
3601       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
3602   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3603   EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3604   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3605   EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3606 
3607   scheduler_->SetTreePrioritiesAndScrollState(
3608       SMOOTHNESS_TAKES_PRIORITY,
3609       ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER);
3610   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3611   EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3612   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3613   EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3614 
3615   scheduler_->SetTreePrioritiesAndScrollState(
3616       SAME_PRIORITY_FOR_BOTH_TREES,
3617       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
3618   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3619   EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3620   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3621   EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3622 
3623   scheduler_->SetTreePrioritiesAndScrollState(
3624       SAME_PRIORITY_FOR_BOTH_TREES,
3625       ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER);
3626   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3627   EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3628   scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3629   EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3630 }
3631 
TEST_F(SchedulerTest,NoLayerTreeFrameSinkCreationWhileCommitPending)3632 TEST_F(SchedulerTest, NoLayerTreeFrameSinkCreationWhileCommitPending) {
3633   SetUpScheduler(THROTTLED_BFS);
3634 
3635   // SetNeedsBeginMainFrame should begin the frame.
3636   scheduler_->SetNeedsBeginMainFrame();
3637   client_->Reset();
3638   EXPECT_SCOPED(AdvanceFrame());
3639   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3640 
3641   // Lose the LayerTreeFrameSink and trigger the deadline.
3642   client_->Reset();
3643   scheduler_->DidLoseLayerTreeFrameSink();
3644   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3645   EXPECT_NO_ACTION();
3646 
3647   // The scheduler should not trigger the LayerTreeFrameSink creation till the
3648   // commit is aborted.
3649   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
3650   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3651   EXPECT_NO_ACTION();
3652 
3653   // Abort the commit.
3654   client_->Reset();
3655   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3656   scheduler_->BeginMainFrameAborted(
3657       CommitEarlyOutReason::ABORTED_LAYER_TREE_FRAME_SINK_LOST);
3658   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
3659 }
3660 
TEST_F(SchedulerTest,ImplSideInvalidationInsideImplFrame)3661 TEST_F(SchedulerTest, ImplSideInvalidationInsideImplFrame) {
3662   SetUpScheduler(EXTERNAL_BFS);
3663 
3664   // Request an impl-side invalidation. Ensure that it runs before the deadline.
3665   bool needs_first_draw_on_activation = true;
3666   scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3667   client_->Reset();
3668   EXPECT_SCOPED(AdvanceFrame());
3669   EXPECT_ACTIONS("WillBeginImplFrame",
3670                  "ScheduledActionPerformImplSideInvalidation");
3671 }
3672 
TEST_F(SchedulerTest,ImplSideInvalidationsMergedWithCommit)3673 TEST_F(SchedulerTest, ImplSideInvalidationsMergedWithCommit) {
3674   SetUpScheduler(EXTERNAL_BFS);
3675 
3676   // Request a main frame and invalidation, the only action run should be
3677   // sending the main frame.
3678   SetShouldDeferInvalidationForMainFrame(true);
3679   scheduler_->SetNeedsBeginMainFrame();
3680   bool needs_first_draw_on_activation = true;
3681   scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3682   client_->Reset();
3683   EXPECT_SCOPED(AdvanceFrame());
3684   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3685 
3686   // Respond with a commit. The scheduler should only perform the commit
3687   // actions since the impl-side invalidation request will be merged with the
3688   // commit.
3689   client_->Reset();
3690   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3691   scheduler_->NotifyReadyToCommit(nullptr);
3692   EXPECT_ACTIONS("ScheduledActionCommit");
3693   EXPECT_FALSE(scheduler_->needs_impl_side_invalidation());
3694 }
3695 
TEST_F(SchedulerTest,AbortedCommitsTriggerImplSideInvalidations)3696 TEST_F(SchedulerTest, AbortedCommitsTriggerImplSideInvalidations) {
3697   SetUpScheduler(EXTERNAL_BFS);
3698 
3699   // Request a main frame and invalidation, with a fast main thread so we wait
3700   // for it to respond.
3701   SetShouldDeferInvalidationForMainFrame(true);
3702   scheduler_->SetNeedsBeginMainFrame();
3703   bool needs_first_draw_on_activation = true;
3704   scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3705   client_->Reset();
3706   EXPECT_SCOPED(AdvanceFrame());
3707   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3708 
3709   // Abort the main frame and request another one, the impl-side invalidations
3710   // should not be blocked on the main frame.
3711   client_->Reset();
3712   scheduler_->SetNeedsBeginMainFrame();
3713   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3714   scheduler_->BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
3715   EXPECT_ACTIONS("ScheduledActionPerformImplSideInvalidation");
3716 }
3717 
TEST_F(SchedulerTest,InvalidationNotBlockedOnMainFrame)3718 TEST_F(SchedulerTest, InvalidationNotBlockedOnMainFrame) {
3719   SetUpScheduler(EXTERNAL_BFS);
3720 
3721   // Request a main frame and invalidation, with a slow main thread so the
3722   // invalidation is not blocked on a commit.
3723   SetShouldDeferInvalidationForMainFrame(false);
3724   scheduler_->SetNeedsBeginMainFrame();
3725   bool needs_first_draw_on_activation = true;
3726   scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3727   client_->Reset();
3728   EXPECT_SCOPED(AdvanceFrame());
3729   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
3730                  "ScheduledActionPerformImplSideInvalidation");
3731 }
3732 
3733 // The three letters appeneded to each version of this test mean the following:s
3734 // tree_priority: B = both trees same priority; A = active tree priority;
3735 // scroll_handler_state: H = affects scroll handler; N = does not affect scroll
3736 // handler;
3737 // durations: F = fast durations; S = slow durations
BeginMainFrameOnCriticalPath(TreePriority tree_priority,ScrollHandlerState scroll_handler_state,base::TimeDelta durations)3738 bool SchedulerTest::BeginMainFrameOnCriticalPath(
3739     TreePriority tree_priority,
3740     ScrollHandlerState scroll_handler_state,
3741     base::TimeDelta durations) {
3742   SetUpScheduler(EXTERNAL_BFS);
3743   fake_compositor_timing_history_->SetAllEstimatesTo(durations);
3744   client_->Reset();
3745   scheduler_->SetTreePrioritiesAndScrollState(tree_priority,
3746                                               scroll_handler_state);
3747   scheduler_->SetNeedsBeginMainFrame();
3748   EXPECT_FALSE(client_->last_begin_main_frame_args().IsValid());
3749   EXPECT_SCOPED(AdvanceFrame());
3750   EXPECT_TRUE(client_->last_begin_main_frame_args().IsValid());
3751   return client_->last_begin_main_frame_args().on_critical_path;
3752 }
3753 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BNF)3754 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BNF) {
3755   EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3756       SAME_PRIORITY_FOR_BOTH_TREES,
3757       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3758       kFastDuration));
3759 }
3760 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BNS)3761 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BNS) {
3762   EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3763       SAME_PRIORITY_FOR_BOTH_TREES,
3764       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3765       kSlowDuration));
3766 }
3767 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BHF)3768 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BHF) {
3769   EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3770       SAME_PRIORITY_FOR_BOTH_TREES,
3771       ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kFastDuration));
3772 }
3773 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BHS)3774 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BHS) {
3775   EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3776       SAME_PRIORITY_FOR_BOTH_TREES,
3777       ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kSlowDuration));
3778 }
3779 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_ANF)3780 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_ANF) {
3781   EXPECT_FALSE(BeginMainFrameOnCriticalPath(
3782       SMOOTHNESS_TAKES_PRIORITY,
3783       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3784       kFastDuration));
3785 }
3786 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_ANS)3787 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_ANS) {
3788   EXPECT_FALSE(BeginMainFrameOnCriticalPath(
3789       SMOOTHNESS_TAKES_PRIORITY,
3790       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3791       kSlowDuration));
3792 }
3793 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_AHF)3794 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_AHF) {
3795   EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3796       SMOOTHNESS_TAKES_PRIORITY,
3797       ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kFastDuration));
3798 }
3799 
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_AHS)3800 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_AHS) {
3801   EXPECT_FALSE(BeginMainFrameOnCriticalPath(
3802       SMOOTHNESS_TAKES_PRIORITY,
3803       ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kSlowDuration));
3804 }
3805 
TEST_F(SchedulerTest,BeginFrameAckForFinishedImplFrame)3806 TEST_F(SchedulerTest, BeginFrameAckForFinishedImplFrame) {
3807   // Sets up scheduler and sends two BeginFrames, both finished.
3808   SetUpScheduler(EXTERNAL_BFS);
3809 
3810   // Run a successful redraw and verify that a new ack is sent.
3811   scheduler_->SetNeedsRedraw();
3812   client_->Reset();
3813 
3814   viz::BeginFrameArgs args = SendNextBeginFrame();
3815   EXPECT_ACTIONS("WillBeginImplFrame");
3816   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3817   EXPECT_TRUE(scheduler_->begin_frames_expected());
3818   client_->Reset();
3819 
3820   task_runner_->RunPendingTasks();  // Run posted deadline.
3821   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3822   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3823   EXPECT_TRUE(scheduler_->begin_frames_expected());
3824 
3825   // Successful draw caused damage.
3826   bool has_damage = true;
3827   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3828             client_->last_begin_frame_ack());
3829   client_->Reset();
3830 
3831   // Request another redraw, but fail it. Verify that a new ack is sent.
3832   scheduler_->SetNeedsRedraw();
3833   client_->Reset();
3834 
3835   args = SendNextBeginFrame();
3836   EXPECT_ACTIONS("WillBeginImplFrame");
3837   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3838   EXPECT_TRUE(scheduler_->begin_frames_expected());
3839   client_->Reset();
3840 
3841   client_->SetDrawWillHappen(false);
3842   task_runner_->RunPendingTasks();  // Run posted deadline.
3843   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3844                  // Failed draw triggers SendBeginMainFrame.
3845                  "ScheduledActionSendBeginMainFrame");
3846   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3847   EXPECT_TRUE(scheduler_->begin_frames_expected());
3848 
3849   // Failed draw: no damage.
3850   has_damage = false;
3851   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3852             client_->last_begin_frame_ack());
3853   client_->Reset();
3854 }
3855 
TEST_F(SchedulerTest,BeginFrameAckForSkippedImplFrame)3856 TEST_F(SchedulerTest, BeginFrameAckForSkippedImplFrame) {
3857   SetUpScheduler(EXTERNAL_BFS);
3858 
3859   // To get into a high latency state, this test disables automatic swap acks.
3860   client_->SetAutomaticSubmitCompositorFrameAck(false);
3861   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
3862 
3863   // Run a successful redraw that submits a compositor frame but doesn't receive
3864   // a swap ack. Verify that a viz::BeginFrameAck is sent for it.
3865   scheduler_->SetNeedsRedraw();
3866   client_->Reset();
3867 
3868   viz::BeginFrameArgs args = SendNextBeginFrame();
3869   EXPECT_ACTIONS("WillBeginImplFrame");
3870   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3871   EXPECT_TRUE(scheduler_->begin_frames_expected());
3872   client_->Reset();
3873 
3874   task_runner_->RunPendingTasks();  // Run posted deadline.
3875   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3876   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3877   EXPECT_TRUE(scheduler_->begin_frames_expected());
3878 
3879   // Successful draw caused damage.
3880   bool has_damage = true;
3881   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3882             client_->last_begin_frame_ack());
3883   client_->Reset();
3884 
3885   // Request another redraw that will be skipped because the swap ack is still
3886   // missing. Verify that a new viz::BeginFrameAck is sent.
3887   scheduler_->SetNeedsRedraw();
3888   client_->Reset();
3889 
3890   args = SendNextBeginFrame();
3891   EXPECT_NO_ACTION();
3892   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3893   EXPECT_TRUE(scheduler_->begin_frames_expected());
3894 
3895   // Skipped draw: no damage.
3896   has_damage = false;
3897   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3898             client_->last_begin_frame_ack());
3899   client_->Reset();
3900 }
3901 
TEST_F(SchedulerTest,BeginFrameAckForBeginFrameBeforeLastDeadline)3902 TEST_F(SchedulerTest, BeginFrameAckForBeginFrameBeforeLastDeadline) {
3903   SetUpScheduler(EXTERNAL_BFS);
3904 
3905   // Request tile preparation to schedule a proactive BeginFrame.
3906   scheduler_->SetNeedsPrepareTiles();
3907   client_->Reset();
3908 
3909   SendNextBeginFrame();
3910   EXPECT_ACTIONS("WillBeginImplFrame");
3911   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3912   // Until tiles were prepared, further proactive BeginFrames are expected.
3913   EXPECT_TRUE(scheduler_->begin_frames_expected());
3914   client_->Reset();
3915 
3916   // Send the next BeginFrame before the previous one's deadline was executed.
3917   // This should post the previous BeginFrame's deadline, during which tiles
3918   // will be prepared. As a result of that, no further BeginFrames will be
3919   // needed, and the new BeginFrame should be dropped.
3920   viz::BeginFrameArgs args = SendNextBeginFrame();
3921   task_runner_->RunPendingTasks();  // Run posted deadline.
3922   EXPECT_ACTIONS("ScheduledActionPrepareTiles", "RemoveObserver(this)");
3923   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3924   EXPECT_FALSE(scheduler_->begin_frames_expected());
3925 
3926   // Latest ack should be for the dropped BeginFrame.
3927   bool has_damage = false;
3928   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3929             client_->last_begin_frame_ack());
3930   client_->Reset();
3931 }
3932 
TEST_F(SchedulerTest,BeginFrameAckForDroppedBeginFrame)3933 TEST_F(SchedulerTest, BeginFrameAckForDroppedBeginFrame) {
3934   SetUpScheduler(EXTERNAL_BFS);
3935 
3936   // Request a single BeginFrame.
3937   scheduler_->SetNeedsOneBeginImplFrame();
3938   EXPECT_TRUE(scheduler_->begin_frames_expected());
3939   client_->Reset();
3940 
3941   // First BeginFrame is handled by StateMachine.
3942   viz::BeginFrameArgs first_args = SendNextBeginFrame();
3943   EXPECT_ACTIONS("WillBeginImplFrame");
3944   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3945   // State machine is no longer interested in BeginFrames, but scheduler is
3946   // still observing the source.
3947   EXPECT_TRUE(scheduler_->begin_frames_expected());
3948   EXPECT_FALSE(scheduler_->BeginFrameNeeded());
3949   client_->Reset();
3950 
3951   // Send the next BeginFrame before the previous one's deadline was executed.
3952   // The BeginFrame should be dropped immediately, since the state machine is
3953   // not expecting any BeginFrames.
3954   viz::BeginFrameArgs second_args = SendNextBeginFrame();
3955   EXPECT_NO_ACTION();
3956 
3957   // Latest ack should be for the dropped BeginFrame.
3958   bool has_damage = false;
3959   EXPECT_EQ(viz::BeginFrameAck(second_args, has_damage),
3960             client_->last_begin_frame_ack());
3961   client_->Reset();
3962 
3963   task_runner_->RunPendingTasks();  // Run deadline of prior BeginFrame.
3964   EXPECT_ACTIONS("RemoveObserver(this)");
3965 
3966   // We'd expect an out-of-order ack for the prior BeginFrame.
3967   has_damage = false;
3968   EXPECT_EQ(viz::BeginFrameAck(first_args, has_damage),
3969             client_->last_begin_frame_ack());
3970   client_->Reset();
3971 }
3972 
TEST_F(SchedulerTest,BeginFrameAckForLateMissedBeginFrame)3973 TEST_F(SchedulerTest, BeginFrameAckForLateMissedBeginFrame) {
3974   SetUpScheduler(EXTERNAL_BFS);
3975 
3976   scheduler_->SetNeedsRedraw();
3977   client_->Reset();
3978 
3979   // Send a missed BeginFrame with a passed deadline.
3980   task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
3981   viz::BeginFrameArgs args =
3982       fake_external_begin_frame_source_->CreateBeginFrameArgs(
3983           BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
3984   args.type = viz::BeginFrameArgs::MISSED;
3985   task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
3986   EXPECT_GT(task_runner_->NowTicks(), args.deadline);
3987   fake_external_begin_frame_source_->TestOnBeginFrame(args);
3988   task_runner_->RunPendingTasks();
3989 
3990   EXPECT_NO_ACTION();
3991   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3992 
3993   // Latest ack should be for the missed BeginFrame that was too late: no
3994   // damage.
3995   bool has_damage = false;
3996   EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3997             client_->last_begin_frame_ack());
3998   client_->Reset();
3999 }
4000 
TEST_F(SchedulerTest,CriticalBeginMainFrameToActivateIsFast)4001 TEST_F(SchedulerTest, CriticalBeginMainFrameToActivateIsFast) {
4002   SetUpScheduler(EXTERNAL_BFS);
4003 
4004   scheduler_->SetNeedsRedraw();
4005   base::TimeDelta estimate_duration = base::TimeDelta::FromMilliseconds(1);
4006   fake_compositor_timing_history_->SetAllEstimatesTo(estimate_duration);
4007 
4008   // If we have a scroll handler but the critical main frame is slow, we should
4009   // still prioritize impl thread latency.
4010   scheduler_->SetTreePrioritiesAndScrollState(
4011       SMOOTHNESS_TAKES_PRIORITY,
4012       ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER);
4013   scheduler_->SetNeedsRedraw();
4014   // An interval of 2ms makes sure that the main frame is considered slow.
4015   base::TimeDelta interval = base::TimeDelta::FromMilliseconds(2);
4016   task_runner_->AdvanceMockTickClock(interval);
4017   viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
4018       BEGINFRAME_FROM_HERE, 0u, 1u, task_runner_->NowTicks(),
4019       task_runner_->NowTicks() + interval, interval,
4020       viz::BeginFrameArgs::NORMAL);
4021   fake_external_begin_frame_source_->TestOnBeginFrame(args);
4022   EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
4023 
4024   task_runner_->RunPendingTasks();  // Run posted deadline to finish the frame.
4025   ASSERT_FALSE(client_->IsInsideBeginImplFrame());
4026 
4027   // Set an interval of 10ms. The bmf_to_activate_interval should be 1*4 = 4ms,
4028   // to account for queue + main_frame + pending_tree + activation durations.
4029   // With a draw time of 1ms and fudge factor of 1ms, the interval available for
4030   // the main frame to be activated is 8ms, so it should be considered fast.
4031   scheduler_->SetNeedsRedraw();
4032   interval = base::TimeDelta::FromMilliseconds(10);
4033   task_runner_->AdvanceMockTickClock(interval);
4034   args = viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 0u, 2u,
4035                                      task_runner_->NowTicks(),
4036                                      task_runner_->NowTicks() + interval,
4037                                      interval, viz::BeginFrameArgs::NORMAL);
4038   fake_external_begin_frame_source_->TestOnBeginFrame(args);
4039   EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
4040 
4041   task_runner_->RunPendingTasks();  // Run posted deadline to finish the frame.
4042   ASSERT_FALSE(client_->IsInsideBeginImplFrame());
4043 
4044   // Increase the draw duration to decrease the time available for the main
4045   // frame. This should prioritize the impl thread.
4046   scheduler_->SetNeedsRedraw();
4047   fake_compositor_timing_history_->SetDrawDurationEstimate(
4048       base::TimeDelta::FromMilliseconds(7));
4049   task_runner_->AdvanceMockTickClock(interval);
4050   args = viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 0u, 3u,
4051                                      task_runner_->NowTicks(),
4052                                      task_runner_->NowTicks() + interval,
4053                                      interval, viz::BeginFrameArgs::NORMAL);
4054   fake_external_begin_frame_source_->TestOnBeginFrame(args);
4055   EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
4056 }
4057 
TEST_F(SchedulerTest,WaitForAllPipelineStagesUsesMissedBeginFrames)4058 TEST_F(SchedulerTest, WaitForAllPipelineStagesUsesMissedBeginFrames) {
4059   scheduler_settings_.wait_for_all_pipeline_stages_before_draw = true;
4060   client_ = std::make_unique<FakeSchedulerClient>();
4061   CreateScheduler(EXTERNAL_BFS);
4062 
4063   // Initialize frame sink so that Scheduler and state machine need BeginFrames.
4064   scheduler_->SetVisible(true);
4065   scheduler_->SetCanDraw(true);
4066   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
4067   client_->Reset();
4068   scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
4069   scheduler_->SetNeedsBeginMainFrame();
4070   EXPECT_TRUE(scheduler_->begin_frames_expected());
4071   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
4072   client_->Reset();
4073 
4074   // Uses MISSED BeginFrames even after the deadline has passed.
4075   base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
4076   task_runner_->AdvanceMockTickClock(interval);
4077   base::TimeTicks timestamp = task_runner_->NowTicks();
4078   // Deadline should have passed after this.
4079   task_runner_->AdvanceMockTickClock(interval * 2);
4080   viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
4081       BEGINFRAME_FROM_HERE, 0u, 1u, timestamp, timestamp + interval, interval,
4082       viz::BeginFrameArgs::MISSED);
4083   fake_external_begin_frame_source_->TestOnBeginFrame(args);
4084   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
4085 }
4086 
TEST_F(SchedulerTest,WaitForAllPipelineStagesAlwaysObservesBeginFrames)4087 TEST_F(SchedulerTest, WaitForAllPipelineStagesAlwaysObservesBeginFrames) {
4088   scheduler_settings_.wait_for_all_pipeline_stages_before_draw = true;
4089   client_ = std::make_unique<FakeSchedulerClient>();
4090   CreateScheduler(EXTERNAL_BFS);
4091 
4092   // Initialize frame sink, request a main frame but defer commits, so that
4093   // state machine is idle.
4094   scheduler_->SetVisible(true);
4095   scheduler_->SetCanDraw(true);
4096   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
4097   client_->Reset();
4098   scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
4099   scheduler_->SetDeferBeginMainFrame(true);
4100   scheduler_->SetNeedsBeginMainFrame();
4101   EXPECT_TRUE(scheduler_->begin_frames_expected());
4102   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
4103   client_->Reset();
4104 
4105   // In full-pipe mode, the SchedulerStateMachine always wants BeginFrames, even
4106   // if it is otherwise idle.
4107   EXPECT_TRUE(scheduler_->begin_frames_expected());
4108   EXPECT_TRUE(scheduler_->BeginFrameNeeded());
4109 
4110   // Scheduler begins a frame even if otherwise idle.
4111   base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
4112   task_runner_->AdvanceMockTickClock(interval);
4113   base::TimeTicks timestamp = task_runner_->NowTicks();
4114   viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
4115       BEGINFRAME_FROM_HERE, 0u, 1u, timestamp, timestamp + interval, interval,
4116       viz::BeginFrameArgs::NORMAL);
4117   fake_external_begin_frame_source_->TestOnBeginFrame(args);
4118   EXPECT_ACTIONS("WillBeginImplFrame");
4119   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
4120   client_->Reset();
4121 
4122   // BeginFrame deadline is not blocked because commits are deferred.
4123   task_runner_->RunPendingTasks();
4124   EXPECT_ACTIONS();
4125   EXPECT_TRUE(!client_->IsInsideBeginImplFrame());
4126   client_->Reset();
4127 }
4128 
TEST_F(SchedulerTest,CriticalBeginMainFrameIsFast_CommitEstimateSlow)4129 TEST_F(SchedulerTest, CriticalBeginMainFrameIsFast_CommitEstimateSlow) {
4130   SetUpScheduler(EXTERNAL_BFS);
4131   scheduler_->SetNeedsBeginMainFrame();
4132   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4133   fake_compositor_timing_history_->SetCommitDurationEstimate(kSlowDuration);
4134   EXPECT_SCOPED(AdvanceFrame());
4135   EXPECT_FALSE(scheduler_->state_machine()
4136                    .critical_begin_main_frame_to_activate_is_fast());
4137 }
4138 
TEST_F(SchedulerTest,CriticalBeginMainFrameIsFast_CommitEstimateFast)4139 TEST_F(SchedulerTest, CriticalBeginMainFrameIsFast_CommitEstimateFast) {
4140   SetUpScheduler(EXTERNAL_BFS);
4141   scheduler_->SetNeedsBeginMainFrame();
4142   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4143   EXPECT_SCOPED(AdvanceFrame());
4144   EXPECT_TRUE(scheduler_->state_machine()
4145                   .critical_begin_main_frame_to_activate_is_fast());
4146 }
4147 
TEST_F(SchedulerTest,ShouldDeferInvalidation_AllEstimatesFast)4148 TEST_F(SchedulerTest, ShouldDeferInvalidation_AllEstimatesFast) {
4149   SetUpScheduler(EXTERNAL_BFS);
4150   scheduler_->SetNeedsBeginMainFrame();
4151   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4152   EXPECT_SCOPED(AdvanceFrame());
4153   EXPECT_TRUE(scheduler_->state_machine()
4154                   .should_defer_invalidation_for_fast_main_frame());
4155 }
4156 
TEST_F(SchedulerTest,ShouldDeferInvalidation_BMFStartToReadyToCommitSlow)4157 TEST_F(SchedulerTest, ShouldDeferInvalidation_BMFStartToReadyToCommitSlow) {
4158   SetUpScheduler(EXTERNAL_BFS);
4159   scheduler_->SetNeedsBeginMainFrame();
4160   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4161   fake_compositor_timing_history_
4162       ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(kSlowDuration);
4163   EXPECT_SCOPED(AdvanceFrame());
4164   EXPECT_FALSE(scheduler_->state_machine()
4165                    .should_defer_invalidation_for_fast_main_frame());
4166 }
4167 
TEST_F(SchedulerTest,ShouldDeferInvalidation_BMFQueueDurationCriticalSlow)4168 TEST_F(SchedulerTest, ShouldDeferInvalidation_BMFQueueDurationCriticalSlow) {
4169   SetUpScheduler(EXTERNAL_BFS);
4170   scheduler_->SetNeedsBeginMainFrame();
4171   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4172   fake_compositor_timing_history_
4173       ->SetBeginMainFrameQueueDurationCriticalEstimate(kSlowDuration);
4174   EXPECT_SCOPED(AdvanceFrame());
4175   EXPECT_FALSE(scheduler_->state_machine()
4176                    .should_defer_invalidation_for_fast_main_frame());
4177 }
4178 
TEST_F(SchedulerTest,ShouldDeferInvalidation_BMFQueueDurationNotCriticalSlow)4179 TEST_F(SchedulerTest, ShouldDeferInvalidation_BMFQueueDurationNotCriticalSlow) {
4180   SetUpScheduler(EXTERNAL_BFS);
4181   scheduler_->SetNeedsBeginMainFrame();
4182   scheduler_->SetTreePrioritiesAndScrollState(
4183       TreePriority::SMOOTHNESS_TAKES_PRIORITY,
4184       ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
4185   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4186   fake_compositor_timing_history_
4187       ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
4188   EXPECT_SCOPED(AdvanceFrame());
4189   EXPECT_FALSE(scheduler_->state_machine()
4190                    .should_defer_invalidation_for_fast_main_frame());
4191 }
4192 
TEST_F(SchedulerTest,SlowMainThreadButEstimatedFastTriggersInvalidations)4193 TEST_F(SchedulerTest, SlowMainThreadButEstimatedFastTriggersInvalidations) {
4194   SetUpScheduler(EXTERNAL_BFS);
4195   scheduler_->SetNeedsBeginMainFrame();
4196   scheduler_->SetNeedsImplSideInvalidation(true);
4197   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4198 
4199   // Main thread is estimated fast, invalidation will be deferred.
4200   client_->Reset();
4201   EXPECT_SCOPED(AdvanceFrame());
4202   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4203 
4204   // Draw deadline.
4205   client_->Reset();
4206   task_runner_->RunPendingTasks();
4207   EXPECT_ACTIONS();
4208 
4209   // Next frame. The invalidation should not be throttled.
4210   client_->Reset();
4211   EXPECT_SCOPED(AdvanceFrame());
4212   EXPECT_ACTIONS("WillBeginImplFrame",
4213                  "ScheduledActionPerformImplSideInvalidation");
4214 }
4215 
TEST_F(SchedulerTest,SlowMainThreadRasterButEstimatedFastDoesNotTriggersInvalidations)4216 TEST_F(SchedulerTest,
4217        SlowMainThreadRasterButEstimatedFastDoesNotTriggersInvalidations) {
4218   SetUpScheduler(EXTERNAL_BFS);
4219   scheduler_->SetNeedsBeginMainFrame();
4220   scheduler_->SetNeedsImplSideInvalidation(true);
4221   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4222 
4223   // Main thread is estimated fast, invalidation will be deferred.
4224   client_->Reset();
4225   EXPECT_SCOPED(AdvanceFrame());
4226   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4227 
4228   // Commit before deadline but not ready to activate.
4229   client_->Reset();
4230   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
4231   scheduler_->NotifyReadyToCommit(nullptr);
4232   EXPECT_ACTIONS("ScheduledActionCommit");
4233 
4234   // Draw deadline.
4235   client_->Reset();
4236   task_runner_->RunPendingTasks();
4237   EXPECT_ACTIONS();
4238 
4239   // Next frame. The invalidation should still be throttled.
4240   client_->Reset();
4241   EXPECT_SCOPED(AdvanceFrame());
4242   EXPECT_ACTIONS("WillBeginImplFrame");
4243 }
4244 
TEST_F(SchedulerTest,SynchronousCompositorImplSideInvalidation)4245 TEST_F(SchedulerTest, SynchronousCompositorImplSideInvalidation) {
4246   // Synchronous compositor doesn't have a deadline and our heuristics can't
4247   // work. We should never be prioritizing impl-side invalidations over main
4248   // frames.
4249   scheduler_settings_.using_synchronous_renderer_compositor = true;
4250   SetUpScheduler(EXTERNAL_BFS);
4251 
4252   fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
4253   scheduler_->SetNeedsBeginMainFrame();
4254   const bool needs_first_draw_on_activation = true;
4255   scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
4256   client_->Reset();
4257   EXPECT_SCOPED(AdvanceFrame());
4258   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4259 }
4260 
TEST_F(SchedulerTest,DontSkipMainFrameAfterClearingHistory)4261 TEST_F(SchedulerTest, DontSkipMainFrameAfterClearingHistory) {
4262   // Set up a fast estimate for the main frame and make it miss the deadline.
4263   scheduler_settings_.main_frame_before_activation_enabled = true;
4264   SetUpScheduler(EXTERNAL_BFS);
4265   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4266   client_->Reset();
4267   scheduler_->SetNeedsBeginMainFrame();
4268   EXPECT_SCOPED(AdvanceFrame());
4269   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
4270   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
4271                  "ScheduledActionSendBeginMainFrame");
4272 
4273   // Now commit during the second frame, since the main thread missed the last
4274   // deadline but we have a fast estimate, we would want to skip the next main
4275   // frame.
4276   client_->Reset();
4277   EXPECT_SCOPED(AdvanceFrame());
4278   scheduler_->SetNeedsBeginMainFrame();
4279   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
4280   scheduler_->NotifyReadyToCommit(nullptr);
4281   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionCommit");
4282 
4283   // But during the commit, the history is cleared. So the main frame should not
4284   // be skipped.
4285   client_->Reset();
4286   scheduler_->ClearHistory();
4287   EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
4288 }
4289 
TEST_F(SchedulerTest,NoInvalidationForAnimateOnlyFrames)4290 TEST_F(SchedulerTest, NoInvalidationForAnimateOnlyFrames) {
4291   SetUpScheduler(EXTERNAL_BFS);
4292   fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4293   client_->Reset();
4294   scheduler_->SetNeedsImplSideInvalidation(true);
4295 
4296   bool animate_only = true;
4297   EXPECT_SCOPED(AdvanceFrame(animate_only));
4298   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame");
4299   client_->Reset();
4300   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
4301   EXPECT_ACTIONS();
4302 
4303   // Now send a frame which requires full updates.
4304   animate_only = false;
4305   EXPECT_SCOPED(AdvanceFrame(animate_only));
4306   EXPECT_ACTIONS("WillBeginImplFrame",
4307                  "ScheduledActionPerformImplSideInvalidation");
4308   client_->Reset();
4309   task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
4310   EXPECT_ACTIONS();
4311 }
4312 
TEST_F(SchedulerTest,SendEarlyDidNotProduceFrameIfIdle)4313 TEST_F(SchedulerTest, SendEarlyDidNotProduceFrameIfIdle) {
4314   SetUpScheduler(EXTERNAL_BFS);
4315   scheduler_->SetNeedsBeginMainFrame();
4316 
4317   client_->Reset();
4318   EXPECT_SCOPED(AdvanceFrame());
4319   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4320   auto begin_main_frame_args = client_->last_begin_main_frame_args();
4321   EXPECT_NE(client_->last_begin_frame_ack().frame_id.sequence_number,
4322             begin_main_frame_args.frame_id.sequence_number);
4323 
4324   client_->Reset();
4325   scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
4326   // Request a new commit before finishing the current one to simulate behavior
4327   // seen in certain OOPIF renderers.
4328   scheduler_->SetNeedsBeginMainFrame();
4329   scheduler_->BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
4330   EXPECT_EQ(client_->last_begin_frame_ack().frame_id.sequence_number,
4331             begin_main_frame_args.frame_id.sequence_number);
4332 }
4333 
4334 }  // namespace
4335 }  // namespace cc
4336