screen_rotation_animator_unittest.cc 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. // Copyright 2017 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 "ash/rotator/screen_rotation_animator.h"
  5. #include <memory>
  6. #include "ash/display/display_configuration_controller_test_api.h"
  7. #include "ash/display/screen_orientation_controller.h"
  8. #include "ash/display/screen_orientation_controller_test_api.h"
  9. #include "ash/display/window_tree_host_manager.h"
  10. #include "ash/rotator/screen_rotation_animator_observer.h"
  11. #include "ash/rotator/screen_rotation_animator_test_api.h"
  12. #include "ash/shell.h"
  13. #include "ash/system/overview/overview_button_tray.h"
  14. #include "ash/system/status_area_widget.h"
  15. #include "ash/system/status_area_widget_test_helper.h"
  16. #include "ash/test/ash_test_base.h"
  17. #include "ash/test/ash_test_helper.h"
  18. #include "ash/wallpaper/wallpaper_controller_impl.h"
  19. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  20. #include "base/bind.h"
  21. #include "base/command_line.h"
  22. #include "base/run_loop.h"
  23. #include "base/strings/stringprintf.h"
  24. #include "components/viz/common/frame_sinks/copy_output_request.h"
  25. #include "components/viz/common/frame_sinks/copy_output_result.h"
  26. #include "ui/compositor/layer_animator.h"
  27. #include "ui/compositor/layer_tree_owner.h"
  28. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  29. #include "ui/display/display.h"
  30. #include "ui/display/manager/display_manager.h"
  31. #include "ui/display/screen.h"
  32. #include "ui/display/test/display_manager_test_api.h"
  33. #include "ui/wm/core/window_util.h"
  34. namespace ash {
  35. namespace {
  36. display::Display::Rotation GetDisplayRotation(int64_t display_id) {
  37. return Shell::Get()
  38. ->display_manager()
  39. ->GetDisplayInfo(display_id)
  40. .GetActiveRotation();
  41. }
  42. void SetDisplayRotation(int64_t display_id,
  43. display::Display::Rotation rotation) {
  44. Shell::Get()->display_manager()->SetDisplayRotation(
  45. display_id, rotation, display::Display::RotationSource::USER);
  46. }
  47. OverviewButtonTray* GetTray() {
  48. return StatusAreaWidgetTestHelper::GetStatusAreaWidget()
  49. ->overview_button_tray();
  50. }
  51. class AnimationObserver : public ScreenRotationAnimatorObserver {
  52. public:
  53. AnimationObserver() = default;
  54. AnimationObserver(const AnimationObserver&) = delete;
  55. AnimationObserver& operator=(const AnimationObserver&) = delete;
  56. bool copy_notified() const { return copy_notified_; }
  57. bool finish_notified() const { return finish_notified_; }
  58. void OnScreenCopiedBeforeRotation() override { copy_notified_ = true; }
  59. void OnScreenRotationAnimationFinished(ScreenRotationAnimator* animator,
  60. bool canceled) override {
  61. finish_notified_ = true;
  62. }
  63. private:
  64. bool copy_notified_ = false;
  65. bool finish_notified_ = false;
  66. };
  67. class TestScreenRotationAnimator : public ScreenRotationAnimator {
  68. public:
  69. TestScreenRotationAnimator(aura::Window* root_window,
  70. const base::RepeatingClosure& before_callback,
  71. const base::RepeatingClosure& after_callback);
  72. TestScreenRotationAnimator(const TestScreenRotationAnimator&) = delete;
  73. TestScreenRotationAnimator& operator=(const TestScreenRotationAnimator&) =
  74. delete;
  75. ~TestScreenRotationAnimator() override = default;
  76. private:
  77. CopyCallback CreateAfterCopyCallbackBeforeRotation(
  78. std::unique_ptr<ScreenRotationRequest> rotation_request) override;
  79. CopyCallback CreateAfterCopyCallbackAfterRotation(
  80. std::unique_ptr<ScreenRotationRequest> rotation_request) override;
  81. void IntersectBefore(CopyCallback next_callback,
  82. std::unique_ptr<viz::CopyOutputResult> result);
  83. void IntersectAfter(CopyCallback next_callback,
  84. std::unique_ptr<viz::CopyOutputResult> result);
  85. base::RepeatingClosure intersect_before_callback_;
  86. base::RepeatingClosure intersect_after_callback_;
  87. };
  88. TestScreenRotationAnimator::TestScreenRotationAnimator(
  89. aura::Window* root_window,
  90. const base::RepeatingClosure& before_callback,
  91. const base::RepeatingClosure& after_callback)
  92. : ScreenRotationAnimator(root_window),
  93. intersect_before_callback_(before_callback),
  94. intersect_after_callback_(after_callback) {}
  95. ScreenRotationAnimator::CopyCallback
  96. TestScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
  97. std::unique_ptr<ScreenRotationRequest> rotation_request) {
  98. CopyCallback next_callback =
  99. ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
  100. std::move(rotation_request));
  101. return base::BindOnce(&TestScreenRotationAnimator::IntersectBefore,
  102. base::Unretained(this), std::move(next_callback));
  103. }
  104. ScreenRotationAnimator::CopyCallback
  105. TestScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
  106. std::unique_ptr<ScreenRotationRequest> rotation_request) {
  107. CopyCallback next_callback =
  108. ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
  109. std::move(rotation_request));
  110. return base::BindOnce(&TestScreenRotationAnimator::IntersectAfter,
  111. base::Unretained(this), std::move(next_callback));
  112. }
  113. void TestScreenRotationAnimator::IntersectBefore(
  114. CopyCallback next_callback,
  115. std::unique_ptr<viz::CopyOutputResult> result) {
  116. intersect_before_callback_.Run();
  117. std::move(next_callback).Run(std::move(result));
  118. }
  119. void TestScreenRotationAnimator::IntersectAfter(
  120. CopyCallback next_callback,
  121. std::unique_ptr<viz::CopyOutputResult> result) {
  122. intersect_after_callback_.Run();
  123. std::move(next_callback).Run(std::move(result));
  124. }
  125. } // namespace
  126. class ScreenRotationAnimatorSlowAnimationTest : public AshTestBase {
  127. public:
  128. ScreenRotationAnimatorSlowAnimationTest() = default;
  129. ScreenRotationAnimatorSlowAnimationTest(
  130. const ScreenRotationAnimatorSlowAnimationTest&) = delete;
  131. ScreenRotationAnimatorSlowAnimationTest& operator=(
  132. const ScreenRotationAnimatorSlowAnimationTest&) = delete;
  133. ~ScreenRotationAnimatorSlowAnimationTest() override = default;
  134. // AshTestBase:
  135. void SetUp() override;
  136. protected:
  137. int64_t display_id() const { return display_.id(); }
  138. ScreenRotationAnimator* animator() { return animator_.get(); }
  139. ScreenRotationAnimatorTestApi* test_api() { return test_api_.get(); }
  140. private:
  141. display::Display display_;
  142. std::unique_ptr<ScreenRotationAnimator> animator_;
  143. std::unique_ptr<ScreenRotationAnimatorTestApi> test_api_;
  144. std::unique_ptr<ui::ScopedAnimationDurationScaleMode> non_zero_duration_mode_;
  145. };
  146. void ScreenRotationAnimatorSlowAnimationTest::SetUp() {
  147. AshTestBase::SetUp();
  148. // ScreenRotionAnimator skips animation if the wallpaper isn't ready.
  149. Shell::Get()->wallpaper_controller()->set_bypass_decode_for_testing();
  150. Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting();
  151. display_ = display::Screen::GetScreen()->GetPrimaryDisplay();
  152. animator_ = std::make_unique<ScreenRotationAnimator>(
  153. Shell::GetRootWindowForDisplayId(display_.id()));
  154. test_api_ = std::make_unique<ScreenRotationAnimatorTestApi>(animator_.get());
  155. test_api()->DisableAnimationTimers();
  156. non_zero_duration_mode_ =
  157. std::make_unique<ui::ScopedAnimationDurationScaleMode>(
  158. ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
  159. }
  160. class ScreenRotationAnimatorSmoothAnimationTest
  161. : public AshTestBase,
  162. public testing::WithParamInterface<bool> {
  163. public:
  164. ScreenRotationAnimatorSmoothAnimationTest() = default;
  165. ScreenRotationAnimatorSmoothAnimationTest(
  166. const ScreenRotationAnimatorSmoothAnimationTest&) = delete;
  167. ScreenRotationAnimatorSmoothAnimationTest& operator=(
  168. const ScreenRotationAnimatorSmoothAnimationTest&) = delete;
  169. ~ScreenRotationAnimatorSmoothAnimationTest() override = default;
  170. // AshTestBase:
  171. void SetUp() override;
  172. void RemoveSecondaryDisplay(const std::string& specs);
  173. void QuitWaitForCopyCallback();
  174. protected:
  175. int64_t display_id() const { return display_.id(); }
  176. std::string GetDisplaySpec(int width, int height) const {
  177. int scale = GetParam() ? 1 : 2;
  178. return base::StringPrintf("%dx%d*%d", width * scale, height * scale, scale);
  179. }
  180. void UpdateDisplayWithParam() {
  181. auto current = display::Screen::GetScreen()->GetPrimaryDisplay();
  182. UpdateDisplay(
  183. GetDisplaySpec(current.size().width(), current.size().height()));
  184. }
  185. TestScreenRotationAnimator* animator() { return animator_.get(); }
  186. void SetScreenRotationAnimator(aura::Window* root_window,
  187. const base::RepeatingClosure& before_callback,
  188. const base::RepeatingClosure& after_callback);
  189. ScreenRotationAnimatorTestApi* test_api() { return test_api_.get(); }
  190. void WaitForCopyCallback();
  191. std::unique_ptr<base::RunLoop> run_loop_;
  192. std::unique_ptr<TestScreenRotationAnimator> animator_;
  193. private:
  194. display::Display display_;
  195. std::unique_ptr<ScreenRotationAnimatorTestApi> test_api_;
  196. std::unique_ptr<ui::ScopedAnimationDurationScaleMode> non_zero_duration_mode_;
  197. };
  198. void ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay(
  199. const std::string& specs) {
  200. UpdateDisplay(specs);
  201. QuitWaitForCopyCallback();
  202. }
  203. void ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback() {
  204. run_loop_->Quit();
  205. }
  206. void ScreenRotationAnimatorSmoothAnimationTest::SetUp() {
  207. AshTestBase::SetUp();
  208. // ScreenRotationAnimator skips animation if the wallpaper isn't ready.
  209. Shell::Get()->wallpaper_controller()->set_bypass_decode_for_testing();
  210. Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting();
  211. display_ = display::Screen::GetScreen()->GetPrimaryDisplay();
  212. run_loop_ = std::make_unique<base::RunLoop>();
  213. SetScreenRotationAnimator(Shell::GetRootWindowForDisplayId(display_.id()),
  214. run_loop_->QuitWhenIdleClosure(),
  215. run_loop_->QuitWhenIdleClosure());
  216. non_zero_duration_mode_ =
  217. std::make_unique<ui::ScopedAnimationDurationScaleMode>(
  218. ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
  219. }
  220. void ScreenRotationAnimatorSmoothAnimationTest::SetScreenRotationAnimator(
  221. aura::Window* root_window,
  222. const base::RepeatingClosure& before_callback,
  223. const base::RepeatingClosure& after_callback) {
  224. animator_ = std::make_unique<TestScreenRotationAnimator>(
  225. root_window, before_callback, after_callback);
  226. test_api_ = std::make_unique<ScreenRotationAnimatorTestApi>(animator_.get());
  227. test_api()->DisableAnimationTimers();
  228. }
  229. void ScreenRotationAnimatorSmoothAnimationTest::WaitForCopyCallback() {
  230. run_loop_ = std::make_unique<base::RunLoop>();
  231. run_loop_->Run();
  232. }
  233. TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldNotifyObserver) {
  234. SetDisplayRotation(display_id(), display::Display::ROTATE_0);
  235. AnimationObserver observer;
  236. animator()->AddObserver(&observer);
  237. EXPECT_FALSE(observer.copy_notified());
  238. EXPECT_FALSE(observer.finish_notified());
  239. animator()->Rotate(display::Display::ROTATE_90,
  240. display::Display::RotationSource::USER,
  241. DisplayConfigurationController::ANIMATION_SYNC);
  242. EXPECT_FALSE(observer.copy_notified());
  243. EXPECT_FALSE(observer.finish_notified());
  244. test_api()->CompleteAnimations();
  245. EXPECT_FALSE(observer.copy_notified());
  246. EXPECT_TRUE(observer.finish_notified());
  247. EXPECT_FALSE(test_api()->HasActiveAnimations());
  248. animator()->RemoveObserver(&observer);
  249. }
  250. TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldNotifyObserverOnce) {
  251. SetDisplayRotation(display_id(), display::Display::ROTATE_0);
  252. AnimationObserver observer;
  253. animator()->AddObserver(&observer);
  254. EXPECT_FALSE(observer.copy_notified());
  255. EXPECT_FALSE(observer.finish_notified());
  256. animator()->Rotate(display::Display::ROTATE_90,
  257. display::Display::RotationSource::USER,
  258. DisplayConfigurationController::ANIMATION_SYNC);
  259. EXPECT_FALSE(observer.copy_notified());
  260. EXPECT_FALSE(observer.finish_notified());
  261. animator()->Rotate(display::Display::ROTATE_180,
  262. display::Display::RotationSource::USER,
  263. DisplayConfigurationController::ANIMATION_SYNC);
  264. EXPECT_FALSE(observer.finish_notified());
  265. test_api()->CompleteAnimations();
  266. EXPECT_FALSE(observer.copy_notified());
  267. EXPECT_TRUE(observer.finish_notified());
  268. EXPECT_FALSE(test_api()->HasActiveAnimations());
  269. animator()->RemoveObserver(&observer);
  270. }
  271. TEST_F(ScreenRotationAnimatorSlowAnimationTest, RotatesToDifferentRotation) {
  272. SetDisplayRotation(display_id(), display::Display::ROTATE_0);
  273. animator()->Rotate(display::Display::ROTATE_90,
  274. display::Display::RotationSource::USER,
  275. DisplayConfigurationController::ANIMATION_SYNC);
  276. EXPECT_TRUE(test_api()->HasActiveAnimations());
  277. test_api()->CompleteAnimations();
  278. EXPECT_FALSE(test_api()->HasActiveAnimations());
  279. }
  280. TEST_F(ScreenRotationAnimatorSlowAnimationTest,
  281. ShouldNotRotateTheSameRotation) {
  282. SetDisplayRotation(display_id(), display::Display::ROTATE_0);
  283. animator()->Rotate(display::Display::ROTATE_0,
  284. display::Display::RotationSource::USER,
  285. DisplayConfigurationController::ANIMATION_SYNC);
  286. EXPECT_FALSE(test_api()->HasActiveAnimations());
  287. }
  288. // Simulates the situation that if there is a new rotation request during
  289. // animation, it should stop the animation immediately and add the new rotation
  290. // request to the |last_pending_request_|.
  291. TEST_F(ScreenRotationAnimatorSlowAnimationTest, RotatesDuringRotation) {
  292. SetDisplayRotation(display_id(), display::Display::ROTATE_0);
  293. animator()->Rotate(display::Display::ROTATE_90,
  294. display::Display::RotationSource::USER,
  295. DisplayConfigurationController::ANIMATION_SYNC);
  296. EXPECT_TRUE(animator()->IsRotating());
  297. EXPECT_EQ(display::Display::ROTATE_90, animator()->GetTargetRotation());
  298. animator()->Rotate(display::Display::ROTATE_180,
  299. display::Display::RotationSource::USER,
  300. DisplayConfigurationController::ANIMATION_SYNC);
  301. EXPECT_TRUE(test_api()->HasActiveAnimations());
  302. EXPECT_TRUE(animator()->IsRotating());
  303. EXPECT_EQ(display::Display::ROTATE_180, animator()->GetTargetRotation());
  304. test_api()->CompleteAnimations();
  305. EXPECT_FALSE(test_api()->HasActiveAnimations());
  306. EXPECT_FALSE(animator()->IsRotating());
  307. EXPECT_EQ(display::Display::ROTATE_180, GetDisplayRotation(display_id()));
  308. }
  309. // If there are multiple requests queued during animation, it should process the
  310. // last request and finish the rotation animation.
  311. TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldCompleteAnimations) {
  312. SetDisplayRotation(display_id(), display::Display::ROTATE_0);
  313. animator()->Rotate(display::Display::ROTATE_90,
  314. display::Display::RotationSource::USER,
  315. DisplayConfigurationController::ANIMATION_SYNC);
  316. EXPECT_TRUE(test_api()->HasActiveAnimations());
  317. animator()->Rotate(display::Display::ROTATE_180,
  318. display::Display::RotationSource::USER,
  319. DisplayConfigurationController::ANIMATION_SYNC);
  320. EXPECT_TRUE(test_api()->HasActiveAnimations());
  321. animator()->Rotate(display::Display::ROTATE_270,
  322. display::Display::RotationSource::USER,
  323. DisplayConfigurationController::ANIMATION_SYNC);
  324. EXPECT_TRUE(test_api()->HasActiveAnimations());
  325. test_api()->CompleteAnimations();
  326. EXPECT_FALSE(test_api()->HasActiveAnimations());
  327. EXPECT_EQ(display::Display::ROTATE_270, GetDisplayRotation(display_id()));
  328. }
  329. // Test that slow screen rotation animation will not interrupt hide animation.
  330. // The OverviewButton should be hidden.
  331. TEST_F(ScreenRotationAnimatorSlowAnimationTest,
  332. OverviewButtonTrayHideAnimationAlwaysCompletes) {
  333. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  334. // Long duration for hide animation, to allow it to be interrupted.
  335. ui::ScopedAnimationDurationScaleMode hide_duration(
  336. ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
  337. GetTray()->SetVisiblePreferred(false);
  338. // ScreenRotationAnimator copies the current layers, and deletes them upon
  339. // completion. Allow its animation to complete first.
  340. ui::ScopedAnimationDurationScaleMode rotate_duration(
  341. ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
  342. SetDisplayRotation(display_id(), display::Display::ROTATE_0);
  343. animator()->Rotate(display::Display::ROTATE_90,
  344. display::Display::RotationSource::USER,
  345. DisplayConfigurationController::ANIMATION_SYNC);
  346. EXPECT_FALSE(GetTray()->GetVisible());
  347. }
  348. TEST_P(ScreenRotationAnimatorSmoothAnimationTest, Observer) {
  349. UpdateDisplayWithParam();
  350. const int64_t display_id = display_manager()->GetDisplayAt(0).id();
  351. SetScreenRotationAnimator(
  352. Shell::GetRootWindowForDisplayId(display_id),
  353. base::BindRepeating(
  354. &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
  355. base::Unretained(this)),
  356. base::BindRepeating(
  357. &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
  358. base::Unretained(this)));
  359. AnimationObserver observer;
  360. animator()->AddObserver(&observer);
  361. EXPECT_FALSE(observer.copy_notified());
  362. EXPECT_FALSE(observer.finish_notified());
  363. SetDisplayRotation(display_id, display::Display::ROTATE_0);
  364. animator()->Rotate(display::Display::ROTATE_90,
  365. display::Display::RotationSource::USER,
  366. DisplayConfigurationController::ANIMATION_ASYNC);
  367. EXPECT_TRUE(animator()->IsRotating());
  368. WaitForCopyCallback();
  369. EXPECT_TRUE(observer.copy_notified());
  370. EXPECT_FALSE(observer.finish_notified());
  371. WaitForCopyCallback();
  372. EXPECT_TRUE(observer.copy_notified());
  373. EXPECT_FALSE(observer.finish_notified());
  374. test_api()->CompleteAnimations();
  375. EXPECT_FALSE(test_api()->HasActiveAnimations());
  376. EXPECT_EQ(display::Display::ROTATE_90, GetDisplayRotation(display_id));
  377. EXPECT_TRUE(observer.copy_notified());
  378. EXPECT_TRUE(observer.finish_notified());
  379. }
  380. // Test enable smooth screen rotation code path.
  381. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  382. RotatesToDifferentRotationWithCopyCallback) {
  383. UpdateDisplayWithParam();
  384. const int64_t display_id = display_manager()->GetDisplayAt(0).id();
  385. SetScreenRotationAnimator(
  386. Shell::GetRootWindowForDisplayId(display_id),
  387. run_loop_->QuitWhenIdleClosure(),
  388. base::BindRepeating(
  389. &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
  390. base::Unretained(this)));
  391. AnimationObserver observer;
  392. animator()->AddObserver(&observer);
  393. EXPECT_FALSE(observer.copy_notified());
  394. EXPECT_FALSE(observer.finish_notified());
  395. SetDisplayRotation(display_id, display::Display::ROTATE_0);
  396. animator()->Rotate(display::Display::ROTATE_90,
  397. display::Display::RotationSource::USER,
  398. DisplayConfigurationController::ANIMATION_ASYNC);
  399. EXPECT_TRUE(animator()->IsRotating());
  400. EXPECT_EQ(display::Display::ROTATE_90, animator()->GetTargetRotation());
  401. EXPECT_NE(display::Display::ROTATE_90, GetDisplayRotation(display_id));
  402. EXPECT_FALSE(observer.copy_notified());
  403. EXPECT_FALSE(observer.finish_notified());
  404. WaitForCopyCallback();
  405. EXPECT_TRUE(test_api()->HasActiveAnimations());
  406. EXPECT_TRUE(observer.copy_notified());
  407. EXPECT_FALSE(observer.finish_notified());
  408. EXPECT_EQ(display::Display::ROTATE_90, animator()->GetTargetRotation());
  409. // Once copy is made, the rotation is set to the target, with the
  410. // image that was rotated to the original orientation.
  411. EXPECT_EQ(display::Display::ROTATE_90, GetDisplayRotation(display_id));
  412. test_api()->CompleteAnimations();
  413. EXPECT_FALSE(test_api()->HasActiveAnimations());
  414. EXPECT_EQ(display::Display::ROTATE_90, GetDisplayRotation(display_id));
  415. EXPECT_TRUE(observer.copy_notified());
  416. EXPECT_TRUE(observer.finish_notified());
  417. }
  418. // If the rotating external secondary display is removed before the first copy
  419. // request callback called, it should stop rotating.
  420. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  421. RemoveExternalSecondaryDisplayBeforeFirstCopyCallback) {
  422. UpdateDisplay("640x480," + GetDisplaySpec(800, 600));
  423. EXPECT_EQ(2U, display_manager()->GetNumDisplays());
  424. const int64_t primary_display_id = display_manager()->GetDisplayAt(0).id();
  425. const int64_t secondary_display_id = display_manager()->GetDisplayAt(1).id();
  426. SetScreenRotationAnimator(
  427. Shell::GetRootWindowForDisplayId(secondary_display_id),
  428. base::BindRepeating(
  429. &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
  430. base::Unretained(this), "640x480"),
  431. run_loop_->QuitWhenIdleClosure());
  432. SetDisplayRotation(secondary_display_id, display::Display::ROTATE_0);
  433. animator()->Rotate(display::Display::ROTATE_90,
  434. display::Display::RotationSource::USER,
  435. DisplayConfigurationController::ANIMATION_ASYNC);
  436. WaitForCopyCallback();
  437. EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  438. EXPECT_EQ(primary_display_id, display_manager()->GetDisplayAt(0).id());
  439. }
  440. // If the rotating external primary display is removed before the first copy
  441. // request callback called, it should stop rotating.
  442. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  443. RemoveExternalPrimaryDisplayBeforeFirstCopyCallback) {
  444. UpdateDisplay(GetDisplaySpec(640, 480) + ",800x600");
  445. EXPECT_EQ(2U, display_manager()->GetNumDisplays());
  446. Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
  447. display_manager()->GetDisplayAt(1).id());
  448. const int64_t primary_display_id = display_manager()->GetDisplayAt(1).id();
  449. const int64_t secondary_display_id = display_manager()->GetDisplayAt(0).id();
  450. SetScreenRotationAnimator(
  451. Shell::GetRootWindowForDisplayId(primary_display_id),
  452. base::BindRepeating(
  453. &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
  454. base::Unretained(this), "640x480"),
  455. run_loop_->QuitWhenIdleClosure());
  456. SetDisplayRotation(primary_display_id, display::Display::ROTATE_0);
  457. animator()->Rotate(display::Display::ROTATE_90,
  458. display::Display::RotationSource::USER,
  459. DisplayConfigurationController::ANIMATION_ASYNC);
  460. WaitForCopyCallback();
  461. EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  462. EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
  463. }
  464. // If the rotating external secondary display is removed before the second copy
  465. // request callback called, it should stop rotating.
  466. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  467. RemoveExternalSecondaryDisplayBeforeSecondCopyCallback) {
  468. {
  469. // Disable wallpaper animation on a secondary display.
  470. ui::ScopedAnimationDurationScaleMode disable(
  471. ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
  472. UpdateDisplay("640x480," + GetDisplaySpec(800, 600));
  473. }
  474. EXPECT_EQ(2U, display_manager()->GetNumDisplays());
  475. const int64_t primary_display_id = display_manager()->GetDisplayAt(0).id();
  476. const int64_t secondary_display_id = display_manager()->GetDisplayAt(1).id();
  477. SetScreenRotationAnimator(
  478. Shell::GetRootWindowForDisplayId(secondary_display_id),
  479. run_loop_->QuitWhenIdleClosure(),
  480. base::BindRepeating(
  481. &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
  482. base::Unretained(this), "640x480"));
  483. SetDisplayRotation(secondary_display_id, display::Display::ROTATE_0);
  484. animator()->Rotate(display::Display::ROTATE_90,
  485. display::Display::RotationSource::USER,
  486. DisplayConfigurationController::ANIMATION_ASYNC);
  487. WaitForCopyCallback();
  488. EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  489. EXPECT_EQ(primary_display_id, display_manager()->GetDisplayAt(0).id());
  490. }
  491. // If the rotating external primary display is removed before the second copy
  492. // request callback called, it should stop rotating.
  493. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  494. RemoveExternalPrimaryDisplayBeforeSecondCopyCallback) {
  495. UpdateDisplay("640x480," + GetDisplaySpec(800, 600));
  496. EXPECT_EQ(2U, display_manager()->GetNumDisplays());
  497. Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
  498. display_manager()->GetDisplayAt(1).id());
  499. const int64_t primary_display_id = display_manager()->GetDisplayAt(1).id();
  500. const int64_t secondary_display_id = display_manager()->GetDisplayAt(0).id();
  501. SetScreenRotationAnimator(
  502. Shell::GetRootWindowForDisplayId(primary_display_id),
  503. run_loop_->QuitWhenIdleClosure(),
  504. base::BindRepeating(
  505. &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
  506. base::Unretained(this), "640x480"));
  507. SetDisplayRotation(primary_display_id, display::Display::ROTATE_0);
  508. animator()->Rotate(display::Display::ROTATE_90,
  509. display::Display::RotationSource::USER,
  510. DisplayConfigurationController::ANIMATION_ASYNC);
  511. WaitForCopyCallback();
  512. EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  513. EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
  514. }
  515. // If the external primary display is removed while rotating the secondary
  516. // display. It should stop rotating the secondary display because the
  517. // |root_window| changed.
  518. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  519. RemoveExternalPrimaryDisplayDuringAnimationChangedRootWindow) {
  520. UpdateDisplay("640x480," + GetDisplaySpec(800, 600));
  521. EXPECT_EQ(2U, display_manager()->GetNumDisplays());
  522. Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
  523. display_manager()->GetDisplayAt(1).id());
  524. const int64_t secondary_display_id = display_manager()->GetDisplayAt(0).id();
  525. SetScreenRotationAnimator(
  526. Shell::GetRootWindowForDisplayId(secondary_display_id),
  527. base::BindRepeating(
  528. &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
  529. base::Unretained(this), "640x480"),
  530. run_loop_->QuitWhenIdleClosure());
  531. SetDisplayRotation(secondary_display_id, display::Display::ROTATE_0);
  532. animator()->Rotate(display::Display::ROTATE_90,
  533. display::Display::RotationSource::USER,
  534. DisplayConfigurationController::ANIMATION_ASYNC);
  535. WaitForCopyCallback();
  536. EXPECT_EQ(1U, display_manager()->GetNumDisplays());
  537. EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
  538. EXPECT_EQ(display::Display::ROTATE_0,
  539. GetDisplayRotation(secondary_display_id));
  540. }
  541. // Test that smooth screen rotation animation will not interrupt hide animation.
  542. // The OverviewButton should be hidden.
  543. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  544. OverviewButtonTrayHideAnimationAlwaysCompletes) {
  545. UpdateDisplayWithParam();
  546. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  547. // Long duration for hide animation, to allow it to be interrupted.
  548. ui::ScopedAnimationDurationScaleMode hide_duration(
  549. ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
  550. GetTray()->SetVisiblePreferred(false);
  551. // Allow ScreenRotationAnimator animation to complete first.
  552. ui::ScopedAnimationDurationScaleMode rotate_duration(
  553. ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
  554. int64_t display_id = display_manager()->GetDisplayAt(0).id();
  555. SetScreenRotationAnimator(
  556. Shell::GetRootWindowForDisplayId(display_id),
  557. run_loop_->QuitWhenIdleClosure(),
  558. base::BindRepeating(
  559. &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
  560. base::Unretained(this)));
  561. SetDisplayRotation(display_id, display::Display::ROTATE_0);
  562. animator()->Rotate(display::Display::ROTATE_90,
  563. display::Display::RotationSource::USER,
  564. DisplayConfigurationController::ANIMATION_ASYNC);
  565. WaitForCopyCallback();
  566. GetTray()->layer()->GetAnimator()->StopAnimating();
  567. EXPECT_FALSE(GetTray()->GetVisible());
  568. }
  569. // Test that smooth screen rotation animation will work when |root_window|
  570. // recreated.
  571. TEST_P(ScreenRotationAnimatorSmoothAnimationTest,
  572. ShouldRotateAfterRecreateLayers) {
  573. UpdateDisplayWithParam();
  574. const int64_t display_id = display_manager()->GetDisplayAt(0).id();
  575. aura::Window* root_window = Shell::GetRootWindowForDisplayId(display_id);
  576. SetScreenRotationAnimator(
  577. root_window, run_loop_->QuitWhenIdleClosure(),
  578. base::BindRepeating(
  579. &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
  580. base::Unretained(this)));
  581. SetDisplayRotation(display_id, display::Display::ROTATE_0);
  582. animator()->Rotate(display::Display::ROTATE_90,
  583. display::Display::RotationSource::USER,
  584. DisplayConfigurationController::ANIMATION_ASYNC);
  585. WaitForCopyCallback();
  586. EXPECT_TRUE(test_api()->HasActiveAnimations());
  587. test_api()->CompleteAnimations();
  588. EXPECT_FALSE(test_api()->HasActiveAnimations());
  589. EXPECT_EQ(display::Display::ROTATE_90, GetDisplayRotation(display_id));
  590. // Colone and delete the old layer tree.
  591. std::unique_ptr<ui::LayerTreeOwner> old_layer_tree_owner =
  592. ::wm::RecreateLayers(root_window);
  593. old_layer_tree_owner.reset();
  594. // Should work for another rotation.
  595. animator()->Rotate(display::Display::ROTATE_180,
  596. display::Display::RotationSource::USER,
  597. DisplayConfigurationController::ANIMATION_ASYNC);
  598. WaitForCopyCallback();
  599. EXPECT_TRUE(test_api()->HasActiveAnimations());
  600. test_api()->CompleteAnimations();
  601. EXPECT_FALSE(test_api()->HasActiveAnimations());
  602. EXPECT_EQ(display::Display::ROTATE_180, GetDisplayRotation(display_id));
  603. }
  604. TEST_P(ScreenRotationAnimatorSmoothAnimationTest, DisplayChangeDuringCopy) {
  605. UpdateDisplayWithParam();
  606. const int64_t internal_display_id =
  607. display::test::DisplayManagerTestApi(display_manager())
  608. .SetFirstDisplayAsInternalDisplay();
  609. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  610. aura::Window* root_window =
  611. Shell::GetRootWindowForDisplayId(internal_display_id);
  612. SetScreenRotationAnimator(
  613. root_window,
  614. base::BindRepeating(
  615. &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
  616. base::Unretained(this)),
  617. run_loop_->QuitWhenIdleClosure());
  618. TestScreenRotationAnimator* animator = animator_.get();
  619. DisplayConfigurationControllerTestApi testapi(
  620. Shell::Get()->display_configuration_controller());
  621. testapi.SetDisplayAnimator(true);
  622. testapi.SetScreenRotationAnimatorForDisplay(internal_display_id,
  623. std::move(animator_));
  624. ScreenOrientationControllerTestApi(
  625. Shell::Get()->screen_orientation_controller())
  626. .SetDisplayRotation(display::Display::ROTATE_90,
  627. display::Display::RotationSource::ACCELEROMETER);
  628. EXPECT_TRUE(animator->IsRotating());
  629. display_manager()->UpdateDisplays();
  630. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
  631. EXPECT_FALSE(animator->IsRotating());
  632. WaitForCopyCallback();
  633. EXPECT_FALSE(animator->IsRotating());
  634. EXPECT_EQ(display::Display::ROTATE_0,
  635. GetDisplayRotation(internal_display_id));
  636. }
  637. TEST_P(ScreenRotationAnimatorSmoothAnimationTest, NewRequestShouldNotCancel) {
  638. UpdateDisplayWithParam();
  639. const int64_t display_id = display_manager()->GetDisplayAt(0).id();
  640. aura::Window* root_window = Shell::GetRootWindowForDisplayId(display_id);
  641. SetScreenRotationAnimator(
  642. root_window, run_loop_->QuitWhenIdleClosure(),
  643. base::BindRepeating(
  644. &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
  645. base::Unretained(this)));
  646. SetDisplayRotation(display_id, display::Display::ROTATE_0);
  647. animator()->Rotate(display::Display::ROTATE_90,
  648. display::Display::RotationSource::USER,
  649. DisplayConfigurationController::ANIMATION_ASYNC);
  650. EXPECT_EQ(display::Display::ROTATE_0, GetDisplayRotation(display_id));
  651. // Requesting new orientation while waiting for copy should apply the previous
  652. // change immediately.
  653. animator()->Rotate(display::Display::ROTATE_180,
  654. display::Display::RotationSource::USER,
  655. DisplayConfigurationController::ANIMATION_ASYNC);
  656. EXPECT_EQ(display::Display::ROTATE_90, GetDisplayRotation(display_id));
  657. // Requesting yet another new orientation while waiting for copy should do the
  658. // same.
  659. animator()->Rotate(display::Display::ROTATE_270,
  660. display::Display::RotationSource::USER,
  661. DisplayConfigurationController::ANIMATION_ASYNC);
  662. EXPECT_EQ(display::Display::ROTATE_180, GetDisplayRotation(display_id));
  663. WaitForCopyCallback();
  664. // The display must be rotated once copy finishes.
  665. EXPECT_EQ(display::Display::ROTATE_270, GetDisplayRotation(display_id));
  666. EXPECT_TRUE(test_api()->HasActiveAnimations());
  667. // Requesting new orientation while animating will be queued.
  668. animator()->Rotate(display::Display::ROTATE_0,
  669. display::Display::RotationSource::USER,
  670. DisplayConfigurationController::ANIMATION_ASYNC);
  671. EXPECT_EQ(display::Display::ROTATE_270, GetDisplayRotation(display_id));
  672. EXPECT_FALSE(test_api()->HasActiveAnimations());
  673. // Finish current animation will start queued animation (from 270 to 0).
  674. test_api()->CompleteAnimations();
  675. EXPECT_TRUE(animator()->IsRotating());
  676. EXPECT_EQ(display::Display::ROTATE_270, GetDisplayRotation(display_id));
  677. EXPECT_FALSE(test_api()->HasActiveAnimations());
  678. WaitForCopyCallback();
  679. EXPECT_TRUE(test_api()->HasActiveAnimations());
  680. EXPECT_EQ(display::Display::ROTATE_0, GetDisplayRotation(display_id));
  681. test_api()->CompleteAnimations();
  682. EXPECT_FALSE(test_api()->HasActiveAnimations());
  683. EXPECT_EQ(display::Display::ROTATE_0, GetDisplayRotation(display_id));
  684. }
  685. INSTANTIATE_TEST_SUITE_P(All,
  686. ScreenRotationAnimatorSmoothAnimationTest,
  687. testing::Bool());
  688. } // namespace ash