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 allow_screen_wake_locks(true),
85 enable_screen_lock(false),
86 presentation_screen_dim_delay_factor(1.0),
87 user_activity_screen_dim_delay_factor(1.0),
88 wait_for_initial_user_activity(false) {}
91 std::string PowerPolicyController::GetPolicyDebugString(
92 const power_manager::PowerManagementPolicy& policy) {
94 if (policy.has_ac_delays())
95 APPEND_DELAYS(str, policy.ac_delays(), "ac");
96 if (policy.has_battery_delays())
97 APPEND_DELAYS(str, policy.battery_delays(), "battery");
98 if (policy.has_ac_idle_action())
99 str += base::StringPrintf("ac_idle=%d ", policy.ac_idle_action());
100 if (policy.has_battery_idle_action())
101 str += base::StringPrintf("battery_idle=%d ", policy.battery_idle_action());
102 if (policy.has_lid_closed_action())
103 str += base::StringPrintf("lid_closed=%d ", policy.lid_closed_action());
104 if (policy.has_use_audio_activity())
105 str += base::StringPrintf("use_audio=%d ", policy.use_audio_activity());
106 if (policy.has_use_video_activity())
107 str += base::StringPrintf("use_video=%d ", policy.use_audio_activity());
108 if (policy.has_presentation_screen_dim_delay_factor()) {
109 str += base::StringPrintf("presentation_screen_dim_delay_factor=%f ",
110 policy.presentation_screen_dim_delay_factor());
112 if (policy.has_user_activity_screen_dim_delay_factor()) {
113 str += base::StringPrintf("user_activity_screen_dim_delay_factor=%f ",
114 policy.user_activity_screen_dim_delay_factor());
116 if (policy.has_wait_for_initial_user_activity()) {
117 str += base::StringPrintf("wait_for_initial_user_activity=%d ",
118 policy.wait_for_initial_user_activity());
120 if (policy.has_reason())
121 str += base::StringPrintf("reason=\"%s\" ", policy.reason().c_str());
122 TrimWhitespace(str, TRIM_TRAILING, &str);
126 PowerPolicyController::PowerPolicyController(DBusThreadManager* manager,
127 PowerManagerClient* client)
130 prefs_were_set_(false),
131 honor_screen_wake_locks_(true),
132 next_wake_lock_id_(1) {
133 manager_->AddObserver(this);
134 client_->AddObserver(this);
138 PowerPolicyController::~PowerPolicyController() {
139 // The power manager's policy is reset before this point, in
140 // OnDBusThreadManagerDestroying(). At the time that
141 // PowerPolicyController is destroyed, PowerManagerClient's D-Bus proxy
142 // to the power manager is already gone.
143 client_->RemoveObserver(this);
145 manager_->RemoveObserver(this);
149 void PowerPolicyController::ApplyPrefs(const PrefValues& values) {
150 prefs_policy_.Clear();
152 power_manager::PowerManagementPolicy::Delays* delays =
153 prefs_policy_.mutable_ac_delays();
154 delays->set_screen_dim_ms(values.ac_screen_dim_delay_ms);
155 delays->set_screen_off_ms(values.ac_screen_off_delay_ms);
156 delays->set_screen_lock_ms(values.ac_screen_lock_delay_ms);
157 delays->set_idle_warning_ms(values.ac_idle_warning_delay_ms);
158 delays->set_idle_ms(values.ac_idle_delay_ms);
160 // If screen-locking is enabled, ensure that the screen is locked soon
161 // after it's turned off due to user inactivity.
162 int64 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs;
163 if (values.enable_screen_lock && delays->screen_off_ms() > 0 &&
164 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) &&
165 lock_ms < delays->idle_ms()) {
166 delays->set_screen_lock_ms(lock_ms);
169 delays = prefs_policy_.mutable_battery_delays();
170 delays->set_screen_dim_ms(values.battery_screen_dim_delay_ms);
171 delays->set_screen_off_ms(values.battery_screen_off_delay_ms);
172 delays->set_screen_lock_ms(values.battery_screen_lock_delay_ms);
173 delays->set_idle_warning_ms(values.battery_idle_warning_delay_ms);
174 delays->set_idle_ms(values.battery_idle_delay_ms);
176 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs;
177 if (values.enable_screen_lock && delays->screen_off_ms() > 0 &&
178 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) &&
179 lock_ms < delays->idle_ms()) {
180 delays->set_screen_lock_ms(lock_ms);
183 prefs_policy_.set_ac_idle_action(GetProtoAction(values.ac_idle_action));
184 prefs_policy_.set_battery_idle_action(
185 GetProtoAction(values.battery_idle_action));
186 prefs_policy_.set_lid_closed_action(GetProtoAction(values.lid_closed_action));
187 prefs_policy_.set_use_audio_activity(values.use_audio_activity);
188 prefs_policy_.set_use_video_activity(values.use_video_activity);
189 prefs_policy_.set_presentation_screen_dim_delay_factor(
190 values.presentation_screen_dim_delay_factor);
191 prefs_policy_.set_user_activity_screen_dim_delay_factor(
192 values.user_activity_screen_dim_delay_factor);
193 prefs_policy_.set_wait_for_initial_user_activity(
194 values.wait_for_initial_user_activity);
196 honor_screen_wake_locks_ = values.allow_screen_wake_locks;
198 prefs_were_set_ = true;
202 void PowerPolicyController::ClearPrefs() {
203 prefs_policy_.Clear();
204 honor_screen_wake_locks_ = true;
205 prefs_were_set_ = false;
209 int PowerPolicyController::AddScreenWakeLock(const std::string& reason) {
210 int id = next_wake_lock_id_++;
211 screen_wake_locks_[id] = reason;
216 int PowerPolicyController::AddSystemWakeLock(const std::string& reason) {
217 int id = next_wake_lock_id_++;
218 system_wake_locks_[id] = reason;
223 void PowerPolicyController::RemoveWakeLock(int id) {
224 if (!screen_wake_locks_.erase(id) && !system_wake_locks_.erase(id))
225 LOG(WARNING) << "Ignoring request to remove nonexistent wake lock " << id;
230 void PowerPolicyController::OnDBusThreadManagerDestroying(
231 DBusThreadManager* manager) {
232 DCHECK_EQ(manager, manager_);
236 void PowerPolicyController::PowerManagerRestarted() {
240 void PowerPolicyController::SendCurrentPolicy() {
243 power_manager::PowerManagementPolicy policy = prefs_policy_;
247 if (honor_screen_wake_locks_ && !screen_wake_locks_.empty()) {
248 policy.mutable_ac_delays()->set_screen_dim_ms(0);
249 policy.mutable_ac_delays()->set_screen_off_ms(0);
250 policy.mutable_ac_delays()->set_screen_lock_ms(0);
251 policy.mutable_battery_delays()->set_screen_dim_ms(0);
252 policy.mutable_battery_delays()->set_screen_off_ms(0);
253 policy.mutable_battery_delays()->set_screen_lock_ms(0);
256 if (!screen_wake_locks_.empty() || !system_wake_locks_.empty()) {
257 if (!policy.has_ac_idle_action() || policy.ac_idle_action() ==
258 power_manager::PowerManagementPolicy_Action_SUSPEND) {
259 policy.set_ac_idle_action(
260 power_manager::PowerManagementPolicy_Action_DO_NOTHING);
262 if (!policy.has_battery_idle_action() || policy.battery_idle_action() ==
263 power_manager::PowerManagementPolicy_Action_SUSPEND) {
264 policy.set_battery_idle_action(
265 power_manager::PowerManagementPolicy_Action_DO_NOTHING);
269 for (WakeLockMap::const_iterator it = screen_wake_locks_.begin();
270 it != screen_wake_locks_.end(); ++it) {
271 reason += (reason.empty() ? "" : ", ") + it->second;
273 for (WakeLockMap::const_iterator it = system_wake_locks_.begin();
274 it != system_wake_locks_.end(); ++it) {
275 reason += (reason.empty() ? "" : ", ") + it->second;
279 policy.set_reason(reason);
280 client_->SetPolicy(policy);
283 void PowerPolicyController::SendEmptyPolicy() {
284 client_->SetPolicy(power_manager::PowerManagementPolicy());
287 } // namespace chromeos