1 // Copyright (c) 2012 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 #ifndef ASH_SYSTEM_POWER_POWER_BUTTON_CONTROLLER_H_
6 #define ASH_SYSTEM_POWER_POWER_BUTTON_CONTROLLER_H_
7 
8 #include <memory>
9 
10 #include "ash/accelerometer/accelerometer_reader.h"
11 #include "ash/ash_export.h"
12 #include "ash/public/cpp/session/session_observer.h"
13 #include "ash/public/cpp/tablet_mode_observer.h"
14 #include "ash/system/power/backlights_forced_off_setter.h"
15 #include "ash/wm/lock_state_observer.h"
16 #include "base/macros.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/timer/timer.h"
19 #include "chromeos/dbus/power/power_manager_client.h"
20 #include "ui/display/manager/display_configurator.h"
21 #include "ui/views/widget/widget.h"
22 
23 namespace base {
24 class TickClock;
25 class TimeTicks;
26 }  // namespace base
27 
28 namespace ash {
29 
30 class LockStateController;
31 class PowerButtonDisplayController;
32 class PowerButtonScreenshotController;
33 
34 // Handles power button and lock button events. Holding the power button
35 // displays a menu and later shuts down on all devices. Tapping the power button
36 // of convertible/slate/detachable devices (except forced clamshell set by
37 // command line) will turn screen off but nothing will happen for clamshell
38 // devices. In tablet mode, power button may also be consumed to take a
39 // screenshot.
40 class ASH_EXPORT PowerButtonController
41     : public display::DisplayConfigurator::Observer,
42       public chromeos::PowerManagerClient::Observer,
43       public AccelerometerReader::Observer,
44       public ScreenBacklightObserver,
45       public TabletModeObserver,
46       public LockStateObserver,
47       public SessionObserver {
48  public:
49   enum class ButtonType {
50     // Indicates normal power button type.
51     NORMAL,
52 
53     // Indicates legacy power button type. It could be set by command-line
54     // switch telling us that we're running on hardware that misreports power
55     // button releases.
56     LEGACY,
57   };
58 
59   // The physical display side of power button.
60   enum class PowerButtonPosition { NONE, LEFT, TOP, RIGHT, BOTTOM };
61 
62   // Amount of time since last screen state change that power button event needs
63   // to be ignored.
64   static constexpr base::TimeDelta kScreenStateChangeDelay =
65       base::TimeDelta::FromMilliseconds(500);
66 
67   // Ignore button-up events occurring within this many milliseconds of the
68   // previous button-up event. This prevents us from falling behind if the power
69   // button is pressed repeatedly.
70   static constexpr base::TimeDelta kIgnoreRepeatedButtonUpDelay =
71       base::TimeDelta::FromMilliseconds(500);
72 
73   // Amount of time since last SuspendDone() that power button event needs to be
74   // ignored.
75   static constexpr base::TimeDelta kIgnorePowerButtonAfterResumeDelay =
76       base::TimeDelta::FromSeconds(2);
77 
78   // Value of switches::kAshPowerButtonPosition stored in JSON format. These
79   // are the field names of the flag.
80   static constexpr const char* kEdgeField = "edge";
81   static constexpr const char* kPositionField = "position";
82 
83   // Value of |kEdgeField|.
84   static constexpr const char* kLeftEdge = "left";
85   static constexpr const char* kRightEdge = "right";
86   static constexpr const char* kTopEdge = "top";
87   static constexpr const char* kBottomEdge = "bottom";
88 
89   explicit PowerButtonController(
90       BacklightsForcedOffSetter* backlights_forced_off_setter);
91   ~PowerButtonController() override;
92 
93   // Handles events from "legacy" ACPI power buttons. On devices with these
94   // buttons (typically Chromeboxes), button releases are misreported
95   // immediately after button presses, regardless of how long the button
96   // is actually held.
97   void OnLegacyPowerButtonEvent(bool down);
98 
99   // Handles events from "normal" power buttons where button presses and
100   // releases are both reported accurately.
101   void OnPowerButtonEvent(bool down, const base::TimeTicks& timestamp);
102 
103   // Handles lock button behavior.
104   void OnLockButtonEvent(bool down, const base::TimeTicks& timestamp);
105 
106   // Cancels the ongoing power button behavior. This can be called while the
107   // button is still held to prevent any action from being taken on release.
108   void CancelPowerButtonEvent();
109 
110   // True if the menu is opened.
111   bool IsMenuOpened() const;
112 
113   // Dismisses the menu.
114   void DismissMenu();
115 
116   // Do not force backlights to be turned off.
117   void StopForcingBacklightsOff();
118 
119   // display::DisplayConfigurator::Observer:
120   void OnDisplayModeChanged(
121       const display::DisplayConfigurator::DisplayStateList& outputs) override;
122 
123   // chromeos::PowerManagerClient::Observer:
124   void ScreenBrightnessChanged(
125       const power_manager::BacklightBrightnessChange& change) override;
126   void PowerButtonEventReceived(bool down,
127                                 const base::TimeTicks& timestamp) override;
128   void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
129   void SuspendDone(const base::TimeDelta& sleep_duration) override;
130 
131   // SessionObserver:
132   void OnLoginStatusChanged(LoginStatus status) override;
133 
134   // Initializes |screenshot_controller_| according to the tablet mode switch in
135   // |result|.
136   void OnGetSwitchStates(
137       base::Optional<chromeos::PowerManagerClient::SwitchStates> result);
138 
139   // TODO(minch): Remove this if/when all applicable devices expose a tablet
140   // mode switch: https://crbug.com/798646.
141   // AccelerometerReader::Observer:
142   void OnAccelerometerUpdated(
143       scoped_refptr<const AccelerometerUpdate> update) override;
144 
145   // BacklightsForcedOffSetter::Observer:
146   void OnBacklightsForcedOffChanged(bool forced_off) override;
147   void OnScreenStateChanged(ScreenState screen_state) override;
148 
149   // TabletModeObserver:
150   void OnTabletModeStarted() override;
151   void OnTabletModeEnded() override;
152 
153   // LockStateObserver:
154   void OnLockStateEvent(LockStateObserver::EventType event) override;
155 
156  private:
157   friend class PowerButtonControllerTestApi;
158 
159   // Returns true if tablet power button behavior (i.e. tapping the button turns
160   // the screen off) should currently be used.
161   bool UseTabletBehavior() const;
162 
163   // Stops |power_button_menu_timer_|, |shutdown_timer_| and dismisses the power
164   // button menu.
165   void StopTimersAndDismissMenu();
166 
167   // Starts the power menu animation. Called when a clamshell device's power
168   // button is pressed or when |power_button_menu_timer_| fires.
169   void StartPowerMenuAnimation();
170 
171   // Called by |pre_shutdown_timer_| to start the cancellable pre-shutdown
172   // animation.
173   void OnPreShutdownTimeout();
174 
175   // Updates |button_type_| and power button position info based on the current
176   // command line.
177   void ProcessCommandLine();
178 
179   // Initializes tablet power button behavior related member
180   // |screenshot_controller_|.
181   void InitTabletPowerButtonMembers();
182 
183   // Locks the screen if the "Show lock screen when waking from sleep" pref is
184   // set and locking is possible.
185   void LockScreenIfRequired();
186 
187   // Sets |show_menu_animation_done_| to true.
188   void SetShowMenuAnimationDone();
189 
190   // A helper function called by ProcessCommandLine to parse the value of
191   // switches::kAshPowerButtonPosition.
192   void ParsePowerButtonPositionSwitch();
193 
194   // Updates UMA histogram of power button press according to the power button
195   // up state. |up_state| is a bit field containing values from the
196   // PowerButtonUpState enum defined in the .cc file.
197   void UpdatePowerButtonEventUMAHistogram(uint32_t up_state);
198 
199   // Are the power or lock buttons currently held?
200   bool power_button_down_ = false;
201   bool lock_button_down_ = false;
202 
203   // True if the device is curently in tablet mode (per TabletModeController).
204   bool in_tablet_mode_ = false;
205 
206   // Has the screen brightness been reduced to 0%?
207   bool brightness_is_zero_ = false;
208 
209   // True if an internal display is off while an external display is on (e.g.
210   // for Chrome OS's docked mode, where a Chromebook's lid is closed while an
211   // external display is connected).
212   bool internal_display_off_and_external_display_on_ = false;
213 
214   // True after the animation that shows the power menu has finished.
215   bool show_menu_animation_done_ = false;
216 
217   // Saves the button type for this power button.
218   ButtonType button_type_ = ButtonType::NORMAL;
219 
220   // True if the device should observe accelerometer events to enter tablet
221   // mode.
222   bool observe_accelerometer_events_ = false;
223 
224   // True if the kForceTabletPowerButton flag is set. This forces tablet power
225   // button behavior even while in laptop mode.
226   bool force_tablet_power_button_ = false;
227 
228   // True if the device has tablet mode switch.
229   bool has_tablet_mode_switch_ = false;
230 
231   // When ChromeOS EC lid angle driver is supported, there's always tablet mode
232   // switch in device, so PowerButtonController doesn't need to listens to
233   // accelerometer events.
234   ECLidAngleDriverStatus ec_lid_angle_driver_status_ =
235       ECLidAngleDriverStatus::UNKNOWN;
236 
237   // True if the screen was off when the power button was pressed.
238   bool screen_off_when_power_button_down_ = false;
239 
240   // True if power menu is already shown when pressing the power button.
241   bool menu_shown_when_power_button_down_ = false;
242 
243   // True if the next button release event should force the display off.
244   bool force_off_on_button_up_ = false;
245 
246   // Used to force backlights off, when needed.
247   BacklightsForcedOffSetter* backlights_forced_off_setter_;  // Not owned.
248 
249   LockStateController* lock_state_controller_;  // Not owned.
250 
251   // Time source for performed action times.
252   const base::TickClock* tick_clock_;
253 
254   // Used to interact with the display.
255   std::unique_ptr<PowerButtonDisplayController> display_controller_;
256 
257   // Handles events for power button screenshot.
258   std::unique_ptr<PowerButtonScreenshotController> screenshot_controller_;
259 
260   // Saves the most recent timestamp that powerd resumed from suspend,
261   // updated in SuspendDone().
262   base::TimeTicks last_resume_time_;
263 
264   // Saves the most recent timestamp that power button was released.
265   base::TimeTicks last_button_up_time_;
266 
267   // Started when |show_menu_animation_done_| is set to true and stopped when
268   // power button is released. Runs OnPreShutdownTimeout() to start the
269   // cancellable pre-shutdown animation.
270   base::OneShotTimer pre_shutdown_timer_;
271 
272   // Started when the power button of convertible/slate/detachable devices is
273   // pressed and stopped when it's released. Runs StartPowerMenuAnimation() to
274   // show the power button menu.
275   base::OneShotTimer power_button_menu_timer_;
276 
277   // The fullscreen widget of power button menu.
278   std::unique_ptr<views::Widget> menu_widget_;
279 
280   // The physical display side of power button in landscape primary.
281   PowerButtonPosition power_button_position_ = PowerButtonPosition::NONE;
282 
283   // The center of the power button's offset from the top of the screen (for
284   // left/right) or left side of the screen (for top/bottom) in
285   // landscape_primary. Values are in [0.0, 1.0] and express a fraction of the
286   // display's height or width, respectively.
287   double power_button_offset_percentage_ = 0.f;
288 
289   ScopedObserver<BacklightsForcedOffSetter, ScreenBacklightObserver>
290       backlights_forced_off_observer_;
291 
292   // Used to maintain active state of the active window that exists before
293   // showing menu.
294   std::unique_ptr<views::Widget::PaintAsActiveLock>
295       active_window_paint_as_active_lock_;
296 
297   base::WeakPtrFactory<PowerButtonController> weak_factory_{this};
298 
299   DISALLOW_COPY_AND_ASSIGN(PowerButtonController);
300 };
301 
302 }  // namespace ash
303 
304 #endif  // ASH_SYSTEM_POWER_POWER_BUTTON_CONTROLLER_H_
305