// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/trees/layer_tree_host.h"

#include <stdint.h>
#include <climits>

#include "base/bind.h"
#include "cc/animation/animation_curve.h"
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_id_provider.h"
#include "cc/animation/animation_player.h"
#include "cc/animation/animation_ticker.h"
#include "cc/animation/animation_timeline.h"
#include "cc/animation/element_animations.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/scroll_offset_animations.h"
#include "cc/animation/timing_function.h"
#include "cc/animation/transform_operations.h"
#include "cc/base/completion_event.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/transform_node.h"

namespace cc {
namespace {

class LayerTreeHostAnimationTest : public LayerTreeTest {
 public:
  LayerTreeHostAnimationTest()
      : timeline_id_(AnimationIdProvider::NextTimelineId()),
        player_id_(AnimationIdProvider::NextPlayerId()),
        player_child_id_(AnimationIdProvider::NextPlayerId()) {
    timeline_ = AnimationTimeline::Create(timeline_id_);
    player_ = AnimationPlayer::Create(player_id_);
    player_child_ = AnimationPlayer::Create(player_child_id_);

    player_->set_animation_delegate(this);
  }

  void AttachPlayersToTimeline() {
    animation_host()->AddAnimationTimeline(timeline_.get());
    layer_tree_host()->SetElementIdsForTesting();
    timeline_->AttachPlayer(player_.get());
    timeline_->AttachPlayer(player_child_.get());
  }

  void GetImplTimelineAndPlayerByID(const LayerTreeHostImpl& host_impl) {
    AnimationHost* animation_host_impl = GetImplAnimationHost(&host_impl);
    timeline_impl_ = animation_host_impl->GetTimelineById(timeline_id_);
    EXPECT_TRUE(timeline_impl_);
    player_impl_ = timeline_impl_->GetPlayerById(player_id_);
    EXPECT_TRUE(player_impl_);
    player_child_impl_ = timeline_impl_->GetPlayerById(player_child_id_);
    EXPECT_TRUE(player_child_impl_);
  }

  AnimationHost* GetImplAnimationHost(
      const LayerTreeHostImpl* host_impl) const {
    return static_cast<AnimationHost*>(host_impl->mutator_host());
  }

 protected:
  scoped_refptr<AnimationTimeline> timeline_;
  scoped_refptr<AnimationPlayer> player_;
  scoped_refptr<AnimationPlayer> player_child_;

  scoped_refptr<AnimationTimeline> timeline_impl_;
  scoped_refptr<AnimationPlayer> player_impl_;
  scoped_refptr<AnimationPlayer> player_child_impl_;

  const int timeline_id_;
  const int player_id_;
  const int player_child_id_;
};

// Makes sure that SetNeedsAnimate does not cause the CommitRequested() state to
// be set.
class LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested()
      : num_commits_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    // We skip the first commit because its the commit that populates the
    // impl thread with a tree. After the second commit, the test is done.
    if (num_commits_ != 1)
      return;

    layer_tree_host()->SetNeedsAnimate();
    // Right now, CommitRequested is going to be true, because during
    // BeginFrame, we force CommitRequested to true to prevent requests from
    // hitting the impl thread. But, when the next DidCommit happens, we should
    // verify that CommitRequested has gone back to false.
  }

  void DidCommit() override {
    if (!num_commits_) {
      EXPECT_FALSE(layer_tree_host()->CommitRequested());
      layer_tree_host()->SetNeedsAnimate();
      EXPECT_FALSE(layer_tree_host()->CommitRequested());
    }

    // Verifies that the SetNeedsAnimate we made in ::Animate did not
    // trigger CommitRequested.
    EXPECT_FALSE(layer_tree_host()->CommitRequested());
    EndTest();
    num_commits_++;
  }

  void AfterTest() override {}

 private:
  int num_commits_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested);

// Trigger a frame with SetNeedsCommit. Then, inside the resulting animate
// callback, request another frame using SetNeedsAnimate. End the test when
// animate gets called yet-again, indicating that the proxy is correctly
// handling the case where SetNeedsAnimate() is called inside the BeginFrame
// flow.
class LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback()
      : num_begin_frames_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    if (!num_begin_frames_) {
      layer_tree_host()->SetNeedsAnimate();
      num_begin_frames_++;
      return;
    }
    EndTest();
  }

  void AfterTest() override {}

 private:
  int num_begin_frames_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback);

// Add a layer animation and confirm that
// LayerTreeHostImpl::UpdateAnimationState does get called.
class LayerTreeHostAnimationTestAddAnimation
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAddAnimation()
      : update_animation_state_was_called_(false) {}

  void BeginTest() override {
    AttachPlayersToTimeline();
    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddInstantAnimationToMainThreadPlayer(player_.get());
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    EXPECT_FALSE(has_unfinished_animation);
    update_animation_state_was_called_ = true;
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    EXPECT_LT(base::TimeTicks(), monotonic_time);

    Animation* animation = player_->GetAnimation(TargetProperty::OPACITY);
    if (animation)
      player_->RemoveAnimation(animation->id());

    EndTest();
  }

  void AfterTest() override { EXPECT_TRUE(update_animation_state_was_called_); }

 private:
  bool update_animation_state_was_called_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAddAnimation);

// Add a layer animation to a layer, but continually fail to draw. Confirm that
// after a while, we do eventually force a draw.
class LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws()
      : started_animating_(false) {}

  void BeginTest() override {
    AttachPlayersToTimeline();
    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddAnimationToMainThreadPlayer(player_.get());
  }

  void AnimateLayers(LayerTreeHostImpl* host_impl,
                     base::TimeTicks monotonic_time) override {
    started_animating_ = true;
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (started_animating_)
      EndTest();
  }

  DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                   LayerTreeHostImpl::FrameData* frame,
                                   DrawResult draw_result) override {
    return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
  }

  void AfterTest() override {}

 private:
  bool started_animating_;
};

// Starvation can only be an issue with the MT compositor.
MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws);

