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 ~PowerManagerClientImpl() override
{
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 void AddObserver(Observer
* observer
) override
{
74 CHECK(observer
); // http://crbug.com/119976
75 observers_
.AddObserver(observer
);
78 void RemoveObserver(Observer
* observer
) override
{
79 observers_
.RemoveObserver(observer
);
82 bool HasObserver(const Observer
* observer
) const override
{
83 return observers_
.HasObserver(observer
);
86 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 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 void IncreaseScreenBrightness() override
{
106 SimpleMethodCallToPowerManager(
107 power_manager::kIncreaseScreenBrightnessMethod
);
110 void DecreaseKeyboardBrightness() override
{
111 SimpleMethodCallToPowerManager(
112 power_manager::kDecreaseKeyboardBrightnessMethod
);
115 void IncreaseKeyboardBrightness() override
{
116 SimpleMethodCallToPowerManager(
117 power_manager::kIncreaseKeyboardBrightnessMethod
);
120 void SetScreenBrightnessPercent(double percent
, bool gradual
) override
{
121 dbus::MethodCall
method_call(
122 power_manager::kPowerManagerInterface
,
123 power_manager::kSetScreenBrightnessPercentMethod
);
124 dbus::MessageWriter
writer(&method_call
);
125 writer
.AppendDouble(percent
);
128 power_manager::kBrightnessTransitionGradual
:
129 power_manager::kBrightnessTransitionInstant
);
130 power_manager_proxy_
->CallMethod(
132 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
133 dbus::ObjectProxy::EmptyResponseCallback());
136 void GetScreenBrightnessPercent(
137 const GetScreenBrightnessPercentCallback
& callback
) override
{
138 dbus::MethodCall
method_call(
139 power_manager::kPowerManagerInterface
,
140 power_manager::kGetScreenBrightnessPercentMethod
);
141 power_manager_proxy_
->CallMethod(
143 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
144 base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent
,
145 weak_ptr_factory_
.GetWeakPtr(), callback
));
148 void RequestStatusUpdate() override
{
149 POWER_LOG(USER
) << "RequestStatusUpdate";
150 dbus::MethodCall
method_call(
151 power_manager::kPowerManagerInterface
,
152 power_manager::kGetPowerSupplyPropertiesMethod
);
153 power_manager_proxy_
->CallMethod(
155 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
156 base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod
,
157 weak_ptr_factory_
.GetWeakPtr()));
160 void RequestSuspend() override
{
161 POWER_LOG(USER
) << "RequestSuspend";
162 SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod
);
165 void RequestRestart() override
{
166 POWER_LOG(USER
) << "RequestRestart";
167 SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod
);
170 void RequestShutdown() override
{
171 POWER_LOG(USER
) << "RequestShutdown";
172 SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod
);
175 void NotifyUserActivity(power_manager::UserActivityType type
) override
{
176 dbus::MethodCall
method_call(
177 power_manager::kPowerManagerInterface
,
178 power_manager::kHandleUserActivityMethod
);
179 dbus::MessageWriter
writer(&method_call
);
180 writer
.AppendInt32(type
);
182 power_manager_proxy_
->CallMethod(
184 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
185 dbus::ObjectProxy::EmptyResponseCallback());
188 void NotifyVideoActivity(bool is_fullscreen
) override
{
189 dbus::MethodCall
method_call(
190 power_manager::kPowerManagerInterface
,
191 power_manager::kHandleVideoActivityMethod
);
192 dbus::MessageWriter
writer(&method_call
);
193 writer
.AppendBool(is_fullscreen
);
195 power_manager_proxy_
->CallMethod(
197 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
198 dbus::ObjectProxy::EmptyResponseCallback());
201 void SetPolicy(const power_manager::PowerManagementPolicy
& policy
) override
{
202 POWER_LOG(USER
) << "SetPolicy";
203 dbus::MethodCall
method_call(
204 power_manager::kPowerManagerInterface
,
205 power_manager::kSetPolicyMethod
);
206 dbus::MessageWriter
writer(&method_call
);
207 if (!writer
.AppendProtoAsArrayOfBytes(policy
)) {
208 POWER_LOG(ERROR
) << "Error calling " << power_manager::kSetPolicyMethod
;
211 power_manager_proxy_
->CallMethod(
213 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
214 dbus::ObjectProxy::EmptyResponseCallback());
217 void SetIsProjecting(bool is_projecting
) override
{
218 POWER_LOG(USER
) << "SetIsProjecting";
219 dbus::MethodCall
method_call(
220 power_manager::kPowerManagerInterface
,
221 power_manager::kSetIsProjectingMethod
);
222 dbus::MessageWriter
writer(&method_call
);
223 writer
.AppendBool(is_projecting
);
224 power_manager_proxy_
->CallMethod(
226 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
227 dbus::ObjectProxy::EmptyResponseCallback());
228 last_is_projecting_
= is_projecting
;
231 base::Closure
GetSuspendReadinessCallback() override
{
232 DCHECK(OnOriginThread());
233 DCHECK(suspend_is_pending_
);
234 num_pending_suspend_readiness_callbacks_
++;
235 return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness
,
236 weak_ptr_factory_
.GetWeakPtr(), pending_suspend_id_
,
237 suspending_from_dark_resume_
);
240 int GetNumPendingSuspendReadinessCallbacks() override
{
241 return num_pending_suspend_readiness_callbacks_
;
245 void Init(dbus::Bus
* bus
) override
{
246 power_manager_proxy_
= bus
->GetObjectProxy(
247 power_manager::kPowerManagerServiceName
,
248 dbus::ObjectPath(power_manager::kPowerManagerServicePath
));
250 power_manager_proxy_
->SetNameOwnerChangedCallback(
251 base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived
,
252 weak_ptr_factory_
.GetWeakPtr()));
254 // Monitor the D-Bus signal for brightness changes. Only the power
255 // manager knows the actual brightness level. We don't cache the
256 // brightness level in Chrome as it'll make things less reliable.
257 power_manager_proxy_
->ConnectToSignal(
258 power_manager::kPowerManagerInterface
,
259 power_manager::kBrightnessChangedSignal
,
260 base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived
,
261 weak_ptr_factory_
.GetWeakPtr()),
262 base::Bind(&PowerManagerClientImpl::SignalConnected
,
263 weak_ptr_factory_
.GetWeakPtr()));
265 power_manager_proxy_
->ConnectToSignal(
266 power_manager::kPowerManagerInterface
,
267 power_manager::kPeripheralBatteryStatusSignal
,
268 base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived
,
269 weak_ptr_factory_
.GetWeakPtr()),
270 base::Bind(&PowerManagerClientImpl::SignalConnected
,
271 weak_ptr_factory_
.GetWeakPtr()));
273 power_manager_proxy_
->ConnectToSignal(
274 power_manager::kPowerManagerInterface
,
275 power_manager::kPowerSupplyPollSignal
,
276 base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived
,
277 weak_ptr_factory_
.GetWeakPtr()),
278 base::Bind(&PowerManagerClientImpl::SignalConnected
,
279 weak_ptr_factory_
.GetWeakPtr()));
281 power_manager_proxy_
->ConnectToSignal(
282 power_manager::kPowerManagerInterface
,
283 power_manager::kInputEventSignal
,
284 base::Bind(&PowerManagerClientImpl::InputEventReceived
,
285 weak_ptr_factory_
.GetWeakPtr()),
286 base::Bind(&PowerManagerClientImpl::SignalConnected
,
287 weak_ptr_factory_
.GetWeakPtr()));
289 power_manager_proxy_
->ConnectToSignal(
290 power_manager::kPowerManagerInterface
,
291 power_manager::kSuspendImminentSignal
,
293 &PowerManagerClientImpl::HandleSuspendImminent
,
294 weak_ptr_factory_
.GetWeakPtr(), false),
295 base::Bind(&PowerManagerClientImpl::SignalConnected
,
296 weak_ptr_factory_
.GetWeakPtr()));
298 power_manager_proxy_
->ConnectToSignal(
299 power_manager::kPowerManagerInterface
,
300 power_manager::kSuspendDoneSignal
,
301 base::Bind(&PowerManagerClientImpl::SuspendDoneReceived
,
302 weak_ptr_factory_
.GetWeakPtr()),
303 base::Bind(&PowerManagerClientImpl::SignalConnected
,
304 weak_ptr_factory_
.GetWeakPtr()));
306 power_manager_proxy_
->ConnectToSignal(
307 power_manager::kPowerManagerInterface
,
308 power_manager::kDarkSuspendImminentSignal
,
310 &PowerManagerClientImpl::HandleSuspendImminent
,
311 weak_ptr_factory_
.GetWeakPtr(), true),
312 base::Bind(&PowerManagerClientImpl::SignalConnected
,
313 weak_ptr_factory_
.GetWeakPtr()));
315 power_manager_proxy_
->ConnectToSignal(
316 power_manager::kPowerManagerInterface
,
317 power_manager::kIdleActionImminentSignal
,
319 &PowerManagerClientImpl::IdleActionImminentReceived
,
320 weak_ptr_factory_
.GetWeakPtr()),
321 base::Bind(&PowerManagerClientImpl::SignalConnected
,
322 weak_ptr_factory_
.GetWeakPtr()));
324 power_manager_proxy_
->ConnectToSignal(
325 power_manager::kPowerManagerInterface
,
326 power_manager::kIdleActionDeferredSignal
,
328 &PowerManagerClientImpl::IdleActionDeferredReceived
,
329 weak_ptr_factory_
.GetWeakPtr()),
330 base::Bind(&PowerManagerClientImpl::SignalConnected
,
331 weak_ptr_factory_
.GetWeakPtr()));
333 RegisterSuspendDelays();
337 // Returns true if the current thread is the origin thread.
338 bool OnOriginThread() {
339 return base::PlatformThread::CurrentId() == origin_thread_id_
;
342 // Called when a dbus signal is initially connected.
343 void SignalConnected(const std::string
& interface_name
,
344 const std::string
& signal_name
,
347 POWER_LOG(ERROR
) << "Failed to connect to signal " << signal_name
<< ".";
350 // Makes a method call to power manager with no arguments and no response.
351 void SimpleMethodCallToPowerManager(const std::string
& method_name
) {
352 dbus::MethodCall
method_call(power_manager::kPowerManagerInterface
,
354 power_manager_proxy_
->CallMethod(
356 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
357 dbus::ObjectProxy::EmptyResponseCallback());
360 void NameOwnerChangedReceived(const std::string
& old_owner
,
361 const std::string
& new_owner
) {
362 POWER_LOG(EVENT
) << "Power manager restarted. Old owner: "
363 << (old_owner
.empty() ? "[none]" : old_owner
.c_str())
365 << (new_owner
.empty() ? "[none]" : new_owner
.c_str());
366 suspend_is_pending_
= false;
367 pending_suspend_id_
= -1;
368 suspending_from_dark_resume_
= false;
369 if (!new_owner
.empty()) {
370 POWER_LOG(EVENT
) << "Sending initial state to power manager";
371 RegisterSuspendDelays();
372 SetIsProjecting(last_is_projecting_
);
373 FOR_EACH_OBSERVER(Observer
, observers_
, PowerManagerRestarted());
377 void BrightnessChangedReceived(dbus::Signal
* signal
) {
378 dbus::MessageReader
reader(signal
);
379 int32_t brightness_level
= 0;
380 bool user_initiated
= 0;
381 if (!(reader
.PopInt32(&brightness_level
) &&
382 reader
.PopBool(&user_initiated
))) {
383 POWER_LOG(ERROR
) << "Brightness changed signal had incorrect parameters: "
384 << signal
->ToString();
387 POWER_LOG(DEBUG
) << "Brightness changed to " << brightness_level
388 << ": user initiated " << user_initiated
;
389 FOR_EACH_OBSERVER(Observer
, observers_
,
390 BrightnessChanged(brightness_level
, user_initiated
));
393 void PeripheralBatteryStatusReceived(dbus::Signal
* signal
) {
394 dbus::MessageReader
reader(signal
);
395 power_manager::PeripheralBatteryStatus protobuf_status
;
396 if (!reader
.PopArrayOfBytesAsProto(&protobuf_status
)) {
397 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
398 << power_manager::kPeripheralBatteryStatusSignal
403 std::string path
= protobuf_status
.path();
404 std::string name
= protobuf_status
.name();
405 int level
= protobuf_status
.has_level() ? protobuf_status
.level() : -1;
407 POWER_LOG(DEBUG
) << "Device battery status received " << level
<< " for "
408 << name
<< " at " << path
;
410 FOR_EACH_OBSERVER(Observer
, observers_
,
411 PeripheralBatteryStatusReceived(path
, name
, level
));
414 void PowerSupplyPollReceived(dbus::Signal
* signal
) {
415 POWER_LOG(DEBUG
) << "Received power supply poll signal.";
416 dbus::MessageReader
reader(signal
);
417 power_manager::PowerSupplyProperties protobuf
;
418 if (reader
.PopArrayOfBytesAsProto(&protobuf
)) {
419 HandlePowerSupplyProperties(protobuf
);
421 POWER_LOG(ERROR
) << "Unable to decode "
422 << power_manager::kPowerSupplyPollSignal
<< " signal";
426 void OnGetPowerSupplyPropertiesMethod(dbus::Response
* response
) {
428 POWER_LOG(ERROR
) << "Error calling "
429 << power_manager::kGetPowerSupplyPropertiesMethod
;
433 dbus::MessageReader
reader(response
);
434 power_manager::PowerSupplyProperties protobuf
;
435 if (reader
.PopArrayOfBytesAsProto(&protobuf
)) {
436 HandlePowerSupplyProperties(protobuf
);
438 POWER_LOG(ERROR
) << "Unable to decode "
439 << power_manager::kGetPowerSupplyPropertiesMethod
444 void OnGetScreenBrightnessPercent(
445 const GetScreenBrightnessPercentCallback
& callback
,
446 dbus::Response
* response
) {
448 POWER_LOG(ERROR
) << "Error calling "
449 << power_manager::kGetScreenBrightnessPercentMethod
;
452 dbus::MessageReader
reader(response
);
453 double percent
= 0.0;
454 if (!reader
.PopDouble(&percent
))
455 POWER_LOG(ERROR
) << "Error reading response from powerd: "
456 << response
->ToString();
457 callback
.Run(percent
);
460 void HandlePowerSupplyProperties(
461 const power_manager::PowerSupplyProperties
& proto
) {
462 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(proto
));
463 const bool on_battery
= proto
.external_power() ==
464 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
;
465 base::PowerMonitorDeviceSource::SetPowerSource(on_battery
);
468 void HandleRegisterSuspendDelayReply(bool dark_suspend
,
469 const std::string
& method_name
,
470 dbus::Response
* response
) {
472 POWER_LOG(ERROR
) << "Error calling " << method_name
;
476 dbus::MessageReader
reader(response
);
477 power_manager::RegisterSuspendDelayReply protobuf
;
478 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
479 POWER_LOG(ERROR
) << "Unable to parse reply from " << method_name
;
484 dark_suspend_delay_id_
= protobuf
.delay_id();
485 has_dark_suspend_delay_id_
= true;
486 POWER_LOG(EVENT
) << "Registered dark suspend delay "
487 << dark_suspend_delay_id_
;
489 suspend_delay_id_
= protobuf
.delay_id();
490 has_suspend_delay_id_
= true;
491 POWER_LOG(EVENT
) << "Registered suspend delay " << suspend_delay_id_
;
495 void HandleSuspendImminent(bool in_dark_resume
, dbus::Signal
* signal
) {
496 std::string signal_name
= signal
->GetMember();
497 if ((in_dark_resume
&& !has_dark_suspend_delay_id_
) ||
498 (!in_dark_resume
&& !has_suspend_delay_id_
)) {
499 POWER_LOG(ERROR
) << "Received unrequested " << signal_name
<< " signal";
503 dbus::MessageReader
reader(signal
);
504 power_manager::SuspendImminent proto
;
505 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
506 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
507 << signal_name
<< " signal";
511 POWER_LOG(EVENT
) << "Got " << signal_name
512 << " signal announcing suspend attempt "
513 << proto
.suspend_id();
515 // If a previous suspend is pending from the same state we are currently in
516 // (fully powered on or in dark resume), then something's gone a little
518 if (suspend_is_pending_
&& suspending_from_dark_resume_
== in_dark_resume
) {
519 POWER_LOG(ERROR
) << "Got " << signal_name
520 << " signal about pending suspend attempt "
521 << proto
.suspend_id()
522 << " while still waiting on attempt "
523 << pending_suspend_id_
;
526 pending_suspend_id_
= proto
.suspend_id();
527 suspend_is_pending_
= true;
528 suspending_from_dark_resume_
= in_dark_resume
;
529 num_pending_suspend_readiness_callbacks_
= 0;
530 if (suspending_from_dark_resume_
)
531 FOR_EACH_OBSERVER(Observer
, observers_
, DarkSuspendImminent());
533 FOR_EACH_OBSERVER(Observer
, observers_
, SuspendImminent());
534 base::PowerMonitorDeviceSource::HandleSystemSuspending();
535 MaybeReportSuspendReadiness();
538 void SuspendDoneReceived(dbus::Signal
* signal
) {
539 dbus::MessageReader
reader(signal
);
540 power_manager::SuspendDone proto
;
541 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
542 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
543 << power_manager::kSuspendDoneSignal
<< " signal";
547 const base::TimeDelta duration
=
548 base::TimeDelta::FromInternalValue(proto
.suspend_duration());
549 POWER_LOG(EVENT
) << "Got " << power_manager::kSuspendDoneSignal
551 << " suspend_id=" << proto
.suspend_id()
552 << " duration=" << duration
.InSeconds() << " sec";
554 if (render_process_manager_delegate_
)
555 render_process_manager_delegate_
->SuspendDone();
558 PowerManagerClient::Observer
, observers_
, SuspendDone(duration
));
559 base::PowerMonitorDeviceSource::HandleSystemResumed();
562 void IdleActionImminentReceived(dbus::Signal
* signal
) {
563 dbus::MessageReader
reader(signal
);
564 power_manager::IdleActionImminent proto
;
565 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
566 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
567 << power_manager::kIdleActionImminentSignal
<< " signal";
570 FOR_EACH_OBSERVER(Observer
, observers_
,
571 IdleActionImminent(base::TimeDelta::FromInternalValue(
572 proto
.time_until_idle_action())));
575 void IdleActionDeferredReceived(dbus::Signal
* signal
) {
576 FOR_EACH_OBSERVER(Observer
, observers_
, IdleActionDeferred());
579 void InputEventReceived(dbus::Signal
* signal
) {
580 dbus::MessageReader
reader(signal
);
581 power_manager::InputEvent proto
;
582 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
583 POWER_LOG(ERROR
) << "Unable to decode protocol buffer from "
584 << power_manager::kInputEventSignal
<< " signal";
588 base::TimeTicks timestamp
=
589 base::TimeTicks::FromInternalValue(proto
.timestamp());
590 POWER_LOG(USER
) << "Got " << power_manager::kInputEventSignal
<< " signal:"
591 << " type=" << proto
.type()
592 << " timestamp=" << proto
.timestamp();
593 switch (proto
.type()) {
594 case power_manager::InputEvent_Type_POWER_BUTTON_DOWN
:
595 case power_manager::InputEvent_Type_POWER_BUTTON_UP
: {
597 (proto
.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN
);
598 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
599 PowerButtonEventReceived(down
, timestamp
));
601 // Tell powerd that Chrome has handled power button presses.
603 dbus::MethodCall
method_call(
604 power_manager::kPowerManagerInterface
,
605 power_manager::kHandlePowerButtonAcknowledgmentMethod
);
606 dbus::MessageWriter
writer(&method_call
);
607 writer
.AppendInt64(proto
.timestamp());
608 power_manager_proxy_
->CallMethod(
610 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
611 dbus::ObjectProxy::EmptyResponseCallback());
615 case power_manager::InputEvent_Type_LID_OPEN
:
616 case power_manager::InputEvent_Type_LID_CLOSED
: {
618 (proto
.type() == power_manager::InputEvent_Type_LID_OPEN
);
619 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
620 LidEventReceived(open
, timestamp
));
626 void RegisterSuspendDelayImpl(
627 const std::string
& method_name
,
628 const power_manager::RegisterSuspendDelayRequest
& protobuf_request
,
629 dbus::ObjectProxy::ResponseCallback callback
) {
630 dbus::MethodCall
method_call(
631 power_manager::kPowerManagerInterface
, method_name
);
632 dbus::MessageWriter
writer(&method_call
);
634 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
635 POWER_LOG(ERROR
) << "Error constructing message for " << method_name
;
639 power_manager_proxy_
->CallMethod(
640 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
, callback
);
643 // Registers suspend delays with the power manager. This is usually only
644 // called at startup, but if the power manager restarts, we need to create new
646 void RegisterSuspendDelays() {
647 // Throw out any old delay that was registered.
648 suspend_delay_id_
= -1;
649 has_suspend_delay_id_
= false;
650 dark_suspend_delay_id_
= -1;
651 has_dark_suspend_delay_id_
= false;
653 power_manager::RegisterSuspendDelayRequest protobuf_request
;
654 base::TimeDelta timeout
=
655 base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs
);
656 protobuf_request
.set_timeout(timeout
.ToInternalValue());
657 protobuf_request
.set_description(kSuspendDelayDescription
);
659 RegisterSuspendDelayImpl(
660 power_manager::kRegisterSuspendDelayMethod
,
662 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply
,
663 weak_ptr_factory_
.GetWeakPtr(), false,
664 power_manager::kRegisterSuspendDelayMethod
));
665 RegisterSuspendDelayImpl(
666 power_manager::kRegisterDarkSuspendDelayMethod
,
668 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply
,
669 weak_ptr_factory_
.GetWeakPtr(), true,
670 power_manager::kRegisterDarkSuspendDelayMethod
));
673 // Records the fact that an observer has finished doing asynchronous work
674 // that was blocking a pending suspend attempt and possibly reports
675 // suspend readiness to powerd. Called by callbacks returned via
676 // GetSuspendReadinessCallback().
677 void HandleObserverSuspendReadiness(int32_t suspend_id
, bool in_dark_resume
) {
678 DCHECK(OnOriginThread());
679 if (!suspend_is_pending_
|| suspend_id
!= pending_suspend_id_
||
680 in_dark_resume
!= suspending_from_dark_resume_
)
683 num_pending_suspend_readiness_callbacks_
--;
684 MaybeReportSuspendReadiness();
687 // Reports suspend readiness to powerd if no observers are still holding
688 // suspend readiness callbacks.
689 void MaybeReportSuspendReadiness() {
690 if (!suspend_is_pending_
|| num_pending_suspend_readiness_callbacks_
> 0)
693 std::string method_name
;
694 int32_t delay_id
= -1;
695 if (suspending_from_dark_resume_
) {
696 method_name
= power_manager::kHandleDarkSuspendReadinessMethod
;
697 delay_id
= dark_suspend_delay_id_
;
699 method_name
= power_manager::kHandleSuspendReadinessMethod
;
700 delay_id
= suspend_delay_id_
;
703 if (render_process_manager_delegate_
&& !suspending_from_dark_resume_
)
704 render_process_manager_delegate_
->SuspendImminent();
706 dbus::MethodCall
method_call(
707 power_manager::kPowerManagerInterface
, method_name
);
708 dbus::MessageWriter
writer(&method_call
);
710 POWER_LOG(EVENT
) << "Announcing readiness of suspend delay " << delay_id
711 << " for suspend attempt " << pending_suspend_id_
;
712 power_manager::SuspendReadinessInfo protobuf_request
;
713 protobuf_request
.set_delay_id(delay_id
);
714 protobuf_request
.set_suspend_id(pending_suspend_id_
);
716 pending_suspend_id_
= -1;
717 suspend_is_pending_
= false;
719 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
720 POWER_LOG(ERROR
) << "Error constructing message for " << method_name
;
723 power_manager_proxy_
->CallMethod(
725 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
726 dbus::ObjectProxy::EmptyResponseCallback());
729 // Origin thread (i.e. the UI thread in production).
730 base::PlatformThreadId origin_thread_id_
;
732 dbus::ObjectProxy
* power_manager_proxy_
;
733 ObserverList
<Observer
> observers_
;
735 // The delay_id_ obtained from the RegisterSuspendDelay request.
736 int32_t suspend_delay_id_
;
737 bool has_suspend_delay_id_
;
739 // The delay_id_ obtained from the RegisterDarkSuspendDelay request.
740 int32_t dark_suspend_delay_id_
;
741 bool has_dark_suspend_delay_id_
;
743 // powerd-supplied ID corresponding to an imminent suspend attempt that is
744 // currently being delayed.
745 int32_t pending_suspend_id_
;
746 bool suspend_is_pending_
;
748 // Set to true when the suspend currently being delayed was triggered during a
749 // dark resume. Since |pending_suspend_id_| and |suspend_is_pending_| are
750 // both shared by normal and dark suspends, |suspending_from_dark_resume_|
751 // helps distinguish the context within which these variables are being used.
752 bool suspending_from_dark_resume_
;
754 // Number of callbacks that have been returned by
755 // GetSuspendReadinessCallback() during the currently-pending suspend
756 // attempt but have not yet been called.
757 int num_pending_suspend_readiness_callbacks_
;
759 // Last state passed to SetIsProjecting().
760 bool last_is_projecting_
;
762 // The delegate used to manage the power consumption of Chrome's renderer
764 base::WeakPtr
<RenderProcessManagerDelegate
> render_process_manager_delegate_
;
766 // Note: This should remain the last member so it'll be destroyed and
767 // invalidate its weak pointers before any other members are destroyed.
768 base::WeakPtrFactory
<PowerManagerClientImpl
> weak_ptr_factory_
;
770 DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl
);
773 // The PowerManagerClient implementation used on Linux desktop,
774 // which does nothing.
775 class PowerManagerClientStubImpl
: public PowerManagerClient
{
777 PowerManagerClientStubImpl()
778 : discharging_(true),
779 battery_percentage_(40),
783 num_pending_suspend_readiness_callbacks_(0),
784 weak_ptr_factory_(this) {}
786 ~PowerManagerClientStubImpl() override
{}
788 int num_pending_suspend_readiness_callbacks() const {
789 return num_pending_suspend_readiness_callbacks_
;
792 // PowerManagerClient overrides:
793 void Init(dbus::Bus
* bus
) override
{
794 ParseCommandLineSwitch();
795 if (power_cycle_delay_
!= base::TimeDelta()) {
796 update_timer_
.Start(FROM_HERE
,
799 &PowerManagerClientStubImpl::UpdateStatus
);
803 void AddObserver(Observer
* observer
) override
{
804 observers_
.AddObserver(observer
);
807 void RemoveObserver(Observer
* observer
) override
{
808 observers_
.RemoveObserver(observer
);
811 bool HasObserver(const Observer
* observer
) const override
{
812 return observers_
.HasObserver(observer
);
815 void SetRenderProcessManagerDelegate(
816 base::WeakPtr
<RenderProcessManagerDelegate
> delegate
) override
{}
818 void DecreaseScreenBrightness(bool allow_off
) override
{
819 POWER_LOG(USER
) << "Requested to descrease screen brightness";
820 SetBrightness(brightness_
- 5.0, true);
823 void IncreaseScreenBrightness() override
{
824 POWER_LOG(USER
) << "Requested to increase screen brightness";
825 SetBrightness(brightness_
+ 5.0, true);
828 void SetScreenBrightnessPercent(double percent
, bool gradual
) override
{
829 POWER_LOG(USER
) << "Requested to set screen brightness to " << percent
830 << "% " << (gradual
? "gradually" : "instantaneously");
831 SetBrightness(percent
, false);
834 void GetScreenBrightnessPercent(
835 const GetScreenBrightnessPercentCallback
& callback
) override
{
836 POWER_LOG(USER
) << "Requested to get screen brightness";
837 callback
.Run(brightness_
);
840 void DecreaseKeyboardBrightness() override
{
841 POWER_LOG(USER
) << "Requested to descrease keyboard brightness";
844 void IncreaseKeyboardBrightness() override
{
845 POWER_LOG(USER
) << "Requested to increase keyboard brightness";
848 void RequestStatusUpdate() override
{
849 POWER_LOG(USER
) << "Requested status update";
850 base::MessageLoop::current()->PostTask(
851 FROM_HERE
, base::Bind(&PowerManagerClientStubImpl::UpdateStatus
,
852 weak_ptr_factory_
.GetWeakPtr()));
855 void RequestSuspend() override
{}
856 void RequestRestart() override
{}
857 void RequestShutdown() override
{}
859 void NotifyUserActivity(power_manager::UserActivityType type
) override
{}
860 void NotifyVideoActivity(bool is_fullscreen
) override
{}
861 void SetPolicy(const power_manager::PowerManagementPolicy
& policy
) override
{}
862 void SetIsProjecting(bool is_projecting
) override
{}
863 base::Closure
GetSuspendReadinessCallback() override
{
864 num_pending_suspend_readiness_callbacks_
++;
865 return base::Bind(&PowerManagerClientStubImpl::HandleSuspendReadiness
,
866 weak_ptr_factory_
.GetWeakPtr());
868 int GetNumPendingSuspendReadinessCallbacks() override
{
869 return num_pending_suspend_readiness_callbacks_
;
873 void HandleSuspendReadiness() {
874 num_pending_suspend_readiness_callbacks_
--;
877 void UpdateStatus() {
878 if (pause_count_
> 0) {
880 if (pause_count_
== 2)
881 discharging_
= !discharging_
;
884 battery_percentage_
-= (battery_percentage_
<= 10 ? 1 : 10);
886 battery_percentage_
+= (battery_percentage_
>= 10 ? 10 : 1);
887 battery_percentage_
= std::min(std::max(battery_percentage_
, 0), 100);
888 // We pause at 0 and 100% so that it's easier to check those conditions.
889 if (battery_percentage_
== 0 || battery_percentage_
== 100) {
891 if (battery_percentage_
== 100)
892 cycle_count_
= (cycle_count_
+ 1) % 3;
896 const int kSecondsToEmptyFullBattery
= 3 * 60 * 60; // 3 hours.
897 int64 remaining_battery_time
=
898 std::max(1, battery_percentage_
* kSecondsToEmptyFullBattery
/ 100);
902 switch (cycle_count_
) {
904 // Say that the system is charging with AC connected and
905 // discharging without any charger connected.
906 props_
.set_external_power(discharging_
?
907 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
:
908 power_manager::PowerSupplyProperties_ExternalPower_AC
);
911 // Say that the system is both charging and discharging on USB
912 // (i.e. a low-power charger).
913 props_
.set_external_power(
914 power_manager::PowerSupplyProperties_ExternalPower_USB
);
917 // Say that the system is both charging and discharging on AC.
918 props_
.set_external_power(
919 power_manager::PowerSupplyProperties_ExternalPower_AC
);
922 NOTREACHED() << "Unhandled cycle " << cycle_count_
;
925 if (battery_percentage_
== 100 && !discharging_
) {
926 props_
.set_battery_state(
927 power_manager::PowerSupplyProperties_BatteryState_FULL
);
928 } else if (!discharging_
) {
929 props_
.set_battery_state(
930 power_manager::PowerSupplyProperties_BatteryState_CHARGING
);
931 props_
.set_battery_time_to_full_sec(std::max(static_cast<int64
>(1),
932 kSecondsToEmptyFullBattery
- remaining_battery_time
));
934 props_
.set_battery_state(
935 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING
);
936 props_
.set_battery_time_to_empty_sec(remaining_battery_time
);
939 props_
.set_battery_percent(battery_percentage_
);
940 props_
.set_is_calculating_battery_time(pause_count_
> 1);
942 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(props_
));
945 void SetBrightness(double percent
, bool user_initiated
) {
946 brightness_
= std::min(std::max(0.0, percent
), 100.0);
947 int brightness_level
= static_cast<int>(brightness_
);
948 FOR_EACH_OBSERVER(Observer
, observers_
,
949 BrightnessChanged(brightness_level
, user_initiated
));
952 void ParseCommandLineSwitch() {
953 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
954 if (!command_line
|| !command_line
->HasSwitch(switches::kPowerStub
))
956 std::string option_str
=
957 command_line
->GetSwitchValueASCII(switches::kPowerStub
);
958 base::StringPairs string_pairs
;
959 base::SplitStringIntoKeyValuePairs(option_str
, '=', ',', &string_pairs
);
960 for (base::StringPairs::iterator iter
= string_pairs
.begin();
961 iter
!= string_pairs
.end(); ++iter
) {
962 ParseOption((*iter
).first
, (*iter
).second
);
966 void ParseOption(const std::string
& arg0
, const std::string
& arg1
) {
967 if (arg0
== "cycle" || arg0
== "interactive") {
970 base::StringToInt(arg1
, &seconds
);
971 power_cycle_delay_
= base::TimeDelta::FromSeconds(seconds
);
975 base::TimeDelta power_cycle_delay_
; // Time over which to cycle power state
977 int battery_percentage_
;
981 ObserverList
<Observer
> observers_
;
982 base::RepeatingTimer
<PowerManagerClientStubImpl
> update_timer_
;
983 power_manager::PowerSupplyProperties props_
;
985 // Number of callbacks returned by GetSuspendReadinessCallback() but not yet
987 int num_pending_suspend_readiness_callbacks_
;
989 // Note: This should remain the last member so it'll be destroyed and
990 // invalidate its weak pointers before any other members are destroyed.
991 base::WeakPtrFactory
<PowerManagerClientStubImpl
> weak_ptr_factory_
;
994 PowerManagerClient::PowerManagerClient() {
997 PowerManagerClient::~PowerManagerClient() {
1001 PowerManagerClient
* PowerManagerClient::Create(
1002 DBusClientImplementationType type
) {
1003 if (type
== REAL_DBUS_CLIENT_IMPLEMENTATION
)
1004 return new PowerManagerClientImpl();
1005 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION
, type
);
1006 return new PowerManagerClientStubImpl();
1009 } // namespace chromeos