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"
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
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
24 #define APPEND_DELAY(str, delays, field, name) \
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
34 #define APPEND_DELAYS(str, delays, prefix) \
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
) {
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
;
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
&&
70 if (reason
== PowerPolicyController::REASON_VIDEO_PLAYBACK
&&
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),
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) {}
112 std::string
PowerPolicyController::GetPolicyDebugString(
113 const power_manager::PowerManagementPolicy
& policy
) {
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
);
160 void PowerPolicyController::Initialize(PowerManagerClient
* client
) {
161 DCHECK(!IsInitialized());
162 g_power_policy_controller
= new PowerPolicyController(client
);
166 bool PowerPolicyController::IsInitialized() {
167 return g_power_policy_controller
;
171 void PowerPolicyController::Shutdown() {
172 DCHECK(IsInitialized());
173 delete g_power_policy_controller
;
174 g_power_policy_controller
= nullptr;
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;
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
;
261 void PowerPolicyController::PowerManagerRestarted() {
265 PowerPolicyController::PowerPolicyController(PowerManagerClient
* client
)
267 prefs_were_set_(false),
268 honor_screen_wake_locks_(true),
269 next_wake_lock_id_(1) {
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
)));
296 void PowerPolicyController::SendCurrentPolicy() {
299 power_manager::PowerManagementPolicy policy
= prefs_policy_
;
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()))
311 switch (it
.second
.type
) {
312 case WakeLock::TYPE_SCREEN
:
313 have_screen_wake_locks
= true;
315 case WakeLock::TYPE_SYSTEM
:
316 have_system_wake_locks
= true;
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
);
345 policy
.set_reason(causes
);
346 client_
->SetPolicy(policy
);
349 } // namespace chromeos