// Ensures that animations eventually get deleted.
class LayerTreeHostAnimationTestAnimationsGetDeleted
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimationsGetDeleted()
      : started_animating_(false) {}

  void BeginTest() override {
    AttachPlayersToTimeline();
    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddAnimationToMainThreadPlayer(player_.get());
  }

  void AnimateLayers(LayerTreeHostImpl* host_impl,
                     base::TimeTicks monotonic_time) override {
    bool have_animations =
        !GetImplAnimationHost(host_impl)->ticking_players_for_testing().empty();
    if (!started_animating_ && have_animations) {
      started_animating_ = true;
      return;
    }

    if (started_animating_ && !have_animations)
      EndTest();
  }

  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
                               int target_property,
                               int group) override {
    // Animations on the impl-side ElementAnimations only get deleted during
    // a commit, so we need to schedule a commit.
    layer_tree_host()->SetNeedsCommit();
  }

  void AfterTest() override {}

 private:
  bool started_animating_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted);

// Ensure that an animation's timing function is respected.
class LayerTreeHostAnimationTestAddAnimationWithTimingFunction
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());
    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachPlayersToTimeline();
    player_child_->AttachElement(picture_->element_id());
  }

  void BeginTest() override {
    PostAddAnimationToMainThreadPlayer(player_child_.get());
  }

  void AnimateLayers(LayerTreeHostImpl* host_impl,
                     base::TimeTicks monotonic_time) override {
    // TODO(ajuma): This test only checks the active tree. Add checks for
    // pending tree too.
    if (!host_impl->active_tree()->root_layer_for_testing())
      return;

    // Wait for the commit with the animation to happen.
    if (host_impl->active_tree()->source_frame_number() != 0)
      return;

    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<AnimationPlayer> player_child_impl =
        timeline_impl->GetPlayerById(player_child_id_);

    Animation* animation =
        player_child_impl->GetAnimation(TargetProperty::OPACITY);

    const FloatAnimationCurve* curve =
        animation->curve()->ToFloatAnimationCurve();
    float start_opacity = curve->GetValue(base::TimeDelta());
    float end_opacity = curve->GetValue(curve->Duration());
    float linearly_interpolated_opacity =
        0.25f * end_opacity + 0.75f * start_opacity;
    base::TimeDelta time = curve->Duration() * 0.25f;
    // If the linear timing function associated with this animation was not
    // picked up, then the linearly interpolated opacity would be different
    // because of the default ease timing function.
    EXPECT_FLOAT_EQ(linearly_interpolated_opacity, curve->GetValue(time));

    EndTest();
  }

  void AfterTest() override {}

  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAddAnimationWithTimingFunction);

// Ensures that main thread animations have their start times synchronized with
// impl thread animations.
class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());

    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachPlayersToTimeline();
    player_child_->set_animation_delegate(this);
    player_child_->AttachElement(picture_->element_id());
  }

  void BeginTest() override {
    PostAddAnimationToMainThreadPlayer(player_child_.get());
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    Animation* animation = player_child_->GetAnimation(TargetProperty::OPACITY);
    main_start_time_ = animation->start_time();
    player_child_->RemoveAnimation(animation->id());
    EndTest();
  }

  void UpdateAnimationState(LayerTreeHostImpl* impl_host,
                            bool has_unfinished_animation) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(impl_host)->GetTimelineById(timeline_id_);
    scoped_refptr<AnimationPlayer> player_child_impl =
        timeline_impl->GetPlayerById(player_child_id_);

    Animation* animation =
        player_child_impl->GetAnimation(TargetProperty::OPACITY);
    if (!animation)
      return;

    impl_start_time_ = animation->start_time();
  }

  void AfterTest() override {
    EXPECT_EQ(impl_start_time_, main_start_time_);
    EXPECT_LT(base::TimeTicks(), impl_start_time_);
  }

 private:
  base::TimeTicks main_start_time_;
  base::TimeTicks impl_start_time_;
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSynchronizeAnimationStartTimes);

// Ensures that notify animation finished is called.
class LayerTreeHostAnimationTestAnimationFinishedEvents
    : public LayerTreeHostAnimationTest {
 public:
  void BeginTest() override {
    AttachPlayersToTimeline();
    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    PostAddInstantAnimationToMainThreadPlayer(player_.get());
  }

  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
                               int target_property,
                               int group) override {
    Animation* animation = player_->GetAnimation(TargetProperty::OPACITY);
    if (animation)
      player_->RemoveAnimation(animation->id());
    EndTest();
  }

  void AfterTest() override {}
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAnimationFinishedEvents);

// Ensures that when opacity is being animated, this value does not cause the
// subtree to be skipped.
class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity()
      : update_check_layer_() {}

  void SetupTree() override {
    update_check_layer_ = FakePictureLayer::Create(&client_);
    update_check_layer_->SetOpacity(0.f);
    layer_tree_host()->SetRootLayer(update_check_layer_);
    client_.set_bounds(update_check_layer_->bounds());
    LayerTreeHostAnimationTest::SetupTree();

    AttachPlayersToTimeline();
    player_->AttachElement(update_check_layer_->element_id());
  }

  void BeginTest() override {
    PostAddAnimationToMainThreadPlayer(player_.get());
  }

  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<AnimationPlayer> player_impl =
        timeline_impl->GetPlayerById(player_id_);

    Animation* animation_impl =
        player_impl->GetAnimation(TargetProperty::OPACITY);
    player_impl->RemoveAnimation(animation_impl->id());
    EndTest();
  }

  void AfterTest() override {
    // Update() should have been called once, proving that the layer was not
    // skipped.
    EXPECT_EQ(1, update_check_layer_->update_count());

    // clear update_check_layer_ so LayerTreeHost dies.
    update_check_layer_ = nullptr;
  }

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> update_check_layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity);

// Layers added to tree with existing active animations should have the
// animation correctly recognized.
class LayerTreeHostAnimationTestLayerAddedWithAnimation
    : public LayerTreeHostAnimationTest {
 public:
  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      AttachPlayersToTimeline();

      scoped_refptr<Layer> layer = Layer::Create();
      layer->SetElementId(ElementId(42));
      player_->AttachElement(layer->element_id());
      player_->set_animation_delegate(this);

      // Any valid AnimationCurve will do here.
      std::unique_ptr<AnimationCurve> curve(new FakeFloatAnimationCurve());
      std::unique_ptr<Animation> animation(
          Animation::Create(std::move(curve), 1, 1, TargetProperty::OPACITY));
      player_->AddAnimation(std::move(animation));

      // We add the animation *before* attaching the layer to the tree.
      layer_tree_host()->root_layer()->AddChild(layer);
    }
  }

  void AnimateLayers(LayerTreeHostImpl* impl_host,
                     base::TimeTicks monotonic_time) override {
    EndTest();
  }

  void AfterTest() override {}
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestLayerAddedWithAnimation);

