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"
16 PowerPolicyController
* g_power_policy_controller
= nullptr;
18 // Appends a description of |field|, a field within |delays|, a
19 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
20 // std::string, if the field is set. |name| is a char* describing the
22 #define APPEND_DELAY(str, delays, field, name) \
24 if (delays.has_##field()) \
25 str += base::StringPrintf(name "=%" PRId64 " ", delays.field()); \
28 // Appends descriptions of all of the set delays in |delays|, a
29 // power_manager::PowerManagementPolicy::Delays object, to |str|, an
30 // std::string. |prefix| should be a char* containing either "ac" or
32 #define APPEND_DELAYS(str, delays, prefix) \
34 APPEND_DELAY(str, delays, screen_dim_ms, prefix "_screen_dim_ms"); \
35 APPEND_DELAY(str, delays, screen_off_ms, prefix "_screen_off_ms"); \
36 APPEND_DELAY(str, delays, screen_lock_ms, prefix "_screen_lock_ms"); \
37 APPEND_DELAY(str, delays, idle_warning_ms, prefix "_idle_warning_ms"); \
38 APPEND_DELAY(str, delays, idle_ms, prefix "_idle_ms"); \
41 // Returns the power_manager::PowerManagementPolicy_Action value
42 // corresponding to |action|.
43 power_manager::PowerManagementPolicy_Action
GetProtoAction(
44 PowerPolicyController::Action action
) {
46 case PowerPolicyController::ACTION_SUSPEND
:
47 return power_manager::PowerManagementPolicy_Action_SUSPEND
;
48 case PowerPolicyController::ACTION_STOP_SESSION
:
49 return power_manager::PowerManagementPolicy_Action_STOP_SESSION
;
50 case PowerPolicyController::ACTION_SHUT_DOWN
:
51 return power_manager::PowerManagementPolicy_Action_SHUT_DOWN
;
52 case PowerPolicyController::ACTION_DO_NOTHING
:
53 return power_manager::PowerManagementPolicy_Action_DO_NOTHING
;
55 NOTREACHED() << "Unhandled action " << action
;
56 return power_manager::PowerManagementPolicy_Action_DO_NOTHING
;
62 const int PowerPolicyController::kScreenLockAfterOffDelayMs
= 10000; // 10 sec.
64 // -1 is interpreted as "unset" by powerd, resulting in powerd's default
65 // delays being used instead. There are no similarly-interpreted values
66 // for the other fields, unfortunately (but the constructor-assigned values
67 // will only reach powerd if Chrome messes up and forgets to override them
68 // with the pref-assigned values).
69 PowerPolicyController::PrefValues::PrefValues()
70 : ac_screen_dim_delay_ms(-1),
71 ac_screen_off_delay_ms(-1),
72 ac_screen_lock_delay_ms(-1),
73 ac_idle_warning_delay_ms(-1),
75 battery_screen_dim_delay_ms(-1),
76 battery_screen_off_delay_ms(-1),
77 battery_screen_lock_delay_ms(-1),
78 battery_idle_warning_delay_ms(-1),
79 battery_idle_delay_ms(-1),
80 ac_idle_action(ACTION_SUSPEND
),
81 battery_idle_action(ACTION_SUSPEND
),
82 lid_closed_action(ACTION_SUSPEND
),
83 use_audio_activity(true),
84 use_video_activity(true),
85 ac_brightness_percent(-1.0),
86 battery_brightness_percent(-1.0),
87 allow_screen_wake_locks(true),
88 enable_auto_screen_lock(false),
89 presentation_screen_dim_delay_factor(1.0),
90 user_activity_screen_dim_delay_factor(1.0),
91 wait_for_initial_user_activity(false) {}
94 std::string
PowerPolicyController::GetPolicyDebugString(
95 const power_manager::PowerManagementPolicy
& policy
) {
97 if (policy
.has_ac_delays())
98 APPEND_DELAYS(str
, policy
.ac_delays(), "ac");
99 if (policy
.has_battery_delays())
100 APPEND_DELAYS(str
, policy
.battery_delays(), "battery");
101 if (policy
.has_ac_idle_action())
102 str
+= base::StringPrintf("ac_idle=%d ", policy
.ac_idle_action());
103 if (policy
.has_battery_idle_action())
104 str
+= base::StringPrintf("battery_idle=%d ", policy
.battery_idle_action());
105 if (policy
.has_lid_closed_action())
106 str
+= base::StringPrintf("lid_closed=%d ", policy
.lid_closed_action());
107 if (policy
.has_use_audio_activity())
108 str
+= base::StringPrintf("use_audio=%d ", policy
.use_audio_activity());
109 if (policy
.has_use_video_activity())
110 str
+= base::StringPrintf("use_video=%d ", policy
.use_audio_activity());
111 if (policy
.has_ac_brightness_percent()) {
112 str
+= base::StringPrintf("ac_brightness_percent=%f ",
113 policy
.ac_brightness_percent());
115 if (policy
.has_battery_brightness_percent()) {
116 str
+= base::StringPrintf("battery_brightness_percent=%f ",
117 policy
.battery_brightness_percent());
119 if (policy
.has_presentation_screen_dim_delay_factor()) {
120 str
+= base::StringPrintf("presentation_screen_dim_delay_factor=%f ",
121 policy
.presentation_screen_dim_delay_factor());
123 if (policy
.has_user_activity_screen_dim_delay_factor()) {
124 str
+= base::StringPrintf("user_activity_screen_dim_delay_factor=%f ",
125 policy
.user_activity_screen_dim_delay_factor());
127 if (policy
.has_wait_for_initial_user_activity()) {
128 str
+= base::StringPrintf("wait_for_initial_user_activity=%d ",
129 policy
.wait_for_initial_user_activity());
131 if (policy
.has_reason())
132 str
+= base::StringPrintf("reason=\"%s\" ", policy
.reason().c_str());
133 base::TrimWhitespace(str
, base::TRIM_TRAILING
, &str
);
138 void PowerPolicyController::Initialize(PowerManagerClient
* client
) {
139 DCHECK(!IsInitialized());
140 g_power_policy_controller
= new PowerPolicyController(client
);
144 bool PowerPolicyController::IsInitialized() {
145 return g_power_policy_controller
;
149 void PowerPolicyController::Shutdown() {
150 DCHECK(IsInitialized());
151 delete g_power_policy_controller
;
152 g_power_policy_controller
= nullptr;
156 PowerPolicyController
* PowerPolicyController::Get() {
157 DCHECK(IsInitialized());
158 return g_power_policy_controller
;
161 void PowerPolicyController::ApplyPrefs(const PrefValues
& values
) {
162 prefs_policy_
.Clear();
164 power_manager::PowerManagementPolicy::Delays
* delays
=
165 prefs_policy_
.mutable_ac_delays();
166 delays
->set_screen_dim_ms(values
.ac_screen_dim_delay_ms
);
167 delays
->set_screen_off_ms(values
.ac_screen_off_delay_ms
);
168 delays
->set_screen_lock_ms(values
.ac_screen_lock_delay_ms
);
169 delays
->set_idle_warning_ms(values
.ac_idle_warning_delay_ms
);
170 delays
->set_idle_ms(values
.ac_idle_delay_ms
);
172 // If auto screen-locking is enabled, ensure that the screen is locked soon
173 // after it's turned off due to user inactivity.
174 int64 lock_ms
= delays
->screen_off_ms() + kScreenLockAfterOffDelayMs
;
175 if (values
.enable_auto_screen_lock
&& delays
->screen_off_ms() > 0 &&
176 (delays
->screen_lock_ms() <= 0 || lock_ms
< delays
->screen_lock_ms()) &&
177 lock_ms
< delays
->idle_ms()) {
178 delays
->set_screen_lock_ms(lock_ms
);
181 delays
= prefs_policy_
.mutable_battery_delays();
182 delays
->set_screen_dim_ms(values
.battery_screen_dim_delay_ms
);
183 delays
->set_screen_off_ms(values
.battery_screen_off_delay_ms
);
184 delays
->set_screen_lock_ms(values
.battery_screen_lock_delay_ms
);
185 delays
->set_idle_warning_ms(values
.battery_idle_warning_delay_ms
);
186 delays
->set_idle_ms(values
.battery_idle_delay_ms
);
188 lock_ms
= delays
->screen_off_ms() + kScreenLockAfterOffDelayMs
;
189 if (values
.enable_auto_screen_lock
&& delays
->screen_off_ms() > 0 &&
190 (delays
->screen_lock_ms() <= 0 || lock_ms
< delays
->screen_lock_ms()) &&
191 lock_ms
< delays
->idle_ms()) {
192 delays
->set_screen_lock_ms(lock_ms
);
195 prefs_policy_
.set_ac_idle_action(GetProtoAction(values
.ac_idle_action
));
196 prefs_policy_
.set_battery_idle_action(
197 GetProtoAction(values
.battery_idle_action
));
198 prefs_policy_
.set_lid_closed_action(GetProtoAction(values
.lid_closed_action
));
199 prefs_policy_
.set_use_audio_activity(values
.use_audio_activity
);
200 prefs_policy_
.set_use_video_activity(values
.use_video_activity
);
201 if (values
.ac_brightness_percent
>= 0.0)
202 prefs_policy_
.set_ac_brightness_percent(values
.ac_brightness_percent
);
203 if (values
.battery_brightness_percent
>= 0.0) {
204 prefs_policy_
.set_battery_brightness_percent(
205 values
.battery_brightness_percent
);
207 prefs_policy_
.set_presentation_screen_dim_delay_factor(
208 values
.presentation_screen_dim_delay_factor
);
209 prefs_policy_
.set_user_activity_screen_dim_delay_factor(
210 values
.user_activity_screen_dim_delay_factor
);
211 prefs_policy_
.set_wait_for_initial_user_activity(
212 values
.wait_for_initial_user_activity
);
214 honor_screen_wake_locks_
= values
.allow_screen_wake_locks
;
216 prefs_were_set_
= true;
220 int PowerPolicyController::AddScreenWakeLock(const std::string
& reason
) {
221 int id
= next_wake_lock_id_
++;
222 screen_wake_locks_
[id
] = reason
;
227 int PowerPolicyController::AddSystemWakeLock(const std::string
& reason
) {
228 int id
= next_wake_lock_id_
++;
229 system_wake_locks_
[id
] = reason
;
234 void PowerPolicyController::RemoveWakeLock(int id
) {
235 if (!screen_wake_locks_
.erase(id
) && !system_wake_locks_
.erase(id
))
236 LOG(WARNING
) << "Ignoring request to remove nonexistent wake lock " << id
;
241 void PowerPolicyController::PowerManagerRestarted() {
245 PowerPolicyController::PowerPolicyController(PowerManagerClient
* client
)
247 prefs_were_set_(false),
248 honor_screen_wake_locks_(true),
249 next_wake_lock_id_(1) {
251 client_
->AddObserver(this);
254 PowerPolicyController::~PowerPolicyController() {
255 client_
->RemoveObserver(this);
258 void PowerPolicyController::SendCurrentPolicy() {
261 power_manager::PowerManagementPolicy policy
= prefs_policy_
;
265 if (honor_screen_wake_locks_
&& !screen_wake_locks_
.empty()) {
266 policy
.mutable_ac_delays()->set_screen_dim_ms(0);
267 policy
.mutable_ac_delays()->set_screen_off_ms(0);
268 policy
.mutable_ac_delays()->set_screen_lock_ms(0);
269 policy
.mutable_battery_delays()->set_screen_dim_ms(0);
270 policy
.mutable_battery_delays()->set_screen_off_ms(0);
271 policy
.mutable_battery_delays()->set_screen_lock_ms(0);
274 if (!screen_wake_locks_
.empty() || !system_wake_locks_
.empty()) {
275 if (!policy
.has_ac_idle_action() || policy
.ac_idle_action() ==
276 power_manager::PowerManagementPolicy_Action_SUSPEND
) {
277 policy
.set_ac_idle_action(
278 power_manager::PowerManagementPolicy_Action_DO_NOTHING
);
280 if (!policy
.has_battery_idle_action() || policy
.battery_idle_action() ==
281 power_manager::PowerManagementPolicy_Action_SUSPEND
) {
282 policy
.set_battery_idle_action(
283 power_manager::PowerManagementPolicy_Action_DO_NOTHING
);
287 for (WakeLockMap::const_iterator it
= screen_wake_locks_
.begin();
288 it
!= screen_wake_locks_
.end(); ++it
) {
289 reason
+= (reason
.empty() ? "" : ", ") + it
->second
;
291 for (WakeLockMap::const_iterator it
= system_wake_locks_
.begin();
292 it
!= system_wake_locks_
.end(); ++it
) {
293 reason
+= (reason
.empty() ? "" : ", ") + it
->second
;
297 policy
.set_reason(reason
);
298 client_
->SetPolicy(policy
);
301 } // namespace chromeos