1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
ash / system / power / power_event_observer.h [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_POWER_POWER_EVENT_OBSERVER_H_
#define ASH_SYSTEM_POWER_POWER_EVENT_OBSERVER_H_
#include <memory>
#include "ash/ash_export.h"
#include "ash/login_status.h"
#include "ash/public/cpp/session/session_observer.h"
#include "base/compiler_specific.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
#include "chromeos/dbus/power/power_manager_client.h"
namespace ui {
class CompositorObserver;
}
namespace ash {
class LockOnSuspendUsage;
// 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 https://crbug.com/807511.
class ASH_EXPORT PowerEventObserver
: public chromeos::PowerManagerClient::Observer,
public SessionObserver {
public:
// This class registers/unregisters itself as an observer in ctor/dtor.
PowerEventObserver();
PowerEventObserver(const PowerEventObserver&) = delete;
PowerEventObserver& operator=(const PowerEventObserver&) = delete;
~PowerEventObserver() override;
// Called by D-Bus when the current switches state is successfully obtained.
void OnGetSwitchStates(
std::optional<chromeos::PowerManagerClient::SwitchStates> result);
// 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 SuspendDoneEx(const power_manager::SuspendDone& proto) override;
void LidEventReceived(chromeos::PowerManagerClient::LidState state,
base::TimeTicks timestamp) override;
// SessionObserver overrides:
void OnLoginStatusChanged(LoginStatus login_status) override;
void OnLockStateChanged(bool locked) override;
// Sets whether the device is projecting (docked). This is used in along with
// lid state to lock the device.
void SetIsProjecting(bool is_projecting);
private:
friend class PowerEventObserverTestApi;
// Locks device when lid is closed, and device is not projecting (docked), if
// user/policy settings configured.
void MaybeLockOnLidClose(bool is_projecting);
enum class LockState {
// Screen lock has not been requested, nor detected.
kUnlocked,
// Screen lock has been requested, or detected, but screen lock has not
// reported that it finished showing.
kLocking,
// 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.
kLockedCompositingPending,
// Screen is locked, and displays have picked up lock screen changes - it
// should be safe to stop compositing and start suspend at this time.
kLocked,
};
// 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 unblock suspend via |block_suspend_token_| 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();
// Starts |wait_for_external_display_timer_|.
void StartExternalDisplayTimer();
LockState lock_state_ = LockState::kUnlocked;
chromeos::PowerManagerClient::LidState lid_state_ =
chromeos::PowerManagerClient::LidState::OPEN;
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_;
// Token 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 unblocking and clearing this - call
// StopCompositingAndSuspendDisplays(). This will only be set while the device
// is suspending.
base::UnguessableToken block_suspend_token_;
std::unique_ptr<LockOnSuspendUsage> lock_on_suspend_usage_;
// Amount of time (in seconds) to wait for external displays when a display
// mode change occurs and the lid is closed.
int defer_external_display_timeout_s_ = 0;
base::OneShotTimer wait_for_external_display_timer_;
base::WeakPtrFactory<PowerEventObserver> weak_factory_{this};
};
} // namespace ash
#endif // ASH_SYSTEM_POWER_POWER_EVENT_OBSERVER_H_