// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/compositor/layer_animator.h" #include <memory> #include <string> #include <vector> #include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" #include "base/numerics/safe_conversions.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/test/scoped_mock_clock_override.h" #include "base/test/task_environment.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/mutator_host.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_delegate.h" #include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/layer_animator_collection.h" #include "ui/compositor/layer_owner.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/test/layer_animator_test_controller.h" #include "ui/compositor/test/test_compositor_host.h" #include "ui/compositor/test/test_context_factories.h" #include "ui/compositor/test/test_layer_animation_delegate.h" #include "ui/compositor/test/test_layer_animation_observer.h" #include "ui/compositor/test/test_utils.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/transform.h" namespace ui { namespace { // Converts |color| to a string. Each component of the color is separated by a // space and the order if A R G B. std::string ColorToString(SkColor color) { … } // Creates vector with two LayerAnimationSequences, based on |first| and // |second| layer animation elements. std::vector<LayerAnimationSequence*> CreateMultiSequence( std::unique_ptr<LayerAnimationElement> first, std::unique_ptr<LayerAnimationElement> second) { … } // Creates a default animator with timers disabled for test. |delegate| and // |observer| are attached if non-null. scoped_refptr<LayerAnimator> CreateDefaultTestAnimator( LayerAnimationDelegate* delegate, LayerAnimationObserver* observer) { … } // Creates a default animator with timers disabled for test. |delegate| is // attached if non-null. scoped_refptr<LayerAnimator> CreateDefaultTestAnimator( LayerAnimationDelegate* delegate) { … } // Creates a default animator with timers disabled for test. scoped_refptr<LayerAnimator> CreateDefaultTestAnimator() { … } // Creates an implicit animator with timers disabled for test. |delegate| and // |observer| are attached if non-null. scoped_refptr<LayerAnimator> CreateImplicitTestAnimator( LayerAnimationDelegate* delegate, LayerAnimationObserver* observer) { … } // Creates an implicit animator with timers disabled for test. |delegate| is // attached if non-null. scoped_refptr<LayerAnimator> CreateImplicitTestAnimator( LayerAnimationDelegate* delegate) { … } // Creates an implicit animator with timers disabled for test. scoped_refptr<LayerAnimator> CreateImplicitTestAnimator() { … } class TestImplicitAnimationObserver : public ImplicitAnimationObserver { … }; // When notified that an animation has ended, stops all other animations. class DeletingLayerAnimationObserver : public LayerAnimationObserver { … }; // When notified that an animation has started, aborts all animations. class AbortAnimationsOnStartedLayerAnimationObserver : public LayerAnimationObserver { … }; class LayerAnimatorDestructionObserver { … }; class TestLayerAnimator : public LayerAnimator { … }; // The test layer animation sequence updates a live instances count when it is // created and destroyed. class TestLayerAnimationSequence : public LayerAnimationSequence { … }; } // namespace namespace test { // Tracks the number of calls to the LayerAnimationObserver overrides and fails // CHECKS if the counts are inconsistent, e.g. the number of started sequences // is greater than the number of attached sequences. class CountCheckingLayerAnimationObserver : public LayerAnimationObserver { … }; } // namespace test // Checks that setting a property on an implicit animator causes an animation to // happen. TEST(LayerAnimatorTest, ImplicitAnimation) { … } // Checks that if the animator is a default animator, that implicit animations // are not started. TEST(LayerAnimatorTest, NoImplicitAnimation) { … } // Checks that StopAnimatingProperty stops animation for that property, and also // skips the stopped animation to the end. TEST(LayerAnimatorTest, StopAnimatingProperty) { … } // Checks that multiple running animations for separate properties can be // stopped simultaneously and that all animations are advanced to their target // values. TEST(LayerAnimatorTest, StopAnimating) { … } // Checks that multiple running animations for separate properties can be // stopped simultaneously and that aborted animations are NOT advanced to their // target values. TEST(LayerAnimatorTest, AbortAllAnimations) { … } // Schedule a non-threaded animation that can run immediately. This is the // trivial case and should result in the animation being started immediately. TEST(LayerAnimatorTest, ScheduleAnimationThatCanRunImmediately) { … } // Schedule a threaded animation that can run immediately. TEST(LayerAnimatorTest, ScheduleThreadedAnimationThatCanRunImmediately) { … } // Schedule two non-threaded animations on separate properties. Both animations // should start immediately and should progress in lock step. TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { … } // Schedule a threaded and a non-threaded animation on separate properties. Both // animations should progress in lock step. TEST(LayerAnimatorTest, ScheduleThreadedAndNonThreadedAnimations) { … } // Schedule two animations on the same property. In this case, the two // animations should run one after another. TEST(LayerAnimatorTest, ScheduleTwoAnimationsOnSameProperty) { … } // Schedule [{g}, {g,b}, {b}] and ensure that {b} doesn't run right away. That // is, ensure that all animations targetting a particular property are run in // order. TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { … } // Schedule {g} and then schedule {g} and {b} together. In this case, since // ScheduleTogether is being used, the bounds animation should not start until // the second grayscale animation starts. TEST(LayerAnimatorTest, ScheduleTogether) { … } // Start non-threaded animation (that can run immediately). This is the trivial // case (see the trival case for ScheduleAnimation). TEST(LayerAnimatorTest, StartAnimationThatCanRunImmediately) { … } // Start threaded animation (that can run immediately). TEST(LayerAnimatorTest, StartThreadedAnimationThatCanRunImmediately) { … } // Preempt by immediately setting new target. TEST(LayerAnimatorTest, PreemptBySettingNewTarget) { … } // Preempt by animating to new target, with a non-threaded animation. TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) { … } // Preempt by animating to new target, with a threaded animation. TEST(LayerAnimatorTest, PreemptThreadedByImmediatelyAnimatingToNewTarget) { … } // Preempt by enqueuing the new animation. TEST(LayerAnimatorTest, PreemptEnqueueNewAnimation) { … } // Start an animation when there are sequences waiting in the queue. In this // case, all pending and running animations should be finished, and the new // animation started. TEST(LayerAnimatorTest, PreemptyByReplacingQueuedAnimations) { … } TEST(LayerAnimatorTest, StartTogetherSetsLastStepTime) { … } //------------------------------------------------------- // Preempt by immediately setting new target. TEST(LayerAnimatorTest, MultiPreemptBySettingNewTarget) { … } // Preempt by animating to new target. TEST(LayerAnimatorTest, MultiPreemptByImmediatelyAnimatingToNewTarget) { … } // Preempt a threaded animation by animating to new target. TEST(LayerAnimatorTest, MultiPreemptThreadedByImmediatelyAnimatingToNewTarget) { … } // Preempt by enqueuing the new animation. TEST(LayerAnimatorTest, MultiPreemptEnqueueNewAnimation) { … } // Start an animation when there are sequences waiting in the queue. In this // case, all pending and running animations should be finished, and the new // animation started. TEST(LayerAnimatorTest, MultiPreemptByReplacingQueuedAnimations) { … } //------------------------------------------------------- // Test that non-threaded cyclic sequences continue to animate. TEST(LayerAnimatorTest, CyclicSequences) { … } // Test that threaded cyclic sequences continue to animate. TEST(LayerAnimatorTest, ThreadedCyclicSequences) { … } TEST(LayerAnimatorTest, AddObserverExplicit) { … } // Tests that an observer added to a scoped settings object is still notified // when the object goes out of scope. TEST(LayerAnimatorTest, ImplicitAnimationObservers) { … } // Tests that caching render surface added to a scoped settings object is still // reset when the object goes out of scope. TEST(LayerAnimatorTest, CacheRenderSurface) { … } // Tests that caching render surface added to a scoped settings object will not // crash when the layer was destroyed. TEST(LayerAnimatorTest, CacheRenderSurfaceOnWillBeDestroyedLayer) { … } // Tests that caching render surface added to two scoped settings objects is // still reset when animation finishes. TEST(LayerAnimatorTest, CacheRenderSurfaceInTwoAnimations) { … } // Tests that deferred painting request added to a scoped settings object is // still reset when the object goes out of scope. TEST(LayerAnimatorTest, DeferredPaint) { … } // Tests that deferred painting request is added to child layers and will be // removed even the child layer was reparented. TEST(LayerAnimatorTest, DeferredPaintOnChildLayer) { … } // Tests that deffered paint request added to two scoped settings objects is // still reset when animation finishes. TEST(LayerAnimatorTest, DeferredPaintInTwoAnimations) { … } // Tests that deferred paint request added to a scoped settings object will // not crash when the layer was destroyed. TEST(LayerAnimatorTest, DeferredPaintOnWillBeDestroyedLayer) { … } // Tests that trilinear filtering request added to a scoped settings object is // still reset when the object goes out of scope. TEST(LayerAnimatorTest, TrilinearFiltering) { … } // Tests that trilinear filtering request added to a scoped settings object will // not crash when the layer was destroyed. TEST(LayerAnimatorTest, TrilinearFilteringOnWillBeDestroyedLayer) { … } // Tests that trilinear filtering request added to two scoped settings objects // is still reset when animation finishes. TEST(LayerAnimatorTest, TrilinearFilteringInTwoAnimations) { … } // Tests that an observer added to a scoped settings object is still notified // when the object goes out of scope due to the animation being interrupted. TEST(LayerAnimatorTest, InterruptedImplicitAnimationObservers) { … } // Tests that LayerAnimator is not deleted after the animation completes as long // as there is a live ScopedLayerAnimationSettings object wrapped around it. TEST(LayerAnimatorTest, AnimatorKeptAliveBySettings) { … } // Tests that an observer added to a scoped settings object is not notified // when the animator is destroyed unless explicitly requested. TEST(LayerAnimatorTest, ImplicitObserversAtAnimatorDestruction) { … } TEST(LayerAnimatorTest, AbortedAnimationStatusInImplicitObservers) { … } TEST(LayerAnimatorTest, RemoveObserverShouldRemoveFromSequences) { … } TEST(LayerAnimatorTest, ObserverReleasedBeforeAnimationSequenceEnds) { … } TEST(LayerAnimatorTest, ObserverAttachedAfterAnimationStarted) { … } TEST(LayerAnimatorTest, ObserverDetachedBeforeAnimationFinished) { … } // This checks that if an animation is deleted due to a callback, that the // animator does not try to use the deleted animation. For example, if we have // two running animations, and the first finishes and the resulting callback // causes the second to be deleted, we should not attempt to animate the second // animation. TEST(LayerAnimatorTest, ObserverDeletesAnimationsOnEnd) { … } // Ensure that stopping animation in a bounds change does not crash and that // animation gets stopped correctly. // This scenario is possible when animation is restarted from inside a // callback triggered by the animation progress. TEST(LayerAnimatorTest, CallbackDeletesAnimationInProgress) { … } // Similar to the ObserverDeletesAnimationsOnEnd test above except that it // tests the behavior when the OnLayerAnimationAborted() callback causes // all of the animator's other animations to be deleted. TEST(LayerAnimatorTest, ObserverDeletesAnimationsOnAbort) { … } // Check that setting a property during an animation with a default animator // cancels the original animation. TEST(LayerAnimatorTest, SettingPropertyDuringAnAnimation) { … } // Tests that the preemption mode IMMEDIATELY_SET_NEW_TARGET, doesn't cause the // second sequence to be leaked. TEST(LayerAnimatorTest, ImmediatelySettingNewTargetDoesNotLeak) { … } // Verifies GetTargetOpacity() works when multiple sequences are scheduled. TEST(LayerAnimatorTest, GetTargetOpacity) { … } // Verifies GetTargetBrightness() works when multiple sequences are scheduled. TEST(LayerAnimatorTest, GetTargetBrightness) { … } // Verifies GetTargetGrayscale() works when multiple sequences are scheduled. TEST(LayerAnimatorTest, GetTargetGrayscale) { … } // Verifies color property is modified appropriately. TEST(LayerAnimatorTest, Color) { … } // Verifies SchedulePauseForProperties(). TEST(LayerAnimatorTest, SchedulePauseForProperties) { … } // Verifies that IsAnimatingOnePropertyOf() returns true iff at least one of the // input properties is animated. TEST(LayerAnimatorTest, IsAnimatingOnePropertyOf) { … } class AnimatorOwner { … }; class DeletingObserver : public LayerAnimationObserver { … }; TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterFinishingAnimation) { … } TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterStoppingAnimating) { … } TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterScheduling) { … } TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterAborted) { … } TEST(LayerAnimatorTest, TestSetterRespectEnqueueStrategy) { … } class CollectionLayerAnimationDelegate : public TestLayerAnimationDelegate { … }; TEST(LayerAnimatorTest, LayerAnimatorCollectionTickTime) { … } // Verifies that sequences are removed from the animation queue prior to be // notified of being started. This will allow observers to abort animations in // the OnLayerAnimationStarted() callback without triggering a sequence to be // started a second time. TEST(LayerAnimatorTest, SequencesAreRemovedFromQueueBeforeBeingNotifiedOfStarted) { … } TEST(LayerAnimatorTest, AnimatorStartedCorrectly) { … } TEST(LayerAnimatorTest, AnimatorRemovedFromCollectionWhenLayerIsDestroyed) { … } TEST(LayerAnimatorTest, LayerMovedBetweenCompositorsDuringAnimation) { … } TEST(LayerAnimatorTest, ThreadedAnimationSurvivesIfLayerRemovedAdded) { … } class LayerOwnerAnimationObserver : public LayerAnimationObserver { … }; TEST(LayerAnimatorTest, ObserverDeletesLayerInStopAnimating) { … } TEST(LayerAnimatorTest, SetPropertyWithObserverThatDeletesLayerInStopAnimating) { … } TEST(LayerAnimatorTest, SetPropertyWithObserverThatDeletesLayerOnImplicitAnimationCompletion) { … } class CountCyclesObserver : public LayerAnimationObserver { … }; // Verifies that an observer is notified each time a LayerAnimationSequence's // cycle has ended. TEST(LayerAnimatorTest, ObserverGetsNotifiedOnCycleEnded) { … } // Verifies the LayerAnimatorObserver notification order for an animation // sequence that completes successfully. TEST(LayerAnimatorObserverNotificationOrderTest, SuccessfulCompletionOfSequence) { … } // Verifies the LayerAnimatorObserver notification order for an animation // sequence that is aborted after being scheduled. TEST(LayerAnimatorObserverNotificationOrderTest, AbortingAScheduledSequence) { … } // Verifies the LayerAnimatorObserver notification order for an animation // sequence that is queued up after another sequence that // completes successfully. TEST(LayerAnimatorObserverNotificationOrderTest, RunningASequenceThatIsQueuedForLaterStartTime) { … } // Verifies the LayerAnimatorObserver notification order for an animation // sequence that pre-empts another sequence. TEST(LayerAnimatorObserverNotificationOrderTest, RunningASequenceThatPreEmptsAnotherSequence) { … } // Verifies that an observer can be attached to a LayerAnimationSequence that // has already been scheduled. TEST(LayerAnimatorObserverNotificationOrderTest, ObserverAddedAfterAnimationStarts) { … } } // namespace ui