class LayerTreeHostAnimationTestCancelAnimateCommit
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestCancelAnimateCommit()
      : num_begin_frames_(0), num_commit_calls_(0), num_draw_calls_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    num_begin_frames_++;
    // No-op animate will cancel the commit.
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      EndTest();
      return;
    }
    layer_tree_host()->SetNeedsAnimate();
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
    num_commit_calls_++;
    if (impl->active_tree()->source_frame_number() > 1)
      FAIL() << "Commit should have been canceled.";
  }

  void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
    num_draw_calls_++;
    if (impl->active_tree()->source_frame_number() > 1)
      FAIL() << "Draw should have been canceled.";
  }

  void AfterTest() override {
    EXPECT_EQ(2, num_begin_frames_);
    EXPECT_EQ(1, num_commit_calls_);
    EXPECT_EQ(1, num_draw_calls_);
  }

 private:
  int num_begin_frames_;
  int num_commit_calls_;
  int num_draw_calls_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCancelAnimateCommit);

class LayerTreeHostAnimationTestForceRedraw
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestForceRedraw()
      : num_animate_(0), num_draw_layers_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    if (++num_animate_ < 2)
      layer_tree_host()->SetNeedsAnimate();
  }

  void UpdateLayerTreeHost(
      LayerTreeHostClient::VisualStateUpdate requested_update) override {
    layer_tree_host()->SetNeedsCommitWithForcedRedraw();
  }

  void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
    if (++num_draw_layers_ == 2)
      EndTest();
  }

  void AfterTest() override {
    // The first commit will always draw; make sure the second draw triggered
    // by the animation was not cancelled.
    EXPECT_EQ(2, num_draw_layers_);
    EXPECT_EQ(2, num_animate_);
  }

 private:
  int num_animate_;
  int num_draw_layers_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestForceRedraw);

class LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit()
      : num_animate_(0), num_draw_layers_(0) {}

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    if (++num_animate_ <= 2) {
      layer_tree_host()->SetNeedsCommit();
      layer_tree_host()->SetNeedsAnimate();
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
    if (++num_draw_layers_ == 2)
      EndTest();
  }

  void AfterTest() override {
    // The first commit will always draw; make sure the second draw triggered
    // by the SetNeedsCommit was not cancelled.
    EXPECT_EQ(2, num_draw_layers_);
    EXPECT_GE(num_animate_, 2);
  }

 private:
  int num_animate_;
  int num_draw_layers_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit);

// Animations should not be started when frames are being skipped due to
// checkerboard.
class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
    : public LayerTreeHostAnimationTest {
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());
    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachPlayersToTimeline();
    player_child_->AttachElement(picture_->element_id());
    player_child_->set_animation_delegate(this);
  }

  void InitializeSettings(LayerTreeSettings* settings) override {
    // Make sure that drawing many times doesn't cause a checkerboarded
    // animation to start so we avoid flake in this test.
    settings->timeout_and_draw_when_animation_checkerboards = false;
    LayerTreeHostAnimationTest::InitializeSettings(settings);
  }

  void BeginTest() override {
    prevented_draw_ = 0;
    started_times_ = 0;

    PostSetNeedsCommitToMainThread();
  }

  DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                   LayerTreeHostImpl::FrameData* frame_data,
                                   DrawResult draw_result) override {
    // Don't checkerboard when the first animation wants to start.
    if (host_impl->active_tree()->source_frame_number() < 2)
      return draw_result;
    if (TestEnded())
      return draw_result;
    // Act like there is checkerboard when the second animation wants to draw.
    ++prevented_draw_;
    if (prevented_draw_ > 2)
      EndTest();
    return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
  }

  void DidCommitAndDrawFrame() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        // The animation is longer than 1 BeginFrame interval.
        AddOpacityTransitionToPlayer(player_child_.get(), 0.1, 0.2f, 0.8f,
                                     false);
        break;
      case 2:
        // This second animation will not be drawn so it should not start.
        AddAnimatedTransformToPlayer(player_child_.get(), 0.1, 5, 5);
        break;
    }
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    if (TestEnded())
      return;
    started_times_++;
  }

  void AfterTest() override {
    // Make sure we tried to draw the second animation but failed.
    EXPECT_LT(0, prevented_draw_);
    // The first animation should be started, but the second should not because
    // of checkerboard.
    EXPECT_EQ(1, started_times_);
  }

  int prevented_draw_;
  int started_times_;
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations);

// Verifies that scroll offset animations are only accepted when impl-scrolling
// is supported, and that when scroll offset animations are accepted,
// scroll offset updates are sent back to the main thread.
class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetScrollable(gfx::Size(100, 100));
    scroll_layer_->SetBounds(gfx::Size(1000, 1000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    AttachPlayersToTimeline();
    player_child_->AttachElement(scroll_layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1: {
        std::unique_ptr<ScrollOffsetAnimationCurve> curve(
            ScrollOffsetAnimationCurve::Create(
                gfx::ScrollOffset(500.f, 550.f),
                CubicBezierTimingFunction::CreatePreset(
                    CubicBezierTimingFunction::EaseType::EASE_IN_OUT)));
        std::unique_ptr<Animation> animation(Animation::Create(
            std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET));
        animation->set_needs_synchronized_start_time(true);
        bool impl_scrolling_supported = proxy()->SupportsImplScrolling();
        if (impl_scrolling_supported)
          player_child_->AddAnimation(std::move(animation));
        else
          EndTest();
        break;
      }
      default:
        EXPECT_GE(scroll_layer_->scroll_offset().x(), 10);
        EXPECT_GE(scroll_layer_->scroll_offset().y(), 20);
        if (scroll_layer_->scroll_offset().x() > 10 &&
            scroll_layer_->scroll_offset().y() > 20)
          EndTest();
    }
  }

  void AfterTest() override {}

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestScrollOffsetChangesArePropagated);

