15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/power_manager_client.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/strings/string_split.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chromeos/chromeos_switches.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/input_event.pb.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/policy.pb.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/suspend.pb.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum amount of time that the power manager will wait for Chrome to
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// say that it's ready for the system to be suspended, in milliseconds.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuspendDelayTimeoutMs = 5000;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Human-readable description of Chrome's suspend delay.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kSuspendDelayDescription[] = "chrome";
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The PowerManagerClient implementation used in production.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerManagerClientImpl : public PowerManagerClient {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  PowerManagerClientImpl()
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : origin_thread_id_(base::PlatformThread::CurrentId()),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager_proxy_(NULL),
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        suspend_delay_id_(-1),
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        has_suspend_delay_id_(false),
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        dark_suspend_delay_id_(-1),
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        has_dark_suspend_delay_id_(false),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_suspend_id_(-1),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        suspend_is_pending_(false),
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        suspending_from_dark_resume_(false),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        num_pending_suspend_readiness_callbacks_(0),
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        last_is_projecting_(false),
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        weak_ptr_factory_(this) {}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PowerManagerClientImpl() {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Here we should unregister suspend notifications from powerd,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // however:
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - The lifetime of the PowerManagerClientImpl can extend past that of
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //   the objectproxy,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - power_manager can already detect that the client is gone and
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //   unregister our suspend delay.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PowerManagerClient overrides:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(observer);  // http://crbug.com/119976
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.AddObserver(observer);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.RemoveObserver(observer);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observers_.HasObserver(observer);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        power_manager::kDecreaseScreenBrightnessMethod);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendBool(allow_off);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseScreenBrightness() OVERRIDE {
97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SimpleMethodCallToPowerManager(
98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        power_manager::kIncreaseScreenBrightnessMethod);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseKeyboardBrightness() OVERRIDE {
102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SimpleMethodCallToPowerManager(
103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        power_manager::kDecreaseKeyboardBrightnessMethod);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseKeyboardBrightness() OVERRIDE {
107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SimpleMethodCallToPowerManager(
108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        power_manager::kIncreaseKeyboardBrightnessMethod);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetScreenBrightnessPercent(double percent,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          bool gradual) OVERRIDE {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        power_manager::kSetScreenBrightnessPercentMethod);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendDouble(percent);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendInt32(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gradual ?
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessTransitionGradual :
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessTransitionInstant);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetScreenBrightnessPercent(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback) OVERRIDE {
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    dbus::MethodCall method_call(
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        power_manager::kPowerManagerInterface,
132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        power_manager::kGetScreenBrightnessPercentMethod);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), callback));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void RequestStatusUpdate() OVERRIDE {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kGetPowerSupplyPropertiesMethod);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void RequestSuspend() OVERRIDE {
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod);
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestRestart() OVERRIDE {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod);
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestShutdown() OVERRIDE {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void NotifyUserActivity(
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      power_manager::UserActivityType type) OVERRIDE {
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    dbus::MethodCall method_call(
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        power_manager::kPowerManagerInterface,
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        power_manager::kHandleUserActivityMethod);
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    dbus::MessageWriter writer(&method_call);
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    writer.AppendInt32(type);
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    power_manager_proxy_->CallMethod(
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        &method_call,
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        dbus::ObjectProxy::EmptyResponseCallback());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void NotifyVideoActivity(bool is_fullscreen) OVERRIDE {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kHandleVideoActivityMethod);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writer.AppendBool(is_fullscreen);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetPolicy(
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const power_manager::PowerManagementPolicy& policy) OVERRIDE {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kSetPolicyMethod);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(policy)) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling " << power_manager::kSetPolicyMethod;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetIsProjecting(bool is_projecting) OVERRIDE {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kSetIsProjectingMethod);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendBool(is_projecting);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    last_is_projecting_ = is_projecting;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::Closure GetSuspendReadinessCallback() OVERRIDE {
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(OnOriginThread());
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(suspend_is_pending_);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_++;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness,
22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                      weak_ptr_factory_.GetWeakPtr(), pending_suspend_id_,
22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                      suspending_from_dark_resume_);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual int GetNumPendingSuspendReadinessCallbacks() OVERRIDE {
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return num_pending_suspend_readiness_callbacks_;
2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) protected:
233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual void Init(dbus::Bus* bus) OVERRIDE {
234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_ = bus->GetObjectProxy(
235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerServiceName,
236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        dbus::ObjectPath(power_manager::kPowerManagerServicePath));
237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->SetNameOwnerChangedCallback(
239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived,
240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor the D-Bus signal for brightness changes. Only the power
243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // manager knows the actual brightness level. We don't cache the
244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // brightness level in Chrome as it'll make things less reliable.
245424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
246424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
247424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kBrightnessChangedSignal,
248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived,
249424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
251424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
252424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
253424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
254424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
255424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPeripheralBatteryStatusSignal,
256424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived,
257424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
258424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerSupplyPollSignal,
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived,
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kInputEventSignal,
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::InputEventReceived,
273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        power_manager::kSuspendImminentSignal,
2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        base::Bind(
28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            &PowerManagerClientImpl::HandleSuspendImminent,
28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            weak_ptr_factory_.GetWeakPtr(), false),
283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        power_manager::kSuspendDoneSignal,
2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        base::Bind(&PowerManagerClientImpl::SuspendDoneReceived,
2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                   weak_ptr_factory_.GetWeakPtr()),
291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
292424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
294424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
295424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        power_manager::kDarkSuspendImminentSignal,
29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        base::Bind(
29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            &PowerManagerClientImpl::HandleSuspendImminent,
29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            weak_ptr_factory_.GetWeakPtr(), true),
30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        power_manager::kPowerManagerInterface,
305424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kIdleActionImminentSignal,
306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(
307424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            &PowerManagerClientImpl::IdleActionImminentReceived,
308424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kPowerManagerInterface,
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        power_manager::kIdleActionDeferredSignal,
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            &PowerManagerClientImpl::IdleActionDeferredReceived,
317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
318424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
320424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
32103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    RegisterSuspendDelays();
322424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if the current thread is the origin thread.
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool OnOriginThread() {
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::PlatformThread::CurrentId() == origin_thread_id_;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a dbus signal is initially connected.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SignalConnected(const std::string& interface_name,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& signal_name,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       bool success) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(WARNING, !success) << "Failed to connect to signal "
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              << signal_name << ".";
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Makes a method call to power manager with no arguments and no response.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SimpleMethodCallToPowerManager(const std::string& method_name) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 method_name);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void NameOwnerChangedReceived(const std::string& old_owner,
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                const std::string& new_owner) {
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VLOG(1) << "Power manager restarted (old owner was "
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            << (old_owner.empty() ? "[none]" : old_owner.c_str())
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            << ", new owner is "
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            << (new_owner.empty() ? "[none]" : new_owner.c_str()) << ")";
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    suspend_is_pending_ = false;
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    pending_suspend_id_ = -1;
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    suspending_from_dark_resume_ = false;
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!new_owner.empty()) {
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VLOG(1) << "Sending initial state to power manager";
35903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      RegisterSuspendDelays();
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetIsProjecting(last_is_projecting_);
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FOR_EACH_OBSERVER(Observer, observers_, PowerManagerRestarted());
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BrightnessChangedReceived(dbus::Signal* signal) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(signal);
36703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    int32_t brightness_level = 0;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool user_initiated = 0;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(reader.PopInt32(&brightness_level) &&
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reader.PopBool(&user_initiated))) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Brightness changed signal had incorrect parameters: "
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << signal->ToString();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Brightness changed to " << brightness_level
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ": user initiated " << user_initiated;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      BrightnessChanged(brightness_level, user_initiated));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void PeripheralBatteryStatusReceived(dbus::Signal* signal) {
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(signal);
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    power_manager::PeripheralBatteryStatus protobuf_status;
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf_status)) {
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << power_manager::kPeripheralBatteryStatusSignal << " signal";
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string path = protobuf_status.path();
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string name = protobuf_status.name();
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int level = protobuf_status.has_level() ? protobuf_status.level() : -1;
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "Device battery status received " << level
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            << " for " << name << " at " << path;
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      PeripheralBatteryStatusReceived(path, name, level));
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void PowerSupplyPollReceived(dbus::Signal* signal) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received power supply poll signal.";
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    dbus::MessageReader reader(signal);
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    power_manager::PowerSupplyProperties protobuf;
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (reader.PopArrayOfBytesAsProto(&protobuf)) {
406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(protobuf));
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "Unable to decode "
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 << power_manager::kPowerSupplyPollSignal << "signal";
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Error calling "
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << power_manager::kGetPowerSupplyPropertiesMethod;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    power_manager::PowerSupplyProperties protobuf;
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (reader.PopArrayOfBytesAsProto(&protobuf)) {
423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(protobuf));
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "Unable to decode "
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << power_manager::kGetPowerSupplyPropertiesMethod
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 << " response";
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGetScreenBrightnessPercent(
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback,
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dbus::Response* response) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling "
436effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 << power_manager::kGetScreenBrightnessPercentMethod;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double percent = 0.0;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopDouble(&percent))
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Error reading response from powerd: "
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << response->ToString();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(percent);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void HandleRegisterSuspendDelayReply(bool dark_suspend,
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       const std::string& method_name,
44903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                       dbus::Response* response) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      LOG(ERROR) << "Error calling " << method_name;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::RegisterSuspendDelayReply protobuf;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      LOG(ERROR) << "Unable to parse reply from " << method_name;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (dark_suspend) {
46303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      dark_suspend_delay_id_ = protobuf.delay_id();
46403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      has_dark_suspend_delay_id_ = true;
46503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      VLOG(1) << "Registered dark suspend delay " << dark_suspend_delay_id_;
46603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
46703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      suspend_delay_id_ = protobuf.delay_id();
46803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      has_suspend_delay_id_ = true;
46903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      VLOG(1) << "Registered suspend delay " << suspend_delay_id_;
47003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void HandleSuspendImminent(bool in_dark_resume, dbus::Signal* signal) {
47403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::string signal_name = signal->GetMember();
47503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if ((in_dark_resume && !has_dark_suspend_delay_id_) ||
47603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        (!in_dark_resume && !has_suspend_delay_id_)) {
47703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      LOG(ERROR) << "Received unrequested " << signal_name << " signal";
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
4820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    power_manager::SuspendImminent proto;
4830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!reader.PopArrayOfBytesAsProto(&proto)) {
48403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from " << signal_name
48503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 << " signal";
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
48903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    VLOG(1) << "Got " << signal_name << " signal announcing suspend attempt "
49003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            << proto.suspend_id();
49103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
49203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // If a previous suspend is pending from the same state we are currently in
49303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // (fully powered on or in dark resume), then something's gone a little
49403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // wonky.
49503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (suspend_is_pending_ &&
49603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        suspending_from_dark_resume_ == in_dark_resume) {
49703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      LOG(WARNING) << "Got " << signal_name << " signal about pending suspend "
49803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   << "attempt " << proto.suspend_id() << " while still "
49903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   << "waiting on attempt " << pending_suspend_id_;
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    pending_suspend_id_ = proto.suspend_id();
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_is_pending_ = true;
50403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    suspending_from_dark_resume_ = in_dark_resume;
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_ = 0;
50603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (suspending_from_dark_resume_)
50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      FOR_EACH_OBSERVER(Observer, observers_, DarkSuspendImminent());
50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    else
50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      FOR_EACH_OBSERVER(Observer, observers_, SuspendImminent());
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MaybeReportSuspendReadiness();
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void SuspendDoneReceived(dbus::Signal* signal) {
5140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    dbus::MessageReader reader(signal);
5150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    power_manager::SuspendDone proto;
5160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!reader.PopArrayOfBytesAsProto(&proto)) {
5170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      LOG(ERROR) << "Unable to decode protocol buffer from "
5180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                 << power_manager::kSuspendDoneSignal << " signal";
5190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return;
5200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
5210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const base::TimeDelta duration =
5230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        base::TimeDelta::FromInternalValue(proto.suspend_duration());
5240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    VLOG(1) << "Got " << power_manager::kSuspendDoneSignal << " signal:"
5250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            << " suspend_id=" << proto.suspend_id()
5260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            << " duration=" << duration.InSeconds() << " sec";
5270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    FOR_EACH_OBSERVER(
5280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        PowerManagerClient::Observer, observers_, SuspendDone(duration));
5290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
5300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void IdleActionImminentReceived(dbus::Signal* signal) {
5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    dbus::MessageReader reader(signal);
5330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    power_manager::IdleActionImminent proto;
5340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!reader.PopArrayOfBytesAsProto(&proto)) {
5350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      LOG(ERROR) << "Unable to decode protocol buffer from "
5360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                 << power_manager::kIdleActionImminentSignal << " signal";
5370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return;
5380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
5390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    FOR_EACH_OBSERVER(Observer, observers_,
5400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        IdleActionImminent(base::TimeDelta::FromInternalValue(
5410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            proto.time_until_idle_action())));
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void IdleActionDeferredReceived(dbus::Signal* signal) {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleActionDeferred());
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InputEventReceived(dbus::Signal* signal) {
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::InputEvent proto;
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&proto)) {
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kInputEventSignal << " signal";
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks timestamp =
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeTicks::FromInternalValue(proto.timestamp());
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Got " << power_manager::kInputEventSignal << " signal:"
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " type=" << proto.type() << " timestamp=" << proto.timestamp();
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (proto.type()) {
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_POWER_BUTTON_DOWN:
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_POWER_BUTTON_UP: {
564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        const bool down =
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (proto.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN);
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          PowerButtonEventReceived(down, timestamp));
568f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
569f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // Tell powerd that Chrome has handled power button presses.
570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (down) {
571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          dbus::MethodCall method_call(
572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              power_manager::kPowerManagerInterface,
573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              power_manager::kHandlePowerButtonAcknowledgmentMethod);
574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          dbus::MessageWriter writer(&method_call);
575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          writer.AppendInt64(proto.timestamp());
576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          power_manager_proxy_->CallMethod(
577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              &method_call,
578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              dbus::ObjectProxy::EmptyResponseCallback());
580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_LID_OPEN:
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_LID_CLOSED: {
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool open =
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (proto.type() == power_manager::InputEvent_Type_LID_OPEN);
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          LidEventReceived(open, timestamp));
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
59403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void RegisterSuspendDelayImpl(
59503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const std::string& method_name,
59603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const power_manager::RegisterSuspendDelayRequest& protobuf_request,
59703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      dbus::ObjectProxy::ResponseCallback callback) {
59803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    dbus::MethodCall method_call(
59903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        power_manager::kPowerManagerInterface, method_name);
60003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
60103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
60203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
60303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      LOG(ERROR) << "Error constructing message for " << method_name;
60403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
60503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
60603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
60703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    power_manager_proxy_->CallMethod(
60803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, callback);
60903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
61003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
61103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Registers suspend delays with the power manager.  This is usually only
61203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // called at startup, but if the power manager restarts, we need to create new
61303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // delays.
61403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void RegisterSuspendDelays() {
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Throw out any old delay that was registered.
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_delay_id_ = -1;
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    has_suspend_delay_id_ = false;
61803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    dark_suspend_delay_id_ = -1;
61903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    has_dark_suspend_delay_id_ = false;
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::RegisterSuspendDelayRequest protobuf_request;
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta timeout =
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs);
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_timeout(timeout.ToInternalValue());
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_description(kSuspendDelayDescription);
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    RegisterSuspendDelayImpl(
62803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        power_manager::kRegisterSuspendDelayMethod,
62903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        protobuf_request,
6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   weak_ptr_factory_.GetWeakPtr(), false,
6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   power_manager::kRegisterSuspendDelayMethod));
63303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    RegisterSuspendDelayImpl(
63403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        power_manager::kRegisterDarkSuspendDelayMethod,
63503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        protobuf_request,
6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   weak_ptr_factory_.GetWeakPtr(), true,
6381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   power_manager::kRegisterDarkSuspendDelayMethod));
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Records the fact that an observer has finished doing asynchronous work
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // that was blocking a pending suspend attempt and possibly reports
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend readiness to powerd.  Called by callbacks returned via
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSuspendReadinessCallback().
64503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void HandleObserverSuspendReadiness(int32_t suspend_id, bool in_dark_resume) {
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(OnOriginThread());
64703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!suspend_is_pending_ || suspend_id != pending_suspend_id_ ||
64803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        in_dark_resume != suspending_from_dark_resume_)
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_--;
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MaybeReportSuspendReadiness();
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Reports suspend readiness to powerd if no observers are still holding
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend readiness callbacks.
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MaybeReportSuspendReadiness() {
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!suspend_is_pending_ || num_pending_suspend_readiness_callbacks_ > 0)
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
66103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::string method_name;
66203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    int32_t delay_id = -1;
66303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (suspending_from_dark_resume_) {
66403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      method_name = power_manager::kHandleDarkSuspendReadinessMethod;
66503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      delay_id = dark_suspend_delay_id_;
66603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
66703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      method_name = power_manager::kHandleSuspendReadinessMethod;
66803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      delay_id = suspend_delay_id_;
66903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
67003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
67203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        power_manager::kPowerManagerInterface, method_name);
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
67503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    VLOG(1) << "Announcing readiness of suspend delay " << delay_id
6760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            << " for suspend attempt " << pending_suspend_id_;
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::SuspendReadinessInfo protobuf_request;
67803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    protobuf_request.set_delay_id(delay_id);
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_suspend_id(pending_suspend_id_);
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_suspend_id_ = -1;
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_is_pending_ = false;
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
68503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      LOG(ERROR) << "Error constructing message for " << method_name;
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->CallMethod(
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &method_call,
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Origin thread (i.e. the UI thread in production).
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::PlatformThreadId origin_thread_id_;
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectProxy* power_manager_proxy_;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The delay_id_ obtained from the RegisterSuspendDelay request.
70103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int32_t suspend_delay_id_;
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_suspend_delay_id_;
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
70403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // The delay_id_ obtained from the RegisterDarkSuspendDelay request.
70503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int32_t dark_suspend_delay_id_;
70603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool has_dark_suspend_delay_id_;
70703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // powerd-supplied ID corresponding to an imminent suspend attempt that is
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // currently being delayed.
71003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int32_t pending_suspend_id_;
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool suspend_is_pending_;
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Set to true when the suspend currently being delayed was triggered during a
71403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // dark resume.  Since |pending_suspend_id_| and |suspend_is_pending_| are
71503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // both shared by normal and dark suspends, |suspending_from_dark_resume_|
71603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // helps distinguish the context within which these variables are being used.
71703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool suspending_from_dark_resume_;
71803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Number of callbacks that have been returned by
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSuspendReadinessCallback() during the currently-pending suspend
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // attempt but have not yet been called.
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_pending_suspend_readiness_callbacks_;
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Last state passed to SetIsProjecting().
72590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool last_is_projecting_;
72690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<PowerManagerClientImpl> weak_ptr_factory_;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The PowerManagerClient implementation used on Linux desktop,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which does nothing.
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerManagerClientStubImpl : public PowerManagerClient {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PowerManagerClientStubImpl()
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : discharging_(true),
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        battery_percentage_(40),
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        brightness_(50.0),
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        pause_count_(2),
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cycle_count_(0),
7441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        num_pending_suspend_readiness_callbacks_(0),
745424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        weak_ptr_factory_(this) {}
746424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
747424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual ~PowerManagerClientStubImpl() {}
748424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
7491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int num_pending_suspend_readiness_callbacks() const {
7501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return num_pending_suspend_readiness_callbacks_;
7511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
7521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // PowerManagerClient overrides:
754424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual void Init(dbus::Bus* bus) OVERRIDE {
75523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ParseCommandLineSwitch();
75623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (power_cycle_delay_ != base::TimeDelta()) {
7577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      update_timer_.Start(FROM_HERE,
75823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          power_cycle_delay_,
75923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          this,
76023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          &PowerManagerClientStubImpl::UpdateStatus);
7617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.AddObserver(observer);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.RemoveObserver(observer);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observers_.HasObserver(observer);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to descrease screen brightness";
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(brightness_ - 5.0, true);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseScreenBrightness() OVERRIDE {
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to increase screen brightness";
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(brightness_ + 5.0, true);
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetScreenBrightnessPercent(double percent,
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          bool gradual) OVERRIDE {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to set screen brightness to " << percent << "% "
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << (gradual ? "gradually" : "instantaneously");
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(percent, false);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetScreenBrightnessPercent(
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback) OVERRIDE {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(brightness_);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseKeyboardBrightness() OVERRIDE {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to descrease keyboard brightness";
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseKeyboardBrightness() OVERRIDE {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to increase keyboard brightness";
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
806868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void RequestStatusUpdate() OVERRIDE {
807868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE,
808868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&PowerManagerClientStubImpl::UpdateStatus,
809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void RequestSuspend() OVERRIDE {}
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestRestart() OVERRIDE {}
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestShutdown() OVERRIDE {}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void NotifyUserActivity(
8177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      power_manager::UserActivityType type) OVERRIDE {}
818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void NotifyVideoActivity(bool is_fullscreen) OVERRIDE {}
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetPolicy(
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const power_manager::PowerManagementPolicy& policy) OVERRIDE {}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetIsProjecting(bool is_projecting) OVERRIDE {}
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::Closure GetSuspendReadinessCallback() OVERRIDE {
8231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    num_pending_suspend_readiness_callbacks_++;
8241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return base::Bind(&PowerManagerClientStubImpl::HandleSuspendReadiness,
8251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                      weak_ptr_factory_.GetWeakPtr());
8261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
8271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual int GetNumPendingSuspendReadinessCallbacks() OVERRIDE {
8281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return num_pending_suspend_readiness_callbacks_;
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void HandleSuspendReadiness() {
8331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    num_pending_suspend_readiness_callbacks_--;
8341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
8351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void UpdateStatus() {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pause_count_ > 0) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pause_count_--;
839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (pause_count_ == 2)
840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        discharging_ = !discharging_;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (discharging_)
843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        battery_percentage_ -= (battery_percentage_ <= 10 ? 1 : 10);
844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      else
845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        battery_percentage_ += (battery_percentage_ >= 10 ? 10 : 1);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      battery_percentage_ = std::min(std::max(battery_percentage_, 0), 100);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We pause at 0 and 100% so that it's easier to check those conditions.
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (battery_percentage_ == 0 || battery_percentage_ == 100) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pause_count_ = 4;
850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (battery_percentage_ == 100)
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          cycle_count_ = (cycle_count_ + 1) % 3;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const int kSecondsToEmptyFullBattery = 3 * 60 * 60;  // 3 hours.
856a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int64 remaining_battery_time =
857a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        std::max(1, battery_percentage_ * kSecondsToEmptyFullBattery / 100);
858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.Clear();
860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    switch (cycle_count_) {
862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 0:
863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is charging with AC connected and
864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // discharging without any charger connected.
865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(discharging_ ?
866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED :
867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_AC);
868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 1:
870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is both charging and discharging on USB
871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // (i.e. a low-power charger).
872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(
873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_USB);
874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 2:
876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is both charging and discharging on AC.
877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(
878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_AC);
879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      default:
881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NOTREACHED() << "Unhandled cycle " << cycle_count_;
882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (battery_percentage_ == 100 && !discharging_) {
885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_FULL);
887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else if (!discharging_) {
888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_CHARGING);
890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_time_to_full_sec(std::max(static_cast<int64>(1),
891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSecondsToEmptyFullBattery - remaining_battery_time));
892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_time_to_empty_sec(remaining_battery_time);
896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.set_battery_percent(battery_percentage_);
899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.set_is_calculating_battery_time(pause_count_ > 1);
900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(props_));
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBrightness(double percent, bool user_initiated) {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    brightness_ = std::min(std::max(0.0, percent), 100.0);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int brightness_level = static_cast<int>(brightness_);
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      BrightnessChanged(brightness_level, user_initiated));
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void ParseCommandLineSwitch() {
91223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    CommandLine* command_line = CommandLine::ForCurrentProcess();
91323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (!command_line || !command_line->HasSwitch(switches::kPowerStub))
91423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return;
91523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    std::string option_str =
91623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        command_line->GetSwitchValueASCII(switches::kPowerStub);
91723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::StringPairs string_pairs;
91823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::SplitStringIntoKeyValuePairs(option_str, '=', ',', &string_pairs);
91923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    for (base::StringPairs::iterator iter = string_pairs.begin();
92023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         iter != string_pairs.end(); ++iter) {
92123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      ParseOption((*iter).first, (*iter).second);
92223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
92323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
92423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
92523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void ParseOption(const std::string& arg0, const std::string& arg1) {
92623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (arg0 == "cycle" || arg0 == "interactive") {
92723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      int seconds = 1;
92823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (!arg1.empty())
92923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        base::StringToInt(arg1, &seconds);
93023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      power_cycle_delay_ = base::TimeDelta::FromSeconds(seconds);
93123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
93223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
93323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
93423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::TimeDelta power_cycle_delay_;  // Time over which to cycle power state
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool discharging_;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int battery_percentage_;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double brightness_;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pause_count_;
939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int cycle_count_;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RepeatingTimer<PowerManagerClientStubImpl> update_timer_;
942eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  power_manager::PowerSupplyProperties props_;
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Number of callbacks returned by GetSuspendReadinessCallback() but not yet
9451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // invoked.
9461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int num_pending_suspend_readiness_callbacks_;
9471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::WeakPtrFactory<PowerManagerClientStubImpl> weak_ptr_factory_;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient::PowerManagerClient() {
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient::~PowerManagerClient() {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient* PowerManagerClient::Create(
961424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DBusClientImplementationType type) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
963424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return new PowerManagerClientImpl();
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PowerManagerClientStubImpl();
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
969