blob: beb6343543fe8e527e8d8af2b1b81f674bf4d2de [file] [log] [blame]
Gary Morain43bc6272012-01-30 14:01:15 -08001// Copyright (c) 2012 The Chromium OS 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 "shill/power_manager.h"
6
7#include <map>
8#include <string>
9
Eric Shienbrood3e20a232012-02-16 11:35:56 -050010#include <base/stl_util.h>
Gary Morain43bc6272012-01-30 14:01:15 -080011
Darin Petkov3ec55342012-09-28 14:04:44 +020012#include "shill/event_dispatcher.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070013#include "shill/logging.h"
Gary Morain43bc6272012-01-30 14:01:15 -080014#include "shill/power_manager_proxy_interface.h"
15#include "shill/proxy_factory.h"
16
Gary Morain52fabab2012-08-22 09:27:31 -070017using std::map;
Gary Morain43bc6272012-01-30 14:01:15 -080018using std::string;
19
20namespace shill {
21
Darin Petkov3ec55342012-09-28 14:04:44 +020022const int PowerManager::kSuspendTimeoutMilliseconds = 15 * 1000;
23
24PowerManager::PowerManager(EventDispatcher *dispatcher,
25 ProxyFactory *proxy_factory)
26 : dispatcher_(dispatcher),
27 power_manager_proxy_(proxy_factory->CreatePowerManagerProxy(this)),
Darin Petkovca621542012-07-25 14:25:56 +020028 power_state_(kUnknown) {}
Gary Morain43bc6272012-01-30 14:01:15 -080029
30PowerManager::~PowerManager() {
Gary Morain43bc6272012-01-30 14:01:15 -080031}
32
33void PowerManager::AddStateChangeCallback(const string &key,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050034 const PowerStateCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070035 SLOG(Power, 2) << __func__ << " key " << key;
Gary Morain52fabab2012-08-22 09:27:31 -070036 AddCallback(key, callback, &state_change_callbacks_);
37}
38
39void PowerManager::AddSuspendDelayCallback(
40 const string &key, const SuspendDelayCallback &callback) {
41 SLOG(Power, 2) << __func__ << " key " << key;
42 AddCallback(key, callback, &suspend_delay_callbacks_);
Gary Morain43bc6272012-01-30 14:01:15 -080043}
44
45void PowerManager::RemoveStateChangeCallback(const string &key) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070046 SLOG(Power, 2) << __func__ << " key " << key;
Gary Morain52fabab2012-08-22 09:27:31 -070047 RemoveCallback(key, &state_change_callbacks_);
Gary Morain43bc6272012-01-30 14:01:15 -080048}
49
Gary Morain52fabab2012-08-22 09:27:31 -070050void PowerManager::RemoveSuspendDelayCallback(const string &key) {
51 SLOG(Power, 2) << __func__ << " key " << key;
52 RemoveCallback(key, &suspend_delay_callbacks_);
53}
54
Daniel Erat0818cca2012-12-14 10:16:21 -080055void PowerManager::OnSuspendImminent(int suspend_id) {
56 LOG(INFO) << __func__ << "(" << suspend_id << ")";
Darin Petkov3ec55342012-09-28 14:04:44 +020057 // Change the power state to suspending as soon as this signal is received so
58 // that the manager can suppress auto-connect, for example. Schedules a
59 // suspend timeout in case the suspend attempt failed or got interrupted, and
60 // there's no proper notification from the power manager.
61 power_state_ = kSuspending;
62 suspend_timeout_.Reset(
63 base::Bind(&PowerManager::OnSuspendTimeout, base::Unretained(this)));
64 dispatcher_->PostDelayedTask(suspend_timeout_.callback(),
65 kSuspendTimeoutMilliseconds);
Daniel Erat0818cca2012-12-14 10:16:21 -080066 OnEvent(suspend_id, &suspend_delay_callbacks_);
Gary Morain43bc6272012-01-30 14:01:15 -080067}
68
69void PowerManager::OnPowerStateChanged(SuspendState new_power_state) {
Darin Petkovca621542012-07-25 14:25:56 +020070 LOG(INFO) << "Power state changed: "
71 << power_state_ << "->" << new_power_state;
Darin Petkov3ec55342012-09-28 14:04:44 +020072 suspend_timeout_.Cancel();
Darin Petkovca621542012-07-25 14:25:56 +020073 power_state_ = new_power_state;
Gary Morain52fabab2012-08-22 09:27:31 -070074 OnEvent(new_power_state, &state_change_callbacks_);
75}
76
Daniel Erat0818cca2012-12-14 10:16:21 -080077bool PowerManager::RegisterSuspendDelay(base::TimeDelta timeout,
Daniel Eratf9753672013-01-24 10:17:02 -080078 const string &description,
Daniel Erat0818cca2012-12-14 10:16:21 -080079 int *delay_id_out) {
Daniel Eratf9753672013-01-24 10:17:02 -080080 return power_manager_proxy_->RegisterSuspendDelay(timeout, description,
81 delay_id_out);
Gary Morain52fabab2012-08-22 09:27:31 -070082}
83
Daniel Erat0818cca2012-12-14 10:16:21 -080084bool PowerManager::UnregisterSuspendDelay(int delay_id) {
85 return power_manager_proxy_->UnregisterSuspendDelay(delay_id);
Darin Petkov3ec55342012-09-28 14:04:44 +020086}
87
Daniel Erat0818cca2012-12-14 10:16:21 -080088bool PowerManager::ReportSuspendReadiness(int delay_id, int suspend_id) {
89 return power_manager_proxy_->ReportSuspendReadiness(delay_id, suspend_id);
Darin Petkov3ec55342012-09-28 14:04:44 +020090}
91
92void PowerManager::OnSuspendTimeout() {
93 LOG(ERROR) << "Suspend timed out -- assuming power-on state.";
94 OnPowerStateChanged(kOn);
95}
96
Gary Morain52fabab2012-08-22 09:27:31 -070097template<class Callback>
98void PowerManager::AddCallback(const string &key, const Callback &callback,
99 map<const string, Callback> *callback_map) {
100 CHECK(callback_map != NULL);
101 CHECK(!callback.is_null());
102 if (ContainsKey(*callback_map, key)) {
103 LOG(DFATAL) << "Inserting duplicate key " << key;
104 LOG(INFO) << "Removing previous callback for key " << key;
105 RemoveCallback(key, callback_map);
106 }
107 (*callback_map)[key] = callback;
108}
109
110template<class Callback>
111void PowerManager::RemoveCallback(const string &key,
112 map<const string, Callback> *callback_map) {
113 CHECK(callback_map != NULL);
114 DCHECK(ContainsKey(*callback_map, key)) << "Removing unknown key " << key;
Daniel Eratf9753672013-01-24 10:17:02 -0800115 typename map<const string, Callback>::iterator it = callback_map->find(key);
Gary Morain52fabab2012-08-22 09:27:31 -0700116 if (it != callback_map->end()) {
117 callback_map->erase(it);
Gary Morain43bc6272012-01-30 14:01:15 -0800118 }
119}
120
Gary Morain52fabab2012-08-22 09:27:31 -0700121template<class Param, class Callback>
122void PowerManager::OnEvent(const Param &param,
123 map<const string, Callback> *callback_map) const {
124 CHECK(callback_map != NULL);
125 for (typename map<const string, Callback>::const_iterator it =
126 callback_map->begin();
127 it != callback_map->end(); ++it) {
128 CHECK(!it->second.is_null());
129 it->second.Run(param);
130 }
Gary Morain43bc6272012-01-30 14:01:15 -0800131}
132
Gary Morain52fabab2012-08-22 09:27:31 -0700133
134
Gary Morain43bc6272012-01-30 14:01:15 -0800135} // namespace shill