Home | History | Annotate | Download | only in dbus
      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