blob: 6463d6865b03caf422aba18d572aedd68b1e3709 [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
55void PowerManager::OnSuspendDelay(uint32 sequence_number) {
Darin Petkov3ec55342012-09-28 14:04:44 +020056 LOG(INFO) << __func__ << "(" << sequence_number << ")";
57 // 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);
Gary Morain52fabab2012-08-22 09:27:31 -070066 OnEvent(sequence_number, &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
Darin Petkov3ec55342012-09-28 14:04:44 +020077void PowerManager::RegisterSuspendDelay(uint32 delay_ms) {
Gary Morain52fabab2012-08-22 09:27:31 -070078 power_manager_proxy_->RegisterSuspendDelay(delay_ms);
79}
80
Darin Petkov3ec55342012-09-28 14:04:44 +020081void PowerManager::UnregisterSuspendDelay() {
82 power_manager_proxy_->UnregisterSuspendDelay();
83}
84
85void PowerManager::SuspendReady(uint32 sequence_number) {
86 power_manager_proxy_->SuspendReady(sequence_number);
87}
88
89void PowerManager::OnSuspendTimeout() {
90 LOG(ERROR) << "Suspend timed out -- assuming power-on state.";
91 OnPowerStateChanged(kOn);
92}
93
Gary Morain52fabab2012-08-22 09:27:31 -070094template<class Callback>
95void PowerManager::AddCallback(const string &key, const Callback &callback,
96 map<const string, Callback> *callback_map) {
97 CHECK(callback_map != NULL);
98 CHECK(!callback.is_null());
99 if (ContainsKey(*callback_map, key)) {
100 LOG(DFATAL) << "Inserting duplicate key " << key;
101 LOG(INFO) << "Removing previous callback for key " << key;
102 RemoveCallback(key, callback_map);
103 }
104 (*callback_map)[key] = callback;
105}
106
107template<class Callback>
108void PowerManager::RemoveCallback(const string &key,
109 map<const string, Callback> *callback_map) {
110 CHECK(callback_map != NULL);
111 DCHECK(ContainsKey(*callback_map, key)) << "Removing unknown key " << key;
112 typename map<const std::string, Callback>::iterator it =
113 callback_map->find(key);
114 if (it != callback_map->end()) {
115 callback_map->erase(it);
Gary Morain43bc6272012-01-30 14:01:15 -0800116 }
117}
118
Gary Morain52fabab2012-08-22 09:27:31 -0700119template<class Param, class Callback>
120void PowerManager::OnEvent(const Param &param,
121 map<const string, Callback> *callback_map) const {
122 CHECK(callback_map != NULL);
123 for (typename map<const string, Callback>::const_iterator it =
124 callback_map->begin();
125 it != callback_map->end(); ++it) {
126 CHECK(!it->second.is_null());
127 it->second.Run(param);
128 }
Gary Morain43bc6272012-01-30 14:01:15 -0800129}
130
Gary Morain52fabab2012-08-22 09:27:31 -0700131
132
Gary Morain43bc6272012-01-30 14:01:15 -0800133} // namespace shill