Home | History | Annotate | Download | only in wm
      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 #include <string>
      9 
     10 #include "ash/accessibility_delegate.h"
     11 #include "ash/ash_switches.h"
     12 #include "ash/cancel_mode.h"
     13 #include "ash/metrics/user_metrics_recorder.h"
     14 #include "ash/shell.h"
     15 #include "ash/shell_delegate.h"
     16 #include "ash/shell_window_ids.h"
     17 #include "ash/wm/session_state_animator.h"
     18 #include "ash/wm/session_state_animator_impl.h"
     19 #include "base/bind_helpers.h"
     20 #include "base/command_line.h"
     21 #include "base/strings/string_util.h"
     22 #include "base/timer/timer.h"
     23 #include "ui/aura/window_tree_host.h"
     24 #include "ui/views/controls/menu/menu_controller.h"
     25 #include "ui/wm/core/compound_event_filter.h"
     26 
     27 #if defined(OS_CHROMEOS)
     28 #include "base/sys_info.h"
     29 #include "media/audio/sounds/sounds_manager.h"
     30 #endif
     31 
     32 #if defined(OS_CHROMEOS)
     33 using media::SoundsManager;
     34 #endif
     35 
     36 namespace ash {
     37 
     38 namespace {
     39 
     40 #if defined(OS_CHROMEOS)
     41 const int kMaxShutdownSoundDurationMs = 1500;
     42 #endif
     43 
     44 }  // namespace
     45 
     46 const int LockStateController::kLockTimeoutMs = 400;
     47 const int LockStateController::kShutdownTimeoutMs = 400;
     48 const int LockStateController::kLockFailTimeoutMs = 8000;
     49 const int LockStateController::kLockToShutdownTimeoutMs = 150;
     50 const int LockStateController::kShutdownRequestDelayMs = 50;
     51 
     52 LockStateController::TestApi::TestApi(LockStateController* controller)
     53     : controller_(controller) {
     54 }
     55 
     56 LockStateController::TestApi::~TestApi() {
     57 }
     58 
     59 LockStateController::LockStateController()
     60     : animator_(new SessionStateAnimatorImpl()),
     61       login_status_(user::LOGGED_IN_NONE),
     62       system_is_locked_(false),
     63       shutting_down_(false),
     64       shutdown_after_lock_(false),
     65       animating_lock_(false),
     66       can_cancel_lock_animation_(false),
     67       weak_ptr_factory_(this) {
     68   Shell::GetPrimaryRootWindow()->GetHost()->AddObserver(this);
     69 }
     70 
     71 LockStateController::~LockStateController() {
     72   Shell::GetPrimaryRootWindow()->GetHost()->RemoveObserver(this);
     73 }
     74 
     75 void LockStateController::SetDelegate(
     76     scoped_ptr<LockStateControllerDelegate> delegate) {
     77   delegate_ = delegate.Pass();
     78 }
     79 
     80 void LockStateController::AddObserver(LockStateObserver* observer) {
     81   observers_.AddObserver(observer);
     82 }
     83 
     84 void LockStateController::RemoveObserver(LockStateObserver* observer) {
     85   observers_.RemoveObserver(observer);
     86 }
     87 
     88 bool LockStateController::HasObserver(LockStateObserver* observer) {
     89   return observers_.HasObserver(observer);
     90 }
     91 
     92 void LockStateController::StartLockAnimation(
     93     bool shutdown_after_lock) {
     94   if (animating_lock_)
     95     return;
     96   shutdown_after_lock_ = shutdown_after_lock;
     97   can_cancel_lock_animation_ = true;
     98 
     99   StartCancellablePreLockAnimation();
    100 }
    101 
    102 void LockStateController::StartShutdownAnimation() {
    103   StartCancellableShutdownAnimation();
    104 }
    105 
    106 void LockStateController::StartLockAnimationAndLockImmediately(
    107     bool shutdown_after_lock) {
    108   if (animating_lock_)
    109     return;
    110   shutdown_after_lock_ = shutdown_after_lock;
    111   StartImmediatePreLockAnimation(true /* request_lock_on_completion */);
    112 }
    113 
    114 bool LockStateController::LockRequested() {
    115   return lock_fail_timer_.IsRunning();
    116 }
    117 
    118 bool LockStateController::ShutdownRequested() {
    119   return shutting_down_;
    120 }
    121 
    122 bool LockStateController::CanCancelLockAnimation() {
    123   return can_cancel_lock_animation_;
    124 }
    125 
    126 void LockStateController::CancelLockAnimation() {
    127   if (!CanCancelLockAnimation())
    128     return;
    129   shutdown_after_lock_ = false;
    130   animating_lock_ = false;
    131   CancelPreLockAnimation();
    132 }
    133 
    134 bool LockStateController::CanCancelShutdownAnimation() {
    135   return pre_shutdown_timer_.IsRunning() ||
    136          shutdown_after_lock_ ||
    137          lock_to_shutdown_timer_.IsRunning();
    138 }
    139 
    140 void LockStateController::CancelShutdownAnimation() {
    141   if (!CanCancelShutdownAnimation())
    142     return;
    143   if (lock_to_shutdown_timer_.IsRunning()) {
    144     lock_to_shutdown_timer_.Stop();
    145     return;
    146   }
    147   if (shutdown_after_lock_) {
    148     shutdown_after_lock_ = false;
    149     return;
    150   }
    151 
    152   animator_->StartAnimation(
    153       SessionStateAnimator::ROOT_CONTAINER,
    154       SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS,
    155       SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN);
    156   pre_shutdown_timer_.Stop();
    157 }
    158 
    159 void LockStateController::OnStartingLock() {
    160   if (shutting_down_ || system_is_locked_)
    161     return;
    162   if (animating_lock_)
    163     return;
    164   StartImmediatePreLockAnimation(false /* request_lock_on_completion */);
    165 }
    166 
    167 void LockStateController::RequestShutdown() {
    168   if (shutting_down_)
    169     return;
    170 
    171   shutting_down_ = true;
    172 
    173   Shell* shell = ash::Shell::GetInstance();
    174   shell->cursor_manager()->HideCursor();
    175   shell->cursor_manager()->LockCursor();
    176 
    177   animator_->StartAnimation(
    178       SessionStateAnimator::ROOT_CONTAINER,
    179       SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
    180       SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
    181   StartRealShutdownTimer(true);
    182 }
    183 
    184 void LockStateController::OnLockScreenHide(
    185   base::Callback<void(void)>& callback) {
    186   StartUnlockAnimationBeforeUIDestroyed(callback);
    187 }
    188 
    189 void LockStateController::SetLockScreenDisplayedCallback(
    190     const base::Closure& callback) {
    191   lock_screen_displayed_callback_ = callback;
    192 }
    193 
    194 void LockStateController::OnHostCloseRequested(
    195     const aura::WindowTreeHost* host) {
    196   Shell::GetInstance()->delegate()->Exit();
    197 }
    198 
    199 void LockStateController::OnLoginStateChanged(
    200     user::LoginStatus status) {
    201   if (status != user::LOGGED_IN_LOCKED)
    202     login_status_ = status;
    203   system_is_locked_ = (status == user::LOGGED_IN_LOCKED);
    204 }
    205 
    206 void LockStateController::OnAppTerminating() {
    207   // If we hear that Chrome is exiting but didn't request it ourselves, all we
    208   // can really hope for is that we'll have time to clear the screen.
    209   // This is also the case when the user signs off.
    210   if (!shutting_down_) {
    211     shutting_down_ = true;
    212     Shell* shell = ash::Shell::GetInstance();
    213     shell->cursor_manager()->HideCursor();
    214     shell->cursor_manager()->LockCursor();
    215     animator_->StartAnimation(SessionStateAnimator::kAllNonRootContainersMask,
    216                               SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
    217                               SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    218   }
    219 }
    220 
    221 void LockStateController::OnLockStateChanged(bool locked) {
    222   VLOG(1) << "OnLockStateChanged " << locked;
    223   if (shutting_down_ || (system_is_locked_ == locked))
    224     return;
    225 
    226   system_is_locked_ = locked;
    227 
    228   if (locked) {
    229     StartPostLockAnimation();
    230     lock_fail_timer_.Stop();
    231   } else {
    232     StartUnlockAnimationAfterUIDestroyed();
    233   }
    234 }
    235 
    236 void LockStateController::OnLockFailTimeout() {
    237   DCHECK(!system_is_locked_);
    238   CHECK(false) << "We can not be sure about the lock state. Crash and let the "
    239                << "SessionManager end the session";
    240 }
    241 
    242 void LockStateController::StartLockToShutdownTimer() {
    243   shutdown_after_lock_ = false;
    244   lock_to_shutdown_timer_.Stop();
    245   lock_to_shutdown_timer_.Start(
    246       FROM_HERE,
    247       base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs),
    248       this, &LockStateController::OnLockToShutdownTimeout);
    249 }
    250 
    251 void LockStateController::OnLockToShutdownTimeout() {
    252   DCHECK(system_is_locked_);
    253   StartCancellableShutdownAnimation();
    254 }
    255 
    256 void LockStateController::StartPreShutdownAnimationTimer() {
    257   pre_shutdown_timer_.Stop();
    258   pre_shutdown_timer_.Start(
    259       FROM_HERE,
    260       animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN),
    261       this,
    262       &LockStateController::OnPreShutdownAnimationTimeout);
    263 }
    264 
    265 void LockStateController::OnPreShutdownAnimationTimeout() {
    266   VLOG(1) << "OnPreShutdownAnimationTimeout";
    267   shutting_down_ = true;
    268 
    269   Shell* shell = ash::Shell::GetInstance();
    270   shell->cursor_manager()->HideCursor();
    271 
    272   StartRealShutdownTimer(false);
    273 }
    274 
    275 void LockStateController::StartRealShutdownTimer(bool with_animation_time) {
    276   base::TimeDelta duration =
    277       base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs);
    278   if (with_animation_time) {
    279     duration +=
    280         animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
    281   }
    282 
    283 #if defined(OS_CHROMEOS)
    284   const AccessibilityDelegate* const delegate =
    285       Shell::GetInstance()->accessibility_delegate();
    286   base::TimeDelta sound_duration = delegate->PlayShutdownSound();
    287   sound_duration =
    288       std::min(sound_duration,
    289                base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs));
    290   duration = std::max(duration, sound_duration);
    291 #endif
    292 
    293   real_shutdown_timer_.Start(
    294       FROM_HERE, duration, this, &LockStateController::OnRealShutdownTimeout);
    295 }
    296 
    297 void LockStateController::OnRealShutdownTimeout() {
    298   VLOG(1) << "OnRealShutdownTimeout";
    299   DCHECK(shutting_down_);
    300 #if defined(OS_CHROMEOS)
    301   if (!base::SysInfo::IsRunningOnChromeOS()) {
    302     ShellDelegate* delegate = Shell::GetInstance()->delegate();
    303     if (delegate) {
    304       delegate->Exit();
    305       return;
    306     }
    307   }
    308 #endif
    309   Shell::GetInstance()->metrics()->RecordUserMetricsAction(
    310       UMA_ACCEL_SHUT_DOWN_POWER_BUTTON);
    311   delegate_->RequestShutdown();
    312 }
    313 
    314 void LockStateController::StartCancellableShutdownAnimation() {
    315   Shell* shell = ash::Shell::GetInstance();
    316   // Hide cursor, but let it reappear if the mouse moves.
    317   shell->cursor_manager()->HideCursor();
    318 
    319   animator_->StartAnimation(
    320       SessionStateAnimator::ROOT_CONTAINER,
    321       SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS,
    322       SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
    323   StartPreShutdownAnimationTimer();
    324 }
    325 
    326 void LockStateController::StartImmediatePreLockAnimation(
    327     bool request_lock_on_completion) {
    328   VLOG(1) << "StartImmediatePreLockAnimation " << request_lock_on_completion;
    329   animating_lock_ = true;
    330   StoreUnlockedProperties();
    331 
    332   base::Closure next_animation_starter =
    333       base::Bind(&LockStateController::PreLockAnimationFinished,
    334                  weak_ptr_factory_.GetWeakPtr(),
    335                  request_lock_on_completion);
    336   SessionStateAnimator::AnimationSequence* animation_sequence =
    337       animator_->BeginAnimationSequence(next_animation_starter);
    338 
    339   animation_sequence->StartAnimation(
    340       SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    341       SessionStateAnimator::ANIMATION_LIFT,
    342       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
    343   animation_sequence->StartAnimation(
    344       SessionStateAnimator::LAUNCHER,
    345       SessionStateAnimator::ANIMATION_FADE_OUT,
    346       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
    347   // Hide the screen locker containers so we can raise them later.
    348   animator_->StartAnimation(SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
    349                             SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
    350                             SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    351   AnimateBackgroundAppearanceIfNecessary(
    352       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, animation_sequence);
    353 
    354   animation_sequence->EndSequence();
    355 
    356   DispatchCancelMode();
    357   FOR_EACH_OBSERVER(LockStateObserver, observers_,
    358       OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED));
    359 }
    360 
    361 void LockStateController::StartCancellablePreLockAnimation() {
    362   animating_lock_ = true;
    363   StoreUnlockedProperties();
    364   VLOG(1) << "StartCancellablePreLockAnimation";
    365   base::Closure next_animation_starter =
    366       base::Bind(&LockStateController::PreLockAnimationFinished,
    367                  weak_ptr_factory_.GetWeakPtr(),
    368                  true /* request_lock */);
    369   SessionStateAnimator::AnimationSequence* animation_sequence =
    370       animator_->BeginAnimationSequence(next_animation_starter);
    371 
    372   animation_sequence->StartAnimation(
    373       SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    374       SessionStateAnimator::ANIMATION_LIFT,
    375       SessionStateAnimator::ANIMATION_SPEED_UNDOABLE);
    376   animation_sequence->StartAnimation(
    377       SessionStateAnimator::LAUNCHER,
    378       SessionStateAnimator::ANIMATION_FADE_OUT,
    379       SessionStateAnimator::ANIMATION_SPEED_UNDOABLE);
    380   // Hide the screen locker containers so we can raise them later.
    381   animator_->StartAnimation(SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
    382                             SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
    383                             SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    384   AnimateBackgroundAppearanceIfNecessary(
    385       SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, animation_sequence);
    386 
    387   DispatchCancelMode();
    388   FOR_EACH_OBSERVER(LockStateObserver, observers_,
    389       OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED));
    390   animation_sequence->EndSequence();
    391 }
    392 
    393 void LockStateController::CancelPreLockAnimation() {
    394   VLOG(1) << "CancelPreLockAnimation";
    395   base::Closure next_animation_starter =
    396       base::Bind(&LockStateController::LockAnimationCancelled,
    397                  weak_ptr_factory_.GetWeakPtr());
    398   SessionStateAnimator::AnimationSequence* animation_sequence =
    399       animator_->BeginAnimationSequence(next_animation_starter);
    400 
    401   animation_sequence->StartAnimation(
    402       SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    403       SessionStateAnimator::ANIMATION_UNDO_LIFT,
    404       SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS);
    405   animation_sequence->StartAnimation(
    406       SessionStateAnimator::LAUNCHER,
    407       SessionStateAnimator::ANIMATION_FADE_IN,
    408       SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS);
    409   AnimateBackgroundHidingIfNecessary(
    410       SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS,
    411       animation_sequence);
    412 
    413   animation_sequence->EndSequence();
    414 }
    415 
    416 void LockStateController::StartPostLockAnimation() {
    417   VLOG(1) << "StartPostLockAnimation";
    418   base::Closure next_animation_starter =
    419       base::Bind(&LockStateController::PostLockAnimationFinished,
    420                  weak_ptr_factory_.GetWeakPtr());
    421   SessionStateAnimator::AnimationSequence* animation_sequence =
    422       animator_->BeginAnimationSequence(next_animation_starter);
    423 
    424   animation_sequence->StartAnimation(
    425       SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
    426       SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN,
    427       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
    428   animation_sequence->EndSequence();
    429 }
    430 
    431 void LockStateController::StartUnlockAnimationBeforeUIDestroyed(
    432     base::Closure& callback) {
    433   VLOG(1) << "StartUnlockAnimationBeforeUIDestroyed";
    434   animator_->StartAnimationWithCallback(
    435       SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
    436       SessionStateAnimator::ANIMATION_LIFT,
    437       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS,
    438       callback);
    439 }
    440 
    441 void LockStateController::StartUnlockAnimationAfterUIDestroyed() {
    442   VLOG(1) << "StartUnlockAnimationAfterUIDestroyed";
    443   base::Closure next_animation_starter =
    444       base::Bind(&LockStateController::UnlockAnimationAfterUIDestroyedFinished,
    445                  weak_ptr_factory_.GetWeakPtr());
    446   SessionStateAnimator::AnimationSequence* animation_sequence =
    447       animator_->BeginAnimationSequence(next_animation_starter);
    448 
    449   animation_sequence->StartAnimation(
    450       SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
    451       SessionStateAnimator::ANIMATION_DROP,
    452       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
    453   animation_sequence->StartAnimation(
    454       SessionStateAnimator::LAUNCHER,
    455       SessionStateAnimator::ANIMATION_FADE_IN,
    456       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS);
    457   AnimateBackgroundHidingIfNecessary(
    458       SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, animation_sequence);
    459   animation_sequence->EndSequence();
    460 }
    461 
    462 void LockStateController::LockAnimationCancelled() {
    463   can_cancel_lock_animation_ = false;
    464   RestoreUnlockedProperties();
    465 }
    466 
    467 void LockStateController::PreLockAnimationFinished(bool request_lock) {
    468   VLOG(1) << "PreLockAnimationFinished";
    469   can_cancel_lock_animation_ = false;
    470 
    471   // Don't do anything (including starting the lock-fail timer) if the screen
    472   // was already locked while the animation was going.
    473   if (system_is_locked_) {
    474     DCHECK(!request_lock) << "Got request to lock already-locked system "
    475                           << "at completion of pre-lock animation";
    476     return;
    477   }
    478 
    479   if (request_lock) {
    480     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
    481         shutdown_after_lock_ ?
    482         UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON :
    483         UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON);
    484     delegate_->RequestLockScreen();
    485   }
    486 
    487   base::TimeDelta timeout =
    488       base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs);
    489 #if defined(OS_CHROMEOS)
    490   // Increase lock timeout for slower hardware, see http://crbug.com/350628
    491   const std::string board = base::SysInfo::GetLsbReleaseBoard();
    492   if (board == "x86-mario" ||
    493       StartsWithASCII(board, "x86-alex", true /* case_sensitive */) ||
    494       StartsWithASCII(board, "x86-zgb", true /* case_sensitive */)) {
    495     timeout *= 2;
    496   }
    497 #endif
    498   lock_fail_timer_.Start(
    499       FROM_HERE, timeout, this, &LockStateController::OnLockFailTimeout);
    500 }
    501 
    502 void LockStateController::PostLockAnimationFinished() {
    503   animating_lock_ = false;
    504   VLOG(1) << "PostLockAnimationFinished";
    505   FOR_EACH_OBSERVER(LockStateObserver, observers_,
    506       OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED));
    507   if (!lock_screen_displayed_callback_.is_null()) {
    508     lock_screen_displayed_callback_.Run();
    509     lock_screen_displayed_callback_.Reset();
    510   }
    511   CHECK(!views::MenuController::GetActiveInstance());
    512   if (shutdown_after_lock_) {
    513     shutdown_after_lock_ = false;
    514     StartLockToShutdownTimer();
    515   }
    516 }
    517 
    518 void LockStateController::UnlockAnimationAfterUIDestroyedFinished() {
    519   RestoreUnlockedProperties();
    520 }
    521 
    522 void LockStateController::StoreUnlockedProperties() {
    523   if (!unlocked_properties_) {
    524     unlocked_properties_.reset(new UnlockedStateProperties());
    525     unlocked_properties_->background_is_hidden =
    526         animator_->IsBackgroundHidden();
    527   }
    528   if (unlocked_properties_->background_is_hidden) {
    529     // Hide background so that it can be animated later.
    530     animator_->StartAnimation(SessionStateAnimator::DESKTOP_BACKGROUND,
    531                               SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY,
    532                               SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    533     animator_->ShowBackground();
    534   }
    535 }
    536 
    537 void LockStateController::RestoreUnlockedProperties() {
    538   if (!unlocked_properties_)
    539     return;
    540   if (unlocked_properties_->background_is_hidden) {
    541     animator_->HideBackground();
    542     // Restore background visibility.
    543     animator_->StartAnimation(SessionStateAnimator::DESKTOP_BACKGROUND,
    544                               SessionStateAnimator::ANIMATION_FADE_IN,
    545                               SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE);
    546   }
    547   unlocked_properties_.reset();
    548 }
    549 
    550 void LockStateController::AnimateBackgroundAppearanceIfNecessary(
    551     SessionStateAnimator::AnimationSpeed speed,
    552     SessionStateAnimator::AnimationSequence* animation_sequence) {
    553   if (unlocked_properties_.get() &&
    554       unlocked_properties_->background_is_hidden) {
    555     animation_sequence->StartAnimation(
    556         SessionStateAnimator::DESKTOP_BACKGROUND,
    557         SessionStateAnimator::ANIMATION_FADE_IN,
    558         speed);
    559   }
    560 }
    561 
    562 void LockStateController::AnimateBackgroundHidingIfNecessary(
    563     SessionStateAnimator::AnimationSpeed speed,
    564     SessionStateAnimator::AnimationSequence* animation_sequence) {
    565   if (unlocked_properties_.get() &&
    566       unlocked_properties_->background_is_hidden) {
    567     animation_sequence->StartAnimation(
    568         SessionStateAnimator::DESKTOP_BACKGROUND,
    569         SessionStateAnimator::ANIMATION_FADE_OUT,
    570         speed);
    571   }
    572 }
    573 
    574 }  // namespace ash
    575