Home | History | Annotate | Download | only in scheduler
      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 #include "cc/scheduler/scheduler.h"
      5 
      6 #include <string>
      7 #include <vector>
      8 
      9 #include "base/debug/trace_event.h"
     10 #include "base/logging.h"
     11 #include "base/memory/scoped_vector.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/run_loop.h"
     14 #include "base/time/time.h"
     15 #include "cc/test/begin_frame_args_test.h"
     16 #include "cc/test/ordered_simple_task_runner.h"
     17 #include "cc/test/scheduler_test_common.h"
     18 #include "testing/gmock/include/gmock/gmock.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
     22   do {                                                                    \
     23     EXPECT_EQ(expected_num_actions, client.num_actions_());               \
     24     if (action_index >= 0) {                                              \
     25       ASSERT_LT(action_index, client.num_actions_()) << scheduler;        \
     26       EXPECT_STREQ(action, client.Action(action_index));                  \
     27     }                                                                     \
     28     for (int i = expected_num_actions; i < client.num_actions_(); ++i)    \
     29       ADD_FAILURE() << "Unexpected action: " << client.Action(i)          \
     30                     << " with state:\n" << client.StateForAction(i);      \
     31   } while (false)
     32 
     33 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
     34 
     35 #define EXPECT_SINGLE_ACTION(action, client) \
     36   EXPECT_ACTION(action, client, 0, 1)
     37 
     38 namespace cc {
     39 namespace {
     40 
     41 class FakeSchedulerClient;
     42 
     43 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
     44                                            FakeSchedulerClient* client);
     45 
     46 class FakeSchedulerClient : public SchedulerClient {
     47  public:
     48   FakeSchedulerClient()
     49       : needs_begin_frame_(false),
     50         automatic_swap_ack_(true),
     51         swap_contains_incomplete_tile_(false),
     52         redraw_will_happen_if_update_visible_tiles_happens_(false),
     53         now_src_(TestNowSource::Create()) {
     54     Reset();
     55   }
     56 
     57   void Reset() {
     58     actions_.clear();
     59     states_.clear();
     60     draw_will_happen_ = true;
     61     swap_will_happen_if_draw_happens_ = true;
     62     num_draws_ = 0;
     63     log_anticipated_draw_time_change_ = false;
     64   }
     65 
     66   TestScheduler* CreateScheduler(const SchedulerSettings& settings) {
     67     scheduler_ = TestScheduler::Create(now_src_, this, settings, 0);
     68     // Fail if we need to run 100 tasks in a row.
     69     task_runner().SetRunTaskLimit(100);
     70     return scheduler_.get();
     71   }
     72 
     73   // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
     74   // for tests that do.
     75   void set_log_anticipated_draw_time_change(bool log) {
     76     log_anticipated_draw_time_change_ = log;
     77   }
     78   bool needs_begin_frame() { return needs_begin_frame_; }
     79   int num_draws() const { return num_draws_; }
     80   int num_actions_() const { return static_cast<int>(actions_.size()); }
     81   const char* Action(int i) const { return actions_[i]; }
     82   std::string StateForAction(int i) const { return states_[i]->ToString(); }
     83   base::TimeTicks posted_begin_impl_frame_deadline() const {
     84     return posted_begin_impl_frame_deadline_;
     85   }
     86 
     87   void AdvanceFrame() {
     88     bool external_begin_frame =
     89         scheduler_->settings().begin_frame_scheduling_enabled &&
     90         scheduler_->settings().throttle_frame_production;
     91 
     92     if (external_begin_frame) {
     93       scheduler_->BeginFrame(CreateBeginFrameArgsForTesting(now_src_));
     94     }
     95 
     96     EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(false)));
     97     EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
     98   }
     99 
    100   OrderedSimpleTaskRunner& task_runner() { return scheduler_->task_runner(); }
    101   TestNowSource* now_src() { return now_src_.get(); }
    102 
    103   int ActionIndex(const char* action) const {
    104     for (size_t i = 0; i < actions_.size(); i++)
    105       if (!strcmp(actions_[i], action))
    106         return i;
    107     return -1;
    108   }
    109 
    110   void SetSwapContainsIncompleteTile(bool contain) {
    111     swap_contains_incomplete_tile_ = contain;
    112   }
    113 
    114   bool HasAction(const char* action) const {
    115     return ActionIndex(action) >= 0;
    116   }
    117 
    118   void SetDrawWillHappen(bool draw_will_happen) {
    119     draw_will_happen_ = draw_will_happen;
    120   }
    121   void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
    122     swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
    123   }
    124   void SetAutomaticSwapAck(bool automatic_swap_ack) {
    125     automatic_swap_ack_ = automatic_swap_ack;
    126   }
    127   void SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw) {
    128     redraw_will_happen_if_update_visible_tiles_happens_ = redraw;
    129   }
    130   // SchedulerClient implementation.
    131   virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
    132     actions_.push_back("SetNeedsBeginFrame");
    133     states_.push_back(scheduler_->AsValue());
    134     needs_begin_frame_ = enable;
    135   }
    136   virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
    137     actions_.push_back("WillBeginImplFrame");
    138     states_.push_back(scheduler_->AsValue());
    139   }
    140   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
    141     actions_.push_back("ScheduledActionSendBeginMainFrame");
    142     states_.push_back(scheduler_->AsValue());
    143   }
    144   virtual void ScheduledActionAnimate() OVERRIDE {
    145     actions_.push_back("ScheduledActionAnimate");
    146     states_.push_back(scheduler_->AsValue());
    147   }
    148   virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
    149     actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
    150     states_.push_back(scheduler_->AsValue());
    151     num_draws_++;
    152     DrawResult result =
    153         draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
    154     bool swap_will_happen =
    155         draw_will_happen_ && swap_will_happen_if_draw_happens_;
    156     if (swap_will_happen) {
    157       scheduler_->DidSwapBuffers();
    158       if (swap_contains_incomplete_tile_) {
    159         scheduler_->SetSwapUsedIncompleteTile(true);
    160         swap_contains_incomplete_tile_ = false;
    161       } else {
    162         scheduler_->SetSwapUsedIncompleteTile(false);
    163       }
    164 
    165       if (automatic_swap_ack_)
    166         scheduler_->DidSwapBuffersComplete();
    167     }
    168     return result;
    169   }
    170   virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
    171     actions_.push_back("ScheduledActionDrawAndSwapForced");
    172     states_.push_back(scheduler_->AsValue());
    173     return DRAW_SUCCESS;
    174   }
    175   virtual void ScheduledActionCommit() OVERRIDE {
    176     actions_.push_back("ScheduledActionCommit");
    177     states_.push_back(scheduler_->AsValue());
    178   }
    179   virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
    180     actions_.push_back("ScheduledActionUpdateVisibleTiles");
    181     states_.push_back(scheduler_->AsValue());
    182     if (redraw_will_happen_if_update_visible_tiles_happens_)
    183       scheduler_->SetNeedsRedraw();
    184   }
    185   virtual void ScheduledActionActivateSyncTree() OVERRIDE {
    186     actions_.push_back("ScheduledActionActivateSyncTree");
    187     states_.push_back(scheduler_->AsValue());
    188   }
    189   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
    190     actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
    191     states_.push_back(scheduler_->AsValue());
    192   }
    193   virtual void ScheduledActionManageTiles() OVERRIDE {
    194     actions_.push_back("ScheduledActionManageTiles");
    195     states_.push_back(scheduler_->AsValue());
    196   }
    197   virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
    198     if (log_anticipated_draw_time_change_)
    199       actions_.push_back("DidAnticipatedDrawTimeChange");
    200   }
    201   virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
    202     return base::TimeDelta();
    203   }
    204   virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
    205     return base::TimeDelta();
    206   }
    207   virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
    208     return base::TimeDelta();
    209   }
    210 
    211   virtual void DidBeginImplFrameDeadline() OVERRIDE {}
    212 
    213   base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
    214     return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
    215                       base::Unretained(this),
    216                       state);
    217   }
    218 
    219  protected:
    220   bool ImplFrameDeadlinePendingCallback(bool state) {
    221     return scheduler_->BeginImplFrameDeadlinePending() == state;
    222   }
    223 
    224   bool needs_begin_frame_;
    225   bool draw_will_happen_;
    226   bool swap_will_happen_if_draw_happens_;
    227   bool automatic_swap_ack_;
    228   int num_draws_;
    229   bool log_anticipated_draw_time_change_;
    230   bool swap_contains_incomplete_tile_;
    231   bool redraw_will_happen_if_update_visible_tiles_happens_;
    232   base::TimeTicks posted_begin_impl_frame_deadline_;
    233   std::vector<const char*> actions_;
    234   std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat> > states_;
    235   scoped_ptr<TestScheduler> scheduler_;
    236   scoped_refptr<TestNowSource> now_src_;
    237 };
    238 
    239 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
    240                                            FakeSchedulerClient* client) {
    241   TRACE_EVENT0("cc",
    242                "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
    243 
    244   scheduler->DidCreateAndInitializeOutputSurface();
    245   scheduler->SetNeedsCommit();
    246   scheduler->NotifyBeginMainFrameStarted();
    247   scheduler->NotifyReadyToCommit();
    248   if (scheduler->settings().impl_side_painting)
    249     scheduler->NotifyReadyToActivate();
    250 
    251   // Go through the motions to draw the commit.
    252   client->AdvanceFrame();
    253 
    254   // Run the posted deadline task.
    255   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    256   client->task_runner().RunTasksWhile(client->ImplFrameDeadlinePending(true));
    257   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    258 
    259   // We need another BeginImplFrame so Scheduler calls
    260   // SetNeedsBeginFrame(false).
    261   client->AdvanceFrame();
    262 
    263   // Run the posted deadline task.
    264   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    265   client->task_runner().RunTasksWhile(client->ImplFrameDeadlinePending(true));
    266   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    267 }
    268 
    269 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
    270   FakeSchedulerClient client;
    271   SchedulerSettings default_scheduler_settings;
    272   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    273   scheduler->SetCanStart();
    274   scheduler->SetVisible(true);
    275   scheduler->SetCanDraw(true);
    276 
    277   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
    278   client.Reset();
    279   scheduler->DidCreateAndInitializeOutputSurface();
    280   EXPECT_NO_ACTION(client);
    281 }
    282 
    283 TEST(SchedulerTest, RequestCommit) {
    284   FakeSchedulerClient client;
    285   SchedulerSettings scheduler_settings;
    286   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
    287   scheduler->SetCanStart();
    288   scheduler->SetVisible(true);
    289   scheduler->SetCanDraw(true);
    290 
    291   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
    292   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    293 
    294   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
    295   client.Reset();
    296   scheduler->SetNeedsCommit();
    297   EXPECT_TRUE(client.needs_begin_frame());
    298   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
    299   client.Reset();
    300 
    301   client.AdvanceFrame();
    302   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    303   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
    304   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    305   EXPECT_TRUE(client.needs_begin_frame());
    306   client.Reset();
    307 
    308   // If we don't swap on the deadline, we wait for the next BeginFrame.
    309   client.task_runner().RunPendingTasks();  // Run posted deadline.
    310   EXPECT_NO_ACTION(client);
    311   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    312   EXPECT_TRUE(client.needs_begin_frame());
    313   client.Reset();
    314 
    315   // NotifyReadyToCommit should trigger the commit.
    316   scheduler->NotifyBeginMainFrameStarted();
    317   scheduler->NotifyReadyToCommit();
    318   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
    319   EXPECT_TRUE(client.needs_begin_frame());
    320   client.Reset();
    321 
    322   // BeginImplFrame should prepare the draw.
    323   client.AdvanceFrame();
    324   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    325   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    326   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    327   EXPECT_TRUE(client.needs_begin_frame());
    328   client.Reset();
    329 
    330   // BeginImplFrame deadline should draw.
    331   client.task_runner().RunPendingTasks();  // Run posted deadline.
    332   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
    333   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    334   EXPECT_TRUE(client.needs_begin_frame());
    335   client.Reset();
    336 
    337   // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
    338   // to avoid excessive toggles.
    339   client.AdvanceFrame();
    340   EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
    341   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    342   client.Reset();
    343 
    344   client.task_runner().RunPendingTasks();  // Run posted deadline.
    345   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
    346   EXPECT_FALSE(client.needs_begin_frame());
    347   client.Reset();
    348 }
    349 
    350 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
    351   FakeSchedulerClient client;
    352   SchedulerSettings scheduler_settings;
    353   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
    354   scheduler->SetCanStart();
    355   scheduler->SetVisible(true);
    356   scheduler->SetCanDraw(true);
    357 
    358   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
    359   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    360   client.Reset();
    361 
    362   // SetNeedsCommit should begin the frame.
    363   scheduler->SetNeedsCommit();
    364   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
    365 
    366   client.Reset();
    367   client.AdvanceFrame();
    368   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    369   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
    370   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    371 
    372   EXPECT_TRUE(client.needs_begin_frame());
    373   client.Reset();
    374 
    375   // Now SetNeedsCommit again. Calling here means we need a second commit.
    376   scheduler->SetNeedsCommit();
    377   EXPECT_EQ(client.num_actions_(), 0);
    378   client.Reset();
    379 
    380   // Finish the first commit.
    381   scheduler->NotifyBeginMainFrameStarted();
    382   scheduler->NotifyReadyToCommit();
    383   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
    384   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    385   client.Reset();
    386   client.task_runner().RunPendingTasks();  // Run posted deadline.
    387   EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
    388   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
    389   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    390 
    391   // Because we just swapped, the Scheduler should also request the next
    392   // BeginImplFrame from the OutputSurface.
    393   EXPECT_TRUE(client.needs_begin_frame());
    394   client.Reset();
    395   // Since another commit is needed, the next BeginImplFrame should initiate
    396   // the second commit.
    397   client.AdvanceFrame();
    398   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    399   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
    400   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    401   client.Reset();
    402 
    403   // Finishing the commit before the deadline should post a new deadline task
    404   // to trigger the deadline early.
    405   scheduler->NotifyBeginMainFrameStarted();
    406   scheduler->NotifyReadyToCommit();
    407   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
    408   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    409   client.Reset();
    410   client.task_runner().RunPendingTasks();  // Run posted deadline.
    411   EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
    412   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
    413   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    414   EXPECT_TRUE(client.needs_begin_frame());
    415   client.Reset();
    416 
    417   // On the next BeginImplFrame, verify we go back to a quiescent state and
    418   // no longer request BeginImplFrames.
    419   client.AdvanceFrame();
    420   client.task_runner().RunPendingTasks();  // Run posted deadline.
    421   EXPECT_FALSE(client.needs_begin_frame());
    422   client.Reset();
    423 }
    424 
    425 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
    426  public:
    427   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
    428   virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
    429       OVERRIDE {
    430     // Only SetNeedsRedraw the first time this is called
    431     if (!num_draws_)
    432       scheduler_->SetNeedsRedraw();
    433     return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
    434   }
    435 
    436   virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
    437     NOTREACHED();
    438     return DRAW_SUCCESS;
    439   }
    440 
    441   virtual void ScheduledActionCommit() OVERRIDE {}
    442   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
    443   virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
    444 };
    445 
    446 // Tests for two different situations:
    447 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
    448 //    a ScheduledActionDrawAndSwap
    449 // 2. the scheduler drawing twice inside a single tick
    450 TEST(SchedulerTest, RequestRedrawInsideDraw) {
    451   SchedulerClientThatsetNeedsDrawInsideDraw client;
    452   SchedulerSettings default_scheduler_settings;
    453   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    454   scheduler->SetCanStart();
    455   scheduler->SetVisible(true);
    456   scheduler->SetCanDraw(true);
    457   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    458   client.Reset();
    459 
    460   scheduler->SetNeedsRedraw();
    461   EXPECT_TRUE(scheduler->RedrawPending());
    462   EXPECT_TRUE(client.needs_begin_frame());
    463   EXPECT_EQ(0, client.num_draws());
    464 
    465   client.AdvanceFrame();
    466   client.task_runner().RunPendingTasks();  // Run posted deadline.
    467   EXPECT_EQ(1, client.num_draws());
    468   EXPECT_TRUE(scheduler->RedrawPending());
    469   EXPECT_TRUE(client.needs_begin_frame());
    470 
    471   client.AdvanceFrame();
    472   client.task_runner().RunPendingTasks();  // Run posted deadline.
    473   EXPECT_EQ(2, client.num_draws());
    474   EXPECT_FALSE(scheduler->RedrawPending());
    475   EXPECT_TRUE(client.needs_begin_frame());
    476 
    477   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
    478   // swap.
    479   client.AdvanceFrame();
    480   client.task_runner().RunPendingTasks();  // Run posted deadline.
    481   EXPECT_EQ(2, client.num_draws());
    482   EXPECT_FALSE(scheduler->RedrawPending());
    483   EXPECT_FALSE(client.needs_begin_frame());
    484 }
    485 
    486 // Test that requesting redraw inside a failed draw doesn't lose the request.
    487 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
    488   SchedulerClientThatsetNeedsDrawInsideDraw client;
    489   SchedulerSettings default_scheduler_settings;
    490   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    491   scheduler->SetCanStart();
    492   scheduler->SetVisible(true);
    493   scheduler->SetCanDraw(true);
    494   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    495   client.Reset();
    496 
    497   client.SetDrawWillHappen(false);
    498 
    499   scheduler->SetNeedsRedraw();
    500   EXPECT_TRUE(scheduler->RedrawPending());
    501   EXPECT_TRUE(client.needs_begin_frame());
    502   EXPECT_EQ(0, client.num_draws());
    503 
    504   // Fail the draw.
    505   client.AdvanceFrame();
    506   client.task_runner().RunPendingTasks();  // Run posted deadline.
    507   EXPECT_EQ(1, client.num_draws());
    508 
    509   // We have a commit pending and the draw failed, and we didn't lose the redraw
    510   // request.
    511   EXPECT_TRUE(scheduler->CommitPending());
    512   EXPECT_TRUE(scheduler->RedrawPending());
    513   EXPECT_TRUE(client.needs_begin_frame());
    514 
    515   // Fail the draw again.
    516   client.AdvanceFrame();
    517   client.task_runner().RunPendingTasks();  // Run posted deadline.
    518   EXPECT_EQ(2, client.num_draws());
    519   EXPECT_TRUE(scheduler->CommitPending());
    520   EXPECT_TRUE(scheduler->RedrawPending());
    521   EXPECT_TRUE(client.needs_begin_frame());
    522 
    523   // Draw successfully.
    524   client.SetDrawWillHappen(true);
    525   client.AdvanceFrame();
    526   client.task_runner().RunPendingTasks();  // Run posted deadline.
    527   EXPECT_EQ(3, client.num_draws());
    528   EXPECT_TRUE(scheduler->CommitPending());
    529   EXPECT_FALSE(scheduler->RedrawPending());
    530   EXPECT_TRUE(client.needs_begin_frame());
    531 }
    532 
    533 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
    534  public:
    535   SchedulerClientThatSetNeedsCommitInsideDraw()
    536       : set_needs_commit_on_next_draw_(false) {}
    537 
    538   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
    539   virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
    540       OVERRIDE {
    541     // Only SetNeedsCommit the first time this is called
    542     if (set_needs_commit_on_next_draw_) {
    543       scheduler_->SetNeedsCommit();
    544       set_needs_commit_on_next_draw_ = false;
    545     }
    546     return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
    547   }
    548 
    549   virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
    550     NOTREACHED();
    551     return DRAW_SUCCESS;
    552   }
    553 
    554   virtual void ScheduledActionCommit() OVERRIDE {}
    555   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
    556   virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
    557 
    558   void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
    559 
    560  private:
    561   bool set_needs_commit_on_next_draw_;
    562 };
    563 
    564 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
    565 // happen inside a ScheduledActionDrawAndSwap
    566 TEST(SchedulerTest, RequestCommitInsideDraw) {
    567   SchedulerClientThatSetNeedsCommitInsideDraw client;
    568   SchedulerSettings default_scheduler_settings;
    569   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    570   scheduler->SetCanStart();
    571   scheduler->SetVisible(true);
    572   scheduler->SetCanDraw(true);
    573   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    574   client.Reset();
    575 
    576   EXPECT_FALSE(client.needs_begin_frame());
    577   scheduler->SetNeedsRedraw();
    578   EXPECT_TRUE(scheduler->RedrawPending());
    579   EXPECT_EQ(0, client.num_draws());
    580   EXPECT_TRUE(client.needs_begin_frame());
    581 
    582   client.SetNeedsCommitOnNextDraw();
    583   client.AdvanceFrame();
    584   client.SetNeedsCommitOnNextDraw();
    585   client.task_runner().RunPendingTasks();  // Run posted deadline.
    586   EXPECT_EQ(1, client.num_draws());
    587   EXPECT_TRUE(scheduler->CommitPending());
    588   EXPECT_TRUE(client.needs_begin_frame());
    589   scheduler->NotifyBeginMainFrameStarted();
    590   scheduler->NotifyReadyToCommit();
    591 
    592   client.AdvanceFrame();
    593   client.task_runner().RunPendingTasks();  // Run posted deadline.
    594   EXPECT_EQ(2, client.num_draws());
    595 
    596   EXPECT_FALSE(scheduler->RedrawPending());
    597   EXPECT_FALSE(scheduler->CommitPending());
    598   EXPECT_TRUE(client.needs_begin_frame());
    599 
    600   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
    601   // swap.
    602   client.AdvanceFrame();
    603   client.task_runner().RunPendingTasks();  // Run posted deadline.
    604   EXPECT_EQ(2, client.num_draws());
    605   EXPECT_FALSE(scheduler->RedrawPending());
    606   EXPECT_FALSE(scheduler->CommitPending());
    607   EXPECT_FALSE(client.needs_begin_frame());
    608 }
    609 
    610 // Tests that when a draw fails then the pending commit should not be dropped.
    611 TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
    612   SchedulerClientThatsetNeedsDrawInsideDraw client;
    613   SchedulerSettings default_scheduler_settings;
    614   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    615   scheduler->SetCanStart();
    616   scheduler->SetVisible(true);
    617   scheduler->SetCanDraw(true);
    618   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    619   client.Reset();
    620 
    621   client.SetDrawWillHappen(false);
    622 
    623   scheduler->SetNeedsRedraw();
    624   EXPECT_TRUE(scheduler->RedrawPending());
    625   EXPECT_TRUE(client.needs_begin_frame());
    626   EXPECT_EQ(0, client.num_draws());
    627 
    628   // Fail the draw.
    629   client.AdvanceFrame();
    630   client.task_runner().RunPendingTasks();  // Run posted deadline.
    631   EXPECT_EQ(1, client.num_draws());
    632 
    633   // We have a commit pending and the draw failed, and we didn't lose the commit
    634   // request.
    635   EXPECT_TRUE(scheduler->CommitPending());
    636   EXPECT_TRUE(scheduler->RedrawPending());
    637   EXPECT_TRUE(client.needs_begin_frame());
    638 
    639   // Fail the draw again.
    640   client.AdvanceFrame();
    641 
    642   client.task_runner().RunPendingTasks();  // Run posted deadline.
    643   EXPECT_EQ(2, client.num_draws());
    644   EXPECT_TRUE(scheduler->CommitPending());
    645   EXPECT_TRUE(scheduler->RedrawPending());
    646   EXPECT_TRUE(client.needs_begin_frame());
    647 
    648   // Draw successfully.
    649   client.SetDrawWillHappen(true);
    650   client.AdvanceFrame();
    651   client.task_runner().RunPendingTasks();  // Run posted deadline.
    652   EXPECT_EQ(3, client.num_draws());
    653   EXPECT_TRUE(scheduler->CommitPending());
    654   EXPECT_FALSE(scheduler->RedrawPending());
    655   EXPECT_TRUE(client.needs_begin_frame());
    656 }
    657 
    658 TEST(SchedulerTest, NoSwapWhenDrawFails) {
    659   SchedulerClientThatSetNeedsCommitInsideDraw client;
    660   SchedulerSettings default_scheduler_settings;
    661   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    662   scheduler->SetCanStart();
    663   scheduler->SetVisible(true);
    664   scheduler->SetCanDraw(true);
    665   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    666   client.Reset();
    667 
    668   scheduler->SetNeedsRedraw();
    669   EXPECT_TRUE(scheduler->RedrawPending());
    670   EXPECT_TRUE(client.needs_begin_frame());
    671   EXPECT_EQ(0, client.num_draws());
    672 
    673   // Draw successfully, this starts a new frame.
    674   client.SetNeedsCommitOnNextDraw();
    675   client.AdvanceFrame();
    676   client.task_runner().RunPendingTasks();  // Run posted deadline.
    677   EXPECT_EQ(1, client.num_draws());
    678 
    679   scheduler->SetNeedsRedraw();
    680   EXPECT_TRUE(scheduler->RedrawPending());
    681   EXPECT_TRUE(client.needs_begin_frame());
    682 
    683   // Fail to draw, this should not start a frame.
    684   client.SetDrawWillHappen(false);
    685   client.SetNeedsCommitOnNextDraw();
    686   client.AdvanceFrame();
    687   client.task_runner().RunPendingTasks();  // Run posted deadline.
    688   EXPECT_EQ(2, client.num_draws());
    689 }
    690 
    691 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
    692  public:
    693   virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
    694       OVERRIDE {
    695     scheduler_->SetNeedsManageTiles();
    696     return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
    697   }
    698 };
    699 
    700 // Test manage tiles is independant of draws.
    701 TEST(SchedulerTest, ManageTiles) {
    702   SchedulerClientNeedsManageTilesInDraw client;
    703   SchedulerSettings default_scheduler_settings;
    704   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    705   scheduler->SetCanStart();
    706   scheduler->SetVisible(true);
    707   scheduler->SetCanDraw(true);
    708   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    709 
    710   // Request both draw and manage tiles. ManageTiles shouldn't
    711   // be trigged until BeginImplFrame.
    712   client.Reset();
    713   scheduler->SetNeedsManageTiles();
    714   scheduler->SetNeedsRedraw();
    715   EXPECT_TRUE(scheduler->RedrawPending());
    716   EXPECT_TRUE(scheduler->ManageTilesPending());
    717   EXPECT_TRUE(client.needs_begin_frame());
    718   EXPECT_EQ(0, client.num_draws());
    719   EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
    720   EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    721 
    722   // We have no immediate actions to perform, so the BeginImplFrame should post
    723   // the deadline task.
    724   client.Reset();
    725   client.AdvanceFrame();
    726   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    727   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    728   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    729 
    730   // On the deadline, he actions should have occured in the right order.
    731   client.Reset();
    732   client.task_runner().RunPendingTasks();  // Run posted deadline.
    733   EXPECT_EQ(1, client.num_draws());
    734   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    735   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
    736   EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
    737             client.ActionIndex("ScheduledActionManageTiles"));
    738   EXPECT_FALSE(scheduler->RedrawPending());
    739   EXPECT_FALSE(scheduler->ManageTilesPending());
    740   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    741 
    742   // Request a draw. We don't need a ManageTiles yet.
    743   client.Reset();
    744   scheduler->SetNeedsRedraw();
    745   EXPECT_TRUE(scheduler->RedrawPending());
    746   EXPECT_FALSE(scheduler->ManageTilesPending());
    747   EXPECT_TRUE(client.needs_begin_frame());
    748   EXPECT_EQ(0, client.num_draws());
    749 
    750   // We have no immediate actions to perform, so the BeginImplFrame should post
    751   // the deadline task.
    752   client.Reset();
    753   client.AdvanceFrame();
    754   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    755   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    756   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    757 
    758   // Draw. The draw will trigger SetNeedsManageTiles, and
    759   // then the ManageTiles action will be triggered after the Draw.
    760   // Afterwards, neither a draw nor ManageTiles are pending.
    761   client.Reset();
    762   client.task_runner().RunPendingTasks();  // Run posted deadline.
    763   EXPECT_EQ(1, client.num_draws());
    764   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    765   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
    766   EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
    767             client.ActionIndex("ScheduledActionManageTiles"));
    768   EXPECT_FALSE(scheduler->RedrawPending());
    769   EXPECT_FALSE(scheduler->ManageTilesPending());
    770   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    771 
    772   // We need a BeginImplFrame where we don't swap to go idle.
    773   client.Reset();
    774   client.AdvanceFrame();
    775   EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
    776   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    777   client.Reset();
    778   client.task_runner().RunPendingTasks();  // Run posted deadline.
    779   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
    780   EXPECT_FALSE(client.needs_begin_frame());
    781   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    782   EXPECT_EQ(0, client.num_draws());
    783 
    784   // Now trigger a ManageTiles outside of a draw. We will then need
    785   // a begin-frame for the ManageTiles, but we don't need a draw.
    786   client.Reset();
    787   EXPECT_FALSE(client.needs_begin_frame());
    788   scheduler->SetNeedsManageTiles();
    789   EXPECT_TRUE(client.needs_begin_frame());
    790   EXPECT_TRUE(scheduler->ManageTilesPending());
    791   EXPECT_FALSE(scheduler->RedrawPending());
    792 
    793   // BeginImplFrame. There will be no draw, only ManageTiles.
    794   client.Reset();
    795   client.AdvanceFrame();
    796   EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
    797   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    798   client.Reset();
    799   client.task_runner().RunPendingTasks();  // Run posted deadline.
    800   EXPECT_EQ(0, client.num_draws());
    801   EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    802   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
    803   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    804 }
    805 
    806 // Test that ManageTiles only happens once per frame.  If an external caller
    807 // initiates it, then the state machine should not ManageTiles on that frame.
    808 TEST(SchedulerTest, ManageTilesOncePerFrame) {
    809   FakeSchedulerClient client;
    810   SchedulerSettings default_scheduler_settings;
    811   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    812   scheduler->SetCanStart();
    813   scheduler->SetVisible(true);
    814   scheduler->SetCanDraw(true);
    815   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    816 
    817   // If DidManageTiles during a frame, then ManageTiles should not occur again.
    818   scheduler->SetNeedsManageTiles();
    819   scheduler->SetNeedsRedraw();
    820   client.Reset();
    821   client.AdvanceFrame();
    822   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    823   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    824   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    825 
    826   EXPECT_TRUE(scheduler->ManageTilesPending());
    827   scheduler->DidManageTiles();  // An explicit ManageTiles.
    828   EXPECT_FALSE(scheduler->ManageTilesPending());
    829 
    830   client.Reset();
    831   client.task_runner().RunPendingTasks();  // Run posted deadline.
    832   EXPECT_EQ(1, client.num_draws());
    833   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    834   EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
    835   EXPECT_FALSE(scheduler->RedrawPending());
    836   EXPECT_FALSE(scheduler->ManageTilesPending());
    837   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    838 
    839   // Next frame without DidManageTiles should ManageTiles with draw.
    840   scheduler->SetNeedsManageTiles();
    841   scheduler->SetNeedsRedraw();
    842   client.Reset();
    843   client.AdvanceFrame();
    844   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    845   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    846   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    847 
    848   client.Reset();
    849   client.task_runner().RunPendingTasks();  // Run posted deadline.
    850   EXPECT_EQ(1, client.num_draws());
    851   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    852   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
    853   EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
    854             client.ActionIndex("ScheduledActionManageTiles"));
    855   EXPECT_FALSE(scheduler->RedrawPending());
    856   EXPECT_FALSE(scheduler->ManageTilesPending());
    857   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    858   scheduler->DidManageTiles();  // Corresponds to ScheduledActionManageTiles
    859 
    860   // If we get another DidManageTiles within the same frame, we should
    861   // not ManageTiles on the next frame.
    862   scheduler->DidManageTiles();  // An explicit ManageTiles.
    863   scheduler->SetNeedsManageTiles();
    864   scheduler->SetNeedsRedraw();
    865   client.Reset();
    866   client.AdvanceFrame();
    867   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    868   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    869   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    870 
    871   EXPECT_TRUE(scheduler->ManageTilesPending());
    872 
    873   client.Reset();
    874   client.task_runner().RunPendingTasks();  // Run posted deadline.
    875   EXPECT_EQ(1, client.num_draws());
    876   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    877   EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
    878   EXPECT_FALSE(scheduler->RedrawPending());
    879   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    880 
    881   // If we get another DidManageTiles, we should not ManageTiles on the next
    882   // frame. This verifies we don't alternate calling ManageTiles once and twice.
    883   EXPECT_TRUE(scheduler->ManageTilesPending());
    884   scheduler->DidManageTiles();  // An explicit ManageTiles.
    885   EXPECT_FALSE(scheduler->ManageTilesPending());
    886   scheduler->SetNeedsManageTiles();
    887   scheduler->SetNeedsRedraw();
    888   client.Reset();
    889   client.AdvanceFrame();
    890   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    891   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    892   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    893 
    894   EXPECT_TRUE(scheduler->ManageTilesPending());
    895 
    896   client.Reset();
    897   client.task_runner().RunPendingTasks();  // Run posted deadline.
    898   EXPECT_EQ(1, client.num_draws());
    899   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    900   EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
    901   EXPECT_FALSE(scheduler->RedrawPending());
    902   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    903 
    904   // Next frame without DidManageTiles should ManageTiles with draw.
    905   scheduler->SetNeedsManageTiles();
    906   scheduler->SetNeedsRedraw();
    907   client.Reset();
    908   client.AdvanceFrame();
    909   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    910   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
    911   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    912 
    913   client.Reset();
    914   client.task_runner().RunPendingTasks();  // Run posted deadline.
    915   EXPECT_EQ(1, client.num_draws());
    916   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
    917   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
    918   EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
    919             client.ActionIndex("ScheduledActionManageTiles"));
    920   EXPECT_FALSE(scheduler->RedrawPending());
    921   EXPECT_FALSE(scheduler->ManageTilesPending());
    922   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
    923   scheduler->DidManageTiles();  // Corresponds to ScheduledActionManageTiles
    924 }
    925 
    926 TEST(SchedulerTest, ShouldUpdateVisibleTiles) {
    927   FakeSchedulerClient client;
    928   SchedulerSettings scheduler_settings;
    929   scheduler_settings.impl_side_painting = true;
    930   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
    931   scheduler->SetCanStart();
    932   scheduler->SetVisible(true);
    933   scheduler->SetCanDraw(true);
    934   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    935 
    936   client.SetRedrawWillHappenIfUpdateVisibleTilesHappens(true);
    937 
    938   // SetNeedsCommit should begin the frame.
    939   client.Reset();
    940   scheduler->SetNeedsCommit();
    941   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
    942 
    943   client.Reset();
    944   client.AdvanceFrame();
    945   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
    946   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
    947   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    948 
    949   client.Reset();
    950   scheduler->NotifyBeginMainFrameStarted();
    951   scheduler->NotifyReadyToCommit();
    952   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
    953 
    954   client.Reset();
    955   scheduler->NotifyReadyToActivate();
    956   EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
    957 
    958   client.Reset();
    959   client.SetSwapContainsIncompleteTile(true);
    960   client.task_runner().RunPendingTasks();  // Run posted deadline.
    961   EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
    962   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
    963   EXPECT_FALSE(scheduler->RedrawPending());
    964 
    965   client.Reset();
    966   client.AdvanceFrame();
    967   EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
    968   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    969 
    970   client.Reset();
    971   client.task_runner().RunPendingTasks();  // Run posted deadline.
    972   EXPECT_ACTION("ScheduledActionUpdateVisibleTiles", client, 0, 3);
    973   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 3);
    974   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 2, 3);
    975 
    976   client.Reset();
    977   client.AdvanceFrame();
    978   EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
    979   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
    980 
    981   // No more UpdateVisibleTiles().
    982   client.Reset();
    983   client.task_runner().RunPendingTasks();  // Run posted deadline.
    984   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
    985   EXPECT_FALSE(client.needs_begin_frame());
    986 }
    987 
    988 TEST(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
    989   SchedulerClientNeedsManageTilesInDraw client;
    990   SchedulerSettings default_scheduler_settings;
    991   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
    992   scheduler->SetCanStart();
    993   scheduler->SetVisible(true);
    994   scheduler->SetCanDraw(true);
    995   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
    996 
    997   client.Reset();
    998   scheduler->SetNeedsRedraw();
    999   client.AdvanceFrame();
   1000 
   1001   // The deadline should be zero since there is no work other than drawing
   1002   // pending.
   1003   EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline());
   1004 }
   1005 
   1006 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
   1007  public:
   1008   SchedulerClientWithFixedEstimates(
   1009       base::TimeDelta draw_duration,
   1010       base::TimeDelta begin_main_frame_to_commit_duration,
   1011       base::TimeDelta commit_to_activate_duration)
   1012       : draw_duration_(draw_duration),
   1013         begin_main_frame_to_commit_duration_(
   1014             begin_main_frame_to_commit_duration),
   1015         commit_to_activate_duration_(commit_to_activate_duration) {}
   1016 
   1017   virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
   1018     return draw_duration_;
   1019   }
   1020   virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
   1021     return begin_main_frame_to_commit_duration_;
   1022   }
   1023   virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
   1024     return commit_to_activate_duration_;
   1025   }
   1026 
   1027  private:
   1028     base::TimeDelta draw_duration_;
   1029     base::TimeDelta begin_main_frame_to_commit_duration_;
   1030     base::TimeDelta commit_to_activate_duration_;
   1031 };
   1032 
   1033 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
   1034                                 int64 commit_to_activate_estimate_in_ms,
   1035                                 bool impl_latency_takes_priority,
   1036                                 bool should_send_begin_main_frame) {
   1037   // Set up client with specified estimates (draw duration is set to 1).
   1038   SchedulerClientWithFixedEstimates client(
   1039       base::TimeDelta::FromMilliseconds(1),
   1040       base::TimeDelta::FromMilliseconds(
   1041           begin_main_frame_to_commit_estimate_in_ms),
   1042       base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
   1043   SchedulerSettings default_scheduler_settings;
   1044   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
   1045   scheduler->SetCanStart();
   1046   scheduler->SetVisible(true);
   1047   scheduler->SetCanDraw(true);
   1048   scheduler->SetImplLatencyTakesPriority(impl_latency_takes_priority);
   1049   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1050 
   1051   // Impl thread hits deadline before commit finishes.
   1052   client.Reset();
   1053   scheduler->SetNeedsCommit();
   1054   EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
   1055   client.AdvanceFrame();
   1056   EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
   1057   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1058   EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
   1059   scheduler->NotifyBeginMainFrameStarted();
   1060   scheduler->NotifyReadyToCommit();
   1061   EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
   1062   EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
   1063 
   1064   client.Reset();
   1065   scheduler->SetNeedsCommit();
   1066   EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
   1067   client.AdvanceFrame();
   1068   EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
   1069   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1070   EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(),
   1071             should_send_begin_main_frame);
   1072   EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"),
   1073             should_send_begin_main_frame);
   1074 }
   1075 
   1076 TEST(SchedulerTest,
   1077     SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
   1078   // Set up client so that estimates indicate that we can commit and activate
   1079   // before the deadline (~8ms by default).
   1080   MainFrameInHighLatencyMode(1, 1, false, false);
   1081 }
   1082 
   1083 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
   1084   // Set up client so that estimates indicate that the commit cannot finish
   1085   // before the deadline (~8ms by default).
   1086   MainFrameInHighLatencyMode(10, 1, false, true);
   1087 }
   1088 
   1089 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
   1090   // Set up client so that estimates indicate that the activate cannot finish
   1091   // before the deadline (~8ms by default).
   1092   MainFrameInHighLatencyMode(1, 10, false, true);
   1093 }
   1094 
   1095 TEST(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
   1096   // Set up client so that estimates indicate that we can commit and activate
   1097   // before the deadline (~8ms by default), but also enable impl latency takes
   1098   // priority mode.
   1099   MainFrameInHighLatencyMode(1, 1, true, true);
   1100 }
   1101 
   1102 TEST(SchedulerTest, PollForCommitCompletion) {
   1103   // Since we are simulating a long commit, set up a client with draw duration
   1104   // estimates that prevent skipping main frames to get to low latency mode.
   1105   SchedulerClientWithFixedEstimates client(
   1106       base::TimeDelta::FromMilliseconds(1),
   1107       base::TimeDelta::FromMilliseconds(32),
   1108       base::TimeDelta::FromMilliseconds(32));
   1109   client.set_log_anticipated_draw_time_change(true);
   1110   SchedulerSettings default_scheduler_settings;
   1111   TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
   1112 
   1113   scheduler->SetCanDraw(true);
   1114   scheduler->SetCanStart();
   1115   scheduler->SetVisible(true);
   1116   scheduler->DidCreateAndInitializeOutputSurface();
   1117 
   1118   scheduler->SetNeedsCommit();
   1119   EXPECT_TRUE(scheduler->CommitPending());
   1120   scheduler->NotifyBeginMainFrameStarted();
   1121   scheduler->NotifyReadyToCommit();
   1122   scheduler->SetNeedsRedraw();
   1123 
   1124   BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting(client.now_src());
   1125   frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
   1126   scheduler->BeginFrame(frame_args);
   1127 
   1128   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1129   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1130   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1131 
   1132   scheduler->DidSwapBuffers();
   1133   scheduler->DidSwapBuffersComplete();
   1134 
   1135   // At this point, we've drawn a frame. Start another commit, but hold off on
   1136   // the NotifyReadyToCommit for now.
   1137   EXPECT_FALSE(scheduler->CommitPending());
   1138   scheduler->SetNeedsCommit();
   1139   scheduler->BeginFrame(frame_args);
   1140   EXPECT_TRUE(scheduler->CommitPending());
   1141 
   1142   // Draw and swap the frame, but don't ack the swap to simulate the Browser
   1143   // blocking on the renderer.
   1144   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1145   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1146   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1147   scheduler->DidSwapBuffers();
   1148 
   1149   // Spin the event loop a few times and make sure we get more
   1150   // DidAnticipateDrawTimeChange calls every time.
   1151   int actions_so_far = client.num_actions_();
   1152 
   1153   // Does three iterations to make sure that the timer is properly repeating.
   1154   for (int i = 0; i < 3; ++i) {
   1155     EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
   1156               client.task_runner().DelayToNextTaskTime().InMicroseconds())
   1157         << scheduler->AsValue()->ToString();
   1158     client.task_runner().RunPendingTasks();
   1159     EXPECT_GT(client.num_actions_(), actions_so_far);
   1160     EXPECT_STREQ(client.Action(client.num_actions_() - 1),
   1161                  "DidAnticipatedDrawTimeChange");
   1162     actions_so_far = client.num_actions_();
   1163   }
   1164 
   1165   // Do the same thing after BeginMainFrame starts but still before activation.
   1166   scheduler->NotifyBeginMainFrameStarted();
   1167   for (int i = 0; i < 3; ++i) {
   1168     EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
   1169               client.task_runner().DelayToNextTaskTime().InMicroseconds())
   1170         << scheduler->AsValue()->ToString();
   1171     client.task_runner().RunPendingTasks();
   1172     EXPECT_GT(client.num_actions_(), actions_so_far);
   1173     EXPECT_STREQ(client.Action(client.num_actions_() - 1),
   1174                  "DidAnticipatedDrawTimeChange");
   1175     actions_so_far = client.num_actions_();
   1176   }
   1177 }
   1178 
   1179 TEST(SchedulerTest, BeginRetroFrame) {
   1180   FakeSchedulerClient client;
   1181   SchedulerSettings scheduler_settings;
   1182   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1183   scheduler->SetCanStart();
   1184   scheduler->SetVisible(true);
   1185   scheduler->SetCanDraw(true);
   1186   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1187 
   1188   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
   1189   client.Reset();
   1190   scheduler->SetNeedsCommit();
   1191   EXPECT_TRUE(client.needs_begin_frame());
   1192   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1193   client.Reset();
   1194 
   1195   // Create a BeginFrame with a long deadline to avoid race conditions.
   1196   // This is the first BeginFrame, which will be handled immediately.
   1197   BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
   1198   args.deadline += base::TimeDelta::FromHours(1);
   1199   scheduler->BeginFrame(args);
   1200   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1201   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1202   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1203   EXPECT_TRUE(client.needs_begin_frame());
   1204   client.Reset();
   1205 
   1206   // Queue BeginFrames while we are still handling the previous BeginFrame.
   1207   args.frame_time += base::TimeDelta::FromSeconds(1);
   1208   scheduler->BeginFrame(args);
   1209   args.frame_time += base::TimeDelta::FromSeconds(1);
   1210   scheduler->BeginFrame(args);
   1211 
   1212   // If we don't swap on the deadline, we wait for the next BeginImplFrame.
   1213   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1214   EXPECT_NO_ACTION(client);
   1215   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1216   EXPECT_TRUE(client.needs_begin_frame());
   1217   client.Reset();
   1218 
   1219   // NotifyReadyToCommit should trigger the commit.
   1220   scheduler->NotifyBeginMainFrameStarted();
   1221   scheduler->NotifyReadyToCommit();
   1222   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1223   EXPECT_TRUE(client.needs_begin_frame());
   1224   client.Reset();
   1225 
   1226   // BeginImplFrame should prepare the draw.
   1227   client.task_runner().RunPendingTasks();  // Run posted BeginRetroFrame.
   1228   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1229   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
   1230   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1231   EXPECT_TRUE(client.needs_begin_frame());
   1232   client.Reset();
   1233 
   1234   // BeginImplFrame deadline should draw.
   1235   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1236   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
   1237   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1238   EXPECT_TRUE(client.needs_begin_frame());
   1239   client.Reset();
   1240 
   1241   // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
   1242   // to avoid excessive toggles.
   1243   client.task_runner().RunPendingTasks();  // Run posted BeginRetroFrame.
   1244   EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
   1245   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1246   client.Reset();
   1247 
   1248   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1249   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1250   EXPECT_FALSE(client.needs_begin_frame());
   1251   client.Reset();
   1252 }
   1253 
   1254 TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
   1255   FakeSchedulerClient client;
   1256   SchedulerSettings scheduler_settings;
   1257   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1258   scheduler->SetCanStart();
   1259   scheduler->SetVisible(true);
   1260   scheduler->SetCanDraw(true);
   1261   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1262 
   1263   // To test swap ack throttling, this test disables automatic swap acks.
   1264   scheduler->SetMaxSwapsPending(1);
   1265   client.SetAutomaticSwapAck(false);
   1266 
   1267   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
   1268   client.Reset();
   1269   scheduler->SetNeedsCommit();
   1270   EXPECT_TRUE(client.needs_begin_frame());
   1271   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1272   client.Reset();
   1273 
   1274   // Create a BeginFrame with a long deadline to avoid race conditions.
   1275   // This is the first BeginFrame, which will be handled immediately.
   1276   BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
   1277   args.deadline += base::TimeDelta::FromHours(1);
   1278   scheduler->BeginFrame(args);
   1279   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1280   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1281   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1282   EXPECT_TRUE(client.needs_begin_frame());
   1283   client.Reset();
   1284 
   1285   // Queue BeginFrame while we are still handling the previous BeginFrame.
   1286   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1287   args.frame_time += base::TimeDelta::FromSeconds(1);
   1288   scheduler->BeginFrame(args);
   1289   EXPECT_NO_ACTION(client);
   1290   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1291   client.Reset();
   1292 
   1293   // NotifyReadyToCommit should trigger the pending commit and draw.
   1294   scheduler->NotifyBeginMainFrameStarted();
   1295   scheduler->NotifyReadyToCommit();
   1296   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1297   EXPECT_TRUE(client.needs_begin_frame());
   1298   client.Reset();
   1299 
   1300   // Swapping will put us into a swap throttled state.
   1301   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1302   EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
   1303   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
   1304   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1305   EXPECT_TRUE(client.needs_begin_frame());
   1306   client.Reset();
   1307 
   1308   // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
   1309   // but not a BeginMainFrame or draw.
   1310   scheduler->SetNeedsCommit();
   1311   client.task_runner().RunPendingTasks();  // Run posted BeginRetroFrame.
   1312   EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
   1313   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1314   EXPECT_TRUE(client.needs_begin_frame());
   1315   client.Reset();
   1316 
   1317   // Queue BeginFrame while we are still handling the previous BeginFrame.
   1318   args.frame_time += base::TimeDelta::FromSeconds(1);
   1319   scheduler->BeginFrame(args);
   1320   EXPECT_NO_ACTION(client);
   1321   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1322   EXPECT_TRUE(client.needs_begin_frame());
   1323   client.Reset();
   1324 
   1325   // Take us out of a swap throttled state.
   1326   scheduler->DidSwapBuffersComplete();
   1327   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
   1328   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1329   EXPECT_TRUE(client.needs_begin_frame());
   1330   client.Reset();
   1331 
   1332   // BeginImplFrame deadline should draw.
   1333   scheduler->SetNeedsRedraw();
   1334 
   1335   EXPECT_TRUE(client.task_runner().RunTasksWhile(
   1336       client.ImplFrameDeadlinePending(true)));
   1337 
   1338   EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
   1339   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
   1340   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1341   EXPECT_TRUE(client.needs_begin_frame());
   1342   client.Reset();
   1343 }
   1344 
   1345 void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled,
   1346                               bool throttle_frame_production) {
   1347   FakeSchedulerClient client;
   1348   SchedulerSettings scheduler_settings;
   1349   scheduler_settings.begin_frame_scheduling_enabled =
   1350       begin_frame_scheduling_enabled;
   1351   scheduler_settings.throttle_frame_production = throttle_frame_production;
   1352   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1353   scheduler->SetCanStart();
   1354   scheduler->SetVisible(true);
   1355   scheduler->SetCanDraw(true);
   1356   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1357 
   1358   // SetNeedsCommit should begin the frame on the next BeginImplFrame
   1359   // without calling SetNeedsBeginFrame.
   1360   client.Reset();
   1361   scheduler->SetNeedsCommit();
   1362   EXPECT_FALSE(client.needs_begin_frame());
   1363   EXPECT_NO_ACTION(client);
   1364   client.Reset();
   1365 
   1366   // When the client-driven BeginFrame are disabled, the scheduler posts it's
   1367   // own BeginFrame tasks.
   1368   client.task_runner().RunPendingTasks();  // Run posted BeginFrame.
   1369   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1370   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1371   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1372   EXPECT_FALSE(client.needs_begin_frame());
   1373   client.Reset();
   1374 
   1375   // If we don't swap on the deadline, we wait for the next BeginFrame.
   1376   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1377   EXPECT_NO_ACTION(client);
   1378   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1379   EXPECT_FALSE(client.needs_begin_frame());
   1380   client.Reset();
   1381 
   1382   // NotifyReadyToCommit should trigger the commit.
   1383   scheduler->NotifyBeginMainFrameStarted();
   1384   scheduler->NotifyReadyToCommit();
   1385   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1386   EXPECT_FALSE(client.needs_begin_frame());
   1387   client.Reset();
   1388 
   1389   // BeginImplFrame should prepare the draw.
   1390   client.task_runner().RunPendingTasks();  // Run posted BeginFrame.
   1391   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1392   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
   1393   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1394   EXPECT_FALSE(client.needs_begin_frame());
   1395   client.Reset();
   1396 
   1397   // BeginImplFrame deadline should draw.
   1398   client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
   1399   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
   1400   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1401   EXPECT_FALSE(client.needs_begin_frame());
   1402   client.Reset();
   1403 
   1404   // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
   1405   // to avoid excessive toggles.
   1406   client.task_runner().RunPendingTasks();  // Run posted BeginFrame.
   1407   EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
   1408   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1409   client.Reset();
   1410 
   1411   // Make sure SetNeedsBeginFrame isn't called on the client
   1412   // when the BeginFrame is no longer needed.
   1413   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1414   EXPECT_NO_ACTION(client);
   1415   EXPECT_FALSE(client.needs_begin_frame());
   1416   client.Reset();
   1417 }
   1418 
   1419 TEST(SchedulerTest, SyntheticBeginFrames) {
   1420   bool begin_frame_scheduling_enabled = false;
   1421   bool throttle_frame_production = true;
   1422   BeginFramesNotFromClient(begin_frame_scheduling_enabled,
   1423                            throttle_frame_production);
   1424 }
   1425 
   1426 TEST(SchedulerTest, VSyncThrottlingDisabled) {
   1427   bool begin_frame_scheduling_enabled = true;
   1428   bool throttle_frame_production = false;
   1429   BeginFramesNotFromClient(begin_frame_scheduling_enabled,
   1430                            throttle_frame_production);
   1431 }
   1432 
   1433 TEST(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
   1434   bool begin_frame_scheduling_enabled = false;
   1435   bool throttle_frame_production = false;
   1436   BeginFramesNotFromClient(begin_frame_scheduling_enabled,
   1437                            throttle_frame_production);
   1438 }
   1439 
   1440 void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled,
   1441                                             bool throttle_frame_production) {
   1442   FakeSchedulerClient client;
   1443   SchedulerSettings scheduler_settings;
   1444   scheduler_settings.begin_frame_scheduling_enabled =
   1445       begin_frame_scheduling_enabled;
   1446   scheduler_settings.throttle_frame_production = throttle_frame_production;
   1447   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1448   scheduler->SetCanStart();
   1449   scheduler->SetVisible(true);
   1450   scheduler->SetCanDraw(true);
   1451   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1452 
   1453   // To test swap ack throttling, this test disables automatic swap acks.
   1454   scheduler->SetMaxSwapsPending(1);
   1455   client.SetAutomaticSwapAck(false);
   1456 
   1457   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
   1458   client.Reset();
   1459   scheduler->SetNeedsCommit();
   1460   EXPECT_FALSE(client.needs_begin_frame());
   1461   EXPECT_NO_ACTION(client);
   1462   client.Reset();
   1463 
   1464   // Trigger the first BeginImplFrame and BeginMainFrame
   1465   client.task_runner().RunPendingTasks();  // Run posted BeginFrame.
   1466   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1467   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1468   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1469   EXPECT_FALSE(client.needs_begin_frame());
   1470   client.Reset();
   1471 
   1472   // NotifyReadyToCommit should trigger the pending commit and draw.
   1473   scheduler->NotifyBeginMainFrameStarted();
   1474   scheduler->NotifyReadyToCommit();
   1475   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1476   EXPECT_FALSE(client.needs_begin_frame());
   1477   client.Reset();
   1478 
   1479   // Swapping will put us into a swap throttled state.
   1480   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1481   EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
   1482   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
   1483   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1484   EXPECT_FALSE(client.needs_begin_frame());
   1485   client.Reset();
   1486 
   1487   // While swap throttled, BeginFrames should trigger BeginImplFrames,
   1488   // but not a BeginMainFrame or draw.
   1489   scheduler->SetNeedsCommit();
   1490   client.task_runner().RunPendingTasks();  // Run posted BeginFrame.
   1491   EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
   1492   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1493   EXPECT_FALSE(client.needs_begin_frame());
   1494   client.Reset();
   1495 
   1496   // Take us out of a swap throttled state.
   1497   scheduler->DidSwapBuffersComplete();
   1498   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
   1499   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1500   EXPECT_FALSE(client.needs_begin_frame());
   1501   client.Reset();
   1502 
   1503   // BeginImplFrame deadline should draw.
   1504   scheduler->SetNeedsRedraw();
   1505   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1506   EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
   1507   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
   1508   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1509   EXPECT_FALSE(client.needs_begin_frame());
   1510   client.Reset();
   1511 }
   1512 
   1513 TEST(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
   1514   bool begin_frame_scheduling_enabled = false;
   1515   bool throttle_frame_production = true;
   1516   BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
   1517                                          throttle_frame_production);
   1518 }
   1519 
   1520 TEST(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
   1521   bool begin_frame_scheduling_enabled = true;
   1522   bool throttle_frame_production = false;
   1523   BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
   1524                                          throttle_frame_production);
   1525 }
   1526 
   1527 TEST(SchedulerTest,
   1528      SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
   1529   bool begin_frame_scheduling_enabled = false;
   1530   bool throttle_frame_production = false;
   1531   BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
   1532                                          throttle_frame_production);
   1533 }
   1534 
   1535 TEST(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
   1536   FakeSchedulerClient client;
   1537   SchedulerSettings scheduler_settings;
   1538   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1539   scheduler->SetCanStart();
   1540   scheduler->SetVisible(true);
   1541   scheduler->SetCanDraw(true);
   1542 
   1543   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1544   client.Reset();
   1545   scheduler->DidCreateAndInitializeOutputSurface();
   1546   EXPECT_NO_ACTION(client);
   1547 
   1548   scheduler->DidLoseOutputSurface();
   1549   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1550 }
   1551 
   1552 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
   1553   FakeSchedulerClient client;
   1554   SchedulerSettings scheduler_settings;
   1555   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1556   scheduler->SetCanStart();
   1557   scheduler->SetVisible(true);
   1558   scheduler->SetCanDraw(true);
   1559 
   1560   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1561   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1562   // SetNeedsCommit should begin the frame.
   1563   client.Reset();
   1564   scheduler->SetNeedsCommit();
   1565   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1566 
   1567   client.Reset();
   1568   client.AdvanceFrame();
   1569   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1570   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1571   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1572 
   1573   client.Reset();
   1574   scheduler->DidLoseOutputSurface();
   1575   // Do nothing when impl frame is in deadine pending state.
   1576   EXPECT_NO_ACTION(client);
   1577 
   1578   client.Reset();
   1579   scheduler->NotifyBeginMainFrameStarted();
   1580   scheduler->NotifyReadyToCommit();
   1581   EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
   1582 
   1583   client.Reset();
   1584   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1585   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1586 }
   1587 
   1588 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
   1589     bool impl_side_painting) {
   1590   FakeSchedulerClient client;
   1591   SchedulerSettings scheduler_settings;
   1592   scheduler_settings.impl_side_painting = impl_side_painting;
   1593   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1594   scheduler->SetCanStart();
   1595   scheduler->SetVisible(true);
   1596   scheduler->SetCanDraw(true);
   1597 
   1598   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1599   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1600 
   1601   // SetNeedsCommit should begin the frame.
   1602   client.Reset();
   1603   scheduler->SetNeedsCommit();
   1604   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1605 
   1606   client.Reset();
   1607   client.AdvanceFrame();
   1608   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1609   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1610   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1611 
   1612   client.Reset();
   1613   scheduler->DidLoseOutputSurface();
   1614   // Do nothing when impl frame is in deadine pending state.
   1615   EXPECT_NO_ACTION(client);
   1616 
   1617   client.Reset();
   1618   // Run posted deadline.
   1619   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1620   client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
   1621   // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
   1622   // not yet completed.
   1623   EXPECT_NO_ACTION(client);
   1624   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1625 
   1626   // BeginImplFrame is not started.
   1627   client.task_runner().RunUntilTime(client.now_src()->Now() +
   1628                                     base::TimeDelta::FromMilliseconds(10));
   1629   EXPECT_NO_ACTION(client);
   1630   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1631 
   1632   client.Reset();
   1633   scheduler->NotifyBeginMainFrameStarted();
   1634   scheduler->NotifyReadyToCommit();
   1635   if (impl_side_painting) {
   1636     EXPECT_ACTION("ScheduledActionCommit", client, 0, 3);
   1637     EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 3);
   1638     EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 2, 3);
   1639   } else {
   1640     EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
   1641     EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
   1642   }
   1643 }
   1644 
   1645 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
   1646   bool impl_side_painting = false;
   1647   DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
   1648 }
   1649 
   1650 TEST(SchedulerTest,
   1651      DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
   1652   bool impl_side_painting = true;
   1653   DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
   1654 }
   1655 
   1656 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting) {
   1657   FakeSchedulerClient client;
   1658   SchedulerSettings scheduler_settings;
   1659   scheduler_settings.impl_side_painting = impl_side_painting;
   1660   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1661   scheduler->SetCanStart();
   1662   scheduler->SetVisible(true);
   1663   scheduler->SetCanDraw(true);
   1664 
   1665   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1666   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1667 
   1668   // SetNeedsCommit should begin the frame.
   1669   client.Reset();
   1670   scheduler->SetNeedsCommit();
   1671   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1672 
   1673   client.Reset();
   1674   client.AdvanceFrame();
   1675   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1676   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1677   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1678 
   1679   client.Reset();
   1680   scheduler->NotifyBeginMainFrameStarted();
   1681   scheduler->NotifyReadyToCommit();
   1682   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1683 
   1684   client.Reset();
   1685   scheduler->DidLoseOutputSurface();
   1686   if (impl_side_painting) {
   1687     // Sync tree should be forced to activate.
   1688     EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
   1689   } else {
   1690     // Do nothing when impl frame is in deadine pending state.
   1691     EXPECT_NO_ACTION(client);
   1692   }
   1693 
   1694   client.Reset();
   1695   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1696   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1697 }
   1698 
   1699 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
   1700   DidLoseOutputSurfaceAfterReadyToCommit(false);
   1701 }
   1702 
   1703 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
   1704   DidLoseOutputSurfaceAfterReadyToCommit(true);
   1705 }
   1706 
   1707 TEST(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsManageTiles) {
   1708   FakeSchedulerClient client;
   1709   SchedulerSettings scheduler_settings;
   1710   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1711   scheduler->SetCanStart();
   1712   scheduler->SetVisible(true);
   1713   scheduler->SetCanDraw(true);
   1714   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1715 
   1716   client.Reset();
   1717   scheduler->SetNeedsManageTiles();
   1718   scheduler->SetNeedsRedraw();
   1719   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1720   EXPECT_TRUE(client.needs_begin_frame());
   1721 
   1722   client.Reset();
   1723   client.AdvanceFrame();
   1724   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1725   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
   1726   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1727 
   1728   client.Reset();
   1729   scheduler->DidLoseOutputSurface();
   1730   EXPECT_NO_ACTION(client);
   1731 
   1732   client.Reset();
   1733   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1734   EXPECT_ACTION("ScheduledActionManageTiles", client, 0, 2);
   1735   EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
   1736 }
   1737 
   1738 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
   1739   FakeSchedulerClient client;
   1740   SchedulerSettings scheduler_settings;
   1741   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1742   scheduler->SetCanStart();
   1743   scheduler->SetVisible(true);
   1744   scheduler->SetCanDraw(true);
   1745   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1746 
   1747   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
   1748   client.Reset();
   1749   scheduler->SetNeedsCommit();
   1750   EXPECT_TRUE(client.needs_begin_frame());
   1751   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1752 
   1753   // Create a BeginFrame with a long deadline to avoid race conditions.
   1754   // This is the first BeginFrame, which will be handled immediately.
   1755   client.Reset();
   1756   BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
   1757   args.deadline += base::TimeDelta::FromHours(1);
   1758   scheduler->BeginFrame(args);
   1759   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1760   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1761   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1762   EXPECT_TRUE(client.needs_begin_frame());
   1763 
   1764   // Queue BeginFrames while we are still handling the previous BeginFrame.
   1765   args.frame_time += base::TimeDelta::FromSeconds(1);
   1766   scheduler->BeginFrame(args);
   1767   args.frame_time += base::TimeDelta::FromSeconds(1);
   1768   scheduler->BeginFrame(args);
   1769 
   1770   // If we don't swap on the deadline, we wait for the next BeginImplFrame.
   1771   client.Reset();
   1772   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1773   EXPECT_NO_ACTION(client);
   1774   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1775   EXPECT_TRUE(client.needs_begin_frame());
   1776 
   1777   // NotifyReadyToCommit should trigger the commit.
   1778   client.Reset();
   1779   scheduler->NotifyBeginMainFrameStarted();
   1780   scheduler->NotifyReadyToCommit();
   1781   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1782   EXPECT_TRUE(client.needs_begin_frame());
   1783 
   1784   client.Reset();
   1785   EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
   1786   scheduler->DidLoseOutputSurface();
   1787   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1788   EXPECT_TRUE(client.needs_begin_frame());
   1789   EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
   1790 
   1791   // Posted BeginRetroFrame is aborted.
   1792   client.Reset();
   1793   client.task_runner().RunPendingTasks();
   1794   EXPECT_NO_ACTION(client);
   1795 }
   1796 
   1797 TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
   1798   FakeSchedulerClient client;
   1799   SchedulerSettings scheduler_settings;
   1800   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1801   scheduler->SetCanStart();
   1802   scheduler->SetVisible(true);
   1803   scheduler->SetCanDraw(true);
   1804   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1805 
   1806   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
   1807   client.Reset();
   1808   scheduler->SetNeedsCommit();
   1809   EXPECT_TRUE(client.needs_begin_frame());
   1810   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1811 
   1812   // Create a BeginFrame with a long deadline to avoid race conditions.
   1813   // This is the first BeginFrame, which will be handled immediately.
   1814   client.Reset();
   1815   BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
   1816   args.deadline += base::TimeDelta::FromHours(1);
   1817   scheduler->BeginFrame(args);
   1818   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1819   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1820   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1821   EXPECT_TRUE(client.needs_begin_frame());
   1822 
   1823   // Queue BeginFrames while we are still handling the previous BeginFrame.
   1824   args.frame_time += base::TimeDelta::FromSeconds(1);
   1825   scheduler->BeginFrame(args);
   1826   args.frame_time += base::TimeDelta::FromSeconds(1);
   1827   scheduler->BeginFrame(args);
   1828 
   1829   // If we don't swap on the deadline, we wait for the next BeginImplFrame.
   1830   client.Reset();
   1831   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1832   EXPECT_NO_ACTION(client);
   1833   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1834   EXPECT_TRUE(client.needs_begin_frame());
   1835 
   1836   // NotifyReadyToCommit should trigger the commit.
   1837   client.Reset();
   1838   scheduler->NotifyBeginMainFrameStarted();
   1839   scheduler->NotifyReadyToCommit();
   1840   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1841   EXPECT_TRUE(client.needs_begin_frame());
   1842 
   1843   // BeginImplFrame should prepare the draw.
   1844   client.Reset();
   1845   client.task_runner().RunPendingTasks();  // Run posted BeginRetroFrame.
   1846   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1847   EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
   1848   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1849   EXPECT_TRUE(client.needs_begin_frame());
   1850 
   1851   client.Reset();
   1852   EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
   1853   scheduler->DidLoseOutputSurface();
   1854   EXPECT_NO_ACTION(client);
   1855   EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
   1856 
   1857   // BeginImplFrame deadline should abort drawing.
   1858   client.Reset();
   1859   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1860   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1861   EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
   1862   EXPECT_TRUE(client.needs_begin_frame());
   1863 
   1864   // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
   1865   client.Reset();
   1866   client.task_runner().RunPendingTasks();
   1867   EXPECT_NO_ACTION(client);
   1868 }
   1869 
   1870 TEST(SchedulerTest,
   1871      StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
   1872   FakeSchedulerClient client;
   1873   SchedulerSettings scheduler_settings;
   1874   scheduler_settings.begin_frame_scheduling_enabled = false;
   1875   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1876   scheduler->SetCanStart();
   1877   scheduler->SetVisible(true);
   1878   scheduler->SetCanDraw(true);
   1879   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1880 
   1881   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
   1882   client.Reset();
   1883   EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
   1884   scheduler->SetNeedsCommit();
   1885   EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
   1886 
   1887   client.Reset();
   1888   client.task_runner().RunPendingTasks();  // Run posted Tick.
   1889   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1890   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1891   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1892   EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
   1893 
   1894   // NotifyReadyToCommit should trigger the commit.
   1895   client.Reset();
   1896   scheduler->NotifyBeginMainFrameStarted();
   1897   scheduler->NotifyReadyToCommit();
   1898   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1899   EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
   1900 
   1901   client.Reset();
   1902   scheduler->DidLoseOutputSurface();
   1903   EXPECT_EQ(0, client.num_actions_());
   1904   EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
   1905 
   1906   client.Reset();
   1907   client.task_runner().RunPendingTasks();  // Run posted deadline.
   1908   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1909   EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
   1910 }
   1911 
   1912 TEST(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
   1913   FakeSchedulerClient client;
   1914   SchedulerSettings scheduler_settings;
   1915   scheduler_settings.impl_side_painting = true;
   1916   TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
   1917   scheduler->SetCanStart();
   1918   scheduler->SetVisible(true);
   1919   scheduler->SetCanDraw(true);
   1920 
   1921   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
   1922   InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
   1923 
   1924   // SetNeedsCommit should begin the frame.
   1925   client.Reset();
   1926   scheduler->SetNeedsCommit();
   1927   EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
   1928 
   1929   client.Reset();
   1930   client.AdvanceFrame();
   1931   EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
   1932   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
   1933   EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
   1934 
   1935   client.Reset();
   1936   scheduler->NotifyBeginMainFrameStarted();
   1937   scheduler->NotifyReadyToCommit();
   1938   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
   1939 
   1940   client.Reset();
   1941   scheduler->SetVisible(false);
   1942   // Sync tree should be forced to activate.
   1943   EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
   1944 }
   1945 
   1946 }  // namespace
   1947 }  // namespace cc
   1948