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 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 89 // static 90 std::string PowerPolicyController::GetPolicyDebugString( 91 const power_manager::PowerManagementPolicy& policy) { 92 std::string str; 93 if (policy.has_ac_delays()) 94 APPEND_DELAYS(str, policy.ac_delays(), "ac"); 95 if (policy.has_battery_delays()) 96 APPEND_DELAYS(str, policy.battery_delays(), "battery"); 97 if (policy.has_ac_idle_action()) 98 str += base::StringPrintf("ac_idle=%d ", policy.ac_idle_action()); 99 if (policy.has_battery_idle_action()) 100 str += base::StringPrintf("battery_idle=%d ", policy.battery_idle_action()); 101 if (policy.has_lid_closed_action()) 102 str += base::StringPrintf("lid_closed=%d ", policy.lid_closed_action()); 103 if (policy.has_use_audio_activity()) 104 str += base::StringPrintf("use_audio=%d ", policy.use_audio_activity()); 105 if (policy.has_use_video_activity()) 106 str += base::StringPrintf("use_video=%d ", policy.use_audio_activity()); 107 if (policy.has_presentation_screen_dim_delay_factor()) { 108 str += base::StringPrintf("presentation_screen_dim_delay_factor=%f ", 109 policy.presentation_screen_dim_delay_factor()); 110 } 111 if (policy.has_user_activity_screen_dim_delay_factor()) { 112 str += base::StringPrintf("user_activity_screen_dim_delay_factor=%f ", 113 policy.user_activity_screen_dim_delay_factor()); 114 } 115 if (policy.has_reason()) 116 str += base::StringPrintf("reason=\"%s\" ", policy.reason().c_str()); 117 TrimWhitespace(str, TRIM_TRAILING, &str); 118 return str; 119 } 120 121 PowerPolicyController::PowerPolicyController(DBusThreadManager* manager, 122 PowerManagerClient* client) 123 : manager_(manager), 124 client_(client), 125 prefs_were_set_(false), 126 honor_screen_wake_locks_(true), 127 next_wake_lock_id_(1) { 128 manager_->AddObserver(this); 129 client_->AddObserver(this); 130 SendCurrentPolicy(); 131 } 132 133 PowerPolicyController::~PowerPolicyController() { 134 // The power manager's policy is reset before this point, in 135 // OnDBusThreadManagerDestroying(). At the time that 136 // PowerPolicyController is destroyed, PowerManagerClient's D-Bus proxy 137 // to the power manager is already gone. 138 client_->RemoveObserver(this); 139 client_ = NULL; 140 manager_->RemoveObserver(this); 141 manager_ = NULL; 142 } 143 144 void PowerPolicyController::ApplyPrefs(const PrefValues& values) { 145 prefs_policy_.Clear(); 146 147 power_manager::PowerManagementPolicy::Delays* delays = 148 prefs_policy_.mutable_ac_delays(); 149 delays->set_screen_dim_ms(values.ac_screen_dim_delay_ms); 150 delays->set_screen_off_ms(values.ac_screen_off_delay_ms); 151 delays->set_screen_lock_ms(values.ac_screen_lock_delay_ms); 152 delays->set_idle_warning_ms(values.ac_idle_warning_delay_ms); 153 delays->set_idle_ms(values.ac_idle_delay_ms); 154 155 // If screen-locking is enabled, ensure that the screen is locked soon 156 // after it's turned off due to user inactivity. 157 int64 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs; 158 if (values.enable_screen_lock && delays->screen_off_ms() > 0 && 159 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) && 160 lock_ms < delays->idle_ms()) { 161 delays->set_screen_lock_ms(lock_ms); 162 } 163 164 delays = prefs_policy_.mutable_battery_delays(); 165 delays->set_screen_dim_ms(values.battery_screen_dim_delay_ms); 166 delays->set_screen_off_ms(values.battery_screen_off_delay_ms); 167 delays->set_screen_lock_ms(values.battery_screen_lock_delay_ms); 168 delays->set_idle_warning_ms(values.battery_idle_warning_delay_ms); 169 delays->set_idle_ms(values.battery_idle_delay_ms); 170 171 lock_ms = delays->screen_off_ms() + kScreenLockAfterOffDelayMs; 172 if (values.enable_screen_lock && delays->screen_off_ms() > 0 && 173 (delays->screen_lock_ms() <= 0 || lock_ms < delays->screen_lock_ms()) && 174 lock_ms < delays->idle_ms()) { 175 delays->set_screen_lock_ms(lock_ms); 176 } 177 178 prefs_policy_.set_ac_idle_action(GetProtoAction(values.ac_idle_action)); 179 prefs_policy_.set_battery_idle_action( 180 GetProtoAction(values.battery_idle_action)); 181 prefs_policy_.set_lid_closed_action(GetProtoAction(values.lid_closed_action)); 182 prefs_policy_.set_use_audio_activity(values.use_audio_activity); 183 prefs_policy_.set_use_video_activity(values.use_video_activity); 184 prefs_policy_.set_presentation_screen_dim_delay_factor( 185 values.presentation_screen_dim_delay_factor); 186 prefs_policy_.set_user_activity_screen_dim_delay_factor( 187 values.user_activity_screen_dim_delay_factor); 188 189 honor_screen_wake_locks_ = values.allow_screen_wake_locks; 190 191 prefs_were_set_ = true; 192 SendCurrentPolicy(); 193 } 194 195 void PowerPolicyController::ClearPrefs() { 196 prefs_policy_.Clear(); 197 honor_screen_wake_locks_ = true; 198 prefs_were_set_ = false; 199 SendCurrentPolicy(); 200 } 201 202 int PowerPolicyController::AddScreenWakeLock(const std::string& reason) { 203 int id = next_wake_lock_id_++; 204 screen_wake_locks_[id] = reason; 205 SendCurrentPolicy(); 206 return id; 207 } 208 209 int PowerPolicyController::AddSystemWakeLock(const std::string& reason) { 210 int id = next_wake_lock_id_++; 211 system_wake_locks_[id] = reason; 212 SendCurrentPolicy(); 213 return id; 214 } 215 216 void PowerPolicyController::RemoveWakeLock(int id) { 217 if (!screen_wake_locks_.erase(id) && !system_wake_locks_.erase(id)) 218 LOG(WARNING) << "Ignoring request to remove nonexistent wake lock " << id; 219 else 220 SendCurrentPolicy(); 221 } 222 223 void PowerPolicyController::OnDBusThreadManagerDestroying( 224 DBusThreadManager* manager) { 225 DCHECK_EQ(manager, manager_); 226 SendEmptyPolicy(); 227 } 228 229 void PowerPolicyController::PowerManagerRestarted() { 230 SendCurrentPolicy(); 231 } 232 233 void PowerPolicyController::SendCurrentPolicy() { 234 std::string reason; 235 236 power_manager::PowerManagementPolicy policy = prefs_policy_; 237 if (prefs_were_set_) 238 reason = "Prefs"; 239 240 if (honor_screen_wake_locks_ && !screen_wake_locks_.empty()) { 241 policy.mutable_ac_delays()->set_screen_dim_ms(0); 242 policy.mutable_ac_delays()->set_screen_off_ms(0); 243 policy.mutable_ac_delays()->set_screen_lock_ms(0); 244 policy.mutable_battery_delays()->set_screen_dim_ms(0); 245 policy.mutable_battery_delays()->set_screen_off_ms(0); 246 policy.mutable_battery_delays()->set_screen_lock_ms(0); 247 } 248 249 if (!screen_wake_locks_.empty() || !system_wake_locks_.empty()) { 250 if (!policy.has_ac_idle_action() || policy.ac_idle_action() == 251 power_manager::PowerManagementPolicy_Action_SUSPEND) { 252 policy.set_ac_idle_action( 253 power_manager::PowerManagementPolicy_Action_DO_NOTHING); 254 } 255 if (!policy.has_battery_idle_action() || policy.battery_idle_action() == 256 power_manager::PowerManagementPolicy_Action_SUSPEND) { 257 policy.set_battery_idle_action( 258 power_manager::PowerManagementPolicy_Action_DO_NOTHING); 259 } 260 } 261 262 for (WakeLockMap::const_iterator it = screen_wake_locks_.begin(); 263 it != screen_wake_locks_.end(); ++it) { 264 reason += (reason.empty() ? "" : ", ") + it->second; 265 } 266 for (WakeLockMap::const_iterator it = system_wake_locks_.begin(); 267 it != system_wake_locks_.end(); ++it) { 268 reason += (reason.empty() ? "" : ", ") + it->second; 269 } 270 271 if (!reason.empty()) 272 policy.set_reason(reason); 273 client_->SetPolicy(policy); 274 } 275 276 void PowerPolicyController::SendEmptyPolicy() { 277 client_->SetPolicy(power_manager::PowerManagementPolicy()); 278 } 279 280 } // namespace chromeos 281