Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / power_manager_client.cc
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.
4
5 #include "chromeos/dbus/power_manager_client.h"
6
7 #include <algorithm>
8
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 "dbus/bus.h"
31 #include "dbus/message.h"
32 #include "dbus/object_path.h"
33 #include "dbus/object_proxy.h"
34
35 namespace chromeos {
36
37 // Maximum amount of time that the power manager will wait for Chrome to
38 // say that it's ready for the system to be suspended, in milliseconds.
39 const int kSuspendDelayTimeoutMs = 5000;
40
41 // Human-readable description of Chrome's suspend delay.
42 const char kSuspendDelayDescription[] = "chrome";
43
44 // The PowerManagerClient implementation used in production.
45 class PowerManagerClientImpl : public PowerManagerClient {
46  public:
47   PowerManagerClientImpl()
48       : origin_thread_id_(base::PlatformThread::CurrentId()),
49         power_manager_proxy_(NULL),
50         suspend_delay_id_(-1),
51         has_suspend_delay_id_(false),
52         dark_suspend_delay_id_(-1),
53         has_dark_suspend_delay_id_(false),
54         pending_suspend_id_(-1),
55         suspend_is_pending_(false),
56         suspending_from_dark_resume_(false),
57         num_pending_suspend_readiness_callbacks_(0),
58         last_is_projecting_(false),
59         weak_ptr_factory_(this) {}
60
61   virtual ~PowerManagerClientImpl() {
62     // Here we should unregister suspend notifications from powerd,
63     // however:
64     // - The lifetime of the PowerManagerClientImpl can extend past that of
65     //   the objectproxy,
66     // - power_manager can already detect that the client is gone and
67     //   unregister our suspend delay.
68   }
69
70   // PowerManagerClient overrides:
71
72   virtual void AddObserver(Observer* observer) override {
73     CHECK(observer);  // http://crbug.com/119976
74     observers_.AddObserver(observer);
75   }
76
77   virtual void RemoveObserver(Observer* observer) override {
78     observers_.RemoveObserver(observer);
79   }
80
81   virtual bool HasObserver(Observer* observer) override {
82     return observers_.HasObserver(observer);
83   }
84
85   virtual void DecreaseScreenBrightness(bool allow_off) override {
86     dbus::MethodCall method_call(
87         power_manager::kPowerManagerInterface,
88         power_manager::kDecreaseScreenBrightnessMethod);
89     dbus::MessageWriter writer(&method_call);
90     writer.AppendBool(allow_off);
91     power_manager_proxy_->CallMethod(
92         &method_call,
93         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
94         dbus::ObjectProxy::EmptyResponseCallback());
95   }
96
97   virtual void IncreaseScreenBrightness() override {
98     SimpleMethodCallToPowerManager(
99         power_manager::kIncreaseScreenBrightnessMethod);
100   }
101
102   virtual void DecreaseKeyboardBrightness() override {
103     SimpleMethodCallToPowerManager(
104         power_manager::kDecreaseKeyboardBrightnessMethod);
105   }
106
107   virtual void IncreaseKeyboardBrightness() override {
108     SimpleMethodCallToPowerManager(
109         power_manager::kIncreaseKeyboardBrightnessMethod);
110   }
111
112   virtual void SetScreenBrightnessPercent(double percent,
113                                           bool gradual) override {
114     dbus::MethodCall method_call(
115         power_manager::kPowerManagerInterface,
116         power_manager::kSetScreenBrightnessPercentMethod);
117     dbus::MessageWriter writer(&method_call);
118     writer.AppendDouble(percent);
119     writer.AppendInt32(
120         gradual ?
121         power_manager::kBrightnessTransitionGradual :
122         power_manager::kBrightnessTransitionInstant);
123     power_manager_proxy_->CallMethod(
124         &method_call,
125         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
126         dbus::ObjectProxy::EmptyResponseCallback());
127   }
128
129   virtual void GetScreenBrightnessPercent(
130       const GetScreenBrightnessPercentCallback& callback) override {
131     dbus::MethodCall method_call(
132         power_manager::kPowerManagerInterface,
133         power_manager::kGetScreenBrightnessPercentMethod);
134     power_manager_proxy_->CallMethod(
135         &method_call,
136         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
137         base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent,
138                    weak_ptr_factory_.GetWeakPtr(), callback));
139   }
140
141   virtual void RequestStatusUpdate() override {
142     dbus::MethodCall method_call(
143         power_manager::kPowerManagerInterface,
144         power_manager::kGetPowerSupplyPropertiesMethod);
145     power_manager_proxy_->CallMethod(
146         &method_call,
147         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
148         base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod,
149                    weak_ptr_factory_.GetWeakPtr()));
150   }
151
152   virtual void RequestSuspend() override {
153     SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod);
154   }
155
156   virtual void RequestRestart() override {
157     SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod);
158   }
159
160   virtual void RequestShutdown() override {
161     SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod);
162   }
163
164   virtual void NotifyUserActivity(
165       power_manager::UserActivityType type) override {
166     dbus::MethodCall method_call(
167         power_manager::kPowerManagerInterface,
168         power_manager::kHandleUserActivityMethod);
169     dbus::MessageWriter writer(&method_call);
170     writer.AppendInt32(type);
171
172     power_manager_proxy_->CallMethod(
173         &method_call,
174         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
175         dbus::ObjectProxy::EmptyResponseCallback());
176   }
177
178   virtual void NotifyVideoActivity(bool is_fullscreen) override {
179     dbus::MethodCall method_call(
180         power_manager::kPowerManagerInterface,
181         power_manager::kHandleVideoActivityMethod);
182     dbus::MessageWriter writer(&method_call);
183     writer.AppendBool(is_fullscreen);
184
185     power_manager_proxy_->CallMethod(
186         &method_call,
187         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
188         dbus::ObjectProxy::EmptyResponseCallback());
189   }
190
191   virtual void SetPolicy(
192       const power_manager::PowerManagementPolicy& policy) override {
193     dbus::MethodCall method_call(
194         power_manager::kPowerManagerInterface,
195         power_manager::kSetPolicyMethod);
196     dbus::MessageWriter writer(&method_call);
197     if (!writer.AppendProtoAsArrayOfBytes(policy)) {
198       LOG(ERROR) << "Error calling " << power_manager::kSetPolicyMethod;
199       return;
200     }
201     power_manager_proxy_->CallMethod(
202         &method_call,
203         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
204         dbus::ObjectProxy::EmptyResponseCallback());
205   }
206
207   virtual void SetIsProjecting(bool is_projecting) override {
208     dbus::MethodCall method_call(
209         power_manager::kPowerManagerInterface,
210         power_manager::kSetIsProjectingMethod);
211     dbus::MessageWriter writer(&method_call);
212     writer.AppendBool(is_projecting);
213     power_manager_proxy_->CallMethod(
214         &method_call,
215         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
216         dbus::ObjectProxy::EmptyResponseCallback());
217     last_is_projecting_ = is_projecting;
218   }
219
220   virtual base::Closure GetSuspendReadinessCallback() override {
221     DCHECK(OnOriginThread());
222     DCHECK(suspend_is_pending_);
223     num_pending_suspend_readiness_callbacks_++;
224     return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness,
225                       weak_ptr_factory_.GetWeakPtr(), pending_suspend_id_,
226                       suspending_from_dark_resume_);
227   }
228
229   virtual int GetNumPendingSuspendReadinessCallbacks() override {
230     return num_pending_suspend_readiness_callbacks_;
231   }
232
233  protected:
234   virtual void Init(dbus::Bus* bus) override {
235     power_manager_proxy_ = bus->GetObjectProxy(
236         power_manager::kPowerManagerServiceName,
237         dbus::ObjectPath(power_manager::kPowerManagerServicePath));
238
239     power_manager_proxy_->SetNameOwnerChangedCallback(
240         base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived,
241                    weak_ptr_factory_.GetWeakPtr()));
242
243     // Monitor the D-Bus signal for brightness changes. Only the power
244     // manager knows the actual brightness level. We don't cache the
245     // brightness level in Chrome as it'll make things less reliable.
246     power_manager_proxy_->ConnectToSignal(
247         power_manager::kPowerManagerInterface,
248         power_manager::kBrightnessChangedSignal,
249         base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived,
250                    weak_ptr_factory_.GetWeakPtr()),
251         base::Bind(&PowerManagerClientImpl::SignalConnected,
252                    weak_ptr_factory_.GetWeakPtr()));
253
254     power_manager_proxy_->ConnectToSignal(
255         power_manager::kPowerManagerInterface,
256         power_manager::kPeripheralBatteryStatusSignal,
257         base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived,
258                    weak_ptr_factory_.GetWeakPtr()),
259         base::Bind(&PowerManagerClientImpl::SignalConnected,
260                    weak_ptr_factory_.GetWeakPtr()));
261
262     power_manager_proxy_->ConnectToSignal(
263         power_manager::kPowerManagerInterface,
264         power_manager::kPowerSupplyPollSignal,
265         base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived,
266                    weak_ptr_factory_.GetWeakPtr()),
267         base::Bind(&PowerManagerClientImpl::SignalConnected,
268                    weak_ptr_factory_.GetWeakPtr()));
269
270     power_manager_proxy_->ConnectToSignal(
271         power_manager::kPowerManagerInterface,
272         power_manager::kInputEventSignal,
273         base::Bind(&PowerManagerClientImpl::InputEventReceived,
274                    weak_ptr_factory_.GetWeakPtr()),
275         base::Bind(&PowerManagerClientImpl::SignalConnected,
276                    weak_ptr_factory_.GetWeakPtr()));
277
278     power_manager_proxy_->ConnectToSignal(
279         power_manager::kPowerManagerInterface,
280         power_manager::kSuspendImminentSignal,
281         base::Bind(
282             &PowerManagerClientImpl::HandleSuspendImminent,
283             weak_ptr_factory_.GetWeakPtr(), false),
284         base::Bind(&PowerManagerClientImpl::SignalConnected,
285                    weak_ptr_factory_.GetWeakPtr()));
286
287     power_manager_proxy_->ConnectToSignal(
288         power_manager::kPowerManagerInterface,
289         power_manager::kSuspendDoneSignal,
290         base::Bind(&PowerManagerClientImpl::SuspendDoneReceived,
291                    weak_ptr_factory_.GetWeakPtr()),
292         base::Bind(&PowerManagerClientImpl::SignalConnected,
293                    weak_ptr_factory_.GetWeakPtr()));
294
295     power_manager_proxy_->ConnectToSignal(
296         power_manager::kPowerManagerInterface,
297         power_manager::kDarkSuspendImminentSignal,
298         base::Bind(
299             &PowerManagerClientImpl::HandleSuspendImminent,
300             weak_ptr_factory_.GetWeakPtr(), true),
301         base::Bind(&PowerManagerClientImpl::SignalConnected,
302                    weak_ptr_factory_.GetWeakPtr()));
303
304     power_manager_proxy_->ConnectToSignal(
305         power_manager::kPowerManagerInterface,
306         power_manager::kIdleActionImminentSignal,
307         base::Bind(
308             &PowerManagerClientImpl::IdleActionImminentReceived,
309             weak_ptr_factory_.GetWeakPtr()),
310         base::Bind(&PowerManagerClientImpl::SignalConnected,
311                    weak_ptr_factory_.GetWeakPtr()));
312
313     power_manager_proxy_->ConnectToSignal(
314         power_manager::kPowerManagerInterface,
315         power_manager::kIdleActionDeferredSignal,
316         base::Bind(
317             &PowerManagerClientImpl::IdleActionDeferredReceived,
318             weak_ptr_factory_.GetWeakPtr()),
319         base::Bind(&PowerManagerClientImpl::SignalConnected,
320                    weak_ptr_factory_.GetWeakPtr()));
321
322     RegisterSuspendDelays();
323   }
324
325  private:
326   // Returns true if the current thread is the origin thread.
327   bool OnOriginThread() {
328     return base::PlatformThread::CurrentId() == origin_thread_id_;
329   }
330
331   // Called when a dbus signal is initially connected.
332   void SignalConnected(const std::string& interface_name,
333                        const std::string& signal_name,
334                        bool success) {
335     LOG_IF(WARNING, !success) << "Failed to connect to signal "
336                               << signal_name << ".";
337   }
338
339   // Makes a method call to power manager with no arguments and no response.
340   void SimpleMethodCallToPowerManager(const std::string& method_name) {
341     dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
342                                  method_name);
343     power_manager_proxy_->CallMethod(
344         &method_call,
345         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
346         dbus::ObjectProxy::EmptyResponseCallback());
347   }
348
349   void NameOwnerChangedReceived(const std::string& old_owner,
350                                 const std::string& new_owner) {
351     VLOG(1) << "Power manager restarted (old owner was "
352             << (old_owner.empty() ? "[none]" : old_owner.c_str())
353             << ", new owner is "
354             << (new_owner.empty() ? "[none]" : new_owner.c_str()) << ")";
355     suspend_is_pending_ = false;
356     pending_suspend_id_ = -1;
357     suspending_from_dark_resume_ = false;
358     if (!new_owner.empty()) {
359       VLOG(1) << "Sending initial state to power manager";
360       RegisterSuspendDelays();
361       SetIsProjecting(last_is_projecting_);
362       FOR_EACH_OBSERVER(Observer, observers_, PowerManagerRestarted());
363     }
364   }
365
366   void BrightnessChangedReceived(dbus::Signal* signal) {
367     dbus::MessageReader reader(signal);
368     int32_t brightness_level = 0;
369     bool user_initiated = 0;
370     if (!(reader.PopInt32(&brightness_level) &&
371           reader.PopBool(&user_initiated))) {
372       LOG(ERROR) << "Brightness changed signal had incorrect parameters: "
373                  << signal->ToString();
374       return;
375     }
376     VLOG(1) << "Brightness changed to " << brightness_level
377             << ": user initiated " << user_initiated;
378     FOR_EACH_OBSERVER(Observer, observers_,
379                       BrightnessChanged(brightness_level, user_initiated));
380   }
381
382   void PeripheralBatteryStatusReceived(dbus::Signal* signal) {
383     dbus::MessageReader reader(signal);
384     power_manager::PeripheralBatteryStatus protobuf_status;
385     if (!reader.PopArrayOfBytesAsProto(&protobuf_status)) {
386       LOG(ERROR) << "Unable to decode protocol buffer from "
387                  << power_manager::kPeripheralBatteryStatusSignal << " signal";
388       return;
389     }
390
391     std::string path = protobuf_status.path();
392     std::string name = protobuf_status.name();
393     int level = protobuf_status.has_level() ? protobuf_status.level() : -1;
394
395     VLOG(1) << "Device battery status received " << level
396             << " for " << name << " at " << path;
397
398     FOR_EACH_OBSERVER(Observer, observers_,
399                       PeripheralBatteryStatusReceived(path, name, level));
400   }
401
402   void PowerSupplyPollReceived(dbus::Signal* signal) {
403     VLOG(1) << "Received power supply poll signal.";
404     dbus::MessageReader reader(signal);
405     power_manager::PowerSupplyProperties protobuf;
406     if (reader.PopArrayOfBytesAsProto(&protobuf)) {
407       HandlePowerSupplyProperties(protobuf);
408     } else {
409       LOG(ERROR) << "Unable to decode "
410                  << power_manager::kPowerSupplyPollSignal << "signal";
411     }
412   }
413
414   void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
415     if (!response) {
416       LOG(ERROR) << "Error calling "
417                  << power_manager::kGetPowerSupplyPropertiesMethod;
418       return;
419     }
420
421     dbus::MessageReader reader(response);
422     power_manager::PowerSupplyProperties protobuf;
423     if (reader.PopArrayOfBytesAsProto(&protobuf)) {
424       HandlePowerSupplyProperties(protobuf);
425     } else {
426       LOG(ERROR) << "Unable to decode "
427                  << power_manager::kGetPowerSupplyPropertiesMethod
428                  << " response";
429     }
430   }
431
432   void OnGetScreenBrightnessPercent(
433       const GetScreenBrightnessPercentCallback& callback,
434       dbus::Response* response) {
435     if (!response) {
436       LOG(ERROR) << "Error calling "
437                  << power_manager::kGetScreenBrightnessPercentMethod;
438       return;
439     }
440     dbus::MessageReader reader(response);
441     double percent = 0.0;
442     if (!reader.PopDouble(&percent))
443       LOG(ERROR) << "Error reading response from powerd: "
444                  << response->ToString();
445     callback.Run(percent);
446   }
447
448   void HandlePowerSupplyProperties(
449       const power_manager::PowerSupplyProperties& proto) {
450     FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(proto));
451     const bool on_battery = proto.external_power() ==
452         power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
453     base::PowerMonitorDeviceSource::SetPowerSource(on_battery);
454   }
455
456   void HandleRegisterSuspendDelayReply(bool dark_suspend,
457                                        const std::string& method_name,
458                                        dbus::Response* response) {
459     if (!response) {
460       LOG(ERROR) << "Error calling " << method_name;
461       return;
462     }
463
464     dbus::MessageReader reader(response);
465     power_manager::RegisterSuspendDelayReply protobuf;
466     if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
467       LOG(ERROR) << "Unable to parse reply from " << method_name;
468       return;
469     }
470
471     if (dark_suspend) {
472       dark_suspend_delay_id_ = protobuf.delay_id();
473       has_dark_suspend_delay_id_ = true;
474       VLOG(1) << "Registered dark suspend delay " << dark_suspend_delay_id_;
475     } else {
476       suspend_delay_id_ = protobuf.delay_id();
477       has_suspend_delay_id_ = true;
478       VLOG(1) << "Registered suspend delay " << suspend_delay_id_;
479     }
480   }
481
482   void HandleSuspendImminent(bool in_dark_resume, dbus::Signal* signal) {
483     std::string signal_name = signal->GetMember();
484     if ((in_dark_resume && !has_dark_suspend_delay_id_) ||
485         (!in_dark_resume && !has_suspend_delay_id_)) {
486       LOG(ERROR) << "Received unrequested " << signal_name << " signal";
487       return;
488     }
489
490     dbus::MessageReader reader(signal);
491     power_manager::SuspendImminent proto;
492     if (!reader.PopArrayOfBytesAsProto(&proto)) {
493       LOG(ERROR) << "Unable to decode protocol buffer from " << signal_name
494                  << " signal";
495       return;
496     }
497
498     VLOG(1) << "Got " << signal_name << " signal announcing suspend attempt "
499             << proto.suspend_id();
500
501     // If a previous suspend is pending from the same state we are currently in
502     // (fully powered on or in dark resume), then something's gone a little
503     // wonky.
504     if (suspend_is_pending_ &&
505         suspending_from_dark_resume_ == in_dark_resume) {
506       LOG(WARNING) << "Got " << signal_name << " signal about pending suspend "
507                    << "attempt " << proto.suspend_id() << " while still "
508                    << "waiting on attempt " << pending_suspend_id_;
509     }
510
511     pending_suspend_id_ = proto.suspend_id();
512     suspend_is_pending_ = true;
513     suspending_from_dark_resume_ = in_dark_resume;
514     num_pending_suspend_readiness_callbacks_ = 0;
515     if (suspending_from_dark_resume_)
516       FOR_EACH_OBSERVER(Observer, observers_, DarkSuspendImminent());
517     else
518       FOR_EACH_OBSERVER(Observer, observers_, SuspendImminent());
519     base::PowerMonitorDeviceSource::HandleSystemSuspending();
520     MaybeReportSuspendReadiness();
521   }
522
523   void SuspendDoneReceived(dbus::Signal* signal) {
524     dbus::MessageReader reader(signal);
525     power_manager::SuspendDone proto;
526     if (!reader.PopArrayOfBytesAsProto(&proto)) {
527       LOG(ERROR) << "Unable to decode protocol buffer from "
528                  << power_manager::kSuspendDoneSignal << " signal";
529       return;
530     }
531
532     const base::TimeDelta duration =
533         base::TimeDelta::FromInternalValue(proto.suspend_duration());
534     VLOG(1) << "Got " << power_manager::kSuspendDoneSignal << " signal:"
535             << " suspend_id=" << proto.suspend_id()
536             << " duration=" << duration.InSeconds() << " sec";
537     FOR_EACH_OBSERVER(
538         PowerManagerClient::Observer, observers_, SuspendDone(duration));
539     base::PowerMonitorDeviceSource::HandleSystemResumed();
540   }
541
542   void IdleActionImminentReceived(dbus::Signal* signal) {
543     dbus::MessageReader reader(signal);
544     power_manager::IdleActionImminent proto;
545     if (!reader.PopArrayOfBytesAsProto(&proto)) {
546       LOG(ERROR) << "Unable to decode protocol buffer from "
547                  << power_manager::kIdleActionImminentSignal << " signal";
548       return;
549     }
550     FOR_EACH_OBSERVER(Observer, observers_,
551         IdleActionImminent(base::TimeDelta::FromInternalValue(
552             proto.time_until_idle_action())));
553   }
554
555   void IdleActionDeferredReceived(dbus::Signal* signal) {
556     FOR_EACH_OBSERVER(Observer, observers_, IdleActionDeferred());
557   }
558
559   void InputEventReceived(dbus::Signal* signal) {
560     dbus::MessageReader reader(signal);
561     power_manager::InputEvent proto;
562     if (!reader.PopArrayOfBytesAsProto(&proto)) {
563       LOG(ERROR) << "Unable to decode protocol buffer from "
564                  << power_manager::kInputEventSignal << " signal";
565       return;
566     }
567
568     base::TimeTicks timestamp =
569         base::TimeTicks::FromInternalValue(proto.timestamp());
570     VLOG(1) << "Got " << power_manager::kInputEventSignal << " signal:"
571             << " type=" << proto.type() << " timestamp=" << proto.timestamp();
572     switch (proto.type()) {
573       case power_manager::InputEvent_Type_POWER_BUTTON_DOWN:
574       case power_manager::InputEvent_Type_POWER_BUTTON_UP: {
575         const bool down =
576             (proto.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN);
577         FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
578                           PowerButtonEventReceived(down, timestamp));
579
580         // Tell powerd that Chrome has handled power button presses.
581         if (down) {
582           dbus::MethodCall method_call(
583               power_manager::kPowerManagerInterface,
584               power_manager::kHandlePowerButtonAcknowledgmentMethod);
585           dbus::MessageWriter writer(&method_call);
586           writer.AppendInt64(proto.timestamp());
587           power_manager_proxy_->CallMethod(
588               &method_call,
589               dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
590               dbus::ObjectProxy::EmptyResponseCallback());
591         }
592         break;
593       }
594       case power_manager::InputEvent_Type_LID_OPEN:
595       case power_manager::InputEvent_Type_LID_CLOSED: {
596         bool open =
597             (proto.type() == power_manager::InputEvent_Type_LID_OPEN);
598         FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
599                           LidEventReceived(open, timestamp));
600         break;
601       }
602     }
603   }
604
605   void RegisterSuspendDelayImpl(
606       const std::string& method_name,
607       const power_manager::RegisterSuspendDelayRequest& protobuf_request,
608       dbus::ObjectProxy::ResponseCallback callback) {
609     dbus::MethodCall method_call(
610         power_manager::kPowerManagerInterface, method_name);
611     dbus::MessageWriter writer(&method_call);
612
613     if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
614       LOG(ERROR) << "Error constructing message for " << method_name;
615       return;
616     }
617
618     power_manager_proxy_->CallMethod(
619         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, callback);
620   }
621
622   // Registers suspend delays with the power manager.  This is usually only
623   // called at startup, but if the power manager restarts, we need to create new
624   // delays.
625   void RegisterSuspendDelays() {
626     // Throw out any old delay that was registered.
627     suspend_delay_id_ = -1;
628     has_suspend_delay_id_ = false;
629     dark_suspend_delay_id_ = -1;
630     has_dark_suspend_delay_id_ = false;
631
632     power_manager::RegisterSuspendDelayRequest protobuf_request;
633     base::TimeDelta timeout =
634         base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs);
635     protobuf_request.set_timeout(timeout.ToInternalValue());
636     protobuf_request.set_description(kSuspendDelayDescription);
637
638     RegisterSuspendDelayImpl(
639         power_manager::kRegisterSuspendDelayMethod,
640         protobuf_request,
641         base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
642                    weak_ptr_factory_.GetWeakPtr(), false,
643                    power_manager::kRegisterSuspendDelayMethod));
644     RegisterSuspendDelayImpl(
645         power_manager::kRegisterDarkSuspendDelayMethod,
646         protobuf_request,
647         base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
648                    weak_ptr_factory_.GetWeakPtr(), true,
649                    power_manager::kRegisterDarkSuspendDelayMethod));
650   }
651
652   // Records the fact that an observer has finished doing asynchronous work
653   // that was blocking a pending suspend attempt and possibly reports
654   // suspend readiness to powerd.  Called by callbacks returned via
655   // GetSuspendReadinessCallback().
656   void HandleObserverSuspendReadiness(int32_t suspend_id, bool in_dark_resume) {
657     DCHECK(OnOriginThread());
658     if (!suspend_is_pending_ || suspend_id != pending_suspend_id_ ||
659         in_dark_resume != suspending_from_dark_resume_)
660       return;
661
662     num_pending_suspend_readiness_callbacks_--;
663     MaybeReportSuspendReadiness();
664   }
665
666   // Reports suspend readiness to powerd if no observers are still holding
667   // suspend readiness callbacks.
668   void MaybeReportSuspendReadiness() {
669     if (!suspend_is_pending_ || num_pending_suspend_readiness_callbacks_ > 0)
670       return;
671
672     std::string method_name;
673     int32_t delay_id = -1;
674     if (suspending_from_dark_resume_) {
675       method_name = power_manager::kHandleDarkSuspendReadinessMethod;
676       delay_id = dark_suspend_delay_id_;
677     } else {
678       method_name = power_manager::kHandleSuspendReadinessMethod;
679       delay_id = suspend_delay_id_;
680     }
681
682     dbus::MethodCall method_call(
683         power_manager::kPowerManagerInterface, method_name);
684     dbus::MessageWriter writer(&method_call);
685
686     VLOG(1) << "Announcing readiness of suspend delay " << delay_id
687             << " for suspend attempt " << pending_suspend_id_;
688     power_manager::SuspendReadinessInfo protobuf_request;
689     protobuf_request.set_delay_id(delay_id);
690     protobuf_request.set_suspend_id(pending_suspend_id_);
691
692     pending_suspend_id_ = -1;
693     suspend_is_pending_ = false;
694
695     if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
696       LOG(ERROR) << "Error constructing message for " << method_name;
697       return;
698     }
699     power_manager_proxy_->CallMethod(
700         &method_call,
701         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
702         dbus::ObjectProxy::EmptyResponseCallback());
703   }
704
705   // Origin thread (i.e. the UI thread in production).
706   base::PlatformThreadId origin_thread_id_;
707
708   dbus::ObjectProxy* power_manager_proxy_;
709   ObserverList<Observer> observers_;
710
711   // The delay_id_ obtained from the RegisterSuspendDelay request.
712   int32_t suspend_delay_id_;
713   bool has_suspend_delay_id_;
714
715   // The delay_id_ obtained from the RegisterDarkSuspendDelay request.
716   int32_t dark_suspend_delay_id_;
717   bool has_dark_suspend_delay_id_;
718
719   // powerd-supplied ID corresponding to an imminent suspend attempt that is
720   // currently being delayed.
721   int32_t pending_suspend_id_;
722   bool suspend_is_pending_;
723
724   // Set to true when the suspend currently being delayed was triggered during a
725   // dark resume.  Since |pending_suspend_id_| and |suspend_is_pending_| are
726   // both shared by normal and dark suspends, |suspending_from_dark_resume_|
727   // helps distinguish the context within which these variables are being used.
728   bool suspending_from_dark_resume_;
729
730   // Number of callbacks that have been returned by
731   // GetSuspendReadinessCallback() during the currently-pending suspend
732   // attempt but have not yet been called.
733   int num_pending_suspend_readiness_callbacks_;
734
735   // Last state passed to SetIsProjecting().
736   bool last_is_projecting_;
737
738   // Note: This should remain the last member so it'll be destroyed and
739   // invalidate its weak pointers before any other members are destroyed.
740   base::WeakPtrFactory<PowerManagerClientImpl> weak_ptr_factory_;
741
742   DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl);
743 };
744
745 // The PowerManagerClient implementation used on Linux desktop,
746 // which does nothing.
747 class PowerManagerClientStubImpl : public PowerManagerClient {
748  public:
749   PowerManagerClientStubImpl()
750       : discharging_(true),
751         battery_percentage_(40),
752         brightness_(50.0),
753         pause_count_(2),
754         cycle_count_(0),
755         num_pending_suspend_readiness_callbacks_(0),
756         weak_ptr_factory_(this) {}
757
758   virtual ~PowerManagerClientStubImpl() {}
759
760   int num_pending_suspend_readiness_callbacks() const {
761     return num_pending_suspend_readiness_callbacks_;
762   }
763
764   // PowerManagerClient overrides:
765   virtual void Init(dbus::Bus* bus) override {
766     ParseCommandLineSwitch();
767     if (power_cycle_delay_ != base::TimeDelta()) {
768       update_timer_.Start(FROM_HERE,
769                           power_cycle_delay_,
770                           this,
771                           &PowerManagerClientStubImpl::UpdateStatus);
772     }
773   }
774
775   virtual void AddObserver(Observer* observer) override {
776     observers_.AddObserver(observer);
777   }
778
779   virtual void RemoveObserver(Observer* observer) override {
780     observers_.RemoveObserver(observer);
781   }
782
783   virtual bool HasObserver(Observer* observer) override {
784     return observers_.HasObserver(observer);
785   }
786
787   virtual void DecreaseScreenBrightness(bool allow_off) override {
788     VLOG(1) << "Requested to descrease screen brightness";
789     SetBrightness(brightness_ - 5.0, true);
790   }
791
792   virtual void IncreaseScreenBrightness() override {
793     VLOG(1) << "Requested to increase screen brightness";
794     SetBrightness(brightness_ + 5.0, true);
795   }
796
797   virtual void SetScreenBrightnessPercent(double percent,
798                                           bool gradual) override {
799     VLOG(1) << "Requested to set screen brightness to " << percent << "% "
800             << (gradual ? "gradually" : "instantaneously");
801     SetBrightness(percent, false);
802   }
803
804   virtual void GetScreenBrightnessPercent(
805       const GetScreenBrightnessPercentCallback& callback) override {
806     callback.Run(brightness_);
807   }
808
809   virtual void DecreaseKeyboardBrightness() override {
810     VLOG(1) << "Requested to descrease keyboard brightness";
811   }
812
813   virtual void IncreaseKeyboardBrightness() override {
814     VLOG(1) << "Requested to increase keyboard brightness";
815   }
816
817   virtual void RequestStatusUpdate() override {
818     base::MessageLoop::current()->PostTask(FROM_HERE,
819         base::Bind(&PowerManagerClientStubImpl::UpdateStatus,
820                    weak_ptr_factory_.GetWeakPtr()));
821   }
822
823   virtual void RequestSuspend() override {}
824   virtual void RequestRestart() override {}
825   virtual void RequestShutdown() override {}
826
827   virtual void NotifyUserActivity(
828       power_manager::UserActivityType type) override {}
829   virtual void NotifyVideoActivity(bool is_fullscreen) override {}
830   virtual void SetPolicy(
831       const power_manager::PowerManagementPolicy& policy) override {}
832   virtual void SetIsProjecting(bool is_projecting) override {}
833   virtual base::Closure GetSuspendReadinessCallback() override {
834     num_pending_suspend_readiness_callbacks_++;
835     return base::Bind(&PowerManagerClientStubImpl::HandleSuspendReadiness,
836                       weak_ptr_factory_.GetWeakPtr());
837   }
838   virtual int GetNumPendingSuspendReadinessCallbacks() override {
839     return num_pending_suspend_readiness_callbacks_;
840   }
841
842  private:
843   void HandleSuspendReadiness() {
844     num_pending_suspend_readiness_callbacks_--;
845   }
846
847   void UpdateStatus() {
848     if (pause_count_ > 0) {
849       pause_count_--;
850       if (pause_count_ == 2)
851         discharging_ = !discharging_;
852     } else {
853       if (discharging_)
854         battery_percentage_ -= (battery_percentage_ <= 10 ? 1 : 10);
855       else
856         battery_percentage_ += (battery_percentage_ >= 10 ? 10 : 1);
857       battery_percentage_ = std::min(std::max(battery_percentage_, 0), 100);
858       // We pause at 0 and 100% so that it's easier to check those conditions.
859       if (battery_percentage_ == 0 || battery_percentage_ == 100) {
860         pause_count_ = 4;
861         if (battery_percentage_ == 100)
862           cycle_count_ = (cycle_count_ + 1) % 3;
863       }
864     }
865
866     const int kSecondsToEmptyFullBattery = 3 * 60 * 60;  // 3 hours.
867     int64 remaining_battery_time =
868         std::max(1, battery_percentage_ * kSecondsToEmptyFullBattery / 100);
869
870     props_.Clear();
871
872     switch (cycle_count_) {
873       case 0:
874         // Say that the system is charging with AC connected and
875         // discharging without any charger connected.
876         props_.set_external_power(discharging_ ?
877             power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED :
878             power_manager::PowerSupplyProperties_ExternalPower_AC);
879         break;
880       case 1:
881         // Say that the system is both charging and discharging on USB
882         // (i.e. a low-power charger).
883         props_.set_external_power(
884             power_manager::PowerSupplyProperties_ExternalPower_USB);
885         break;
886       case 2:
887         // Say that the system is both charging and discharging on AC.
888         props_.set_external_power(
889             power_manager::PowerSupplyProperties_ExternalPower_AC);
890         break;
891       default:
892         NOTREACHED() << "Unhandled cycle " << cycle_count_;
893     }
894
895     if (battery_percentage_ == 100 && !discharging_) {
896       props_.set_battery_state(
897           power_manager::PowerSupplyProperties_BatteryState_FULL);
898     } else if (!discharging_) {
899       props_.set_battery_state(
900           power_manager::PowerSupplyProperties_BatteryState_CHARGING);
901       props_.set_battery_time_to_full_sec(std::max(static_cast<int64>(1),
902           kSecondsToEmptyFullBattery - remaining_battery_time));
903     } else {
904       props_.set_battery_state(
905           power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
906       props_.set_battery_time_to_empty_sec(remaining_battery_time);
907     }
908
909     props_.set_battery_percent(battery_percentage_);
910     props_.set_is_calculating_battery_time(pause_count_ > 1);
911
912     FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(props_));
913   }
914
915   void SetBrightness(double percent, bool user_initiated) {
916     brightness_ = std::min(std::max(0.0, percent), 100.0);
917     int brightness_level = static_cast<int>(brightness_);
918     FOR_EACH_OBSERVER(Observer, observers_,
919                       BrightnessChanged(brightness_level, user_initiated));
920   }
921
922   void ParseCommandLineSwitch() {
923     CommandLine* command_line = CommandLine::ForCurrentProcess();
924     if (!command_line || !command_line->HasSwitch(switches::kPowerStub))
925       return;
926     std::string option_str =
927         command_line->GetSwitchValueASCII(switches::kPowerStub);
928     base::StringPairs string_pairs;
929     base::SplitStringIntoKeyValuePairs(option_str, '=', ',', &string_pairs);
930     for (base::StringPairs::iterator iter = string_pairs.begin();
931          iter != string_pairs.end(); ++iter) {
932       ParseOption((*iter).first, (*iter).second);
933     }
934   }
935
936   void ParseOption(const std::string& arg0, const std::string& arg1) {
937     if (arg0 == "cycle" || arg0 == "interactive") {
938       int seconds = 1;
939       if (!arg1.empty())
940         base::StringToInt(arg1, &seconds);
941       power_cycle_delay_ = base::TimeDelta::FromSeconds(seconds);
942     }
943   }
944
945   base::TimeDelta power_cycle_delay_;  // Time over which to cycle power state
946   bool discharging_;
947   int battery_percentage_;
948   double brightness_;
949   int pause_count_;
950   int cycle_count_;
951   ObserverList<Observer> observers_;
952   base::RepeatingTimer<PowerManagerClientStubImpl> update_timer_;
953   power_manager::PowerSupplyProperties props_;
954
955   // Number of callbacks returned by GetSuspendReadinessCallback() but not yet
956   // invoked.
957   int num_pending_suspend_readiness_callbacks_;
958
959   // Note: This should remain the last member so it'll be destroyed and
960   // invalidate its weak pointers before any other members are destroyed.
961   base::WeakPtrFactory<PowerManagerClientStubImpl> weak_ptr_factory_;
962 };
963
964 PowerManagerClient::PowerManagerClient() {
965 }
966
967 PowerManagerClient::~PowerManagerClient() {
968 }
969
970 // static
971 PowerManagerClient* PowerManagerClient::Create(
972     DBusClientImplementationType type) {
973   if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
974     return new PowerManagerClientImpl();
975   DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
976   return new PowerManagerClientStubImpl();
977 }
978
979 }  // namespace chromeos