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/power_manager/input_event.pb.h"
24 #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
25 #include "chromeos/dbus/power_manager/policy.pb.h"
26 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
27 #include "chromeos/dbus/power_manager/suspend.pb.h"
28 #include "components/device_event_log/device_event_log.h"
30 #include "dbus/message.h"
31 #include "dbus/object_path.h"
32 #include "dbus/object_proxy.h"
36 // Maximum amount of time that the power manager will wait for Chrome to
37 // say that it's ready for the system to be suspended, in milliseconds.
38 const int kSuspendDelayTimeoutMs
= 5000;
40 // Human-readable description of Chrome's suspend delay.
41 const char kSuspendDelayDescription
[] = "chrome";
43 // The PowerManagerClient implementation used in production.
44 class PowerManagerClientImpl
: public PowerManagerClient
{
46 PowerManagerClientImpl()
47 : origin_thread_id_(base::PlatformThread::CurrentId()),
48 power_manager_proxy_(NULL
),
49 suspend_delay_id_(-1),
50 has_suspend_delay_id_(false),
51 dark_suspend_delay_id_(-1),
52 has_dark_suspend_delay_id_(false),
53 pending_suspend_id_(-1),
54 suspend_is_pending_(false),
55 suspending_from_dark_resume_(false),
56 num_pending_suspend_readiness_callbacks_(0),
57 last_is_projecting_(false),
58 weak_ptr_factory_(this) {}
60 ~PowerManagerClientImpl() override
{
61 // Here we should unregister suspend notifications from powerd,
63 // - The lifetime of the PowerManagerClientImpl can extend past that of
65 // - power_manager can already detect that the client is gone and
66 // unregister our suspend delay.
69 // PowerManagerClient overrides:
71 void AddObserver(Observer
* observer
) override
{
72 CHECK(observer
); // http://crbug.com/119976
73 observers_
.AddObserver(observer
);
76 void RemoveObserver(Observer
* observer
) override
{
77 observers_
.RemoveObserver(observer
);
80 bool HasObserver(const Observer
* observer
) const override
{
81 return observers_
.HasObserver(observer
);
84 void SetRenderProcessManagerDelegate(
85 base::WeakPtr
<RenderProcessManagerDelegate
> delegate
) override
{
86 DCHECK(!render_process_manager_delegate_
)
87 << "There can be only one! ...RenderProcessManagerDelegate";
88 render_process_manager_delegate_
= delegate
;
91 void DecreaseScreenBrightness(bool allow_off
) override
{
92 dbus::MethodCall
method_call(
93 power_manager::kPowerManagerInterface
,
94 power_manager::kDecreaseScreenBrightnessMethod
);
95 dbus::MessageWriter
writer(&method_call
);
96 writer
.AppendBool(allow_off
);
97 power_manager_proxy_
->CallMethod(
99 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
100 dbus::ObjectProxy::EmptyResponseCallback());
103 void IncreaseScreenBrightness() override
{
104 SimpleMethodCallToPowerManager(
105 power_manager::kIncreaseScreenBrightnessMethod
);
108 void DecreaseKeyboardBrightness() override
{
109 SimpleMethodCallToPowerManager(
110 power_manager::kDecreaseKeyboardBrightnessMethod
);
113 void IncreaseKeyboardBrightness() override
{
114 SimpleMethodCallToPowerManager(
115 power_manager::kIncreaseKeyboardBrightnessMethod
);
118 void SetScreenBrightnessPercent(double percent
, bool gradual
) override
{
119 dbus::MethodCall
method_call(
120 power_manager::kPowerManagerInterface
,
121 power_manager::kSetScreenBrightnessPercentMethod
);
122 dbus::MessageWriter
writer(&method_call
);
123 writer
.AppendDouble(percent
);
126 power_manager::kBrightnessTransitionGradual
:
127 power_manager::kBrightnessTransitionInstant
);
128 power_manager_proxy_
->CallMethod(
130 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
131 dbus::ObjectProxy::EmptyResponseCallback());
134 void GetScreenBrightnessPercent(
135 const GetScreenBrightnessPercentCallback
& callback
) override
{
136 dbus::MethodCall
method_call(
137 power_manager::kPowerManagerInterface
,
138 power_manager::kGetScreenBrightnessPercentMethod
);
139 power_manager_proxy_
->CallMethod(
141 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
142 base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent
,
143 weak_ptr_factory_
.GetWeakPtr(), callback
));
146 void RequestStatusUpdate() override
{
147 POWER_LOG(USER
) << "RequestStatusUpdate";
148 dbus::MethodCall
method_call(
149 power_manager::kPowerManagerInterface
,
150 power_manager::kGetPowerSupplyPropertiesMethod
);
151 power_manager_proxy_
->CallMethod(
153 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
154 base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod
,
155 weak_ptr_factory_
.GetWeakPtr()));
158 void RequestSuspend() override
{
159 POWER_LOG(USER
) << "RequestSuspend";
160 SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod
);
163 void RequestRestart() override
{
164 POWER_LOG(USER
) << "RequestRestart";
165 SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod
);
168 void RequestShutdown() override
{
169 POWER_LOG(USER
) << "RequestShutdown";
170 SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod
);
173 void NotifyUserActivity(power_manager::UserActivityType type
) override
{
174 dbus::MethodCall
method_call(
175 power_manager::kPowerManagerInterface
,
176 power_manager::kHandleUserActivityMethod
);
177 dbus::MessageWriter
writer(&method_call
);
178 writer
.AppendInt32(type
);
180 power_manager_proxy_
->CallMethod(
182 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
183 dbus::ObjectProxy::EmptyResponseCallback());
186 void NotifyVideoActivity(bool is_fullscreen
) override
{
187 dbus::MethodCall
method_call(
188 power_manager::kPowerManagerInterface
,
189 power_manager::kHandleVideoActivityMethod
);
190 dbus::MessageWriter
writer(&method_call
);
191 writer
.AppendBool(is_fullscreen
);
193 power_manager_proxy_
->CallMethod(
195 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
196 dbus::ObjectProxy::EmptyResponseCallback());
199 void SetPolicy(const power_manager::PowerManagementPolicy
& policy
) override
{
200 POWER_LOG(USER
) << "SetPolicy";
201 dbus::MethodCall
method_call(
202 power_manager::kPowerManagerInterface
,
203 power_manager::kSetPolicyMethod
);
204 dbus::MessageWriter
writer(&method_call
);
205 if (!writer
.AppendProtoAsArrayOfBytes(policy
)) {
206 POWER_LOG(ERROR
) << "Error calling " << power_manager::kSetPolicyMethod
;
209 power_manager_proxy_
->CallMethod(
211 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
212 dbus::ObjectProxy::EmptyResponseCallback());
215 void SetIsProjecting(bool is_projecting
) override
{
216 POWER_LOG(USER
) << "SetIsProjecting";
217 dbus::MethodCall
method_call(
218 power_manager::kPowerManagerInterface
,
219 power_manager::kSetIsProjectingMethod
);
220 dbus::MessageWriter
writer(&method_call
);
221 writer
.AppendBool(is_projecting
);
222 power_manager_proxy_
->CallMethod(
224 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
225 dbus::ObjectProxy::EmptyResponseCallback());
226 last_is_projecting_
= is_projecting
;
229 base::Closure
GetSuspendReadinessCallback() override
{
230 DCHECK(OnOriginThread());
231 DCHECK(suspend_is_pending_
);
232 num_pending_suspend_readiness_callbacks_
++;
233 return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness
,
234 weak_ptr_factory_
.GetWeakPtr(), pending_suspend_id_
,
235 suspending_from_dark_resume_
);
238 int GetNumPendingSuspendReadinessCallbacks() override
{
239 return num_pending_suspend_readiness_callbacks_
;
243 void Init(dbus::Bus
* bus
) override
{
244 power_manager_proxy_
= bus
->GetObjectProxy(
245 power_manager::kPowerManagerServiceName
,
246 dbus::ObjectPath(power_manager::kPowerManagerServicePath
));
248 power_manager_proxy_
->SetNameOwnerChangedCallback(
249 base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived
,
250 weak_ptr_factory_
.GetWeakPtr()));
252 // Monitor the D-Bus signal for brightness changes. Only the power
253 // manager knows the actual brightness level. We don't cache the
254 // brightness level in Chrome as it'll make things less reliable.
255 power_manager_proxy_
->ConnectToSignal(
256 power_manager::kPowerManagerInterface
,
257 power_manager::kBrightnessChangedSignal
,
258 base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived
,
259 weak_ptr_factory_
.GetWeakPtr()),
260 base::Bind(&PowerManagerClientImpl::SignalConnected
,
261 weak_ptr_factory_
.GetWeakPtr()));
263 power_manager_proxy_
->ConnectToSignal(
264 power_manager::kPowerManagerInterface
,
265 power_manager::kPeripheralBatteryStatusSignal
,
266 base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived
,
267 weak_ptr_factory_
.GetWeakPtr()),
268 base::Bind(&PowerManagerClientImpl::SignalConnected
,
269 weak_ptr_factory_
.GetWeakPtr()));
271 power_manager_proxy_
->ConnectToSignal(
272 power_manager::kPowerManagerInterface
,
273 power_manager::kPowerSupplyPollSignal
,
274 base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived
,
275 weak_ptr_factory_
.GetWeakPtr()),
276 base::Bind(&PowerManagerClientImpl::SignalConnected
,
277 weak_ptr_factory_
.GetWeakPtr()));
279 power_manager_proxy_
->ConnectToSignal(
280 power_manager::kPowerManagerInterface
,
281 power_manager::kInputEventSignal
,
282 base::Bind(&PowerManagerClientImpl::InputEventReceived
,
283 weak_ptr_factory_
.GetWeakPtr()),
284 base::Bind(&PowerManagerClientImpl::SignalConnected
,
285 weak_ptr_factory_
.GetWeakPtr()));
287 power_manager_proxy_
->ConnectToSignal(
288 power_manager::kPowerManagerInterface
,
289 power_manager::kSuspendImminentSignal
,
291 &PowerManagerClientImpl::HandleSuspendImminent
,
292 weak_ptr_factory_
.GetWeakPtr(), false),
293 base::Bind(&PowerManagerClientImpl::SignalConnected
,
294 weak_ptr_factory_
.GetWeakPtr()));
296 power_manager_proxy_
->ConnectToSignal(
297 power_manager::kPowerManagerInterface
,
298 power_manager::kSuspendDoneSignal
,
299 base::Bind(&PowerManagerClientImpl::SuspendDoneReceived
,
300 weak_ptr_factory_
.GetWeakPtr()),
301 base::Bind(&PowerManagerClientImpl::SignalConnected
,
302 weak_ptr_factory_
.GetWeakPtr()));
304 power_manager_proxy_
->ConnectToSignal(
305 power_manager::kPowerManagerInterface
,
306 power_manager::kDarkSuspendImminentSignal
,
308 &PowerManagerClientImpl::HandleSuspendImminent
,
309 weak_ptr_factory_
.GetWeakPtr(), true),
310 base::Bind(&PowerManagerClientImpl::SignalConnected
,
311 weak_ptr_factory_
.GetWeakPtr()));
313 power_manager_proxy_
->ConnectToSignal(
314 power_manager::kPowerManagerInterface
,
315 power_manager::kIdleActionImminentSignal
,
317 &PowerManagerClientImpl::IdleActionImminentReceived
,
318 weak_ptr_factory_
.GetWeakPtr()),
319 base::Bind(&PowerManagerClientImpl::SignalConnected
,
320 weak_ptr_factory_
.GetWeakPtr()));
322 power_manager_proxy_
->ConnectToSignal(
323 power_manager::kPowerManagerInterface
,
324 power_manager::kIdleActionDeferredSignal
,
326 &PowerManagerClientImpl::IdleActionDeferredReceived
,
327 weak_ptr_factory_
.GetWeakPtr()),
328 base::Bind(&PowerManagerClientImpl::SignalConnected
,
329 weak_ptr_factory_
.GetWeakPtr()));
331 RegisterSuspendDelays();
335 // Returns true if the current thread is the origin thread.
336 bool OnOriginThread() {
337 return base::PlatformThread::CurrentId() == origin_thread_id_
;
340 // Called when a dbus signal is initially connected.
341 void SignalConnected(const std::string
& interface_name
,
342 const std::string
& signal_name
,
345 POWER_LOG(ERROR
) << "Failed to connect to signal " << signal_name
<< ".";
348 // Makes a method call to power manager with no arguments and no response.
349 void SimpleMethodCallToPowerManager(const std::string
& method_name
) {
350 dbus::MethodCall
method_call(power_manager::kPowerManagerInterface
,
352 power_manager_proxy_
->CallMethod(
354 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
355 dbus::ObjectProxy::EmptyResponseCallback());
358 void NameOwnerChangedReceived(const std::string
& old_owner
,
359 const std::string
& new_owner
) {
360 POWER_LOG(EVENT
) << "Power manager restarted. Old owner: "
361 << (old_owner
.empty() ? "[none]" : old_owner
.c_str())
363 << (new_owner
.empty() ? "[none]" : new_owner
.c_str());
364 suspend_is_pending_
= false;
365 pending_suspend_id_
= -1;
366 suspending_from_dark_resume_
= false;
367 if (!new_owner
.empty()) {
368 POWER_LOG(EVENT
) << "Sending initial state to power manager";
369 RegisterSuspendDelays();
370 SetIsProjecting(last_is_projecting_
);
371 FOR_EACH_OBSERVER(Observer
, observers_
, PowerManagerRestarted());
375 void BrightnessChangedReceived(dbus::Signal
* signal
) {
376 dbus::MessageReader
reader(signal
);
377 int32_t brightness_level
= 0;
378 bool user_initiated
= 0;
379 if (!(reader
.PopInt32(&brightness_level
) &&
380 reader
.PopBool(&user_initiated
))) {
381 POWER_LOG(ERROR
) << "Brightness changed signal had incorrect parameters: "
382 << signal
->ToString();
385 POWER_LOG(DEBUG
) << "Brightness changed to " << brightness_level
386 << ": user initiated " << user_initiated
;
387 FOR_EACH_OBSERVER(Observer
, observers_
,
388 BrightnessChanged(brightness_level
, user_initiated
));
391 void PeripheralBatteryStatusReceived(dbus::Signal
* signal
) {
392 dbus::MessageReader
reader(signal
);
393 power_manager::PeripheralBatteryStatus protobuf_status
;
394 if (!reader
.PopArrayOfBytesAsProto(&protobuf_status
)) {
395 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
396 << power_manager::kPeripheralBatteryStatusSignal
401 std::string path
= protobuf_status
.path();
402 std::string name
= protobuf_status
.name();
403 int level
= protobuf_status
.has_level() ? protobuf_status
.level() : -1;
405 POWER_LOG(DEBUG
) << "Device battery status received " << level
<< " for "
406 << name
<< " at " << path
;
408 FOR_EACH_OBSERVER(Observer
, observers_
,
409 PeripheralBatteryStatusReceived(path
, name
, level
));
412 void PowerSupplyPollReceived(dbus::Signal
* signal
) {
413 POWER_LOG(DEBUG
) << "Received power supply poll signal.";
414 dbus::MessageReader
reader(signal
);
415 power_manager::PowerSupplyProperties protobuf
;
416 if (reader
.PopArrayOfBytesAsProto(&protobuf
)) {
417 HandlePowerSupplyProperties(protobuf
);
419 POWER_LOG(ERROR
) << "Unable to decode "
420 << power_manager::kPowerSupplyPollSignal
<< " signal";
424 void OnGetPowerSupplyPropertiesMethod(dbus::Response
* response
) {
426 POWER_LOG(ERROR
) << "Error calling "
427 << power_manager::kGetPowerSupplyPropertiesMethod
;
431 dbus::MessageReader
reader(response
);
432 power_manager::PowerSupplyProperties protobuf
;
433 if (reader
.PopArrayOfBytesAsProto(&protobuf
)) {
434 HandlePowerSupplyProperties(protobuf
);
436 POWER_LOG(ERROR
) << "Unable to decode "
437 << power_manager::kGetPowerSupplyPropertiesMethod
442 void OnGetScreenBrightnessPercent(
443 const GetScreenBrightnessPercentCallback
& callback
,
444 dbus::Response
* response
) {
446 POWER_LOG(ERROR
) << "Error calling "
447 << power_manager::kGetScreenBrightnessPercentMethod
;
450 dbus::MessageReader
reader(response
);
451 double percent
= 0.0;
452 if (!reader
.PopDouble(&percent
))
453 POWER_LOG(ERROR
) << "Error reading response from powerd: "
454 << response
->ToString();
455 callback
.Run(percent
);
458 void HandlePowerSupplyProperties(
459 const power_manager::PowerSupplyProperties
& proto
) {
460 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(proto
));
461 const bool on_battery
= proto
.external_power() ==
462 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
;
463 base::PowerMonitorDeviceSource::SetPowerSource(on_battery
);
466 void HandleRegisterSuspendDelayReply(bool dark_suspend
,
467 const std::string
& method_name
,
468 dbus::Response
* response
) {
470 POWER_LOG(ERROR
) << "Error calling " << method_name
;
474 dbus::MessageReader
reader(response
);
475 power_manager::RegisterSuspendDelayReply protobuf
;
476 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
477 POWER_LOG(ERROR
) << "Unable to parse reply from " << method_name
;
482 dark_suspend_delay_id_
= protobuf
.delay_id();
483 has_dark_suspend_delay_id_
= true;
484 POWER_LOG(EVENT
) << "Registered dark suspend delay "
485 << dark_suspend_delay_id_
;
487 suspend_delay_id_
= protobuf
.delay_id();
488 has_suspend_delay_id_
= true;
489 POWER_LOG(EVENT
) << "Registered suspend delay " << suspend_delay_id_
;
493 void HandleSuspendImminent(bool in_dark_resume
, dbus::Signal
* signal
) {
494 std::string signal_name
= signal
->GetMember();
495 if ((in_dark_resume
&& !has_dark_suspend_delay_id_
) ||
496 (!in_dark_resume
&& !has_suspend_delay_id_
)) {
497 POWER_LOG(ERROR
) << "Received unrequested " << signal_name
<< " signal";
501 dbus::MessageReader
reader(signal
);
502 power_manager::SuspendImminent proto
;
503 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
504 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
505 << signal_name
<< " signal";
509 POWER_LOG(EVENT
) << "Got " << signal_name
510 << " signal announcing suspend attempt "
511 << proto
.suspend_id();
513 // If a previous suspend is pending from the same state we are currently in
514 // (fully powered on or in dark resume), then something's gone a little
516 if (suspend_is_pending_
&& suspending_from_dark_resume_
== in_dark_resume
) {
517 POWER_LOG(ERROR
) << "Got " << signal_name
518 << " signal about pending suspend attempt "
519 << proto
.suspend_id()
520 << " while still waiting on attempt "
521 << pending_suspend_id_
;
524 pending_suspend_id_
= proto
.suspend_id();
525 suspend_is_pending_
= true;
526 suspending_from_dark_resume_
= in_dark_resume
;
527 num_pending_suspend_readiness_callbacks_
= 0;
528 if (suspending_from_dark_resume_
)
529 FOR_EACH_OBSERVER(Observer
, observers_
, DarkSuspendImminent());
531 FOR_EACH_OBSERVER(Observer
, observers_
, SuspendImminent());
532 base::PowerMonitorDeviceSource::HandleSystemSuspending();
533 MaybeReportSuspendReadiness();
536 void SuspendDoneReceived(dbus::Signal
* signal
) {
537 dbus::MessageReader
reader(signal
);
538 power_manager::SuspendDone proto
;
539 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
540 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
541 << power_manager::kSuspendDoneSignal
<< " signal";
545 const base::TimeDelta duration
=
546 base::TimeDelta::FromInternalValue(proto
.suspend_duration());
547 POWER_LOG(EVENT
) << "Got " << power_manager::kSuspendDoneSignal
549 << " suspend_id=" << proto
.suspend_id()
550 << " duration=" << duration
.InSeconds() << " sec";
552 if (render_process_manager_delegate_
)
553 render_process_manager_delegate_
->SuspendDone();
556 PowerManagerClient::Observer
, observers_
, SuspendDone(duration
));
557 base::PowerMonitorDeviceSource::HandleSystemResumed();
560 void IdleActionImminentReceived(dbus::Signal
* signal
) {
561 dbus::MessageReader
reader(signal
);
562 power_manager::IdleActionImminent proto
;
563 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
564 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
565 << power_manager::kIdleActionImminentSignal
<< " signal";
568 FOR_EACH_OBSERVER(Observer
, observers_
,
569 IdleActionImminent(base::TimeDelta::FromInternalValue(
570 proto
.time_until_idle_action())));
573 void IdleActionDeferredReceived(dbus::Signal
* signal
) {
574 FOR_EACH_OBSERVER(Observer
, observers_
, IdleActionDeferred());
577 void InputEventReceived(dbus::Signal
* signal
) {
578 dbus::MessageReader
reader(signal
);
579 power_manager::InputEvent proto
;
580 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
581 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
582 << power_manager::kInputEventSignal
<< " signal";
586 base::TimeTicks timestamp
=
587 base::TimeTicks::FromInternalValue(proto
.timestamp());
588 POWER_LOG(USER
) << "Got " << power_manager::kInputEventSignal
<< " signal:"
589 << " type=" << proto
.type()
590 << " timestamp=" << proto
.timestamp();
591 switch (proto
.type()) {
592 case power_manager::InputEvent_Type_POWER_BUTTON_DOWN
:
593 case power_manager::InputEvent_Type_POWER_BUTTON_UP
: {
595 (proto
.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN
);
596 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
597 PowerButtonEventReceived(down
, timestamp
));
599 // Tell powerd that Chrome has handled power button presses.
601 dbus::MethodCall
method_call(
602 power_manager::kPowerManagerInterface
,
603 power_manager::kHandlePowerButtonAcknowledgmentMethod
);
604 dbus::MessageWriter
writer(&method_call
);
605 writer
.AppendInt64(proto
.timestamp());
606 power_manager_proxy_
->CallMethod(
608 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
609 dbus::ObjectProxy::EmptyResponseCallback());
613 case power_manager::InputEvent_Type_LID_OPEN
:
614 case power_manager::InputEvent_Type_LID_CLOSED
: {
616 (proto
.type() == power_manager::InputEvent_Type_LID_OPEN
);
617 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
618 LidEventReceived(open
, timestamp
));
624 void RegisterSuspendDelayImpl(
625 const std::string
& method_name
,
626 const power_manager::RegisterSuspendDelayRequest
& protobuf_request
,
627 dbus::ObjectProxy::ResponseCallback callback
) {
628 dbus::MethodCall
method_call(
629 power_manager::kPowerManagerInterface
, method_name
);
630 dbus::MessageWriter
writer(&method_call
);
632 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
633 POWER_LOG(ERROR
) << "Error constructing message for " << method_name
;
637 power_manager_proxy_
->CallMethod(
638 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
, callback
);
641 // Registers suspend delays with the power manager. This is usually only
642 // called at startup, but if the power manager restarts, we need to create new
644 void RegisterSuspendDelays() {
645 // Throw out any old delay that was registered.
646 suspend_delay_id_
= -1;
647 has_suspend_delay_id_
= false;
648 dark_suspend_delay_id_
= -1;
649 has_dark_suspend_delay_id_
= false;
651 power_manager::RegisterSuspendDelayRequest protobuf_request
;
652 base::TimeDelta timeout
=
653 base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs
);
654 protobuf_request
.set_timeout(timeout
.ToInternalValue());
655 protobuf_request
.set_description(kSuspendDelayDescription
);
657 RegisterSuspendDelayImpl(
658 power_manager::kRegisterSuspendDelayMethod
,
660 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply
,
661 weak_ptr_factory_
.GetWeakPtr(), false,
662 power_manager::kRegisterSuspendDelayMethod
));
663 RegisterSuspendDelayImpl(
664 power_manager::kRegisterDarkSuspendDelayMethod
,
666 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply
,
667 weak_ptr_factory_
.GetWeakPtr(), true,
668 power_manager::kRegisterDarkSuspendDelayMethod
));
671 // Records the fact that an observer has finished doing asynchronous work
672 // that was blocking a pending suspend attempt and possibly reports
673 // suspend readiness to powerd. Called by callbacks returned via
674 // GetSuspendReadinessCallback().
675 void HandleObserverSuspendReadiness(int32_t suspend_id
, bool in_dark_resume
) {
676 DCHECK(OnOriginThread());
677 if (!suspend_is_pending_
|| suspend_id
!= pending_suspend_id_
||
678 in_dark_resume
!= suspending_from_dark_resume_
)
681 num_pending_suspend_readiness_callbacks_
--;
682 MaybeReportSuspendReadiness();
685 // Reports suspend readiness to powerd if no observers are still holding
686 // suspend readiness callbacks.
687 void MaybeReportSuspendReadiness() {
688 if (!suspend_is_pending_
|| num_pending_suspend_readiness_callbacks_
> 0)
691 std::string method_name
;
692 int32_t delay_id
= -1;
693 if (suspending_from_dark_resume_
) {
694 method_name
= power_manager::kHandleDarkSuspendReadinessMethod
;
695 delay_id
= dark_suspend_delay_id_
;
697 method_name
= power_manager::kHandleSuspendReadinessMethod
;
698 delay_id
= suspend_delay_id_
;
701 if (render_process_manager_delegate_
&& !suspending_from_dark_resume_
)
702 render_process_manager_delegate_
->SuspendImminent();
704 dbus::MethodCall
method_call(
705 power_manager::kPowerManagerInterface
, method_name
);
706 dbus::MessageWriter
writer(&method_call
);
708 POWER_LOG(EVENT
) << "Announcing readiness of suspend delay " << delay_id
709 << " for suspend attempt " << pending_suspend_id_
;
710 power_manager::SuspendReadinessInfo protobuf_request
;
711 protobuf_request
.set_delay_id(delay_id
);
712 protobuf_request
.set_suspend_id(pending_suspend_id_
);
714 pending_suspend_id_
= -1;
715 suspend_is_pending_
= false;
717 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
718 POWER_LOG(ERROR
) << "Error constructing message for " << method_name
;
721 power_manager_proxy_
->CallMethod(
723 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
724 dbus::ObjectProxy::EmptyResponseCallback());
727 // Origin thread (i.e. the UI thread in production).
728 base::PlatformThreadId origin_thread_id_
;
730 dbus::ObjectProxy
* power_manager_proxy_
;
731 base::ObserverList
<Observer
> observers_
;
733 // The delay_id_ obtained from the RegisterSuspendDelay request.
734 int32_t suspend_delay_id_
;
735 bool has_suspend_delay_id_
;
737 // The delay_id_ obtained from the RegisterDarkSuspendDelay request.
738 int32_t dark_suspend_delay_id_
;
739 bool has_dark_suspend_delay_id_
;
741 // powerd-supplied ID corresponding to an imminent suspend attempt that is
742 // currently being delayed.
743 int32_t pending_suspend_id_
;
744 bool suspend_is_pending_
;
746 // Set to true when the suspend currently being delayed was triggered during a
747 // dark resume. Since |pending_suspend_id_| and |suspend_is_pending_| are
748 // both shared by normal and dark suspends, |suspending_from_dark_resume_|
749 // helps distinguish the context within which these variables are being used.
750 bool suspending_from_dark_resume_
;
752 // Number of callbacks that have been returned by
753 // GetSuspendReadinessCallback() during the currently-pending suspend
754 // attempt but have not yet been called.
755 int num_pending_suspend_readiness_callbacks_
;
757 // Last state passed to SetIsProjecting().
758 bool last_is_projecting_
;
760 // The delegate used to manage the power consumption of Chrome's renderer
762 base::WeakPtr
<RenderProcessManagerDelegate
> render_process_manager_delegate_
;
764 // Note: This should remain the last member so it'll be destroyed and
765 // invalidate its weak pointers before any other members are destroyed.
766 base::WeakPtrFactory
<PowerManagerClientImpl
> weak_ptr_factory_
;
768 DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl
);
771 // The PowerManagerClient implementation used on Linux desktop,
772 // which does nothing.
773 class PowerManagerClientStubImpl
: public PowerManagerClient
{
775 PowerManagerClientStubImpl()
776 : discharging_(true),
777 battery_percentage_(40),
781 num_pending_suspend_readiness_callbacks_(0),
782 weak_ptr_factory_(this) {}
784 ~PowerManagerClientStubImpl() override
{}
786 int num_pending_suspend_readiness_callbacks() const {
787 return num_pending_suspend_readiness_callbacks_
;
790 // PowerManagerClient overrides:
791 void Init(dbus::Bus
* bus
) override
{
792 ParseCommandLineSwitch();
793 if (power_cycle_delay_
!= base::TimeDelta()) {
794 update_timer_
.Start(FROM_HERE
,
797 &PowerManagerClientStubImpl::UpdateStatus
);
801 void AddObserver(Observer
* observer
) override
{
802 observers_
.AddObserver(observer
);
805 void RemoveObserver(Observer
* observer
) override
{
806 observers_
.RemoveObserver(observer
);
809 bool HasObserver(const Observer
* observer
) const override
{
810 return observers_
.HasObserver(observer
);
813 void SetRenderProcessManagerDelegate(
814 base::WeakPtr
<RenderProcessManagerDelegate
> delegate
) override
{}
816 void DecreaseScreenBrightness(bool allow_off
) override
{
817 POWER_LOG(USER
) << "Requested to descrease screen brightness";
818 SetBrightness(brightness_
- 5.0, true);
821 void IncreaseScreenBrightness() override
{
822 POWER_LOG(USER
) << "Requested to increase screen brightness";
823 SetBrightness(brightness_
+ 5.0, true);
826 void SetScreenBrightnessPercent(double percent
, bool gradual
) override
{
827 POWER_LOG(USER
) << "Requested to set screen brightness to " << percent
828 << "% " << (gradual
? "gradually" : "instantaneously");
829 SetBrightness(percent
, false);
832 void GetScreenBrightnessPercent(
833 const GetScreenBrightnessPercentCallback
& callback
) override
{
834 POWER_LOG(USER
) << "Requested to get screen brightness";
835 callback
.Run(brightness_
);
838 void DecreaseKeyboardBrightness() override
{
839 POWER_LOG(USER
) << "Requested to descrease keyboard brightness";
842 void IncreaseKeyboardBrightness() override
{
843 POWER_LOG(USER
) << "Requested to increase keyboard brightness";
846 void RequestStatusUpdate() override
{
847 POWER_LOG(USER
) << "Requested status update";
848 base::MessageLoop::current()->PostTask(
849 FROM_HERE
, base::Bind(&PowerManagerClientStubImpl::UpdateStatus
,
850 weak_ptr_factory_
.GetWeakPtr()));
853 void RequestSuspend() override
{}
854 void RequestRestart() override
{}
855 void RequestShutdown() override
{}
857 void NotifyUserActivity(power_manager::UserActivityType type
) override
{}
858 void NotifyVideoActivity(bool is_fullscreen
) override
{}
859 void SetPolicy(const power_manager::PowerManagementPolicy
& policy
) override
{}
860 void SetIsProjecting(bool is_projecting
) override
{}
861 base::Closure
GetSuspendReadinessCallback() override
{
862 num_pending_suspend_readiness_callbacks_
++;
863 return base::Bind(&PowerManagerClientStubImpl::HandleSuspendReadiness
,
864 weak_ptr_factory_
.GetWeakPtr());
866 int GetNumPendingSuspendReadinessCallbacks() override
{
867 return num_pending_suspend_readiness_callbacks_
;
871 void HandleSuspendReadiness() {
872 num_pending_suspend_readiness_callbacks_
--;
875 void UpdateStatus() {
876 if (pause_count_
> 0) {
878 if (pause_count_
== 2)
879 discharging_
= !discharging_
;
882 battery_percentage_
-= (battery_percentage_
<= 10 ? 1 : 10);
884 battery_percentage_
+= (battery_percentage_
>= 10 ? 10 : 1);
885 battery_percentage_
= std::min(std::max(battery_percentage_
, 0), 100);
886 // We pause at 0 and 100% so that it's easier to check those conditions.
887 if (battery_percentage_
== 0 || battery_percentage_
== 100) {
889 if (battery_percentage_
== 100)
890 cycle_count_
= (cycle_count_
+ 1) % 3;
894 const int kSecondsToEmptyFullBattery
= 3 * 60 * 60; // 3 hours.
895 int64 remaining_battery_time
=
896 std::max(1, battery_percentage_
* kSecondsToEmptyFullBattery
/ 100);
900 switch (cycle_count_
) {
902 // Say that the system is charging with AC connected and
903 // discharging without any charger connected.
904 props_
.set_external_power(discharging_
?
905 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
:
906 power_manager::PowerSupplyProperties_ExternalPower_AC
);
909 // Say that the system is both charging and discharging on USB
910 // (i.e. a low-power charger).
911 props_
.set_external_power(
912 power_manager::PowerSupplyProperties_ExternalPower_USB
);
915 // Say that the system is both charging and discharging on AC.
916 props_
.set_external_power(
917 power_manager::PowerSupplyProperties_ExternalPower_AC
);
920 NOTREACHED() << "Unhandled cycle " << cycle_count_
;
923 if (battery_percentage_
== 100 && !discharging_
) {
924 props_
.set_battery_state(
925 power_manager::PowerSupplyProperties_BatteryState_FULL
);
926 } else if (!discharging_
) {
927 props_
.set_battery_state(
928 power_manager::PowerSupplyProperties_BatteryState_CHARGING
);
929 props_
.set_battery_time_to_full_sec(std::max(static_cast<int64
>(1),
930 kSecondsToEmptyFullBattery
- remaining_battery_time
));
932 props_
.set_battery_state(
933 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING
);
934 props_
.set_battery_time_to_empty_sec(remaining_battery_time
);
937 props_
.set_battery_percent(battery_percentage_
);
938 props_
.set_is_calculating_battery_time(pause_count_
> 1);
940 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(props_
));
943 void SetBrightness(double percent
, bool user_initiated
) {
944 brightness_
= std::min(std::max(0.0, percent
), 100.0);
945 int brightness_level
= static_cast<int>(brightness_
);
946 FOR_EACH_OBSERVER(Observer
, observers_
,
947 BrightnessChanged(brightness_level
, user_initiated
));
950 void ParseCommandLineSwitch() {
951 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
952 if (!command_line
|| !command_line
->HasSwitch(switches::kPowerStub
))
954 std::string option_str
=
955 command_line
->GetSwitchValueASCII(switches::kPowerStub
);
956 base::StringPairs string_pairs
;
957 base::SplitStringIntoKeyValuePairs(option_str
, '=', ',', &string_pairs
);
958 for (base::StringPairs::iterator iter
= string_pairs
.begin();
959 iter
!= string_pairs
.end(); ++iter
) {
960 ParseOption((*iter
).first
, (*iter
).second
);
964 void ParseOption(const std::string
& arg0
, const std::string
& arg1
) {
965 if (arg0
== "cycle" || arg0
== "interactive") {
968 base::StringToInt(arg1
, &seconds
);
969 power_cycle_delay_
= base::TimeDelta::FromSeconds(seconds
);
973 base::TimeDelta power_cycle_delay_
; // Time over which to cycle power state
975 int battery_percentage_
;
979 base::ObserverList
<Observer
> observers_
;
980 base::RepeatingTimer
<PowerManagerClientStubImpl
> update_timer_
;
981 power_manager::PowerSupplyProperties props_
;
983 // Number of callbacks returned by GetSuspendReadinessCallback() but not yet
985 int num_pending_suspend_readiness_callbacks_
;
987 // Note: This should remain the last member so it'll be destroyed and
988 // invalidate its weak pointers before any other members are destroyed.
989 base::WeakPtrFactory
<PowerManagerClientStubImpl
> weak_ptr_factory_
;
992 PowerManagerClient::PowerManagerClient() {
995 PowerManagerClient::~PowerManagerClient() {
999 PowerManagerClient
* PowerManagerClient::Create(
1000 DBusClientImplementationType type
) {
1001 if (type
== REAL_DBUS_CLIENT_IMPLEMENTATION
)
1002 return new PowerManagerClientImpl();
1003 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION
, type
);
1004 return new PowerManagerClientStubImpl();
1007 } // namespace chromeos