1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/power_manager.h"
18
19 #include <map>
20 #include <string>
21
22 #include <base/bind.h>
23 #include <base/stl_util.h>
24 #if defined(__ANDROID__)
25 #include <dbus/service_constants.h>
26 #else
27 #include <chromeos/dbus/service_constants.h>
28 #endif // __ANDROID__
29
30 #include "shill/control_interface.h"
31 #include "shill/event_dispatcher.h"
32 #include "shill/logging.h"
33 #include "shill/power_manager_proxy_interface.h"
34
35 using base::Bind;
36 using base::TimeDelta;
37 using base::Unretained;
38 using std::map;
39 using std::string;
40
41 namespace shill {
42
43 // static
44 const int PowerManager::kInvalidSuspendId = -1;
45 const char PowerManager::kSuspendDelayDescription[] = "shill";
46 const char PowerManager::kDarkSuspendDelayDescription[] = "shill";
47 const int PowerManager::kSuspendTimeoutMilliseconds = 15 * 1000;
48
PowerManager(EventDispatcher * dispatcher,ControlInterface * control_interface)49 PowerManager::PowerManager(EventDispatcher* dispatcher,
50 ControlInterface* control_interface)
51 : dispatcher_(dispatcher),
52 control_interface_(control_interface),
53 suspend_delay_registered_(false),
54 suspend_delay_id_(0),
55 dark_suspend_delay_registered_(false),
56 dark_suspend_delay_id_(0),
57 suspending_(false),
58 in_dark_resume_(false),
59 current_suspend_id_(0),
60 current_dark_suspend_id_(0) {}
61
~PowerManager()62 PowerManager::~PowerManager() {}
63
Start(TimeDelta suspend_delay,const SuspendImminentCallback & suspend_imminent_callback,const SuspendDoneCallback & suspend_done_callback,const DarkSuspendImminentCallback & dark_suspend_imminent_callback)64 void PowerManager::Start(
65 TimeDelta suspend_delay,
66 const SuspendImminentCallback& suspend_imminent_callback,
67 const SuspendDoneCallback& suspend_done_callback,
68 const DarkSuspendImminentCallback& dark_suspend_imminent_callback) {
69 power_manager_proxy_.reset(
70 control_interface_->CreatePowerManagerProxy(
71 this,
72 Bind(&PowerManager::OnPowerManagerAppeared, Unretained(this)),
73 Bind(&PowerManager::OnPowerManagerVanished, Unretained(this))));
74 suspend_delay_ = suspend_delay;
75 suspend_imminent_callback_ = suspend_imminent_callback;
76 suspend_done_callback_ = suspend_done_callback;
77 dark_suspend_imminent_callback_ = dark_suspend_imminent_callback;
78 }
79
Stop()80 void PowerManager::Stop() {
81 LOG(INFO) << __func__;
82 // We may attempt to unregister with a stale |suspend_delay_id_| if powerd
83 // reappeared behind our back. It is safe to do so.
84 if (suspend_delay_registered_)
85 power_manager_proxy_->UnregisterSuspendDelay(suspend_delay_id_);
86 if (dark_suspend_delay_registered_)
87 power_manager_proxy_->UnregisterDarkSuspendDelay(dark_suspend_delay_id_);
88
89 suspend_delay_registered_ = false;
90 dark_suspend_delay_registered_ = false;
91 power_manager_proxy_.reset();
92 }
93
ReportSuspendReadiness()94 bool PowerManager::ReportSuspendReadiness() {
95 if (!suspending_) {
96 LOG(INFO) << __func__ << ": Suspend attempt ("
97 << current_suspend_id_ << ") not active. Ignoring signal.";
98 return false;
99 }
100 return power_manager_proxy_->ReportSuspendReadiness(suspend_delay_id_,
101 current_suspend_id_);
102 }
103
ReportDarkSuspendReadiness()104 bool PowerManager::ReportDarkSuspendReadiness() {
105 return power_manager_proxy_->ReportDarkSuspendReadiness(
106 dark_suspend_delay_id_,
107 current_dark_suspend_id_);
108 }
109
RecordDarkResumeWakeReason(const string & wake_reason)110 bool PowerManager::RecordDarkResumeWakeReason(const string& wake_reason) {
111 return power_manager_proxy_->RecordDarkResumeWakeReason(wake_reason);
112 }
113
OnSuspendImminent(int suspend_id)114 void PowerManager::OnSuspendImminent(int suspend_id) {
115 LOG(INFO) << __func__ << "(" << suspend_id << ")";
116 current_suspend_id_ = suspend_id;
117
118 // If we're already suspending, don't call the |suspend_imminent_callback_|
119 // again.
120 if (!suspending_) {
121 // Change the power state to suspending as soon as this signal is received
122 // so that the manager can suppress auto-connect, for example.
123 // Also, we must set this before running the callback below, because the
124 // callback may synchronously report suspend readiness.
125 suspending_ = true;
126 suspend_imminent_callback_.Run();
127 }
128 }
129
OnSuspendDone(int suspend_id)130 void PowerManager::OnSuspendDone(int suspend_id) {
131 // NB: |suspend_id| could be -1. See OnPowerManagerVanished.
132 LOG(INFO) << __func__ << "(" << suspend_id << ")";
133 if (!suspending_) {
134 LOG(WARNING) << "Recieved unexpected SuspendDone ("
135 << suspend_id << "). Ignoring.";
136 return;
137 }
138
139 suspending_ = false;
140 in_dark_resume_ = false;
141 suspend_done_callback_.Run();
142 }
143
OnDarkSuspendImminent(int suspend_id)144 void PowerManager::OnDarkSuspendImminent(int suspend_id) {
145 LOG(INFO) << __func__ << "(" << suspend_id << ")";
146 if (!dark_suspend_delay_registered_) {
147 LOG(WARNING) << "Ignoring DarkSuspendImminent signal from powerd. shill "
148 << "does not have a dark suspend delay registered. This "
149 << "means that shill is not guaranteed any time before a "
150 << "resuspend.";
151 return;
152 }
153 in_dark_resume_ = true;
154 current_dark_suspend_id_ = suspend_id;
155 dark_suspend_imminent_callback_.Run();
156 }
157
OnPowerManagerAppeared()158 void PowerManager::OnPowerManagerAppeared() {
159 LOG(INFO) << __func__;
160 CHECK(!suspend_delay_registered_);
161 if (power_manager_proxy_->RegisterSuspendDelay(suspend_delay_,
162 kSuspendDelayDescription,
163 &suspend_delay_id_))
164 suspend_delay_registered_ = true;
165
166 if (power_manager_proxy_->RegisterDarkSuspendDelay(
167 suspend_delay_,
168 kDarkSuspendDelayDescription,
169 &dark_suspend_delay_id_))
170 dark_suspend_delay_registered_ = true;
171 }
172
OnPowerManagerVanished()173 void PowerManager::OnPowerManagerVanished() {
174 LOG(INFO) << __func__;
175 // If powerd vanished during a suspend, we need to wake ourselves up.
176 if (suspending_)
177 OnSuspendDone(kInvalidSuspendId);
178 suspend_delay_registered_ = false;
179 dark_suspend_delay_registered_ = false;
180 }
181
182 } // namespace shill
183