// Verifies that when a main thread scrolling reason gets added, the
// notification to takover the animation on the main thread gets sent.
class LayerTreeHostAnimationTestScrollOffsetAnimationTakeover
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestScrollOffsetAnimationTakeover() = default;

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetBounds(gfx::Size(10000, 10000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
    scroll_layer_->SetScrollable(gfx::Size(10, 10));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    AttachPlayersToTimeline();
    player_child_->AttachElement(scroll_layer_->element_id());
    // Allows NotifyAnimationTakeover to get called.
    player_child_->set_animation_delegate(this);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      // Add an update after the first commit to trigger the animation takeover
      // path.
      animation_host()->scroll_offset_animations().AddTakeoverUpdate(
          scroll_layer_->element_id());
      EXPECT_TRUE(
          animation_host()->scroll_offset_animations().HasUpdatesForTesting());
    }
  }

  void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() == 0) {
      GetImplAnimationHost(host_impl)->ImplOnlyScrollAnimationCreate(
          scroll_layer_->element_id(), gfx::ScrollOffset(650.f, 750.f),
          gfx::ScrollOffset(10, 20), base::TimeDelta(), base::TimeDelta());
    }
  }

  void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
                               int target_property,
                               base::TimeTicks animation_start_time,
                               std::unique_ptr<AnimationCurve> curve) override {
    EndTest();
  }

  void AfterTest() override {}

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationTakeover);

// Verifies that an impl-only scroll offset animation gets updated when the
// scroll offset is adjusted on the main thread.
class LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted() = default;

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetBounds(gfx::Size(10000, 10000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
    scroll_layer_->SetScrollable(gfx::Size(10, 10));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    AttachPlayersToTimeline();
  }

  AnimationTicker& ScrollOffsetTicker(
      const LayerTreeHostImpl& host_impl,
      scoped_refptr<FakePictureLayer> layer) const {
    scoped_refptr<ElementAnimations> element_animations =
        GetImplAnimationHost(&host_impl)
            ->GetElementAnimationsForElementId(layer->element_id());
    DCHECK(element_animations);
    DCHECK(element_animations->tickers_list().might_have_observers());
    AnimationTicker* ticker = &*element_animations->tickers_list().begin();
    DCHECK(ticker);
    return *ticker;
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      // Add an update after the first commit to trigger the animation update
      // path.
      animation_host()->scroll_offset_animations().AddAdjustmentUpdate(
          scroll_layer_->element_id(), gfx::Vector2dF(100.f, 100.f));
      EXPECT_TRUE(
          animation_host()->scroll_offset_animations().HasUpdatesForTesting());
    } else if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Verify that the update queue is cleared after the update is applied.
      EXPECT_FALSE(
          animation_host()->scroll_offset_animations().HasUpdatesForTesting());
    }
  }

  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
    // Note that the frame number gets incremented after BeginCommitOnThread but
    // before WillCommitCompleteOnThread and CommitCompleteOnThread.
    if (host_impl->sync_tree()->source_frame_number() == 0) {
      GetImplTimelineAndPlayerByID(*host_impl);
      // This happens after the impl-only animation is added in
      // WillCommitCompleteOnThread.
      Animation* animation = ScrollOffsetTicker(*host_impl, scroll_layer_)
                                 .GetAnimation(TargetProperty::SCROLL_OFFSET);
      DCHECK(animation);
      ScrollOffsetAnimationCurve* curve =
          animation->curve()->ToScrollOffsetAnimationCurve();

      // Verifiy the initial and target position before the scroll offset
      // update from MT.
      EXPECT_EQ(gfx::ScrollOffset(10.f, 20.f),
                curve->GetValue(base::TimeDelta()));
      EXPECT_EQ(gfx::ScrollOffset(650.f, 750.f), curve->target_value());
    }
  }

  void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() == 0) {
      GetImplAnimationHost(host_impl)->ImplOnlyScrollAnimationCreate(
          scroll_layer_->element_id(), gfx::ScrollOffset(650.f, 750.f),
          gfx::ScrollOffset(10, 20), base::TimeDelta(), base::TimeDelta());
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() == 1) {
      Animation* animation = ScrollOffsetTicker(*host_impl, scroll_layer_)
                                 .GetAnimation(TargetProperty::SCROLL_OFFSET);
      DCHECK(animation);
      ScrollOffsetAnimationCurve* curve =
          animation->curve()->ToScrollOffsetAnimationCurve();
      // Verifiy the initial and target position after the scroll offset
      // update from MT
      EXPECT_EQ(Animation::RunState::STARTING, animation->run_state());
      EXPECT_EQ(gfx::ScrollOffset(110.f, 120.f),
                curve->GetValue(base::TimeDelta()));
      EXPECT_EQ(gfx::ScrollOffset(750.f, 850.f), curve->target_value());

      EndTest();
    }
  }

  void AfterTest() override {}

 private:
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted);

// Verifies that when the main thread removes a scroll animation and sets a new
// scroll position, the active tree takes on exactly this new scroll position
// after activation, and the main thread doesn't receive a spurious scroll
// delta.
class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestScrollOffsetAnimationRemoval()
      : final_postion_(50.0, 100.0) {}

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    scroll_layer_ = FakePictureLayer::Create(&client_);
    scroll_layer_->SetScrollable(gfx::Size(100, 100));
    scroll_layer_->SetBounds(gfx::Size(10000, 10000));
    client_.set_bounds(scroll_layer_->bounds());
    scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0));
    layer_tree_host()->root_layer()->AddChild(scroll_layer_);

    std::unique_ptr<ScrollOffsetAnimationCurve> curve(
        ScrollOffsetAnimationCurve::Create(
            gfx::ScrollOffset(6500.f, 7500.f),
            CubicBezierTimingFunction::CreatePreset(
                CubicBezierTimingFunction::EaseType::EASE_IN_OUT)));
    std::unique_ptr<Animation> animation(Animation::Create(
        std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET));
    animation->set_needs_synchronized_start_time(true);

    AttachPlayersToTimeline();
    player_child_->AttachElement(scroll_layer_->element_id());
    player_child_->AddAnimation(std::move(animation));
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void BeginMainFrame(const viz::BeginFrameArgs& args) override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 0:
        EXPECT_EQ(scroll_layer_->scroll_offset().x(), 100);
        EXPECT_EQ(scroll_layer_->scroll_offset().y(), 200);
        break;
      case 1: {
        EXPECT_GE(scroll_layer_->scroll_offset().x(), 100);
        EXPECT_GE(scroll_layer_->scroll_offset().y(), 200);
        Animation* animation =
            player_child_->GetAnimation(TargetProperty::SCROLL_OFFSET);
        player_child_->RemoveAnimation(animation->id());
        scroll_layer_->SetScrollOffset(final_postion_);
        break;
      }
      default:
        EXPECT_EQ(final_postion_, scroll_layer_->scroll_offset());
    }
  }

  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
    host_impl->BlockNotifyReadyToActivateForTesting(
        ShouldBlockActivation(host_impl));
  }

  void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
                                  const viz::BeginFrameArgs& args) override {
    host_impl->BlockNotifyReadyToActivateForTesting(
        ShouldBlockActivation(host_impl));
  }

  void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->pending_tree()->source_frame_number() != 1)
      return;
    LayerImpl* scroll_layer_impl =
        host_impl->pending_tree()->LayerById(scroll_layer_->id());
    EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
  }

  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->active_tree()->source_frame_number() != 1)
      return;
    LayerImpl* scroll_layer_impl =
        host_impl->active_tree()->LayerById(scroll_layer_->id());
    EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
    EndTest();
  }

  void AfterTest() override {
    EXPECT_EQ(final_postion_, scroll_layer_->scroll_offset());
  }

 private:
  bool ShouldBlockActivation(LayerTreeHostImpl* host_impl) {
    if (!host_impl->pending_tree())
      return false;

    if (!host_impl->active_tree()->root_layer_for_testing())
      return false;

    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<AnimationPlayer> player_impl =
        timeline_impl->GetPlayerById(player_child_id_);

    LayerImpl* scroll_layer_impl =
        host_impl->active_tree()->LayerById(scroll_layer_->id());
    Animation* animation =
        player_impl->GetAnimation(TargetProperty::SCROLL_OFFSET);

    if (!animation || animation->run_state() != Animation::RUNNING)
      return false;

    // Block activation until the running animation has a chance to produce a
    // scroll delta.
    gfx::Vector2dF scroll_delta = ScrollDelta(scroll_layer_impl);
    if (scroll_delta.x() > 0.f || scroll_delta.y() > 0.f)
      return false;

    return true;
  }

  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> scroll_layer_;
  const gfx::ScrollOffset final_postion_;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationRemoval);

