Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromeos / dbus / power_manager_client.cc
blobf0c10f604b15360360431df6a4187fd786f11c2f
1 // Copyright (c) 2012 The Chromium 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.
5 #include "chromeos/dbus/power_manager_client.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/format_macros.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/observer_list.h"
16 #include "base/power_monitor/power_monitor_device_source.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_split.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/threading/platform_thread.h"
21 #include "base/timer/timer.h"
22 #include "chromeos/chromeos_switches.h"
23 #include "chromeos/dbus/fake_power_manager_client.h"
24 #include "chromeos/dbus/power_manager/input_event.pb.h"
25 #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
26 #include "chromeos/dbus/power_manager/policy.pb.h"
27 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
28 #include "chromeos/dbus/power_manager/suspend.pb.h"
29 #include "components/device_event_log/device_event_log.h"
30 #include "dbus/bus.h"
31 #include "dbus/message.h"
32 #include "dbus/object_path.h"
33 #include "dbus/object_proxy.h"
35 namespace chromeos {
37 // Maximum amount of time that the power manager will wait for Chrome to
38 // say that it's ready for the system to be suspended, in milliseconds.
39 const int kSuspendDelayTimeoutMs = 5000;
41 // Human-readable description of Chrome's suspend delay.
42 const char kSuspendDelayDescription[] = "chrome";
44 // The PowerManagerClient implementation used in production.
45 class PowerManagerClientImpl : public PowerManagerClient {
46 public:
47 PowerManagerClientImpl()
48 : origin_thread_id_(base::PlatformThread::CurrentId()),
49 power_manager_proxy_(NULL),
50 suspend_delay_id_(-1),
51 has_suspend_delay_id_(false),
52 dark_suspend_delay_id_(-1),
53 has_dark_suspend_delay_id_(false),
54 pending_suspend_id_(-1),
55 suspend_is_pending_(false),
56 suspending_from_dark_resume_(false),
57 num_pending_suspend_readiness_callbacks_(0),
58 last_is_projecting_(false),
59 weak_ptr_factory_(this) {}
61 ~PowerManagerClientImpl() override {
62 // Here we should unregister suspend notifications from powerd,
63 // however:
64 // - The lifetime of the PowerManagerClientImpl can extend past that of
65 // the objectproxy,
66 // - power_manager can already detect that the client is gone and
67 // unregister our suspend delay.
70 // PowerManagerClient overrides:
72 void AddObserver(Observer* observer) override {
73 CHECK(observer); // http://crbug.com/119976
74 observers_.AddObserver(observer);
77 void RemoveObserver(Observer* observer) override {
78 observers_.RemoveObserver(observer);
81 bool HasObserver(const Observer* observer) const override {
82 return observers_.HasObserver(observer);
85 void SetRenderProcessManagerDelegate(
86 base::WeakPtr<RenderProcessManagerDelegate> delegate) override {
87 DCHECK(!render_process_manager_delegate_)
88 << "There can be only one! ...RenderProcessManagerDelegate";
89 render_process_manager_delegate_ = delegate;
92 void DecreaseScreenBrightness(bool allow_off) override {
93 dbus::MethodCall method_call(
94 power_manager::kPowerManagerInterface,
95 power_manager::kDecreaseScreenBrightnessMethod);
96 dbus::MessageWriter writer(&method_call);
97 writer.AppendBool(allow_off);
98 power_manager_proxy_->CallMethod(
99 &method_call,
100 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
101 dbus::ObjectProxy::EmptyResponseCallback());
104 void IncreaseScreenBrightness() override {
105 SimpleMethodCallToPowerManager(
106 power_manager::kIncreaseScreenBrightnessMethod);
109 void DecreaseKeyboardBrightness() override {
110 SimpleMethodCallToPowerManager(
111 power_manager::kDecreaseKeyboardBrightnessMethod);
114 void IncreaseKeyboardBrightness() override {
115 SimpleMethodCallToPowerManager(
116 power_manager::kIncreaseKeyboardBrightnessMethod);
119 void SetScreenBrightnessPercent(double percent, bool gradual) override {
120 dbus::MethodCall method_call(
121 power_manager::kPowerManagerInterface,
122 power_manager::kSetScreenBrightnessPercentMethod);
123 dbus::MessageWriter writer(&method_call);
124 writer.AppendDouble(percent);
125 writer.AppendInt32(
126 gradual ?
127 power_manager::kBrightnessTransitionGradual :
128 power_manager::kBrightnessTransitionInstant);
129 power_manager_proxy_->CallMethod(
130 &method_call,
131 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
132 dbus::ObjectProxy::EmptyResponseCallback());
135 void GetScreenBrightnessPercent(
136 const GetScreenBrightnessPercentCallback& callback) override {
137 dbus::MethodCall method_call(
138 power_manager::kPowerManagerInterface,
139 power_manager::kGetScreenBrightnessPercentMethod);
140 power_manager_proxy_->CallMethod(
141 &method_call,
142 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
143 base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent,
144 weak_ptr_factory_.GetWeakPtr(), callback));
147 void RequestStatusUpdate() override {
148 POWER_LOG(USER) << "RequestStatusUpdate";
149 dbus::MethodCall method_call(
150 power_manager::kPowerManagerInterface,
151 power_manager::kGetPowerSupplyPropertiesMethod);
152 power_manager_proxy_->CallMethod(
153 &method_call,
154 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
155 base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod,
156 weak_ptr_factory_.GetWeakPtr()));
159 void RequestSuspend() override {
160 POWER_LOG(USER) << "RequestSuspend";
161 SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod);
164 void RequestRestart() override {
165 POWER_LOG(USER) << "RequestRestart";
166 SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod);
169 void RequestShutdown() override {
170 POWER_LOG(USER) << "RequestShutdown";
171 SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod);
174 void NotifyUserActivity(power_manager::UserActivityType type) override {
175 dbus::MethodCall method_call(
176 power_manager::kPowerManagerInterface,
177 power_manager::kHandleUserActivityMethod);
178 dbus::MessageWriter writer(&method_call);
179 writer.AppendInt32(type);
181 power_manager_proxy_->CallMethod(
182 &method_call,
183 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
184 dbus::ObjectProxy::EmptyResponseCallback());
187 void NotifyVideoActivity(bool is_fullscreen) override {
188 dbus::MethodCall method_call(
189 power_manager::kPowerManagerInterface,
190 power_manager::kHandleVideoActivityMethod);
191 dbus::MessageWriter writer(&method_call);
192 writer.AppendBool(is_fullscreen);
194 power_manager_proxy_->CallMethod(
195 &method_call,
196 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
197 dbus::ObjectProxy::EmptyResponseCallback());
200 void SetPolicy(const power_manager::PowerManagementPolicy& policy) override {
201 POWER_LOG(USER) << "SetPolicy";
202 dbus::MethodCall method_call(
203 power_manager::kPowerManagerInterface,
204 power_manager::kSetPolicyMethod);
205 dbus::MessageWriter writer(&method_call);
206 if (!writer.AppendProtoAsArrayOfBytes(policy)) {
207 POWER_LOG(ERROR) << "Error calling " << power_manager::kSetPolicyMethod;
208 return;
210 power_manager_proxy_->CallMethod(
211 &method_call,
212 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
213 dbus::ObjectProxy::EmptyResponseCallback());
216 void SetIsProjecting(bool is_projecting) override {
217 POWER_LOG(USER) << "SetIsProjecting";
218 dbus::MethodCall method_call(
219 power_manager::kPowerManagerInterface,
220 power_manager::kSetIsProjectingMethod);
221 dbus::MessageWriter writer(&method_call);
222 writer.AppendBool(is_projecting);
223 power_manager_proxy_->CallMethod(
224 &method_call,
225 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
226 dbus::ObjectProxy::EmptyResponseCallback());
227 last_is_projecting_ = is_projecting;
230 void SetPowerSource(const std::string& id) override {
231 POWER_LOG(USER) << "SetPowerSource: " << id;
232 dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
233 power_manager::kSetPowerSourceMethod);
234 dbus::MessageWriter writer(&method_call);
235 writer.AppendString(id);
236 power_manager_proxy_->CallMethod(
237 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
238 dbus::ObjectProxy::EmptyResponseCallback());
241 base::Closure GetSuspendReadinessCallback() override {
242 DCHECK(OnOriginThread());
243 DCHECK(suspend_is_pending_);
244 num_pending_suspend_readiness_callbacks_++;
245 return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness,
246 weak_ptr_factory_.GetWeakPtr(), pending_suspend_id_,
247 suspending_from_dark_resume_);
250 int GetNumPendingSuspendReadinessCallbacks() override {
251 return num_pending_suspend_readiness_callbacks_;
254 protected:
255 void Init(dbus::Bus* bus) override {
256 power_manager_proxy_ = bus->GetObjectProxy(
257 power_manager::kPowerManagerServiceName,
258 dbus::ObjectPath(power_manager::kPowerManagerServicePath));
260 power_manager_proxy_->SetNameOwnerChangedCallback(
261 base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived,
262 weak_ptr_factory_.GetWeakPtr()));
264 // Monitor the D-Bus signal for brightness changes. Only the power
265 // manager knows the actual brightness level. We don't cache the
266 // brightness level in Chrome as it'll make things less reliable.
267 power_manager_proxy_->ConnectToSignal(
268 power_manager::kPowerManagerInterface,
269 power_manager::kBrightnessChangedSignal,
270 base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived,
271 weak_ptr_factory_.GetWeakPtr()),
272 base::Bind(&PowerManagerClientImpl::SignalConnected,
273 weak_ptr_factory_.GetWeakPtr()));
275 power_manager_proxy_->ConnectToSignal(
276 power_manager::kPowerManagerInterface,
277 power_manager::kPeripheralBatteryStatusSignal,
278 base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived,
279 weak_ptr_factory_.GetWeakPtr()),
280 base::Bind(&PowerManagerClientImpl::SignalConnected,
281 weak_ptr_factory_.GetWeakPtr()));
283 power_manager_proxy_->ConnectToSignal(
284 power_manager::kPowerManagerInterface,
285 power_manager::kPowerSupplyPollSignal,
286 base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived,
287 weak_ptr_factory_.GetWeakPtr()),
288 base::Bind(&PowerManagerClientImpl::SignalConnected,
289 weak_ptr_factory_.GetWeakPtr()));
291 power_manager_proxy_->ConnectToSignal(
292 power_manager::kPowerManagerInterface,
293 power_manager::kInputEventSignal,
294 base::Bind(&PowerManagerClientImpl::InputEventReceived,
295 weak_ptr_factory_.GetWeakPtr()),
296 base::Bind(&PowerManagerClientImpl::SignalConnected,
297 weak_ptr_factory_.GetWeakPtr()));
299 power_manager_proxy_->ConnectToSignal(
300 power_manager::kPowerManagerInterface,
301 power_manager::kSuspendImminentSignal,
302 base::Bind(
303 &PowerManagerClientImpl::HandleSuspendImminent,
304 weak_ptr_factory_.GetWeakPtr(), false),
305 base::Bind(&PowerManagerClientImpl::SignalConnected,
306 weak_ptr_factory_.GetWeakPtr()));
308 power_manager_proxy_->ConnectToSignal(
309 power_manager::kPowerManagerInterface,
310 power_manager::kSuspendDoneSignal,
311 base::Bind(&PowerManagerClientImpl::SuspendDoneReceived,
312 weak_ptr_factory_.GetWeakPtr()),
313 base::Bind(&PowerManagerClientImpl::SignalConnected,
314 weak_ptr_factory_.GetWeakPtr()));
316 power_manager_proxy_->ConnectToSignal(
317 power_manager::kPowerManagerInterface,
318 power_manager::kDarkSuspendImminentSignal,
319 base::Bind(
320 &PowerManagerClientImpl::HandleSuspendImminent,
321 weak_ptr_factory_.GetWeakPtr(), true),
322 base::Bind(&PowerManagerClientImpl::SignalConnected,
323 weak_ptr_factory_.GetWeakPtr()));
325 power_manager_proxy_->ConnectToSignal(
326 power_manager::kPowerManagerInterface,
327 power_manager::kIdleActionImminentSignal,
328 base::Bind(
329 &PowerManagerClientImpl::IdleActionImminentReceived,
330 weak_ptr_factory_.GetWeakPtr()),
331 base::Bind(&PowerManagerClientImpl::SignalConnected,
332 weak_ptr_factory_.GetWeakPtr()));
334 power_manager_proxy_->ConnectToSignal(
335 power_manager::kPowerManagerInterface,
336 power_manager::kIdleActionDeferredSignal,
337 base::Bind(
338 &PowerManagerClientImpl::IdleActionDeferredReceived,
339 weak_ptr_factory_.GetWeakPtr()),
340 base::Bind(&PowerManagerClientImpl::SignalConnected,
341 weak_ptr_factory_.GetWeakPtr()));
343 RegisterSuspendDelays();
346 private:
347 // Returns true if the current thread is the origin thread.
348 bool OnOriginThread() {
349 return base::PlatformThread::CurrentId() == origin_thread_id_;
352 // Called when a dbus signal is initially connected.
353 void SignalConnected(const std::string& interface_name,
354 const std::string& signal_name,
355 bool success) {
356 if (!success)
357 POWER_LOG(ERROR) << "Failed to connect to signal " << signal_name << ".";
360 // Makes a method call to power manager with no arguments and no response.
361 void SimpleMethodCallToPowerManager(const std::string& method_name) {
362 dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
363 method_name);
364 power_manager_proxy_->CallMethod(
365 &method_call,
366 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
367 dbus::ObjectProxy::EmptyResponseCallback());
370 void NameOwnerChangedReceived(const std::string& old_owner,
371 const std::string& new_owner) {
372 POWER_LOG(EVENT) << "Power manager restarted. Old owner: "
373 << (old_owner.empty() ? "[none]" : old_owner.c_str())
374 << " New owner: "
375 << (new_owner.empty() ? "[none]" : new_owner.c_str());
376 suspend_is_pending_ = false;
377 pending_suspend_id_ = -1;
378 suspending_from_dark_resume_ = false;
379 if (!new_owner.empty()) {
380 POWER_LOG(EVENT) << "Sending initial state to power manager";
381 RegisterSuspendDelays();
382 SetIsProjecting(last_is_projecting_);
383 FOR_EACH_OBSERVER(Observer, observers_, PowerManagerRestarted());
387 void BrightnessChangedReceived(dbus::Signal* signal) {
388 dbus::MessageReader reader(signal);
389 int32_t brightness_level = 0;
390 bool user_initiated = 0;
391 if (!(reader.PopInt32(&brightness_level) &&
392 reader.PopBool(&user_initiated))) {
393 POWER_LOG(ERROR) << "Brightness changed signal had incorrect parameters: "
394 << signal->ToString();
395 return;
397 POWER_LOG(DEBUG) << "Brightness changed to " << brightness_level
398 << ": user initiated " << user_initiated;
399 FOR_EACH_OBSERVER(Observer, observers_,
400 BrightnessChanged(brightness_level, user_initiated));
403 void PeripheralBatteryStatusReceived(dbus::Signal* signal) {
404 dbus::MessageReader reader(signal);
405 power_manager::PeripheralBatteryStatus protobuf_status;
406 if (!reader.PopArrayOfBytesAsProto(&protobuf_status)) {
407 POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
408 << power_manager::kPeripheralBatteryStatusSignal
409 << " signal";
410 return;
413 std::string path = protobuf_status.path();
414 std::string name = protobuf_status.name();
415 int level = protobuf_status.has_level() ? protobuf_status.level() : -1;
417 POWER_LOG(DEBUG) << "Device battery status received " << level << " for "
418 << name << " at " << path;
420 FOR_EACH_OBSERVER(Observer, observers_,
421 PeripheralBatteryStatusReceived(path, name, level));
424 void PowerSupplyPollReceived(dbus::Signal* signal) {
425 POWER_LOG(DEBUG) << "Received power supply poll signal.";
426 dbus::MessageReader reader(signal);
427 power_manager::PowerSupplyProperties protobuf;
428 if (reader.PopArrayOfBytesAsProto(&protobuf)) {
429 HandlePowerSupplyProperties(protobuf);
430 } else {
431 POWER_LOG(ERROR) << "Unable to decode "
432 << power_manager::kPowerSupplyPollSignal << " signal";
436 void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
437 if (!response) {
438 POWER_LOG(ERROR) << "Error calling "
439 << power_manager::kGetPowerSupplyPropertiesMethod;
440 return;
443 dbus::MessageReader reader(response);
444 power_manager::PowerSupplyProperties protobuf;
445 if (reader.PopArrayOfBytesAsProto(&protobuf)) {
446 HandlePowerSupplyProperties(protobuf);
447 } else {
448 POWER_LOG(ERROR) << "Unable to decode "
449 << power_manager::kGetPowerSupplyPropertiesMethod
450 << " response";
454 void OnGetScreenBrightnessPercent(
455 const GetScreenBrightnessPercentCallback& callback,
456 dbus::Response* response) {
457 if (!response) {
458 POWER_LOG(ERROR) << "Error calling "
459 << power_manager::kGetScreenBrightnessPercentMethod;
460 return;
462 dbus::MessageReader reader(response);
463 double percent = 0.0;
464 if (!reader.PopDouble(&percent))
465 POWER_LOG(ERROR) << "Error reading response from powerd: "
466 << response->ToString();
467 callback.Run(percent);
470 void HandlePowerSupplyProperties(
471 const power_manager::PowerSupplyProperties& proto) {
472 FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(proto));
473 const bool on_battery = proto.external_power() ==
474 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
475 base::PowerMonitorDeviceSource::SetPowerSource(on_battery);
478 void HandleRegisterSuspendDelayReply(bool dark_suspend,
479 const std::string& method_name,
480 dbus::Response* response) {
481 if (!response) {
482 POWER_LOG(ERROR) << "Error calling " << method_name;
483 return;
486 dbus::MessageReader reader(response);
487 power_manager::RegisterSuspendDelayReply protobuf;
488 if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
489 POWER_LOG(ERROR) << "Unable to parse reply from " << method_name;
490 return;
493 if (dark_suspend) {
494 dark_suspend_delay_id_ = protobuf.delay_id();
495 has_dark_suspend_delay_id_ = true;
496 POWER_LOG(EVENT) << "Registered dark suspend delay "
497 << dark_suspend_delay_id_;
498 } else {
499 suspend_delay_id_ = protobuf.delay_id();
500 has_suspend_delay_id_ = true;
501 POWER_LOG(EVENT) << "Registered suspend delay " << suspend_delay_id_;
505 void HandleSuspendImminent(bool in_dark_resume, dbus::Signal* signal) {
506 std::string signal_name = signal->GetMember();
507 if ((in_dark_resume && !has_dark_suspend_delay_id_) ||
508 (!in_dark_resume && !has_suspend_delay_id_)) {
509 POWER_LOG(ERROR) << "Received unrequested " << signal_name << " signal";
510 return;
513 dbus::MessageReader reader(signal);
514 power_manager::SuspendImminent proto;
515 if (!reader.PopArrayOfBytesAsProto(&proto)) {
516 POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
517 << signal_name << " signal";
518 return;
521 POWER_LOG(EVENT) << "Got " << signal_name
522 << " signal announcing suspend attempt "
523 << proto.suspend_id();
525 // If a previous suspend is pending from the same state we are currently in
526 // (fully powered on or in dark resume), then something's gone a little
527 // wonky.
528 if (suspend_is_pending_ && suspending_from_dark_resume_ == in_dark_resume) {
529 POWER_LOG(ERROR) << "Got " << signal_name
530 << " signal about pending suspend attempt "
531 << proto.suspend_id()
532 << " while still waiting on attempt "
533 << pending_suspend_id_;
536 pending_suspend_id_ = proto.suspend_id();
537 suspend_is_pending_ = true;
538 suspending_from_dark_resume_ = in_dark_resume;
539 num_pending_suspend_readiness_callbacks_ = 0;
540 if (suspending_from_dark_resume_)
541 FOR_EACH_OBSERVER(Observer, observers_, DarkSuspendImminent());
542 else
543 FOR_EACH_OBSERVER(Observer, observers_, SuspendImminent());
544 base::PowerMonitorDeviceSource::HandleSystemSuspending();
545 MaybeReportSuspendReadiness();
548 void SuspendDoneReceived(dbus::Signal* signal) {
549 dbus::MessageReader reader(signal);
550 power_manager::SuspendDone proto;
551 if (!reader.PopArrayOfBytesAsProto(&proto)) {
552 POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
553 << power_manager::kSuspendDoneSignal << " signal";
554 return;
557 const base::TimeDelta duration =
558 base::TimeDelta::FromInternalValue(proto.suspend_duration());
559 POWER_LOG(EVENT) << "Got " << power_manager::kSuspendDoneSignal
560 << " signal:"
561 << " suspend_id=" << proto.suspend_id()
562 << " duration=" << duration.InSeconds() << " sec";
564 if (render_process_manager_delegate_)
565 render_process_manager_delegate_->SuspendDone();
567 FOR_EACH_OBSERVER(
568 PowerManagerClient::Observer, observers_, SuspendDone(duration));
569 base::PowerMonitorDeviceSource::HandleSystemResumed();
572 void IdleActionImminentReceived(dbus::Signal* signal) {
573 dbus::MessageReader reader(signal);
574 power_manager::IdleActionImminent proto;
575 if (!reader.PopArrayOfBytesAsProto(&proto)) {
576 POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
577 << power_manager::kIdleActionImminentSignal << " signal";
578 return;
580 FOR_EACH_OBSERVER(Observer, observers_,
581 IdleActionImminent(base::TimeDelta::FromInternalValue(
582 proto.time_until_idle_action())));
585 void IdleActionDeferredReceived(dbus::Signal* signal) {
586 FOR_EACH_OBSERVER(Observer, observers_, IdleActionDeferred());
589 void InputEventReceived(dbus::Signal* signal) {
590 dbus::MessageReader reader(signal);
591 power_manager::InputEvent proto;
592 if (!reader.PopArrayOfBytesAsProto(&proto)) {
593 POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
594 << power_manager::kInputEventSignal << " signal";
595 return;
598 base::TimeTicks timestamp =
599 base::TimeTicks::FromInternalValue(proto.timestamp());
600 POWER_LOG(USER) << "Got " << power_manager::kInputEventSignal << " signal:"
601 << " type=" << proto.type()
602 << " timestamp=" << proto.timestamp();
603 switch (proto.type()) {
604 case power_manager::InputEvent_Type_POWER_BUTTON_DOWN:
605 case power_manager::InputEvent_Type_POWER_BUTTON_UP: {
606 const bool down =
607 (proto.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN);
608 FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
609 PowerButtonEventReceived(down, timestamp));
611 // Tell powerd that Chrome has handled power button presses.
612 if (down) {
613 dbus::MethodCall method_call(
614 power_manager::kPowerManagerInterface,
615 power_manager::kHandlePowerButtonAcknowledgmentMethod);
616 dbus::MessageWriter writer(&method_call);
617 writer.AppendInt64(proto.timestamp());
618 power_manager_proxy_->CallMethod(
619 &method_call,
620 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
621 dbus::ObjectProxy::EmptyResponseCallback());
623 break;
625 case power_manager::InputEvent_Type_LID_OPEN:
626 case power_manager::InputEvent_Type_LID_CLOSED: {
627 bool open =
628 (proto.type() == power_manager::InputEvent_Type_LID_OPEN);
629 FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
630 LidEventReceived(open, timestamp));
631 break;
636 void RegisterSuspendDelayImpl(
637 const std::string& method_name,
638 const power_manager::RegisterSuspendDelayRequest& protobuf_request,
639 dbus::ObjectProxy::ResponseCallback callback) {
640 dbus::MethodCall method_call(
641 power_manager::kPowerManagerInterface, method_name);
642 dbus::MessageWriter writer(&method_call);
644 if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
645 POWER_LOG(ERROR) << "Error constructing message for " << method_name;
646 return;
649 power_manager_proxy_->CallMethod(
650 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, callback);
653 // Registers suspend delays with the power manager. This is usually only
654 // called at startup, but if the power manager restarts, we need to create new
655 // delays.
656 void RegisterSuspendDelays() {
657 // Throw out any old delay that was registered.
658 suspend_delay_id_ = -1;
659 has_suspend_delay_id_ = false;
660 dark_suspend_delay_id_ = -1;
661 has_dark_suspend_delay_id_ = false;
663 power_manager::RegisterSuspendDelayRequest protobuf_request;
664 base::TimeDelta timeout =
665 base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs);
666 protobuf_request.set_timeout(timeout.ToInternalValue());
667 protobuf_request.set_description(kSuspendDelayDescription);
669 RegisterSuspendDelayImpl(
670 power_manager::kRegisterSuspendDelayMethod,
671 protobuf_request,
672 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
673 weak_ptr_factory_.GetWeakPtr(), false,
674 power_manager::kRegisterSuspendDelayMethod));
675 RegisterSuspendDelayImpl(
676 power_manager::kRegisterDarkSuspendDelayMethod,
677 protobuf_request,
678 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
679 weak_ptr_factory_.GetWeakPtr(), true,
680 power_manager::kRegisterDarkSuspendDelayMethod));
683 // Records the fact that an observer has finished doing asynchronous work
684 // that was blocking a pending suspend attempt and possibly reports
685 // suspend readiness to powerd. Called by callbacks returned via
686 // GetSuspendReadinessCallback().
687 void HandleObserverSuspendReadiness(int32_t suspend_id, bool in_dark_resume) {
688 DCHECK(OnOriginThread());
689 if (!suspend_is_pending_ || suspend_id != pending_suspend_id_ ||
690 in_dark_resume != suspending_from_dark_resume_)
691 return;
693 num_pending_suspend_readiness_callbacks_--;
694 MaybeReportSuspendReadiness();
697 // Reports suspend readiness to powerd if no observers are still holding
698 // suspend readiness callbacks.
699 void MaybeReportSuspendReadiness() {
700 if (!suspend_is_pending_ || num_pending_suspend_readiness_callbacks_ > 0)
701 return;
703 std::string method_name;
704 int32_t delay_id = -1;
705 if (suspending_from_dark_resume_) {
706 method_name = power_manager::kHandleDarkSuspendReadinessMethod;
707 delay_id = dark_suspend_delay_id_;
708 } else {
709 method_name = power_manager::kHandleSuspendReadinessMethod;
710 delay_id = suspend_delay_id_;
713 if (render_process_manager_delegate_ && !suspending_from_dark_resume_)
714 render_process_manager_delegate_->SuspendImminent();
716 dbus::MethodCall method_call(
717 power_manager::kPowerManagerInterface, method_name);
718 dbus::MessageWriter writer(&method_call);
720 POWER_LOG(EVENT) << "Announcing readiness of suspend delay " << delay_id
721 << " for suspend attempt " << pending_suspend_id_;
722 power_manager::SuspendReadinessInfo protobuf_request;
723 protobuf_request.set_delay_id(delay_id);
724 protobuf_request.set_suspend_id(pending_suspend_id_);
726 pending_suspend_id_ = -1;
727 suspend_is_pending_ = false;
729 if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
730 POWER_LOG(ERROR) << "Error constructing message for " << method_name;
731 return;
733 power_manager_proxy_->CallMethod(
734 &method_call,
735 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
736 dbus::ObjectProxy::EmptyResponseCallback());
739 // Origin thread (i.e. the UI thread in production).
740 base::PlatformThreadId origin_thread_id_;
742 dbus::ObjectProxy* power_manager_proxy_;
743 base::ObserverList<Observer> observers_;
745 // The delay_id_ obtained from the RegisterSuspendDelay request.
746 int32_t suspend_delay_id_;
747 bool has_suspend_delay_id_;
749 // The delay_id_ obtained from the RegisterDarkSuspendDelay request.
750 int32_t dark_suspend_delay_id_;
751 bool has_dark_suspend_delay_id_;
753 // powerd-supplied ID corresponding to an imminent suspend attempt that is
754 // currently being delayed.
755 int32_t pending_suspend_id_;
756 bool suspend_is_pending_;
758 // Set to true when the suspend currently being delayed was triggered during a
759 // dark resume. Since |pending_suspend_id_| and |suspend_is_pending_| are
760 // both shared by normal and dark suspends, |suspending_from_dark_resume_|
761 // helps distinguish the context within which these variables are being used.
762 bool suspending_from_dark_resume_;
764 // Number of callbacks that have been returned by
765 // GetSuspendReadinessCallback() during the currently-pending suspend
766 // attempt but have not yet been called.
767 int num_pending_suspend_readiness_callbacks_;
769 // Last state passed to SetIsProjecting().
770 bool last_is_projecting_;
772 // The delegate used to manage the power consumption of Chrome's renderer
773 // processes.
774 base::WeakPtr<RenderProcessManagerDelegate> render_process_manager_delegate_;
776 // Note: This should remain the last member so it'll be destroyed and
777 // invalidate its weak pointers before any other members are destroyed.
778 base::WeakPtrFactory<PowerManagerClientImpl> weak_ptr_factory_;
780 DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl);
783 PowerManagerClient::PowerManagerClient() {
786 PowerManagerClient::~PowerManagerClient() {
789 // static
790 PowerManagerClient* PowerManagerClient::Create(
791 DBusClientImplementationType type) {
792 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
793 return new PowerManagerClientImpl();
794 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
795 return new FakePowerManagerClient();
798 } // namespace chromeos