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"
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"
31 #include "dbus/message.h"
32 #include "dbus/object_path.h"
33 #include "dbus/object_proxy.h"
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
{
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,
64 // - The lifetime of the PowerManagerClientImpl can extend past that of
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(
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
);
127 power_manager::kBrightnessTransitionGradual
:
128 power_manager::kBrightnessTransitionInstant
);
129 power_manager_proxy_
->CallMethod(
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(
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(
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(
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(
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
;
210 power_manager_proxy_
->CallMethod(
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(
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_
;
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
,
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
,
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
,
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
,
338 &PowerManagerClientImpl::IdleActionDeferredReceived
,
339 weak_ptr_factory_
.GetWeakPtr()),
340 base::Bind(&PowerManagerClientImpl::SignalConnected
,
341 weak_ptr_factory_
.GetWeakPtr()));
343 RegisterSuspendDelays();
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
,
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
,
364 power_manager_proxy_
->CallMethod(
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())
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();
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
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
);
431 POWER_LOG(ERROR
) << "Unable to decode "
432 << power_manager::kPowerSupplyPollSignal
<< " signal";
436 void OnGetPowerSupplyPropertiesMethod(dbus::Response
* response
) {
438 POWER_LOG(ERROR
) << "Error calling "
439 << power_manager::kGetPowerSupplyPropertiesMethod
;
443 dbus::MessageReader
reader(response
);
444 power_manager::PowerSupplyProperties protobuf
;
445 if (reader
.PopArrayOfBytesAsProto(&protobuf
)) {
446 HandlePowerSupplyProperties(protobuf
);
448 POWER_LOG(ERROR
) << "Unable to decode "
449 << power_manager::kGetPowerSupplyPropertiesMethod
454 void OnGetScreenBrightnessPercent(
455 const GetScreenBrightnessPercentCallback
& callback
,
456 dbus::Response
* response
) {
458 POWER_LOG(ERROR
) << "Error calling "
459 << power_manager::kGetScreenBrightnessPercentMethod
;
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
) {
482 POWER_LOG(ERROR
) << "Error calling " << method_name
;
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
;
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_
;
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";
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";
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
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());
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";
557 const base::TimeDelta duration
=
558 base::TimeDelta::FromInternalValue(proto
.suspend_duration());
559 POWER_LOG(EVENT
) << "Got " << power_manager::kSuspendDoneSignal
561 << " suspend_id=" << proto
.suspend_id()
562 << " duration=" << duration
.InSeconds() << " sec";
564 if (render_process_manager_delegate_
)
565 render_process_manager_delegate_
->SuspendDone();
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";
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";
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
: {
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.
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(
620 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
621 dbus::ObjectProxy::EmptyResponseCallback());
625 case power_manager::InputEvent_Type_LID_OPEN
:
626 case power_manager::InputEvent_Type_LID_CLOSED
: {
628 (proto
.type() == power_manager::InputEvent_Type_LID_OPEN
);
629 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
630 LidEventReceived(open
, timestamp
));
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
;
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
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
,
672 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply
,
673 weak_ptr_factory_
.GetWeakPtr(), false,
674 power_manager::kRegisterSuspendDelayMethod
));
675 RegisterSuspendDelayImpl(
676 power_manager::kRegisterDarkSuspendDelayMethod
,
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_
)
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)
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_
;
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
;
733 power_manager_proxy_
->CallMethod(
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
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() {
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