// When animations are simultaneously added to an existing layer and to a new
// layer, they should start at the same time, even when there's already a
// running animation on the existing layer.
class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers()
      : frame_count_with_pending_tree_(0) {}

  void BeginTest() override {
    AttachPlayersToTimeline();
    PostSetNeedsCommitToMainThread();
  }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      player_->AttachElement(layer_tree_host()->root_layer()->element_id());
      AddAnimatedTransformToPlayer(player_.get(), 4, 1, 1);
    } else if (layer_tree_host()->SourceFrameNumber() == 2) {
      AddOpacityTransitionToPlayer(player_.get(), 1, 0.f, 0.5f, true);

      scoped_refptr<Layer> layer = Layer::Create();
      layer_tree_host()->root_layer()->AddChild(layer);

      layer_tree_host()->SetElementIdsForTesting();
      layer->SetBounds(gfx::Size(4, 4));

      player_child_->AttachElement(layer->element_id());
      player_child_->set_animation_delegate(this);
      AddOpacityTransitionToPlayer(player_child_.get(), 1, 0.f, 0.5f, true);
    }
  }

  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
    host_impl->BlockNotifyReadyToActivateForTesting(true);
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    // For the commit that added animations to new and existing layers, keep
    // blocking activation. We want to verify that even with activation blocked,
    // the animation on the layer that's already in the active tree won't get a
    // head start.
    if (host_impl->pending_tree()->source_frame_number() != 2) {
      host_impl->BlockNotifyReadyToActivateForTesting(false);
    }
  }

  void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
                                  const viz::BeginFrameArgs& args) override {
    if (!host_impl->pending_tree() ||
        host_impl->pending_tree()->source_frame_number() != 2)
      return;

    frame_count_with_pending_tree_++;
    if (frame_count_with_pending_tree_ == 2) {
      host_impl->BlockNotifyReadyToActivateForTesting(false);
    }
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<AnimationPlayer> player_impl =
        timeline_impl->GetPlayerById(player_id_);
    scoped_refptr<AnimationPlayer> player_child_impl =
        timeline_impl->GetPlayerById(player_child_id_);

    // wait for tree activation.
    if (!player_impl->element_animations())
      return;

    Animation* root_animation =
        player_impl->GetAnimation(TargetProperty::OPACITY);
    if (!root_animation || root_animation->run_state() != Animation::RUNNING)
      return;

    Animation* child_animation =
        player_child_impl->GetAnimation(TargetProperty::OPACITY);
    EXPECT_EQ(Animation::RUNNING, child_animation->run_state());
    EXPECT_EQ(root_animation->start_time(), child_animation->start_time());
    player_impl->AbortAnimations(TargetProperty::OPACITY, false);
    player_impl->AbortAnimations(TargetProperty::TRANSFORM, false);
    player_child_impl->AbortAnimations(TargetProperty::OPACITY, false);
    EndTest();
  }

  void AfterTest() override {}

 private:
  int frame_count_with_pending_tree_;
};

// This test blocks activation which is not supported for single thread mode.
MULTI_THREAD_BLOCKNOTIFY_TEST_F(
    LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers);

class LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();

    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(2, 2));
    client_.set_bounds(layer_->bounds());
    // Transform the layer to 4,4 to start.
    gfx::Transform start_transform;
    start_transform.Translate(4.0, 4.0);
    layer_->SetTransform(start_transform);

    layer_tree_host()->root_layer()->AddChild(layer_);
    layer_tree_host()->SetElementIdsForTesting();

    player_->AttachElement(layer_->element_id());

    AttachPlayersToTimeline();
  }

  void BeginTest() override {
    // Add a translate from 6,7 to 8,9.
    TransformOperations start;
    start.AppendTranslate(6.f, 7.f, 0.f);
    TransformOperations end;
    end.AppendTranslate(8.f, 9.f, 0.f);
    AddAnimatedTransformToPlayer(player_.get(), 4.0, start, end);

    PostSetNeedsCommitToMainThread();
  }

  void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override {
    // After activating the sync tree PrepareTiles will be called
    // again (which races with the test exiting).
    LayerTreeImpl* sync_tree = host_impl->sync_tree();
    if (!sync_tree || TestEnded())
      return;

    if (sync_tree->source_frame_number() != 0)
      return;

    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<AnimationPlayer> player_impl =
        timeline_impl->GetPlayerById(player_id_);

    LayerImpl* child = sync_tree->LayerById(layer_->id());
    Animation* animation = player_impl->GetAnimation(TargetProperty::TRANSFORM);

    // The animation should be starting for the first frame.
    EXPECT_EQ(Animation::STARTING, animation->run_state());

    // And the transform should be propogated to the sync tree layer, at its
    // starting state which is 6,7.
    gfx::Transform expected_transform;
    expected_transform.Translate(6.0, 7.0);
    EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, child->DrawTransform());
    // And the sync tree layer should know it is animating.
    EXPECT_TRUE(child->screen_space_transform_is_animating());

    player_impl->AbortAnimations(TargetProperty::TRANSFORM, false);
    EndTest();
  }

  void AfterTest() override {}

  FakeContentLayerClient client_;
  scoped_refptr<Layer> layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit);

