Add type annotations to exif_parser.js.
[chromium-blink-merge.git] / chromeos / dbus / power_manager_client.cc
blob374af7f2234b3abdbb3d3e9dc1e15522a4fdb40c
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"
7 #include <algorithm>
9 #include "base/bind.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"
31 #include "dbus/bus.h"
32 #include "dbus/message.h"
33 #include "dbus/object_path.h"
34 #include "dbus/object_proxy.h"
36 namespace chromeos {
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 {
47 public:
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,
64 // however:
65 // - The lifetime of the PowerManagerClientImpl can extend past that of
66 // the objectproxy,
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(
100 &method_call,
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);
127 writer.AppendInt32(
128 gradual ?
129 power_manager::kBrightnessTransitionGradual :
130 power_manager::kBrightnessTransitionInstant);
131 power_manager_proxy_->CallMethod(
132 &method_call,
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(
143 &method_call,
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(
155 &method_call,
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(
185 &method_call,
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(
198 &method_call,
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;
212 return;
214 power_manager_proxy_->CallMethod(
215 &method_call,
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(
228 &method_call,
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_;
247 protected:
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,
295 base::Bind(
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,
312 base::Bind(
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,
321 base::Bind(
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,
330 base::Bind(
331 &PowerManagerClientImpl::IdleActionDeferredReceived,
332 weak_ptr_factory_.GetWeakPtr()),
333 base::Bind(&PowerManagerClientImpl::SignalConnected,
334 weak_ptr_factory_.GetWeakPtr()));
336 RegisterSuspendDelays();
339 private:
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,
348 bool success) {
349 if (!success)
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,
356 method_name);
357 power_manager_proxy_->CallMethod(
358 &method_call,
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())
367 << " New owner: "
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();
388 return;
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
402 << " signal";
403 return;
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);
423 } else {
424 POWER_LOG(ERROR) << "Unable to decode "
425 << power_manager::kPowerSupplyPollSignal << " signal";
429 void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
430 if (!response) {
431 POWER_LOG(ERROR) << "Error calling "
432 << power_manager::kGetPowerSupplyPropertiesMethod;
433 return;
436 dbus::MessageReader reader(response);
437 power_manager::PowerSupplyProperties protobuf;
438 if (reader.PopArrayOfBytesAsProto(&protobuf)) {
439 HandlePowerSupplyProperties(protobuf);
440 } else {
441 POWER_LOG(ERROR) << "Unable to decode "
442 << power_manager::kGetPowerSupplyPropertiesMethod
443 << " response";
447 void OnGetScreenBrightnessPercent(
448 const GetScreenBrightnessPercentCallback& callback,
449 dbus::Response* response) {
450 if (!response) {
451 POWER_LOG(ERROR) << "Error calling "
452 << power_manager::kGetScreenBrightnessPercentMethod;
453 return;
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) {
474 if (!response) {
475 POWER_LOG(ERROR) << "Error calling " << method_name;
476 return;
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;
483 return;
486 if (dark_suspend) {
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_;
491 } else {
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";
503 return;
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";
511 return;
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
520 // wonky.
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());
535 else
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";
547 return;
550 const base::TimeDelta duration =
551 base::TimeDelta::FromInternalValue(proto.suspend_duration());
552 POWER_LOG(EVENT) << "Got " << power_manager::kSuspendDoneSignal
553 << " signal:"
554 << " suspend_id=" << proto.suspend_id()
555 << " duration=" << duration.InSeconds() << " sec";
557 if (render_process_manager_delegate_)
558 render_process_manager_delegate_->SuspendDone();
560 FOR_EACH_OBSERVER(
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";
571 return;
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";
588 return;
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: {
599 const bool down =
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.
605 if (down) {
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(
612 &method_call,
613 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
614 dbus::ObjectProxy::EmptyResponseCallback());
616 break;
618 case power_manager::InputEvent_Type_LID_OPEN:
619 case power_manager::InputEvent_Type_LID_CLOSED: {
620 bool open =
621 (proto.type() == power_manager::InputEvent_Type_LID_OPEN);
622 FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
623 LidEventReceived(open, timestamp));
624 break;
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;
639 return;
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
648 // delays.
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,
664 protobuf_request,
665 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
666 weak_ptr_factory_.GetWeakPtr(), false,
667 power_manager::kRegisterSuspendDelayMethod));
668 RegisterSuspendDelayImpl(
669 power_manager::kRegisterDarkSuspendDelayMethod,
670 protobuf_request,
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_)
684 return;
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)
694 return;
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_;
701 } else {
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;
724 return;
726 power_manager_proxy_->CallMethod(
727 &method_call,
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
766 // processes.
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 {
779 public:
780 PowerManagerClientStubImpl()
781 : discharging_(true),
782 battery_percentage_(40),
783 brightness_(50.0),
784 pause_count_(2),
785 cycle_count_(0),
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,
800 power_cycle_delay_,
801 this,
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_;
879 private:
880 void HandleSuspendReadiness() {
881 num_pending_suspend_readiness_callbacks_--;
884 void UpdateStatus() {
885 if (pause_count_ > 0) {
886 pause_count_--;
887 if (pause_count_ == 2)
888 discharging_ = !discharging_;
889 } else {
890 if (discharging_)
891 battery_percentage_ -= (battery_percentage_ <= 10 ? 1 : 10);
892 else
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) {
897 pause_count_ = 4;
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);
907 props_.Clear();
909 switch (cycle_count_) {
910 case 0:
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);
916 break;
917 case 1:
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);
922 break;
923 case 2:
924 // Say that the system is both charging and discharging on AC.
925 props_.set_external_power(
926 power_manager::PowerSupplyProperties_ExternalPower_AC);
927 break;
928 default:
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));
940 } else {
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))
962 return;
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") {
975 int seconds = 1;
976 if (!arg1.empty())
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
983 bool discharging_;
984 int battery_percentage_;
985 double brightness_;
986 int pause_count_;
987 int cycle_count_;
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
993 // invoked.
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() {
1007 // static
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