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"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chromeos/chromeos_switches.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/input_event.pb.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/policy.pb.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/suspend.pb.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum amount of time that the power manager will wait for Chrome to
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// say that it's ready for the system to be suspended, in milliseconds.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuspendDelayTimeoutMs = 5000;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Human-readable description of Chrome's suspend delay.
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kSuspendDelayDescription[] = "chrome";
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The PowerManagerClient implementation used in production.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerManagerClientImpl : public PowerManagerClient {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit PowerManagerClientImpl(dbus::Bus* bus)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : origin_thread_id_(base::PlatformThread::CurrentId()),
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager_proxy_(NULL),
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        suspend_delay_id_(-1),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        has_suspend_delay_id_(false),
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_suspend_id_(-1),
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        suspend_is_pending_(false),
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        num_pending_suspend_readiness_callbacks_(0),
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        last_is_projecting_(false),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        weak_ptr_factory_(this) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_ = bus->GetObjectProxy(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerServiceName,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectPath(power_manager::kPowerManagerServicePath));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->SetNameOwnerChangedCallback(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Monitor the D-Bus signal for brightness changes. Only the power
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // manager knows the actual brightness level. We don't cache the
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // brightness level in Chrome as it'll make things less reliable.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessChangedSignal,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        power_manager::kPeripheralBatteryStatusSignal,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        power_manager::kPowerSupplyPollSignal,
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        power_manager::kIdleNotifySignal,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::IdleNotifySignalReceived,
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kInputEventSignal,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::InputEventReceived,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kSuspendStateChangedSignal,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SuspendStateChangedReceived,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kSuspendImminentSignal,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::SuspendImminentReceived,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kIdleActionImminentSignal,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::IdleActionImminentReceived,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kIdleActionDeferredSignal,
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::IdleActionDeferredReceived,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RegisterSuspendDelay();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PowerManagerClientImpl() {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Here we should unregister suspend notifications from powerd,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // however:
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - The lifetime of the PowerManagerClientImpl can extend past that of
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //   the objectproxy,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - power_manager can already detect that the client is gone and
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //   unregister our suspend delay.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PowerManagerClient overrides:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(observer);  // http://crbug.com/119976
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.AddObserver(observer);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.RemoveObserver(observer);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observers_.HasObserver(observer);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kDecreaseScreenBrightness);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendBool(allow_off);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseScreenBrightness() OVERRIDE {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kIncreaseScreenBrightness);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseKeyboardBrightness() OVERRIDE {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kDecreaseKeyboardBrightness);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseKeyboardBrightness() OVERRIDE {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kIncreaseKeyboardBrightness);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetScreenBrightnessPercent(double percent,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          bool gradual) OVERRIDE {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kSetScreenBrightnessPercent);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendDouble(percent);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendInt32(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gradual ?
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessTransitionGradual :
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessTransitionInstant);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetScreenBrightnessPercent(
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback) OVERRIDE {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 power_manager::kGetScreenBrightnessPercent);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), callback));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void RequestStatusUpdate() OVERRIDE {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kGetPowerSupplyPropertiesMethod);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestRestart() OVERRIDE {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestShutdown() OVERRIDE {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestIdleNotification(int64 threshold) OVERRIDE {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 power_manager::kRequestIdleNotification);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendInt64(threshold);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void NotifyUserActivity(
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      power_manager::UserActivityType type) OVERRIDE {
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    dbus::MethodCall method_call(
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        power_manager::kPowerManagerInterface,
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        power_manager::kHandleUserActivityMethod);
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    dbus::MessageWriter writer(&method_call);
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    writer.AppendInt32(type);
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    power_manager_proxy_->CallMethod(
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        &method_call,
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        dbus::ObjectProxy::EmptyResponseCallback());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void NotifyVideoActivity(bool is_fullscreen) OVERRIDE {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kHandleVideoActivityMethod);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writer.AppendBool(is_fullscreen);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetPolicy(
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const power_manager::PowerManagementPolicy& policy) OVERRIDE {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kSetPolicyMethod);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(policy)) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling " << power_manager::kSetPolicyMethod;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetIsProjecting(bool is_projecting) OVERRIDE {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kSetIsProjectingMethod);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendBool(is_projecting);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    last_is_projecting_ = is_projecting;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::Closure GetSuspendReadinessCallback() OVERRIDE {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(OnOriginThread());
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(suspend_is_pending_);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_++;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness,
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      weak_ptr_factory_.GetWeakPtr(), pending_suspend_id_);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if the current thread is the origin thread.
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool OnOriginThread() {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::PlatformThread::CurrentId() == origin_thread_id_;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a dbus signal is initially connected.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SignalConnected(const std::string& interface_name,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& signal_name,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       bool success) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(WARNING, !success) << "Failed to connect to signal "
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              << signal_name << ".";
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a method call to power manager with no arguments and no response.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SimpleMethodCallToPowerManager(const std::string& method_name) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 method_name);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NameOwnerChangedReceived(dbus::Signal* signal) {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Power manager restarted";
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RegisterSuspendDelay();
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetIsProjecting(last_is_projecting_);
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, PowerManagerRestarted());
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BrightnessChangedReceived(dbus::Signal* signal) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(signal);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 brightness_level = 0;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool user_initiated = 0;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(reader.PopInt32(&brightness_level) &&
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reader.PopBool(&user_initiated))) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Brightness changed signal had incorrect parameters: "
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << signal->ToString();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Brightness changed to " << brightness_level
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ": user initiated " << user_initiated;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      BrightnessChanged(brightness_level, user_initiated));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void PeripheralBatteryStatusReceived(dbus::Signal* signal) {
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(signal);
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    power_manager::PeripheralBatteryStatus protobuf_status;
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf_status)) {
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << power_manager::kPeripheralBatteryStatusSignal << " signal";
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string path = protobuf_status.path();
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string name = protobuf_status.name();
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int level = protobuf_status.has_level() ? protobuf_status.level() : -1;
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "Device battery status received " << level
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            << " for " << name << " at " << path;
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      PeripheralBatteryStatusReceived(path, name, level));
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void PowerSupplyPollReceived(dbus::Signal* signal) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received power supply poll signal.";
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    dbus::MessageReader reader(signal);
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    power_manager::PowerSupplyProperties protobuf;
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (reader.PopArrayOfBytesAsProto(&protobuf)) {
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(protobuf));
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "Unable to decode "
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 << power_manager::kPowerSupplyPollSignal << "signal";
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Error calling "
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << power_manager::kGetPowerSupplyPropertiesMethod;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    power_manager::PowerSupplyProperties protobuf;
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (reader.PopArrayOfBytesAsProto(&protobuf)) {
403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(protobuf));
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "Unable to decode "
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << power_manager::kGetPowerSupplyPropertiesMethod
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 << " response";
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGetScreenBrightnessPercent(
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback,
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dbus::Response* response) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling "
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kGetScreenBrightnessPercent;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double percent = 0.0;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopDouble(&percent))
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Error reading response from powerd: "
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << response->ToString();
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(percent);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnRegisterSuspendDelayReply(dbus::Response* response) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling "
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kRegisterSuspendDelayMethod;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::RegisterSuspendDelayReply protobuf;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to parse reply from "
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kRegisterSuspendDelayMethod;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_delay_id_ = protobuf.delay_id();
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    has_suspend_delay_id_ = true;
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Registered suspend delay " << suspend_delay_id_;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void IdleNotifySignalReceived(dbus::Signal* signal) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(signal);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 threshold = 0;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reader.PopInt64(&threshold)) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Idle Notify signal had incorrect parameters: "
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << signal->ToString();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GT(threshold, 0);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Idle Notify: " << threshold;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleNotify(threshold));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SuspendImminentReceived(dbus::Signal* signal) {
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!has_suspend_delay_id_) {
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Received unrequested "
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kSuspendImminentSignal << " signal";
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::SuspendImminent protobuf_imminent;
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf_imminent)) {
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kSuspendImminentSignal << " signal";
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (suspend_is_pending_) {
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Got " << power_manager::kSuspendImminentSignal
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " signal about pending suspend attempt "
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << protobuf_imminent.suspend_id() << " while still waiting "
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << "on attempt " << pending_suspend_id_;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_suspend_id_ = protobuf_imminent.suspend_id();
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_is_pending_ = true;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_ = 0;
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, SuspendImminent());
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MaybeReportSuspendReadiness();
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void IdleActionImminentReceived(dbus::Signal* signal) {
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleActionImminent());
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void IdleActionDeferredReceived(dbus::Signal* signal) {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleActionDeferred());
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InputEventReceived(dbus::Signal* signal) {
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::InputEvent proto;
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&proto)) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kInputEventSignal << " signal";
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks timestamp =
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeTicks::FromInternalValue(proto.timestamp());
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Got " << power_manager::kInputEventSignal << " signal:"
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " type=" << proto.type() << " timestamp=" << proto.timestamp();
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (proto.type()) {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_POWER_BUTTON_DOWN:
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_POWER_BUTTON_UP: {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool down =
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (proto.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN);
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          PowerButtonEventReceived(down, timestamp));
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_LID_OPEN:
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_LID_CLOSED: {
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool open =
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (proto.type() == power_manager::InputEvent_Type_LID_OPEN);
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          LidEventReceived(open, timestamp));
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SuspendStateChangedReceived(dbus::Signal* signal) {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::SuspendState proto;
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&proto)) {
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kSuspendStateChangedSignal << " signal";
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Got " << power_manager::kSuspendStateChangedSignal << " signal:"
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " type=" << proto.type() << " wall_time=" << proto.wall_time();
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time wall_time =
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Time::FromInternalValue(proto.wall_time());
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (proto.type()) {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::SuspendState_Type_SUSPEND_TO_MEMORY:
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_suspend_wall_time_ = wall_time;
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::SuspendState_Type_RESUME:
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            PowerManagerClient::Observer, observers_,
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            SystemResumed(wall_time - last_suspend_wall_time_));
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Registers a suspend delay with the power manager.  This is usually
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only called at startup, but if the power manager restarts, we need to
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // create a new delay.
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RegisterSuspendDelay() {
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Throw out any old delay that was registered.
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_delay_id_ = -1;
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    has_suspend_delay_id_ = false;
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kRegisterSuspendDelayMethod);
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::RegisterSuspendDelayRequest protobuf_request;
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta timeout =
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs);
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_timeout(timeout.ToInternalValue());
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_description(kSuspendDelayDescription);
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error constructing message for "
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kRegisterSuspendDelayMethod;
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->CallMethod(
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &method_call,
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::OnRegisterSuspendDelayReply,
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()));
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Records the fact that an observer has finished doing asynchronous work
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // that was blocking a pending suspend attempt and possibly reports
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend readiness to powerd.  Called by callbacks returned via
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSuspendReadinessCallback().
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void HandleObserverSuspendReadiness(int32 suspend_id) {
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(OnOriginThread());
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!suspend_is_pending_ || suspend_id != pending_suspend_id_)
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_--;
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MaybeReportSuspendReadiness();
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Reports suspend readiness to powerd if no observers are still holding
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend readiness callbacks.
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MaybeReportSuspendReadiness() {
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!suspend_is_pending_ || num_pending_suspend_readiness_callbacks_ > 0)
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kHandleSuspendReadinessMethod);
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::SuspendReadinessInfo protobuf_request;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_delay_id(suspend_delay_id_);
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_suspend_id(pending_suspend_id_);
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_suspend_id_ = -1;
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_is_pending_ = false;
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error constructing message for "
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kHandleSuspendReadinessMethod;
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->CallMethod(
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &method_call,
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Origin thread (i.e. the UI thread in production).
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::PlatformThreadId origin_thread_id_;
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectProxy* power_manager_proxy_;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The delay_id_ obtained from the RegisterSuspendDelay request.
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 suspend_delay_id_;
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_suspend_delay_id_;
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // powerd-supplied ID corresponding to an imminent suspend attempt that is
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // currently being delayed.
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 pending_suspend_id_;
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool suspend_is_pending_;
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Number of callbacks that have been returned by
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSuspendReadinessCallback() during the currently-pending suspend
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // attempt but have not yet been called.
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_pending_suspend_readiness_callbacks_;
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wall time from the latest signal telling us that the system was about to
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend to memory.
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time last_suspend_wall_time_;
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
65490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Last state passed to SetIsProjecting().
65590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool last_is_projecting_;
65690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<PowerManagerClientImpl> weak_ptr_factory_;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The PowerManagerClient implementation used on Linux desktop,
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which does nothing.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerManagerClientStubImpl : public PowerManagerClient {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PowerManagerClientStubImpl()
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : discharging_(true),
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        battery_percentage_(40),
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        brightness_(50.0),
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        pause_count_(2),
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cycle_count_(0),
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        weak_ptr_factory_(this) {
6757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (CommandLine::ForCurrentProcess()->HasSwitch(
6767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        chromeos::switches::kEnableStubInteractive)) {
6777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const int kStatusUpdateMs = 1000;
6787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      update_timer_.Start(FROM_HERE,
6797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          base::TimeDelta::FromMilliseconds(kStatusUpdateMs), this,
6807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          &PowerManagerClientStubImpl::UpdateStatus);
6817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PowerManagerClientStubImpl() {}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PowerManagerClient overrides:
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.AddObserver(observer);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.RemoveObserver(observer);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observers_.HasObserver(observer);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to descrease screen brightness";
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(brightness_ - 5.0, true);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseScreenBrightness() OVERRIDE {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to increase screen brightness";
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(brightness_ + 5.0, true);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetScreenBrightnessPercent(double percent,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          bool gradual) OVERRIDE {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to set screen brightness to " << percent << "% "
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << (gradual ? "gradually" : "instantaneously");
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(percent, false);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetScreenBrightnessPercent(
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback) OVERRIDE {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(brightness_);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseKeyboardBrightness() OVERRIDE {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to descrease keyboard brightness";
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseKeyboardBrightness() OVERRIDE {
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to increase keyboard brightness";
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void RequestStatusUpdate() OVERRIDE {
731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE,
732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&PowerManagerClientStubImpl::UpdateStatus,
733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestRestart() OVERRIDE {}
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestShutdown() OVERRIDE {}
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void RequestIdleNotification(int64 threshold) OVERRIDE {
740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientStubImpl::TriggerIdleNotify,
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), threshold),
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(threshold));
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void NotifyUserActivity(
7487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      power_manager::UserActivityType type) OVERRIDE {}
749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void NotifyVideoActivity(bool is_fullscreen) OVERRIDE {}
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetPolicy(
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const power_manager::PowerManagementPolicy& policy) OVERRIDE {}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetIsProjecting(bool is_projecting) OVERRIDE {}
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::Closure GetSuspendReadinessCallback() OVERRIDE {
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::Closure();
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void UpdateStatus() {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pause_count_ > 0) {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pause_count_--;
761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (pause_count_ == 2)
762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        discharging_ = !discharging_;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (discharging_)
765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        battery_percentage_ -= (battery_percentage_ <= 10 ? 1 : 10);
766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      else
767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        battery_percentage_ += (battery_percentage_ >= 10 ? 10 : 1);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      battery_percentage_ = std::min(std::max(battery_percentage_, 0), 100);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We pause at 0 and 100% so that it's easier to check those conditions.
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (battery_percentage_ == 0 || battery_percentage_ == 100) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pause_count_ = 4;
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (battery_percentage_ == 100)
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          cycle_count_ = (cycle_count_ + 1) % 3;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const int kSecondsToEmptyFullBattery = 3 * 60 * 60;  // 3 hours.
778a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int64 remaining_battery_time =
779a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        std::max(1, battery_percentage_ * kSecondsToEmptyFullBattery / 100);
780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.Clear();
782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    switch (cycle_count_) {
784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 0:
785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is charging with AC connected and
786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // discharging without any charger connected.
787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(discharging_ ?
788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED :
789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_AC);
790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 1:
792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is both charging and discharging on USB
793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // (i.e. a low-power charger).
794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(
795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_USB);
796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 2:
798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is both charging and discharging on AC.
799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(
800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_AC);
801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      default:
803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NOTREACHED() << "Unhandled cycle " << cycle_count_;
804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (battery_percentage_ == 100 && !discharging_) {
807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_FULL);
809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else if (!discharging_) {
810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_CHARGING);
812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_time_to_full_sec(std::max(static_cast<int64>(1),
813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSecondsToEmptyFullBattery - remaining_battery_time));
814eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_time_to_empty_sec(remaining_battery_time);
818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.set_battery_percent(battery_percentage_);
821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.set_is_calculating_battery_time(pause_count_ > 1);
822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(props_));
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBrightness(double percent, bool user_initiated) {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    brightness_ = std::min(std::max(0.0, percent), 100.0);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int brightness_level = static_cast<int>(brightness_);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      BrightnessChanged(brightness_level, user_initiated));
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TriggerIdleNotify(int64 threshold) {
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleNotify(threshold));
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool discharging_;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int battery_percentage_;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double brightness_;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pause_count_;
841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int cycle_count_;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RepeatingTimer<PowerManagerClientStubImpl> update_timer_;
844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  power_manager::PowerSupplyProperties props_;
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
846868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::WeakPtrFactory<PowerManagerClientStubImpl> weak_ptr_factory_;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient::PowerManagerClient() {
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient::~PowerManagerClient() {
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient* PowerManagerClient::Create(
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusClientImplementationType type,
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::Bus* bus) {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new PowerManagerClientImpl(bus);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PowerManagerClientStubImpl();
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
868