// When a layer with an animation is removed from the tree and later re-added,
// the animation should resume.
class LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = Layer::Create();
    layer_->SetBounds(gfx::Size(4, 4));
    layer_tree_host()->root_layer()->AddChild(layer_);

    layer_tree_host()->SetElementIdsForTesting();

    animation_host()->AddAnimationTimeline(timeline_.get());
    timeline_->AttachPlayer(player_.get());
    player_->AttachElement(layer_->element_id());
    DCHECK(player_->element_animations());

    AddOpacityTransitionToPlayer(player_.get(), 10000.0, 0.1f, 0.9f, true);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 0:
        EXPECT_TRUE(
            player_->element_animations()->has_element_in_active_list());
        EXPECT_FALSE(
            player_->element_animations()->has_element_in_pending_list());
        EXPECT_TRUE(animation_host()->NeedsTickAnimations());
        break;
      case 1:
        layer_->RemoveFromParent();
        EXPECT_FALSE(
            player_->element_animations()->has_element_in_active_list());
        EXPECT_FALSE(
            player_->element_animations()->has_element_in_pending_list());
        EXPECT_FALSE(animation_host()->NeedsTickAnimations());
        break;
      case 2:
        layer_tree_host()->root_layer()->AddChild(layer_);
        EXPECT_TRUE(
            player_->element_animations()->has_element_in_active_list());
        EXPECT_FALSE(
            player_->element_animations()->has_element_in_pending_list());
        EXPECT_TRUE(animation_host()->NeedsTickAnimations());
        break;
    }
  }

  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
    scoped_refptr<AnimationTimeline> timeline_impl =
        GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
    scoped_refptr<AnimationPlayer> player_impl =
        timeline_impl->GetPlayerById(player_id_);

    switch (host_impl->active_tree()->source_frame_number()) {
      case 0:
        EXPECT_TRUE(
            player_impl->element_animations()->has_element_in_active_list());
        EXPECT_TRUE(GetImplAnimationHost(host_impl)->NeedsTickAnimations());
        break;
      case 1:
        EXPECT_FALSE(
            player_impl->element_animations()->has_element_in_active_list());
        EXPECT_FALSE(GetImplAnimationHost(host_impl)->NeedsTickAnimations());
        break;
      case 2:
        EXPECT_TRUE(
            player_impl->element_animations()->has_element_in_active_list());
        EXPECT_TRUE(GetImplAnimationHost(host_impl)->NeedsTickAnimations());
        EndTest();
        break;
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded);

class LayerTreeHostAnimationTestAddAnimationAfterAnimating
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = Layer::Create();
    layer_->SetBounds(gfx::Size(4, 4));
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachPlayersToTimeline();

    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    player_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        // First frame: add an animation to the root layer.
        AddAnimatedTransformToPlayer(player_.get(), 0.1, 5, 5);
        break;
      case 2:
        // Second frame: add an animation to the content layer. The root layer
        // animation has caused us to animate already during this frame.
        AddOpacityTransitionToPlayer(player_child_.get(), 0.1, 5, 5, false);
        break;
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    // After both animations have started, verify that they have valid
    // start times.
    if (host_impl->active_tree()->source_frame_number() < 2)
      return;

    // Animation state is updated after drawing. Only do this once.
    if (!TestEnded()) {
      ImplThreadTaskRunner()->PostTask(
          FROM_HERE,
          base::BindOnce(&LayerTreeHostAnimationTestAddAnimationAfterAnimating::
                             CheckAnimations,
                         base::Unretained(this), host_impl));
    }
  }

  void CheckAnimations(LayerTreeHostImpl* host_impl) {
    GetImplTimelineAndPlayerByID(*host_impl);

    EXPECT_EQ(
        2u,
        GetImplAnimationHost(host_impl)->ticking_players_for_testing().size());

    Animation* root_anim =
        player_impl_->GetAnimation(TargetProperty::TRANSFORM);
    EXPECT_LT(base::TimeTicks(), root_anim->start_time());

    Animation* anim = player_child_impl_->GetAnimation(TargetProperty::OPACITY);
    EXPECT_LT(base::TimeTicks(), anim->start_time());

    EndTest();
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestAddAnimationAfterAnimating);

class LayerTreeHostAnimationTestRemoveAnimation
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachPlayersToTimeline();

    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    player_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override {
    animation_stopped_ = false;
    last_frame_number_ = INT_MAX;
    PostSetNeedsCommitToMainThread();
  }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        AddAnimatedTransformToPlayer(player_child_.get(), 1.0, 5, 5);
        break;
      case 2:
        Animation* animation =
            player_child_->GetAnimation(TargetProperty::TRANSFORM);
        player_child_->RemoveAnimation(animation->id());
        gfx::Transform transform;
        transform.Translate(10.f, 10.f);
        layer_->SetTransform(transform);

        // Do something that causes property trees to get rebuilt. This is
        // intended to simulate the conditions that caused the bug whose fix
        // this is testing (the test will pass without it but won't test what
        // we want it to). We were updating the wrong transform node at the end
        // of an animation (we were assuming the layer with the finished
        // animation still had its own transform node). But nodes can only get
        // added/deleted when something triggers a rebuild. Adding a layer
        // triggers a rebuild, and since the layer that had an animation before
        // no longer has one, it doesn't get a transform node in the rebuild.
        layer_->AddChild(Layer::Create());
        break;
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    GetImplTimelineAndPlayerByID(*host_impl);
    LayerImpl* child = host_impl->active_tree()->LayerById(layer_->id());
    switch (host_impl->active_tree()->source_frame_number()) {
      case 0:
        // No animation yet.
        break;
      case 1:
        // Animation is started.
        EXPECT_TRUE(child->screen_space_transform_is_animating());
        break;
      case 2: {
        // The animation is stopped, the transform that was set afterward is
        // applied.
        gfx::Transform expected_transform;
        expected_transform.Translate(10.f, 10.f);
        EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform,
                                        child->DrawTransform());
        EXPECT_FALSE(child->screen_space_transform_is_animating());
        animation_stopped_ = true;
        PostSetNeedsCommitToMainThread();
        break;
      }
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->sync_tree()->source_frame_number() >= last_frame_number_) {
      // Check that eventually the animation is removed.
      EXPECT_FALSE(player_child_impl_->animation_ticker()->has_any_animation());
      EndTest();
    }
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    // Non impl only animations are removed during commit. After the animation
    // is fully stopped on compositor thread, make sure another commit happens.
    if (animation_stopped_ && !has_unfinished_animation) {
      last_frame_number_ =
          std::min(last_frame_number_,
                   host_impl->active_tree()->source_frame_number() + 1);
      PostSetNeedsCommitToMainThread();
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;

  int last_frame_number_;
  bool animation_stopped_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestRemoveAnimation);

