| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/wm/lock_state_controller.h" |
| |
| #include <algorithm> |
| #include <string> |
| #include <utility> |
| |
| #include "ash/accessibility/accessibility_controller.h" |
| #include "ash/cancel_mode.h" |
| #include "ash/public/cpp/shell_window_ids.h" |
| #include "ash/public/interfaces/shutdown.mojom.h" |
| #include "ash/session/session_controller_impl.h" |
| #include "ash/shell.h" |
| #include "ash/shell_delegate.h" |
| #include "ash/shutdown_controller.h" |
| #include "ash/shutdown_reason.h" |
| #include "ash/wallpaper/wallpaper_controller.h" |
| #include "ash/wm/session_state_animator.h" |
| #include "ash/wm/session_state_animator_impl.h" |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/command_line.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/user_metrics.h" |
| #include "base/strings/string_util.h" |
| #include "base/system/sys_info.h" |
| #include "base/timer/timer.h" |
| #include "ui/aura/window_tree_host.h" |
| #include "ui/views/controls/menu/menu_controller.h" |
| #include "ui/wm/core/compound_event_filter.h" |
| #include "ui/wm/core/cursor_manager.h" |
| |
| #define UMA_HISTOGRAM_LOCK_TIMES(name, sample) \ |
| UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, \ |
| base::TimeDelta::FromMilliseconds(1), \ |
| base::TimeDelta::FromSeconds(50), 100) |
| |
| namespace ash { |
| |
| namespace { |
| |
| // ASan/TSan/MSan instrument each memory access. This may slow the execution |
| // down significantly. |
| #if defined(MEMORY_SANITIZER) |
| // For MSan the slowdown depends heavily on the value of msan_track_origins GYP |
| // flag. The multiplier below corresponds to msan_track_origins=1. |
| constexpr int kTimeoutMultiplier = 6; |
| #elif defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) |
| constexpr int kTimeoutMultiplier = 2; |
| #else |
| constexpr int kTimeoutMultiplier = 1; |
| #endif |
| |
| constexpr int kMaxShutdownSoundDurationMs = 1500; |
| |
| // Amount of time to wait for our lock requests to be honored before giving up. |
| constexpr base::TimeDelta kLockFailTimeout = |
| base::TimeDelta::FromSeconds(8 * kTimeoutMultiplier); |
| |
| // When the button has been held continuously from the unlocked state, amount of |
| // time that we wait after the screen locker window is shown before starting the |
| // pre-shutdown animation. |
| constexpr base::TimeDelta kLockToShutdownTimeout = |
| base::TimeDelta::FromMilliseconds(150); |
| |
| // Additional time to wait after starting the fast-close shutdown animation |
| // before actually requesting shutdown, to give the animation time to finish. |
| constexpr base::TimeDelta kShutdownRequestDelay = |
| base::TimeDelta::FromMilliseconds(50); |
| |
| } // namespace |
| |
| // static |
| const int LockStateController::kPreLockContainersMask = |
| SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS | |
| SessionStateAnimator::SHELF; |
| |
| LockStateController::LockStateController( |
| ShutdownController* shutdown_controller) |
| : animator_(new SessionStateAnimatorImpl()), |
| shutdown_controller_(shutdown_controller), |
| scoped_session_observer_(this), |
| weak_ptr_factory_(this) { |
| DCHECK(shutdown_controller_); |
| Shell::GetPrimaryRootWindow()->GetHost()->AddObserver(this); |
| } |
| |
| LockStateController::~LockStateController() { |
| Shell::GetPrimaryRootWindow()->GetHost()->RemoveObserver(this); |
| } |
| |
| void LockStateController::AddObserver(LockStateObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void LockStateController::RemoveObserver(LockStateObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| void LockStateController::StartLockAnimation() { |
| if (animating_lock_) |
| return; |
| can_cancel_lock_animation_ = true; |
| |
| StartCancellablePreLockAnimation(); |
| } |
| |
| void LockStateController::StartLockThenShutdownAnimation( |
| ShutdownReason shutdown_reason) { |
| shutdown_after_lock_ = true; |
| shutdown_reason_ = shutdown_reason; |
| StartLockAnimation(); |
| } |
| |
| void LockStateController::StartShutdownAnimation(ShutdownReason reason) { |
| shutdown_reason_ = reason; |
| StartCancellableShutdownAnimation(); |
| } |
| |
| void LockStateController::StartLockAnimationAndLockImmediately() { |
| if (animating_lock_) |
| return; |
| StartImmediatePreLockAnimation(true /* request_lock_on_completion */); |
| } |
| |
| void LockStateController::LockWithoutAnimation() { |
| if (animating_lock_) |
| return; |
| animating_lock_ = true; |
| post_lock_immediate_animation_ = true; |
| animator_->StartAnimation(kPreLockContainersMask, |
| SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, |
| SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); |
| OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED); |
| Shell::Get()->session_controller()->LockScreen(); |
| } |
| |
| bool LockStateController::LockRequested() { |
| return lock_fail_timer_.IsRunning(); |
| } |
| |
| bool LockStateController::ShutdownRequested() { |
| return shutting_down_; |
| } |
| |
| bool LockStateController::CanCancelLockAnimation() { |
| return can_cancel_lock_animation_; |
| } |
| |
| void LockStateController::CancelLockAnimation() { |
| if (!CanCancelLockAnimation()) |
| return; |
| shutdown_after_lock_ = false; |
| animating_lock_ = false; |
| CancelPreLockAnimation(); |
| } |
| |
| bool LockStateController::CanCancelShutdownAnimation() { |
| return pre_shutdown_timer_.IsRunning() || shutdown_after_lock_ || |
| lock_to_shutdown_timer_.IsRunning(); |
| } |
| |
| void LockStateController::CancelShutdownAnimation() { |
| if (!CanCancelShutdownAnimation()) |
| return; |
| if (lock_to_shutdown_timer_.IsRunning()) { |
| lock_to_shutdown_timer_.Stop(); |
| return; |
| } |
| if (shutdown_after_lock_) { |
| shutdown_after_lock_ = false; |
| return; |
| } |
| |
| animator_->StartAnimation( |
| SessionStateAnimator::ROOT_CONTAINER, |
| SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS, |
| SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN); |
| pre_shutdown_timer_.Stop(); |
| } |
| |
| void LockStateController::OnStartingLock() { |
| if (shutting_down_ || system_is_locked_) |
| return; |
| if (animating_lock_) |
| return; |
| StartImmediatePreLockAnimation(false /* request_lock_on_completion */); |
| } |
| |
| void LockStateController::RequestShutdown(ShutdownReason reason) { |
| if (shutting_down_) |
| return; |
| |
| shutting_down_ = true; |
| shutdown_reason_ = reason; |
| |
| ::wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager(); |
| cursor_manager->HideCursor(); |
| cursor_manager->LockCursor(); |
| |
| animator_->StartAnimation( |
| SessionStateAnimator::ROOT_CONTAINER, |
| SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS, |
| SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); |
| StartRealShutdownTimer(true); |
| } |
| |
| void LockStateController::OnLockScreenHide(base::OnceClosure callback) { |
| StartUnlockAnimationBeforeUIDestroyed(std::move(callback)); |
| } |
| |
| void LockStateController::SetLockScreenDisplayedCallback( |
| base::OnceClosure callback) { |
| DCHECK(lock_screen_displayed_callback_.is_null()); |
| lock_screen_displayed_callback_ = std::move(callback); |
| } |
| |
| void LockStateController::OnHostCloseRequested(aura::WindowTreeHost* host) { |
| Shell::Get()->session_controller()->RequestSignOut(); |
| } |
| |
| void LockStateController::OnChromeTerminating() { |
| // If we hear that Chrome is exiting but didn't request it ourselves, all we |
| // can really hope for is that we'll have time to clear the screen. |
| // This is also the case when the user signs off. |
| if (!shutting_down_) { |
| shutting_down_ = true; |
| ::wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager(); |
| cursor_manager->HideCursor(); |
| cursor_manager->LockCursor(); |
| animator_->StartAnimation(SessionStateAnimator::kAllNonRootContainersMask, |
| SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, |
| SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); |
| } |
| } |
| |
| void LockStateController::OnLockStateChanged(bool locked) { |
| DCHECK((lock_fail_timer_.IsRunning() && lock_duration_timer_ != nullptr) || |
| (!lock_fail_timer_.IsRunning() && lock_duration_timer_ == nullptr)); |
| VLOG(1) << "OnLockStateChanged called with locked: " << locked |
| << ", shutting_down_: " << shutting_down_ |
| << ", system_is_locked_: " << system_is_locked_ |
| << ", lock_fail_timer_.IsRunning(): " << lock_fail_timer_.IsRunning(); |
| |
| if (shutting_down_ || (system_is_locked_ == locked)) |
| return; |
| |
| system_is_locked_ = locked; |
| |
| if (locked) { |
| StartPostLockAnimation(); |
| |
| lock_fail_timer_.Stop(); |
| |
| if (lock_duration_timer_) { |
| UMA_HISTOGRAM_LOCK_TIMES("Ash.WindowManager.Lock.Success", |
| lock_duration_timer_->Elapsed()); |
| lock_duration_timer_.reset(); |
| } |
| } else { |
| StartUnlockAnimationAfterUIDestroyed(); |
| } |
| } |
| |
| void LockStateController::OnLockFailTimeout() { |
| UMA_HISTOGRAM_LOCK_TIMES("Ash.WindowManager.Lock.Timeout", |
| lock_duration_timer_->Elapsed()); |
| lock_duration_timer_.reset(); |
| DCHECK(!system_is_locked_); |
| |
| LOG(FATAL) << "Screen lock took too long; crashing intentionally"; |
| } |
| |
| void LockStateController::StartLockToShutdownTimer() { |
| DCHECK(shutdown_reason_); |
| shutdown_after_lock_ = false; |
| lock_to_shutdown_timer_.Stop(); |
| lock_to_shutdown_timer_.Start(FROM_HERE, kLockToShutdownTimeout, this, |
| &LockStateController::OnLockToShutdownTimeout); |
| } |
| |
| void LockStateController::OnLockToShutdownTimeout() { |
| DCHECK(system_is_locked_); |
| StartCancellableShutdownAnimation(); |
| } |
| |
| void LockStateController::StartPreShutdownAnimationTimer() { |
| pre_shutdown_timer_.Stop(); |
| pre_shutdown_timer_.Start( |
| FROM_HERE, |
| animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN), |
| this, &LockStateController::OnPreShutdownAnimationTimeout); |
| } |
| |
| void LockStateController::OnPreShutdownAnimationTimeout() { |
| VLOG(1) << "OnPreShutdownAnimationTimeout"; |
| shutting_down_ = true; |
| |
| Shell* shell = Shell::Get(); |
| if (shell->cursor_manager()) |
| shell->cursor_manager()->HideCursor(); |
| |
| StartRealShutdownTimer(false); |
| } |
| |
| void LockStateController::StartRealShutdownTimer(bool with_animation_time) { |
| base::TimeDelta duration = kShutdownRequestDelay; |
| if (with_animation_time) { |
| duration += |
| animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); |
| } |
| // Play and get shutdown sound duration from chrome in |sound_duration|. And |
| // start real shutdown after a delay of |duration|. |
| Shell::Get()->accessibility_controller()->PlayShutdownSound(base::BindOnce( |
| [](base::WeakPtr<LockStateController> self, base::TimeDelta duration, |
| base::TimeDelta sound_duration) { |
| if (!self) |
| return; |
| sound_duration = std::min( |
| sound_duration, |
| base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs)); |
| duration = std::max(duration, sound_duration); |
| self->real_shutdown_timer_.Start( |
| FROM_HERE, duration, self.get(), |
| &LockStateController::OnRealPowerTimeout); |
| }, |
| weak_ptr_factory_.GetWeakPtr(), duration)); |
| } |
| |
| void LockStateController::OnRealPowerTimeout() { |
| VLOG(1) << "OnRealPowerTimeout"; |
| DCHECK(shutting_down_); |
| DCHECK(shutdown_reason_); |
| // Shut down or reboot based on device policy. |
| shutdown_controller_->ShutDownOrReboot(*shutdown_reason_); |
| } |
| |
| void LockStateController::StartCancellableShutdownAnimation() { |
| Shell* shell = Shell::Get(); |
| // Hide cursor, but let it reappear if the mouse moves. |
| if (shell->cursor_manager()) |
| shell->cursor_manager()->HideCursor(); |
| |
| animator_->StartAnimation( |
| SessionStateAnimator::ROOT_CONTAINER, |
| SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS, |
| SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); |
| StartPreShutdownAnimationTimer(); |
| } |
| |
| void LockStateController::StartImmediatePreLockAnimation( |
| bool request_lock_on_completion) { |
| VLOG(1) << "StartImmediatePreLockAnimation " << request_lock_on_completion; |
| animating_lock_ = true; |
| StoreUnlockedProperties(); |
| PreLockAnimation(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, |
| request_lock_on_completion); |
| DispatchCancelMode(); |
| OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED); |
| } |
| |
| void LockStateController::StartCancellablePreLockAnimation() { |
| animating_lock_ = true; |
| StoreUnlockedProperties(); |
| VLOG(1) << "StartCancellablePreLockAnimation"; |
| PreLockAnimation(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, true); |
| DispatchCancelMode(); |
| OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED); |
| } |
| |
| void LockStateController::PreLockAnimation( |
| SessionStateAnimator::AnimationSpeed speed, |
| bool request_lock_on_completion) { |
| Shell::Get()->wallpaper_controller()->UpdateWallpaperBlur(true); |
| base::Closure next_animation_starter = |
| base::Bind(&LockStateController::PreLockAnimationFinished, |
| weak_ptr_factory_.GetWeakPtr(), request_lock_on_completion); |
| SessionStateAnimator::AnimationSequence* animation_sequence = |
| animator_->BeginAnimationSequence(next_animation_starter); |
| |
| animation_sequence->StartAnimation( |
| SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, |
| SessionStateAnimator::ANIMATION_LIFT, speed); |
| animation_sequence->StartAnimation(SessionStateAnimator::SHELF, |
| SessionStateAnimator::ANIMATION_FADE_OUT, |
| speed); |
| // Hide the screen locker containers so we can raise them later. |
| animator_->StartAnimation(SessionStateAnimator::LOCK_SCREEN_CONTAINERS, |
| SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, |
| SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); |
| AnimateWallpaperAppearanceIfNecessary(speed, animation_sequence); |
| |
| animation_sequence->EndSequence(); |
| } |
| |
| void LockStateController::CancelPreLockAnimation() { |
| VLOG(1) << "CancelPreLockAnimation"; |
| Shell::Get()->wallpaper_controller()->UpdateWallpaperBlur(false); |
| base::Closure next_animation_starter = |
| base::Bind(&LockStateController::LockAnimationCancelled, |
| weak_ptr_factory_.GetWeakPtr()); |
| SessionStateAnimator::AnimationSequence* animation_sequence = |
| animator_->BeginAnimationSequence(next_animation_starter); |
| |
| animation_sequence->StartAnimation( |
| SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, |
| SessionStateAnimator::ANIMATION_UNDO_LIFT, |
| SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS); |
| animation_sequence->StartAnimation( |
| SessionStateAnimator::SHELF, SessionStateAnimator::ANIMATION_FADE_IN, |
| SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS); |
| AnimateWallpaperHidingIfNecessary( |
| SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS, |
| animation_sequence); |
| |
| animation_sequence->EndSequence(); |
| } |
| |
| void LockStateController::StartPostLockAnimation() { |
| VLOG(1) << "StartPostLockAnimation"; |
| base::Closure next_animation_starter = |
| base::Bind(&LockStateController::PostLockAnimationFinished, |
| weak_ptr_factory_.GetWeakPtr()); |
| SessionStateAnimator::AnimationSequence* animation_sequence = |
| animator_->BeginAnimationSequence(next_animation_starter); |
| |
| animation_sequence->StartAnimation( |
| SessionStateAnimator::LOCK_SCREEN_CONTAINERS, |
| SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN, |
| post_lock_immediate_animation_ |
| ? SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE |
| : SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); |
| // Show the lock screen shelf. This is a no-op if views-based shelf is |
| // disabled, since shelf is in NonLockScreenContainersContainer. |
| animation_sequence->StartAnimation( |
| SessionStateAnimator::SHELF, SessionStateAnimator::ANIMATION_FADE_IN, |
| post_lock_immediate_animation_ |
| ? SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE |
| : SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); |
| animation_sequence->EndSequence(); |
| } |
| |
| void LockStateController::StartUnlockAnimationBeforeUIDestroyed( |
| base::OnceClosure callback) { |
| VLOG(1) << "StartUnlockAnimationBeforeUIDestroyed"; |
| animator_->StartAnimationWithCallback( |
| SessionStateAnimator::LOCK_SCREEN_CONTAINERS, |
| SessionStateAnimator::ANIMATION_LIFT, |
| SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, std::move(callback)); |
| // Hide the lock screen shelf. This is a no-op if views-based shelf is |
| // disabled, since shelf is in NonLockScreenContainersContainer. |
| animator_->StartAnimation(SessionStateAnimator::SHELF, |
| SessionStateAnimator::ANIMATION_FADE_OUT, |
| SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); |
| } |
| |
| void LockStateController::StartUnlockAnimationAfterUIDestroyed() { |
| VLOG(1) << "StartUnlockAnimationAfterUIDestroyed"; |
| base::Closure next_animation_starter = |
| base::Bind(&LockStateController::UnlockAnimationAfterUIDestroyedFinished, |
| weak_ptr_factory_.GetWeakPtr()); |
| SessionStateAnimator::AnimationSequence* animation_sequence = |
| animator_->BeginAnimationSequence(next_animation_starter); |
| |
| animation_sequence->StartAnimation( |
| SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, |
| SessionStateAnimator::ANIMATION_DROP, |
| SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); |
| animation_sequence->StartAnimation( |
| SessionStateAnimator::SHELF, SessionStateAnimator::ANIMATION_FADE_IN, |
| SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); |
| AnimateWallpaperHidingIfNecessary( |
| SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, animation_sequence); |
| animation_sequence->EndSequence(); |
| } |
| |
| void LockStateController::LockAnimationCancelled() { |
| can_cancel_lock_animation_ = false; |
| RestoreUnlockedProperties(); |
| } |
| |
| void LockStateController::PreLockAnimationFinished(bool request_lock) { |
| VLOG(1) << "PreLockAnimationFinished"; |
| can_cancel_lock_animation_ = false; |
| |
| // Don't do anything (including starting the lock-fail timer) if the screen |
| // was already locked while the animation was going. |
| if (system_is_locked_) { |
| DCHECK(!request_lock) << "Got request to lock already-locked system " |
| << "at completion of pre-lock animation"; |
| return; |
| } |
| |
| if (request_lock) { |
| if (shutdown_after_lock_) { |
| base::RecordAction( |
| base::UserMetricsAction("Accel_LockScreen_PowerButton")); |
| } else { |
| base::RecordAction( |
| base::UserMetricsAction("Accel_LockScreen_LockButton")); |
| } |
| Shell::Get()->session_controller()->LockScreen(); |
| } |
| |
| lock_fail_timer_.Start(FROM_HERE, kLockFailTimeout, this, |
| &LockStateController::OnLockFailTimeout); |
| |
| lock_duration_timer_.reset(new base::ElapsedTimer()); |
| } |
| |
| void LockStateController::PostLockAnimationFinished() { |
| animating_lock_ = false; |
| post_lock_immediate_animation_ = false; |
| VLOG(1) << "PostLockAnimationFinished"; |
| OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED); |
| if (!lock_screen_displayed_callback_.is_null()) |
| std::move(lock_screen_displayed_callback_).Run(); |
| |
| CHECK(!views::MenuController::GetActiveInstance()); |
| if (shutdown_after_lock_) { |
| shutdown_after_lock_ = false; |
| StartLockToShutdownTimer(); |
| } |
| } |
| |
| void LockStateController::UnlockAnimationAfterUIDestroyedFinished() { |
| Shell::Get()->wallpaper_controller()->UpdateWallpaperBlur(false); |
| RestoreUnlockedProperties(); |
| } |
| |
| void LockStateController::StoreUnlockedProperties() { |
| if (!unlocked_properties_) { |
| unlocked_properties_.reset(new UnlockedStateProperties()); |
| unlocked_properties_->wallpaper_is_hidden = animator_->IsWallpaperHidden(); |
| } |
| if (unlocked_properties_->wallpaper_is_hidden) { |
| // Hide wallpaper so that it can be animated later. |
| animator_->StartAnimation(SessionStateAnimator::WALLPAPER, |
| SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, |
| SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); |
| animator_->ShowWallpaper(); |
| } |
| } |
| |
| void LockStateController::RestoreUnlockedProperties() { |
| if (!unlocked_properties_) |
| return; |
| if (unlocked_properties_->wallpaper_is_hidden) { |
| animator_->HideWallpaper(); |
| // Restore wallpaper visibility. |
| animator_->StartAnimation(SessionStateAnimator::WALLPAPER, |
| SessionStateAnimator::ANIMATION_FADE_IN, |
| SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); |
| } |
| unlocked_properties_.reset(); |
| } |
| |
| void LockStateController::AnimateWallpaperAppearanceIfNecessary( |
| SessionStateAnimator::AnimationSpeed speed, |
| SessionStateAnimator::AnimationSequence* animation_sequence) { |
| if (unlocked_properties_.get() && unlocked_properties_->wallpaper_is_hidden) { |
| animation_sequence->StartAnimation(SessionStateAnimator::WALLPAPER, |
| SessionStateAnimator::ANIMATION_FADE_IN, |
| speed); |
| } |
| } |
| |
| void LockStateController::AnimateWallpaperHidingIfNecessary( |
| SessionStateAnimator::AnimationSpeed speed, |
| SessionStateAnimator::AnimationSequence* animation_sequence) { |
| if (unlocked_properties_.get() && unlocked_properties_->wallpaper_is_hidden) { |
| animation_sequence->StartAnimation(SessionStateAnimator::WALLPAPER, |
| SessionStateAnimator::ANIMATION_FADE_OUT, |
| speed); |
| } |
| } |
| |
| void LockStateController::OnLockStateEvent(LockStateObserver::EventType event) { |
| for (auto& observer : observers_) |
| observer.OnLockStateEvent(event); |
| } |
| |
| } // namespace ash |