blob: 5af8d9453503f0d4ffeb9e8e4df050b2806b0ed4 [file] [log] [blame]
// 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 <memory>
#include "ash/ash_export.h"
#include "ash/session/session_observer.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "chromeos/dbus/power_manager_client.h"
namespace ui {
class CompositorObserver;
namespace ash {
// A class that observes power-management-related events - in particular, it
// observes the device suspend state and updates display states accordingly.
// When the device suspends, it suspends all displays and stops compositing.
// On resume, displays are resumed, and compositing is started again.
// During suspend, it ensures compositing is not stopped prematurely if the
// screen is being locked during suspend - display compositing will not be
// stopped before:
// 1. lock screen window is shown
// 2. wallpaper changes due to screen lock are finished
// 3. the compositor goes through at least two compositing cycles after the
// screen lock
// This is done to ensure that displays have picked up frames from after the
// screen was locked. Without this, displays might initially show
// pre-screen-lock frames when resumed.
// For example, see
class ASH_EXPORT PowerEventObserver
: public chromeos::PowerManagerClient::Observer,
public SessionObserver {
// This class registers/unregisters itself as an observer in ctor/dtor.
~PowerEventObserver() override;
// Called by the WebUIScreenLocker when all the lock screen animations have
// completed. This really should be implemented via an observer but since
// ash/ isn't allowed to depend on chrome/ we need to have the
// WebUIScreenLocker reach into ash::Shell to make this call.
void OnLockAnimationsComplete();
// chromeos::PowerManagerClient::Observer overrides:
void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
void SuspendDone(const base::TimeDelta& sleep_duration) override;
// SessionObserver overrides:
void OnLockStateChanged(bool locked) override;
friend class PowerEventObserverTestApi;
enum class LockState {
// Screen lock has not been requested, nor detected.
// Screen lock has been requested, or detected, but screen lock has not
// reported that it finished showing.
// Screen has been locked, but all compositors might not have yet picked up
// locked screen state - |compositor_watcher_| is observing compositors,
// waiting for them to become ready to suspend.
// Screen is locked, and displays have picked up lock screen changes - it
// should be safe to stop compositing and start suspend at this time.
// Sets all root window compositors' visibility to true.
void StartRootWindowCompositors();
// Sets all root window compositors' visibility to false, and then suspends
// displays. It will run |display_suspended_callback_| once displays are
// suspended.
// This should only be called when it's safe to stop compositing -
// either if the screen is not expected to get locked, or all compositors
// have gone through compositing cycle after the screen was locked.
void StopCompositingAndSuspendDisplays();
// If any of the root windows have pending wallpaper animations, it stops
// them - this is used to stop wallpaper animations during suspend, and thus
// improve the suspend time (given that suspend will be delayed until the
// wallpaper animations finish).
void EndPendingWallpaperAnimations();
// Callback run by |compositor_watcher_| when it detects that composting
// can be stopped for all root windows when device suspends.
void OnCompositorsReadyForSuspend();
LockState lock_state_ = LockState::kUnlocked;
ScopedSessionObserver session_observer_;
// Whether the device is suspending.
bool suspend_in_progress_ = false;
// Used to observe compositing state after screen lock to detect when display
// compositors are in state in which it's safe to proceed with suspend.
std::unique_ptr<ui::CompositorObserver> compositor_watcher_;
// Callback set when device suspend is delayed due to a screen lock - suspend
// should be continued when the screen lock finishes showing and display
// compositors pick up screen lock changes. All compositors should be stopped
// prior to calling this - call StopCompositingAndSuspendDisplays() instead of
// runnig this callback directly.
// This will only be set while the device is suspending.
base::OnceClosure displays_suspended_callback_;
} // namespace ash