class LayerTreeHostAnimationTestIsAnimating
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachPlayersToTimeline();
    player_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    switch (layer_tree_host()->SourceFrameNumber()) {
      case 1:
        AddAnimatedTransformToPlayer(player_.get(), 1.0, 5, 5);
        break;
      case 2:
        Animation* animation = player_->GetAnimation(TargetProperty::TRANSFORM);
        player_->RemoveAnimation(animation->id());
        break;
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    LayerImpl* child = host_impl->sync_tree()->LayerById(layer_->id());
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 0:
        // No animation yet.
        break;
      case 1:
        // Animation is started.
        EXPECT_TRUE(child->screen_space_transform_is_animating());
        break;
      case 2:
        // The animation is removed/stopped.
        EXPECT_FALSE(child->screen_space_transform_is_animating());
        EndTest();
        break;
      default:
        NOTREACHED();
    }
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    LayerImpl* child = host_impl->active_tree()->LayerById(layer_->id());
    switch (host_impl->active_tree()->source_frame_number()) {
      case 0:
        // No animation yet.
        break;
      case 1:
        // Animation is started.
        EXPECT_TRUE(child->screen_space_transform_is_animating());
        break;
      case 2:
        // The animation is removed/stopped.
        EXPECT_FALSE(child->screen_space_transform_is_animating());
        EndTest();
        break;
      default:
        NOTREACHED();
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestIsAnimating);

class LayerTreeHostAnimationTestAnimationFinishesDuringCommit
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestAnimationFinishesDuringCommit()
      : signalled_(false) {}

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachPlayersToTimeline();

    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    player_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1)
      AddAnimatedTransformToPlayer(player_child_.get(), 0.04, 5, 5);
  }

  void WillCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Block until the animation finishes on the compositor thread. Since
      // animations have already been ticked on the main thread, when the commit
      // happens the state on the main thread will be consistent with having a
      // running animation but the state on the compositor thread will be
      // consistent with having only a finished animation.
      completion_.Wait();
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 1:
        PostSetNeedsCommitToMainThread();
        break;
      case 2:
        gfx::Transform expected_transform;
        expected_transform.Translate(5.f, 5.f);
        LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id());
        EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform,
                                        layer_impl->DrawTransform());
        EndTest();
        break;
    }
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    if (host_impl->active_tree()->source_frame_number() == 1 &&
        !has_unfinished_animation && !signalled_) {
      // The animation has finished, so allow the main thread to commit.
      completion_.Signal();
      signalled_ = true;
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
  CompletionEvent completion_;
  bool signalled_;
};

// An animation finishing during commit can only happen when we have a separate
// compositor thread.
MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationFinishesDuringCommit);

class LayerTreeHostAnimationTestImplSideInvalidation
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachPlayersToTimeline();

    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    player_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1)
      AddAnimatedTransformToPlayer(player_child_.get(), 0.04, 5, 5);
  }

  void WillCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Block until the animation finishes on the compositor thread. Since
      // animations have already been ticked on the main thread, when the commit
      // happens the state on the main thread will be consistent with having a
      // running animation but the state on the compositor thread will be
      // consistent with having only a finished animation.
      completion_.Wait();
    }
  }

  void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
    DCHECK(did_request_impl_side_invalidation_);
    completion_.Signal();
  }

  void UpdateAnimationState(LayerTreeHostImpl* host_impl,
                            bool has_unfinished_animation) override {
    if (host_impl->active_tree()->source_frame_number() == 1 &&
        !has_unfinished_animation && !did_request_impl_side_invalidation_) {
      // The animation on the active tree has finished, now request an impl-side
      // invalidation and make sure it finishes before the main thread is
      // released.
      did_request_impl_side_invalidation_ = true;
      host_impl->RequestImplSideInvalidationForCheckerImagedTiles();
    }
  }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 1:
        PostSetNeedsCommitToMainThread();
        break;
      case 2:
        gfx::Transform expected_transform;
        expected_transform.Translate(5.f, 5.f);
        LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id());
        EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform,
                                        layer_impl->DrawTransform());
        EndTest();
        break;
    }
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
  CompletionEvent completion_;
  bool did_request_impl_side_invalidation_ = false;
};

MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestImplSideInvalidation);

class LayerTreeHostAnimationTestNotifyAnimationFinished
    : public LayerTreeHostAnimationTest {
 public:
  LayerTreeHostAnimationTestNotifyAnimationFinished()
      : called_animation_started_(false), called_animation_finished_(false) {}

  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    picture_ = FakePictureLayer::Create(&client_);
    picture_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(picture_->bounds());
    layer_tree_host()->root_layer()->AddChild(picture_);

    AttachPlayersToTimeline();
    player_->AttachElement(picture_->element_id());
    player_->set_animation_delegate(this);
  }

  void BeginTest() override {
    PostAddLongAnimationToMainThreadPlayer(player_.get());
  }

  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
                              int target_property,
                              int group) override {
    called_animation_started_ = true;
    layer_tree_host()->AnimateLayers(base::TimeTicks::Max());
    PostSetNeedsCommitToMainThread();
  }

  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
                               int target_property,
                               int group) override {
    called_animation_finished_ = true;
    EndTest();
  }

  void AfterTest() override {
    EXPECT_TRUE(called_animation_started_);
    EXPECT_TRUE(called_animation_finished_);
  }

 private:
  bool called_animation_started_;
  bool called_animation_finished_;
  FakeContentLayerClient client_;
  scoped_refptr<FakePictureLayer> picture_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestNotifyAnimationFinished);

