Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromeos / dbus / power_policy_controller.cc
blobe93427552725c3e8b495773ddfb233a98b21510b
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.
5 #include "chromeos/dbus/power_policy_controller.h"
7 #include <utility>
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
14 namespace chromeos {
16 namespace {
18 PowerPolicyController* g_power_policy_controller = nullptr;
20 // Appends a description of |field|, a field within |delays|, a
21 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
22 // std::string, if the field is set. |name| is a char* describing the
23 // field.
24 #define APPEND_DELAY(str, delays, field, name) \
25 { \
26 if (delays.has_##field()) \
27 str += base::StringPrintf(name "=%" PRId64 " ", delays.field()); \
30 // Appends descriptions of all of the set delays in |delays|, a
31 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
32 // std::string. |prefix| should be a char* containing either "ac" or
33 // "battery".
34 #define APPEND_DELAYS(str, delays, prefix) \
35 { \
36 APPEND_DELAY(str, delays, screen_dim_ms, prefix "_screen_dim_ms"); \
37 APPEND_DELAY(str, delays, screen_off_ms, prefix "_screen_off_ms"); \
38 APPEND_DELAY(str, delays, screen_lock_ms, prefix "_screen_lock_ms"); \
39 APPEND_DELAY(str, delays, idle_warning_ms, prefix "_idle_warning_ms"); \
40 APPEND_DELAY(str, delays, idle_ms, prefix "_idle_ms"); \
43 // Returns the power_manager::PowerManagementPolicy_Action value
44 // corresponding to |action|.
45 power_manager::PowerManagementPolicy_Action GetProtoAction(
46 PowerPolicyController::Action action) {
47 switch (action) {
48 case PowerPolicyController::ACTION_SUSPEND:
49 return power_manager::PowerManagementPolicy_Action_SUSPEND;
50 case PowerPolicyController::ACTION_STOP_SESSION:
51 return power_manager::PowerManagementPolicy_Action_STOP_SESSION;
52 case PowerPolicyController::ACTION_SHUT_DOWN:
53 return power_manager::PowerManagementPolicy_Action_SHUT_DOWN;
54 case PowerPolicyController::ACTION_DO_NOTHING:
55 return power_manager::PowerManagementPolicy_Action_DO_NOTHING;
56 default:
57 NOTREACHED() << "Unhandled action " << action;
58 return power_manager::PowerManagementPolicy_Action_DO_NOTHING;
62 // Returns false if |use_audio_activity| and |use_audio_activity| prevent wake
63 // locks created for |reason| from being honored or true otherwise.
64 bool IsWakeLockReasonHonored(PowerPolicyController::WakeLockReason reason,
65 bool use_audio_activity,
66 bool use_video_activity) {
67 if (reason == PowerPolicyController::REASON_AUDIO_PLAYBACK &&
68 !use_audio_activity)
69 return false;
70 if (reason == PowerPolicyController::REASON_VIDEO_PLAYBACK &&
71 !use_video_activity)
72 return false;
73 return true;
76 } // namespace
78 const int PowerPolicyController::kScreenLockAfterOffDelayMs = 10000; // 10 sec.
79 const char PowerPolicyController::kPrefsReason[] = "Prefs";
81 // -1 is interpreted as "unset" by powerd, resulting in powerd's default
82 // delays being used instead. There are no similarly-interpreted values
83 // for the other fields, unfortunately (but the constructor-assigned values
84 // will only reach powerd if Chrome messes up and forgets to override them
85 // with the pref-assigned values).
86 PowerPolicyController::PrefValues::PrefValues()
87 : ac_screen_dim_delay_ms(-1),
88 ac_screen_off_delay_ms(-1),
89 ac_screen_lock_delay_ms(-1),
90 ac_idle_warning_delay_ms(-1),
91 ac_idle_delay_ms(-1),
92 battery_screen_dim_delay_ms(-1),
93 battery_screen_off_delay_ms(-1),
94 battery_screen_lock_delay_ms(-1),
95 battery_idle_warning_delay_ms(-1),
96 battery_idle_delay_ms(-1),
97 ac_idle_action(ACTION_SUSPEND),
98 battery_idle_action(ACTION_SUSPEND),
99 lid_closed_action(ACTION_SUSPEND),
100 use_audio_activity(true),
101 use_video_activity(true),
102 ac_brightness_percent(-1.0),
103 battery_brightness_percent(-1.0),
104 allow_screen_wake_locks(true),
105 enable_auto_screen_lock(false),
106 presentation_screen_dim_delay_factor(1.0),
107 user_activity_screen_dim_delay_factor(1.0),
108 wait_for_initial_user_activity(false),
109 force_nonzero_brightness_for_user_activity(true) {}
111 // static
112 std::string PowerPolicyController::GetPolicyDebugString(
113 const power_manager::PowerManagementPolicy& policy) {
114 std::string str;
115 if (policy.has_ac_delays())
116 APPEND_DELAYS(str, policy.ac_delays(), "ac");
117 if (policy.has_battery_delays())
118 APPEND_DELAYS(str, policy.battery_delays(), "battery");
119 if (policy.has_ac_idle_action())
120 str += base::StringPrintf("ac_idle=%d ", policy.ac_idle_action());
121 if (policy.has_battery_idle_action())
122 str += base::StringPrintf("battery_idle=%d ", policy.battery_idle_action());
123 if (policy.has_lid_closed_action())
124 str += base::StringPrintf("lid_closed=%d ", policy.lid_closed_action());
125 if (policy.has_use_audio_activity())
126 str += base::StringPrintf("use_audio=%d ", policy.use_audio_activity());
127 if (policy.has_use_video_activity())
128 str += base::StringPrintf("use_video=%d ", policy.use_audio_activity());
129 if (policy.has_ac_brightness_percent()) {
130 str += base::StringPrintf("ac_brightness_percent=%f ",
131 policy.ac_brightness_percent());
133 if (policy.has_battery_brightness_percent()) {
134 str += base::StringPrintf("battery_brightness_percent=%f ",
135 policy.battery_brightness_percent());
137 if (policy.has_presentation_screen_dim_delay_factor()) {
138 str += base::StringPrintf("presentation_screen_dim_delay_factor=%f ",
139 policy.presentation_screen_dim_delay_factor());
141 if (policy.has_user_activity_screen_dim_delay_factor()) {
142 str += base::StringPrintf("user_activity_screen_dim_delay_factor=%f ",
143 policy.user_activity_screen_dim_delay_factor());
145 if (policy.has_wait_for_initial_user_activity()) {
146 str += base::StringPrintf("wait_for_initial_user_activity=%d ",
147 policy.wait_for_initial_user_activity());
149 if (policy.has_force_nonzero_brightness_for_user_activity()) {
150 str += base::StringPrintf("force_nonzero_brightness_for_user_activity=%d ",
151 policy.force_nonzero_brightness_for_user_activity());
153 if (policy.has_reason())
154 str += base::StringPrintf("reason=\"%s\" ", policy.reason().c_str());
155 base::TrimWhitespace(str, base::TRIM_TRAILING, &str);
156 return str;
159 // static
160 void PowerPolicyController::Initialize(PowerManagerClient* client) {
161 DCHECK(!IsInitialized());
162 g_power_policy_controller = new PowerPolicyController(client);
165 // static
166 bool PowerPolicyController::IsInitialized() {
167 return g_power_policy_controller;
170 // static
171 void PowerPolicyController::Shutdown() {
172 DCHECK(IsInitialized());
173 delete g_power_policy_controller;
174 g_power_policy_controller = nullptr;
177 // static
178 PowerPolicyController* PowerPolicyController::Get() {
179 DCHECK(IsInitialized());
180 return g_power_policy_controller;
183 void PowerPolicyController::ApplyPrefs(const PrefValues& values) {
184 prefs_policy_.Clear();
186 power_manager::PowerManagementPolicy::Delays* delays =
187 prefs_policy_.mutable_ac_delays();
188 delays->set_screen_dim_ms(values.ac_screen_dim_delay_ms);
189 delays->set_screen_off_ms(values.ac_screen_off_delay_ms);
190 delays->set_screen_lock_ms(values.ac_screen_lock_delay_ms);
191 delays->set_idle_warning_ms(values.ac_idle_warning_delay_ms);
192 delays->set_idle_ms(values.ac_idle_delay_ms);
194 // If auto screen-locking is enabled, ensure that the screen is locked soon
195 // after it's turned off due to user inactivity.
196 int64 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs;
197 if (values.enable_auto_screen_lock && delays->screen_off_ms() > 0 &&
198 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) &&
199 lock_ms < delays->idle_ms()) {
200 delays->set_screen_lock_ms(lock_ms);
203 delays = prefs_policy_.mutable_battery_delays();
204 delays->set_screen_dim_ms(values.battery_screen_dim_delay_ms);
205 delays->set_screen_off_ms(values.battery_screen_off_delay_ms);
206 delays->set_screen_lock_ms(values.battery_screen_lock_delay_ms);
207 delays->set_idle_warning_ms(values.battery_idle_warning_delay_ms);
208 delays->set_idle_ms(values.battery_idle_delay_ms);
210 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs;
211 if (values.enable_auto_screen_lock && delays->screen_off_ms() > 0 &&
212 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) &&
213 lock_ms < delays->idle_ms()) {
214 delays->set_screen_lock_ms(lock_ms);
217 prefs_policy_.set_ac_idle_action(GetProtoAction(values.ac_idle_action));
218 prefs_policy_.set_battery_idle_action(
219 GetProtoAction(values.battery_idle_action));
220 prefs_policy_.set_lid_closed_action(GetProtoAction(values.lid_closed_action));
221 prefs_policy_.set_use_audio_activity(values.use_audio_activity);
222 prefs_policy_.set_use_video_activity(values.use_video_activity);
223 if (values.ac_brightness_percent >= 0.0)
224 prefs_policy_.set_ac_brightness_percent(values.ac_brightness_percent);
225 if (values.battery_brightness_percent >= 0.0) {
226 prefs_policy_.set_battery_brightness_percent(
227 values.battery_brightness_percent);
229 prefs_policy_.set_presentation_screen_dim_delay_factor(
230 values.presentation_screen_dim_delay_factor);
231 prefs_policy_.set_user_activity_screen_dim_delay_factor(
232 values.user_activity_screen_dim_delay_factor);
233 prefs_policy_.set_wait_for_initial_user_activity(
234 values.wait_for_initial_user_activity);
235 prefs_policy_.set_force_nonzero_brightness_for_user_activity(
236 values.force_nonzero_brightness_for_user_activity);
238 honor_screen_wake_locks_ = values.allow_screen_wake_locks;
240 prefs_were_set_ = true;
241 SendCurrentPolicy();
244 int PowerPolicyController::AddScreenWakeLock(WakeLockReason reason,
245 const std::string& description) {
246 return AddWakeLockInternal(WakeLock::TYPE_SCREEN, reason, description);
249 int PowerPolicyController::AddSystemWakeLock(WakeLockReason reason,
250 const std::string& description) {
251 return AddWakeLockInternal(WakeLock::TYPE_SYSTEM, reason, description);
254 void PowerPolicyController::RemoveWakeLock(int id) {
255 if (!wake_locks_.erase(id))
256 LOG(WARNING) << "Ignoring request to remove nonexistent wake lock " << id;
257 else
258 SendCurrentPolicy();
261 void PowerPolicyController::PowerManagerRestarted() {
262 SendCurrentPolicy();
265 PowerPolicyController::PowerPolicyController(PowerManagerClient* client)
266 : client_(client),
267 prefs_were_set_(false),
268 honor_screen_wake_locks_(true),
269 next_wake_lock_id_(1) {
270 DCHECK(client_);
271 client_->AddObserver(this);
274 PowerPolicyController::~PowerPolicyController() {
275 client_->RemoveObserver(this);
278 PowerPolicyController::WakeLock::WakeLock(Type type,
279 WakeLockReason reason,
280 const std::string& description)
281 : type(type), reason(reason), description(description) {
284 PowerPolicyController::WakeLock::~WakeLock() {
287 int PowerPolicyController::AddWakeLockInternal(WakeLock::Type type,
288 WakeLockReason reason,
289 const std::string& description) {
290 const int id = next_wake_lock_id_++;
291 wake_locks_.insert(std::make_pair(id, WakeLock(type, reason, description)));
292 SendCurrentPolicy();
293 return id;
296 void PowerPolicyController::SendCurrentPolicy() {
297 std::string causes;
299 power_manager::PowerManagementPolicy policy = prefs_policy_;
300 if (prefs_were_set_)
301 causes = kPrefsReason;
303 bool have_screen_wake_locks = false;
304 bool have_system_wake_locks = false;
305 for (const auto& it : wake_locks_) {
306 // Skip audio and video locks that should be ignored due to policy.
307 if (!IsWakeLockReasonHonored(it.second.reason, policy.use_audio_activity(),
308 policy.use_video_activity()))
309 continue;
311 switch (it.second.type) {
312 case WakeLock::TYPE_SCREEN:
313 have_screen_wake_locks = true;
314 break;
315 case WakeLock::TYPE_SYSTEM:
316 have_system_wake_locks = true;
317 break;
319 causes += (causes.empty() ? "" : ", ") + it.second.description;
322 if (honor_screen_wake_locks_ && have_screen_wake_locks) {
323 policy.mutable_ac_delays()->set_screen_dim_ms(0);
324 policy.mutable_ac_delays()->set_screen_off_ms(0);
325 policy.mutable_ac_delays()->set_screen_lock_ms(0);
326 policy.mutable_battery_delays()->set_screen_dim_ms(0);
327 policy.mutable_battery_delays()->set_screen_off_ms(0);
328 policy.mutable_battery_delays()->set_screen_lock_ms(0);
331 if (have_screen_wake_locks || have_system_wake_locks) {
332 if (!policy.has_ac_idle_action() || policy.ac_idle_action() ==
333 power_manager::PowerManagementPolicy_Action_SUSPEND) {
334 policy.set_ac_idle_action(
335 power_manager::PowerManagementPolicy_Action_DO_NOTHING);
337 if (!policy.has_battery_idle_action() || policy.battery_idle_action() ==
338 power_manager::PowerManagementPolicy_Action_SUSPEND) {
339 policy.set_battery_idle_action(
340 power_manager::PowerManagementPolicy_Action_DO_NOTHING);
344 if (!causes.empty())
345 policy.set_reason(causes);
346 client_->SetPolicy(policy);
349 } // namespace chromeos