EXPECT_FALSE(controller_impl->GetAnimation(Animation::Opacity));
+ EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+ EXPECT_FALSE(controller_impl->needs_to_start_animations_for_testing());
+
AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
+ EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
int group_id = controller->GetAnimation(Animation::Opacity)->group();
controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(controller_impl->needs_to_start_animations_for_testing());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
EXPECT_EQ(Animation::WaitingForTargetAvailability,
int group_id = controller->GetAnimation(Animation::Opacity)->group();
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
EXPECT_EQ(Animation::WaitingForTargetAvailability,
Animation::Opacity)->start_time());
}
+TEST(LayerAnimationControllerTest, UseSpecifiedStartTimes) {
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
+ int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+ const double start_time = 123;
+ controller->GetAnimation(Animation::Opacity)->set_start_time(start_time);
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
+
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+ EXPECT_EQ(Animation::WaitingForTargetAvailability,
+ controller_impl->GetAnimation(group_id,
+ Animation::Opacity)->run_state());
+
+ AnimationEventsVector events;
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, &events);
+
+ // Synchronize the start times.
+ EXPECT_EQ(1u, events.size());
+ controller->NotifyAnimationStarted(events[0]);
+
+ EXPECT_EQ(start_time,
+ controller->GetAnimation(group_id,
+ Animation::Opacity)->start_time());
+ EXPECT_EQ(controller->GetAnimation(group_id,
+ Animation::Opacity)->start_time(),
+ controller_impl->GetAnimation(group_id,
+ Animation::Opacity)->start_time());
+
+ // Start the animation on the main thread. Should not affect the start time.
+ controller->Animate(kInitialTickTime + 0.5);
+ controller->UpdateState(true, NULL);
+ EXPECT_EQ(start_time,
+ controller->GetAnimation(group_id,
+ Animation::Opacity)->start_time());
+ EXPECT_EQ(controller->GetAnimation(group_id,
+ Animation::Opacity)->start_time(),
+ controller_impl->GetAnimation(group_id,
+ Animation::Opacity)->start_time());
+}
+
// Tests that controllers activate and deactivate as expected.
TEST(LayerAnimationControllerTest, Activation) {
scoped_ptr<AnimationRegistrar> registrar = AnimationRegistrar::Create();
EXPECT_EQ(1u, registrar->active_animation_controllers().size());
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
// Both controllers should now be active.
EXPECT_EQ(1u, registrar->active_animation_controllers().size());
EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size());
EXPECT_EQ(0u, registrar->active_animation_controllers().size());
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_FALSE(controller->has_any_animation());
EXPECT_FALSE(controller_impl->has_any_animation());
EXPECT_EQ(0u, registrar->active_animation_controllers().size());
int animation_id = controller->GetAnimation(Animation::Opacity)->id();
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
EXPECT_EQ(Animation::WaitingForTargetAvailability,
// The pause run state change should make it to the impl thread controller.
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_EQ(Animation::Paused,
controller_impl->GetAnimation(group_id,
Animation::Opacity)->run_state());
int group_id = controller->GetAnimation(Animation::Opacity)->group();
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
EXPECT_EQ(Animation::WaitingForTargetAvailability,
EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
// Even though the main thread has a 'new' animation, it should not be pushed
// because the animation has already completed on the impl thread.
controller->Animate(kInitialTickTime);
controller->UpdateState(true, NULL);
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
controller_impl->Animate(kInitialTickTime + 0.5);
controller_impl->UpdateState(true, events.get());
controller->PushAnimationUpdatesTo(controller_impl.get());
- // Both controllers should now have deleted the animation.
+ // Both controllers should now have deleted the animation. The impl controller
+ // should have deleted the animation even though activation has not occurred,
+ // since the animation was already waiting for deletion when
+ // PushAnimationUpdatesTo was called.
EXPECT_FALSE(controller->has_any_animation());
EXPECT_FALSE(controller_impl->has_any_animation());
}
1,
Animation::Opacity));
+ EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
controller->AddAnimation(to_add.Pass());
+ EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
controller->Animate(kInitialTickTime);
+ EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
dummy_provider_impl.set_scroll_offset(initial_value);
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(Animation::ScrollOffset));
double duration = controller_impl->GetAnimation(
Animation::ScrollOffset)->curve()->Duration();
dummy_provider.set_scroll_offset(initial_value);
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(Animation::ScrollOffset));
double duration = controller_impl->GetAnimation(
Animation::ScrollOffset)->curve()->Duration();
LayerAnimationController::Create(0));
controller->AddValueObserver(&dummy);
+ EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+
controller->AddAnimation(CreateAnimation(
scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
1,
2,
Animation::Opacity));
+ EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
+
controller->Animate(kInitialTickTime);
+
+ // The second animation still needs to be started.
+ EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
+
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
controller->Animate(kInitialTickTime + 1.0);
+
+ EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
controller->UpdateState(true, events.get());
+ EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(1.f, dummy.opacity());
controller->Animate(kInitialTickTime + 2.0);
EXPECT_TRUE(active_animation->needs_synchronized_start_time());
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
active_animation = controller_impl->GetAnimation(0, Animation::Opacity);
EXPECT_TRUE(active_animation);
EXPECT_FALSE(controller->HasActiveAnimation());
}
-// Tests that an animation controller with only an inactive observer gets ticked
+// Tests that an animation controller with only a pending observer gets ticked
// but doesn't progress animations past the Starting state.
TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
scoped_ptr<AnimationEventsVector> events(
make_scoped_ptr(new AnimationEventsVector));
FakeLayerAnimationValueObserver dummy;
- FakeInactiveLayerAnimationValueObserver inactive_dummy;
+ FakeInactiveLayerAnimationValueObserver pending_dummy;
scoped_refptr<LayerAnimationController> controller(
LayerAnimationController::Create(0));
EXPECT_EQ(Animation::WaitingForTargetAvailability,
controller->GetAnimation(id, Animation::Opacity)->run_state());
- controller->AddValueObserver(&inactive_dummy);
+ controller->AddValueObserver(&pending_dummy);
- // With only an inactive observer, the animation should progress to the
+ // With only a pending observer, the animation should progress to the
// Starting state and get ticked at its starting point, but should not
// progress to Running.
controller->Animate(kInitialTickTime + 1.0);
EXPECT_EQ(0u, events->size());
EXPECT_EQ(Animation::Starting,
controller->GetAnimation(id, Animation::Opacity)->run_state());
- EXPECT_EQ(0.5f, inactive_dummy.opacity());
+ EXPECT_EQ(0.5f, pending_dummy.opacity());
// Even when already in the Starting state, the animation should stay
// there, and shouldn't be ticked past its starting point.
EXPECT_EQ(0u, events->size());
EXPECT_EQ(Animation::Starting,
controller->GetAnimation(id, Animation::Opacity)->run_state());
- EXPECT_EQ(0.5f, inactive_dummy.opacity());
+ EXPECT_EQ(0.5f, pending_dummy.opacity());
controller->AddValueObserver(&dummy);
EXPECT_EQ(1u, events->size());
EXPECT_EQ(Animation::Running,
controller->GetAnimation(id, Animation::Opacity)->run_state());
- EXPECT_EQ(0.5f, inactive_dummy.opacity());
+ EXPECT_EQ(0.5f, pending_dummy.opacity());
EXPECT_EQ(0.5f, dummy.opacity());
// The animation should now tick past its starting point.
controller->Animate(kInitialTickTime + 3.5);
- EXPECT_NE(0.5f, inactive_dummy.opacity());
+ EXPECT_NE(0.5f, pending_dummy.opacity());
EXPECT_NE(0.5f, dummy.opacity());
}
int group_id = controller->GetAnimation(Animation::Opacity)->group();
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
controller->AbortAnimations(Animation::Opacity);
controller->GetAnimation(Animation::Opacity)->run_state());
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_FALSE(controller->GetAnimation(group_id, Animation::Opacity));
EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
}
int group_id = controller->GetAnimation(Animation::Opacity)->group();
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
controller_impl->AbortAnimations(Animation::Opacity);
controller->GetAnimation(Animation::Opacity)->run_state());
controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
EXPECT_FALSE(controller->GetAnimation(group_id, Animation::Opacity));
EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
}
EXPECT_EQ(Animation::Opacity, (*events)[1].target_property);
}
+TEST(LayerAnimationControllerTest, HasAnimationThatAffectsScale) {
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+
+ EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+
+ controller_impl->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+ 1,
+ Animation::Opacity));
+
+ // Opacity animations don't affect scale.
+ EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+
+ scoped_ptr<KeyframedTransformAnimationCurve> curve1(
+ KeyframedTransformAnimationCurve::Create());
+
+ TransformOperations operations1;
+ curve1->AddKeyframe(TransformKeyframe::Create(
+ 0.0, operations1, scoped_ptr<TimingFunction>()));
+ operations1.AppendTranslate(10.0, 15.0, 0.0);
+ curve1->AddKeyframe(TransformKeyframe::Create(
+ 1.0, operations1, scoped_ptr<TimingFunction>()));
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve1.PassAs<AnimationCurve>(), 2, 2, Animation::Transform));
+ controller_impl->AddAnimation(animation.Pass());
+
+ // Translations don't affect scale.
+ EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+
+ scoped_ptr<KeyframedTransformAnimationCurve> curve2(
+ KeyframedTransformAnimationCurve::Create());
+
+ TransformOperations operations2;
+ curve2->AddKeyframe(TransformKeyframe::Create(
+ 0.0, operations2, scoped_ptr<TimingFunction>()));
+ operations2.AppendScale(2.0, 3.0, 4.0);
+ curve2->AddKeyframe(TransformKeyframe::Create(
+ 1.0, operations2, scoped_ptr<TimingFunction>()));
+
+ animation = Animation::Create(
+ curve2.PassAs<AnimationCurve>(), 3, 3, Animation::Transform);
+ controller_impl->AddAnimation(animation.Pass());
+
+ EXPECT_TRUE(controller_impl->HasAnimationThatAffectsScale());
+
+ controller_impl->GetAnimation(3, Animation::Transform)
+ ->SetRunState(Animation::Finished, 0.0);
+
+ // Only unfinished animations should be considered by
+ // HasAnimationThatAffectsScale.
+ EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+}
+
+TEST(LayerAnimationControllerTest, HasOnlyTranslationTransforms) {
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+
+ controller_impl->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+ 1,
+ Animation::Opacity));
+
+ // Opacity animations aren't non-translation transforms.
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+
+ scoped_ptr<KeyframedTransformAnimationCurve> curve1(
+ KeyframedTransformAnimationCurve::Create());
+
+ TransformOperations operations1;
+ curve1->AddKeyframe(TransformKeyframe::Create(
+ 0.0, operations1, scoped_ptr<TimingFunction>()));
+ operations1.AppendTranslate(10.0, 15.0, 0.0);
+ curve1->AddKeyframe(TransformKeyframe::Create(
+ 1.0, operations1, scoped_ptr<TimingFunction>()));
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve1.PassAs<AnimationCurve>(), 2, 2, Animation::Transform));
+ controller_impl->AddAnimation(animation.Pass());
+
+ // The only transform animation we've added is a translation.
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+
+ scoped_ptr<KeyframedTransformAnimationCurve> curve2(
+ KeyframedTransformAnimationCurve::Create());
+
+ TransformOperations operations2;
+ curve2->AddKeyframe(TransformKeyframe::Create(
+ 0.0, operations2, scoped_ptr<TimingFunction>()));
+ operations2.AppendScale(2.0, 3.0, 4.0);
+ curve2->AddKeyframe(TransformKeyframe::Create(
+ 1.0, operations2, scoped_ptr<TimingFunction>()));
+
+ animation = Animation::Create(
+ curve2.PassAs<AnimationCurve>(), 3, 3, Animation::Transform);
+ controller_impl->AddAnimation(animation.Pass());
+
+ // A scale animation is not a translation.
+ EXPECT_FALSE(controller_impl->HasOnlyTranslationTransforms());
+
+ controller_impl->GetAnimation(3, Animation::Transform)
+ ->SetRunState(Animation::Finished, 0.0);
+
+ // Only unfinished animations should be considered by
+ // HasOnlyTranslationTransforms.
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+}
+
+TEST(LayerAnimationControllerTest, MaximumScale) {
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+
+ float max_scale = 0.f;
+ EXPECT_TRUE(controller_impl->MaximumScale(&max_scale));
+ EXPECT_EQ(0.f, max_scale);
+
+ scoped_ptr<KeyframedTransformAnimationCurve> curve1(
+ KeyframedTransformAnimationCurve::Create());
+
+ TransformOperations operations1;
+ curve1->AddKeyframe(TransformKeyframe::Create(
+ 0.0, operations1, scoped_ptr<TimingFunction>()));
+ operations1.AppendScale(2.0, 3.0, 4.0);
+ curve1->AddKeyframe(TransformKeyframe::Create(
+ 1.0, operations1, scoped_ptr<TimingFunction>()));
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve1.PassAs<AnimationCurve>(), 1, 1, Animation::Transform));
+ controller_impl->AddAnimation(animation.Pass());
+
+ EXPECT_TRUE(controller_impl->MaximumScale(&max_scale));
+ EXPECT_EQ(4.f, max_scale);
+
+ scoped_ptr<KeyframedTransformAnimationCurve> curve2(
+ KeyframedTransformAnimationCurve::Create());
+
+ TransformOperations operations2;
+ curve2->AddKeyframe(TransformKeyframe::Create(
+ 0.0, operations2, scoped_ptr<TimingFunction>()));
+ operations2.AppendScale(6.0, 5.0, 4.0);
+ curve2->AddKeyframe(TransformKeyframe::Create(
+ 1.0, operations2, scoped_ptr<TimingFunction>()));
+
+ animation = Animation::Create(
+ curve2.PassAs<AnimationCurve>(), 2, 2, Animation::Transform);
+ controller_impl->AddAnimation(animation.Pass());
+
+ EXPECT_TRUE(controller_impl->MaximumScale(&max_scale));
+ EXPECT_EQ(6.f, max_scale);
+
+ scoped_ptr<KeyframedTransformAnimationCurve> curve3(
+ KeyframedTransformAnimationCurve::Create());
+
+ TransformOperations operations3;
+ curve3->AddKeyframe(TransformKeyframe::Create(
+ 0.0, operations3, scoped_ptr<TimingFunction>()));
+ operations3.AppendPerspective(6.0);
+ curve3->AddKeyframe(TransformKeyframe::Create(
+ 1.0, operations3, scoped_ptr<TimingFunction>()));
+
+ animation = Animation::Create(
+ curve3.PassAs<AnimationCurve>(), 3, 3, Animation::Transform);
+ controller_impl->AddAnimation(animation.Pass());
+
+ EXPECT_FALSE(controller_impl->MaximumScale(&max_scale));
+
+ controller_impl->GetAnimation(3, Animation::Transform)
+ ->SetRunState(Animation::Finished, 0.0);
+ controller_impl->GetAnimation(2, Animation::Transform)
+ ->SetRunState(Animation::Finished, 0.0);
+
+ // Only unfinished animations should be considered by
+ // MaximumScale.
+ EXPECT_TRUE(controller_impl->MaximumScale(&max_scale));
+ EXPECT_EQ(4.f, max_scale);
+}
+
+TEST(LayerAnimationControllerTest, NewlyPushedAnimationWaitsForActivation) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy_impl;
+ FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ controller_impl->AddValueObserver(&pending_dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+ AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, false);
+ int group_id = controller->GetAnimation(Animation::Opacity)->group();
+ EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
+
+ EXPECT_FALSE(controller_impl->needs_to_start_animations_for_testing());
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(controller_impl->needs_to_start_animations_for_testing());
+
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+ EXPECT_EQ(
+ Animation::WaitingForTargetAvailability,
+ controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_active_observers());
+
+ controller_impl->Animate(kInitialTickTime);
+ EXPECT_FALSE(controller_impl->needs_to_start_animations_for_testing());
+ controller_impl->UpdateState(true, events.get());
+
+ // Since the animation hasn't been activated, it should still be Starting
+ // rather than Running.
+ EXPECT_EQ(
+ Animation::Starting,
+ controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+
+ // Since the animation hasn't been activated, only the pending observer
+ // should have been ticked.
+ EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+ EXPECT_EQ(0.f, dummy_impl.opacity());
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_active_observers());
+
+ controller_impl->Animate(kInitialTickTime + 1.0);
+ controller_impl->UpdateState(true, events.get());
+
+ // Since the animation has been activated, it should have reached the
+ // Running state and the active observer should start to get ticked.
+ EXPECT_EQ(
+ Animation::Running,
+ controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+ EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+ EXPECT_EQ(0.5f, dummy_impl.opacity());
+}
+
+TEST(LayerAnimationControllerTest, ActivationBetweenAnimateAndUpdateState) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy_impl;
+ FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ controller_impl->AddValueObserver(&pending_dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, true);
+ int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+ EXPECT_EQ(
+ Animation::WaitingForTargetAvailability,
+ controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_active_observers());
+
+ controller_impl->Animate(kInitialTickTime);
+
+ // Since the animation hasn't been activated, only the pending observer
+ // should have been ticked.
+ EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+ EXPECT_EQ(0.f, dummy_impl.opacity());
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_active_observers());
+
+ controller_impl->UpdateState(true, events.get());
+
+ // Since the animation has been activated, it should have reached the
+ // Running state.
+ EXPECT_EQ(
+ Animation::Running,
+ controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+
+ controller_impl->Animate(kInitialTickTime + 0.5);
+
+ // Both observers should have been ticked.
+ EXPECT_EQ(0.75f, pending_dummy_impl.opacity());
+ EXPECT_EQ(0.75f, dummy_impl.opacity());
+}
+
+TEST(LayerAnimationControllerTest, PushedDeletedAnimationWaitsForActivation) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy_impl;
+ FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ controller_impl->AddValueObserver(&pending_dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, true);
+ int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_EQ(
+ Animation::Running,
+ controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+ EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+ EXPECT_EQ(0.5f, dummy_impl.opacity());
+
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_active_observers());
+
+ // Delete the animation on the main-thread controller.
+ controller->RemoveAnimation(
+ controller->GetAnimation(Animation::Opacity)->id());
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+
+ // The animation should no longer affect pending observers.
+ EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+ ->affects_active_observers());
+
+ controller_impl->Animate(kInitialTickTime + 0.5);
+ controller_impl->UpdateState(true, events.get());
+
+ // Only the active observer should have been ticked.
+ EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+ EXPECT_EQ(0.75f, dummy_impl.opacity());
+
+ controller_impl->ActivateAnimations();
+
+ // Activation should cause the animation to be deleted.
+ EXPECT_FALSE(controller_impl->has_any_animation());
+}
+
+// Tests that an animation that affects only active observers won't block
+// an animation that affects only pending observers from starting.
+TEST(LayerAnimationControllerTest, StartAnimationsAffectingDifferentObservers) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy_impl;
+ FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ controller_impl->AddValueObserver(&pending_dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ AddOpacityTransitionToController(controller.get(), 1, 0.f, 1.f, true);
+ int first_animation_group_id =
+ controller->GetAnimation(Animation::Opacity)->group();
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+
+ // Remove the first animation from the main-thread controller, and add a
+ // new animation affecting the same property.
+ controller->RemoveAnimation(
+ controller->GetAnimation(Animation::Opacity)->id());
+ AddOpacityTransitionToController(controller.get(), 1, 1.f, 0.5f, true);
+ int second_animation_group_id =
+ controller->GetAnimation(Animation::Opacity)->group();
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+
+ // The original animation should only affect active observers, and the new
+ // animation should only affect pending observers.
+ EXPECT_FALSE(controller_impl->GetAnimation(first_animation_group_id,
+ Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_TRUE(controller_impl->GetAnimation(first_animation_group_id,
+ Animation::Opacity)
+ ->affects_active_observers());
+ EXPECT_TRUE(controller_impl->GetAnimation(second_animation_group_id,
+ Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_FALSE(controller_impl->GetAnimation(second_animation_group_id,
+ Animation::Opacity)
+ ->affects_active_observers());
+
+ controller_impl->Animate(kInitialTickTime + 0.5);
+ controller_impl->UpdateState(true, events.get());
+
+ // The original animation should still be running, and the new animation
+ // should be starting.
+ EXPECT_EQ(Animation::Running,
+ controller_impl->GetAnimation(first_animation_group_id,
+ Animation::Opacity)->run_state());
+ EXPECT_EQ(Animation::Starting,
+ controller_impl->GetAnimation(second_animation_group_id,
+ Animation::Opacity)->run_state());
+
+ // The active observer should have been ticked by the original animation,
+ // and the pending observer should have been ticked by the new animation.
+ EXPECT_EQ(1.f, pending_dummy_impl.opacity());
+ EXPECT_EQ(0.5f, dummy_impl.opacity());
+
+ controller_impl->ActivateAnimations();
+
+ // The original animation should have been deleted, and the new animation
+ // should now affect both observers.
+ EXPECT_FALSE(controller_impl->GetAnimation(first_animation_group_id,
+ Animation::Opacity));
+ EXPECT_TRUE(controller_impl->GetAnimation(second_animation_group_id,
+ Animation::Opacity)
+ ->affects_pending_observers());
+ EXPECT_TRUE(controller_impl->GetAnimation(second_animation_group_id,
+ Animation::Opacity)
+ ->affects_active_observers());
+
+ controller_impl->Animate(kInitialTickTime + 1.0);
+ controller_impl->UpdateState(true, events.get());
+
+ // The new animation should be running, and the active observer should have
+ // been ticked at the new animation's starting point.
+ EXPECT_EQ(Animation::Running,
+ controller_impl->GetAnimation(second_animation_group_id,
+ Animation::Opacity)->run_state());
+ EXPECT_EQ(1.f, pending_dummy_impl.opacity());
+ EXPECT_EQ(1.f, dummy_impl.opacity());
+}
+
} // namespace
} // namespace cc