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