// Check that transform sync happens correctly at commit when we remove and add
// a different animation player to an element.
class LayerTreeHostAnimationTestChangeAnimationPlayer
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    AttachPlayersToTimeline();
    timeline_->DetachPlayer(player_child_.get());
    player_->AttachElement(layer_tree_host()->root_layer()->element_id());

    TransformOperations start;
    start.AppendTranslate(5.f, 5.f, 0.f);
    TransformOperations end;
    end.AppendTranslate(5.f, 5.f, 0.f);
    AddAnimatedTransformToPlayer(player_.get(), 1.0, start, end);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    PropertyTrees* property_trees = host_impl->sync_tree()->property_trees();
    TransformNode* node =
        property_trees->transform_tree.Node(host_impl->sync_tree()
                                                ->root_layer_for_testing()
                                                ->transform_tree_index());
    gfx::Transform translate;
    translate.Translate(5, 5);
    switch (host_impl->sync_tree()->source_frame_number()) {
      case 2:
        EXPECT_TRANSFORMATION_MATRIX_EQ(node->local, translate);
        EndTest();
        break;
      default:
        break;
    }
  }

  void DidCommit() override { PostSetNeedsCommitToMainThread(); }

  void WillBeginMainFrame() override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Destroy player.
      timeline_->DetachPlayer(player_.get());
      player_ = nullptr;
      timeline_->AttachPlayer(player_child_.get());
      player_child_->AttachElement(
          layer_tree_host()->root_layer()->element_id());
      AddAnimatedTransformToPlayer(player_child_.get(), 1.0, 10, 10);
      Animation* animation =
          player_child_->GetAnimation(TargetProperty::TRANSFORM);
      animation->set_start_time(base::TimeTicks::Now() +
                                base::TimeDelta::FromSecondsD(1000));
      animation->set_fill_mode(Animation::FillMode::NONE);
    }
  }

  void AfterTest() override {}
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestChangeAnimationPlayer);

// Check that SetTransformIsPotentiallyAnimatingChanged is called
// if we destroy ElementAnimations.
class LayerTreeHostAnimationTestSetPotentiallyAnimatingOnLacDestruction
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    prev_screen_space_transform_is_animating_ = true;
    screen_space_transform_animation_stopped_ = false;

    LayerTreeHostAnimationTest::SetupTree();
    AttachPlayersToTimeline();
    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    AddAnimatedTransformToPlayer(player_.get(), 1.0, 5, 5);
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->pending_tree()->source_frame_number() <= 1) {
      EXPECT_TRUE(host_impl->pending_tree()
                      ->root_layer_for_testing()
                      ->screen_space_transform_is_animating());
    } else {
      EXPECT_FALSE(host_impl->pending_tree()
                       ->root_layer_for_testing()
                       ->screen_space_transform_is_animating());
    }
  }

  void DidCommit() override { PostSetNeedsCommitToMainThread(); }

  void UpdateLayerTreeHost(
      LayerTreeHostClient::VisualStateUpdate requested_update) override {
    if (layer_tree_host()->SourceFrameNumber() == 2) {
      // Destroy player.
      timeline_->DetachPlayer(player_.get());
      player_ = nullptr;
    }
  }

  DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                   LayerTreeHostImpl::FrameData* frame_data,
                                   DrawResult draw_result) override {
    const bool screen_space_transform_is_animating =
        host_impl->active_tree()
            ->root_layer_for_testing()
            ->screen_space_transform_is_animating();

    // Check that screen_space_transform_is_animating changes only once.
    if (screen_space_transform_is_animating &&
        prev_screen_space_transform_is_animating_)
      EXPECT_FALSE(screen_space_transform_animation_stopped_);
    if (!screen_space_transform_is_animating &&
        prev_screen_space_transform_is_animating_) {
      EXPECT_FALSE(screen_space_transform_animation_stopped_);
      screen_space_transform_animation_stopped_ = true;
    }
    if (!screen_space_transform_is_animating &&
        !prev_screen_space_transform_is_animating_)
      EXPECT_TRUE(screen_space_transform_animation_stopped_);

    prev_screen_space_transform_is_animating_ =
        screen_space_transform_is_animating;

    return draw_result;
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->active_tree()->source_frame_number() >= 2)
      EndTest();
  }

  void AfterTest() override {
    EXPECT_TRUE(screen_space_transform_animation_stopped_);
  }

  bool prev_screen_space_transform_is_animating_;
  bool screen_space_transform_animation_stopped_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestSetPotentiallyAnimatingOnLacDestruction);

// Check that we invalidate property trees on AnimationPlayer::SetNeedsCommit.
class LayerTreeHostAnimationTestRebuildPropertyTreesOnAnimationSetNeedsCommit
    : public LayerTreeHostAnimationTest {
 public:
  void SetupTree() override {
    LayerTreeHostAnimationTest::SetupTree();
    layer_ = FakePictureLayer::Create(&client_);
    layer_->SetBounds(gfx::Size(4, 4));
    client_.set_bounds(layer_->bounds());
    layer_tree_host()->root_layer()->AddChild(layer_);

    AttachPlayersToTimeline();

    player_->AttachElement(layer_tree_host()->root_layer()->element_id());
    player_child_->AttachElement(layer_->element_id());
  }

  void BeginTest() override { PostSetNeedsCommitToMainThread(); }

  void DidCommit() override {
    if (layer_tree_host()->SourceFrameNumber() == 1 ||
        layer_tree_host()->SourceFrameNumber() == 2)
      PostSetNeedsCommitToMainThread();
  }

  void UpdateLayerTreeHost(
      LayerTreeHostClient::VisualStateUpdate requested_update) override {
    if (layer_tree_host()->SourceFrameNumber() == 1) {
      EXPECT_FALSE(layer_tree_host()->property_trees()->needs_rebuild);
      AddAnimatedTransformToPlayer(player_child_.get(), 1.0, 5, 5);
    }

    EXPECT_TRUE(layer_tree_host()->property_trees()->needs_rebuild);
  }

  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
    if (host_impl->active_tree()->source_frame_number() >= 2)
      EndTest();
  }

  void AfterTest() override {}

 private:
  scoped_refptr<Layer> layer_;
  FakeContentLayerClient client_;
};

MULTI_THREAD_TEST_F(
    LayerTreeHostAnimationTestRebuildPropertyTreesOnAnimationSetNeedsCommit);

}  // namespace
}  // namespace cc
