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/format_macros.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop.h"
15 #include "base/observer_list.h"
16 #include "base/stringprintf.h"
17 #include "base/threading/platform_thread.h"
18 #include "base/time.h"
19 #include "base/timer.h"
20 #include "chromeos/dbus/power_manager/input_event.pb.h"
21 #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
22 #include "chromeos/dbus/power_manager/policy.pb.h"
23 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
24 #include "chromeos/dbus/power_manager/suspend.pb.h"
25 #include "chromeos/dbus/video_activity_update.pb.h"
27 #include "dbus/message.h"
28 #include "dbus/object_path.h"
29 #include "dbus/object_proxy.h"
30 #include "third_party/cros_system_api/dbus/service_constants.h"
34 // Maximum amount of time that the power manager will wait for Chrome to
35 // say that it's ready for the system to be suspended, in milliseconds.
36 const int kSuspendDelayTimeoutMs
= 5000;
38 // Human-readable description of Chrome's suspend delay.
39 const char kSuspendDelayDescription
[] = "chrome";
41 // The PowerManagerClient implementation used in production.
42 class PowerManagerClientImpl
: public PowerManagerClient
{
44 explicit PowerManagerClientImpl(dbus::Bus
* bus
)
45 : origin_thread_id_(base::PlatformThread::CurrentId()),
46 power_manager_proxy_(NULL
),
47 suspend_delay_id_(-1),
48 has_suspend_delay_id_(false),
49 pending_suspend_id_(-1),
50 suspend_is_pending_(false),
51 num_pending_suspend_readiness_callbacks_(0),
52 last_is_projecting_(false),
53 weak_ptr_factory_(this) {
54 power_manager_proxy_
= bus
->GetObjectProxy(
55 power_manager::kPowerManagerServiceName
,
56 dbus::ObjectPath(power_manager::kPowerManagerServicePath
));
58 power_manager_proxy_
->SetNameOwnerChangedCallback(
59 base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived
,
60 weak_ptr_factory_
.GetWeakPtr()));
62 // Monitor the D-Bus signal for brightness changes. Only the power
63 // manager knows the actual brightness level. We don't cache the
64 // brightness level in Chrome as it'll make things less reliable.
65 power_manager_proxy_
->ConnectToSignal(
66 power_manager::kPowerManagerInterface
,
67 power_manager::kBrightnessChangedSignal
,
68 base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived
,
69 weak_ptr_factory_
.GetWeakPtr()),
70 base::Bind(&PowerManagerClientImpl::SignalConnected
,
71 weak_ptr_factory_
.GetWeakPtr()));
73 power_manager_proxy_
->ConnectToSignal(
74 power_manager::kPowerManagerInterface
,
75 power_manager::kPeripheralBatteryStatusSignal
,
76 base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived
,
77 weak_ptr_factory_
.GetWeakPtr()),
78 base::Bind(&PowerManagerClientImpl::SignalConnected
,
79 weak_ptr_factory_
.GetWeakPtr()));
81 power_manager_proxy_
->ConnectToSignal(
82 power_manager::kPowerManagerInterface
,
83 power_manager::kPowerSupplyPollSignal
,
84 base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived
,
85 weak_ptr_factory_
.GetWeakPtr()),
86 base::Bind(&PowerManagerClientImpl::SignalConnected
,
87 weak_ptr_factory_
.GetWeakPtr()));
89 power_manager_proxy_
->ConnectToSignal(
90 power_manager::kPowerManagerInterface
,
91 power_manager::kIdleNotifySignal
,
92 base::Bind(&PowerManagerClientImpl::IdleNotifySignalReceived
,
93 weak_ptr_factory_
.GetWeakPtr()),
94 base::Bind(&PowerManagerClientImpl::SignalConnected
,
95 weak_ptr_factory_
.GetWeakPtr()));
97 power_manager_proxy_
->ConnectToSignal(
98 power_manager::kPowerManagerInterface
,
99 power_manager::kInputEventSignal
,
100 base::Bind(&PowerManagerClientImpl::InputEventReceived
,
101 weak_ptr_factory_
.GetWeakPtr()),
102 base::Bind(&PowerManagerClientImpl::SignalConnected
,
103 weak_ptr_factory_
.GetWeakPtr()));
105 power_manager_proxy_
->ConnectToSignal(
106 power_manager::kPowerManagerInterface
,
107 power_manager::kSuspendStateChangedSignal
,
108 base::Bind(&PowerManagerClientImpl::SuspendStateChangedReceived
,
109 weak_ptr_factory_
.GetWeakPtr()),
110 base::Bind(&PowerManagerClientImpl::SignalConnected
,
111 weak_ptr_factory_
.GetWeakPtr()));
113 power_manager_proxy_
->ConnectToSignal(
114 power_manager::kPowerManagerInterface
,
115 power_manager::kSuspendImminentSignal
,
117 &PowerManagerClientImpl::SuspendImminentReceived
,
118 weak_ptr_factory_
.GetWeakPtr()),
119 base::Bind(&PowerManagerClientImpl::SignalConnected
,
120 weak_ptr_factory_
.GetWeakPtr()));
122 power_manager_proxy_
->ConnectToSignal(
123 power_manager::kPowerManagerInterface
,
124 power_manager::kIdleActionImminentSignal
,
126 &PowerManagerClientImpl::IdleActionImminentReceived
,
127 weak_ptr_factory_
.GetWeakPtr()),
128 base::Bind(&PowerManagerClientImpl::SignalConnected
,
129 weak_ptr_factory_
.GetWeakPtr()));
131 power_manager_proxy_
->ConnectToSignal(
132 power_manager::kPowerManagerInterface
,
133 power_manager::kIdleActionDeferredSignal
,
135 &PowerManagerClientImpl::IdleActionDeferredReceived
,
136 weak_ptr_factory_
.GetWeakPtr()),
137 base::Bind(&PowerManagerClientImpl::SignalConnected
,
138 weak_ptr_factory_
.GetWeakPtr()));
140 RegisterSuspendDelay();
143 virtual ~PowerManagerClientImpl() {
144 // Here we should unregister suspend notifications from powerd,
146 // - The lifetime of the PowerManagerClientImpl can extend past that of
148 // - power_manager can already detect that the client is gone and
149 // unregister our suspend delay.
152 // PowerManagerClient overrides:
154 virtual void AddObserver(Observer
* observer
) OVERRIDE
{
155 CHECK(observer
); // http://crbug.com/119976
156 observers_
.AddObserver(observer
);
159 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
{
160 observers_
.RemoveObserver(observer
);
163 virtual bool HasObserver(Observer
* observer
) OVERRIDE
{
164 return observers_
.HasObserver(observer
);
167 virtual void DecreaseScreenBrightness(bool allow_off
) OVERRIDE
{
168 dbus::MethodCall
method_call(
169 power_manager::kPowerManagerInterface
,
170 power_manager::kDecreaseScreenBrightness
);
171 dbus::MessageWriter
writer(&method_call
);
172 writer
.AppendBool(allow_off
);
173 power_manager_proxy_
->CallMethod(
175 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
176 dbus::ObjectProxy::EmptyResponseCallback());
179 virtual void IncreaseScreenBrightness() OVERRIDE
{
180 SimpleMethodCallToPowerManager(power_manager::kIncreaseScreenBrightness
);
183 virtual void DecreaseKeyboardBrightness() OVERRIDE
{
184 SimpleMethodCallToPowerManager(power_manager::kDecreaseKeyboardBrightness
);
187 virtual void IncreaseKeyboardBrightness() OVERRIDE
{
188 SimpleMethodCallToPowerManager(power_manager::kIncreaseKeyboardBrightness
);
191 virtual void SetScreenBrightnessPercent(double percent
,
192 bool gradual
) OVERRIDE
{
193 dbus::MethodCall
method_call(
194 power_manager::kPowerManagerInterface
,
195 power_manager::kSetScreenBrightnessPercent
);
196 dbus::MessageWriter
writer(&method_call
);
197 writer
.AppendDouble(percent
);
200 power_manager::kBrightnessTransitionGradual
:
201 power_manager::kBrightnessTransitionInstant
);
202 power_manager_proxy_
->CallMethod(
204 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
205 dbus::ObjectProxy::EmptyResponseCallback());
208 virtual void GetScreenBrightnessPercent(
209 const GetScreenBrightnessPercentCallback
& callback
) OVERRIDE
{
210 dbus::MethodCall
method_call(power_manager::kPowerManagerInterface
,
211 power_manager::kGetScreenBrightnessPercent
);
212 power_manager_proxy_
->CallMethod(
214 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
215 base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent
,
216 weak_ptr_factory_
.GetWeakPtr(), callback
));
219 virtual void RequestStatusUpdate(UpdateRequestType update_type
) OVERRIDE
{
220 dbus::MethodCall
method_call(
221 power_manager::kPowerManagerInterface
,
222 power_manager::kGetPowerSupplyPropertiesMethod
);
223 power_manager_proxy_
->CallMethod(
225 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
226 base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod
,
227 weak_ptr_factory_
.GetWeakPtr()));
230 virtual void RequestRestart() OVERRIDE
{
231 SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod
);
234 virtual void RequestShutdown() OVERRIDE
{
235 SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod
);
238 virtual void RequestIdleNotification(int64 threshold
) OVERRIDE
{
239 dbus::MethodCall
method_call(power_manager::kPowerManagerInterface
,
240 power_manager::kRequestIdleNotification
);
241 dbus::MessageWriter
writer(&method_call
);
242 writer
.AppendInt64(threshold
);
244 power_manager_proxy_
->CallMethod(
246 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
247 dbus::ObjectProxy::EmptyResponseCallback());
250 virtual void NotifyUserActivity() OVERRIDE
{
251 SimpleMethodCallToPowerManager(power_manager::kHandleUserActivityMethod
);
254 virtual void NotifyVideoActivity(
255 const base::TimeTicks
& last_activity_time
,
256 bool is_fullscreen
) OVERRIDE
{
257 dbus::MethodCall
method_call(
258 power_manager::kPowerManagerInterface
,
259 power_manager::kHandleVideoActivityMethod
);
260 dbus::MessageWriter
writer(&method_call
);
262 VideoActivityUpdate protobuf
;
263 protobuf
.set_last_activity_time(last_activity_time
.ToInternalValue());
264 protobuf
.set_is_fullscreen(is_fullscreen
);
266 if (!writer
.AppendProtoAsArrayOfBytes(protobuf
)) {
267 LOG(ERROR
) << "Error calling "
268 << power_manager::kHandleVideoActivityMethod
;
271 power_manager_proxy_
->CallMethod(
273 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
274 dbus::ObjectProxy::EmptyResponseCallback());
277 virtual void SetPolicy(
278 const power_manager::PowerManagementPolicy
& policy
) OVERRIDE
{
279 dbus::MethodCall
method_call(
280 power_manager::kPowerManagerInterface
,
281 power_manager::kSetPolicyMethod
);
282 dbus::MessageWriter
writer(&method_call
);
283 if (!writer
.AppendProtoAsArrayOfBytes(policy
)) {
284 LOG(ERROR
) << "Error calling " << power_manager::kSetPolicyMethod
;
287 power_manager_proxy_
->CallMethod(
289 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
290 dbus::ObjectProxy::EmptyResponseCallback());
293 virtual void SetIsProjecting(bool is_projecting
) OVERRIDE
{
294 dbus::MethodCall
method_call(
295 power_manager::kPowerManagerInterface
,
296 power_manager::kSetIsProjectingMethod
);
297 dbus::MessageWriter
writer(&method_call
);
298 writer
.AppendBool(is_projecting
);
299 power_manager_proxy_
->CallMethod(
301 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
302 dbus::ObjectProxy::EmptyResponseCallback());
303 last_is_projecting_
= is_projecting
;
306 virtual base::Closure
GetSuspendReadinessCallback() OVERRIDE
{
307 DCHECK(OnOriginThread());
308 DCHECK(suspend_is_pending_
);
309 num_pending_suspend_readiness_callbacks_
++;
310 return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness
,
311 weak_ptr_factory_
.GetWeakPtr(), pending_suspend_id_
);
315 // Returns true if the current thread is the origin thread.
316 bool OnOriginThread() {
317 return base::PlatformThread::CurrentId() == origin_thread_id_
;
320 // Called when a dbus signal is initially connected.
321 void SignalConnected(const std::string
& interface_name
,
322 const std::string
& signal_name
,
324 LOG_IF(WARNING
, !success
) << "Failed to connect to signal "
325 << signal_name
<< ".";
328 // Make a method call to power manager with no arguments and no response.
329 void SimpleMethodCallToPowerManager(const std::string
& method_name
) {
330 dbus::MethodCall
method_call(power_manager::kPowerManagerInterface
,
332 power_manager_proxy_
->CallMethod(
334 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
335 dbus::ObjectProxy::EmptyResponseCallback());
338 void NameOwnerChangedReceived(dbus::Signal
* signal
) {
339 VLOG(1) << "Power manager restarted";
340 RegisterSuspendDelay();
341 SetIsProjecting(last_is_projecting_
);
342 FOR_EACH_OBSERVER(Observer
, observers_
, PowerManagerRestarted());
345 void BrightnessChangedReceived(dbus::Signal
* signal
) {
346 dbus::MessageReader
reader(signal
);
347 int32 brightness_level
= 0;
348 bool user_initiated
= 0;
349 if (!(reader
.PopInt32(&brightness_level
) &&
350 reader
.PopBool(&user_initiated
))) {
351 LOG(ERROR
) << "Brightness changed signal had incorrect parameters: "
352 << signal
->ToString();
355 VLOG(1) << "Brightness changed to " << brightness_level
356 << ": user initiated " << user_initiated
;
357 FOR_EACH_OBSERVER(Observer
, observers_
,
358 BrightnessChanged(brightness_level
, user_initiated
));
361 void PeripheralBatteryStatusReceived(dbus::Signal
* signal
) {
362 dbus::MessageReader
reader(signal
);
363 power_manager::PeripheralBatteryStatus protobuf_status
;
364 if (!reader
.PopArrayOfBytesAsProto(&protobuf_status
)) {
365 LOG(ERROR
) << "Unable to decode protocol buffer from "
366 << power_manager::kPeripheralBatteryStatusSignal
<< " signal";
370 std::string path
= protobuf_status
.path();
371 std::string name
= protobuf_status
.name();
372 int level
= protobuf_status
.has_level() ? protobuf_status
.level() : -1;
374 VLOG(1) << "Device battery status received " << level
375 << " for " << name
<< " at " << path
;
377 FOR_EACH_OBSERVER(Observer
, observers_
,
378 PeripheralBatteryStatusReceived(path
, name
, level
));
381 void PowerSupplyPollReceived(dbus::Signal
* unused_signal
) {
382 VLOG(1) << "Received power supply poll signal.";
383 RequestStatusUpdate(UPDATE_POLL
);
386 void OnGetPowerSupplyPropertiesMethod(dbus::Response
* response
) {
388 LOG(ERROR
) << "Error calling "
389 << power_manager::kGetPowerSupplyPropertiesMethod
;
393 dbus::MessageReader
reader(response
);
394 power_manager::PowerSupplyProperties protobuf
;
395 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
396 LOG(ERROR
) << "Error calling "
397 << power_manager::kGetPowerSupplyPropertiesMethod
398 << response
->ToString();
402 // TODO(derat): Update PowerSupplyStatus to keep the ExternalPower and
403 // BatteryState information from PowerSupplyProperties intact.
404 PowerSupplyStatus status
;
405 status
.line_power_on
= protobuf
.external_power() !=
406 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
;
407 status
.battery_is_present
= protobuf
.battery_state() !=
408 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT
;
409 status
.battery_is_full
= protobuf
.battery_state() ==
410 power_manager::PowerSupplyProperties_BatteryState_FULL
;
411 status
.battery_seconds_to_empty
= protobuf
.battery_time_to_empty_sec();
412 status
.battery_seconds_to_full
= protobuf
.battery_time_to_full_sec();
413 status
.battery_percentage
= protobuf
.battery_percent();
414 status
.is_calculating_battery_time
= protobuf
.is_calculating_battery_time();
416 switch (protobuf
.external_power()) {
417 case power_manager::PowerSupplyProperties_ExternalPower_AC
:
418 status
.battery_state
= PowerSupplyStatus::CHARGING
;
420 case power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
:
421 status
.battery_state
= PowerSupplyStatus::DISCHARGING
;
423 case power_manager::PowerSupplyProperties_ExternalPower_USB
:
424 status
.battery_state
= PowerSupplyStatus::CONNECTED_TO_USB
;
427 NOTREACHED() << "Unhandled external power state "
428 << protobuf
.external_power();
431 // Check power status values are consistent
432 if (!status
.is_calculating_battery_time
) {
433 int64 battery_seconds_to_goal
= status
.line_power_on
?
434 status
.battery_seconds_to_full
: status
.battery_seconds_to_empty
;
435 if (battery_seconds_to_goal
< 0) {
436 LOG(ERROR
) << "Received power supply status with negative seconds to "
437 << (status
.line_power_on
? "full" : "empty")
438 << ". Assume time is still being calculated.";
439 status
.is_calculating_battery_time
= true;
443 VLOG(1) << "Power status: " << status
.ToString();
444 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(status
));
447 void OnGetScreenBrightnessPercent(
448 const GetScreenBrightnessPercentCallback
& callback
,
449 dbus::Response
* response
) {
451 LOG(ERROR
) << "Error calling "
452 << power_manager::kGetScreenBrightnessPercent
;
455 dbus::MessageReader
reader(response
);
456 double percent
= 0.0;
457 if (!reader
.PopDouble(&percent
))
458 LOG(ERROR
) << "Error reading response from powerd: "
459 << response
->ToString();
460 callback
.Run(percent
);
463 void OnRegisterSuspendDelayReply(dbus::Response
* response
) {
465 LOG(ERROR
) << "Error calling "
466 << power_manager::kRegisterSuspendDelayMethod
;
470 dbus::MessageReader
reader(response
);
471 power_manager::RegisterSuspendDelayReply protobuf
;
472 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
473 LOG(ERROR
) << "Unable to parse reply from "
474 << power_manager::kRegisterSuspendDelayMethod
;
478 suspend_delay_id_
= protobuf
.delay_id();
479 has_suspend_delay_id_
= true;
480 VLOG(1) << "Registered suspend delay " << suspend_delay_id_
;
483 void IdleNotifySignalReceived(dbus::Signal
* signal
) {
484 dbus::MessageReader
reader(signal
);
486 if (!reader
.PopInt64(&threshold
)) {
487 LOG(ERROR
) << "Idle Notify signal had incorrect parameters: "
488 << signal
->ToString();
491 DCHECK_GT(threshold
, 0);
493 VLOG(1) << "Idle Notify: " << threshold
;
494 FOR_EACH_OBSERVER(Observer
, observers_
, IdleNotify(threshold
));
497 void SuspendImminentReceived(dbus::Signal
* signal
) {
498 if (!has_suspend_delay_id_
) {
499 LOG(ERROR
) << "Received unrequested "
500 << power_manager::kSuspendImminentSignal
<< " signal";
504 dbus::MessageReader
reader(signal
);
505 power_manager::SuspendImminent protobuf_imminent
;
506 if (!reader
.PopArrayOfBytesAsProto(&protobuf_imminent
)) {
507 LOG(ERROR
) << "Unable to decode protocol buffer from "
508 << power_manager::kSuspendImminentSignal
<< " signal";
512 if (suspend_is_pending_
) {
513 LOG(WARNING
) << "Got " << power_manager::kSuspendImminentSignal
514 << " signal about pending suspend attempt "
515 << protobuf_imminent
.suspend_id() << " while still waiting "
516 << "on attempt " << pending_suspend_id_
;
519 pending_suspend_id_
= protobuf_imminent
.suspend_id();
520 suspend_is_pending_
= true;
521 num_pending_suspend_readiness_callbacks_
= 0;
522 FOR_EACH_OBSERVER(Observer
, observers_
, SuspendImminent());
523 MaybeReportSuspendReadiness();
526 void IdleActionImminentReceived(dbus::Signal
* signal
) {
527 FOR_EACH_OBSERVER(Observer
, observers_
, IdleActionImminent());
530 void IdleActionDeferredReceived(dbus::Signal
* signal
) {
531 FOR_EACH_OBSERVER(Observer
, observers_
, IdleActionDeferred());
534 void InputEventReceived(dbus::Signal
* signal
) {
535 dbus::MessageReader
reader(signal
);
536 power_manager::InputEvent proto
;
537 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
538 LOG(ERROR
) << "Unable to decode protocol buffer from "
539 << power_manager::kInputEventSignal
<< " signal";
543 base::TimeTicks timestamp
=
544 base::TimeTicks::FromInternalValue(proto
.timestamp());
545 VLOG(1) << "Got " << power_manager::kInputEventSignal
<< " signal:"
546 << " type=" << proto
.type() << " timestamp=" << proto
.timestamp();
547 switch (proto
.type()) {
548 case power_manager::InputEvent_Type_POWER_BUTTON_DOWN
:
549 case power_manager::InputEvent_Type_POWER_BUTTON_UP
: {
551 (proto
.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN
);
552 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
553 PowerButtonEventReceived(down
, timestamp
));
556 case power_manager::InputEvent_Type_LID_OPEN
:
557 case power_manager::InputEvent_Type_LID_CLOSED
: {
559 (proto
.type() == power_manager::InputEvent_Type_LID_OPEN
);
560 FOR_EACH_OBSERVER(PowerManagerClient::Observer
, observers_
,
561 LidEventReceived(open
, timestamp
));
567 void SuspendStateChangedReceived(dbus::Signal
* signal
) {
568 dbus::MessageReader
reader(signal
);
569 power_manager::SuspendState proto
;
570 if (!reader
.PopArrayOfBytesAsProto(&proto
)) {
571 LOG(ERROR
) << "Unable to decode protocol buffer from "
572 << power_manager::kSuspendStateChangedSignal
<< " signal";
576 VLOG(1) << "Got " << power_manager::kSuspendStateChangedSignal
<< " signal:"
577 << " type=" << proto
.type() << " wall_time=" << proto
.wall_time();
578 base::Time wall_time
=
579 base::Time::FromInternalValue(proto
.wall_time());
580 switch (proto
.type()) {
581 case power_manager::SuspendState_Type_SUSPEND_TO_MEMORY
:
582 last_suspend_wall_time_
= wall_time
;
584 case power_manager::SuspendState_Type_RESUME
:
586 PowerManagerClient::Observer
, observers_
,
587 SystemResumed(wall_time
- last_suspend_wall_time_
));
592 // Registers a suspend delay with the power manager. This is usually
593 // only called at startup, but if the power manager restarts, we need to
594 // create a new delay.
595 void RegisterSuspendDelay() {
596 // Throw out any old delay that was registered.
597 suspend_delay_id_
= -1;
598 has_suspend_delay_id_
= false;
600 dbus::MethodCall
method_call(
601 power_manager::kPowerManagerInterface
,
602 power_manager::kRegisterSuspendDelayMethod
);
603 dbus::MessageWriter
writer(&method_call
);
605 power_manager::RegisterSuspendDelayRequest protobuf_request
;
606 base::TimeDelta timeout
=
607 base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs
);
608 protobuf_request
.set_timeout(timeout
.ToInternalValue());
609 protobuf_request
.set_description(kSuspendDelayDescription
);
611 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
612 LOG(ERROR
) << "Error constructing message for "
613 << power_manager::kRegisterSuspendDelayMethod
;
616 power_manager_proxy_
->CallMethod(
618 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
620 &PowerManagerClientImpl::OnRegisterSuspendDelayReply
,
621 weak_ptr_factory_
.GetWeakPtr()));
624 // Records the fact that an observer has finished doing asynchronous work
625 // that was blocking a pending suspend attempt and possibly reports
626 // suspend readiness to powerd. Called by callbacks returned via
627 // GetSuspendReadinessCallback().
628 void HandleObserverSuspendReadiness(int32 suspend_id
) {
629 DCHECK(OnOriginThread());
630 if (!suspend_is_pending_
|| suspend_id
!= pending_suspend_id_
)
633 num_pending_suspend_readiness_callbacks_
--;
634 MaybeReportSuspendReadiness();
637 // Reports suspend readiness to powerd if no observers are still holding
638 // suspend readiness callbacks.
639 void MaybeReportSuspendReadiness() {
640 if (!suspend_is_pending_
|| num_pending_suspend_readiness_callbacks_
> 0)
643 dbus::MethodCall
method_call(
644 power_manager::kPowerManagerInterface
,
645 power_manager::kHandleSuspendReadinessMethod
);
646 dbus::MessageWriter
writer(&method_call
);
648 power_manager::SuspendReadinessInfo protobuf_request
;
649 protobuf_request
.set_delay_id(suspend_delay_id_
);
650 protobuf_request
.set_suspend_id(pending_suspend_id_
);
652 pending_suspend_id_
= -1;
653 suspend_is_pending_
= false;
655 if (!writer
.AppendProtoAsArrayOfBytes(protobuf_request
)) {
656 LOG(ERROR
) << "Error constructing message for "
657 << power_manager::kHandleSuspendReadinessMethod
;
660 power_manager_proxy_
->CallMethod(
662 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
663 dbus::ObjectProxy::EmptyResponseCallback());
666 // Origin thread (i.e. the UI thread in production).
667 base::PlatformThreadId origin_thread_id_
;
669 dbus::ObjectProxy
* power_manager_proxy_
;
670 ObserverList
<Observer
> observers_
;
672 // The delay_id_ obtained from the RegisterSuspendDelay request.
673 int32 suspend_delay_id_
;
674 bool has_suspend_delay_id_
;
676 // powerd-supplied ID corresponding to an imminent suspend attempt that is
677 // currently being delayed.
678 int32 pending_suspend_id_
;
679 bool suspend_is_pending_
;
681 // Number of callbacks that have been returned by
682 // GetSuspendReadinessCallback() during the currently-pending suspend
683 // attempt but have not yet been called.
684 int num_pending_suspend_readiness_callbacks_
;
686 // Wall time from the latest signal telling us that the system was about to
687 // suspend to memory.
688 base::Time last_suspend_wall_time_
;
690 // Last state passed to SetIsProjecting().
691 bool last_is_projecting_
;
693 // Note: This should remain the last member so it'll be destroyed and
694 // invalidate its weak pointers before any other members are destroyed.
695 base::WeakPtrFactory
<PowerManagerClientImpl
> weak_ptr_factory_
;
697 DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl
);
700 // The PowerManagerClient implementation used on Linux desktop,
701 // which does nothing.
702 class PowerManagerClientStubImpl
: public PowerManagerClient
{
704 PowerManagerClientStubImpl()
705 : discharging_(true),
706 battery_percentage_(40),
712 virtual ~PowerManagerClientStubImpl() {}
714 // PowerManagerClient overrides:
716 virtual void AddObserver(Observer
* observer
) OVERRIDE
{
717 observers_
.AddObserver(observer
);
720 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
{
721 observers_
.RemoveObserver(observer
);
724 virtual bool HasObserver(Observer
* observer
) OVERRIDE
{
725 return observers_
.HasObserver(observer
);
728 virtual void DecreaseScreenBrightness(bool allow_off
) OVERRIDE
{
729 VLOG(1) << "Requested to descrease screen brightness";
730 SetBrightness(brightness_
- 5.0, true);
733 virtual void IncreaseScreenBrightness() OVERRIDE
{
734 VLOG(1) << "Requested to increase screen brightness";
735 SetBrightness(brightness_
+ 5.0, true);
738 virtual void SetScreenBrightnessPercent(double percent
,
739 bool gradual
) OVERRIDE
{
740 VLOG(1) << "Requested to set screen brightness to " << percent
<< "% "
741 << (gradual
? "gradually" : "instantaneously");
742 SetBrightness(percent
, false);
745 virtual void GetScreenBrightnessPercent(
746 const GetScreenBrightnessPercentCallback
& callback
) OVERRIDE
{
747 callback
.Run(brightness_
);
750 virtual void DecreaseKeyboardBrightness() OVERRIDE
{
751 VLOG(1) << "Requested to descrease keyboard brightness";
754 virtual void IncreaseKeyboardBrightness() OVERRIDE
{
755 VLOG(1) << "Requested to increase keyboard brightness";
758 virtual void RequestStatusUpdate(UpdateRequestType update_type
) OVERRIDE
{
759 if (update_type
== UPDATE_INITIAL
) {
763 if (!timer_
.IsRunning() && update_type
== UPDATE_USER
) {
767 base::TimeDelta::FromMilliseconds(1000),
769 &PowerManagerClientStubImpl::Update
);
775 virtual void RequestRestart() OVERRIDE
{}
776 virtual void RequestShutdown() OVERRIDE
{}
778 virtual void RequestIdleNotification(int64 threshold
) OVERRIDE
{
779 base::MessageLoop::current()->PostDelayedTask(
781 base::Bind(&PowerManagerClientStubImpl::TriggerIdleNotify
,
782 base::Unretained(this),
784 base::TimeDelta::FromMilliseconds(threshold
));
787 virtual void NotifyUserActivity() OVERRIDE
{}
788 virtual void NotifyVideoActivity(
789 const base::TimeTicks
& last_activity_time
,
790 bool is_fullscreen
) OVERRIDE
{}
791 virtual void SetPolicy(
792 const power_manager::PowerManagementPolicy
& policy
) OVERRIDE
{}
793 virtual void SetIsProjecting(bool is_projecting
) OVERRIDE
{}
794 virtual base::Closure
GetSuspendReadinessCallback() OVERRIDE
{
795 return base::Closure();
800 if (pause_count_
> 0) {
803 int discharge_amt
= battery_percentage_
<= 10 ? 1 : 10;
804 battery_percentage_
+= (discharging_
? -discharge_amt
: discharge_amt
);
805 battery_percentage_
= std::min(std::max(battery_percentage_
, 0), 100);
806 // We pause at 0 and 100% so that it's easier to check those conditions.
807 if (battery_percentage_
== 0 || battery_percentage_
== 100) {
808 discharging_
= !discharging_
;
810 if (battery_percentage_
== 100)
811 cycle_count_
= (cycle_count_
+ 1) % 3;
814 const int kSecondsToEmptyFullBattery(3 * 60 * 60); // 3 hours.
816 status_
.is_calculating_battery_time
= (pause_count_
> 1);
817 status_
.line_power_on
= !discharging_
;
818 status_
.battery_is_present
= true;
819 status_
.battery_percentage
= battery_percentage_
;
820 if (cycle_count_
!= 2) {
821 status_
.battery_state
= discharging_
?
822 PowerSupplyStatus::DISCHARGING
: PowerSupplyStatus::CHARGING
;
824 // Simulating a non-standard weak power supply.
825 status_
.battery_state
=
826 PowerSupplyStatus::NEITHER_CHARGING_NOR_DISCHARGING
;
829 int64 remaining_battery_time
=
830 std::max(1, battery_percentage_
* kSecondsToEmptyFullBattery
/ 100);
831 status_
.battery_seconds_to_empty
=
832 status_
.battery_state
== PowerSupplyStatus::DISCHARGING
?
833 remaining_battery_time
: 0;
834 status_
.battery_seconds_to_full
=
835 status_
.battery_state
== PowerSupplyStatus::DISCHARGING
?
836 0 : std::max(static_cast<int64
>(1),
837 kSecondsToEmptyFullBattery
- remaining_battery_time
);
838 FOR_EACH_OBSERVER(Observer
, observers_
, PowerChanged(status_
));
841 void SetBrightness(double percent
, bool user_initiated
) {
842 brightness_
= std::min(std::max(0.0, percent
), 100.0);
843 int brightness_level
= static_cast<int>(brightness_
);
844 FOR_EACH_OBSERVER(Observer
, observers_
,
845 BrightnessChanged(brightness_level
, user_initiated
));
848 void TriggerIdleNotify(int64 threshold
) {
849 FOR_EACH_OBSERVER(Observer
, observers_
, IdleNotify(threshold
));
853 int battery_percentage_
;
857 ObserverList
<Observer
> observers_
;
858 base::RepeatingTimer
<PowerManagerClientStubImpl
> timer_
;
859 PowerSupplyStatus status_
;
862 PowerManagerClient::PowerManagerClient() {
865 PowerManagerClient::~PowerManagerClient() {
869 PowerManagerClient
* PowerManagerClient::Create(
870 DBusClientImplementationType type
,
872 if (type
== REAL_DBUS_CLIENT_IMPLEMENTATION
)
873 return new PowerManagerClientImpl(bus
);
874 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION
, type
);
875 return new PowerManagerClientStubImpl();
878 } // namespace chromeos