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 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 62 PowerManager::~PowerManager() {} 63 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 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 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 104 bool PowerManager::ReportDarkSuspendReadiness() { 105 return power_manager_proxy_->ReportDarkSuspendReadiness( 106 dark_suspend_delay_id_, 107 current_dark_suspend_id_); 108 } 109 110 bool PowerManager::RecordDarkResumeWakeReason(const string& wake_reason) { 111 return power_manager_proxy_->RecordDarkResumeWakeReason(wake_reason); 112 } 113 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 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 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 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 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