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