[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / chromeos / dbus / power_manager_client.cc
blob6840dcf67a483424a1cf0105a9d2f5a89f2e8152
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 ~PowerManagerClientImpl() override {
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 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(
100 &method_call,
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);
126 writer.AppendInt32(
127 gradual ?
128 power_manager::kBrightnessTransitionGradual :
129 power_manager::kBrightnessTransitionInstant);
130 power_manager_proxy_->CallMethod(
131 &method_call,
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(
142 &method_call,
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(
154 &method_call,
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(
183 &method_call,
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(
196 &method_call,
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;
209 return;
211 power_manager_proxy_->CallMethod(
212 &method_call,
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(
225 &method_call,
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_;
244 protected:
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,
292 base::Bind(
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,
309 base::Bind(
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,
318 base::Bind(
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,
327 base::Bind(
328 &PowerManagerClientImpl::IdleActionDeferredReceived,
329 weak_ptr_factory_.GetWeakPtr()),
330 base::Bind(&PowerManagerClientImpl::SignalConnected,
331 weak_ptr_factory_.GetWeakPtr()));
333 RegisterSuspendDelays();
336 private:
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,
345 bool success) {
346 if (!success)
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,
353 method_name);
354 power_manager_proxy_->CallMethod(
355 &method_call,
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())
364 << " New owner: "
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();
385 return;
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
399 << " signal";
400 return;
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);
420 } else {
421 POWER_LOG(ERROR) << "Unable to decode "
422 << power_manager::kPowerSupplyPollSignal << " signal";
426 void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
427 if (!response) {
428 POWER_LOG(ERROR) << "Error calling "
429 << power_manager::kGetPowerSupplyPropertiesMethod;
430 return;
433 dbus::MessageReader reader(response);
434 power_manager::PowerSupplyProperties protobuf;
435 if (reader.PopArrayOfBytesAsProto(&protobuf)) {
436 HandlePowerSupplyProperties(protobuf);
437 } else {
438 POWER_LOG(ERROR) << "Unable to decode "
439 << power_manager::kGetPowerSupplyPropertiesMethod
440 << " response";
444 void OnGetScreenBrightnessPercent(
445 const GetScreenBrightnessPercentCallback& callback,
446 dbus::Response* response) {
447 if (!response) {
448 POWER_LOG(ERROR) << "Error calling "
449 << power_manager::kGetScreenBrightnessPercentMethod;
450 return;
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) {
471 if (!response) {
472 POWER_LOG(ERROR) << "Error calling " << method_name;
473 return;
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;
480 return;
483 if (dark_suspend) {
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_;
488 } else {
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";
500 return;
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";
508 return;
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
517 // wonky.
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());
532 else
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";
544 return;
547 const base::TimeDelta duration =
548 base::TimeDelta::FromInternalValue(proto.suspend_duration());
549 POWER_LOG(EVENT) << "Got " << power_manager::kSuspendDoneSignal
550 << " signal:"
551 << " suspend_id=" << proto.suspend_id()
552 << " duration=" << duration.InSeconds() << " sec";
554 if (render_process_manager_delegate_)
555 render_process_manager_delegate_->SuspendDone();
557 FOR_EACH_OBSERVER(
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";
568 return;
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";
585 return;
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: {
596 const bool down =
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.
602 if (down) {
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(
609 &method_call,
610 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
611 dbus::ObjectProxy::EmptyResponseCallback());
613 break;
615 case power_manager::InputEvent_Type_LID_OPEN:
616 case power_manager::InputEvent_Type_LID_CLOSED: {
617 bool open =
618 (proto.type() == power_manager::InputEvent_Type_LID_OPEN);
619 FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
620 LidEventReceived(open, timestamp));
621 break;
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;
636 return;
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
645 // delays.
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,
661 protobuf_request,
662 base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
663 weak_ptr_factory_.GetWeakPtr(), false,
664 power_manager::kRegisterSuspendDelayMethod));
665 RegisterSuspendDelayImpl(
666 power_manager::kRegisterDarkSuspendDelayMethod,
667 protobuf_request,
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_)
681 return;
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)
691 return;
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_;
698 } else {
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;
721 return;
723 power_manager_proxy_->CallMethod(
724 &method_call,
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
763 // processes.
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 {
776 public:
777 PowerManagerClientStubImpl()
778 : discharging_(true),
779 battery_percentage_(40),
780 brightness_(50.0),
781 pause_count_(2),
782 cycle_count_(0),
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,
797 power_cycle_delay_,
798 this,
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_;
872 private:
873 void HandleSuspendReadiness() {
874 num_pending_suspend_readiness_callbacks_--;
877 void UpdateStatus() {
878 if (pause_count_ > 0) {
879 pause_count_--;
880 if (pause_count_ == 2)
881 discharging_ = !discharging_;
882 } else {
883 if (discharging_)
884 battery_percentage_ -= (battery_percentage_ <= 10 ? 1 : 10);
885 else
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) {
890 pause_count_ = 4;
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);
900 props_.Clear();
902 switch (cycle_count_) {
903 case 0:
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);
909 break;
910 case 1:
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);
915 break;
916 case 2:
917 // Say that the system is both charging and discharging on AC.
918 props_.set_external_power(
919 power_manager::PowerSupplyProperties_ExternalPower_AC);
920 break;
921 default:
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));
933 } else {
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))
955 return;
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") {
968 int seconds = 1;
969 if (!arg1.empty())
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
976 bool discharging_;
977 int battery_percentage_;
978 double brightness_;
979 int pause_count_;
980 int cycle_count_;
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
986 // invoked.
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() {
1000 // static
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