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 "base/format_macros.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "chromeos/dbus/dbus_thread_manager.h"
17 // Appends a description of |field|, a field within |delays|, a
18 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
19 // std::string, if the field is set. |name| is a char* describing the
21 #define APPEND_DELAY(str, delays, field, name) \
23 if (delays.has_##field()) \
24 str += base::StringPrintf(name "=%" PRId64 " ", delays.field()); \
27 // Appends descriptions of all of the set delays in |delays|, a
28 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
29 // std::string. |prefix| should be a char* containing either "ac" or
31 #define APPEND_DELAYS(str, delays, prefix) \
33 APPEND_DELAY(str, delays, screen_dim_ms, prefix "_screen_dim_ms"); \
34 APPEND_DELAY(str, delays, screen_off_ms, prefix "_screen_off_ms"); \
35 APPEND_DELAY(str, delays, screen_lock_ms, prefix "_screen_lock_ms"); \
36 APPEND_DELAY(str, delays, idle_warning_ms, prefix "_idle_warning_ms"); \
37 APPEND_DELAY(str, delays, idle_ms, prefix "_idle_ms"); \
40 // Returns the power_manager::PowerManagementPolicy_Action value
41 // corresponding to |action|.
42 power_manager::PowerManagementPolicy_Action
GetProtoAction(
43 PowerPolicyController::Action action
) {
45 case PowerPolicyController::ACTION_SUSPEND
:
46 return power_manager::PowerManagementPolicy_Action_SUSPEND
;
47 case PowerPolicyController::ACTION_STOP_SESSION
:
48 return power_manager::PowerManagementPolicy_Action_STOP_SESSION
;
49 case PowerPolicyController::ACTION_SHUT_DOWN
:
50 return power_manager::PowerManagementPolicy_Action_SHUT_DOWN
;
51 case PowerPolicyController::ACTION_DO_NOTHING
:
52 return power_manager::PowerManagementPolicy_Action_DO_NOTHING
;
54 NOTREACHED() << "Unhandled action " << action
;
55 return power_manager::PowerManagementPolicy_Action_DO_NOTHING
;
61 const int PowerPolicyController::kScreenLockAfterOffDelayMs
= 10000; // 10 sec.
63 // -1 is interpreted as "unset" by powerd, resulting in powerd's default
64 // delays being used instead. There are no similarly-interpreted values
65 // for the other fields, unfortunately (but the constructor-assigned values
66 // will only reach powerd if Chrome messes up and forgets to override them
67 // with the pref-assigned values).
68 PowerPolicyController::PrefValues::PrefValues()
69 : ac_screen_dim_delay_ms(-1),
70 ac_screen_off_delay_ms(-1),
71 ac_screen_lock_delay_ms(-1),
72 ac_idle_warning_delay_ms(-1),
74 battery_screen_dim_delay_ms(-1),
75 battery_screen_off_delay_ms(-1),
76 battery_screen_lock_delay_ms(-1),
77 battery_idle_warning_delay_ms(-1),
78 battery_idle_delay_ms(-1),
79 ac_idle_action(ACTION_SUSPEND
),
80 battery_idle_action(ACTION_SUSPEND
),
81 lid_closed_action(ACTION_SUSPEND
),
82 use_audio_activity(true),
83 use_video_activity(true),
84 ac_brightness_percent(-1.0),
85 battery_brightness_percent(-1.0),
86 allow_screen_wake_locks(true),
87 enable_auto_screen_lock(false),
88 presentation_screen_dim_delay_factor(1.0),
89 user_activity_screen_dim_delay_factor(1.0),
90 wait_for_initial_user_activity(false) {}
93 std::string
PowerPolicyController::GetPolicyDebugString(
94 const power_manager::PowerManagementPolicy
& policy
) {
96 if (policy
.has_ac_delays())
97 APPEND_DELAYS(str
, policy
.ac_delays(), "ac");
98 if (policy
.has_battery_delays())
99 APPEND_DELAYS(str
, policy
.battery_delays(), "battery");
100 if (policy
.has_ac_idle_action())
101 str
+= base::StringPrintf("ac_idle=%d ", policy
.ac_idle_action());
102 if (policy
.has_battery_idle_action())
103 str
+= base::StringPrintf("battery_idle=%d ", policy
.battery_idle_action());
104 if (policy
.has_lid_closed_action())
105 str
+= base::StringPrintf("lid_closed=%d ", policy
.lid_closed_action());
106 if (policy
.has_use_audio_activity())
107 str
+= base::StringPrintf("use_audio=%d ", policy
.use_audio_activity());
108 if (policy
.has_use_video_activity())
109 str
+= base::StringPrintf("use_video=%d ", policy
.use_audio_activity());
110 if (policy
.has_ac_brightness_percent()) {
111 str
+= base::StringPrintf("ac_brightness_percent=%f ",
112 policy
.ac_brightness_percent());
114 if (policy
.has_battery_brightness_percent()) {
115 str
+= base::StringPrintf("battery_brightness_percent=%f ",
116 policy
.battery_brightness_percent());
118 if (policy
.has_presentation_screen_dim_delay_factor()) {
119 str
+= base::StringPrintf("presentation_screen_dim_delay_factor=%f ",
120 policy
.presentation_screen_dim_delay_factor());
122 if (policy
.has_user_activity_screen_dim_delay_factor()) {
123 str
+= base::StringPrintf("user_activity_screen_dim_delay_factor=%f ",
124 policy
.user_activity_screen_dim_delay_factor());
126 if (policy
.has_wait_for_initial_user_activity()) {
127 str
+= base::StringPrintf("wait_for_initial_user_activity=%d ",
128 policy
.wait_for_initial_user_activity());
130 if (policy
.has_reason())
131 str
+= base::StringPrintf("reason=\"%s\" ", policy
.reason().c_str());
132 base::TrimWhitespace(str
, base::TRIM_TRAILING
, &str
);
136 PowerPolicyController::PowerPolicyController()
138 prefs_were_set_(false),
139 honor_screen_wake_locks_(true),
140 next_wake_lock_id_(1) {
143 PowerPolicyController::~PowerPolicyController() {
145 client_
->RemoveObserver(this);
150 void PowerPolicyController::Init(DBusThreadManager
* manager
) {
151 client_
= manager
->GetPowerManagerClient();
152 client_
->AddObserver(this);
155 void PowerPolicyController::ApplyPrefs(const PrefValues
& values
) {
156 prefs_policy_
.Clear();
158 power_manager::PowerManagementPolicy::Delays
* delays
=
159 prefs_policy_
.mutable_ac_delays();
160 delays
->set_screen_dim_ms(values
.ac_screen_dim_delay_ms
);
161 delays
->set_screen_off_ms(values
.ac_screen_off_delay_ms
);
162 delays
->set_screen_lock_ms(values
.ac_screen_lock_delay_ms
);
163 delays
->set_idle_warning_ms(values
.ac_idle_warning_delay_ms
);
164 delays
->set_idle_ms(values
.ac_idle_delay_ms
);
166 // If auto screen-locking is enabled, ensure that the screen is locked soon
167 // after it's turned off due to user inactivity.
168 int64 lock_ms
= delays
->screen_off_ms() + kScreenLockAfterOffDelayMs
;
169 if (values
.enable_auto_screen_lock
&& delays
->screen_off_ms() > 0 &&
170 (delays
->screen_lock_ms() <= 0 || lock_ms
< delays
->screen_lock_ms()) &&
171 lock_ms
< delays
->idle_ms()) {
172 delays
->set_screen_lock_ms(lock_ms
);
175 delays
= prefs_policy_
.mutable_battery_delays();
176 delays
->set_screen_dim_ms(values
.battery_screen_dim_delay_ms
);
177 delays
->set_screen_off_ms(values
.battery_screen_off_delay_ms
);
178 delays
->set_screen_lock_ms(values
.battery_screen_lock_delay_ms
);
179 delays
->set_idle_warning_ms(values
.battery_idle_warning_delay_ms
);
180 delays
->set_idle_ms(values
.battery_idle_delay_ms
);
182 lock_ms
= delays
->screen_off_ms() + kScreenLockAfterOffDelayMs
;
183 if (values
.enable_auto_screen_lock
&& delays
->screen_off_ms() > 0 &&
184 (delays
->screen_lock_ms() <= 0 || lock_ms
< delays
->screen_lock_ms()) &&
185 lock_ms
< delays
->idle_ms()) {
186 delays
->set_screen_lock_ms(lock_ms
);
189 prefs_policy_
.set_ac_idle_action(GetProtoAction(values
.ac_idle_action
));
190 prefs_policy_
.set_battery_idle_action(
191 GetProtoAction(values
.battery_idle_action
));
192 prefs_policy_
.set_lid_closed_action(GetProtoAction(values
.lid_closed_action
));
193 prefs_policy_
.set_use_audio_activity(values
.use_audio_activity
);
194 prefs_policy_
.set_use_video_activity(values
.use_video_activity
);
195 if (values
.ac_brightness_percent
>= 0.0)
196 prefs_policy_
.set_ac_brightness_percent(values
.ac_brightness_percent
);
197 if (values
.battery_brightness_percent
>= 0.0) {
198 prefs_policy_
.set_battery_brightness_percent(
199 values
.battery_brightness_percent
);
201 prefs_policy_
.set_presentation_screen_dim_delay_factor(
202 values
.presentation_screen_dim_delay_factor
);
203 prefs_policy_
.set_user_activity_screen_dim_delay_factor(
204 values
.user_activity_screen_dim_delay_factor
);
205 prefs_policy_
.set_wait_for_initial_user_activity(
206 values
.wait_for_initial_user_activity
);
208 honor_screen_wake_locks_
= values
.allow_screen_wake_locks
;
210 prefs_were_set_
= true;
214 int PowerPolicyController::AddScreenWakeLock(const std::string
& reason
) {
215 int id
= next_wake_lock_id_
++;
216 screen_wake_locks_
[id
] = reason
;
221 int PowerPolicyController::AddSystemWakeLock(const std::string
& reason
) {
222 int id
= next_wake_lock_id_
++;
223 system_wake_locks_
[id
] = reason
;
228 void PowerPolicyController::RemoveWakeLock(int id
) {
229 if (!screen_wake_locks_
.erase(id
) && !system_wake_locks_
.erase(id
))
230 LOG(WARNING
) << "Ignoring request to remove nonexistent wake lock " << id
;
235 void PowerPolicyController::PowerManagerRestarted() {
239 void PowerPolicyController::SendCurrentPolicy() {
242 power_manager::PowerManagementPolicy policy
= prefs_policy_
;
246 if (honor_screen_wake_locks_
&& !screen_wake_locks_
.empty()) {
247 policy
.mutable_ac_delays()->set_screen_dim_ms(0);
248 policy
.mutable_ac_delays()->set_screen_off_ms(0);
249 policy
.mutable_ac_delays()->set_screen_lock_ms(0);
250 policy
.mutable_battery_delays()->set_screen_dim_ms(0);
251 policy
.mutable_battery_delays()->set_screen_off_ms(0);
252 policy
.mutable_battery_delays()->set_screen_lock_ms(0);
255 if (!screen_wake_locks_
.empty() || !system_wake_locks_
.empty()) {
256 if (!policy
.has_ac_idle_action() || policy
.ac_idle_action() ==
257 power_manager::PowerManagementPolicy_Action_SUSPEND
) {
258 policy
.set_ac_idle_action(
259 power_manager::PowerManagementPolicy_Action_DO_NOTHING
);
261 if (!policy
.has_battery_idle_action() || policy
.battery_idle_action() ==
262 power_manager::PowerManagementPolicy_Action_SUSPEND
) {
263 policy
.set_battery_idle_action(
264 power_manager::PowerManagementPolicy_Action_DO_NOTHING
);
268 for (WakeLockMap::const_iterator it
= screen_wake_locks_
.begin();
269 it
!= screen_wake_locks_
.end(); ++it
) {
270 reason
+= (reason
.empty() ? "" : ", ") + it
->second
;
272 for (WakeLockMap::const_iterator it
= system_wake_locks_
.begin();
273 it
!= system_wake_locks_
.end(); ++it
) {
274 reason
+= (reason
.empty() ? "" : ", ") + it
->second
;
278 policy
.set_reason(reason
);
279 client_
->SetPolicy(policy
);
282 } // namespace chromeos