1 // Copyright (c) 2013 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 #include "chromeos/dbus/power/power_policy_controller.h"
6
7 #include <stdint.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12
13 #include "base/format_macros.h"
14 #include "base/logging.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "chromeos/dbus/power_manager/backlight.pb.h"
18
19 // Avoid some ugly line-wrapping later.
20 using base::StringAppendF;
21
22 namespace chromeos {
23
24 namespace {
25
26 PowerPolicyController* g_power_policy_controller = nullptr;
27
28 // Appends a description of |field|, a field within |delays|, a
29 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
30 // std::string, if the field is set. |name| is a char* describing the
31 // field.
32 #define APPEND_DELAY(str, delays, field, name) \
33 { \
34 if (delays.has_##field()) \
35 StringAppendF(&str, name "=%" PRId64 " ", delays.field()); \
36 }
37
38 // Appends descriptions of all of the set delays in |delays|, a
39 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
40 // std::string. |prefix| should be a char* containing either "ac" or
41 // "battery".
42 #define APPEND_DELAYS(str, delays, prefix) \
43 { \
44 APPEND_DELAY(str, delays, screen_dim_ms, prefix "_screen_dim_ms"); \
45 APPEND_DELAY(str, delays, screen_off_ms, prefix "_screen_off_ms"); \
46 APPEND_DELAY(str, delays, screen_lock_ms, prefix "_screen_lock_ms"); \
47 APPEND_DELAY(str, delays, idle_warning_ms, prefix "_idle_warning_ms"); \
48 APPEND_DELAY(str, delays, idle_ms, prefix "_idle_ms"); \
49 }
50
51 // Returns the power_manager::PowerManagementPolicy_Action value
52 // corresponding to |action|.
GetProtoAction(PowerPolicyController::Action action)53 power_manager::PowerManagementPolicy_Action GetProtoAction(
54 PowerPolicyController::Action action) {
55 switch (action) {
56 case PowerPolicyController::ACTION_SUSPEND:
57 return power_manager::PowerManagementPolicy_Action_SUSPEND;
58 case PowerPolicyController::ACTION_STOP_SESSION:
59 return power_manager::PowerManagementPolicy_Action_STOP_SESSION;
60 case PowerPolicyController::ACTION_SHUT_DOWN:
61 return power_manager::PowerManagementPolicy_Action_SHUT_DOWN;
62 case PowerPolicyController::ACTION_DO_NOTHING:
63 return power_manager::PowerManagementPolicy_Action_DO_NOTHING;
64 default:
65 NOTREACHED() << "Unhandled action " << action;
66 return power_manager::PowerManagementPolicy_Action_DO_NOTHING;
67 }
68 }
69
70 // Returns false if |use_audio_activity| and |use_audio_activity| prevent wake
71 // locks created for |reason| from being honored or true otherwise.
IsWakeLockReasonHonored(PowerPolicyController::WakeLockReason reason,bool use_audio_activity,bool use_video_activity)72 bool IsWakeLockReasonHonored(PowerPolicyController::WakeLockReason reason,
73 bool use_audio_activity,
74 bool use_video_activity) {
75 if (reason == PowerPolicyController::REASON_AUDIO_PLAYBACK &&
76 !use_audio_activity)
77 return false;
78 if (reason == PowerPolicyController::REASON_VIDEO_PLAYBACK &&
79 !use_video_activity)
80 return false;
81 return true;
82 }
83
84 // Adjusts |delays| appropriately for backlights having been forced off by
85 // tapping the power button. The idle delay is shortened to (idle - screen off),
86 // and the idle warning delay (if set) is shortened to (idle warning - screen
87 // off). All other delays are cleared, as the display should already be off.
AdjustDelaysForBacklightsForcedOff(power_manager::PowerManagementPolicy::Delays * delays)88 void AdjustDelaysForBacklightsForcedOff(
89 power_manager::PowerManagementPolicy::Delays* delays) {
90 if (delays->screen_off_ms() <= 0 || delays->idle_ms() <= 0)
91 return;
92
93 // The screen-off delay should always be shorter than or equal to the idle
94 // delay, but we clamp the value just in case the prefs don't adhere to this.
95 // powerd only honors delays that are greater than 0, so use 1 ms as the min.
96 const int64_t idle_ms = std::max(delays->idle_ms() - delays->screen_off_ms(),
97 static_cast<int64_t>(1));
98 const int64_t warn_ms =
99 delays->idle_warning_ms() > 0
100 ? std::max(delays->idle_warning_ms() - delays->screen_off_ms(),
101 static_cast<int64_t>(1))
102 : -1;
103
104 delays->Clear();
105 delays->set_idle_ms(idle_ms);
106 if (warn_ms > 0)
107 delays->set_idle_warning_ms(warn_ms);
108 }
109
110 // Saves appropriate value to |week_day| and returns true if there is mapping
111 // between week day string and enum value.
GetWeekDayFromString(const std::string & week_day_str,power_manager::PowerManagementPolicy::WeekDay * week_day)112 bool GetWeekDayFromString(
113 const std::string& week_day_str,
114 power_manager::PowerManagementPolicy::WeekDay* week_day) {
115 DCHECK(week_day);
116 if (week_day_str == "MONDAY") {
117 *week_day = power_manager::PowerManagementPolicy::MONDAY;
118 } else if (week_day_str == "TUESDAY") {
119 *week_day = power_manager::PowerManagementPolicy::TUESDAY;
120 } else if (week_day_str == "WEDNESDAY") {
121 *week_day = power_manager::PowerManagementPolicy::WEDNESDAY;
122 } else if (week_day_str == "THURSDAY") {
123 *week_day = power_manager::PowerManagementPolicy::THURSDAY;
124 } else if (week_day_str == "FRIDAY") {
125 *week_day = power_manager::PowerManagementPolicy::FRIDAY;
126 } else if (week_day_str == "SATURDAY") {
127 *week_day = power_manager::PowerManagementPolicy::SATURDAY;
128 } else if (week_day_str == "SUNDAY") {
129 *week_day = power_manager::PowerManagementPolicy::SUNDAY;
130 } else {
131 return false;
132 }
133 return true;
134 }
135
136 } // namespace
137
138 PowerPolicyController::PrefValues::PrefValues() = default;
139 PowerPolicyController::PrefValues::~PrefValues() = default;
140
141 const int PowerPolicyController::kScreenLockAfterOffDelayMs = 10000; // 10 sec.
142 const char PowerPolicyController::kPrefsReason[] = "Prefs";
143
144 // static
GetPeakShiftDayConfigs(const base::DictionaryValue & value,std::vector<PeakShiftDayConfig> * configs_out)145 bool PowerPolicyController::GetPeakShiftDayConfigs(
146 const base::DictionaryValue& value,
147 std::vector<PeakShiftDayConfig>* configs_out) {
148 DCHECK(configs_out);
149 configs_out->clear();
150
151 const base::Value* entries =
152 value.FindKeyOfType({"entries"}, base::Value::Type::LIST);
153 if (!entries) {
154 return false;
155 }
156
157 for (const base::Value& item : entries->GetList()) {
158 const base::Value* week_day_value =
159 item.FindKeyOfType({"day"}, base::Value::Type::STRING);
160 const base::Value* start_time_hour =
161 item.FindPathOfType({"start_time", "hour"}, base::Value::Type::INTEGER);
162 const base::Value* start_time_minute = item.FindPathOfType(
163 {"start_time", "minute"}, base::Value::Type::INTEGER);
164 const base::Value* end_time_hour =
165 item.FindPathOfType({"end_time", "hour"}, base::Value::Type::INTEGER);
166 const base::Value* end_time_minute =
167 item.FindPathOfType({"end_time", "minute"}, base::Value::Type::INTEGER);
168 const base::Value* charge_start_time_hour = item.FindPathOfType(
169 {"charge_start_time", "hour"}, base::Value::Type::INTEGER);
170 const base::Value* charge_start_time_minute = item.FindPathOfType(
171 {"charge_start_time", "minute"}, base::Value::Type::INTEGER);
172
173 power_manager::PowerManagementPolicy::WeekDay week_day_enum;
174 if (!week_day_value ||
175 !GetWeekDayFromString(week_day_value->GetString(), &week_day_enum) ||
176 !start_time_hour || !start_time_minute || !end_time_hour ||
177 !end_time_minute || !charge_start_time_hour ||
178 !charge_start_time_minute) {
179 return false;
180 }
181
182 PeakShiftDayConfig config;
183 config.set_day(week_day_enum);
184 config.mutable_start_time()->set_hour(start_time_hour->GetInt());
185 config.mutable_start_time()->set_minute(start_time_minute->GetInt());
186 config.mutable_end_time()->set_hour(end_time_hour->GetInt());
187 config.mutable_end_time()->set_minute(end_time_minute->GetInt());
188 config.mutable_charge_start_time()->set_hour(
189 charge_start_time_hour->GetInt());
190 config.mutable_charge_start_time()->set_minute(
191 charge_start_time_minute->GetInt());
192
193 configs_out->push_back(std::move(config));
194 }
195
196 return true;
197 }
198
199 // static
GetAdvancedBatteryChargeModeDayConfigs(const base::DictionaryValue & value,std::vector<AdvancedBatteryChargeModeDayConfig> * configs_out)200 bool PowerPolicyController::GetAdvancedBatteryChargeModeDayConfigs(
201 const base::DictionaryValue& value,
202 std::vector<AdvancedBatteryChargeModeDayConfig>* configs_out) {
203 DCHECK(configs_out);
204 configs_out->clear();
205
206 const base::Value* entries =
207 value.FindKeyOfType({"entries"}, base::Value::Type::LIST);
208 if (!entries) {
209 return false;
210 }
211
212 for (const base::Value& item : entries->GetList()) {
213 const base::Value* week_day_value =
214 item.FindKeyOfType({"day"}, base::Value::Type::STRING);
215 const base::Value* charge_start_time_hour = item.FindPathOfType(
216 {"charge_start_time", "hour"}, base::Value::Type::INTEGER);
217 const base::Value* charge_start_time_minute = item.FindPathOfType(
218 {"charge_start_time", "minute"}, base::Value::Type::INTEGER);
219 const base::Value* charge_end_time_hour = item.FindPathOfType(
220 {"charge_end_time", "hour"}, base::Value::Type::INTEGER);
221 const base::Value* charge_end_time_minute = item.FindPathOfType(
222 {"charge_end_time", "minute"}, base::Value::Type::INTEGER);
223
224 power_manager::PowerManagementPolicy::WeekDay week_day_enum;
225 if (!week_day_value ||
226 !GetWeekDayFromString(week_day_value->GetString(), &week_day_enum) ||
227 !charge_start_time_hour || !charge_start_time_minute ||
228 !charge_end_time_hour || !charge_end_time_minute) {
229 return false;
230 }
231
232 AdvancedBatteryChargeModeDayConfig config;
233 config.set_day(week_day_enum);
234 config.mutable_charge_start_time()->set_hour(
235 charge_start_time_hour->GetInt());
236 config.mutable_charge_start_time()->set_minute(
237 charge_start_time_minute->GetInt());
238 config.mutable_charge_end_time()->set_hour(charge_end_time_hour->GetInt());
239 config.mutable_charge_end_time()->set_minute(
240 charge_end_time_minute->GetInt());
241
242 configs_out->push_back(std::move(config));
243 }
244
245 return true;
246 }
247
248 // static
GetBatteryChargeModeFromInteger(int mode,power_manager::PowerManagementPolicy::BatteryChargeMode::Mode * mode_out)249 bool PowerPolicyController::GetBatteryChargeModeFromInteger(
250 int mode,
251 power_manager::PowerManagementPolicy::BatteryChargeMode::Mode* mode_out) {
252 DCHECK(mode_out);
253 switch (mode) {
254 case 1:
255 *mode_out =
256 power_manager::PowerManagementPolicy::BatteryChargeMode::STANDARD;
257 return true;
258 case 2:
259 *mode_out = power_manager::PowerManagementPolicy::BatteryChargeMode::
260 EXPRESS_CHARGE;
261 return true;
262 case 3:
263 *mode_out = power_manager::PowerManagementPolicy::BatteryChargeMode::
264 PRIMARILY_AC_USE;
265 return true;
266 case 4:
267 *mode_out =
268 power_manager::PowerManagementPolicy::BatteryChargeMode::ADAPTIVE;
269 return true;
270 case 5:
271 *mode_out =
272 power_manager::PowerManagementPolicy::BatteryChargeMode::CUSTOM;
273 return true;
274 default:
275 return false;
276 }
277 }
278
279 // static
GetPolicyDebugString(const power_manager::PowerManagementPolicy & policy)280 std::string PowerPolicyController::GetPolicyDebugString(
281 const power_manager::PowerManagementPolicy& policy) {
282 std::string str;
283 if (policy.has_ac_delays())
284 APPEND_DELAYS(str, policy.ac_delays(), "ac");
285 if (policy.has_battery_delays())
286 APPEND_DELAYS(str, policy.battery_delays(), "battery");
287 if (policy.has_ac_idle_action())
288 StringAppendF(&str, "ac_idle=%d ", policy.ac_idle_action());
289 if (policy.has_battery_idle_action())
290 StringAppendF(&str, "battery_idle=%d ", policy.battery_idle_action());
291 if (policy.has_lid_closed_action())
292 StringAppendF(&str, "lid_closed=%d ", policy.lid_closed_action());
293 if (policy.has_screen_wake_lock())
294 StringAppendF(&str, "screen_wake_lock=%d ", policy.screen_wake_lock());
295 if (policy.has_dim_wake_lock())
296 StringAppendF(&str, "dim_wake_lock=%d ", policy.dim_wake_lock());
297 if (policy.has_system_wake_lock())
298 StringAppendF(&str, "system_wake_lock=%d ", policy.system_wake_lock());
299 if (policy.has_use_audio_activity())
300 StringAppendF(&str, "use_audio=%d ", policy.use_audio_activity());
301 if (policy.has_use_video_activity())
302 StringAppendF(&str, "use_video=%d ", policy.use_audio_activity());
303 if (policy.has_ac_brightness_percent())
304 StringAppendF(&str, "ac_brightness_percent=%f ",
305 policy.ac_brightness_percent());
306 if (policy.has_battery_brightness_percent()) {
307 StringAppendF(&str, "battery_brightness_percent=%f ",
308 policy.battery_brightness_percent());
309 }
310 if (policy.has_presentation_screen_dim_delay_factor()) {
311 StringAppendF(&str, "presentation_screen_dim_delay_factor=%f ",
312 policy.presentation_screen_dim_delay_factor());
313 }
314 if (policy.has_user_activity_screen_dim_delay_factor()) {
315 StringAppendF(&str, "user_activity_screen_dim_delay_factor=%f ",
316 policy.user_activity_screen_dim_delay_factor());
317 }
318 if (policy.has_wait_for_initial_user_activity()) {
319 StringAppendF(&str, "wait_for_initial_user_activity=%d ",
320 policy.wait_for_initial_user_activity());
321 }
322 if (policy.has_force_nonzero_brightness_for_user_activity()) {
323 StringAppendF(&str, "force_nonzero_brightness_for_user_activity=%d ",
324 policy.force_nonzero_brightness_for_user_activity());
325 }
326
327 str += GetPeakShiftPolicyDebugString(policy);
328
329 str += GetAdvancedBatteryChargeModePolicyDebugString(policy);
330
331 if (policy.has_battery_charge_mode()) {
332 if (policy.battery_charge_mode().has_mode()) {
333 StringAppendF(&str, "battery_charge_mode=%d ",
334 policy.battery_charge_mode().mode());
335 }
336 if (policy.battery_charge_mode().has_custom_charge_start()) {
337 StringAppendF(&str, "custom_charge_start=%d ",
338 policy.battery_charge_mode().custom_charge_start());
339 }
340 if (policy.battery_charge_mode().has_custom_charge_stop()) {
341 StringAppendF(&str, "custom_charge_stop=%d ",
342 policy.battery_charge_mode().custom_charge_stop());
343 }
344 }
345
346 if (policy.has_boot_on_ac()) {
347 StringAppendF(&str, "boot_on_ac=%d ", policy.boot_on_ac());
348 }
349
350 if (policy.has_usb_power_share()) {
351 StringAppendF(&str, "usb_power_share=%d ", policy.usb_power_share());
352 }
353
354 if (policy.has_reason())
355 StringAppendF(&str, "reason=\"%s\" ", policy.reason().c_str());
356 base::TrimWhitespaceASCII(str, base::TRIM_TRAILING, &str);
357 return str;
358 }
359
360 // static
GetPeakShiftPolicyDebugString(const power_manager::PowerManagementPolicy & policy)361 std::string PowerPolicyController::GetPeakShiftPolicyDebugString(
362 const power_manager::PowerManagementPolicy& policy) {
363 std::string str;
364 if (policy.has_peak_shift_battery_percent_threshold()) {
365 StringAppendF(&str, "peak_shift_battery_threshold=%d ",
366 policy.peak_shift_battery_percent_threshold());
367 }
368 if (policy.peak_shift_day_configs_size() == 0) {
369 return str;
370 }
371
372 std::vector<std::string> list;
373 for (auto config : policy.peak_shift_day_configs()) {
374 list.push_back(base::StringPrintf(
375 "{day=%d start_time=%d:%02d end_time=%d:%02d "
376 "charge_start_time=%d:%02d}",
377 config.day(), config.start_time().hour(), config.start_time().minute(),
378 config.end_time().hour(), config.end_time().minute(),
379 config.charge_start_time().hour(),
380 config.charge_start_time().minute()));
381 }
382 StringAppendF(&str, "peak_shift_day_config=[%s] ",
383 base::JoinString(list, " ").c_str());
384 return str;
385 }
386
387 // static
388 std::string
GetAdvancedBatteryChargeModePolicyDebugString(const power_manager::PowerManagementPolicy & policy)389 PowerPolicyController::GetAdvancedBatteryChargeModePolicyDebugString(
390 const power_manager::PowerManagementPolicy& policy) {
391 if (policy.advanced_battery_charge_mode_day_configs_size() == 0) {
392 return "";
393 }
394
395 std::vector<std::string> list;
396 for (auto config : policy.advanced_battery_charge_mode_day_configs()) {
397 list.push_back(base::StringPrintf(
398 "{day=%d charge_start_time=%d:%02d charge_end_time=%d:%02d}",
399 config.day(), config.charge_start_time().hour(),
400 config.charge_start_time().minute(), config.charge_end_time().hour(),
401 config.charge_end_time().minute()));
402 }
403 return base::StringPrintf("advanced_battery_charge_mode_day_config=[%s] ",
404 base::JoinString(list, " ").c_str());
405 }
406
407 // static
Initialize(PowerManagerClient * client)408 void PowerPolicyController::Initialize(PowerManagerClient* client) {
409 DCHECK(!IsInitialized());
410 g_power_policy_controller = new PowerPolicyController(client);
411 }
412
413 // static
IsInitialized()414 bool PowerPolicyController::IsInitialized() {
415 return g_power_policy_controller;
416 }
417
418 // static
Shutdown()419 void PowerPolicyController::Shutdown() {
420 DCHECK(IsInitialized());
421 delete g_power_policy_controller;
422 g_power_policy_controller = nullptr;
423 }
424
425 // static
Get()426 PowerPolicyController* PowerPolicyController::Get() {
427 DCHECK(IsInitialized());
428 return g_power_policy_controller;
429 }
430
ApplyPrefs(const PrefValues & values)431 void PowerPolicyController::ApplyPrefs(const PrefValues& values) {
432 prefs_policy_.Clear();
433
434 power_manager::PowerManagementPolicy::Delays* delays =
435 prefs_policy_.mutable_ac_delays();
436 delays->set_screen_dim_ms(values.ac_screen_dim_delay_ms);
437 delays->set_screen_off_ms(values.ac_screen_off_delay_ms);
438 delays->set_screen_lock_ms(values.ac_screen_lock_delay_ms);
439 delays->set_idle_warning_ms(values.ac_idle_warning_delay_ms);
440 delays->set_idle_ms(values.ac_idle_delay_ms);
441
442 // If auto screen-locking is enabled, ensure that the screen is locked soon
443 // after it's turned off due to user inactivity.
444 int64_t lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs;
445 if (values.enable_auto_screen_lock && delays->screen_off_ms() > 0 &&
446 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) &&
447 lock_ms < delays->idle_ms()) {
448 delays->set_screen_lock_ms(lock_ms);
449 }
450
451 delays = prefs_policy_.mutable_battery_delays();
452 delays->set_screen_dim_ms(values.battery_screen_dim_delay_ms);
453 delays->set_screen_off_ms(values.battery_screen_off_delay_ms);
454 delays->set_screen_lock_ms(values.battery_screen_lock_delay_ms);
455 delays->set_idle_warning_ms(values.battery_idle_warning_delay_ms);
456 delays->set_idle_ms(values.battery_idle_delay_ms);
457
458 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs;
459 if (values.enable_auto_screen_lock && delays->screen_off_ms() > 0 &&
460 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) &&
461 lock_ms < delays->idle_ms()) {
462 delays->set_screen_lock_ms(lock_ms);
463 }
464 auto_screen_lock_enabled_ = values.enable_auto_screen_lock;
465
466 prefs_policy_.set_ac_idle_action(GetProtoAction(values.ac_idle_action));
467 prefs_policy_.set_battery_idle_action(
468 GetProtoAction(values.battery_idle_action));
469 prefs_policy_.set_lid_closed_action(GetProtoAction(values.lid_closed_action));
470 prefs_policy_.set_use_audio_activity(values.use_audio_activity);
471 prefs_policy_.set_use_video_activity(values.use_video_activity);
472
473 if (!per_session_brightness_override_) {
474 if (values.ac_brightness_percent >= 0.0)
475 prefs_policy_.set_ac_brightness_percent(values.ac_brightness_percent);
476 if (values.battery_brightness_percent >= 0.0) {
477 prefs_policy_.set_battery_brightness_percent(
478 values.battery_brightness_percent);
479 }
480 }
481
482 prefs_policy_.set_presentation_screen_dim_delay_factor(
483 values.presentation_screen_dim_delay_factor);
484 prefs_policy_.set_user_activity_screen_dim_delay_factor(
485 values.user_activity_screen_dim_delay_factor);
486
487 prefs_policy_.set_wait_for_initial_user_activity(
488 values.wait_for_initial_user_activity);
489 prefs_policy_.set_force_nonzero_brightness_for_user_activity(
490 values.force_nonzero_brightness_for_user_activity);
491
492 honor_wake_locks_ = values.allow_wake_locks;
493 honor_screen_wake_locks_ =
494 honor_wake_locks_ && values.allow_screen_wake_locks;
495
496 fast_suspend_when_backlights_forced_off_ =
497 values.fast_suspend_when_backlights_forced_off;
498
499 if (values.peak_shift_enabled) {
500 prefs_policy_.set_peak_shift_battery_percent_threshold(
501 values.peak_shift_battery_threshold);
502 *prefs_policy_.mutable_peak_shift_day_configs() = {
503 values.peak_shift_day_configs.begin(),
504 values.peak_shift_day_configs.end()};
505 }
506
507 if (values.advanced_battery_charge_mode_enabled) {
508 *prefs_policy_.mutable_advanced_battery_charge_mode_day_configs() = {
509 values.advanced_battery_charge_mode_day_configs.begin(),
510 values.advanced_battery_charge_mode_day_configs.end()};
511 }
512
513 auto* battery_charge_mode = prefs_policy_.mutable_battery_charge_mode();
514 battery_charge_mode->set_mode(values.battery_charge_mode);
515 if (values.battery_charge_mode ==
516 power_manager::PowerManagementPolicy::BatteryChargeMode::CUSTOM) {
517 battery_charge_mode->set_custom_charge_start(values.custom_charge_start);
518 battery_charge_mode->set_custom_charge_stop(values.custom_charge_stop);
519 }
520
521 prefs_policy_.set_boot_on_ac(values.boot_on_ac);
522
523 prefs_policy_.set_usb_power_share(values.usb_power_share);
524
525 prefs_were_set_ = true;
526 SendCurrentPolicy();
527 }
528
GetMaxPolicyAutoScreenLockDelay()529 base::TimeDelta PowerPolicyController::GetMaxPolicyAutoScreenLockDelay() {
530 if (!prefs_were_set_ || !auto_screen_lock_enabled_) {
531 return base::TimeDelta();
532 }
533 int ac_delay = prefs_policy_.ac_delays().screen_lock_ms();
534 int battery_delay = prefs_policy_.battery_delays().screen_lock_ms();
535 return base::TimeDelta::FromMilliseconds(std::max(ac_delay, battery_delay));
536 }
537
AddScreenWakeLock(WakeLockReason reason,const std::string & description)538 int PowerPolicyController::AddScreenWakeLock(WakeLockReason reason,
539 const std::string& description) {
540 return AddWakeLockInternal(WakeLock::TYPE_SCREEN, reason, description);
541 }
542
AddDimWakeLock(WakeLockReason reason,const std::string & description)543 int PowerPolicyController::AddDimWakeLock(WakeLockReason reason,
544 const std::string& description) {
545 return AddWakeLockInternal(WakeLock::TYPE_DIM, reason, description);
546 }
547
AddSystemWakeLock(WakeLockReason reason,const std::string & description)548 int PowerPolicyController::AddSystemWakeLock(WakeLockReason reason,
549 const std::string& description) {
550 return AddWakeLockInternal(WakeLock::TYPE_SYSTEM, reason, description);
551 }
552
RemoveWakeLock(int id)553 void PowerPolicyController::RemoveWakeLock(int id) {
554 if (!wake_locks_.erase(id))
555 LOG(WARNING) << "Ignoring request to remove nonexistent wake lock " << id;
556 else
557 SendCurrentPolicy();
558 }
559
PowerManagerRestarted()560 void PowerPolicyController::PowerManagerRestarted() {
561 SendCurrentPolicy();
562 }
563
ScreenBrightnessChanged(const power_manager::BacklightBrightnessChange & change)564 void PowerPolicyController::ScreenBrightnessChanged(
565 const power_manager::BacklightBrightnessChange& change) {
566 if (prefs_were_set_ &&
567 (prefs_policy_.has_ac_brightness_percent() ||
568 prefs_policy_.has_battery_brightness_percent()) &&
569 change.cause() ==
570 power_manager::BacklightBrightnessChange_Cause_USER_REQUEST) {
571 per_session_brightness_override_ = true;
572 }
573 }
574
NotifyChromeIsExiting()575 void PowerPolicyController::NotifyChromeIsExiting() {
576 if (chrome_is_exiting_)
577 return;
578 chrome_is_exiting_ = true;
579 SendCurrentPolicy();
580 }
581
HandleBacklightsForcedOffForPowerButton(bool forced_off)582 void PowerPolicyController::HandleBacklightsForcedOffForPowerButton(
583 bool forced_off) {
584 if (forced_off == backlights_forced_off_for_power_button_)
585 return;
586 backlights_forced_off_for_power_button_ = forced_off;
587 SendCurrentPolicy();
588 }
589
SetEncryptionMigrationActive(bool active)590 void PowerPolicyController::SetEncryptionMigrationActive(bool active) {
591 if (encryption_migration_active_ == active)
592 return;
593
594 encryption_migration_active_ = active;
595 SendCurrentPolicy();
596 }
597
PowerPolicyController(PowerManagerClient * client)598 PowerPolicyController::PowerPolicyController(PowerManagerClient* client)
599 : client_(client) {
600 DCHECK(client_);
601 client_->AddObserver(this);
602 }
603
~PowerPolicyController()604 PowerPolicyController::~PowerPolicyController() {
605 client_->RemoveObserver(this);
606 }
607
WakeLock(Type type,WakeLockReason reason,const std::string & description)608 PowerPolicyController::WakeLock::WakeLock(Type type,
609 WakeLockReason reason,
610 const std::string& description)
611 : type(type), reason(reason), description(description) {}
612
613 PowerPolicyController::WakeLock::~WakeLock() = default;
614
AddWakeLockInternal(WakeLock::Type type,WakeLockReason reason,const std::string & description)615 int PowerPolicyController::AddWakeLockInternal(WakeLock::Type type,
616 WakeLockReason reason,
617 const std::string& description) {
618 const int id = next_wake_lock_id_++;
619 wake_locks_.insert(std::make_pair(id, WakeLock(type, reason, description)));
620 SendCurrentPolicy();
621 return id;
622 }
623
SendCurrentPolicy()624 void PowerPolicyController::SendCurrentPolicy() {
625 std::string causes;
626
627 power_manager::PowerManagementPolicy policy = prefs_policy_;
628 if (prefs_were_set_)
629 causes = kPrefsReason;
630
631 // Shorten suspend delays if the backlight is forced off via the power button.
632 if (backlights_forced_off_for_power_button_ &&
633 fast_suspend_when_backlights_forced_off_) {
634 if (policy.ac_idle_action() ==
635 power_manager::PowerManagementPolicy_Action_SUSPEND) {
636 AdjustDelaysForBacklightsForcedOff(policy.mutable_ac_delays());
637 }
638 if (policy.battery_idle_action() ==
639 power_manager::PowerManagementPolicy_Action_SUSPEND) {
640 AdjustDelaysForBacklightsForcedOff(policy.mutable_battery_delays());
641 }
642 }
643
644 if (honor_wake_locks_) {
645 bool have_screen_wake_locks = false;
646 bool have_dim_wake_locks = false;
647 bool have_system_wake_locks = false;
648 for (const auto& it : wake_locks_) {
649 // Skip audio and video locks that should be ignored due to policy.
650 if (!IsWakeLockReasonHonored(it.second.reason,
651 policy.use_audio_activity(),
652 policy.use_video_activity()))
653 continue;
654
655 switch (it.second.type) {
656 case WakeLock::TYPE_SCREEN:
657 have_screen_wake_locks = true;
658 break;
659 case WakeLock::TYPE_DIM:
660 have_dim_wake_locks = true;
661 break;
662 case WakeLock::TYPE_SYSTEM:
663 have_system_wake_locks = true;
664 break;
665 }
666 causes += (causes.empty() ? "" : ", ") + it.second.description;
667 }
668
669 // Downgrade full-brightness and dimmed-brightness locks to system locks if
670 // wake locks aren't allowed to keep the screen on.
671 if (!honor_screen_wake_locks_ &&
672 (have_screen_wake_locks || have_dim_wake_locks)) {
673 have_system_wake_locks = true;
674 have_screen_wake_locks = false;
675 have_dim_wake_locks = false;
676 }
677
678 if (have_screen_wake_locks)
679 policy.set_screen_wake_lock(true);
680 if (have_dim_wake_locks)
681 policy.set_dim_wake_lock(true);
682 if (have_system_wake_locks)
683 policy.set_system_wake_lock(true);
684 }
685
686 if (encryption_migration_active_ &&
687 policy.lid_closed_action() !=
688 power_manager::PowerManagementPolicy_Action_DO_NOTHING) {
689 policy.set_lid_closed_action(
690 power_manager::PowerManagementPolicy_Action_SUSPEND);
691 causes +=
692 std::string((causes.empty() ? "" : ", ")) + "encryption migration";
693 }
694
695 // To avoid a race in the case where the user asks Chrome to sign out
696 // and then immediately closes the lid, override the lid-closed action
697 // so the system will stay awake while Chrome is exiting. When Chrome
698 // restarts to display the login screen, it will send an updated
699 // policy that powerd can act on.
700 if (chrome_is_exiting_ &&
701 (!policy.has_lid_closed_action() ||
702 policy.lid_closed_action() ==
703 power_manager::PowerManagementPolicy_Action_SUSPEND ||
704 policy.lid_closed_action() ==
705 power_manager::PowerManagementPolicy_Action_SHUT_DOWN)) {
706 policy.set_lid_closed_action(
707 power_manager::PowerManagementPolicy_Action_DO_NOTHING);
708 }
709
710 if (!causes.empty())
711 policy.set_reason(causes);
712 client_->SetPolicy(policy);
713 }
714
715 } // namespace chromeos
716