1 // 2 // Copyright (C) 2015 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/dbus/chromeos_power_manager_proxy.h" 18 19 #include <base/bind.h> 20 #include <google/protobuf/message_lite.h> 21 22 #include "power_manager/proto_bindings/suspend.pb.h" 23 #include "shill/event_dispatcher.h" 24 #include "shill/logging.h" 25 26 using std::string; 27 using std::vector; 28 29 namespace shill { 30 31 namespace { 32 33 // Serializes |protobuf| to |out| and returns true on success. 34 bool SerializeProtocolBuffer(const google::protobuf::MessageLite& protobuf, 35 vector<uint8_t>* out) { 36 CHECK(out); 37 out->clear(); 38 string serialized_protobuf; 39 if (!protobuf.SerializeToString(&serialized_protobuf)) 40 return false; 41 out->assign(serialized_protobuf.begin(), serialized_protobuf.end()); 42 return true; 43 } 44 45 // Deserializes |serialized_protobuf| to |protobuf_out| and returns true on 46 // success. 47 bool DeserializeProtocolBuffer(const vector<uint8_t>& serialized_protobuf, 48 google::protobuf::MessageLite* protobuf_out) { 49 CHECK(protobuf_out); 50 if (serialized_protobuf.empty()) 51 return false; 52 return protobuf_out->ParseFromArray(&serialized_protobuf.front(), 53 serialized_protobuf.size()); 54 } 55 56 } // namespace 57 58 ChromeosPowerManagerProxy::ChromeosPowerManagerProxy( 59 EventDispatcher* dispatcher, 60 const scoped_refptr<dbus::Bus>& bus, 61 PowerManagerProxyDelegate* delegate, 62 const base::Closure& service_appeared_callback, 63 const base::Closure& service_vanished_callback) 64 : proxy_(new org::chromium::PowerManagerProxy(bus)), 65 dispatcher_(dispatcher), 66 delegate_(delegate), 67 service_appeared_callback_(service_appeared_callback), 68 service_vanished_callback_(service_vanished_callback) { 69 // Register signal handlers. 70 proxy_->RegisterSuspendImminentSignalHandler( 71 base::Bind(&ChromeosPowerManagerProxy::SuspendImminent, 72 weak_factory_.GetWeakPtr()), 73 base::Bind(&ChromeosPowerManagerProxy::OnSignalConnected, 74 weak_factory_.GetWeakPtr())); 75 proxy_->RegisterSuspendDoneSignalHandler( 76 base::Bind(&ChromeosPowerManagerProxy::SuspendDone, 77 weak_factory_.GetWeakPtr()), 78 base::Bind(&ChromeosPowerManagerProxy::OnSignalConnected, 79 weak_factory_.GetWeakPtr())); 80 proxy_->RegisterDarkSuspendImminentSignalHandler( 81 base::Bind(&ChromeosPowerManagerProxy::DarkSuspendImminent, 82 weak_factory_.GetWeakPtr()), 83 base::Bind(&ChromeosPowerManagerProxy::OnSignalConnected, 84 weak_factory_.GetWeakPtr())); 85 86 // One time callback when service becomes available. 87 proxy_->GetObjectProxy()->WaitForServiceToBeAvailable( 88 base::Bind(&ChromeosPowerManagerProxy::OnServiceAvailable, 89 weak_factory_.GetWeakPtr())); 90 } 91 92 ChromeosPowerManagerProxy::~ChromeosPowerManagerProxy() {} 93 94 bool ChromeosPowerManagerProxy::RegisterSuspendDelay( 95 base::TimeDelta timeout, 96 const string& description, 97 int* delay_id_out) { 98 if (!service_available_) { 99 LOG(ERROR) << "PowerManager service not available"; 100 return false; 101 } 102 return RegisterSuspendDelayInternal(false, 103 timeout, 104 description, 105 delay_id_out); 106 } 107 108 bool ChromeosPowerManagerProxy::UnregisterSuspendDelay(int delay_id) { 109 if (!service_available_) { 110 LOG(ERROR) << "PowerManager service not available"; 111 return false; 112 } 113 return UnregisterSuspendDelayInternal(false, delay_id); 114 } 115 116 bool ChromeosPowerManagerProxy::ReportSuspendReadiness(int delay_id, 117 int suspend_id) { 118 if (!service_available_) { 119 LOG(ERROR) << "PowerManager service not available"; 120 return false; 121 } 122 return ReportSuspendReadinessInternal(false, delay_id, suspend_id); 123 } 124 125 bool ChromeosPowerManagerProxy::RegisterDarkSuspendDelay( 126 base::TimeDelta timeout, 127 const string& description, 128 int* delay_id_out) { 129 if (!service_available_) { 130 LOG(ERROR) << "PowerManager service not available"; 131 return false; 132 } 133 return RegisterSuspendDelayInternal(true, 134 timeout, 135 description, 136 delay_id_out); 137 } 138 139 bool ChromeosPowerManagerProxy::UnregisterDarkSuspendDelay(int delay_id) { 140 if (!service_available_) { 141 LOG(ERROR) << "PowerManager service not available"; 142 return false; 143 } 144 return UnregisterSuspendDelayInternal(true, delay_id); 145 } 146 147 bool ChromeosPowerManagerProxy::ReportDarkSuspendReadiness(int delay_id, 148 int suspend_id ) { 149 if (!service_available_) { 150 LOG(ERROR) << "PowerManager service not available"; 151 return false; 152 } 153 return ReportSuspendReadinessInternal(true, delay_id, suspend_id); 154 } 155 156 bool ChromeosPowerManagerProxy::RecordDarkResumeWakeReason( 157 const string& wake_reason) { 158 LOG(INFO) << __func__; 159 160 if (!service_available_) { 161 LOG(ERROR) << "PowerManager service not available"; 162 return false; 163 } 164 165 power_manager::DarkResumeWakeReason proto; 166 proto.set_wake_reason(wake_reason); 167 vector<uint8_t> serialized_proto; 168 CHECK(SerializeProtocolBuffer(proto, &serialized_proto)); 169 170 brillo::ErrorPtr error; 171 if (!proxy_->RecordDarkResumeWakeReason(serialized_proto, &error)) { 172 LOG(ERROR) << "Failed tp record dark resume wake reason: " 173 << error->GetCode() << " " << error->GetMessage(); 174 return false; 175 } 176 return true; 177 } 178 179 bool ChromeosPowerManagerProxy::RegisterSuspendDelayInternal( 180 bool is_dark, 181 base::TimeDelta timeout, 182 const string& description, 183 int* delay_id_out) { 184 const string is_dark_arg = (is_dark ? "dark=true" : "dark=false"); 185 LOG(INFO) << __func__ << "(" << timeout.InMilliseconds() 186 << ", " << is_dark_arg <<")"; 187 188 power_manager::RegisterSuspendDelayRequest request_proto; 189 request_proto.set_timeout(timeout.ToInternalValue()); 190 request_proto.set_description(description); 191 vector<uint8_t> serialized_request; 192 CHECK(SerializeProtocolBuffer(request_proto, &serialized_request)); 193 194 vector<uint8_t> serialized_reply; 195 brillo::ErrorPtr error; 196 if (is_dark) { 197 proxy_->RegisterDarkSuspendDelay(serialized_request, 198 &serialized_reply, 199 &error); 200 } else { 201 proxy_->RegisterSuspendDelay(serialized_request, &serialized_reply, &error); 202 } 203 if (error) { 204 LOG(ERROR) << "Failed to register suspend delay: " 205 << error->GetCode() << " " << error->GetMessage(); 206 return false; 207 } 208 209 power_manager::RegisterSuspendDelayReply reply_proto; 210 if (!DeserializeProtocolBuffer(serialized_reply, &reply_proto)) { 211 LOG(ERROR) << "Failed to register " 212 << (is_dark ? "dark " : "") 213 << "suspend delay. Couldn't parse response."; 214 return false; 215 } 216 *delay_id_out = reply_proto.delay_id(); 217 return true; 218 } 219 220 bool ChromeosPowerManagerProxy::UnregisterSuspendDelayInternal(bool is_dark, 221 int delay_id) { 222 const string is_dark_arg = (is_dark ? "dark=true" : "dark=false"); 223 LOG(INFO) << __func__ << "(" << delay_id << ", " << is_dark_arg << ")"; 224 225 power_manager::UnregisterSuspendDelayRequest request_proto; 226 request_proto.set_delay_id(delay_id); 227 vector<uint8_t> serialized_request; 228 CHECK(SerializeProtocolBuffer(request_proto, &serialized_request)); 229 230 brillo::ErrorPtr error; 231 if (is_dark) { 232 proxy_->UnregisterDarkSuspendDelay(serialized_request, &error); 233 } else { 234 proxy_->UnregisterSuspendDelay(serialized_request, &error); 235 } 236 if (error) { 237 LOG(ERROR) << "Failed to unregister suspend delay: " 238 << error->GetCode() << " " << error->GetMessage(); 239 return false; 240 } 241 return true; 242 } 243 244 bool ChromeosPowerManagerProxy::ReportSuspendReadinessInternal( 245 bool is_dark, int delay_id, int suspend_id) { 246 const string is_dark_arg = (is_dark ? "dark=true" : "dark=false"); 247 LOG(INFO) << __func__ 248 << "(" << delay_id 249 << ", " << suspend_id 250 << ", " << is_dark_arg << ")"; 251 252 power_manager::SuspendReadinessInfo proto; 253 proto.set_delay_id(delay_id); 254 proto.set_suspend_id(suspend_id); 255 vector<uint8_t> serialized_proto; 256 CHECK(SerializeProtocolBuffer(proto, &serialized_proto)); 257 258 brillo::ErrorPtr error; 259 if (is_dark) { 260 proxy_->HandleDarkSuspendReadiness(serialized_proto, &error); 261 } else { 262 proxy_->HandleSuspendReadiness(serialized_proto, &error); 263 } 264 if (error) { 265 LOG(ERROR) << "Failed to report suspend readiness: " 266 << error->GetCode() << " " << error->GetMessage(); 267 return false; 268 } 269 return true; 270 } 271 272 void ChromeosPowerManagerProxy::SuspendImminent( 273 const vector<uint8_t>& serialized_proto) { 274 LOG(INFO) << __func__; 275 power_manager::SuspendImminent proto; 276 if (!DeserializeProtocolBuffer(serialized_proto, &proto)) { 277 LOG(ERROR) << "Failed to parse SuspendImminent signal."; 278 return; 279 } 280 delegate_->OnSuspendImminent(proto.suspend_id()); 281 } 282 283 void ChromeosPowerManagerProxy::SuspendDone( 284 const vector<uint8_t>& serialized_proto) { 285 LOG(INFO) << __func__; 286 power_manager::SuspendDone proto; 287 if (!DeserializeProtocolBuffer(serialized_proto, &proto)) { 288 LOG(ERROR) << "Failed to parse SuspendDone signal."; 289 return; 290 } 291 delegate_->OnSuspendDone(proto.suspend_id()); 292 } 293 294 void ChromeosPowerManagerProxy::DarkSuspendImminent( 295 const vector<uint8_t>& serialized_proto) { 296 LOG(INFO) << __func__; 297 power_manager::SuspendImminent proto; 298 if (!DeserializeProtocolBuffer(serialized_proto, &proto)) { 299 LOG(ERROR) << "Failed to parse DarkSuspendImminent signal."; 300 return; 301 } 302 delegate_->OnDarkSuspendImminent(proto.suspend_id()); 303 } 304 305 void ChromeosPowerManagerProxy::OnServiceAvailable(bool available) { 306 // The only time this function will ever be invoked with |available| set to 307 // false is when we failed to connect the signals, either bus is not setup 308 // yet or we failed to add match rules, and both of these errors are 309 // considered fatal. 310 CHECK(available); 311 312 // Service is available now, continuously monitor the service owner changes. 313 proxy_->GetObjectProxy()->SetNameOwnerChangedCallback( 314 base::Bind(&ChromeosPowerManagerProxy::OnServiceOwnerChanged, 315 weak_factory_.GetWeakPtr())); 316 317 // The callback might invoke calls to the ObjectProxy, so defer the callback 318 // to event loop. 319 if (!service_appeared_callback_.is_null()) { 320 dispatcher_->PostTask(service_appeared_callback_); 321 } 322 323 service_available_ = true; 324 } 325 326 void ChromeosPowerManagerProxy::OnServiceOwnerChanged( 327 const string& old_owner, const string& new_owner) { 328 LOG(INFO) << __func__ << "old: " << old_owner << " new: " << new_owner; 329 330 if (new_owner.empty()) { 331 // The callback might invoke calls to the ObjectProxy, so defer the 332 // callback to event loop. 333 if (!service_vanished_callback_.is_null()) { 334 dispatcher_->PostTask(service_vanished_callback_); 335 } 336 service_available_ = false; 337 } else { 338 // The callback might invoke calls to the ObjectProxy, so defer the 339 // callback to event loop. 340 if (!service_appeared_callback_.is_null()) { 341 dispatcher_->PostTask(service_appeared_callback_); 342 } 343 service_available_ = true; 344 } 345 } 346 347 void ChromeosPowerManagerProxy::OnSignalConnected( 348 const string& interface_name, const string& signal_name, bool success) { 349 LOG(INFO) << __func__ << " interface: " << interface_name 350 << " signal: " << signal_name << "success: " << success; 351 if (!success) { 352 LOG(ERROR) << "Failed to connect signal " << signal_name 353 << " to interface " << interface_name; 354 } 355 } 356 357 } // namespace shill 358