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. 4 5 #include "chromeos/dbus/power_policy_controller.h" 6 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" 12 13 namespace chromeos { 14 15 namespace { 16 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 20 // field. 21 #define APPEND_DELAY(str, delays, field, name) \ 22 { \ 23 if (delays.has_##field()) \ 24 str += base::StringPrintf(name "=%" PRId64 " ", delays.field()); \ 25 } 26 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 30 // "battery". 31 #define APPEND_DELAYS(str, delays, prefix) \ 32 { \ 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"); \ 38 } 39 40 // Returns the power_manager::PowerManagementPolicy_Action value 41 // corresponding to |action|. 42 power_manager::PowerManagementPolicy_Action GetProtoAction( 43 PowerPolicyController::Action action) { 44 switch (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; 53 default: 54 NOTREACHED() << "Unhandled action " << action; 55 return power_manager::PowerManagementPolicy_Action_DO_NOTHING; 56 } 57 } 58 59 } // namespace 60 61 const int PowerPolicyController::kScreenLockAfterOffDelayMs = 10000; // 10 sec. 62 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), 73 ac_idle_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_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) {} 91 92 // static 93 std::string PowerPolicyController::GetPolicyDebugString( 94 const power_manager::PowerManagementPolicy& policy) { 95 std::string str; 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()); 113 } 114 if (policy.has_battery_brightness_percent()) { 115 str += base::StringPrintf("battery_brightness_percent=%f ", 116 policy.battery_brightness_percent()); 117 } 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()); 121 } 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()); 125 } 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()); 129 } 130 if (policy.has_reason()) 131 str += base::StringPrintf("reason=\"%s\" ", policy.reason().c_str()); 132 TrimWhitespace(str, TRIM_TRAILING, &str); 133 return str; 134 } 135 136 PowerPolicyController::PowerPolicyController() 137 : manager_(NULL), 138 client_(NULL), 139 prefs_were_set_(false), 140 honor_screen_wake_locks_(true), 141 next_wake_lock_id_(1) { 142 } 143 144 PowerPolicyController::~PowerPolicyController() { 145 DCHECK(manager_); 146 // The power manager's policy is reset before this point, in 147 // OnDBusThreadManagerDestroying(). At the time that 148 // PowerPolicyController is destroyed, PowerManagerClient's D-Bus proxy 149 // to the power manager is already gone. 150 client_->RemoveObserver(this); 151 client_ = NULL; 152 manager_->RemoveObserver(this); 153 manager_ = NULL; 154 } 155 156 void PowerPolicyController::Init(DBusThreadManager* manager) { 157 manager_ = manager; 158 manager_->AddObserver(this); 159 client_ = manager_->GetPowerManagerClient(); 160 client_->AddObserver(this); 161 SendCurrentPolicy(); 162 } 163 164 void PowerPolicyController::ApplyPrefs(const PrefValues& values) { 165 prefs_policy_.Clear(); 166 167 power_manager::PowerManagementPolicy::Delays* delays = 168 prefs_policy_.mutable_ac_delays(); 169 delays->set_screen_dim_ms(values.ac_screen_dim_delay_ms); 170 delays->set_screen_off_ms(values.ac_screen_off_delay_ms); 171 delays->set_screen_lock_ms(values.ac_screen_lock_delay_ms); 172 delays->set_idle_warning_ms(values.ac_idle_warning_delay_ms); 173 delays->set_idle_ms(values.ac_idle_delay_ms); 174 175 // If screen-locking is enabled, ensure that the screen is locked soon 176 // after it's turned off due to user inactivity. 177 int64 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs; 178 if (values.enable_screen_lock && delays->screen_off_ms() > 0 && 179 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) && 180 lock_ms < delays->idle_ms()) { 181 delays->set_screen_lock_ms(lock_ms); 182 } 183 184 delays = prefs_policy_.mutable_battery_delays(); 185 delays->set_screen_dim_ms(values.battery_screen_dim_delay_ms); 186 delays->set_screen_off_ms(values.battery_screen_off_delay_ms); 187 delays->set_screen_lock_ms(values.battery_screen_lock_delay_ms); 188 delays->set_idle_warning_ms(values.battery_idle_warning_delay_ms); 189 delays->set_idle_ms(values.battery_idle_delay_ms); 190 191 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs; 192 if (values.enable_screen_lock && delays->screen_off_ms() > 0 && 193 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) && 194 lock_ms < delays->idle_ms()) { 195 delays->set_screen_lock_ms(lock_ms); 196 } 197 198 prefs_policy_.set_ac_idle_action(GetProtoAction(values.ac_idle_action)); 199 prefs_policy_.set_battery_idle_action( 200 GetProtoAction(values.battery_idle_action)); 201 prefs_policy_.set_lid_closed_action(GetProtoAction(values.lid_closed_action)); 202 prefs_policy_.set_use_audio_activity(values.use_audio_activity); 203 prefs_policy_.set_use_video_activity(values.use_video_activity); 204 if (values.ac_brightness_percent >= 0.0) 205 prefs_policy_.set_ac_brightness_percent(values.ac_brightness_percent); 206 if (values.battery_brightness_percent >= 0.0) { 207 prefs_policy_.set_battery_brightness_percent( 208 values.battery_brightness_percent); 209 } 210 prefs_policy_.set_presentation_screen_dim_delay_factor( 211 values.presentation_screen_dim_delay_factor); 212 prefs_policy_.set_user_activity_screen_dim_delay_factor( 213 values.user_activity_screen_dim_delay_factor); 214 prefs_policy_.set_wait_for_initial_user_activity( 215 values.wait_for_initial_user_activity); 216 217 honor_screen_wake_locks_ = values.allow_screen_wake_locks; 218 219 prefs_were_set_ = true; 220 SendCurrentPolicy(); 221 } 222 223 void PowerPolicyController::ClearPrefs() { 224 prefs_policy_.Clear(); 225 honor_screen_wake_locks_ = true; 226 prefs_were_set_ = false; 227 SendCurrentPolicy(); 228 } 229 230 int PowerPolicyController::AddScreenWakeLock(const std::string& reason) { 231 int id = next_wake_lock_id_++; 232 screen_wake_locks_[id] = reason; 233 SendCurrentPolicy(); 234 return id; 235 } 236 237 int PowerPolicyController::AddSystemWakeLock(const std::string& reason) { 238 int id = next_wake_lock_id_++; 239 system_wake_locks_[id] = reason; 240 SendCurrentPolicy(); 241 return id; 242 } 243 244 void PowerPolicyController::RemoveWakeLock(int id) { 245 if (!screen_wake_locks_.erase(id) && !system_wake_locks_.erase(id)) 246 LOG(WARNING) << "Ignoring request to remove nonexistent wake lock " << id; 247 else 248 SendCurrentPolicy(); 249 } 250 251 void PowerPolicyController::OnDBusThreadManagerDestroying( 252 DBusThreadManager* manager) { 253 DCHECK_EQ(manager, manager_); 254 SendEmptyPolicy(); 255 } 256 257 void PowerPolicyController::PowerManagerRestarted() { 258 SendCurrentPolicy(); 259 } 260 261 void PowerPolicyController::SendCurrentPolicy() { 262 std::string reason; 263 264 power_manager::PowerManagementPolicy policy = prefs_policy_; 265 if (prefs_were_set_) 266 reason = "Prefs"; 267 268 if (honor_screen_wake_locks_ && !screen_wake_locks_.empty()) { 269 policy.mutable_ac_delays()->set_screen_dim_ms(0); 270 policy.mutable_ac_delays()->set_screen_off_ms(0); 271 policy.mutable_ac_delays()->set_screen_lock_ms(0); 272 policy.mutable_battery_delays()->set_screen_dim_ms(0); 273 policy.mutable_battery_delays()->set_screen_off_ms(0); 274 policy.mutable_battery_delays()->set_screen_lock_ms(0); 275 } 276 277 if (!screen_wake_locks_.empty() || !system_wake_locks_.empty()) { 278 if (!policy.has_ac_idle_action() || policy.ac_idle_action() == 279 power_manager::PowerManagementPolicy_Action_SUSPEND) { 280 policy.set_ac_idle_action( 281 power_manager::PowerManagementPolicy_Action_DO_NOTHING); 282 } 283 if (!policy.has_battery_idle_action() || policy.battery_idle_action() == 284 power_manager::PowerManagementPolicy_Action_SUSPEND) { 285 policy.set_battery_idle_action( 286 power_manager::PowerManagementPolicy_Action_DO_NOTHING); 287 } 288 } 289 290 for (WakeLockMap::const_iterator it = screen_wake_locks_.begin(); 291 it != screen_wake_locks_.end(); ++it) { 292 reason += (reason.empty() ? "" : ", ") + it->second; 293 } 294 for (WakeLockMap::const_iterator it = system_wake_locks_.begin(); 295 it != system_wake_locks_.end(); ++it) { 296 reason += (reason.empty() ? "" : ", ") + it->second; 297 } 298 299 if (!reason.empty()) 300 policy.set_reason(reason); 301 client_->SetPolicy(policy); 302 } 303 304 void PowerPolicyController::SendEmptyPolicy() { 305 client_->SetPolicy(power_manager::PowerManagementPolicy()); 306 } 307 308 } // namespace chromeos 309