123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- // Copyright 2020 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 "ui/compositor/animation_throughput_reporter.h"
- #include <memory>
- #include "base/test/bind.h"
- #include "base/time/time.h"
- #include "build/build_config.h"
- #include "cc/metrics/frame_sequence_metrics.h"
- #include "ui/compositor/layer.h"
- #include "ui/compositor/layer_animation_sequence.h"
- #include "ui/compositor/layer_animator.h"
- #include "ui/compositor/scoped_layer_animation_settings.h"
- #include "ui/compositor/test/animation_throughput_reporter_test_base.h"
- #include "ui/compositor/test/throughput_report_checker.h"
- #include "ui/gfx/geometry/rect.h"
- namespace ui {
- using AnimationThroughputReporterTest = AnimationThroughputReporterTestBase;
- // Tests animation throughput collection with implicit animation scenario.
- TEST_F(AnimationThroughputReporterTest, ImplicitAnimation) {
- Layer layer;
- layer.SetOpacity(0.5f);
- root_layer()->Add(&layer);
- ThroughputReportChecker checker(this);
- {
- LayerAnimator* animator = layer.GetAnimator();
- AnimationThroughputReporter reporter(animator,
- checker.repeating_callback());
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(48));
- layer.SetOpacity(1.0f);
- }
- // The animation starts in next frame (16ms) and ends 48 ms later.
- EXPECT_TRUE(checker.WaitUntilReported());
- }
- // Tests animation throughput collection with implicit animation setup before
- // Layer is attached to a compositor.
- TEST_F(AnimationThroughputReporterTest, ImplicitAnimationLateAttach) {
- Layer layer;
- layer.SetOpacity(0.5f);
- ThroughputReportChecker checker(this);
- {
- LayerAnimator* animator = layer.GetAnimator();
- AnimationThroughputReporter reporter(animator,
- checker.repeating_callback());
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(48));
- layer.SetOpacity(1.0f);
- }
- // Attach to root after animation setup.
- root_layer()->Add(&layer);
- EXPECT_TRUE(checker.WaitUntilReported());
- }
- // Tests animation throughput collection with explicitly created animation
- // sequence scenario.
- TEST_F(AnimationThroughputReporterTest, ExplicitAnimation) {
- Layer layer;
- layer.SetOpacity(0.5f);
- root_layer()->Add(&layer);
- ThroughputReportChecker checker(this);
- LayerAnimator* animator = layer.GetAnimator();
- AnimationThroughputReporter reporter(animator, checker.repeating_callback());
- animator->ScheduleAnimation(
- new LayerAnimationSequence(LayerAnimationElement::CreateOpacityElement(
- 1.0f, base::Milliseconds(48))));
- EXPECT_TRUE(checker.WaitUntilReported());
- }
- // Tests animation throughput collection for a persisted animator of a Layer.
- TEST_F(AnimationThroughputReporterTest, PersistedAnimation) {
- auto layer = std::make_unique<Layer>();
- layer->SetOpacity(0.5f);
- root_layer()->Add(layer.get());
- // Set a persisted animator to |layer|.
- LayerAnimator* animator = new LayerAnimator(base::Milliseconds(48));
- layer->SetAnimator(animator);
- // |reporter| keeps reporting as long as it is alive.
- ThroughputReportChecker checker(this);
- AnimationThroughputReporter reporter(animator, checker.repeating_callback());
- // Report data for animation of opacity goes to 1.
- layer->SetOpacity(1.0f);
- EXPECT_TRUE(checker.WaitUntilReported());
- // Report data for animation of opacity goes to 0.5.
- checker.reset();
- layer->SetOpacity(0.5f);
- EXPECT_TRUE(checker.WaitUntilReported());
- }
- // Tests animation throughput not reported when animation is aborted.
- TEST_F(AnimationThroughputReporterTest, AbortedAnimation) {
- auto layer = std::make_unique<Layer>();
- layer->SetOpacity(0.5f);
- root_layer()->Add(layer.get());
- ThroughputReportChecker checker(this, /*fail_if_reported=*/true);
- // Reporter started monitoring animation, then deleted, which should be
- // reported when the animation ends.
- {
- LayerAnimator* animator = layer->GetAnimator();
- AnimationThroughputReporter reporter(animator,
- checker.repeating_callback());
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(48));
- layer->SetOpacity(1.0f);
- }
- // Delete |layer| to abort on-going animations.
- layer.reset();
- // Wait a bit to ensure that report does not happen.
- Advance(base::Milliseconds(100));
- // TODO(crbug.com/1158510): Test the scenario where the report exists when the
- // layer is removed.
- }
- // Tests no report and no leak when underlying layer is gone before reporter.
- TEST_F(AnimationThroughputReporterTest, LayerDestroyedBeforeReporter) {
- auto layer = std::make_unique<Layer>();
- layer->SetOpacity(0.5f);
- root_layer()->Add(layer.get());
- ThroughputReportChecker checker(this, /*fail_if_reported=*/true);
- LayerAnimator* animator = layer->GetAnimator();
- AnimationThroughputReporter reporter(animator, checker.repeating_callback());
- {
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(48));
- layer->SetOpacity(1.0f);
- }
- // Delete |layer| to before the reporter.
- layer.reset();
- // Wait a bit to ensure that report does not happen.
- Advance(base::Milliseconds(100));
- }
- // Tests animation throughput not reported when detached from timeline.
- TEST_F(AnimationThroughputReporterTest, NoReportOnDetach) {
- auto layer = std::make_unique<Layer>();
- layer->SetOpacity(0.5f);
- root_layer()->Add(layer.get());
- ThroughputReportChecker checker(this, /*fail_if_reported=*/true);
- {
- LayerAnimator* animator = layer->GetAnimator();
- AnimationThroughputReporter reporter(animator,
- checker.repeating_callback());
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(48));
- layer->SetOpacity(1.0f);
- }
- // Detach from the root and attach to a root.
- root_layer()->Remove(layer.get());
- root_layer()->Add(layer.get());
- // Wait a bit to ensure that report does not happen.
- Advance(base::Milliseconds(100));
- }
- // Tests animation throughput not reported and no leak when animation is stopped
- // without being attached to a root.
- TEST_F(AnimationThroughputReporterTest, EndDetachedNoReportNoLeak) {
- auto layer = std::make_unique<Layer>();
- layer->SetOpacity(0.5f);
- ThroughputReportChecker checker(this, /*fail_if_reported=*/true);
- LayerAnimator* animator = layer->GetAnimator();
- // Schedule an animation without being attached to a root.
- {
- AnimationThroughputReporter reporter(animator,
- checker.repeating_callback());
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(50));
- layer->SetOpacity(1.0f);
- }
- // End the animation without being attached to a root.
- animator->StopAnimating();
- // Wait a bit to ensure that report does not happen.
- Advance(base::Milliseconds(100));
- // AnimationTracker in |reporter| should not leak in asan.
- }
- // Tests animation throughput are reported if there was a previous animation
- // preempted under IMMEDIATELY_ANIMATE_TO_NEW_TARGET strategy.
- TEST_F(AnimationThroughputReporterTest, ReportForAnimateToNewTarget) {
- auto layer = std::make_unique<Layer>();
- layer->SetOpacity(0.f);
- layer->SetBounds(gfx::Rect(0, 0, 1, 2));
- root_layer()->Add(layer.get());
- ThroughputReportChecker checker(this, /*fail_if_reported=*/true);
- LayerAnimator* animator = layer->GetAnimator();
- // Schedule an animation that will be preempted. No report should happen.
- {
- AnimationThroughputReporter reporter(animator,
- checker.repeating_callback());
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(50));
- layer->SetOpacity(0.5f);
- layer->SetBounds(gfx::Rect(0, 0, 3, 4));
- }
- // Animate to new target. Report should happen.
- ThroughputReportChecker checker2(this);
- {
- AnimationThroughputReporter reporter(animator,
- checker2.repeating_callback());
- ScopedLayerAnimationSettings settings(animator);
- settings.SetPreemptionStrategy(
- LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- settings.SetTransitionDuration(base::Milliseconds(48));
- layer->SetOpacity(1.0f);
- layer->SetBounds(gfx::Rect(0, 0, 5, 6));
- }
- EXPECT_TRUE(checker2.WaitUntilReported());
- }
- // Tests AnimationThroughputReporter does not leak its AnimationTracker when
- // there are existing animations but no new animation sequence starts after it
- // is created.
- TEST_F(AnimationThroughputReporterTest, NoLeakWithNoAnimationStart) {
- auto layer = std::make_unique<Layer>();
- layer->SetOpacity(0.5f);
- root_layer()->Add(layer.get());
- LayerAnimator* animator = layer->GetAnimator();
- // Create an existing animation.
- {
- ScopedLayerAnimationSettings settings(animator);
- settings.SetTransitionDuration(base::Milliseconds(50));
- layer->SetOpacity(0.0f);
- }
- // Create the reporter with the existing animation.
- ThroughputReportChecker checker(this, /*fail_if_reported=*/true);
- {
- AnimationThroughputReporter reporter(animator,
- checker.repeating_callback());
- }
- // Wait a bit to ensure to let the existing animation finish.
- // There should be no report and no leak.
- Advance(base::Milliseconds(100));
- }
- } // namespace ui
|