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