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/callback.h"
11 #include "base/command_line.h"
12 #include "base/format_macros.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/observer_list.h"
17 #include "base/power_monitor/power_monitor_device_source.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/threading/platform_thread.h"
22 #include "base/time/time.h"
23 #include "base/timer/timer.h"
24 #include "chromeos/chromeos_switches.h"
25 #include "chromeos/dbus/power_manager/input_event.pb.h"
26 #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
27 #include "chromeos/dbus/power_manager/policy.pb.h"
28 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
29 #include "chromeos/dbus/power_manager/suspend.pb.h"
30 #include "chromeos/device_event_log.h"
32 #include "dbus/message.h"
33 #include "dbus/object_path.h"
34 #include "dbus/object_proxy.h"
38 // Maximum amount of time that the power manager will wait for Chrome to
39 // say that it's ready for the system to be suspended, in milliseconds.
40 const int kSuspendDelayTimeoutMs
= 5000;
42 // Human-readable description of Chrome's suspend delay.
43 const char kSuspendDelayDescription
[] = "chrome";
45 // The PowerManagerClient implementation used in production.
46 class PowerManagerClientImpl
: public PowerManagerClient
{
48 PowerManagerClientImpl()
49 : origin_thread_id_(base::PlatformThread::CurrentId()),
50 power_manager_proxy_(NULL
),
51 suspend_delay_id_(-1),
52 has_suspend_delay_id_(false),
53 dark_suspend_delay_id_(-1),
54 has_dark_suspend_delay_id_(false),
55 pending_suspend_id_(-1),
56 suspend_is_pending_(false),
57 suspending_from_dark_resume_(false),
58 num_pending_suspend_readiness_callbacks_(0),
59 last_is_projecting_(false),
60 weak_ptr_factory_(this) {}
62 virtual ~PowerManagerClientImpl() {
63 // Here we should unregister suspend notifications from powerd,
65 // - The lifetime of the PowerManagerClientImpl can extend past that of
67 // - power_manager can already detect that the client is gone and
68 // unregister our suspend delay.
71 // PowerManagerClient overrides:
73 virtual void AddObserver(Observer
* observer
) override
{
74 CHECK(observer
); // http://crbug.com/119976
75 observers_
.AddObserver(observer
);
78 virtual void RemoveObserver(Observer
* observer
) override
{
79 observers_
.RemoveObserver(observer
);
82 virtual bool HasObserver(const Observer
* observer
) const override
{
83 return observers_
.HasObserver(observer
);
86 virtual void SetRenderProcessManagerDelegate(
87 base::WeakPtr
<RenderProcessManagerDelegate
> delegate
) override
{
88 DCHECK(!render_process_manager_delegate_
)
89 << "There can be only one! ...RenderProcessManagerDelegate";
90 render_process_manager_delegate_
= delegate
;
93 virtual void DecreaseScreenBrightness(bool allow_off
) override
{
94 dbus::MethodCall
method_call(
95 power_manager::kPowerManagerInterface
,
96 power_manager::kDecreaseScreenBrightnessMethod
);
97 dbus::MessageWriter
writer(&method_call
);
98 writer
.AppendBool(allow_off
);
99 power_manager_proxy_
->CallMethod(
101 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
102 dbus::ObjectProxy::EmptyResponseCallback());
105 virtual void IncreaseScreenBrightness() override
{
106 SimpleMethodCallToPowerManager(
107 power_manager::kIncreaseScreenBrightnessMethod
);
110 virtual void DecreaseKeyboardBrightness() override
{
111 SimpleMethodCallToPowerManager(
112 power_manager::kDecreaseKeyboardBrightnessMethod
);
115 virtual void IncreaseKeyboardBrightness() override
{
116 SimpleMethodCallToPowerManager(
117 power_manager::kIncreaseKeyboardBrightnessMethod
);
120 virtual void SetScreenBrightnessPercent(double percent
,
121 bool gradual
) override
{
122 dbus::MethodCall
method_call(
123 power_manager::kPowerManagerInterface
,
124 power_manager::kSetScreenBrightnessPercentMethod
);
125 dbus::MessageWriter
writer(&method_call
);
126 writer
.AppendDouble(percent
);
129 power_manager::kBrightnessTransitionGradual
:
130 power_manager::kBrightnessTransitionInstant
);
131 power_manager_proxy_
->CallMethod(
133 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
134 dbus::ObjectProxy::EmptyResponseCallback());
137 virtual void GetScreenBrightnessPercent(
138 const GetScreenBrightnessPercentCallback
& callback
) override
{
139 dbus::MethodCall
method_call(
140 power_manager::kPowerManagerInterface
,
141 power_manager::kGetScreenBrightnessPercentMethod
);
142 power_manager_proxy_
->CallMethod(
144 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
145 base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent
,
146 weak_ptr_factory_
.GetWeakPtr(), callback
));
149 virtual void RequestStatusUpdate() override
{
150 POWER_LOG(USER
) << "RequestStatusUpdate";
151 dbus::MethodCall
method_call(
152 power_manager::kPowerManagerInterface
,
153 power_manager::kGetPowerSupplyPropertiesMethod
);
154 power_manager_proxy_
->CallMethod(
156 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
157 base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod
,
158 weak_ptr_factory_
.GetWeakPtr()));
161 virtual void RequestSuspend() override
{
162 POWER_LOG(USER
) << "RequestSuspend";
163 SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod
);
166 virtual void RequestRestart() override
{
167 POWER_LOG(USER
) << "RequestRestart";
168 SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod
);
171 virtual void RequestShutdown() override
{
172 POWER_LOG(USER
) << "RequestShutdown";
173 SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod
);
176 virtual void NotifyUserActivity(
177 power_manager::UserActivityType type
) override
{
178 dbus::MethodCall
method_call(
179 power_manager::kPowerManagerInterface
,
180 power_manager::kHandleUserActivityMethod
);
181 dbus::MessageWriter
writer(&method_call
);
182 writer
.AppendInt32(type
);
184 power_manager_proxy_
->CallMethod(
186 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
187 dbus::ObjectProxy::EmptyResponseCallback());
190 virtual void NotifyVideoActivity(bool is_fullscreen
) override
{
191 dbus::MethodCall
method_call(
192 power_manager::kPowerManagerInterface
,
193 power_manager::kHandleVideoActivityMethod
);
194 dbus::MessageWriter
writer(&method_call
);
195 writer
.AppendBool(is_fullscreen
);
197 power_manager_proxy_
->CallMethod(
199 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
200 dbus::ObjectProxy::EmptyResponseCallback());
203 virtual void SetPolicy(
204 const power_manager::PowerManagementPolicy
& policy
) override
{
205 POWER_LOG(USER
) << "SetPolicy";
206 dbus::MethodCall
method_call(
207 power_manager::kPowerManagerInterface
,
208 power_manager::kSetPolicyMethod
);
209 dbus::MessageWriter
writer(&method_call
);
210 if (!writer
.AppendProtoAsArrayOfBytes(policy
)) {
211 POWER_LOG(ERROR
) << "Error calling " << power_manager::kSetPolicyMethod
;
214 power_manager_proxy_
->CallMethod(
216 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
217 dbus::ObjectProxy::EmptyResponseCallback());
220 virtual void SetIsProjecting(bool is_projecting
) override
{
221 POWER_LOG(USER
) << "SetIsProjecting";
222 dbus::MethodCall
method_call(
223 power_manager::kPowerManagerInterface
,
224 power_manager::kSetIsProjectingMethod
);
225 dbus::MessageWriter
writer(&method_call
);
226 writer
.AppendBool(is_projecting
);
227 power_manager_proxy_
->CallMethod(
229 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
230 dbus::ObjectProxy::EmptyResponseCallback());
231 last_is_projecting_
= is_projecting
;
234 virtual base::Closure
GetSuspendReadinessCallback() override
{
235 DCHECK(OnOriginThread());
236 DCHECK(suspend_is_pending_
);
237 num_pending_suspend_readiness_callbacks_
++;
238 return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness
,
239 weak_ptr_factory_
.GetWeakPtr(), pending_suspend_id_
,
240 suspending_from_dark_resume_
);
243 virtual int GetNumPendingSuspendReadinessCallbacks() override
{
244 return num_pending_suspend_readiness_callbacks_
;
248 virtual void Init(dbus::Bus
* bus
) override
{
249 power_manager_proxy_
= bus
->GetObjectProxy(
250 power_manager::kPowerManagerServiceName
,
251 dbus::ObjectPath(power_manager::kPowerManagerServicePath
));
253 power_manager_proxy_
->SetNameOwnerChangedCallback(
254 base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived
,
255 weak_ptr_factory_
.GetWeakPtr()));
257 // Monitor the D-Bus signal for brightness changes. Only the power
258 // manager knows the actual brightness level. We don't cache the
259 // brightness level in Chrome as it'll make things less reliable.
260 power_manager_proxy_
->ConnectToSignal(
261 power_manager::kPowerManagerInterface
,
262 power_manager::kBrightnessChangedSignal
,
263 base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived
,
264 weak_ptr_factory_
.GetWeakPtr()),
265 base::Bind(&PowerManagerClientImpl::SignalConnected
,
266 weak_ptr_factory_
.GetWeakPtr()));
268 power_manager_proxy_
->ConnectToSignal(
269 power_manager::kPowerManagerInterface
,
270 power_manager::kPeripheralBatteryStatusSignal
,
271 base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived
,
272 weak_ptr_factory_
.GetWeakPtr()),
273 base::Bind(&PowerManagerClientImpl::SignalConnected
,
274 weak_ptr_factory_
.GetWeakPtr()));
276 power_manager_proxy_
->ConnectToSignal(
277 power_manager::kPowerManagerInterface
,
278 power_manager::kPowerSupplyPollSignal
,
279 base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived
,
280 weak_ptr_factory_
.GetWeakPtr()),
281 base::Bind(&PowerManagerClientImpl::SignalConnected
,
282 weak_ptr_factory_
.GetWeakPtr()));
284 power_manager_proxy_
->ConnectToSignal(
285 power_manager::kPowerManagerInterface
,
286 power_manager::kInputEventSignal
,
287 base::Bind(&PowerManagerClientImpl::InputEventReceived
,
288 weak_ptr_factory_
.GetWeakPtr()),
289 base::Bind(&PowerManagerClientImpl::SignalConnected
,
290 weak_ptr_factory_
.GetWeakPtr()));
292 power_manager_proxy_
->ConnectToSignal(
293 power_manager::kPowerManagerInterface
,
294 power_manager::kSuspendImminentSignal
,
296 &PowerManagerClientImpl::HandleSuspendImminent
,
297 weak_ptr_factory_
.GetWeakPtr(), false),
298 base::Bind(&PowerManagerClientImpl::SignalConnected
,
299 weak_ptr_factory_
.GetWeakPtr()));
301 power_manager_proxy_
->ConnectToSignal(
302 power_manager::kPowerManagerInterface
,
303 power_manager::kSuspendDoneSignal
,
304 base::Bind(&PowerManagerClientImpl::SuspendDoneReceived
,
305 weak_ptr_factory_
.GetWeakPtr()),
306 base::Bind(&PowerManagerClientImpl::SignalConnected
,
307 weak_ptr_factory_
.GetWeakPtr()));
309 power_manager_proxy_
->ConnectToSignal(
310 power_manager::kPowerManagerInterface
,
311 power_manager::kDarkSuspendImminentSignal
,
313 &PowerManagerClientImpl::HandleSuspendImminent
,
314 weak_ptr_factory_
.GetWeakPtr(), true),
315 base::Bind(&PowerManagerClientImpl::SignalConnected
,
316 weak_ptr_factory_
.GetWeakPtr()));
318 power_manager_proxy_
->ConnectToSignal(
319 power_manager::kPowerManagerInterface
,
320 power_manager::kIdleActionImminentSignal
,
322 &PowerManagerClientImpl::IdleActionImminentReceived
,
323 weak_ptr_factory_
.GetWeakPtr()),
324 base::Bind(&PowerManagerClientImpl::SignalConnected
,
325 weak_ptr_factory_
.GetWeakPtr()));
327 power_manager_proxy_
->ConnectToSignal(
328 power_manager::kPowerManagerInterface
,
329 power_manager::kIdleActionDeferredSignal
,
331 &PowerManagerClientImpl::IdleActionDeferredReceived
,
332 weak_ptr_factory_
.GetWeakPtr()),
333 base::Bind(&PowerManagerClientImpl::SignalConnected
,
334 weak_ptr_factory_
.GetWeakPtr()));
336 RegisterSuspendDelays();
340 // Returns true if the current thread is the origin thread.
341 bool OnOriginThread() {
342 return base::PlatformThread::CurrentId() == origin_thread_id_
;
345 // Called when a dbus signal is initially connected.
346 void SignalConnected(const std::string
& interface_name
,
347 const std::string
& signal_name
,
350 POWER_LOG(ERROR
) << "Failed to connect to signal " << signal_name
<< ".";
353 // Makes a method call to power manager with no arguments and no response.
354 void SimpleMethodCallToPowerManager(const std::string
& method_name
) {
355 dbus::MethodCall
method_call(power_manager::kPowerManagerInterface
,
357 power_manager_proxy_
->CallMethod(
359 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
360 dbus::ObjectProxy::EmptyResponseCallback());
363 void NameOwnerChangedReceived(const std::string
& old_owner
,
364 const std::string
& new_owner
) {
365 POWER_LOG(EVENT
) << "Power manager restarted. Old owner: "
366 << (old_owner
.empty() ? "[none]" : old_owner
.c_str())
368 << (new_owner
.empty() ? "[none]" : new_owner
.c_str());
369 suspend_is_pending_
= false;
370 pending_suspend_id_
= -1;
371 suspending_from_dark_resume_
= false;
372 if (!new_owner
.empty()) {
373 POWER_LOG(EVENT
) << "Sending initial state to power manager";
374 RegisterSuspendDelays();
375 SetIsProjecting(last_is_projecting_
);
376 FOR_EACH_OBSERVER(Observer
, observers_
, PowerManagerRestarted());
380 void BrightnessChangedReceived(dbus::Signal
* signal
) {
381 dbus::MessageReader
reader(signal
);
382 int32_t brightness_level
= 0;
383 bool user_initiated
= 0;
384 if (!(reader
.PopInt32(&brightness_level
) &&
385 reader
.PopBool(&user_initiated
))) {
386 POWER_LOG(ERROR
) << "Brightness changed signal had incorrect parameters: "
387 << signal
->ToString();
390 POWER_LOG(DEBUG
) << "Brightness changed to " << brightness_level
391 << ": user initiated " << user_initiated
;
392 FOR_EACH_OBSERVER(Observer
, observers_
,
393 BrightnessChanged(brightness_level
, user_initiated
));
396 void PeripheralBatteryStatusReceived(dbus::Signal
* signal
) {
397 dbus::MessageReader
reader(signal
);
398 power_manager::PeripheralBatteryStatus protobuf_status
;
399 if (!reader
.PopArrayOfBytesAsProto(&protobuf_status
)) {
400 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
401 << power_manager::kPeripheralBatteryStatusSignal
406 std::string path
= protobuf_status
.path();
407 std::string name
= protobuf_status
.name();
408 int level
= protobuf_status
.has_level() ? protobuf_status
.level() : -1;
410 POWER_LOG(DEBUG
) << "Device battery status received " << level
<< " for "
411 << name
<< " at " << path
;
413 FOR_EACH_OBSERVER(Observer
, observers_
,
414 PeripheralBatteryStatusReceived(path
, name
, level
));
417 void PowerSupplyPollReceived(dbus::Signal
* signal
) {
418 POWER_LOG(DEBUG
) << "Received power supply poll signal.";
419 dbus::MessageReader
reader(signal
);
420 power_manager::PowerSupplyProperties protobuf
;
421 if (reader
.PopArrayOfBytesAsProto(&protobuf
)) {
422 HandlePowerSupplyProperties(protobuf
);
424 POWER_LOG(ERROR
) << "Unable to decode "
425 << power_manager::kPowerSupplyPollSignal
<< " signal";
429 void OnGetPowerSupplyPropertiesMethod(dbus::Response
* response
) {
431 POWER_LOG(ERROR
) << "Error calling "
432 << power_manager::kGetPowerSupplyPropertiesMethod
;
436 dbus::MessageReader
reader(response
);
437 power_manager::PowerSupplyProperties protobuf
;
438 if (reader
.PopArrayOfBytesAsProto(&protobuf
)) {
439 HandlePowerSupplyProperties(protobuf
);
441 POWER_LOG(ERROR
) << "Unable to decode "
442 << power_manager::kGetPowerSupplyPropertiesMethod
447 void OnGetScreenBrightnessPercent(
448 const GetScreenBrightnessPercentCallback
& callback
,
449 dbus::Response
* response
) {
451 POWER_LOG(ERROR
) << "Error calling "
452 << power_manager::kGetScreenBrightnessPercentMethod
;
455 dbus::MessageReader
reader(response
);
456 double percent
= 0.0;
457 if (!reader
.PopDouble(&percent
))
458 POWER_LOG(ERROR
) << "Error reading response from powerd: "
459 << response
->ToString();
460 callback
.Run(percent
);
463 void HandlePowerSupplyProperties(
464 const power_manager::PowerSupplyProperties
& proto
) {
465 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(proto
));
466 const bool on_battery
= proto
.external_power() ==
467 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
;
468 base::PowerMonitorDeviceSource::SetPowerSource(on_battery
);
471 void HandleRegisterSuspendDelayReply(bool dark_suspend
,
472 const std::string
& method_name
,
473 dbus::Response
* response
) {
475 POWER_LOG(ERROR
) << "Error calling " << method_name
;
479 dbus::MessageReader
reader(response
);
480 power_manager::RegisterSuspendDelayReply protobuf
;
481 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
482 POWER_LOG(ERROR
) << "Unable to parse reply from " << method_name
;
487 dark_suspend_delay_id_
= protobuf
.delay_id();
488 has_dark_suspend_delay_id_
= true;
489 POWER_LOG(EVENT
) << "Registered dark suspend delay "
490 << dark_suspend_delay_id_
;
492 suspend_delay_id_
= protobuf
.delay_id();
493 has_suspend_delay_id_
= true;
494 POWER_LOG(EVENT
) << "Registered suspend delay " << suspend_delay_id_
;
498 void HandleSuspendImminent(bool in_dark_resume
, dbus::Signal
* signal
) {
499 std::string signal_name
= signal
->GetMember();
500 if ((in_dark_resume
&& !has_dark_suspend_delay_id_
) ||
501 (!in_dark_resume
&& !has_suspend_delay_id_
)) {
502 POWER_LOG(ERROR
) << "Received unrequested " << signal_name
<< " signal";
506 dbus::MessageReader
reader(signal
);
507 power_manager::SuspendImminent proto
;
508 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
509 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
510 << signal_name
<< " signal";
514 POWER_LOG(EVENT
) << "Got " << signal_name
515 << " signal announcing suspend attempt "
516 << proto
.suspend_id();
518 // If a previous suspend is pending from the same state we are currently in
519 // (fully powered on or in dark resume), then something's gone a little
521 if (suspend_is_pending_
&& suspending_from_dark_resume_
== in_dark_resume
) {
522 POWER_LOG(ERROR
) << "Got " << signal_name
523 << " signal about pending suspend attempt "
524 << proto
.suspend_id()
525 << " while still waiting on attempt "
526 << pending_suspend_id_
;
529 pending_suspend_id_
= proto
.suspend_id();
530 suspend_is_pending_
= true;
531 suspending_from_dark_resume_
= in_dark_resume
;
532 num_pending_suspend_readiness_callbacks_
= 0;
533 if (suspending_from_dark_resume_
)
534 FOR_EACH_OBSERVER(Observer
, observers_
, DarkSuspendImminent());
536 FOR_EACH_OBSERVER(Observer
, observers_
, SuspendImminent());
537 base::PowerMonitorDeviceSource::HandleSystemSuspending();
538 MaybeReportSuspendReadiness();
541 void SuspendDoneReceived(dbus::Signal
* signal
) {
542 dbus::MessageReader
reader(signal
);
543 power_manager::SuspendDone proto
;
544 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
545 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
546 << power_manager::kSuspendDoneSignal
<< " signal";
550 const base::TimeDelta duration
=
551 base::TimeDelta::FromInternalValue(proto
.suspend_duration());
552 POWER_LOG(EVENT
) << "Got " << power_manager::kSuspendDoneSignal
554 << " suspend_id=" << proto
.suspend_id()
555 << " duration=" << duration
.InSeconds() << " sec";
557 if (render_process_manager_delegate_
)
558 render_process_manager_delegate_
->SuspendDone();
561 PowerManagerClient::Observer
, observers_
, SuspendDone(duration
));
562 base::PowerMonitorDeviceSource::HandleSystemResumed();
565 void IdleActionImminentReceived(dbus::Signal
* signal
) {
566 dbus::MessageReader
reader(signal
);
567 power_manager::IdleActionImminent proto
;
568 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
569 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
570 << power_manager::kIdleActionImminentSignal
<< " signal";
573 FOR_EACH_OBSERVER(Observer
, observers_
,
574 IdleActionImminent(base::TimeDelta::FromInternalValue(
575 proto
.time_until_idle_action())));
578 void IdleActionDeferredReceived(dbus::Signal
* signal
) {
579 FOR_EACH_OBSERVER(Observer
, observers_
, IdleActionDeferred());
582 void InputEventReceived(dbus::Signal
* signal
) {
583 dbus::MessageReader
reader(signal
);
584 power_manager::InputEvent proto
;
585 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
586 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
587 << power_manager::kInputEventSignal
<< " signal";
591 base::TimeTicks timestamp
=
592 base::TimeTicks::FromInternalValue(proto
.timestamp());
593 POWER_LOG(USER
) << "Got " << power_manager::kInputEventSignal
<< " signal:"
594 << " type=" << proto
.type()
595 << " timestamp=" << proto
.timestamp();
596 switch (proto
.type()) {
597 case power_manager::InputEvent_Type_POWER_BUTTON_DOWN
:
598 case power_manager::InputEvent_Type_POWER_BUTTON_UP
: {
600 (proto
.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN
);
601 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
602 PowerButtonEventReceived(down
, timestamp
));
604 // Tell powerd that Chrome has handled power button presses.
606 dbus::MethodCall
method_call(
607 power_manager::kPowerManagerInterface
,
608 power_manager::kHandlePowerButtonAcknowledgmentMethod
);
609 dbus::MessageWriter
writer(&method_call
);
610 writer
.AppendInt64(proto
.timestamp());
611 power_manager_proxy_
->CallMethod(
613 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
614 dbus::ObjectProxy::EmptyResponseCallback());
618 case power_manager::InputEvent_Type_LID_OPEN
:
619 case power_manager::InputEvent_Type_LID_CLOSED
: {
621 (proto
.type() == power_manager::InputEvent_Type_LID_OPEN
);
622 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
623 LidEventReceived(open
, timestamp
));
629 void RegisterSuspendDelayImpl(
630 const std::string
& method_name
,
631 const power_manager::RegisterSuspendDelayRequest
& protobuf_request
,
632 dbus::ObjectProxy::ResponseCallback callback
) {
633 dbus::MethodCall
method_call(
634 power_manager::kPowerManagerInterface
, method_name
);
635 dbus::MessageWriter
writer(&method_call
);
637 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
638 POWER_LOG(ERROR
) << "Error constructing message for " << method_name
;
642 power_manager_proxy_
->CallMethod(
643 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
, callback
);
646 // Registers suspend delays with the power manager. This is usually only
647 // called at startup, but if the power manager restarts, we need to create new
649 void RegisterSuspendDelays() {
650 // Throw out any old delay that was registered.
651 suspend_delay_id_
= -1;
652 has_suspend_delay_id_
= false;
653 dark_suspend_delay_id_
= -1;
654 has_dark_suspend_delay_id_
= false;
656 power_manager::RegisterSuspendDelayRequest protobuf_request
;
657 base::TimeDelta timeout
=
658 base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs
);
659 protobuf_request
.set_timeout(timeout
.ToInternalValue());
660 protobuf_request
.set_description(kSuspendDelayDescription
);
662 RegisterSuspendDelayImpl(
663 power_manager::kRegisterSuspendDelayMethod
,
665 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply
,
666 weak_ptr_factory_
.GetWeakPtr(), false,
667 power_manager::kRegisterSuspendDelayMethod
));
668 RegisterSuspendDelayImpl(
669 power_manager::kRegisterDarkSuspendDelayMethod
,
671 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply
,
672 weak_ptr_factory_
.GetWeakPtr(), true,
673 power_manager::kRegisterDarkSuspendDelayMethod
));
676 // Records the fact that an observer has finished doing asynchronous work
677 // that was blocking a pending suspend attempt and possibly reports
678 // suspend readiness to powerd. Called by callbacks returned via
679 // GetSuspendReadinessCallback().
680 void HandleObserverSuspendReadiness(int32_t suspend_id
, bool in_dark_resume
) {
681 DCHECK(OnOriginThread());
682 if (!suspend_is_pending_
|| suspend_id
!= pending_suspend_id_
||
683 in_dark_resume
!= suspending_from_dark_resume_
)
686 num_pending_suspend_readiness_callbacks_
--;
687 MaybeReportSuspendReadiness();
690 // Reports suspend readiness to powerd if no observers are still holding
691 // suspend readiness callbacks.
692 void MaybeReportSuspendReadiness() {
693 if (!suspend_is_pending_
|| num_pending_suspend_readiness_callbacks_
> 0)
696 std::string method_name
;
697 int32_t delay_id
= -1;
698 if (suspending_from_dark_resume_
) {
699 method_name
= power_manager::kHandleDarkSuspendReadinessMethod
;
700 delay_id
= dark_suspend_delay_id_
;
702 method_name
= power_manager::kHandleSuspendReadinessMethod
;
703 delay_id
= suspend_delay_id_
;
706 if (render_process_manager_delegate_
&& !suspending_from_dark_resume_
)
707 render_process_manager_delegate_
->SuspendImminent();
709 dbus::MethodCall
method_call(
710 power_manager::kPowerManagerInterface
, method_name
);
711 dbus::MessageWriter
writer(&method_call
);
713 POWER_LOG(EVENT
) << "Announcing readiness of suspend delay " << delay_id
714 << " for suspend attempt " << pending_suspend_id_
;
715 power_manager::SuspendReadinessInfo protobuf_request
;
716 protobuf_request
.set_delay_id(delay_id
);
717 protobuf_request
.set_suspend_id(pending_suspend_id_
);
719 pending_suspend_id_
= -1;
720 suspend_is_pending_
= false;
722 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
723 POWER_LOG(ERROR
) << "Error constructing message for " << method_name
;
726 power_manager_proxy_
->CallMethod(
728 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
729 dbus::ObjectProxy::EmptyResponseCallback());
732 // Origin thread (i.e. the UI thread in production).
733 base::PlatformThreadId origin_thread_id_
;
735 dbus::ObjectProxy
* power_manager_proxy_
;
736 ObserverList
<Observer
> observers_
;
738 // The delay_id_ obtained from the RegisterSuspendDelay request.
739 int32_t suspend_delay_id_
;
740 bool has_suspend_delay_id_
;
742 // The delay_id_ obtained from the RegisterDarkSuspendDelay request.
743 int32_t dark_suspend_delay_id_
;
744 bool has_dark_suspend_delay_id_
;
746 // powerd-supplied ID corresponding to an imminent suspend attempt that is
747 // currently being delayed.
748 int32_t pending_suspend_id_
;
749 bool suspend_is_pending_
;
751 // Set to true when the suspend currently being delayed was triggered during a
752 // dark resume. Since |pending_suspend_id_| and |suspend_is_pending_| are
753 // both shared by normal and dark suspends, |suspending_from_dark_resume_|
754 // helps distinguish the context within which these variables are being used.
755 bool suspending_from_dark_resume_
;
757 // Number of callbacks that have been returned by
758 // GetSuspendReadinessCallback() during the currently-pending suspend
759 // attempt but have not yet been called.
760 int num_pending_suspend_readiness_callbacks_
;
762 // Last state passed to SetIsProjecting().
763 bool last_is_projecting_
;
765 // The delegate used to manage the power consumption of Chrome's renderer
767 base::WeakPtr
<RenderProcessManagerDelegate
> render_process_manager_delegate_
;
769 // Note: This should remain the last member so it'll be destroyed and
770 // invalidate its weak pointers before any other members are destroyed.
771 base::WeakPtrFactory
<PowerManagerClientImpl
> weak_ptr_factory_
;
773 DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl
);
776 // The PowerManagerClient implementation used on Linux desktop,
777 // which does nothing.
778 class PowerManagerClientStubImpl
: public PowerManagerClient
{
780 PowerManagerClientStubImpl()
781 : discharging_(true),
782 battery_percentage_(40),
786 num_pending_suspend_readiness_callbacks_(0),
787 weak_ptr_factory_(this) {}
789 virtual ~PowerManagerClientStubImpl() {}
791 int num_pending_suspend_readiness_callbacks() const {
792 return num_pending_suspend_readiness_callbacks_
;
795 // PowerManagerClient overrides:
796 virtual void Init(dbus::Bus
* bus
) override
{
797 ParseCommandLineSwitch();
798 if (power_cycle_delay_
!= base::TimeDelta()) {
799 update_timer_
.Start(FROM_HERE
,
802 &PowerManagerClientStubImpl::UpdateStatus
);
806 virtual void AddObserver(Observer
* observer
) override
{
807 observers_
.AddObserver(observer
);
810 virtual void RemoveObserver(Observer
* observer
) override
{
811 observers_
.RemoveObserver(observer
);
814 virtual bool HasObserver(const Observer
* observer
) const override
{
815 return observers_
.HasObserver(observer
);
818 virtual void SetRenderProcessManagerDelegate(
819 base::WeakPtr
<RenderProcessManagerDelegate
> delegate
) override
{
822 virtual void DecreaseScreenBrightness(bool allow_off
) override
{
823 POWER_LOG(USER
) << "Requested to descrease screen brightness";
824 SetBrightness(brightness_
- 5.0, true);
827 virtual void IncreaseScreenBrightness() override
{
828 POWER_LOG(USER
) << "Requested to increase screen brightness";
829 SetBrightness(brightness_
+ 5.0, true);
832 virtual void SetScreenBrightnessPercent(double percent
,
833 bool gradual
) override
{
834 POWER_LOG(USER
) << "Requested to set screen brightness to " << percent
835 << "% " << (gradual
? "gradually" : "instantaneously");
836 SetBrightness(percent
, false);
839 virtual void GetScreenBrightnessPercent(
840 const GetScreenBrightnessPercentCallback
& callback
) override
{
841 POWER_LOG(USER
) << "Requested to get screen brightness";
842 callback
.Run(brightness_
);
845 virtual void DecreaseKeyboardBrightness() override
{
846 POWER_LOG(USER
) << "Requested to descrease keyboard brightness";
849 virtual void IncreaseKeyboardBrightness() override
{
850 POWER_LOG(USER
) << "Requested to increase keyboard brightness";
853 virtual void RequestStatusUpdate() override
{
854 POWER_LOG(USER
) << "Requested status update";
855 base::MessageLoop::current()->PostTask(
856 FROM_HERE
, base::Bind(&PowerManagerClientStubImpl::UpdateStatus
,
857 weak_ptr_factory_
.GetWeakPtr()));
860 virtual void RequestSuspend() override
{}
861 virtual void RequestRestart() override
{}
862 virtual void RequestShutdown() override
{}
864 virtual void NotifyUserActivity(
865 power_manager::UserActivityType type
) override
{}
866 virtual void NotifyVideoActivity(bool is_fullscreen
) override
{}
867 virtual void SetPolicy(
868 const power_manager::PowerManagementPolicy
& policy
) override
{}
869 virtual void SetIsProjecting(bool is_projecting
) override
{}
870 virtual base::Closure
GetSuspendReadinessCallback() override
{
871 num_pending_suspend_readiness_callbacks_
++;
872 return base::Bind(&PowerManagerClientStubImpl::HandleSuspendReadiness
,
873 weak_ptr_factory_
.GetWeakPtr());
875 virtual int GetNumPendingSuspendReadinessCallbacks() override
{
876 return num_pending_suspend_readiness_callbacks_
;
880 void HandleSuspendReadiness() {
881 num_pending_suspend_readiness_callbacks_
--;
884 void UpdateStatus() {
885 if (pause_count_
> 0) {
887 if (pause_count_
== 2)
888 discharging_
= !discharging_
;
891 battery_percentage_
-= (battery_percentage_
<= 10 ? 1 : 10);
893 battery_percentage_
+= (battery_percentage_
>= 10 ? 10 : 1);
894 battery_percentage_
= std::min(std::max(battery_percentage_
, 0), 100);
895 // We pause at 0 and 100% so that it's easier to check those conditions.
896 if (battery_percentage_
== 0 || battery_percentage_
== 100) {
898 if (battery_percentage_
== 100)
899 cycle_count_
= (cycle_count_
+ 1) % 3;
903 const int kSecondsToEmptyFullBattery
= 3 * 60 * 60; // 3 hours.
904 int64 remaining_battery_time
=
905 std::max(1, battery_percentage_
* kSecondsToEmptyFullBattery
/ 100);
909 switch (cycle_count_
) {
911 // Say that the system is charging with AC connected and
912 // discharging without any charger connected.
913 props_
.set_external_power(discharging_
?
914 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
:
915 power_manager::PowerSupplyProperties_ExternalPower_AC
);
918 // Say that the system is both charging and discharging on USB
919 // (i.e. a low-power charger).
920 props_
.set_external_power(
921 power_manager::PowerSupplyProperties_ExternalPower_USB
);
924 // Say that the system is both charging and discharging on AC.
925 props_
.set_external_power(
926 power_manager::PowerSupplyProperties_ExternalPower_AC
);
929 NOTREACHED() << "Unhandled cycle " << cycle_count_
;
932 if (battery_percentage_
== 100 && !discharging_
) {
933 props_
.set_battery_state(
934 power_manager::PowerSupplyProperties_BatteryState_FULL
);
935 } else if (!discharging_
) {
936 props_
.set_battery_state(
937 power_manager::PowerSupplyProperties_BatteryState_CHARGING
);
938 props_
.set_battery_time_to_full_sec(std::max(static_cast<int64
>(1),
939 kSecondsToEmptyFullBattery
- remaining_battery_time
));
941 props_
.set_battery_state(
942 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING
);
943 props_
.set_battery_time_to_empty_sec(remaining_battery_time
);
946 props_
.set_battery_percent(battery_percentage_
);
947 props_
.set_is_calculating_battery_time(pause_count_
> 1);
949 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(props_
));
952 void SetBrightness(double percent
, bool user_initiated
) {
953 brightness_
= std::min(std::max(0.0, percent
), 100.0);
954 int brightness_level
= static_cast<int>(brightness_
);
955 FOR_EACH_OBSERVER(Observer
, observers_
,
956 BrightnessChanged(brightness_level
, user_initiated
));
959 void ParseCommandLineSwitch() {
960 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
961 if (!command_line
|| !command_line
->HasSwitch(switches::kPowerStub
))
963 std::string option_str
=
964 command_line
->GetSwitchValueASCII(switches::kPowerStub
);
965 base::StringPairs string_pairs
;
966 base::SplitStringIntoKeyValuePairs(option_str
, '=', ',', &string_pairs
);
967 for (base::StringPairs::iterator iter
= string_pairs
.begin();
968 iter
!= string_pairs
.end(); ++iter
) {
969 ParseOption((*iter
).first
, (*iter
).second
);
973 void ParseOption(const std::string
& arg0
, const std::string
& arg1
) {
974 if (arg0
== "cycle" || arg0
== "interactive") {
977 base::StringToInt(arg1
, &seconds
);
978 power_cycle_delay_
= base::TimeDelta::FromSeconds(seconds
);
982 base::TimeDelta power_cycle_delay_
; // Time over which to cycle power state
984 int battery_percentage_
;
988 ObserverList
<Observer
> observers_
;
989 base::RepeatingTimer
<PowerManagerClientStubImpl
> update_timer_
;
990 power_manager::PowerSupplyProperties props_
;
992 // Number of callbacks returned by GetSuspendReadinessCallback() but not yet
994 int num_pending_suspend_readiness_callbacks_
;
996 // Note: This should remain the last member so it'll be destroyed and
997 // invalidate its weak pointers before any other members are destroyed.
998 base::WeakPtrFactory
<PowerManagerClientStubImpl
> weak_ptr_factory_
;
1001 PowerManagerClient::PowerManagerClient() {
1004 PowerManagerClient::~PowerManagerClient() {
1008 PowerManagerClient
* PowerManagerClient::Create(
1009 DBusClientImplementationType type
) {
1010 if (type
== REAL_DBUS_CLIENT_IMPLEMENTATION
)
1011 return new PowerManagerClientImpl();
1012 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION
, type
);
1013 return new PowerManagerClientStubImpl();
1016 } // namespace chromeos