1 // Copyright 2013 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
5 #include "ash/wm/lock_state_controller.h"
6
7 #include <algorithm>
8
9 #include "ash/accessibility_delegate.h"
10 #include "ash/ash_switches.h"
11 #include "ash/cancel_mode.h"
12 #include "ash/metrics/user_metrics_recorder.h"
13 #include "ash/shell.h"
14 #include "ash/shell_delegate.h"
15 #include "ash/shell_window_ids.h"
16 #include "ash/wm/session_state_animator.h"
17 #include "base/bind_helpers.h"
18 #include "base/command_line.h"
19 #include "base/timer/timer.h"
20 #include "content/public/browser/user_metrics.h"
21 #include "ui/aura/root_window.h"
22 #include "ui/compositor/layer_animation_sequence.h"
23 #include "ui/compositor/scoped_layer_animation_settings.h"
24 #include "ui/views/corewm/compound_event_filter.h"
25
26 #if defined(OS_CHROMEOS)
27 #include "base/sys_info.h"
28 #include "media/audio/sounds/sounds_manager.h"
29 #endif
30
31 #if defined(OS_CHROMEOS)
32 using media::SoundsManager;
33 #endif
34
35 namespace ash {
36
37 namespace {
38
39 const int kMaxShutdownSoundDurationMs = 1500;
40
GetBackground()41 aura::Window* GetBackground() {
42 aura::Window* root_window = Shell::GetPrimaryRootWindow();
43 return Shell::GetContainer(root_window,
44 internal::kShellWindowId_DesktopBackgroundContainer);
45 }
46
IsBackgroundHidden()47 bool IsBackgroundHidden() {
48 return !GetBackground()->IsVisible();
49 }
50
ShowBackground()51 void ShowBackground() {
52 ui::ScopedLayerAnimationSettings settings(
53 GetBackground()->layer()->GetAnimator());
54 settings.SetTransitionDuration(base::TimeDelta());
55 GetBackground()->Show();
56 }
57
HideBackground()58 void HideBackground() {
59 ui::ScopedLayerAnimationSettings settings(
60 GetBackground()->layer()->GetAnimator());
61 settings.SetTransitionDuration(base::TimeDelta());
62 GetBackground()->Hide();
63 }
64
65 // This observer is intended to use in cases when some action has to be taken
66 // once some animation successfully completes (i.e. it was not aborted).
67 // Observer will count a number of sequences it is attached to, and a number of
68 // finished sequences (either Ended or Aborted). Once these two numbers are
69 // equal, observer will delete itself, calling callback passed to constructor if
70 // there were no aborted animations.
71 // This way it can be either used to wait for some animation to be finished in
72 // multiple layers, to wait once a sequence of animations is finished in one
73 // layer or the mixture of both.
74 class AnimationFinishedObserver : public ui::LayerAnimationObserver {
75 public:
AnimationFinishedObserver(base::Closure & callback)76 explicit AnimationFinishedObserver(base::Closure &callback)
77 : callback_(callback),
78 sequences_attached_(0),
79 sequences_completed_(0),
80 paused_(false) {
81 }
82
83 // Pauses observer: no checks will be made while paused. It can be used when
84 // a sequence has some immediate animations in the beginning, and for
85 // animations that can be tested with flag that makes all animations
86 // immediate.
Pause()87 void Pause() {
88 paused_ = true;
89 }
90
91 // Unpauses observer. It does a check and calls callback if conditions are
92 // met.
Unpause()93 void Unpause() {
94 if (!paused_)
95 return;
96 paused_ = false;
97 if (sequences_completed_ == sequences_attached_) {
98 callback_.Run();
99 delete this;
100 }
101 }
102
103 private:
~AnimationFinishedObserver()104 virtual ~AnimationFinishedObserver() {
105 }
106
107 // LayerAnimationObserver implementation
OnLayerAnimationEnded(ui::LayerAnimationSequence * sequence)108 virtual void OnLayerAnimationEnded(
109 ui::LayerAnimationSequence* sequence) OVERRIDE {
110 sequences_completed_++;
111 if ((sequences_completed_ == sequences_attached_) && !paused_) {
112 callback_.Run();
113 delete this;
114 }
115 }
116
OnLayerAnimationAborted(ui::LayerAnimationSequence * sequence)117 virtual void OnLayerAnimationAborted(
118 ui::LayerAnimationSequence* sequence) OVERRIDE {
119 sequences_completed_++;
120 if ((sequences_completed_ == sequences_attached_) && !paused_)
121 delete this;
122 }
123
OnLayerAnimationScheduled(ui::LayerAnimationSequence * sequence)124 virtual void OnLayerAnimationScheduled(
125 ui::LayerAnimationSequence* sequence) OVERRIDE {
126 }
127
OnAttachedToSequence(ui::LayerAnimationSequence * sequence)128 virtual void OnAttachedToSequence(
129 ui::LayerAnimationSequence* sequence) OVERRIDE {
130 LayerAnimationObserver::OnAttachedToSequence(sequence);
131 sequences_attached_++;
132 }
133
134 // Callback to be called.
135 base::Closure callback_;
136
137 // Number of sequences this observer was attached to.
138 int sequences_attached_;
139
140 // Number of sequences either ended or aborted.
141 int sequences_completed_;
142
143 bool paused_;
144
145 DISALLOW_COPY_AND_ASSIGN(AnimationFinishedObserver);
146 };
147
148 } // namespace
149
150 const int LockStateController::kLockTimeoutMs = 400;
151 const int LockStateController::kShutdownTimeoutMs = 400;
152 const int LockStateController::kLockFailTimeoutMs = 8000;
153 const int LockStateController::kLockToShutdownTimeoutMs = 150;
154 const int LockStateController::kShutdownRequestDelayMs = 50;
155
TestApi(LockStateController * controller)156 LockStateController::TestApi::TestApi(LockStateController* controller)
157 : controller_(controller) {
158 }
159
~TestApi()160 LockStateController::TestApi::~TestApi() {
161 }
162
LockStateController()163 LockStateController::LockStateController()
164 : animator_(new internal::SessionStateAnimator()),
165 login_status_(user::LOGGED_IN_NONE),
166 system_is_locked_(false),
167 shutting_down_(false),
168 shutdown_after_lock_(false),
169 animating_lock_(false),
170 can_cancel_lock_animation_(false) {
171 Shell::GetPrimaryRootWindow()->GetDispatcher()->AddRootWindowObserver(this);
172 }
173
~LockStateController()174 LockStateController::~LockStateController() {
175 Shell::GetPrimaryRootWindow()->GetDispatcher()->RemoveRootWindowObserver(
176 this);
177 }
178
SetDelegate(LockStateControllerDelegate * delegate)179 void LockStateController::SetDelegate(LockStateControllerDelegate* delegate) {
180 delegate_.reset(delegate);
181 }
182
AddObserver(LockStateObserver * observer)183 void LockStateController::AddObserver(LockStateObserver* observer) {
184 observers_.AddObserver(observer);
185 }
186
RemoveObserver(LockStateObserver * observer)187 void LockStateController::RemoveObserver(LockStateObserver* observer) {
188 observers_.RemoveObserver(observer);
189 }
190
HasObserver(LockStateObserver * observer)191 bool LockStateController::HasObserver(LockStateObserver* observer) {
192 return observers_.HasObserver(observer);
193 }
194
StartLockAnimation(bool shutdown_after_lock)195 void LockStateController::StartLockAnimation(
196 bool shutdown_after_lock) {
197 if (animating_lock_)
198 return;
199 shutdown_after_lock_ = shutdown_after_lock;
200 can_cancel_lock_animation_ = true;
201
202 StartCancellablePreLockAnimation();
203 }
204
StartShutdownAnimation()205 void LockStateController::StartShutdownAnimation() {
206 StartCancellableShutdownAnimation();
207 }
208
StartLockAnimationAndLockImmediately()209 void LockStateController::StartLockAnimationAndLockImmediately() {
210 if (animating_lock_)
211 return;
212 StartImmediatePreLockAnimation(true /* request_lock_on_completion */);
213 }
214
LockRequested()215 bool LockStateController::LockRequested() {
216 return lock_fail_timer_.IsRunning();
217 }
218
ShutdownRequested()219 bool LockStateController::ShutdownRequested() {
220 return shutting_down_;
221 }
222
CanCancelLockAnimation()223 bool LockStateController::CanCancelLockAnimation() {
224 return can_cancel_lock_animation_;
225 }
226
CancelLockAnimation()227 void LockStateController::CancelLockAnimation() {
228 if (!CanCancelLockAnimation())
229 return;
230 shutdown_after_lock_ = false;
231 animating_lock_ = false;
232 CancelPreLockAnimation();
233 }
234
CanCancelShutdownAnimation()235 bool LockStateController::CanCancelShutdownAnimation() {
236 return pre_shutdown_timer_.IsRunning() ||
237 shutdown_after_lock_ ||
238 lock_to_shutdown_timer_.IsRunning();
239 }
240
CancelShutdownAnimation()241 void LockStateController::CancelShutdownAnimation() {
242 if (!CanCancelShutdownAnimation())
243 return;
244 if (lock_to_shutdown_timer_.IsRunning()) {
245 lock_to_shutdown_timer_.Stop();
246 return;
247 }
248 if (shutdown_after_lock_) {
249 shutdown_after_lock_ = false;
250 return;
251 }
252
253 animator_->StartGlobalAnimation(
254 internal::SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS,
255 internal::SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN);
256 pre_shutdown_timer_.Stop();
257 }
258
OnStartingLock()259 void LockStateController::OnStartingLock() {
260 if (shutting_down_ || system_is_locked_)
261 return;
262 if (animating_lock_)
263 return;
264 StartImmediatePreLockAnimation(false /* request_lock_on_completion */);
265 }
266
RequestShutdown()267 void LockStateController::RequestShutdown() {
268 if (shutting_down_)
269 return;
270
271 shutting_down_ = true;
272
273 Shell* shell = ash::Shell::GetInstance();
274 shell->cursor_manager()->HideCursor();
275
276 animator_->StartGlobalAnimation(
277 internal::SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
278 internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
279 StartRealShutdownTimer(true);
280 }
281
OnLockScreenHide(base::Callback<void (void)> & callback)282 void LockStateController::OnLockScreenHide(
283 base::Callback<void(void)>& callback) {
284 StartUnlockAnimationBeforeUIDestroyed(callback);
285 }
286
SetLockScreenDisplayedCallback(const base::Closure & callback)287 void LockStateController::SetLockScreenDisplayedCallback(
288 const base::Closure& callback) {
289 lock_screen_displayed_callback_ = callback;
290 }
291
OnRootWindowHostCloseRequested(const aura::RootWindow *)292 void LockStateController::OnRootWindowHostCloseRequested(
293 const aura::RootWindow*) {
294 Shell::GetInstance()->delegate()->Exit();
295 }
296
OnLoginStateChanged(user::LoginStatus status)297 void LockStateController::OnLoginStateChanged(
298 user::LoginStatus status) {
299 if (status != user::LOGGED_IN_LOCKED)
300 login_status_ = status;
301 system_is_locked_ = (status == user::LOGGED_IN_LOCKED);
302 }
303
OnAppTerminating()304 void LockStateController::OnAppTerminating() {
305 // If we hear that Chrome is exiting but didn't request it ourselves, all we
306 // can really hope for is that we'll have time to clear the screen.
307 // This is also the case when the user signs off.
308 if (!shutting_down_) {
309 shutting_down_ = true;
310 Shell* shell = ash::Shell::GetInstance();
311 shell->cursor_manager()->HideCursor();
312 shell->cursor_manager()->LockCursor();
313 animator_->StartAnimation(
314 internal::SessionStateAnimator::kAllContainersMask,
315 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
316 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
317 }
318 }
319
OnLockStateChanged(bool locked)320 void LockStateController::OnLockStateChanged(bool locked) {
321 if (shutting_down_ || (system_is_locked_ == locked))
322 return;
323
324 system_is_locked_ = locked;
325
326 if (locked) {
327 StartPostLockAnimation();
328 lock_fail_timer_.Stop();
329 } else {
330 StartUnlockAnimationAfterUIDestroyed();
331 }
332 }
333
OnLockFailTimeout()334 void LockStateController::OnLockFailTimeout() {
335 DCHECK(!system_is_locked_);
336 // Undo lock animation.
337 StartUnlockAnimationAfterUIDestroyed();
338 }
339
StartLockToShutdownTimer()340 void LockStateController::StartLockToShutdownTimer() {
341 shutdown_after_lock_ = false;
342 lock_to_shutdown_timer_.Stop();
343 lock_to_shutdown_timer_.Start(
344 FROM_HERE,
345 base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs),
346 this, &LockStateController::OnLockToShutdownTimeout);
347 }
348
OnLockToShutdownTimeout()349 void LockStateController::OnLockToShutdownTimeout() {
350 DCHECK(system_is_locked_);
351 StartCancellableShutdownAnimation();
352 }
353
StartPreShutdownAnimationTimer()354 void LockStateController::StartPreShutdownAnimationTimer() {
355 pre_shutdown_timer_.Stop();
356 pre_shutdown_timer_.Start(
357 FROM_HERE,
358 animator_->
359 GetDuration(internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN),
360 this,
361 &LockStateController::OnPreShutdownAnimationTimeout);
362 }
363
OnPreShutdownAnimationTimeout()364 void LockStateController::OnPreShutdownAnimationTimeout() {
365 shutting_down_ = true;
366
367 Shell* shell = ash::Shell::GetInstance();
368 shell->cursor_manager()->HideCursor();
369
370 StartRealShutdownTimer(false);
371 }
372
StartRealShutdownTimer(bool with_animation_time)373 void LockStateController::StartRealShutdownTimer(bool with_animation_time) {
374 base::TimeDelta duration =
375 base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs);
376 if (with_animation_time) {
377 duration += animator_->GetDuration(
378 internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
379 }
380
381 #if defined(OS_CHROMEOS)
382 const AccessibilityDelegate* const delegate =
383 Shell::GetInstance()->accessibility_delegate();
384 base::TimeDelta sound_duration = delegate->PlayShutdownSound();
385 sound_duration =
386 std::min(sound_duration,
387 base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs));
388 duration = std::max(duration, sound_duration);
389 #endif
390
391 real_shutdown_timer_.Start(
392 FROM_HERE, duration, this, &LockStateController::OnRealShutdownTimeout);
393 }
394
OnRealShutdownTimeout()395 void LockStateController::OnRealShutdownTimeout() {
396 DCHECK(shutting_down_);
397 #if defined(OS_CHROMEOS)
398 if (!base::SysInfo::IsRunningOnChromeOS()) {
399 ShellDelegate* delegate = Shell::GetInstance()->delegate();
400 if (delegate) {
401 delegate->Exit();
402 return;
403 }
404 }
405 #endif
406 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
407 UMA_ACCEL_SHUT_DOWN_POWER_BUTTON);
408 delegate_->RequestShutdown();
409 }
410
StartCancellableShutdownAnimation()411 void LockStateController::StartCancellableShutdownAnimation() {
412 Shell* shell = ash::Shell::GetInstance();
413 // Hide cursor, but let it reappear if the mouse moves.
414 shell->cursor_manager()->HideCursor();
415
416 animator_->StartGlobalAnimation(
417 internal::SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
418 internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
419 StartPreShutdownAnimationTimer();
420 }
421
StartImmediatePreLockAnimation(bool request_lock_on_completion)422 void LockStateController::StartImmediatePreLockAnimation(
423 bool request_lock_on_completion) {
424 animating_lock_ = true;
425
426 StoreUnlockedProperties();
427
428 base::Closure next_animation_starter =
429 base::Bind(&LockStateController::PreLockAnimationFinished,
430 base::Unretained(this), request_lock_on_completion);
431 AnimationFinishedObserver* observer =
432 new AnimationFinishedObserver(next_animation_starter);
433
434 observer->Pause();
435
436 animator_->StartAnimationWithObserver(
437 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
438 internal::SessionStateAnimator::ANIMATION_LIFT,
439 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
440 observer);
441 animator_->StartAnimationWithObserver(
442 internal::SessionStateAnimator::LAUNCHER,
443 internal::SessionStateAnimator::ANIMATION_FADE_OUT,
444 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
445 observer);
446 // Hide the screen locker containers so we can raise them later.
447 animator_->StartAnimation(
448 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
449 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
450 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
451 AnimateBackgroundAppearanceIfNecessary(
452 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
453 observer);
454
455 observer->Unpause();
456
457 DispatchCancelMode();
458 FOR_EACH_OBSERVER(LockStateObserver, observers_,
459 OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED));
460 }
461
StartCancellablePreLockAnimation()462 void LockStateController::StartCancellablePreLockAnimation() {
463 animating_lock_ = true;
464 StoreUnlockedProperties();
465
466 base::Closure next_animation_starter =
467 base::Bind(&LockStateController::PreLockAnimationFinished,
468 base::Unretained(this), true /* request_lock */);
469 AnimationFinishedObserver* observer =
470 new AnimationFinishedObserver(next_animation_starter);
471
472 observer->Pause();
473
474 animator_->StartAnimationWithObserver(
475 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
476 internal::SessionStateAnimator::ANIMATION_LIFT,
477 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
478 observer);
479 animator_->StartAnimationWithObserver(
480 internal::SessionStateAnimator::LAUNCHER,
481 internal::SessionStateAnimator::ANIMATION_FADE_OUT,
482 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
483 observer);
484 // Hide the screen locker containers so we can raise them later.
485 animator_->StartAnimation(
486 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
487 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
488 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
489 AnimateBackgroundAppearanceIfNecessary(
490 internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE,
491 observer);
492
493 DispatchCancelMode();
494 FOR_EACH_OBSERVER(LockStateObserver, observers_,
495 OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED));
496 observer->Unpause();
497 }
498
CancelPreLockAnimation()499 void LockStateController::CancelPreLockAnimation() {
500 base::Closure next_animation_starter =
501 base::Bind(&LockStateController::LockAnimationCancelled,
502 base::Unretained(this));
503 AnimationFinishedObserver* observer =
504 new AnimationFinishedObserver(next_animation_starter);
505
506 observer->Pause();
507
508 animator_->StartAnimationWithObserver(
509 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
510 internal::SessionStateAnimator::ANIMATION_UNDO_LIFT,
511 internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
512 observer);
513 animator_->StartAnimationWithObserver(
514 internal::SessionStateAnimator::LAUNCHER,
515 internal::SessionStateAnimator::ANIMATION_FADE_IN,
516 internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
517 observer);
518 AnimateBackgroundHidingIfNecessary(
519 internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
520 observer);
521
522 observer->Unpause();
523 }
524
StartPostLockAnimation()525 void LockStateController::StartPostLockAnimation() {
526 base::Closure next_animation_starter =
527 base::Bind(&LockStateController::PostLockAnimationFinished,
528 base::Unretained(this));
529
530 AnimationFinishedObserver* observer =
531 new AnimationFinishedObserver(next_animation_starter);
532
533 observer->Pause();
534 animator_->StartAnimationWithObserver(
535 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
536 internal::SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN,
537 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
538 observer);
539 observer->Unpause();
540 }
541
StartUnlockAnimationBeforeUIDestroyed(base::Closure & callback)542 void LockStateController::StartUnlockAnimationBeforeUIDestroyed(
543 base::Closure& callback) {
544 animator_->StartAnimationWithCallback(
545 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
546 internal::SessionStateAnimator::ANIMATION_LIFT,
547 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
548 callback);
549 }
550
StartUnlockAnimationAfterUIDestroyed()551 void LockStateController::StartUnlockAnimationAfterUIDestroyed() {
552 base::Closure next_animation_starter =
553 base::Bind(&LockStateController::UnlockAnimationAfterUIDestroyedFinished,
554 base::Unretained(this));
555
556 AnimationFinishedObserver* observer =
557 new AnimationFinishedObserver(next_animation_starter);
558
559 observer->Pause();
560
561 animator_->StartAnimationWithObserver(
562 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
563 internal::SessionStateAnimator::ANIMATION_DROP,
564 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
565 observer);
566 animator_->StartAnimationWithObserver(
567 internal::SessionStateAnimator::LAUNCHER,
568 internal::SessionStateAnimator::ANIMATION_FADE_IN,
569 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
570 observer);
571 AnimateBackgroundHidingIfNecessary(
572 internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
573 observer);
574 observer->Unpause();
575 }
576
LockAnimationCancelled()577 void LockStateController::LockAnimationCancelled() {
578 can_cancel_lock_animation_ = false;
579 RestoreUnlockedProperties();
580 }
581
PreLockAnimationFinished(bool request_lock)582 void LockStateController::PreLockAnimationFinished(bool request_lock) {
583 can_cancel_lock_animation_ = false;
584
585 if (request_lock) {
586 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
587 shutdown_after_lock_ ?
588 UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON :
589 UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON);
590 delegate_->RequestLockScreen();
591 }
592
593 lock_fail_timer_.Start(
594 FROM_HERE,
595 base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs),
596 this,
597 &LockStateController::OnLockFailTimeout);
598 }
599
PostLockAnimationFinished()600 void LockStateController::PostLockAnimationFinished() {
601 animating_lock_ = false;
602
603 FOR_EACH_OBSERVER(LockStateObserver, observers_,
604 OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED));
605 if (!lock_screen_displayed_callback_.is_null()) {
606 lock_screen_displayed_callback_.Run();
607 lock_screen_displayed_callback_.Reset();
608 }
609 if (shutdown_after_lock_) {
610 shutdown_after_lock_ = false;
611 StartLockToShutdownTimer();
612 }
613 }
614
UnlockAnimationAfterUIDestroyedFinished()615 void LockStateController::UnlockAnimationAfterUIDestroyedFinished() {
616 RestoreUnlockedProperties();
617 }
618
StoreUnlockedProperties()619 void LockStateController::StoreUnlockedProperties() {
620 if (!unlocked_properties_) {
621 unlocked_properties_.reset(new UnlockedStateProperties());
622 unlocked_properties_->background_is_hidden = IsBackgroundHidden();
623 }
624 if (unlocked_properties_->background_is_hidden) {
625 // Hide background so that it can be animated later.
626 animator_->StartAnimation(
627 internal::SessionStateAnimator::DESKTOP_BACKGROUND,
628 internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
629 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
630 ShowBackground();
631 }
632 }
633
RestoreUnlockedProperties()634 void LockStateController::RestoreUnlockedProperties() {
635 if (!unlocked_properties_)
636 return;
637 if (unlocked_properties_->background_is_hidden) {
638 HideBackground();
639 // Restore background visibility.
640 animator_->StartAnimation(
641 internal::SessionStateAnimator::DESKTOP_BACKGROUND,
642 internal::SessionStateAnimator::ANIMATION_FADE_IN,
643 internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
644 }
645 unlocked_properties_.reset();
646 }
647
AnimateBackgroundAppearanceIfNecessary(internal::SessionStateAnimator::AnimationSpeed speed,ui::LayerAnimationObserver * observer)648 void LockStateController::AnimateBackgroundAppearanceIfNecessary(
649 internal::SessionStateAnimator::AnimationSpeed speed,
650 ui::LayerAnimationObserver* observer) {
651 if (unlocked_properties_.get() &&
652 unlocked_properties_->background_is_hidden) {
653 animator_->StartAnimationWithObserver(
654 internal::SessionStateAnimator::DESKTOP_BACKGROUND,
655 internal::SessionStateAnimator::ANIMATION_FADE_IN,
656 speed,
657 observer);
658 }
659 }
660
AnimateBackgroundHidingIfNecessary(internal::SessionStateAnimator::AnimationSpeed speed,ui::LayerAnimationObserver * observer)661 void LockStateController::AnimateBackgroundHidingIfNecessary(
662 internal::SessionStateAnimator::AnimationSpeed speed,
663 ui::LayerAnimationObserver* observer) {
664 if (unlocked_properties_.get() &&
665 unlocked_properties_->background_is_hidden) {
666 animator_->StartAnimationWithObserver(
667 internal::SessionStateAnimator::DESKTOP_BACKGROUND,
668 internal::SessionStateAnimator::ANIMATION_FADE_OUT,
669 speed,
670 observer);
671 }
672 }
673
674 } // namespace ash
675