total_animation_throughput_reporter_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/compositor/total_animation_throughput_reporter.h"
  5. #include <memory>
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/run_loop.h"
  8. #include "base/test/bind.h"
  9. #include "base/time/time.h"
  10. #include "build/build_config.h"
  11. #include "build/chromeos_buildflags.h"
  12. #include "cc/metrics/frame_sequence_metrics.h"
  13. #include "ui/compositor/compositor_observer.h"
  14. #include "ui/compositor/layer.h"
  15. #include "ui/compositor/layer_animation_sequence.h"
  16. #include "ui/compositor/layer_animator.h"
  17. #include "ui/compositor/scoped_layer_animation_settings.h"
  18. #include "ui/compositor/test/animation_throughput_reporter_test_base.h"
  19. #include "ui/compositor/test/throughput_report_checker.h"
  20. #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
  21. defined(THREAD_SANITIZER) || defined(LEAK_SANITIZER) || \
  22. defined(UNDEFINED_SANITIZER)
  23. #define SANITIZER_ENABLED
  24. #endif
  25. namespace ui {
  26. namespace {
  27. #if !defined(SANITIZER_ENABLED)
  28. // Returns the delta from current time to the (start + duration) time.
  29. // This is used to compute how long it should wait from now to reach
  30. // the `start + duration` time.
  31. base::TimeDelta DeltaFromNowToTarget(const base::TimeTicks start,
  32. int duration) {
  33. return start + base::Milliseconds(duration) - base::TimeTicks::Now();
  34. }
  35. #endif
  36. } // namespace
  37. using TotalAnimationThroughputReporterTest =
  38. AnimationThroughputReporterTestBase;
  39. TEST_F(TotalAnimationThroughputReporterTest, SingleAnimation) {
  40. Layer layer;
  41. layer.SetOpacity(0.5f);
  42. root_layer()->Add(&layer);
  43. ThroughputReportChecker checker(this);
  44. TotalAnimationThroughputReporter reporter(compositor(),
  45. checker.repeating_callback());
  46. {
  47. LayerAnimator* animator = layer.GetAnimator();
  48. ScopedLayerAnimationSettings settings(animator);
  49. settings.SetTransitionDuration(base::Milliseconds(48));
  50. layer.SetOpacity(1.0f);
  51. }
  52. Advance(base::Milliseconds(32));
  53. EXPECT_FALSE(checker.reported());
  54. EXPECT_TRUE(checker.WaitUntilReported());
  55. }
  56. // Tests the stopping last animation will trigger the animation.
  57. TEST_F(TotalAnimationThroughputReporterTest, StopAnimation) {
  58. Layer layer;
  59. layer.SetOpacity(0.5f);
  60. root_layer()->Add(&layer);
  61. ThroughputReportChecker checker(this);
  62. TotalAnimationThroughputReporter reporter(compositor(),
  63. checker.repeating_callback());
  64. {
  65. LayerAnimator* animator = layer.GetAnimator();
  66. ScopedLayerAnimationSettings settings(animator);
  67. settings.SetTransitionDuration(base::Milliseconds(64));
  68. layer.SetOpacity(1.0f);
  69. }
  70. Advance(base::Milliseconds(32));
  71. EXPECT_FALSE(checker.reported());
  72. layer.GetAnimator()->StopAnimating();
  73. EXPECT_TRUE(checker.WaitUntilReported());
  74. }
  75. // Tests the longest animation will trigger the report.
  76. // TODO(crbug.com/1217783): Test is flaky.
  77. TEST_F(TotalAnimationThroughputReporterTest, DISABLED_MultipleAnimations) {
  78. Layer layer1;
  79. layer1.SetOpacity(0.5f);
  80. root_layer()->Add(&layer1);
  81. ThroughputReportChecker checker(this);
  82. TotalAnimationThroughputReporter reporter(compositor(),
  83. checker.repeating_callback());
  84. {
  85. LayerAnimator* animator = layer1.GetAnimator();
  86. ScopedLayerAnimationSettings settings(animator);
  87. settings.SetTransitionDuration(base::Milliseconds(48));
  88. layer1.SetOpacity(1.0f);
  89. }
  90. Layer layer2;
  91. layer2.SetOpacity(0.5f);
  92. root_layer()->Add(&layer2);
  93. {
  94. LayerAnimator* animator = layer2.GetAnimator();
  95. ScopedLayerAnimationSettings settings(animator);
  96. settings.SetTransitionDuration(base::Milliseconds(96));
  97. layer2.SetOpacity(1.0f);
  98. }
  99. #if !defined(SANITIZER_ENABLED)
  100. auto start = base::TimeTicks::Now();
  101. #endif
  102. Advance(base::Milliseconds(32));
  103. EXPECT_FALSE(checker.reported());
  104. // The following check may fail on sanitizer builds which
  105. // runs slwer.
  106. #if !defined(SANITIZER_ENABLED)
  107. auto sixty_four_ms_from_start = DeltaFromNowToTarget(start, 64);
  108. ASSERT_TRUE(sixty_four_ms_from_start.is_positive());
  109. Advance(sixty_four_ms_from_start);
  110. EXPECT_FALSE(checker.reported());
  111. #endif
  112. EXPECT_TRUE(checker.WaitUntilReported());
  113. }
  114. // Tests the longest animation on a single layer will triger the report.
  115. TEST_F(TotalAnimationThroughputReporterTest, MultipleAnimationsOnSingleLayer) {
  116. Layer layer;
  117. layer.SetOpacity(0.5f);
  118. layer.SetLayerBrightness(0.5f);
  119. root_layer()->Add(&layer);
  120. ThroughputReportChecker checker(this);
  121. TotalAnimationThroughputReporter reporter(compositor(),
  122. checker.repeating_callback());
  123. {
  124. LayerAnimator* animator = layer.GetAnimator();
  125. ScopedLayerAnimationSettings settings(animator);
  126. settings.SetTransitionDuration(base::Milliseconds(48));
  127. layer.SetOpacity(1.0f);
  128. }
  129. {
  130. LayerAnimator* animator = layer.GetAnimator();
  131. ScopedLayerAnimationSettings settings(animator);
  132. settings.SetTransitionDuration(base::Milliseconds(96));
  133. layer.SetLayerBrightness(1.0f);
  134. }
  135. Advance(base::Milliseconds(64));
  136. EXPECT_FALSE(checker.reported());
  137. EXPECT_TRUE(checker.WaitUntilReported());
  138. }
  139. // Tests adding new animation will extends the duration.
  140. // TODO(crbug.com/1216715): Test is flaky.
  141. TEST_F(TotalAnimationThroughputReporterTest,
  142. DISABLED_AddAnimationWhileAnimating) {
  143. Layer layer1;
  144. layer1.SetOpacity(0.5f);
  145. root_layer()->Add(&layer1);
  146. ThroughputReportChecker checker(this);
  147. TotalAnimationThroughputReporter reporter(compositor(),
  148. checker.repeating_callback());
  149. {
  150. LayerAnimator* animator = layer1.GetAnimator();
  151. ScopedLayerAnimationSettings settings(animator);
  152. settings.SetTransitionDuration(base::Milliseconds(48));
  153. layer1.SetOpacity(1.0f);
  154. }
  155. #if !defined(SANITIZER_ENABLED)
  156. base::TimeTicks start = base::TimeTicks::Now();
  157. #endif
  158. Advance(base::Milliseconds(32));
  159. EXPECT_FALSE(checker.reported());
  160. // Add new animation while animating.
  161. Layer layer2;
  162. layer2.SetOpacity(0.5f);
  163. root_layer()->Add(&layer2);
  164. {
  165. LayerAnimator* animator = layer2.GetAnimator();
  166. ScopedLayerAnimationSettings settings(animator);
  167. settings.SetTransitionDuration(base::Milliseconds(48));
  168. layer2.SetOpacity(1.0f);
  169. }
  170. // The following check may fail on sanitizer builds which
  171. // runs slwer.
  172. #if !defined(SANITIZER_ENABLED)
  173. // The animation time is extended by 32ms.
  174. auto sixty_four_ms_from_start = DeltaFromNowToTarget(start, 64);
  175. ASSERT_TRUE(sixty_four_ms_from_start.is_positive());
  176. Advance(sixty_four_ms_from_start);
  177. EXPECT_FALSE(checker.reported());
  178. #endif
  179. EXPECT_TRUE(checker.WaitUntilReported());
  180. }
  181. // Tests removing last animation will call report callback.
  182. TEST_F(TotalAnimationThroughputReporterTest, RemoveWhileAnimating) {
  183. auto layer1 = std::make_unique<Layer>();
  184. layer1->SetOpacity(0.5f);
  185. root_layer()->Add(layer1.get());
  186. ThroughputReportChecker checker(this);
  187. TotalAnimationThroughputReporter reporter(compositor(),
  188. checker.repeating_callback());
  189. {
  190. LayerAnimator* animator = layer1->GetAnimator();
  191. ScopedLayerAnimationSettings settings(animator);
  192. settings.SetTransitionDuration(base::Milliseconds(100));
  193. layer1->SetOpacity(1.0f);
  194. }
  195. Layer layer2;
  196. layer2.SetOpacity(0.5f);
  197. root_layer()->Add(&layer2);
  198. {
  199. LayerAnimator* animator = layer2.GetAnimator();
  200. ScopedLayerAnimationSettings settings(animator);
  201. settings.SetTransitionDuration(base::Milliseconds(48));
  202. layer2.SetOpacity(1.0f);
  203. }
  204. Advance(base::Milliseconds(48));
  205. EXPECT_FALSE(checker.reported());
  206. layer1.reset();
  207. // Aborting will be processed in next frame.
  208. EXPECT_TRUE(checker.WaitUntilReported());
  209. }
  210. // Make sure the reporter can start measuring even if the animation
  211. // has started.
  212. TEST_F(TotalAnimationThroughputReporterTest, StartWhileAnimating) {
  213. Layer layer;
  214. layer.SetOpacity(0.5f);
  215. root_layer()->Add(&layer);
  216. {
  217. LayerAnimator* animator = layer.GetAnimator();
  218. ScopedLayerAnimationSettings settings(animator);
  219. settings.SetTransitionDuration(base::Milliseconds(96));
  220. layer.SetOpacity(1.0f);
  221. }
  222. Advance(base::Milliseconds(32));
  223. ThroughputReportChecker checker(this);
  224. TotalAnimationThroughputReporter reporter(compositor(),
  225. checker.repeating_callback());
  226. EXPECT_TRUE(reporter.IsMeasuringForTesting());
  227. EXPECT_TRUE(checker.WaitUntilReported());
  228. }
  229. // Tests the reporter is called multiple times for persistent animation.
  230. TEST_F(TotalAnimationThroughputReporterTest, PersistedAnimation) {
  231. Layer layer;
  232. layer.SetOpacity(0.5f);
  233. root_layer()->Add(&layer);
  234. // Set a persisted animator to |layer|.
  235. LayerAnimator* animator = new LayerAnimator(base::Milliseconds(48));
  236. layer.SetAnimator(animator);
  237. // |reporter| keeps reporting as long as it is alive.
  238. ThroughputReportChecker checker(this);
  239. TotalAnimationThroughputReporter reporter(compositor(),
  240. checker.repeating_callback());
  241. // Report data for animation of opacity goes to 1.
  242. layer.SetOpacity(1.0f);
  243. EXPECT_TRUE(checker.WaitUntilReported());
  244. // Report data for animation of opacity goes to 0.5.
  245. checker.reset();
  246. layer.SetOpacity(0.5f);
  247. EXPECT_TRUE(checker.WaitUntilReported());
  248. }
  249. namespace {
  250. class ObserverChecker : public ui::CompositorObserver {
  251. public:
  252. ObserverChecker(ui::Compositor* compositor,
  253. ui::CompositorObserver* reporter_observer)
  254. : reporter_observer_(reporter_observer) {
  255. EXPECT_TRUE(compositor->HasObserver(reporter_observer_));
  256. compositor->AddObserver(this);
  257. }
  258. ObserverChecker(const ObserverChecker&) = delete;
  259. ObserverChecker& operator=(const ObserverChecker&) = delete;
  260. ~ObserverChecker() override = default;
  261. // ui::CompositorObserver:
  262. void OnLastAnimationEnded(ui::Compositor* compositor) override {
  263. EXPECT_FALSE(compositor->HasObserver(reporter_observer_));
  264. compositor->RemoveObserver(this);
  265. }
  266. private:
  267. const raw_ptr<ui::CompositorObserver> reporter_observer_;
  268. };
  269. } // namespace
  270. // Make sure the once reporter is called only once.
  271. TEST_F(TotalAnimationThroughputReporterTest, OnceReporter) {
  272. Layer layer;
  273. layer.SetOpacity(0.5f);
  274. root_layer()->Add(&layer);
  275. // Set a persisted animator to |layer|.
  276. LayerAnimator* animator = new LayerAnimator(base::Milliseconds(32));
  277. layer.SetAnimator(animator);
  278. ThroughputReportChecker checker(this);
  279. TotalAnimationThroughputReporter reporter(
  280. compositor(), checker.once_callback(), /*should_delete=*/false);
  281. // Make sure the TotalAnimationThroughputReporter removes itself
  282. // from compositor as observer.
  283. ObserverChecker observer_checker(compositor(), &reporter);
  284. // Report data for animation of opacity goes to 1.
  285. layer.SetOpacity(1.0f);
  286. EXPECT_TRUE(checker.WaitUntilReported());
  287. // Report data for animation of opacity goes to 0.5.
  288. checker.reset();
  289. layer.SetOpacity(1.0f);
  290. Advance(base::Milliseconds(100));
  291. EXPECT_FALSE(checker.reported());
  292. }
  293. // One reporter marked as "should_delete" should be deleted when
  294. // reported.
  295. TEST_F(TotalAnimationThroughputReporterTest, OnceReporterShouldDelete) {
  296. class DeleteTestReporter : public TotalAnimationThroughputReporter {
  297. public:
  298. DeleteTestReporter(Compositor* compositor,
  299. ReportOnceCallback callback,
  300. bool* deleted)
  301. : TotalAnimationThroughputReporter(compositor,
  302. std::move(callback),
  303. true),
  304. deleted_(deleted) {}
  305. ~DeleteTestReporter() override { *deleted_ = true; }
  306. private:
  307. raw_ptr<bool> deleted_;
  308. };
  309. Layer layer;
  310. layer.SetOpacity(0.5f);
  311. root_layer()->Add(&layer);
  312. // Set a persisted animator to |layer|.
  313. LayerAnimator* animator = new LayerAnimator(base::Milliseconds(32));
  314. layer.SetAnimator(animator);
  315. // |reporter| keeps reporting as long as it is alive.
  316. base::RunLoop run_loop;
  317. bool deleted = false;
  318. new DeleteTestReporter(
  319. compositor(),
  320. base::BindLambdaForTesting(
  321. [&](const cc::FrameSequenceMetrics::CustomReportData&) {
  322. run_loop.Quit();
  323. }),
  324. &deleted);
  325. // Report data for animation of opacity goes to 1.
  326. layer.SetOpacity(1.0f);
  327. run_loop.Run();
  328. EXPECT_TRUE(deleted);
  329. }
  330. TEST_F(TotalAnimationThroughputReporterTest, ThreadCheck) {
  331. Layer layer;
  332. layer.SetOpacity(0.5f);
  333. root_layer()->Add(&layer);
  334. // Set a persisted animator to |layer|.
  335. LayerAnimator* animator = new LayerAnimator(base::Milliseconds(32));
  336. layer.SetAnimator(animator);
  337. ui::Compositor* c = compositor();
  338. ThroughputReportChecker checker(this);
  339. auto once_callback = checker.once_callback();
  340. ThroughputReportChecker::ReportOnceCallback callback =
  341. base::BindLambdaForTesting(
  342. [&](const cc::FrameSequenceMetrics::CustomReportData& data) {
  343. // This call with fail if this is called on impl thread.
  344. c->ScheduleDraw();
  345. std::move(once_callback).Run(data);
  346. });
  347. TotalAnimationThroughputReporter reporter(c, std::move(callback),
  348. /*should_delete=*/false);
  349. // Report data for animation of opacity goes to 1.
  350. layer.SetOpacity(1.0f);
  351. EXPECT_TRUE(checker.WaitUntilReported());
  352. }
  353. } // namespace ui