test_session_state_animator.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Copyright 2014 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/wm/test_session_state_animator.h"
  5. #include <utility>
  6. #include <vector>
  7. #include "base/barrier_closure.h"
  8. #include "base/bind.h"
  9. #include "base/callback_helpers.h"
  10. namespace ash {
  11. const SessionStateAnimator::Container
  12. TestSessionStateAnimator::kAllContainers[] = {
  13. SessionStateAnimator::WALLPAPER,
  14. SessionStateAnimator::SHELF,
  15. SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
  16. SessionStateAnimator::LOCK_SCREEN_WALLPAPER,
  17. SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
  18. SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS,
  19. SessionStateAnimator::ROOT_CONTAINER};
  20. // A simple SessionStateAnimator::AnimationSequence that tracks the number of
  21. // attached sequences. The callback will be invoked if all animations complete
  22. // successfully.
  23. class TestSessionStateAnimator::AnimationSequence
  24. : public SessionStateAnimator::AnimationSequence {
  25. public:
  26. AnimationSequence(AnimationCallback callback,
  27. TestSessionStateAnimator* animator)
  28. : SessionStateAnimator::AnimationSequence(std::move(callback)),
  29. sequence_count_(0),
  30. sequence_aborted_(false),
  31. animator_(animator) {}
  32. AnimationSequence(const AnimationSequence&) = delete;
  33. AnimationSequence& operator=(const AnimationSequence&) = delete;
  34. ~AnimationSequence() override = default;
  35. virtual void SequenceAttached() { ++sequence_count_; }
  36. // Notify the sequence that is has completed.
  37. virtual void SequenceFinished(bool successfully) {
  38. DCHECK_GT(sequence_count_, 0);
  39. --sequence_count_;
  40. sequence_aborted_ |= !successfully;
  41. if (sequence_count_ == 0) {
  42. if (sequence_aborted_)
  43. OnAnimationAborted();
  44. else
  45. OnAnimationCompleted();
  46. }
  47. }
  48. // ash::SessionStateAnimator::AnimationSequence:
  49. void StartAnimation(int container_mask,
  50. AnimationType type,
  51. AnimationSpeed speed) override {
  52. animator_->StartAnimationInSequence(container_mask, type, speed, this);
  53. }
  54. private:
  55. // Tracks the number of contained animations.
  56. int sequence_count_;
  57. // True if the sequence was aborted.
  58. bool sequence_aborted_;
  59. // The TestSessionAnimator that created this. Not owned.
  60. TestSessionStateAnimator* animator_;
  61. };
  62. TestSessionStateAnimator::ActiveAnimation::ActiveAnimation(
  63. int animation_epoch,
  64. base::TimeDelta duration,
  65. SessionStateAnimator::Container container,
  66. AnimationType type,
  67. AnimationSpeed speed,
  68. base::OnceClosure success_callback,
  69. base::OnceClosure failed_callback)
  70. : animation_epoch(animation_epoch),
  71. remaining_duration(duration),
  72. container(container),
  73. type(type),
  74. speed(speed),
  75. success_callback(std::move(success_callback)),
  76. failed_callback(std::move(failed_callback)) {}
  77. TestSessionStateAnimator::ActiveAnimation::ActiveAnimation(
  78. ActiveAnimation&& other) = default;
  79. TestSessionStateAnimator::ActiveAnimation&
  80. TestSessionStateAnimator::ActiveAnimation::operator=(ActiveAnimation&& other) =
  81. default;
  82. TestSessionStateAnimator::ActiveAnimation::~ActiveAnimation() = default;
  83. TestSessionStateAnimator::TestSessionStateAnimator()
  84. : last_animation_epoch_(0), is_wallpaper_hidden_(false) {}
  85. TestSessionStateAnimator::~TestSessionStateAnimator() {
  86. CompleteAllAnimations(false);
  87. }
  88. void TestSessionStateAnimator::ResetAnimationEpoch() {
  89. CompleteAllAnimations(false);
  90. last_animation_epoch_ = 0;
  91. }
  92. void TestSessionStateAnimator::Advance(const base::TimeDelta& duration) {
  93. for (ActiveAnimationsMap::iterator container_iter =
  94. active_animations_.begin();
  95. container_iter != active_animations_.end(); ++container_iter) {
  96. AnimationList::iterator animation_iter = (*container_iter).second.begin();
  97. while (animation_iter != (*container_iter).second.end()) {
  98. ActiveAnimation& active_animation = *animation_iter;
  99. active_animation.remaining_duration -= duration;
  100. if (active_animation.remaining_duration <= base::TimeDelta()) {
  101. // Save callback and erase animation, then run the callback afterwards
  102. // to avoid running the callback twice for animations that start other
  103. // animations on their same container. This is because the second
  104. // animation will call the first's animation callback when being added
  105. // to the animations list by aborting it, as we don't support 2
  106. // animations on the same container in this object.
  107. auto success_callback = std::move(active_animation.success_callback);
  108. animation_iter = (*container_iter).second.erase(animation_iter);
  109. std::move(success_callback).Run();
  110. } else {
  111. ++animation_iter;
  112. }
  113. }
  114. }
  115. }
  116. void TestSessionStateAnimator::CompleteAnimations(int animation_epoch,
  117. bool completed_successfully) {
  118. for (ActiveAnimationsMap::iterator container_iter =
  119. active_animations_.begin();
  120. container_iter != active_animations_.end(); ++container_iter) {
  121. AnimationList::iterator animation_iter = (*container_iter).second.begin();
  122. while (animation_iter != (*container_iter).second.end()) {
  123. ActiveAnimation& active_animation = *animation_iter;
  124. if (active_animation.animation_epoch <= animation_epoch) {
  125. if (completed_successfully)
  126. std::move(active_animation.success_callback).Run();
  127. else
  128. std::move(active_animation.failed_callback).Run();
  129. animation_iter = (*container_iter).second.erase(animation_iter);
  130. } else {
  131. ++animation_iter;
  132. }
  133. }
  134. }
  135. }
  136. void TestSessionStateAnimator::CompleteAllAnimations(
  137. bool completed_successfully) {
  138. CompleteAnimations(last_animation_epoch_, completed_successfully);
  139. }
  140. bool TestSessionStateAnimator::IsContainerAnimated(
  141. SessionStateAnimator::Container container,
  142. SessionStateAnimator::AnimationType type) const {
  143. ActiveAnimationsMap::const_iterator container_iter =
  144. active_animations_.find(container);
  145. if (container_iter != active_animations_.end()) {
  146. for (AnimationList::const_iterator animation_iter =
  147. (*container_iter).second.begin();
  148. animation_iter != (*container_iter).second.end(); ++animation_iter) {
  149. const ActiveAnimation& active_animation = *animation_iter;
  150. if (active_animation.type == type)
  151. return true;
  152. }
  153. }
  154. return false;
  155. }
  156. bool TestSessionStateAnimator::AreContainersAnimated(
  157. int container_mask,
  158. SessionStateAnimator::AnimationType type) const {
  159. for (size_t i = 0; i < std::size(kAllContainers); ++i) {
  160. if (container_mask & kAllContainers[i] &&
  161. !IsContainerAnimated(kAllContainers[i], type)) {
  162. return false;
  163. }
  164. }
  165. return true;
  166. }
  167. size_t TestSessionStateAnimator::GetAnimationCount() const {
  168. size_t count = 0;
  169. for (ActiveAnimationsMap::const_iterator container_iter =
  170. active_animations_.begin();
  171. container_iter != active_animations_.end(); ++container_iter) {
  172. count += (*container_iter).second.size();
  173. }
  174. return count;
  175. }
  176. void TestSessionStateAnimator::StartAnimation(int container_mask,
  177. AnimationType type,
  178. AnimationSpeed speed) {
  179. ++last_animation_epoch_;
  180. for (size_t i = 0; i < std::size(kAllContainers); ++i) {
  181. if (container_mask & kAllContainers[i]) {
  182. AddAnimation(kAllContainers[i], type, speed, base::DoNothing(),
  183. base::DoNothing());
  184. }
  185. }
  186. }
  187. void TestSessionStateAnimator::StartAnimationWithCallback(
  188. int container_mask,
  189. AnimationType type,
  190. AnimationSpeed speed,
  191. base::OnceClosure callback) {
  192. ++last_animation_epoch_;
  193. int container_count = 0;
  194. for (size_t i = 0; i < std::size(kAllContainers); ++i) {
  195. if (container_mask & kAllContainers[i])
  196. ++container_count;
  197. }
  198. base::RepeatingClosure completion_callback =
  199. base::BarrierClosure(container_count, std::move(callback));
  200. for (size_t i = 0; i < std::size(kAllContainers); ++i) {
  201. if (container_mask & kAllContainers[i]) {
  202. // ash::SessionStateAnimatorImpl invokes the callback whether or not the
  203. // animation was completed successfully or not.
  204. AddAnimation(kAllContainers[i], type, speed, completion_callback,
  205. completion_callback);
  206. }
  207. }
  208. }
  209. SessionStateAnimator::AnimationSequence*
  210. TestSessionStateAnimator::BeginAnimationSequence(AnimationCallback callback) {
  211. return new AnimationSequence(std::move(callback), this);
  212. }
  213. bool TestSessionStateAnimator::IsWallpaperHidden() const {
  214. return is_wallpaper_hidden_;
  215. }
  216. void TestSessionStateAnimator::ShowWallpaper() {
  217. is_wallpaper_hidden_ = false;
  218. }
  219. void TestSessionStateAnimator::HideWallpaper() {
  220. is_wallpaper_hidden_ = true;
  221. }
  222. void TestSessionStateAnimator::AbortAnimations(int container_mask) {
  223. for (size_t i = 0; i < std::size(kAllContainers); ++i) {
  224. if (container_mask & kAllContainers[i])
  225. AbortAnimation(kAllContainers[i]);
  226. }
  227. }
  228. void TestSessionStateAnimator::StartAnimationInSequence(
  229. int container_mask,
  230. AnimationType type,
  231. AnimationSpeed speed,
  232. AnimationSequence* animation_sequence) {
  233. ++last_animation_epoch_;
  234. for (size_t i = 0; i < std::size(kAllContainers); ++i) {
  235. if (container_mask & kAllContainers[i]) {
  236. base::OnceClosure success_callback =
  237. base::BindOnce(&AnimationSequence::SequenceFinished,
  238. base::Unretained(animation_sequence), true);
  239. base::OnceClosure failed_callback =
  240. base::BindOnce(&AnimationSequence::SequenceFinished,
  241. base::Unretained(animation_sequence), false);
  242. animation_sequence->SequenceAttached();
  243. AddAnimation(kAllContainers[i], type, speed, std::move(success_callback),
  244. std::move(failed_callback));
  245. }
  246. }
  247. }
  248. void TestSessionStateAnimator::AddAnimation(
  249. SessionStateAnimator::Container container,
  250. AnimationType type,
  251. AnimationSpeed speed,
  252. base::OnceClosure success_callback,
  253. base::OnceClosure failed_callback) {
  254. base::TimeDelta duration = GetDuration(speed);
  255. ActiveAnimation active_animation(last_animation_epoch_, duration, container,
  256. type, speed, std::move(success_callback),
  257. std::move(failed_callback));
  258. // This test double is limited to only have one animation active for a given
  259. // container at a time.
  260. AbortAnimation(container);
  261. active_animations_[container].push_back(std::move(active_animation));
  262. }
  263. void TestSessionStateAnimator::AbortAnimation(
  264. SessionStateAnimator::Container container) {
  265. ActiveAnimationsMap::iterator container_iter =
  266. active_animations_.find(container);
  267. if (container_iter != active_animations_.end()) {
  268. AnimationList::iterator animation_iter = (*container_iter).second.begin();
  269. while (animation_iter != (*container_iter).second.end()) {
  270. ActiveAnimation& active_animation = *animation_iter;
  271. std::move(active_animation.failed_callback).Run();
  272. animation_iter = (*container_iter).second.erase(animation_iter);
  273. }
  274. }
  275. }
  276. } // namespace ash